pandoc 2.13 → 2.14
raw patch · 282 files changed
+6017/−4732 lines, 282 filesdep +arraydep +unicode-collationdep ~attoparsecdep ~citeprocdep ~commonmarkbinary-added
Dependencies added: array, unicode-collation
Dependency ranges changed: attoparsec, citeproc, commonmark, commonmark-extensions, commonmark-pandoc, haddock-library, jira-wiki-markup, network-uri, skylighting, skylighting-core, texmath, text, time, xml-conduit
Files
- AUTHORS.md +11/−0
- INSTALL.md +4/−0
- MANUAL.txt +136/−44
- cabal.project +0/−4
- changelog.md +418/−0
- data/docx/word/settings.xml +5/−15
- data/templates/default.context +7/−3
- data/templates/default.dzslides +1/−1
- data/templates/default.latex +77/−55
- data/templates/default.revealjs +12/−4
- data/templates/default.s5 +3/−0
- data/templates/default.slideous +7/−0
- data/templates/default.slidy +5/−0
- man/pandoc.1 +169/−28
- pandoc.cabal +28/−19
- src/Text/Pandoc/App.hs +19/−13
- src/Text/Pandoc/App/Opt.hs +1/−1
- src/Text/Pandoc/Asciify.hs +13/−390
- src/Text/Pandoc/BCP47.hs +0/−112
- src/Text/Pandoc/Citeproc.hs +4/−11
- src/Text/Pandoc/Citeproc/BibTeX.hs +22/−14
- src/Text/Pandoc/Citeproc/Data.hs +7/−6
- src/Text/Pandoc/Citeproc/Locator.hs +18/−3
- src/Text/Pandoc/Class/CommonState.hs +1/−1
- src/Text/Pandoc/Class/IO.hs +4/−5
- src/Text/Pandoc/Class/PandocMonad.hs +27/−33
- src/Text/Pandoc/Error.hs +23/−16
- src/Text/Pandoc/Extensions.hs +4/−0
- src/Text/Pandoc/Highlighting.hs +5/−5
- src/Text/Pandoc/Logging.hs +18/−9
- src/Text/Pandoc/Lua/Filter.hs +2/−0
- src/Text/Pandoc/Lua/Module/MediaBag.hs +3/−3
- src/Text/Pandoc/Lua/Module/Pandoc.hs +8/−3
- src/Text/Pandoc/MediaBag.hs +35/−12
- src/Text/Pandoc/Options.hs +17/−17
- src/Text/Pandoc/Parsing.hs +352/−230
- src/Text/Pandoc/Readers.hs +55/−48
- src/Text/Pandoc/Readers/BibTeX.hs +14/−8
- src/Text/Pandoc/Readers/CSV.hs +7/−7
- src/Text/Pandoc/Readers/CommonMark.hs +43/−31
- src/Text/Pandoc/Readers/Creole.hs +5/−6
- src/Text/Pandoc/Readers/CslJson.hs +5/−4
- src/Text/Pandoc/Readers/DocBook.hs +25/−11
- src/Text/Pandoc/Readers/Docx.hs +58/−37
- src/Text/Pandoc/Readers/Docx/Combine.hs +3/−3
- src/Text/Pandoc/Readers/Docx/Parse.hs +110/−16
- src/Text/Pandoc/Readers/Docx/Util.hs +7/−0
- src/Text/Pandoc/Readers/DokuWiki.hs +9/−8
- src/Text/Pandoc/Readers/FB2.hs +6/−3
- src/Text/Pandoc/Readers/HTML.hs +43/−27
- src/Text/Pandoc/Readers/HTML/Table.hs +33/−14
- src/Text/Pandoc/Readers/Haddock.hs +9/−6
- src/Text/Pandoc/Readers/Ipynb.hs +5/−3
- src/Text/Pandoc/Readers/JATS.hs +13/−6
- src/Text/Pandoc/Readers/Jira.hs +11/−7
- src/Text/Pandoc/Readers/LaTeX.hs +16/−25
- src/Text/Pandoc/Readers/LaTeX/Citation.hs +1/−1
- src/Text/Pandoc/Readers/LaTeX/Lang.hs +122/−119
- src/Text/Pandoc/Readers/LaTeX/Macro.hs +45/−14
- src/Text/Pandoc/Readers/LaTeX/Parsing.hs +48/−7
- src/Text/Pandoc/Readers/LaTeX/SIunitx.hs +140/−66
- src/Text/Pandoc/Readers/LaTeX/Types.hs +14/−1
- src/Text/Pandoc/Readers/Man.hs +18/−11
- src/Text/Pandoc/Readers/Markdown.hs +71/−44
- src/Text/Pandoc/Readers/MediaWiki.hs +7/−6
- src/Text/Pandoc/Readers/Metadata.hs +19/−15
- src/Text/Pandoc/Readers/Muse.hs +9/−8
- src/Text/Pandoc/Readers/Native.hs +7/−5
- src/Text/Pandoc/Readers/OPML.hs +9/−4
- src/Text/Pandoc/Readers/Odt/ContentReader.hs +12/−7
- src/Text/Pandoc/Readers/Org.hs +4/−7
- src/Text/Pandoc/Readers/Org/Blocks.hs +5/−2
- src/Text/Pandoc/Readers/Org/Inlines.hs +6/−5
- src/Text/Pandoc/Readers/Org/Parsing.hs +3/−3
- src/Text/Pandoc/Readers/RST.hs +76/−109
- src/Text/Pandoc/Readers/Roff.hs +16/−18
- src/Text/Pandoc/Readers/TWiki.hs +7/−27
- src/Text/Pandoc/Readers/Textile.hs +88/−84
- src/Text/Pandoc/Readers/TikiWiki.hs +6/−6
- src/Text/Pandoc/Readers/Txt2Tags.hs +6/−6
- src/Text/Pandoc/Readers/Vimwiki.hs +12/−7
- src/Text/Pandoc/SelfContained.hs +4/−7
- src/Text/Pandoc/Shared.hs +16/−8
- src/Text/Pandoc/Sources.hs +195/−0
- src/Text/Pandoc/Writers.hs +3/−3
- src/Text/Pandoc/Writers/BibTeX.hs +1/−1
- src/Text/Pandoc/Writers/ConTeXt.hs +39/−39
- src/Text/Pandoc/Writers/CslJson.hs +4/−3
- src/Text/Pandoc/Writers/Docbook.hs +4/−3
- src/Text/Pandoc/Writers/Docx.hs +37/−235
- src/Text/Pandoc/Writers/Docx/Table.hs +200/−0
- src/Text/Pandoc/Writers/Docx/Types.hs +181/−0
- src/Text/Pandoc/Writers/EPUB.hs +3/−3
- src/Text/Pandoc/Writers/GridTable.hs +157/−0
- src/Text/Pandoc/Writers/HTML.hs +14/−2
- src/Text/Pandoc/Writers/JATS.hs +67/−44
- src/Text/Pandoc/Writers/JATS/References.hs +3/−2
- src/Text/Pandoc/Writers/JATS/Table.hs +25/−5
- src/Text/Pandoc/Writers/JATS/Types.hs +12/−3
- src/Text/Pandoc/Writers/Jira.hs +9/−3
- src/Text/Pandoc/Writers/LaTeX.hs +13/−8
- src/Text/Pandoc/Writers/LaTeX/Lang.hs +61/−60
- src/Text/Pandoc/Writers/LaTeX/Table.hs +1/−3
- src/Text/Pandoc/Writers/LaTeX/Types.hs +2/−1
- src/Text/Pandoc/Writers/LaTeX/Util.hs +4/−3
- src/Text/Pandoc/Writers/Markdown.hs +24/−9
- src/Text/Pandoc/Writers/Markdown/Inline.hs +19/−5
- src/Text/Pandoc/Writers/Ms.hs +22/−6
- src/Text/Pandoc/Writers/ODT.hs +4/−3
- src/Text/Pandoc/Writers/OpenDocument.hs +50/−54
- src/Text/Pandoc/Writers/Org.hs +4/−2
- src/Text/Pandoc/Writers/Powerpoint.hs +1/−1
- src/Text/Pandoc/Writers/Powerpoint/Output.hs +18/−5
- src/Text/Pandoc/Writers/Shared.hs +15/−0
- src/Text/Pandoc/Writers/TEI.hs +4/−3
- src/Text/Pandoc/Writers/ZimWiki.hs +1/−1
- src/Text/Pandoc/XML.hs +28/−2
- src/Text/Pandoc/XML/Light/Types.hs +4/−4
- stack.yaml +8/−7
- test/Tests/Command.hs +4/−1
- test/Tests/Readers/Docx.hs +25/−5
- test/Tests/Readers/EPUB.hs +1/−1
- test/Tests/Readers/HTML.hs +20/−5
- test/Tests/Readers/Jira.hs +8/−0
- test/Tests/Readers/Markdown.hs +3/−3
- test/Tests/Readers/Odt.hs +1/−0
- test/Tests/Writers/ConTeXt.hs +122/−113
- test/Tests/Writers/Docx.hs +5/−0
- test/Tests/Writers/HTML.hs +57/−52
- test/Tests/Writers/JATS.hs +134/−90
- test/Tests/Writers/Jira.hs +12/−0
- test/command/1279.md +1/−1
- test/command/2103.md +8/−0
- test/command/3752.md +60/−0
- test/command/3792.md +1/−1
- test/command/4063.md +29/−0
- test/command/4164.md +1/−1
- test/command/4442.md +1/−1
- test/command/5304.md +1/−1
- test/command/5519.md +1/−1
- test/command/6026.md +19/−0
- test/command/6541.md +27/−0
- test/command/6620.md +3/−0
- test/command/6658.md +75/−0
- test/command/6709.md +11/−0
- test/command/6925.md +2/−2
- test/command/6958.md +10/−0
- test/command/7041.md +23/−0
- test/command/7099.md +1/−1
- test/command/7173.md +137/−0
- test/command/7208.md +6/−0
- test/command/7214.md +28/−0
- test/command/7216.md +19/−0
- test/command/7266.md +10/−0
- test/command/7272.md +24/−0
- test/command/7278.md +38/−0
- test/command/7282.md +7/−0
- test/command/7288.md +40/−0
- test/command/7299.md +23/−0
- test/command/7321.md +24/−0
- test/command/7323.md +29/−0
- test/command/7324.md +25/−0
- test/command/averroes.bib +95/−0
- test/command/biblatex-basic.md +5/−3
- test/command/biblatex-examples.bib +0/−1674
- test/command/biblatex-inproceedings.md +1/−1
- test/command/biblatex-jaffe.md +2/−2
- test/command/biblatex-moraux.md +1/−1
- test/command/biblatex-nussbaum.md +0/−63
- test/command/biblatex-quotes.md +1/−1
- test/command/biblatex-sigfridsson.md +1/−1
- test/command/biblatex-spiegelberg.md +2/−2
- test/command/biblatex-test-case-conversion.md +2/−2
- test/command/biblatex-textnormal.md +1/−1
- test/command/chap1/spider.png binary
- test/command/chap1/text.md +17/−0
- test/command/chap2/spider.png binary
- test/command/chap2/text.md +5/−0
- test/command/defaults-inheritance-2.md +1/−1
- test/command/mmd-metadata.md +20/−0
- test/command/newif.md +55/−0
- test/command/pandoc-citeproc-119.md +1/−1
- test/command/pandoc-citeproc-320a.md +3/−3
- test/command/pandoc-citeproc-65.md +1/−1
- test/command/pandoc-citeproc-70.md +2/−2
- test/command/svg.md +1/−1
- test/command/toc.md +2/−2
- test/command/unicode-collation.md +130/−0
- test/docbook-reader.docbook +3/−1
- test/docx/0_level_headers.native +1/−1
- 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_continuing.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/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_vml_as_object.docx binary
- test/docx/image_vml_as_object.native +2/−0
- test/docx/sdt_elements.native +8/−9
- test/docx/table_captions_no_field.docx binary
- test/docx/table_captions_no_field.native +34/−0
- test/docx/table_captions_with_field.docx binary
- test/docx/table_captions_with_field.native +54/−0
- test/docx/table_header_rowspan.docx binary
- test/docx/table_header_rowspan.native +189/−0
- test/docx/table_one_header_row.docx binary
- test/docx/table_one_header_row.native +18/−0
- test/docx/table_one_row.docx binary
- test/docx/table_one_row.native +3/−3
- test/docx/table_variable_width.native +11/−16
- test/docx/table_with_list_cell.native +2/−2
- test/docx/tables-default-widths.native +92/−0
- test/docx/tables.native +8/−8
- test/epub/wasteland.epub binary
- test/fb2/images.fb2 +1/−1
- test/fb2/test.jpg binary
- test/html-reader.native +2/−1
- test/lhs-test.latex +3/−3
- test/lhs-test.latex+lhs +3/−3
- test/odt/native/tab.native +1/−0
- test/odt/odt/tab.odt binary
- test/pptx/code-custom_templated.pptx binary
- test/pptx/code_templated.pptx binary
- test/pptx/document-properties-short-desc_templated.pptx binary
- test/pptx/document-properties_templated.pptx binary
- test/pptx/endnotes_templated.pptx binary
- test/pptx/endnotes_toc_templated.pptx binary
- test/pptx/images_templated.pptx binary
- test/pptx/inline_formatting_templated.pptx binary
- test/pptx/lists_templated.pptx binary
- test/pptx/raw_ooxml_templated.pptx binary
- test/pptx/reference_depth.pptx binary
- test/pptx/remove_empty_slides_templated.pptx binary
- test/pptx/slide_breaks_slide_level_1_templated.pptx binary
- test/pptx/slide_breaks_templated.pptx binary
- test/pptx/slide_breaks_toc_templated.pptx binary
- test/pptx/speaker_notes_after_metadata_templated.pptx binary
- test/pptx/speaker_notes_afterheader_templated.pptx binary
- test/pptx/speaker_notes_afterseps_templated.pptx binary
- test/pptx/speaker_notes_templated.pptx binary
- test/pptx/start_numbering_at_templated.pptx binary
- test/pptx/tables_templated.pptx binary
- test/pptx/two_column_templated.pptx binary
- test/tables.ms +30/−0
- test/writer.context +42/−38
- test/writer.jats_archiving +36/−46
- test/writer.jats_articleauthoring +40/−48
- test/writer.jats_publishing +36/−46
- test/writer.latex +4/−4
- test/writer.opml +1/−1
- test/writer.org +7/−7
- test/writer.zimwiki +3/−3
- test/writers-lang-and-dir.context +4/−0
- test/writers-lang-and-dir.latex +3/−3
@@ -20,6 +20,7 @@ - Andreas Lööw - Andrew Dunning - Andy Morris+- Anti-Distinctlyminty - Antoine Latter - Antonio Terceiro - Arata Mizuki@@ -46,6 +47,7 @@ - Carlos Sosa - Cécile Chemin - Cédric Couralet+- Charanjit Singh - Chris Black - Christian Conkle - Christian Despres@@ -76,6 +78,7 @@ - Eigil Rischel - Emanuel Evans - Emerson Harkin+- Emily Bourke - Emily Eisenberg - Eric Kow - Erik Rask@@ -149,6 +152,7 @@ - Josef Svenningsson - Joseph C. Sible - Julien Cretel+- Julien Dutant - Juliette Fourcot - Juliusz Gonera - Justin Bogner@@ -231,6 +235,7 @@ - Raymond Ehlers - Recai Oktaş - Roland Hieber+- Roman Beránek - RyanGlScott - Salim B - Sascha Wilde@@ -248,6 +253,7 @@ - Stefan Dresselhaus - Sumit Sahrawat - Tarik Graba+- Tatiana Porras - Thenaesh Elango - Thomas Hodgson - Thomas Weißschuh@@ -281,6 +287,7 @@ - a-vrma - andrebauer - argent0+- badumont - blmage - bucklereed - bumper314@@ -296,8 +303,11 @@ - kaizshang91 - lux-lth - lwolfsonkin+- mbrackeantidot - nkalvi - niszet+- nuew+- obcat - oltolm - oquechy - quasicomputational@@ -309,6 +319,7 @@ - shreevatsa.public - takahashim - taotieren+- tecosaur - TEC - tgkokk - the-solipsist
@@ -34,6 +34,10 @@ choco install rsvg-convert python miktex +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].
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: March 20, 2021+date: May 28, 2021 --- # Synopsis@@ -2315,8 +2315,8 @@ These affect HTML output when [producing slide shows with pandoc]. -All [reveal.js configuration options] are available as variables.-To turn off boolean flags that default to true in reveal.js, use `0`.+`institute`+: author affiliations: can be a list when there are multiple authors `revealjs-url` : base URL for reveal.js documents (defaults to@@ -2336,6 +2336,9 @@ : additional attributes for the title slide of reveal.js slide shows. See [background in reveal.js and beamer] 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@@ -3752,7 +3755,7 @@ 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-pandoc extensions], below.)+[Non-default extensions], below.) [^3]: I have been influenced by the suggestions of [David Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).@@ -4177,10 +4180,12 @@ 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. 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:+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'@@ -4255,6 +4260,7 @@ 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 ## Backslash escapes @@ -4948,37 +4954,68 @@ #### Extension: `citations` #### -Markdown citations go inside square brackets and are separated-by semicolons. Each citation must have a key, composed of '@' +-the citation identifier from the database, and may optionally-have a prefix, a locator, and a suffix. The citation key must-begin with a letter, digit, or `_`, and may contain-alphanumerics, `_`, and internal punctuation characters-(`:.#$%&-+?<>~/`). Here are some examples:+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 [see @doe99, pp. 33-35; also @smith04, chap. 1].+ Blah blah [@doe99; @smith2000; @smith2004]. - Blah blah [@doe99, pp. 33-35, 38-39 and *passim*].+How this is rendered depends on the citation style. In an+author-date style, it might render as - Blah blah [@smith04; @doe99].+ Blah blah (Doe 1999, Smith 2000, 2004). -`pandoc` detects locator terms 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+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 start with a letter, digit, or `_`,+and contains only alphanumerics and 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`. 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. 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. -`pandoc` will use heuristics to distinguish the locator-from the suffix. In complex cases, the locator can be enclosed-in curly braces:+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@@ -4986,13 +5023,26 @@ Smith says blah [-@smith04]. -You can also write an in-text citation, as follows:+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@@ -5001,13 +5051,44 @@ [finding and editing styles]: https://citationstyles.org/authors/ [CSL locale files]: https://github.com/citation-style-language/locales -## Non-pandoc extensions+## 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 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@@ -5541,11 +5622,24 @@ `lang` : The `lang` field will affect how the style is localized,- for example in the translation of labels and the use- of quotation marks. (For backwards compatibility,- `locale` may be used instead of `lang`, but this use- is deprecated.)+ 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), pandoc will put footnote citations after following punctuation. For example, if the source@@ -5556,12 +5650,6 @@ punctuation. ------ # Slide shows You can use pandoc to produce an HTML + JavaScript slide presentation@@ -5654,7 +5742,11 @@ * A heading at the slide level always starts a new slide. * Headings *below* the slide level in the hierarchy create- headings *within* a slide.+ 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@@ -6232,7 +6324,7 @@ If you are not satisfied with the built-in highlighting, or you want 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/applications/katepart/highlight.html).+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).
@@ -2,7 +2,3 @@ tests: True flags: +embed_data_files --- source-repository-package--- type: git--- location: https://github.com/jgm/citeproc--- tag: d44e24696ab444090d0e63e321c3a573f68b2e74
@@ -1,5 +1,423 @@ # Revision history for pandoc +## 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: 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!++ ## pandoc 2.13 (2021-03-21) * Support `yaml_metadata_block` extension for `commonmark`, `gfm` (#6537).
@@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <w:settings xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main">- <w:zoom w:percent="90" />+ <w:zoom w:percent="100" /> <w:embedSystemFonts /> <w:proofState w:spelling="clean" w:grammar="clean" /> <w:stylePaneFormatFilter w:val="0004" />@@ -17,28 +17,18 @@ <w:characterSpacingControl w:val="doNotCompress" /> <w:savePreviewPicture /> <w:rsids>- <w:rsidRoot w:val="00590D07" />- <w:rsid w:val="00011C8B" />- <w:rsid w:val="004E29B3" />- <w:rsid w:val="00590D07" />- <w:rsid w:val="00784D58" />- <w:rsid w:val="008D6863" />- <w:rsid w:val="00B86B75" />- <w:rsid w:val="00BC48D5" />- <w:rsid w:val="00C36279" />- <w:rsid w:val="00E315A3" /> </w:rsids> <m:mathPr>- <m:mathFont m:val="Lucida Grande" />+ <m:mathFont m:val="Cambria Math" /> <m:brkBin m:val="before" /> <m:brkBinSub m:val="--" />- <m:smallFrac m:val="false" />- <m:dispDef m:val="false" />+ <m:smallFrac m:val="0" />+ <m:dispDef /> <m:lMargin m:val="0" /> <m:rMargin m:val="0" /> <m:wrapRight /> <m:intLim m:val="subSup" />- <m:naryLim m:val="subSup" />+ <m:naryLim m:val="undOvr" /> </m:mathPr> <w:themeFontLang w:val="en-US" /> <w:clrSchemeMapping w:bg1="light1" w:t1="dark1" w:bg2="light2" w:t2="dark2" w:accent1="accent1" w:accent2="accent2" w:accent3="accent3" w:accent4="accent4" w:accent5="accent5" w:accent6="accent6" w:hyperlink="hyperlink" w:followedHyperlink="followedHyperlink" />
@@ -51,6 +51,7 @@ % use microtypography \definefontfeature[default][default][script=latn, protrusion=quality, expansion=quality, itlc=yes, textitalics=yes, onum=yes, pnum=yes]+\definefontfeature[default:tnum][default][tnum=yes, pnum=no] \definefontfeature[smallcaps][script=latn, protrusion=quality, expansion=quality, smcp=yes, onum=yes, pnum=yes] \setupalign[hz,hanging] \setupitaliccorrection[global, always]@@ -97,6 +98,9 @@ \setupitemize[autointro] % prevent orphan list intro \setupitemize[indentnext=no] +\defineitemgroup[enumerate]+\setupenumerate[each][fit][itemalign=left,distance=.5em,style={\feature[+][default:tnum]}]+ \setupfloat[figure][default={here,nonumber}] \setupfloat[table][default={here,nonumber}] @@ -160,11 +164,11 @@ $if(toc)$ \completecontent $endif$-$if(lot)$-\completelistoftables-$endif$ $if(lof)$ \completelistoffigures+$endif$+$if(lot)$+\completelistoftables $endif$ $body$
@@ -171,7 +171,7 @@ <h1 class="subtitle">$subtitle$</h1> $endif$ <footer>- $if(author)$<span class="author">$for(author)$$author$$sep$, $endfor$</span>$endif$ · $if(date)$<span class="date">$date$</span>$endif$+ $if(author)$<span class="author">$for(author)$$author$$sep$, $endfor$</span> · $endif$$if(institute)$<span class="institute">$for(institute)$$institute$$sep$, $endfor$</span> · $endif$$if(date)$<span class="date">$date$</span>$endif$ </footer> </section> $endif$
@@ -2,7 +2,7 @@ \PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref} \PassOptionsToPackage{hyphens}{url} $if(colorlinks)$-\PassOptionsToPackage{dvipsnames,svgnames*,x11names*}{xcolor}+\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor} $endif$ $if(dir)$ $if(latex-dir-rtl)$@@ -36,7 +36,36 @@ $classoption$$sep$, $endfor$ ]{$documentclass$}+$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$++$if(beamer)$ $if(background-image)$ \usebackgroundtemplate{% \includegraphics[width=\paperwidth]{$background-image$}%@@ -156,6 +185,25 @@ \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$}@@ -325,6 +373,31 @@ $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$ $for(header-includes)$ $header-includes$ $endfor$@@ -375,61 +448,10 @@ $if(nocite-ids)$ \nocite{$for(nocite-ids)$$it$$sep$, $endfor$} $endif$-$if(csl-refs)$-\newlength{\cslhangindent}-\setlength{\cslhangindent}{1.5em}-\newlength{\csllabelwidth}-\setlength{\csllabelwidth}{3em}-\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 \everypar{\setlength{\hangindent}{\cslhangindent}}\ignorespaces\fi- % set entry spacing- \ifnum #2 > 0- \setlength{\parskip}{#2\baselineskip}- \fi- }%- {}-\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(csquotes)$ \usepackage{csquotes} $endif$ -$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@@ -472,11 +494,11 @@ } $endif$ $endif$-$if(lot)$-\listoftables-$endif$ $if(lof)$ \listoffigures+$endif$+$if(lot)$+\listoftables $endif$ $if(linestretch)$ \setstretch{$linestretch$}
@@ -52,6 +52,9 @@ $for(author)$ <p class="author">$author$</p> $endfor$+$for(institute)$+ <p class="institute">$institute$</p>+$endfor$ $if(date)$ <p class="date">$date$</p> $endif$@@ -59,7 +62,12 @@ $endif$ $if(toc)$ <section id="$idprefix$TOC">+<nav role="doc-toc"> +$if(toc-title)$+<h2 id="$idprefix$toc-title">$toc-title$</h2>+$endif$ $table-of-contents$+</nav> </section> $endif$ @@ -116,17 +124,17 @@ // 'all', 'print', or 'speaker' showSlideNumber: '$showSlideNumber$', $endif$-$if(hash)$ // Add the current slide number to the URL hash so that reloading the // page/copying the URL will return you to the same slide- hash: $hash$,-$endif$+ hash: $if(hash)$$hash$$else$true$endif$, $if(hashOneBasedIndex)$ // Start with 1 for the hash rather than 0 hashOneBasedIndex: $hashOneBasedIndex$, $endif$+$if(history)$ // Push each slide change to the browser history- history: $if(history)$$history$$else$true$endif$,+ history: $history$,+$endif$ $if(keyboard)$ // Enable keyboard shortcuts for navigation keyboard: $keyboard$,
@@ -61,6 +61,9 @@ $if(author)$ <h3 class="author">$for(author)$$author$$sep$<br/>$endfor$</h3> $endif$+$if(institute)$+ <h3 class="institute">$for(institute)$$institute$$sep$<br/>$endfor$</h3>+$endif$ $if(date)$ <h4 class="date">$date$</h4> $endif$
@@ -63,9 +63,16 @@ $if(subtitle)$ <h1 class="subtitle">$subtitle$</h1> $endif$+$if(author)$ <p class="author"> $for(author)$$author$$sep$<br/>$endfor$ </p>+$endif$+$if(institute)$+ <p class="institute">+$for(institute)$$institute$$sep$<br/>$endfor$+ </p>+$endif$ $if(date)$ <p class="date">$date$</p> $endif$
@@ -52,6 +52,11 @@ $for(author)$$author$$sep$<br/>$endfor$ </p> $endif$+$if(institute)$+ <p class="institute">+$for(institute)$$institute$$sep$<br/>$endfor$+ </p>+$endif$ $if(date)$ <p class="date">$date$</p> $endif$
@@ -1,7 +1,7 @@ '\" t-.\" Automatically generated by Pandoc 2.12.1+.\" Automatically generated by Pandoc 2.14 .\"-.TH "Pandoc User\[cq]s Guide" "" "March 20, 2021" "pandoc 2.13" ""+.TH "Pandoc User\[cq]s Guide" "" "May 28, 2021" "pandoc 2.14" "" .hy .SH NAME pandoc - general markup converter@@ -2591,11 +2591,10 @@ .SS Variables for HTML slides .PP These affect HTML output when [producing slide shows with pandoc].-.PP-All reveal.js configuration options are available as variables.-To turn off boolean flags that default to true in reveal.js, use-\f[C]0\f[R]. .TP+\f[B]\f[CB]institute\f[B]\f[R]+author affiliations: can be a list when there are multiple authors+.TP \f[B]\f[CB]revealjs-url\f[B]\f[R] base URL for reveal.js documents (defaults to \f[C]https://unpkg.com/reveal.js\[at]\[ha]4/\f[R])@@ -2613,6 +2612,10 @@ \f[B]\f[CB]title-slide-attributes\f[B]\f[R] additional attributes for the title slide of reveal.js slide shows. See background in reveal.js and beamer 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[C]0\f[R]. .SS Variables for Beamer slides .PP These variables change the appearance of PDF slides using@@ -4272,7 +4275,7 @@ 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[C]compact_definition_lists\f[R]:-see Non-pandoc extensions, below.)+see Non-default extensions, below.) .SS Numbered example lists .SS Extension: \f[C]example_lists\f[R] .PP@@ -4793,7 +4796,9 @@ the document. .PP Note that YAML escaping rules must be followed.-Thus, for example, if a title contains a colon, it must be quoted.+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[C]|\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@@ -4880,6 +4885,21 @@ \[ga]\[ga]\[ga] \f[R] .fi+.PP+Note: the \f[C]yaml_metadata_block\f[R] extension works with+\f[C]commonmark\f[R] as well as \f[C]markdown\f[R] (and it is enabled by+default in \f[C]gfm\f[R] and \f[C]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[C]all_symbols_escapable\f[R] .PP@@ -5760,27 +5780,70 @@ .SS Citation syntax .SS Extension: \f[C]citations\f[R] .PP-Markdown citations go inside square brackets and are separated by-semicolons.-Each citation must have a key, composed of `\[at]' + the citation-identifier from the database, and may optionally have a prefix, a-locator, and a suffix.-The citation key must begin with a letter, digit, or \f[C]_\f[R], and-may contain alphanumerics, \f[C]_\f[R], and internal punctuation-characters (\f[C]:.#$%&-+?<>\[ti]/\f[R]).-Here are some examples:+To cite a bibliographic item with an identifier foo, use the syntax+\f[C]\[at]foo\f[R].+Normal citations should be included in square brackets, with semicolons+separating distinct items: .IP .nf \f[C]-Blah blah [see \[at]doe99, pp. 33-35; also \[at]smith04, chap. 1].--Blah blah [\[at]doe99, pp. 33-35, 38-39 and *passim*].+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] -Blah blah [\[at]smith04; \[at]doe99].+[\[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-\f[C]pandoc\f[R] detects locator terms in the CSL locale files.+See the CSL user documentation for more information about CSL styles and+how they affect rendering.+.PP+Unless a citation key start with a letter, digit, or \f[C]_\f[R], and+contains only alphanumerics and internal punctuation characters+(\f[C]:.#$%&-+?<>\[ti]/\f[R]), it must be surrounded by curly braces,+which are not considered part of the key.+In \f[C]\[at]Foo_bar.baz.\f[R], the key is \f[C]Foo_bar.baz\f[R].+The final period is not \f[I]internal\f[R] punctuation, so it is not+included in the key.+In \f[C]\[at]{Foo_bar.baz.}\f[R], the key is \f[C]Foo_bar.baz.\f[R],+including the final period.+The curly braces are recommended if you use URLs as keys:+\f[C][\[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[C]doe99\f[R]) has prefix \f[C]see\f[R], locator+\f[C]pp. 33-35\f[R], and suffix \f[C]and *passim*\f[R].+The second item (\f[C]smith04\f[R]) has locator \f[C]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[C]en-US\f[R] locale, locator terms can be written in either singular or plural forms, as \f[C]book\f[R],@@ -5802,14 +5865,15 @@ \f[C]\[sc]\f[R]/\f[C]\[sc]\[sc]\f[R]. If no locator term is used, \[lq]page\[rq] is assumed. .PP-\f[C]pandoc\f[R] will use heuristics to distinguish the locator from the-suffix.-In complex cases, the locator can be enclosed in curly braces:+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@@ -5823,7 +5887,8 @@ \f[R] .fi .PP-You can also write an in-text citation, as follows:+You can also write an author-in-text citation, by omitting the square+brackets: .IP .nf \f[C]@@ -5832,13 +5897,64 @@ \[at]smith04 [p. 33] says blah. \f[R] .fi-.SS Non-pandoc extensions .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[C]+EXTENSION\f[R] to the format name, where \f[C]EXTENSION\f[R] is the name of the extension. Thus, for example, \f[C]markdown+hard_line_breaks\f[R] is Markdown with hard line breaks.+.SS Extension: \f[C]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 a subdirectory for each chapter of a book,+\f[C]chap1\f[R], \f[C]chap2\f[R], \f[C]chap3\f[R].+Each contains a file \f[C]text.md\f[R] and a number of images used in+the chapter.+You would like to have \f[C]\f[R] in+\f[C]chap1/text.md\f[R] refer to \f[C]chap1/spider.jpg\f[R] and+\f[C]\f[R] in \f[C]chap2/text.md\f[R] refer to+\f[C]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[C]\f[R] in \f[C]chap1/text.md\f[R] and+\f[C]\f[R] in \f[C]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[C]#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[C]attributes\f[R] .PP Allows attributes to be attached to any inline or block-level element.@@ -6468,9 +6584,29 @@ .TP \f[B]\f[CB]lang\f[B]\f[R] The \f[C]lang\f[R] field will affect how the style is localized, for-example in the translation of labels and the use of quotation marks.+example in the translation of labels, the use of quotation marks, and+the way items are sorted. (For backwards compatibility, \f[C]locale\f[R] may be used instead of \f[C]lang\f[R], but this use is deprecated.)+.RS+.PP+A BCP 47 language tag is expected: for example, \f[C]en\f[R],+\f[C]de\f[R], \f[C]en-US\f[R], \f[C]fr-CA\f[R], \f[C]ug-Cyrl\f[R].+The unicode extension syntax (after \f[C]-u-\f[R]) may be used to+specify options for collation (sorting) more precisely.+Here are some examples:+.IP \[bu] 2+\f[C]zh-u-co-pinyin\f[R] \[en] Chinese with the Pinyin collation.+.IP \[bu] 2+\f[C]es-u-co-trad\f[R] \[en] Spanish with the traditional collation+(with \f[C]Ch\f[R] sorting after \f[C]C\f[R]).+.IP \[bu] 2+\f[C]fr-u-kb\f[R] \[en] French with \[lq]backwards\[rq] accent sorting+(with \f[C]cot\['e]\f[R] sorting after \f[C]c\[^o]te\f[R]).+.IP \[bu] 2+\f[C]en-US-u-kf-upper\f[R] \[en] English with uppercase letters sorting+before lower (default is lower before upper).+.RE .TP \f[B]\f[CB]notes-after-punctuation\f[B]\f[R] If true (the default), pandoc will put footnote citations after@@ -6591,6 +6727,11 @@ .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[C]example\f[R], an+\f[C]exampleblock\f[R] environment will be used; if it has the class+\f[C]alert\f[R], an \f[C]alertblock\f[R] will be used; otherwise a+regular \f[C]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
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: pandoc-version: 2.13+version: 2.14 build-type: Simple license: GPL-2.0-or-later license-file: COPYING.md@@ -12,7 +12,7 @@ homepage: https://pandoc.org category: Text tested-with: GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5,- GHC == 8.8.4, GHC == 8.10.2+ GHC == 8.8.4, GHC == 8.10.2, GHC == 9.0.1 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@@ -208,12 +208,16 @@ test/command/*.md test/command/*.csl test/command/biblio.bib- test/command/biblatex-examples.bib+ test/command/averroes.bib test/command/A.txt test/command/B.txt test/command/C.txt test/command/D.txt test/command/01.csv+ test/command/chap1/spider.png+ test/command/chap2/spider.png+ test/command/chap1/text.md+ test/command/chap2/text.md test/command/defaults1.yaml test/command/defaults2.yaml test/command/defaults3.yaml@@ -438,17 +442,18 @@ SHA >= 1.6 && < 1.7, aeson >= 0.7 && < 1.6, aeson-pretty >= 0.8.5 && < 0.9,- attoparsec >= 0.12 && < 0.14,+ 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, case-insensitive >= 1.2 && < 1.3,- citeproc >= 0.3.0.9 && < 0.3.1,- commonmark >= 0.1.1.3 && < 0.2,- commonmark-extensions >= 0.2.0.4 && < 0.3,- commonmark-pandoc >= 0.2 && < 0.3,+ citeproc >= 0.4 && < 0.4.1,+ commonmark >= 0.2 && < 0.3,+ commonmark-extensions >= 0.2.1 && < 0.3,+ commonmark-pandoc >= 0.2.1 && < 0.3, connection >= 0.3.1, containers >= 0.4.2.1 && < 0.7, data-default >= 0.4 && < 0.8,@@ -460,7 +465,7 @@ exceptions >= 0.8 && < 0.11, file-embed >= 0.0 && < 0.1, filepath >= 1.1 && < 1.5,- haddock-library >= 1.8 && < 1.10,+ haddock-library >= 1.10 && < 1.11, hslua >= 1.1 && < 1.4, hslua-module-path >= 0.1.0 && < 0.2.0, hslua-module-system >= 0.2 && < 0.3,@@ -469,30 +474,31 @@ http-client-tls >= 0.2.4 && < 0.4, http-types >= 0.8 && < 0.13, ipynb >= 0.1 && < 0.2,- jira-wiki-markup >= 1.3.4 && < 1.4,+ jira-wiki-markup >= 1.4 && < 1.5, mtl >= 2.2 && < 2.3, network >= 2.6,- network-uri >= 2.6 && < 2.7,+ network-uri >= 2.6 && < 2.8, pandoc-types >= 1.22 && < 1.23, parsec >= 3.1 && < 3.2, process >= 1.2.3 && < 1.7, random >= 1 && < 1.3, safe >= 0.3.18 && < 0.4, scientific >= 0.3 && < 0.4,- skylighting >= 0.10.5 && < 0.10.6,- skylighting-core >= 0.10.5 && < 0.10.6,+ skylighting >= 0.10.5.1 && < 0.10.6,+ skylighting-core >= 0.10.5.1 && < 0.10.6, split >= 0.2 && < 0.3, syb >= 0.1 && < 0.8, tagsoup >= 0.14.6 && < 0.15, temporary >= 1.1 && < 1.4,- texmath >= 0.12.2 && < 0.12.3,+ texmath >= 0.12.3 && < 0.12.4, text >= 1.1.1.0 && < 1.3, text-conversions >= 0.3 && < 0.4,- time >= 1.5 && < 1.10,+ time >= 1.5 && < 1.12, unicode-transforms >= 0.3 && < 0.4, unordered-containers >= 0.2 && < 0.3, xml >= 1.3.12 && < 1.4,- xml-conduit >= 1.7 && < 1.10,+ xml-conduit >= 1.9.1.1 && < 1.10,+ unicode-collation >= 0.1.1 && < 0.2, zip-archive >= 0.2.3.4 && < 0.5, zlib >= 0.5 && < 0.7 if os(windows) && arch(i386)@@ -511,6 +517,7 @@ Text.Pandoc.Options, Text.Pandoc.Extensions, Text.Pandoc.Shared,+ Text.Pandoc.Sources, Text.Pandoc.MediaBag, Text.Pandoc.Error, Text.Pandoc.Filter,@@ -600,7 +607,6 @@ Text.Pandoc.Asciify, Text.Pandoc.Emoji, Text.Pandoc.ImageSize,- Text.Pandoc.BCP47, Text.Pandoc.Class, Text.Pandoc.Citeproc other-modules: Text.Pandoc.App.CommandLineOptions,@@ -657,6 +663,9 @@ Text.Pandoc.Readers.Metadata, Text.Pandoc.Readers.Roff, Text.Pandoc.Writers.Docx.StyleMap,+ Text.Pandoc.Writers.Docx.Table,+ Text.Pandoc.Writers.Docx.Types,+ Text.Pandoc.Writers.GridTable Text.Pandoc.Writers.JATS.References, Text.Pandoc.Writers.JATS.Table, Text.Pandoc.Writers.JATS.Types,@@ -729,7 +738,7 @@ main-is: trypandoc.hs hs-source-dirs: trypandoc if flag(trypandoc)- build-depends: aeson, http-types, wai >= 0.3, wai-extra >= 3.0.24+ build-depends: aeson, http-types, text, wai >= 0.3, wai-extra >= 3.0.24 buildable: True else buildable: False@@ -759,7 +768,7 @@ tasty-lua >= 0.2 && < 0.3, tasty-quickcheck >= 0.8 && < 0.11, text >= 1.1.1.0 && < 1.3,- time >= 1.5 && < 1.10,+ time >= 1.5 && < 1.12, xml >= 1.3.12 && < 1.4, zip-archive >= 0.2.3.4 && < 0.5 other-modules: Tests.Old
@@ -55,7 +55,7 @@ import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs, options) import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings)-import Text.Pandoc.BCP47 (Lang (..), parseBCP47)+import Text.Collate.Lang (Lang (..), parseLang) import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), applyFilters) import Text.Pandoc.PDF (makePDF) import Text.Pandoc.SelfContained (makeSelfContained)@@ -160,9 +160,11 @@ else optTabStop opts) - let readSources :: [FilePath] -> PandocIO Text- readSources srcs = convertTabs . T.intercalate (T.pack "\n") <$>- mapM readSource srcs+ let readSources :: [FilePath] -> PandocIO [(FilePath, Text)]+ readSources srcs =+ mapM (\fp -> do+ t <- readSource fp+ return (if fp == "-" then "" else fp, convertTabs t)) srcs outputSettings <- optToOutputSettings opts@@ -200,8 +202,8 @@ Just f -> readFileStrict f case lookupMetaString "lang" (optMetadata opts) of- "" -> setTranslations $ Lang "en" "" "US" []- l -> case parseBCP47 l of+ "" -> setTranslations $ Lang "en" Nothing (Just "US") [] [] []+ l -> case parseLang l of Left _ -> report $ InvalidLang l Right l' -> setTranslations l' @@ -255,13 +257,17 @@ let sourceToDoc :: [FilePath] -> PandocIO Pandoc sourceToDoc sources' = case reader of- TextReader r- | optFileScope opts || readerNameBase == "json" ->- mconcat <$> mapM (readSource >=> r readerOpts) sources'- | otherwise ->- readSources sources' >>= r readerOpts- ByteStringReader r ->- mconcat <$> mapM (readFile' >=> r readerOpts) sources'+ TextReader r+ | readerNameBase == "json" ->+ mconcat <$> mapM (readSource >=> r readerOpts) sources'+ | optFileScope opts ->+ -- Read source and convert tabs (see #6709)+ let readSource' = fmap convertTabs . readSource+ in mconcat <$> mapM (readSource' >=> r readerOpts) sources'+ | otherwise ->+ readSources sources' >>= r readerOpts+ ByteStringReader r ->+ mconcat <$> mapM (readFile' >=> r readerOpts) sources' when (readerNameBase == "markdown_github" ||
@@ -687,7 +687,7 @@ where pMetaString = pure . MetaString <$> P.manyChar P.anyChar runEverything p =- runPure (P.readWithM p (def :: P.ParserState) "")+ runPure (P.readWithM p (def :: P.ParserState) ("" :: Text)) >>= fmap (Meta . flip P.runF def) yamlToMeta _ = return mempty
@@ -10,396 +10,19 @@ Function to convert accented latin letters to their unaccented ascii equivalents (used in constructing HTML identifiers). -}-module Text.Pandoc.Asciify (toAsciiChar)+module Text.Pandoc.Asciify (toAsciiChar, toAsciiText) where-import Data.Char (isAscii)-import qualified Data.Map as M+import Data.Char (isAscii, isMark)+import qualified Data.Text.Normalize as TN+import Data.Text (Text)+import qualified Data.Text as T -toAsciiChar :: Char -> Maybe Char-toAsciiChar c | isAscii c = Just c- | otherwise = M.lookup c asciiMap+toAsciiText :: Text -> Text+toAsciiText = T.filter isAscii . TN.normalize (TN.NFD) -asciiMap :: M.Map Char Char-asciiMap = M.fromList- [('\192','A')- ,('\193','A')- ,('\194','A')- ,('\195','A')- ,('\196','A')- ,('\197','A')- ,('\199','C')- ,('\200','E')- ,('\201','E')- ,('\202','E')- ,('\203','E')- ,('\204','I')- ,('\205','I')- ,('\206','I')- ,('\207','I')- ,('\209','N')- ,('\210','O')- ,('\211','O')- ,('\212','O')- ,('\213','O')- ,('\214','O')- ,('\217','U')- ,('\218','U')- ,('\219','U')- ,('\220','U')- ,('\221','Y')- ,('\224','a')- ,('\225','a')- ,('\226','a')- ,('\227','a')- ,('\228','a')- ,('\229','a')- ,('\231','c')- ,('\232','e')- ,('\233','e')- ,('\234','e')- ,('\235','e')- ,('\236','i')- ,('\237','i')- ,('\238','i')- ,('\239','i')- ,('\241','n')- ,('\242','o')- ,('\243','o')- ,('\244','o')- ,('\245','o')- ,('\246','o')- ,('\249','u')- ,('\250','u')- ,('\251','u')- ,('\252','u')- ,('\253','y')- ,('\255','y')- ,('\256','A')- ,('\257','a')- ,('\258','A')- ,('\259','a')- ,('\260','A')- ,('\261','a')- ,('\262','C')- ,('\263','c')- ,('\264','C')- ,('\265','c')- ,('\266','C')- ,('\267','c')- ,('\268','C')- ,('\269','c')- ,('\270','D')- ,('\271','d')- ,('\274','E')- ,('\275','e')- ,('\276','E')- ,('\277','e')- ,('\278','E')- ,('\279','e')- ,('\280','E')- ,('\281','e')- ,('\282','E')- ,('\283','e')- ,('\284','G')- ,('\285','g')- ,('\286','G')- ,('\287','g')- ,('\288','G')- ,('\289','g')- ,('\290','G')- ,('\291','g')- ,('\292','H')- ,('\293','h')- ,('\296','I')- ,('\297','i')- ,('\298','I')- ,('\299','i')- ,('\300','I')- ,('\301','i')- ,('\302','I')- ,('\303','i')- ,('\304','I')- ,('\305','i')- ,('\308','J')- ,('\309','j')- ,('\310','K')- ,('\311','k')- ,('\313','L')- ,('\314','l')- ,('\315','L')- ,('\316','l')- ,('\317','L')- ,('\318','l')- ,('\323','N')- ,('\324','n')- ,('\325','N')- ,('\326','n')- ,('\327','N')- ,('\328','n')- ,('\332','O')- ,('\333','o')- ,('\334','O')- ,('\335','o')- ,('\336','O')- ,('\337','o')- ,('\340','R')- ,('\341','r')- ,('\342','R')- ,('\343','r')- ,('\344','R')- ,('\345','r')- ,('\346','S')- ,('\347','s')- ,('\348','S')- ,('\349','s')- ,('\350','S')- ,('\351','s')- ,('\352','S')- ,('\353','s')- ,('\354','T')- ,('\355','t')- ,('\356','T')- ,('\357','t')- ,('\360','U')- ,('\361','u')- ,('\362','U')- ,('\363','u')- ,('\364','U')- ,('\365','u')- ,('\366','U')- ,('\367','u')- ,('\368','U')- ,('\369','u')- ,('\370','U')- ,('\371','u')- ,('\372','W')- ,('\373','w')- ,('\374','Y')- ,('\375','y')- ,('\376','Y')- ,('\377','Z')- ,('\378','z')- ,('\379','Z')- ,('\380','z')- ,('\381','Z')- ,('\382','z')- ,('\416','O')- ,('\417','o')- ,('\431','U')- ,('\432','u')- ,('\461','A')- ,('\462','a')- ,('\463','I')- ,('\464','i')- ,('\465','O')- ,('\466','o')- ,('\467','U')- ,('\468','u')- ,('\486','G')- ,('\487','g')- ,('\488','K')- ,('\489','k')- ,('\490','O')- ,('\491','o')- ,('\496','j')- ,('\500','G')- ,('\501','g')- ,('\504','N')- ,('\505','n')- ,('\512','A')- ,('\513','a')- ,('\514','A')- ,('\515','a')- ,('\516','E')- ,('\517','e')- ,('\518','E')- ,('\519','e')- ,('\520','I')- ,('\521','i')- ,('\522','I')- ,('\523','i')- ,('\524','O')- ,('\525','o')- ,('\526','O')- ,('\527','o')- ,('\528','R')- ,('\529','r')- ,('\530','R')- ,('\531','r')- ,('\532','U')- ,('\533','u')- ,('\534','U')- ,('\535','u')- ,('\536','S')- ,('\537','s')- ,('\538','T')- ,('\539','t')- ,('\542','H')- ,('\543','h')- ,('\550','A')- ,('\551','a')- ,('\552','E')- ,('\553','e')- ,('\558','O')- ,('\559','o')- ,('\562','Y')- ,('\563','y')- ,('\894',';')- ,('\7680','A')- ,('\7681','a')- ,('\7682','B')- ,('\7683','b')- ,('\7684','B')- ,('\7685','b')- ,('\7686','B')- ,('\7687','b')- ,('\7690','D')- ,('\7691','d')- ,('\7692','D')- ,('\7693','d')- ,('\7694','D')- ,('\7695','d')- ,('\7696','D')- ,('\7697','d')- ,('\7698','D')- ,('\7699','d')- ,('\7704','E')- ,('\7705','e')- ,('\7706','E')- ,('\7707','e')- ,('\7710','F')- ,('\7711','f')- ,('\7712','G')- ,('\7713','g')- ,('\7714','H')- ,('\7715','h')- ,('\7716','H')- ,('\7717','h')- ,('\7718','H')- ,('\7719','h')- ,('\7720','H')- ,('\7721','h')- ,('\7722','H')- ,('\7723','h')- ,('\7724','I')- ,('\7725','i')- ,('\7728','K')- ,('\7729','k')- ,('\7730','K')- ,('\7731','k')- ,('\7732','K')- ,('\7733','k')- ,('\7734','L')- ,('\7735','l')- ,('\7738','L')- ,('\7739','l')- ,('\7740','L')- ,('\7741','l')- ,('\7742','M')- ,('\7743','m')- ,('\7744','M')- ,('\7745','m')- ,('\7746','M')- ,('\7747','m')- ,('\7748','N')- ,('\7749','n')- ,('\7750','N')- ,('\7751','n')- ,('\7752','N')- ,('\7753','n')- ,('\7754','N')- ,('\7755','n')- ,('\7764','P')- ,('\7765','p')- ,('\7766','P')- ,('\7767','p')- ,('\7768','R')- ,('\7769','r')- ,('\7770','R')- ,('\7771','r')- ,('\7774','R')- ,('\7775','r')- ,('\7776','S')- ,('\7777','s')- ,('\7778','S')- ,('\7779','s')- ,('\7786','T')- ,('\7787','t')- ,('\7788','T')- ,('\7789','t')- ,('\7790','T')- ,('\7791','t')- ,('\7792','T')- ,('\7793','t')- ,('\7794','U')- ,('\7795','u')- ,('\7796','U')- ,('\7797','u')- ,('\7798','U')- ,('\7799','u')- ,('\7804','V')- ,('\7805','v')- ,('\7806','V')- ,('\7807','v')- ,('\7808','W')- ,('\7809','w')- ,('\7810','W')- ,('\7811','w')- ,('\7812','W')- ,('\7813','w')- ,('\7814','W')- ,('\7815','w')- ,('\7816','W')- ,('\7817','w')- ,('\7818','X')- ,('\7819','x')- ,('\7820','X')- ,('\7821','x')- ,('\7822','Y')- ,('\7823','y')- ,('\7824','Z')- ,('\7825','z')- ,('\7826','Z')- ,('\7827','z')- ,('\7828','Z')- ,('\7829','z')- ,('\7830','h')- ,('\7831','t')- ,('\7832','w')- ,('\7833','y')- ,('\7840','A')- ,('\7841','a')- ,('\7842','A')- ,('\7843','a')- ,('\7864','E')- ,('\7865','e')- ,('\7866','E')- ,('\7867','e')- ,('\7868','E')- ,('\7869','e')- ,('\7880','I')- ,('\7881','i')- ,('\7882','I')- ,('\7883','i')- ,('\7884','O')- ,('\7885','o')- ,('\7886','O')- ,('\7887','o')- ,('\7908','U')- ,('\7909','u')- ,('\7910','U')- ,('\7911','u')- ,('\7922','Y')- ,('\7923','y')- ,('\7924','Y')- ,('\7925','y')- ,('\7926','Y')- ,('\7927','y')- ,('\7928','Y')- ,('\7929','y')- ,('\8175','`')- ,('\8490','K')- ,('\8800','=')- ,('\8814','<')- ,('\8815','>')- ]+toAsciiChar :: Char -> Maybe Char+toAsciiChar c = case T.unpack (TN.normalize TN.NFD (T.singleton c)) of+ (x:xs) | isAscii x+ , all isMark xs+ -> Just x+ _ -> Nothing
@@ -1,112 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.BCP47- Copyright : Copyright (C) 2017-2021 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Functions for parsing and rendering BCP47 language identifiers.--}-module Text.Pandoc.BCP47 (- getLang- , parseBCP47- , Lang(..)- , renderLang- )-where-import Control.Monad (guard)-import Data.Char (isAlphaNum, isAscii, isLetter, isLower, isUpper)-import Text.Pandoc.Definition-import Text.Pandoc.Options-import Text.DocTemplates (FromContext(..))-import qualified Data.Text as T-import qualified Text.Parsec as P---- | Represents BCP 47 language/country code.-data Lang = Lang{ langLanguage :: T.Text- , langScript :: T.Text- , langRegion :: T.Text- , langVariants :: [T.Text] }- deriving (Eq, Ord, Show)---- | Render a Lang as BCP 47.-renderLang :: Lang -> T.Text-renderLang lang = T.intercalate "-" (langLanguage lang : filter (not . T.null)- ([langScript lang, langRegion lang] ++ langVariants lang))---- | Get the contents of the `lang` metadata field or variable.-getLang :: WriterOptions -> Meta -> Maybe T.Text-getLang opts meta =- case lookupContext "lang" (writerVariables opts) of- Just s -> Just s- _ ->- case lookupMeta "lang" meta of- Just (MetaBlocks [Para [Str s]]) -> Just s- Just (MetaBlocks [Plain [Str s]]) -> Just s- Just (MetaInlines [Str s]) -> Just s- Just (MetaString s) -> Just s- _ -> Nothing---- | Parse a BCP 47 string as a Lang. Currently we parse--- extensions and private-use fields as "variants," even--- though officially they aren't.-parseBCP47 :: T.Text -> Either T.Text Lang-parseBCP47 lang =- case P.parse bcp47 "lang" lang of- Right r -> Right r- Left e -> Left $ T.pack $ show e- where bcp47 = do- language <- pLanguage- script <- P.option "" pScript- region <- P.option "" pRegion- variants <- P.many (pVariant P.<|> pExtension P.<|> pPrivateUse)- P.eof- return Lang{ langLanguage = language- , langScript = script- , langRegion = region- , langVariants = variants }- asciiLetter = P.satisfy (\c -> isAscii c && isLetter c)- pLanguage = do- cs <- P.many1 asciiLetter- let lcs = length cs- guard $ lcs == 2 || lcs == 3- return $ T.toLower $ T.pack cs- pScript = P.try $ do- P.char '-'- x <- P.satisfy (\c -> isAscii c && isLetter c && isUpper c)- xs <- P.count 3- (P.satisfy (\c -> isAscii c && isLetter c && isLower c))- return $ T.toLower $ T.pack (x:xs)- pRegion = P.try $ do- P.char '-'- cs <- P.many1 asciiLetter- let lcs = length cs- guard $ lcs == 2 || lcs == 3- return $ T.toUpper $ T.pack cs- pVariant = P.try $ do- P.char '-'- ds <- P.option "" (P.count 1 P.digit)- cs <- P.many1 asciiLetter- let var = ds ++ cs- lv = length var- guard $ if null ds- then lv >= 5 && lv <= 8- else lv == 4- return $ T.toLower $ T.pack var- pExtension = P.try $ do- P.char '-'- cs <- P.many1 $ P.satisfy (\c -> isAscii c && isAlphaNum c)- let lcs = length cs- guard $ lcs >= 2 && lcs <= 8- return $ T.toLower $ T.pack cs- pPrivateUse = P.try $ do- P.char '-'- P.char 'x'- P.char '-'- cs <- P.many1 $ P.satisfy (\c -> isAscii c && isAlphaNum c)- guard $ not (null cs) && length cs <= 8- let var = "x-" ++ cs- return $ T.toLower $ T.pack var
@@ -18,7 +18,6 @@ import Text.Pandoc.Citeproc.BibTeX (readBibtexString, Variant(..)) import Text.Pandoc.Citeproc.MetaValue (metaValueToReference, metaValueToText) import Text.Pandoc.Readers.Markdown (yamlToRefs)-import qualified Text.Pandoc.BCP47 as BCP47 import Text.Pandoc.Builder (Inlines, Many(..), deleteMeta, setMeta) import qualified Text.Pandoc.Builder as B import Text.Pandoc.Definition as Pandoc@@ -75,8 +74,7 @@ let linkCites = maybe False truish $ lookupMeta "link-citations" meta let opts = defaultCiteprocOptions{ linkCitations = linkCites }- let result = Citeproc.citeproc opts style (localeLanguage locale)- refs citations+ let result = Citeproc.citeproc opts style mblang refs citations mapM_ (report . CiteprocWarning) (resultWarnings result) let sopts = styleOptions style let classes = "references" : -- TODO remove this or keep for compatibility?@@ -501,7 +499,7 @@ put True -- refHeader isn't used if you have an explicit references div let cs' = ordNub $ cs ++ refclasses- return $ Div ("refs",cs',kvs) (xs ++ refs)+ return $ Div ("refs",cs' ++ refclasses,kvs ++ refkvs) (xs ++ refs) go x = return x refTitle :: Meta -> Maybe [Inline]@@ -630,13 +628,8 @@ bcp47LangToIETF :: PandocMonad m => Text -> m (Maybe Lang) bcp47LangToIETF bcplang =- case BCP47.parseBCP47 bcplang of+ case parseLang bcplang of Left _ -> do report $ InvalidLang bcplang return Nothing- Right lang ->- return $ Just- $ Lang (BCP47.langLanguage lang)- (if T.null (BCP47.langRegion lang)- then Nothing- else Just (BCP47.langRegion lang))+ Right lang -> return $ Just lang
@@ -59,10 +59,11 @@ deriving (Show, Eq, Ord) -- | Parse BibTeX or BibLaTeX into a list of 'Reference's.-readBibtexString :: Variant -- ^ bibtex or biblatex+readBibtexString :: ToSources a+ => Variant -- ^ bibtex or biblatex -> Locale -- ^ Locale -> (Text -> Bool) -- ^ Filter on citation ids- -> Text -- ^ bibtex/biblatex text+ -> a -- ^ bibtex/biblatex text -> Either ParseError [Reference Inlines] readBibtexString variant locale idpred contents = do case runParser (((resolveCrossRefs variant <$> bibEntries) <* eof) >>=@@ -70,7 +71,7 @@ filter (\item -> idpred (identifier item) && entryType item /= "xdata")) (fromMaybe defaultLang $ localeLanguage locale, Map.empty)- "" contents of+ "" (toSources contents) of Left err -> Left err Right xs -> return xs @@ -155,6 +156,7 @@ , "langid" , "abstract" , "keywords"+ , "annote" ] Bibtex -> [ "author"@@ -174,6 +176,7 @@ , "address" , "type" , "note"+ , "annote" ] valToInlines (TextVal t) = B.text t@@ -205,10 +208,13 @@ [ (", " <>) <$> nameGiven name, nameDroppingParticle name ] - mblang' = (parseLang <$> getVariableAsText "language") <|> mblang+ mblang' = case getVariableAsText "language" of+ Just l -> either (const Nothing) Just $ parseLang l+ Nothing -> mblang titlecase = case mblang' of- Just (Lang "en" _) -> titlecase'+ Just lang | langLanguage lang == "en"+ -> titlecase' Nothing -> titlecase' _ -> case variant of@@ -331,12 +337,12 @@ renderFields = mconcat . intersperse ("," <> cr) . mapMaybe renderField defaultLang :: Lang-defaultLang = Lang "en" (Just "US")+defaultLang = Lang "en" Nothing (Just "US") [] [] [] -- a map of bibtex "string" macros type StringMap = Map.Map Text Text -type BibParser = Parser Text (Lang, StringMap)+type BibParser = Parser Sources (Lang, StringMap) data Item = Item{ identifier :: Text , sourcePos :: SourcePos@@ -351,9 +357,7 @@ bib item $ do let lang = fromMaybe defaultLang $ localeLanguage locale modify $ \st -> st{ localeLang = lang,- untitlecase = case lang of- (Lang "en" _) -> True- _ -> False }+ untitlecase = langLanguage lang == "en" } id' <- asks identifier otherIds <- (Just <$> getRawField "ids")@@ -711,7 +715,7 @@ bib :: Item -> Bib a -> BibParser a-bib entry m = fst <$> evalRWST m entry (BibState True (Lang "en" (Just "US")))+bib entry m = fst <$> evalRWST m entry (BibState True defaultLang) resolveCrossRefs :: Variant -> [Item] -> [Item] resolveCrossRefs variant entries =@@ -803,7 +807,7 @@ (bibComment <|> bibPreamble <|> bibString)) bibSkip :: BibParser ()-bibSkip = () <$ take1WhileP (/='@')+bibSkip = skipMany1 (satisfy (/='@')) bibComment :: BibParser () bibComment = do@@ -828,6 +832,9 @@ updateState (\(l,m) -> (l, Map.insert k v m)) return () +take1WhileP :: Monad m => (Char -> Bool) -> ParserT Sources u m Text+take1WhileP f = T.pack <$> many1 (satisfy f)+ inBraces :: BibParser Text inBraces = do char '{'@@ -1456,8 +1463,9 @@ go x = x resolveKey' :: Lang -> Text -> Text-resolveKey' lang@(Lang l _) k =- case Map.lookup l biblatexStringMap >>= Map.lookup (T.toLower k) of+resolveKey' lang k =+ case Map.lookup (langLanguage lang) biblatexStringMap >>=+ Map.lookup (T.toLower k) of Nothing -> k Just (x, _) -> either (const k) stringify $ parseLaTeX lang x
@@ -10,7 +10,7 @@ import qualified Data.Text as T import Data.Text (Text) import Text.Pandoc.Citeproc.Util (toIETF)-import Citeproc (Lang(..), parseLang)+import Text.Collate.Lang (Lang(..), parseLang) biblatexLocalizations :: [(FilePath, ByteString)] biblatexLocalizations = $(embedDir "citeproc/biblatex-localization")@@ -21,11 +21,12 @@ biblatexStringMap = foldr go mempty biblatexLocalizations where go (fp, bs) =- let Lang lang _ = parseLang (toIETF $ T.takeWhile (/= '.') $ T.pack fp)- ls = T.lines $ TE.decodeUtf8 bs- in if length ls > 4- then M.insert lang (toStringMap $ map (T.splitOn "|") ls)- else id+ let ls = T.lines $ TE.decodeUtf8 bs+ in case parseLang (toIETF $ T.takeWhile (/= '.') $ T.pack fp) of+ Right lang | length ls > 4+ -> M.insert (langLanguage lang)+ (toStringMap $ map (T.splitOn "|") ls)+ _ -> id toStringMap = foldr go' mempty go' [term, x, y] = M.insert term (x, y) go' _ = id
@@ -20,7 +20,7 @@ parseLocator locale inp = case parse (pLocatorWords (toLocatorMap locale)) "suffix" $ splitInp inp of Right r -> r- Left _ -> (Nothing, inp)+ Left _ -> (Nothing, maybeAddComma inp) splitInp :: [Inline] -> [Inline] splitInp = splitStrWhen (\c -> isSpace c || (isPunctuation c && c /= ':'))@@ -42,9 +42,17 @@ -- i.e. the first one will be " 9" return $ if T.null la && T.null lo- then (Nothing, s)+ then (Nothing, maybeAddComma s) else (Just (la, T.strip lo), s) +maybeAddComma :: [Inline] -> [Inline]+maybeAddComma [] = []+maybeAddComma ils@(Space : _) = ils+maybeAddComma ils@(Str t : _)+ | Just (c, _) <- T.uncons t+ , isPunctuation c = ils+maybeAddComma ils = Str "," : Space : ils+ pLocatorDelimited :: LocatorMap -> LocatorParser (Text, Text) pLocatorDelimited locMap = try $ do _ <- pMatchChar "{" (== '{')@@ -97,7 +105,7 @@ t <- anyToken ts <- manyTill anyToken (try $ lookAhead lim) let s = acc <> stringify (t:ts)- case M.lookup (T.strip s) locMap of+ case M.lookup (T.toCaseFold $ T.strip s) locMap of -- try to find a longer one, or return this one Just l -> go s <|> return (l, False) Nothing -> go s@@ -181,6 +189,7 @@ plainUnit = do ts <- many1 (notFollowedBy pSpace >> notFollowedBy pLocatorPunct >>+ notFollowedBy pMath >> anyToken) let s = stringify ts -- otherwise look for actual digits or -s@@ -210,6 +219,12 @@ pSpace :: LocatorParser Inline pSpace = satisfyTok (\t -> isSpacey t || t == Str "\160") <?> "space"++pMath :: LocatorParser Inline+pMath = satisfyTok isMath+ where+ isMath (Math{}) = True+ isMath _ = False satisfyTok :: (Inline -> Bool) -> LocatorParser Inline satisfyTok f = tokenPrim show (\sp _ _ -> sp) (\tok -> if f tok
@@ -19,7 +19,7 @@ import Data.Default (Default (def)) import Data.Text (Text)-import Text.Pandoc.BCP47 (Lang)+import Text.Collate.Lang (Lang) import Text.Pandoc.MediaBag (MediaBag) import Text.Pandoc.Logging (LogMessage, Verbosity (WARNING)) import Text.Pandoc.Translations (Translations)
@@ -62,7 +62,7 @@ import Text.Pandoc.Error (PandocError (..)) import Text.Pandoc.Logging (LogMessage (..), messageVerbosity, showLogMessage) import Text.Pandoc.MIME (MimeType)-import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)+import Text.Pandoc.MediaBag (MediaBag, MediaItem(..), lookupMedia, mediaDirectory) import Text.Pandoc.Walk (walk) import qualified Control.Exception as E import qualified Data.ByteString as B@@ -213,14 +213,13 @@ writeMedia dir mediabag subpath = do -- we join and split to convert a/b/c to a\b\c on Windows; -- in zip containers all paths use /- let fullpath = dir </> unEscapeString (normalise subpath) let mbcontents = lookupMedia subpath mediabag case mbcontents of Nothing -> throwError $ PandocResourceNotFound $ pack subpath- Just (_, bs) -> do- report $ Extracting $ pack fullpath+ Just item -> do+ let fullpath = dir </> mediaPath item liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)- logIOError $ BL.writeFile fullpath bs+ logIOError $ BL.writeFile fullpath $ mediaContents item -- | If the given Inline element is an image with a @src@ path equal to -- one in the list of @paths@, then prepends @dir@ to the image source;
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -37,7 +38,6 @@ , setUserDataDir , getUserDataDir , fetchItem- , fetchMediaResource , getInputFiles , setInputFiles , getOutputFile@@ -57,8 +57,6 @@ import Codec.Archive.Zip import Control.Monad.Except (MonadError (catchError, throwError), MonadTrans, lift, when)-import Data.Digest.Pure.SHA (sha1, showDigest)-import Data.Maybe (fromMaybe) import Data.List (foldl') import Data.Time (UTCTime) import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds,@@ -67,16 +65,16 @@ import Network.URI ( escapeURIString, nonStrictRelativeTo, unEscapeString, parseURIReference, isAllowedInURI, parseURI, URI(..) )-import System.FilePath ((</>), (<.>), takeExtension, dropExtension,+import System.FilePath ((</>), takeExtension, dropExtension, isRelative, splitDirectories) import System.Random (StdGen)-import Text.Pandoc.BCP47 (Lang(..), parseBCP47, renderLang)+import Text.Collate.Lang (Lang(..), parseLang, renderLang) import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Definition import Text.Pandoc.Error import Text.Pandoc.Logging-import Text.Pandoc.MIME (MimeType, getMimeType, extensionFromMimeType)-import Text.Pandoc.MediaBag (MediaBag, lookupMedia)+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)@@ -285,7 +283,7 @@ toLang :: PandocMonad m => Maybe T.Text -> m (Maybe Lang) toLang Nothing = return Nothing toLang (Just s) =- case parseBCP47 s of+ case parseLang s of Left _ -> do report $ InvalidLang s return Nothing@@ -376,7 +374,8 @@ fetchItem s = do mediabag <- getMediaBag case lookupMedia (T.unpack s) mediabag of- Just (mime, bs) -> return (BL.toStrict bs, Just mime)+ Just item -> return (BL.toStrict (mediaContents item),+ Just (mediaMimeType item)) Nothing -> downloadOrRead s -- | Returns the content and, if available, the MIME type of a resource.@@ -411,9 +410,10 @@ _ -> readLocalFile fp -- get from local file system where readLocalFile f = do resourcePath <- getResourcePath- cont <- if isRelative f- then withPaths resourcePath readFileStrict f- else readFileStrict f+ (fp', cont) <- if isRelative f+ then withPaths resourcePath readFileStrict f+ else (f,) <$> readFileStrict f+ report $ LoadedResource f fp' return (cont, mime) httpcolon = URI{ uriScheme = "http:", uriAuthority = Nothing,@@ -623,25 +623,13 @@ -- that filepath. Returns the result of the first successful execution -- of the action, or throws a @PandocResourceNotFound@ exception if the -- action errors for all filepaths.-withPaths :: PandocMonad m => [FilePath] -> (FilePath -> m a) -> FilePath -> m a+withPaths :: PandocMonad m+ => [FilePath] -> (FilePath -> m a) -> FilePath -> m (FilePath, a) withPaths [] _ fp = throwError $ PandocResourceNotFound $ T.pack fp withPaths (p:ps) action fp =- catchError (action (p </> fp))+ catchError ((p </> fp,) <$> action (p </> fp)) (\_ -> withPaths ps action fp) --- | Fetch local or remote resource (like an image) and provide data suitable--- for adding it to the MediaBag.-fetchMediaResource :: PandocMonad m- => T.Text -> m (FilePath, Maybe MimeType, BL.ByteString)-fetchMediaResource src = do- (bs, mt) <- downloadOrRead src- let ext = fromMaybe (T.pack $ takeExtension $ T.unpack src)- (mt >>= extensionFromMimeType)- let bs' = BL.fromChunks [bs]- let basename = showDigest $ sha1 bs'- let fname = basename <.> T.unpack ext- return (fname, mt, bs')- -- | Traverse tree, filling media bag for any images that -- aren't already in the media bag. fillMediaBag :: PandocMonad m => Pandoc -> m Pandoc@@ -649,12 +637,18 @@ where handleImage :: PandocMonad m => Inline -> m Inline handleImage (Image attr lab (src, tit)) = catchError (do mediabag <- getMediaBag- case lookupMedia (T.unpack src) mediabag of- Just (_, _) -> return $ Image attr lab (src, tit)- Nothing -> do- (fname, mt, bs) <- fetchMediaResource src- insertMedia fname mt bs- return $ Image attr lab (T.pack fname, tit))+ let fp = T.unpack src+ src' <- T.pack <$> case lookupMedia fp mediabag of+ Just item -> return $ mediaPath item+ Nothing -> do+ (bs, mt) <- fetchItem src+ insertMedia fp mt (BL.fromStrict bs)+ mediabag' <- getMediaBag+ case lookupMedia fp mediabag' of+ Just item -> return $ mediaPath item+ Nothing -> throwError $ PandocSomeError $+ src <> " not successfully inserted into MediaBag"+ return $ Image attr lab (src', tit)) (\e -> case e of PandocResourceNotFound _ -> do
@@ -23,26 +23,27 @@ 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) -type Input = Text- data PandocError = PandocIOError Text IOError | PandocHttpError Text HttpException | PandocShouldNeverHappenError Text | PandocSomeError Text | PandocParseError Text- | PandocParsecError Input ParseError+ | PandocParsecError Sources ParseError | PandocMakePDFError Text | PandocOptionError Text | PandocSyntaxMapError Text@@ -81,22 +82,28 @@ "Please report this to pandoc's developers: " <> s PandocSomeError s -> s PandocParseError s -> s- PandocParsecError input err' ->+ PandocParsecError (Sources inputs) err' -> let errPos = errorPos err' errLine = sourceLine errPos errColumn = sourceColumn errPos- ls = T.lines input <> [""]- errorInFile = if length ls > errLine - 1- then T.concat ["\n", ls !! (errLine - 1)- ,"\n", T.replicate (errColumn - 1) " "- ,"^"]- else ""- in "\nError at " <> tshow err' <>- -- if error comes from a chunk or included file,- -- then we won't get the right text this way:- if sourceName errPos == "source"- then errorInFile- else ""+ 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+ in if length ls > ln - 1+ then T.concat ["\n", ls !! (ln - 1)+ ,"\n", T.replicate (errColumn - 1) " "+ ,"^"]+ else ""+ in "\nError at " <> tshow err' <> errorInFile PandocMakePDFError s -> s PandocOptionError s -> s PandocSyntaxMapError s -> s
@@ -136,6 +136,8 @@ | Ext_raw_html -- ^ Allow raw HTML | Ext_raw_tex -- ^ Allow raw TeX (other than math) | Ext_raw_markdown -- ^ Parse markdown in ipynb as raw markdown+ | Ext_rebase_relative_paths -- ^ Rebase relative image and link paths,+ -- relative to directory of containing file | Ext_shortcut_reference_links -- ^ Shortcut reference links | Ext_simple_tables -- ^ Pandoc-style simple tables | Ext_smart -- ^ "Smart" quotes, apostrophes, ellipses, dashes@@ -462,6 +464,7 @@ , Ext_gutenberg , Ext_smart , Ext_literate_haskell+ , Ext_rebase_relative_paths ] getAll "markdown_strict" = allMarkdownExtensions getAll "markdown_phpextra" = allMarkdownExtensions@@ -514,6 +517,7 @@ , Ext_attributes , Ext_sourcepos , Ext_yaml_metadata_block+ , Ext_rebase_relative_paths ] getAll "commonmark_x" = getAll "commonmark" getAll "org" = autoIdExtensions <>
@@ -52,12 +52,12 @@ ("breezedark", breezeDark), ("haddock", haddock)] -languages :: [T.Text]-languages = [T.toLower (sName s) | s <- M.elems defaultSyntaxMap]+languages :: SyntaxMap -> [T.Text]+languages syntaxmap = [T.toLower (sName s) | s <- M.elems syntaxmap] -languagesByExtension :: T.Text -> [T.Text]-languagesByExtension ext =- [T.toLower (sName s) | s <- syntaxesByExtension defaultSyntaxMap (T.unpack ext)]+languagesByExtension :: SyntaxMap -> T.Text -> [T.Text]+languagesByExtension syntaxmap ext =+ [T.toLower (sName s) | s <- syntaxesByExtension syntaxmap (T.unpack ext)] highlight :: SyntaxMap -> (FormatOptions -> [SourceLine] -> a) -- ^ Formatter
@@ -85,6 +85,7 @@ | CouldNotParseCSS Text | Fetching Text | Extracting Text+ | LoadedResource FilePath FilePath | NoTitleElement Text | NoLangSpecified | InvalidLang Text@@ -195,6 +196,9 @@ ["path" .= fp] Extracting fp -> ["path" .= fp]+ LoadedResource orig found ->+ ["for" .= orig+ ,"from" .= found] NoTitleElement fallback -> ["fallback" .= fallback] NoLangSpecified -> []@@ -241,9 +245,11 @@ showPos :: SourcePos -> Text showPos pos = Text.pack $ sn ++ "line " ++ show (sourceLine pos) ++ " column " ++ show (sourceColumn pos)- where sn = if sourceName pos == "source" || sourceName pos == ""- then ""- else sourceName pos ++ " "+ where+ sn' = sourceName pos+ sn = if sn' == "source" || sn' == "" || sn' == "-"+ then ""+ else sn' ++ " " encodeLogMessages :: [LogMessage] -> BL.ByteString encodeLogMessages ms =@@ -276,7 +282,7 @@ ParsingUnescaped s pos -> "Parsing unescaped '" <> s <> "' at " <> showPos pos CouldNotLoadIncludeFile fp pos ->- "Could not load include file '" <> fp <> "' at " <> showPos pos+ "Could not load include file " <> fp <> " at " <> showPos pos MacroAlreadyDefined name pos -> "Macro '" <> name <> "' already defined, ignoring at " <> showPos pos InlineNotRendered il ->@@ -288,18 +294,18 @@ IgnoredIOError s -> "IO Error (ignored): " <> s CouldNotFetchResource fp s ->- "Could not fetch resource '" <> fp <> "'" <>+ "Could not fetch resource " <> fp <> if Text.null s then "" else ": " <> s CouldNotDetermineImageSize fp s ->- "Could not determine image size for '" <> fp <> "'" <>+ "Could not determine image size for " <> fp <> if Text.null s then "" else ": " <> s CouldNotConvertImage fp s ->- "Could not convert image '" <> fp <> "'" <>+ "Could not convert image " <> fp <> if Text.null s then "" else ": " <> s CouldNotDetermineMimeType fp ->- "Could not determine mime type for '" <> fp <> "'"+ "Could not determine mime type for " <> fp CouldNotConvertTeXMath s m ->- "Could not convert TeX math '" <> s <> "', rendering as TeX" <>+ "Could not convert TeX math " <> s <> ", rendering as TeX" <> if Text.null m then "" else ":\n" <> m CouldNotParseCSS m -> "Could not parse CSS" <> if Text.null m then "" else ":\n" <> m@@ -307,6 +313,8 @@ "Fetching " <> fp <> "..." Extracting fp -> "Extracting " <> fp <> "..."+ LoadedResource orig found ->+ "Loaded " <> Text.pack orig <> " from " <> Text.pack found NoTitleElement fallback -> "This document format requires a nonempty <title> element.\n" <> "Defaulting to '" <> fallback <> "' as the title.\n" <>@@ -387,6 +395,7 @@ CouldNotParseCSS{} -> WARNING Fetching{} -> INFO Extracting{} -> INFO+ LoadedResource{} -> INFO NoTitleElement{} -> WARNING NoLangSpecified -> INFO InvalidLang{} -> WARNING
@@ -13,7 +13,9 @@ , LuaFilter , runFilterFile , walkInlines+ , walkInlineLists , walkBlocks+ , walkBlockLists , module Text.Pandoc.Lua.Walk ) where import Control.Applicative ((<|>))
@@ -73,9 +73,9 @@ res <- MB.lookupMedia fp <$> getMediaBag liftPandocLua $ case res of Nothing -> 1 <$ Lua.pushnil- Just (mimeType, contents) -> do- Lua.push mimeType- Lua.push contents+ Just item -> do+ Lua.push $ MB.mediaMimeType item+ Lua.push $ MB.mediaContents item return 2 list :: PandocLua NumResults
@@ -23,8 +23,10 @@ import System.Exit (ExitCode (..)) import Text.Pandoc.Class.PandocIO (runIO) import Text.Pandoc.Definition (Block, Inline)-import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter, SingletonsList (..))+import Text.Pandoc.Lua.Filter (LuaFilter, SingletonsList (..), walkInlines,+ walkInlineLists, walkBlocks, walkBlockLists) import Text.Pandoc.Lua.Marshaling ()+import Text.Pandoc.Lua.Marshaling.List (List (..)) import Text.Pandoc.Lua.PandocLua (PandocLua, addFunction, liftPandocLua, loadDefaultModule) import Text.Pandoc.Walk (Walkable)@@ -51,9 +53,12 @@ return 1 walkElement :: (Walkable (SingletonsList Inline) a,- Walkable (SingletonsList Block) a)+ Walkable (SingletonsList Block) a,+ Walkable (List Inline) a,+ Walkable (List Block) a) => a -> LuaFilter -> PandocLua a-walkElement x f = liftPandocLua $ walkInlines f x >>= walkBlocks f+walkElement x f = liftPandocLua $+ walkInlines f x >>= walkInlineLists f >>= walkBlocks f >>= walkBlockLists f walk_inline :: Inline -> LuaFilter -> PandocLua Inline walk_inline = walkElement
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {- |@@ -14,6 +15,7 @@ interface for interacting with it. -} module Text.Pandoc.MediaBag (+ MediaItem(..), MediaBag, deleteMedia, lookupMedia,@@ -27,26 +29,39 @@ import Data.Maybe (fromMaybe) import Data.Typeable (Typeable) import System.FilePath-import qualified System.FilePath.Posix as Posix-import Text.Pandoc.MIME (MimeType, getMimeTypeDef)+import Text.Pandoc.MIME (MimeType, getMimeTypeDef, extensionFromMimeType)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Digest.Pure.SHA (sha1, showDigest) +data MediaItem =+ MediaItem+ { mediaMimeType :: MimeType+ , mediaPath :: FilePath+ , mediaContents :: BL.ByteString+ } deriving (Eq, Ord, Show, Data, Typeable)+ -- | A container for a collection of binary resources, with names and -- mime types. Note that a 'MediaBag' is a Monoid, so 'mempty' -- can be used for an empty 'MediaBag', and '<>' can be used to append -- two 'MediaBag's.-newtype MediaBag = MediaBag (M.Map [FilePath] (MimeType, BL.ByteString))+newtype MediaBag = MediaBag (M.Map Text MediaItem) deriving (Semigroup, Monoid, Data, Typeable) instance Show MediaBag where show bag = "MediaBag " ++ show (mediaDirectory bag) +-- | We represent paths with /, in normalized form.+canonicalize :: FilePath -> Text+canonicalize = T.replace "\\" "/" . T.pack . normalise+ -- | Delete a media item from a 'MediaBag', or do nothing if no item corresponds -- to the given path. deleteMedia :: FilePath -- ^ relative path and canonical name of resource -> MediaBag -> MediaBag deleteMedia fp (MediaBag mediamap) =- MediaBag $ M.delete (splitDirectories fp) mediamap+ MediaBag $ M.delete (canonicalize fp) mediamap -- | Insert a media item into a 'MediaBag', replacing any existing -- value with the same name.@@ -56,26 +71,34 @@ -> MediaBag -> MediaBag insertMedia fp mbMime contents (MediaBag mediamap) =- MediaBag (M.insert (splitDirectories fp) (mime, contents) mediamap)- where mime = fromMaybe fallback mbMime+ MediaBag (M.insert (canonicalize fp) mediaItem mediamap)+ where mediaItem = MediaItem{ mediaPath = showDigest (sha1 contents) <>+ "." <> ext+ , mediaContents = contents+ , mediaMimeType = mt } fallback = case takeExtension fp of ".gz" -> getMimeTypeDef $ dropExtension fp _ -> getMimeTypeDef fp+ mt = fromMaybe fallback mbMime+ ext = maybe (takeExtension fp) T.unpack $ extensionFromMimeType mt + -- | Lookup a media item in a 'MediaBag', returning mime type and contents. lookupMedia :: FilePath -> MediaBag- -> Maybe (MimeType, BL.ByteString)-lookupMedia fp (MediaBag mediamap) = M.lookup (splitDirectories fp) mediamap+ -> Maybe MediaItem+lookupMedia fp (MediaBag mediamap) = M.lookup (canonicalize fp) mediamap -- | Get a list of the file paths stored in a 'MediaBag', with -- their corresponding mime types and the lengths in bytes of the contents. mediaDirectory :: MediaBag -> [(FilePath, MimeType, Int)] mediaDirectory (MediaBag mediamap) =- M.foldrWithKey (\fp (mime,contents) ->- ((Posix.joinPath fp, mime, fromIntegral $ BL.length contents):)) [] mediamap+ M.foldrWithKey (\fp item ->+ ((T.unpack fp, mediaMimeType item,+ fromIntegral (BL.length (mediaContents item))):)) [] mediamap mediaItems :: MediaBag -> [(FilePath, MimeType, BL.ByteString)] mediaItems (MediaBag mediamap) =- M.foldrWithKey (\fp (mime,contents) ->- ((Posix.joinPath fp, mime, contents):)) [] mediamap+ M.foldrWithKey (\fp item ->+ ((T.unpack fp, mediaMimeType item, mediaContents item):))+ [] mediamap
@@ -316,6 +316,23 @@ defaultKaTeXURL = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/" -- Update documentation in doc/filters.md if this is changed.+$(deriveJSON defaultOptions{ constructorTagModifier =+ camelCaseStrToHyphenated+ } ''TrackChanges)++$(deriveJSON defaultOptions{ constructorTagModifier =+ camelCaseStrToHyphenated+ } ''WrapOption)++$(deriveJSON defaultOptions{ constructorTagModifier =+ camelCaseStrToHyphenated . drop 8+ } ''TopLevelDivision)++$(deriveJSON defaultOptions{ constructorTagModifier =+ camelCaseStrToHyphenated+ } ''ReferenceLocation)++-- Update documentation in doc/filters.md if this is changed. $(deriveJSON defaultOptions ''ReaderOptions) $(deriveJSON defaultOptions{@@ -338,20 +355,3 @@ } ''ObfuscationMethod) $(deriveJSON defaultOptions ''HTMLSlideVariant)---- Update documentation in doc/filters.md if this is changed.-$(deriveJSON defaultOptions{ constructorTagModifier =- camelCaseStrToHyphenated- } ''TrackChanges)--$(deriveJSON defaultOptions{ constructorTagModifier =- camelCaseStrToHyphenated- } ''WrapOption)--$(deriveJSON defaultOptions{ constructorTagModifier =- camelCaseStrToHyphenated . drop 8- } ''TopLevelDivision)--$(deriveJSON defaultOptions{ constructorTagModifier =- camelCaseStrToHyphenated- } ''ReferenceLocation)
@@ -5,7 +5,6 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE IncoherentInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing@@ -19,8 +18,7 @@ A utility library with parsers used in pandoc readers. -} -module Text.Pandoc.Parsing ( take1WhileP,- takeP,+module Text.Pandoc.Parsing ( module Text.Pandoc.Sources, countChar, textStr, anyLine,@@ -105,8 +103,9 @@ singleQuoteEnd, doubleQuoteStart, doubleQuoteEnd,- ellipses, apostrophe,+ doubleCloseQuote,+ ellipses, dash, nested, citeKey,@@ -122,7 +121,6 @@ (<+?>), extractIdClass, insertIncludedFile,- insertIncludedFileF, -- * Re-exports from Text.Parsec Stream, runParser,@@ -133,22 +131,10 @@ getInput, setInput, unexpected,- char,- letter,- digit,- alphaNum, skipMany, skipMany1,- spaces,- space,- anyChar,- satisfy,- newline,- string, count, eof,- noneOf,- oneOf, lookAhead, notFollowedBy, many,@@ -173,6 +159,8 @@ SourcePos, getPosition, setPosition,+ sourceName,+ setSourceName, sourceColumn, sourceLine, setSourceColumn,@@ -188,40 +176,135 @@ where import Control.Monad.Identity+ ( guard,+ join,+ unless,+ when,+ void,+ liftM2,+ liftM,+ Identity(..),+ MonadPlus(mzero) ) import Control.Monad.Reader+ ( asks, runReader, MonadReader(ask), Reader, ReaderT(ReaderT) ) import Data.Char (chr, isAlphaNum, isAscii, isAsciiUpper, isAsciiLower, isPunctuation, isSpace, ord, toLower, toUpper)-import Data.Default+import Data.Default ( Default(..) ) import Data.Functor (($>)) import Data.List (intercalate, transpose) import qualified Data.Map as M-import Data.Maybe (mapMaybe, fromMaybe)+import Data.Maybe (fromMaybe) import qualified Data.Set as Set-import Data.String import Data.Text (Text) import qualified Data.Text as T import Text.HTML.TagSoup.Entity (lookupEntity)-import Text.Pandoc.Asciify (toAsciiChar)+import Text.Pandoc.Asciify (toAsciiText) import Text.Pandoc.Builder (Blocks, HasMeta (..), Inlines, trimInlines) import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad, readFileFromDirs, report) import Text.Pandoc.Definition+ ( Target,+ nullMeta,+ nullAttr,+ Meta,+ ColWidth(ColWidthDefault, ColWidth),+ TableFoot(TableFoot),+ TableBody(TableBody),+ Attr,+ TableHead(TableHead),+ Row(..),+ Alignment(..),+ Inline(Str),+ ListNumberDelim(..),+ ListAttributes,+ ListNumberStyle(..) ) import Text.Pandoc.Logging+ ( LogMessage(CouldNotLoadIncludeFile, DuplicateIdentifier) ) import Text.Pandoc.Options+ ( extensionEnabled,+ Extension(Ext_old_dashes, Ext_tex_math_dollars,+ Ext_tex_math_single_backslash, Ext_tex_math_double_backslash,+ Ext_auto_identifiers, Ext_ascii_identifiers, Ext_smart),+ ReaderOptions(readerTabStop, readerColumns, readerExtensions) ) import Text.Pandoc.Readers.LaTeX.Types (Macro) import Text.Pandoc.Shared+ ( uniqueIdent,+ tshow,+ mapLeft,+ compactify,+ trim,+ trimr,+ splitTextByIndices,+ safeRead,+ trimMath,+ schemes,+ escapeURI )+import Text.Pandoc.Sources import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn) import Text.Pandoc.XML (fromEntities)-import Text.Parsec hiding (token)-import Text.Parsec.Pos (initialPos, newPos, updatePosString)--import Control.Monad.Except+import Text.Parsec+ ( between,+ setSourceName,+ Parsec,+ Column,+ Line,+ incSourceLine,+ incSourceColumn,+ setSourceLine,+ setSourceColumn,+ sourceLine,+ sourceColumn,+ sourceName,+ setSourceName,+ setPosition,+ getPosition,+ updateState,+ setState,+ getState,+ optionMaybe,+ optional,+ option,+ endBy1,+ endBy,+ sepEndBy1,+ sepEndBy,+ sepBy1,+ sepBy,+ try,+ choice,+ (<?>),+ (<|>),+ manyTill,+ many1,+ many,+ notFollowedBy,+ lookAhead,+ eof,+ count,+ skipMany1,+ skipMany,+ unexpected,+ setInput,+ getInput,+ anyToken,+ tokenPrim,+ parse,+ runParserT,+ runParser,+ ParseError,+ ParsecT,+ SourcePos,+ Stream(..) )+import Text.Parsec.Pos (initialPos, newPos)+import Control.Monad.Except ( MonadError(throwError) ) import Text.Pandoc.Error+ ( PandocError(PandocParseError, PandocParsecError) ) type Parser t s = Parsec t s 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.@@ -250,70 +333,48 @@ mappend = (<>) -- | Like @count@, but packs its result-countChar :: (Stream s m Char, Monad m)+countChar :: (Stream s m Char, UpdateSourcePos s Char, Monad m) => Int -> ParsecT s st m Char -> ParsecT s st m Text countChar n = fmap T.pack . count n -- | Like @string@, but uses @Text@.-textStr :: Stream s m Char => Text -> ParsecT s u m Text+textStr :: (Stream s m Char, UpdateSourcePos s Char)+ => Text -> ParsecT s u m Text textStr t = string (T.unpack t) $> t --- | Parse characters while a predicate is true.-take1WhileP :: Monad m- => (Char -> Bool)- -> ParserT Text st m Text-take1WhileP f = do- -- needed to persuade parsec that this won't match an empty string:- c <- satisfy f- inp <- getInput- pos <- getPosition- let (t, rest) = T.span f inp- setInput rest- setPosition $- if f '\t' || f '\n'- then updatePosString pos $ T.unpack t- else incSourceColumn pos (T.length t)- return $ T.singleton c <> t --- Parse n characters of input (or the rest of the input if--- there aren't n characters).-takeP :: Monad m => Int -> ParserT Text st m Text-takeP n = do- guard (n > 0)- -- faster than 'count n anyChar'- inp <- getInput- pos <- getPosition- let (xs, rest) = T.splitAt n inp- -- needed to persuade parsec that this won't match an empty string:- anyChar- setInput rest- setPosition $ updatePosString pos $ T.unpack xs- return xs---- | Parse any line of text-anyLine :: Monad m => ParserT Text st m Text+-- | Parse any line of text, returning the contents without the+-- final newline.+anyLine :: Monad m => ParserT Sources st m Text anyLine = do -- This is much faster than: -- manyTill anyChar newline inp <- getInput- pos <- getPosition- case T.break (=='\n') inp of- (this, T.uncons -> Just ('\n', rest)) -> do- -- needed to persuade parsec that this won't match an empty string:- anyChar- setInput rest- setPosition $ incSourceLine (setSourceColumn pos 1) 1- return this- _ -> mzero+ case inp of+ Sources [] -> mzero+ Sources ((fp,t):inps) ->+ -- we assume that lines don't span different input files+ case T.break (=='\n') t of+ (this, rest)+ | T.null rest+ , not (null inps) ->+ -- line may span different input files, so do it+ -- character by character+ T.pack <$> manyTill anyChar newline+ | otherwise -> do -- either end of inputs or newline in rest+ setInput $ Sources ((fp, rest):inps)+ char '\n' -- needed so parsec knows we won't match empty string+ -- and so source pos is updated+ return this -- | Parse any line, include the final newline in the output-anyLineNewline :: Monad m => ParserT Text st m Text+anyLineNewline :: Monad m => ParserT Sources st m Text anyLineNewline = (<> "\n") <$> anyLine -- | Parse indent by specified number of spaces (or equiv. tabs)-indentWith :: Stream s m Char+indentWith :: (Stream s m Char, UpdateSourcePos s Char) => HasReaderOptions st => Int -> ParserT s st m Text indentWith num = do@@ -398,11 +459,13 @@ return (return ()) -- (This version due to Andrew Pimlott on the Haskell mailing list.) -oneOfStrings' :: Stream s m Char => (Char -> Char -> Bool) -> [Text] -> ParserT s st m Text+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 => (Char -> Char -> Bool) -> [String] -> ParserT s st m String+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@@ -417,14 +480,16 @@ -- | 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 => [Text] -> ParserT s st m Text+oneOfStrings :: (Stream s m Char, UpdateSourcePos s Char)+ => [Text] -> ParserT s st m Text oneOfStrings = oneOfStrings' (==) -- | Parses one of a list of strings (tried in order), case insensitive. -- 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 => [Text] -> ParserT s st m Text+oneOfStringsCI :: (Stream s m Char, UpdateSourcePos s Char)+ => [Text] -> ParserT s st m Text oneOfStringsCI = oneOfStrings' ciMatch where ciMatch x y = toLower' x == toLower' y -- this optimizes toLower by checking common ASCII case@@ -435,11 +500,13 @@ | otherwise = toLower c -- | Parses a space or tab.-spaceChar :: Stream s m Char => ParserT s st m Char+spaceChar :: (Stream s m Char, UpdateSourcePos s Char)+ => ParserT s st m Char spaceChar = satisfy $ \c -> c == ' ' || c == '\t' -- | Parses a nonspace, nonnewline character.-nonspaceChar :: Stream s m Char => ParserT s st m Char+nonspaceChar :: (Stream s m Char, UpdateSourcePos s Char)+ => ParserT s st m Char nonspaceChar = satisfy (not . isSpaceChar) isSpaceChar :: Char -> Bool@@ -450,21 +517,24 @@ isSpaceChar _ = False -- | Skips zero or more spaces or tabs.-skipSpaces :: Stream s m Char => ParserT s st m ()+skipSpaces :: (Stream s m Char, UpdateSourcePos s Char)+ => ParserT s st m () skipSpaces = skipMany spaceChar -- | Skips zero or more spaces or tabs, then reads a newline.-blankline :: Stream s m Char => ParserT s st m Char+blankline :: (Stream s m Char, UpdateSourcePos s Char)+ => ParserT 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 => ParserT s st m Text+blanklines :: (Stream s m Char, UpdateSourcePos s Char)+ => ParserT 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 Text st m ()+ => Int -> ParserT Sources st m () gobbleSpaces 0 = return () gobbleSpaces n | n < 0 = error "gobbleSpaces called with negative number"@@ -472,18 +542,26 @@ char ' ' <|> eatOneSpaceOfTab gobbleSpaces (n - 1) -eatOneSpaceOfTab :: (HasReaderOptions st, Monad m) => ParserT Text st m Char+eatOneSpaceOfTab :: (HasReaderOptions st, Monad m) => ParserT Sources st m Char eatOneSpaceOfTab = do- char '\t'+ lookAhead (char '\t')+ pos <- getPosition tabstop <- getOption readerTabStop+ -- replace the tab on the input stream with spaces+ let numSpaces = tabstop - ((sourceColumn pos - 1) `mod` tabstop) inp <- getInput- setInput $ T.replicate (tabstop - 1) " " <> inp- return ' '+ setInput $+ case inp of+ Sources [] -> error "eatOneSpaceOfTab - empty Sources list"+ Sources ((fp,t):rest) ->+ -- drop the tab and add spaces+ Sources ((fp, T.replicate numSpaces " " <> T.drop 1 t):rest)+ char ' ' -- | 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 Text st m Int+ => Int -> ParserT Sources st m Int gobbleAtMostSpaces 0 = return 0 gobbleAtMostSpaces n | n < 0 = error "gobbleAtMostSpaces called with negative number"@@ -492,7 +570,8 @@ (+ 1) <$> gobbleAtMostSpaces (n - 1) -- | Parses material enclosed between start and end parsers.-enclosed :: (Show end, Stream s m Char) => ParserT s st m t -- ^ start parser+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]@@ -500,39 +579,41 @@ start >> notFollowedBy space >> many1Till parser end -- | Parse string, case insensitive.-stringAnyCase :: Stream s m Char => Text -> ParserT s st m Text+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 => String -> ParserT s st m String+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) +-- TODO rewrite by just adding to Sources stream? -- | Parse contents of 'str' using 'parser' and return result.-parseFromString :: (Stream s m Char, IsString s)- => ParserT s st m r+parseFromString :: Monad m+ => ParserT Sources st m r -> Text- -> ParserT s st m r+ -> ParserT Sources st m r parseFromString parser str = do oldPos <- getPosition- setPosition $ initialPos " chunk"+ setPosition $ initialPos "chunk" oldInput <- getInput- setInput $ fromString $ T.unpack str+ setInput $ toSources str result <- parser spaces- eof setInput oldInput setPosition oldPos return result -- | Like 'parseFromString' but specialized for 'ParserState'. -- This resets 'stateLastStrPos', which is almost always what we want.-parseFromString' :: (Stream s m Char, IsString s, HasLastStrPosition u)- => ParserT s u m a+parseFromString' :: (Monad m, HasLastStrPosition u)+ => ParserT Sources u m a -> Text- -> ParserT s u m a+ -> ParserT Sources u m a parseFromString' parser str = do oldLastStrPos <- getLastStrPos <$> getState updateState $ setLastStrPos Nothing@@ -541,7 +622,7 @@ return res -- | Parse raw line block up to and including blank lines.-lineClump :: Monad m => ParserT Text st m Text+lineClump :: Monad m => ParserT Sources st m Text lineClump = blanklines <|> (T.unlines <$> many1 (notFollowedBy blankline >> anyLine)) @@ -550,7 +631,7 @@ -- 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 => Char -> Char -> ParserT s st m Char+charsInBalanced :: (Stream s m Char, UpdateSourcePos s Char) => Char -> Char -> ParserT s st m Char -> ParserT s st m Text charsInBalanced open close parser = try $ do char open@@ -569,7 +650,7 @@ -- Auxiliary functions for romanNumeral: -- | Parses a roman numeral (uppercase or lowercase), returns number.-romanNumeral :: Stream s m Char => Bool -- ^ Uppercase if true+romanNumeral :: (Stream s m Char, UpdateSourcePos s Char) => Bool -- ^ Uppercase if true -> ParserT s st m Int romanNumeral upperCase = do let rchar uc = char $ if upperCase then uc else toLower uc@@ -605,7 +686,7 @@ -- | Parses an email address; returns original and corresponding -- escaped mailto: URI.-emailAddress :: Stream s m Char => ParserT s st m (Text, Text)+emailAddress :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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)@@ -629,11 +710,11 @@ isEmailPunct c = T.any (== c) "!\"#$%&'*+-/=?^_{|}~;" -uriScheme :: Stream s m Char => ParserT s st m Text+uriScheme :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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 => ParserT s st m (Text, Text)+uri :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (Text, Text) uri = try $ do scheme <- uriScheme char ':'@@ -676,7 +757,7 @@ uriChunkBetween l r = try $ do chunk <- between (char l) (char r) uriChunk return (T.pack $ [l] ++ chunk ++ [r]) -mathInlineWith :: Stream s m Char => Text -> Text -> ParserT s st m Text+mathInlineWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParserT s st m Text mathInlineWith op cl = try $ do textStr op when (op == "$") $ notFollowedBy space@@ -697,10 +778,10 @@ notFollowedBy digit -- to prevent capture of $5 return $ trimMath $ T.concat words' where- inBalancedBraces :: Stream s m Char => Int -> Text -> ParserT s st m Text+ 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 => Int -> String -> ParserT s st m String+ inBalancedBraces' :: (Stream s m Char, UpdateSourcePos s Char) => Int -> String -> ParserT s st m String inBalancedBraces' 0 "" = do c <- anyChar if c == '{'@@ -717,13 +798,13 @@ '{' -> inBalancedBraces' (numOpen + 1) (c:xs) _ -> inBalancedBraces' numOpen (c:xs) -mathDisplayWith :: Stream s m Char => Text -> Text -> ParserT s st m Text+mathDisplayWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParserT 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)+mathDisplay :: (HasReaderOptions st, Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Text mathDisplay = (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")@@ -732,7 +813,7 @@ <|> (guardEnabled Ext_tex_math_double_backslash >> mathDisplayWith "\\\\[" "\\\\]") -mathInline :: (HasReaderOptions st , Stream s m Char)+mathInline :: (HasReaderOptions st, Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Text mathInline = (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")@@ -745,7 +826,7 @@ -- 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+withHorizDisplacement :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m a -- ^ Parser to apply -> ParserT s st m (a, Int) -- ^ (result, displacement) withHorizDisplacement parser = do@@ -757,30 +838,37 @@ -- | Applies a parser and returns the raw string that was parsed, -- along with the value produced by the parser. withRaw :: Monad m- => ParsecT Text st m a- -> ParsecT Text st m (a, Text)+ => ParsecT Sources st m a+ -> ParsecT Sources st m (a, Text) withRaw parser = do- pos1 <- getPosition- inp <- getInput+ inps1 <- getInput result <- parser- pos2 <- getPosition- let (l1,c1) = (sourceLine pos1, sourceColumn pos1)- let (l2,c2) = (sourceLine pos2, sourceColumn pos2)- let inplines = take ((l2 - l1) + 1) $ T.lines inp- let raw = case inplines of- [] -> ""- [l] -> T.take (c2 - c1) l- ls -> T.unlines (init ls) <> T.take (c2 - 1) (last ls)- return (result, raw)+ inps2 <- getInput+ -- 'raw' is the difference between inps1 and inps2+ return (result, sourcesDifference inps1 inps2) +sourcesDifference :: Sources -> Sources -> Text+sourcesDifference (Sources is1) (Sources is2) = go is1 is2+ where+ go inps1 inps2 =+ case (inps1, inps2) of+ ([], _) -> mempty+ (_, []) -> mconcat $ map snd inps1+ ((p1,t1):rest1, (p2, t2):rest2)+ | p1 == p2+ , t1 == t2 -> go rest1 rest2+ | p1 == p2+ , t1 /= t2 -> fromMaybe mempty $ T.stripSuffix t2 t1+ | otherwise -> t1 <> go rest1 inps2+ -- | Parses backslash, then applies character parser.-escaped :: Stream s m Char+escaped :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Char -- ^ Parser for character to escape -> ParserT s st m Char escaped parser = try $ char '\\' >> parser -- | Parse character entity.-characterReference :: Stream s m Char => ParserT s st m Char+characterReference :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Char characterReference = try $ do char '&' ent <- many1Till nonspaceChar (char ';')@@ -793,19 +881,19 @@ _ -> Prelude.fail "entity not found" -- | Parses an uppercase roman numeral and returns (UpperRoman, number).-upperRoman :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)+upperRoman :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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 => ParserT s st m (ListNumberStyle, Int)+lowerRoman :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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 => ParserT s st m (ListNumberStyle, Int)+decimal :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int) decimal = do num <- many1 digit return (Decimal, fromMaybe 1 $ safeRead $ T.pack num)@@ -814,7 +902,7 @@ -- returns (DefaultStyle, [next example number]). The next -- example number is incremented in parser state, and the label -- (if present) is added to the label table.-exampleNum :: Stream s m Char+exampleNum :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s ParserState m (ListNumberStyle, Int) exampleNum = do char '@'@@ -833,37 +921,37 @@ return (Example, num) -- | Parses a '#' returns (DefaultStyle, 1).-defaultNum :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)+defaultNum :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int) defaultNum = do char '#' return (DefaultStyle, 1) -- | Parses a lowercase letter and returns (LowerAlpha, number).-lowerAlpha :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)+lowerAlpha :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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 => ParserT s st m (ListNumberStyle, Int)+upperAlpha :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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 => ParserT s st m (ListNumberStyle, Int)+romanOne :: (Stream s m Char, UpdateSourcePos s Char) => ParserT 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 => ParserT s ParserState m ListAttributes+anyOrderedListMarker :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s ParserState m ListAttributes anyOrderedListMarker = choice [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens], numParser <- [decimal, exampleNum, defaultNum, romanOne, lowerAlpha, lowerRoman, upperAlpha, upperRoman]] -- | Parses a list number (num) followed by a period, returns list attributes.-inPeriod :: Stream s m Char+inPeriod :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int) -> ParserT s st m ListAttributes inPeriod num = try $ do@@ -875,7 +963,7 @@ return (start, style, delim) -- | Parses a list number (num) followed by a paren, returns list attributes.-inOneParen :: Stream s m Char+inOneParen :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int) -> ParserT s st m ListAttributes inOneParen num = try $ do@@ -884,7 +972,7 @@ return (start, style, OneParen) -- | Parses a list number (num) enclosed in parens, returns list attributes.-inTwoParens :: Stream s m Char+inTwoParens :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int) -> ParserT s st m ListAttributes inTwoParens num = try $ do@@ -895,7 +983,7 @@ -- | Parses an ordered list marker with a given style and delimiter, -- returns number.-orderedListMarker :: Stream s m Char+orderedListMarker :: (Stream s m Char, UpdateSourcePos s Char) => ListNumberStyle -> ListNumberDelim -> ParserT s ParserState m Int@@ -918,10 +1006,10 @@ return start -- | Parses a character reference and returns a Str element.-charRef :: Stream s m Char => ParserT s st m Inline+charRef :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inline charRef = Str . T.singleton <$> characterReference -lineBlockLine :: Monad m => ParserT Text st m Text+lineBlockLine :: Monad m => ParserT Sources st m Text lineBlockLine = try $ do char '|' char ' '@@ -931,11 +1019,11 @@ continuations <- many (try $ char ' ' >> anyLine) return $ white <> T.unwords (line : continuations) -blankLineBlockLine :: Stream s m Char => ParserT s st m Char+blankLineBlockLine :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Char blankLineBlockLine = try (char '|' >> blankline) -- | Parses an RST-style line block and returns a list of strings.-lineBlockLines :: Monad m => ParserT Text st m [Text]+lineBlockLines :: Monad m => ParserT Sources st m [Text] lineBlockLines = try $ do lines' <- many1 (lineBlockLine <|> (T.singleton <$> blankLineBlockLine)) skipMany blankline@@ -943,7 +1031,8 @@ -- | Parse a table using 'headerParser', 'rowParser', -- 'lineParser', and 'footerParser'.-tableWith :: (Stream s m Char, HasReaderOptions st, Monad mf)+tableWith :: (Stream s m Char, UpdateSourcePos s Char,+ HasReaderOptions st, Monad mf) => ParserT s st m (mf [Blocks], [Alignment], [Int]) -> ([Int] -> ParserT s st m (mf [Blocks])) -> ParserT s st m sep@@ -963,7 +1052,8 @@ type TableComponents mf = ([Alignment], [Double], mf [Row], mf [Row]) -tableWith' :: (Stream s m Char, HasReaderOptions st, Monad mf)+tableWith' :: (Stream s m Char, UpdateSourcePos s Char,+ HasReaderOptions st, Monad mf) => ParserT s st m (mf [Blocks], [Alignment], [Int]) -> ([Int] -> ParserT s st m (mf [Blocks])) -> ParserT s st m sep@@ -1012,20 +1102,19 @@ -- (which may be grid), then the rows, -- which may be grid, separated by blank lines, and -- ending with a footer (dashed line followed by blank line).-gridTableWith :: (Stream s m Char, HasReaderOptions st, HasLastStrPosition st,- Monad mf, IsString s)- => ParserT s st m (mf Blocks) -- ^ Block list parser+gridTableWith :: (Monad m, HasReaderOptions st, HasLastStrPosition st, Monad mf)+ => ParserT Sources st m (mf Blocks) -- ^ Block list parser -> Bool -- ^ Headerless table- -> ParserT s st m (mf Blocks)+ -> ParserT Sources st m (mf Blocks) gridTableWith blocks headless = tableWith (gridTableHeader headless blocks) (gridTableRow blocks) (gridTableSep '-') gridTableFooter -gridTableWith' :: (Stream s m Char, HasReaderOptions st, HasLastStrPosition st,- Monad mf, IsString s)- => ParserT s st m (mf Blocks) -- ^ Block list parser+gridTableWith' :: (Monad m, HasReaderOptions st, HasLastStrPosition st,+ Monad mf)+ => ParserT Sources st m (mf Blocks) -- ^ Block list parser -> Bool -- ^ Headerless table- -> ParserT s st m (TableComponents mf)+ -> ParserT Sources st m (TableComponents mf) gridTableWith' blocks headless = tableWith' (gridTableHeader headless blocks) (gridTableRow blocks) (gridTableSep '-') gridTableFooter@@ -1034,7 +1123,7 @@ gridTableSplitLine indices line = map removeFinalBar $ tail $ splitTextByIndices (init indices) $ trimr line -gridPart :: Stream s m Char => Char -> ParserT s st m ((Int, Int), Alignment)+gridPart :: Monad m => Char -> ParserT Sources st m ((Int, Int), Alignment) gridPart ch = do leftColon <- option False (True <$ char ':') dashes <- many1 (char ch)@@ -1049,7 +1138,7 @@ (False, False) -> AlignDefault return ((lengthDashes, lengthDashes + 1), alignment) -gridDashedLines :: Stream s m Char => Char -> ParserT s st m [((Int, Int), Alignment)]+gridDashedLines :: Monad m => Char -> ParserT Sources st m [((Int, Int), Alignment)] gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) <* blankline removeFinalBar :: Text -> Text@@ -1058,14 +1147,14 @@ go c = T.any (== c) " \t" -- | Separator between rows of grid table.-gridTableSep :: Stream s m Char => Char -> ParserT s st m Char+gridTableSep :: Monad m => Char -> ParserT Sources st m Char gridTableSep ch = try $ gridDashedLines ch >> return '\n' -- | Parse header for a grid table.-gridTableHeader :: (Stream s m Char, Monad mf, IsString s, HasLastStrPosition st)+gridTableHeader :: (Monad m, Monad mf, HasLastStrPosition st) => Bool -- ^ Headerless table- -> ParserT s st m (mf Blocks)- -> ParserT s st m (mf [Blocks], [Alignment], [Int])+ -> ParserT Sources st m (mf Blocks)+ -> ParserT Sources st m (mf [Blocks], [Alignment], [Int]) gridTableHeader True _ = do optional blanklines dashes <- gridDashedLines '-'@@ -1088,17 +1177,17 @@ heads <- sequence <$> mapM (parseFromString' blocks . trim) rawHeads return (heads, aligns, indices) -gridTableRawLine :: Stream s m Char => [Int] -> ParserT s st m [Text]+gridTableRawLine :: (Stream s m Char, UpdateSourcePos s Char) => [Int] -> ParserT s st m [Text] gridTableRawLine indices = do char '|' line <- many1Till anyChar newline return (gridTableSplitLine indices $ T.pack line) -- | Parse row of grid table.-gridTableRow :: (Stream s m Char, Monad mf, IsString s, HasLastStrPosition st)- => ParserT s st m (mf Blocks)+gridTableRow :: (Monad m, Monad mf, HasLastStrPosition st)+ => ParserT Sources st m (mf Blocks) -> [Int]- -> ParserT s st m (mf [Blocks])+ -> ParserT Sources st m (mf [Blocks]) gridTableRow blocks indices = do colLines <- many1 (gridTableRawLine indices) let cols = map ((<> "\n") . T.unlines . removeOneLeadingSpace) $@@ -1119,34 +1208,38 @@ Just (c, _) -> c == ' ' -- | Parse footer for a grid table.-gridTableFooter :: Stream s m Char => ParserT s st m ()+gridTableFooter :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () gridTableFooter = optional blanklines --- -- | Removes the ParsecT layer from the monad transformer stack-readWithM :: Monad m- => ParserT Text st m a -- ^ parser- -> st -- ^ initial state- -> Text -- ^ input+readWithM :: (Monad m, ToSources t)+ => ParserT Sources st m a -- ^ parser+ -> st -- ^ initial state+ -> t -- ^ input -> m (Either PandocError a) readWithM parser state input =- mapLeft (PandocParsecError input) <$> runParserT parser state "source" input+ mapLeft (PandocParsecError sources)+ <$> runParserT parser state (initialSourceName sources) sources+ where+ sources = toSources input -- | Parse a string with a given parser and state-readWith :: Parser Text st a+readWith :: ToSources t+ => Parser Sources st a -> st- -> Text+ -> t -> Either PandocError a readWith p t inp = runIdentity $ readWithM p t inp -- | Parse a string with @parser@ (for testing). testStringWith :: Show a- => ParserT Text ParserState Identity a+ => ParserT Sources ParserState Identity a -> Text -> IO () testStringWith parser str = UTF8.putStrLn $ tshow $- readWith parser defaultParserState str+ readWith parser defaultParserState (toSources str) -- | Parsing options. data ParserState = ParserState@@ -1380,7 +1473,7 @@ then do let id' = uniqueIdent exts (B.toList header') ids let id'' = if Ext_ascii_identifiers `extensionEnabled` exts- then T.pack $ mapMaybe toAsciiChar $ T.unpack id'+ then toAsciiText id' else id' updateState $ updateIdentifierList $ Set.insert id' updateState $ updateIdentifierList $ Set.insert id''@@ -1393,34 +1486,42 @@ updateState $ updateIdentifierList $ Set.insert ident return (ident,classes,kvs) -smartPunctuation :: (HasReaderOptions st, HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)+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 smartPunctuation inlineParser = do guardEnabled Ext_smart- choice [ quoted inlineParser, apostrophe, dash, ellipses ]--apostrophe :: Stream s m Char => ParserT s st m Inlines-apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\x2019")+ choice [ quoted inlineParser, apostrophe, doubleCloseQuote, dash, ellipses ] -quoted :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)+quoted :: (HasLastStrPosition st, HasQuoteContext st m,+ Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines -> ParserT s st m Inlines quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser -singleQuoted :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)+singleQuoted :: (HasLastStrPosition st, HasQuoteContext st m,+ Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines -> ParserT s st m Inlines-singleQuoted inlineParser = try $ B.singleQuoted . mconcat- <$ singleQuoteStart- <*> withQuoteContext InSingleQuote (many1Till inlineParser singleQuoteEnd)+singleQuoted inlineParser = do+ singleQuoteStart+ (B.singleQuoted . mconcat <$>+ try+ (withQuoteContext InSingleQuote (many1Till inlineParser singleQuoteEnd)))+ <|> pure "\8217" -doubleQuoted :: (HasQuoteContext st m, Stream s m Char)+doubleQuoted :: (HasQuoteContext st m, HasLastStrPosition st,+ Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines -> ParserT s st m Inlines-doubleQuoted inlineParser = try $ B.doubleQuoted . mconcat- <$ doubleQuoteStart- <*> withQuoteContext InDoubleQuote (manyTill inlineParser doubleQuoteEnd)+doubleQuoted inlineParser = do+ doubleQuoteStart+ (B.doubleQuoted . mconcat <$>+ try+ (withQuoteContext InDoubleQuote (manyTill inlineParser doubleQuoteEnd)))+ <|> pure (B.str "\8220") failIfInQuoteContext :: (HasQuoteContext st m, Stream s m t) => QuoteContext@@ -1429,13 +1530,14 @@ context' <- getQuoteContext when (context' == context) $ Prelude.fail "already inside quotes" -charOrRef :: Stream s m Char => [Char] -> ParserT s st m Char+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) -singleQuoteStart :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)+singleQuoteStart :: (HasLastStrPosition st, HasQuoteContext st m,+ Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () singleQuoteStart = do failIfInQuoteContext InSingleQuote@@ -1443,30 +1545,39 @@ guard =<< notAfterString try $ do charOrRef "'\8216\145"- notFollowedBy (oneOf [' ', '\t', '\n'])+ void $ lookAhead (satisfy (not . isSpaceChar)) -singleQuoteEnd :: Stream s m Char+singleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () singleQuoteEnd = try $ do charOrRef "'\8217\146" notFollowedBy alphaNum -doubleQuoteStart :: (HasQuoteContext st m, Stream s m Char)+doubleQuoteStart :: (HasLastStrPosition st,+ HasQuoteContext st m,+ Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () doubleQuoteStart = do failIfInQuoteContext InDoubleQuote+ guard =<< notAfterString try $ do charOrRef "\"\8220\147"- notFollowedBy (oneOf [' ', '\t', '\n'])+ void $ lookAhead (satisfy (not . isSpaceChar)) -doubleQuoteEnd :: Stream s m Char+doubleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () doubleQuoteEnd = void (charOrRef "\"\8221\148") -ellipses :: Stream s m Char+apostrophe :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines+apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\8217")++doubleCloseQuote :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines+doubleCloseQuote = B.str "\8221" <$ char '"'++ellipses :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines ellipses = try (string "..." >> return (B.str "\8230")) -dash :: (HasReaderOptions st, Stream s m Char)+dash :: (HasReaderOptions st, Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inlines dash = try $ do oldDashes <- extensionEnabled Ext_old_dashes <$> getOption readerExtensions@@ -1493,20 +1604,28 @@ updateState $ \st -> st{ stateMaxNestingLevel = nestlevel } return res -citeKey :: (Stream s m Char, HasLastStrPosition st)- => ParserT s st m (Bool, Text)-citeKey = try $ do+citeKey :: (Stream s m Char, UpdateSourcePos s Char, HasLastStrPosition st)+ => Bool -- ^ If True, allow expanded @{..} syntax.+ -> ParserT 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))+ else mzero+ return (suppress_author, key)++simpleCiteIdentifier :: (Stream s m Char, UpdateSourcePos s Char)+ => ParserT s st m Text+simpleCiteIdentifier = do firstChar <- alphaNum <|> char '_' <|> char '*' -- @* for wildcard in nocite let regchar = satisfy (\c -> isAlphaNum c || c == '_') let internal p = try $ p <* lookAhead regchar rest <- many $ regchar <|> internal (oneOf ":.#$%&-+?<>~/") <|> try (oneOf ":/" <* lookAhead (char '/'))- let key = firstChar:rest- return (suppress_author, T.pack key)-+ return $ T.pack $ firstChar:rest token :: (Stream s m t) => (t -> Text)@@ -1526,12 +1645,15 @@ cls' = maybe cls T.words $ lookup "class" kvs kvs' = filter (\(k,_) -> k /= "id" || k /= "class") kvs -insertIncludedFile' :: (PandocMonad m, HasIncludeFiles st)- => ParserT a st m (mf Blocks)- -> (Text -> a)- -> [FilePath] -> FilePath- -> ParserT a st m (mf Blocks)-insertIncludedFile' blocks totoks dirs f = do+insertIncludedFile :: (PandocMonad m, HasIncludeFiles st)+ => ParserT 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+insertIncludedFile parser toStream dirs f mbstartline mbendline = do oldPos <- getPosition oldInput <- getInput containers <- getIncludeFiles <$> getState@@ -1540,32 +1662,32 @@ updateState $ addIncludeFile $ T.pack f mbcontents <- readFileFromDirs dirs f contents <- case mbcontents of- Just s -> return s+ Just s -> return $ exciseLines mbstartline mbendline s Nothing -> do report $ CouldNotLoadIncludeFile (T.pack f) oldPos return ""- setPosition $ newPos f 1 1- setInput $ totoks contents- bs <- blocks+ setInput $ toStream contents+ setPosition $ newPos f (fromMaybe 1 mbstartline) 1+ result <- parser setInput oldInput setPosition oldPos updateState dropLatestIncludeFile- return bs+ return result --- | Parse content of include file as blocks. Circular includes result in an--- @PandocParseError@.-insertIncludedFile :: (PandocMonad m, HasIncludeFiles st)- => ParserT [a] st m Blocks- -> (Text -> [a])- -> [FilePath] -> FilePath- -> ParserT [a] st m Blocks-insertIncludedFile blocks totoks dirs f =- runIdentity <$> insertIncludedFile' (Identity <$> blocks) totoks dirs f+exciseLines :: Maybe Int -> Maybe Int -> Text -> Text+exciseLines Nothing Nothing t = t+exciseLines mbstartline mbendline t =+ T.unlines $ take (endline' - (startline' - 1))+ $ drop (startline' - 1) contentLines+ where+ contentLines = T.lines t+ numLines = length contentLines+ startline' = case mbstartline of+ Nothing -> 1+ Just x | x >= 0 -> x+ | otherwise -> numLines + x -- negative from end+ endline' = case mbendline of+ Nothing -> numLines+ Just x | x >= 0 -> x+ | otherwise -> numLines + x -- negative from end --- | Parse content of include file as future blocks. Circular includes result in--- an @PandocParseError@.-insertIncludedFileF :: (PandocMonad m, HasIncludeFiles st)- => ParserT Text st m (Future st Blocks)- -> [FilePath] -> FilePath- -> ParserT Text st m (Future st Blocks)-insertIncludedFileF p = insertIncludedFile' p id
@@ -1,4 +1,5 @@ {-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} {- |@@ -65,12 +66,14 @@ 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 Text.Pandoc.Options 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@@ -83,7 +86,6 @@ import Text.Pandoc.Readers.JATS (readJATS) import Text.Pandoc.Readers.Jira (readJira) import Text.Pandoc.Readers.LaTeX-import Text.Pandoc.Readers.Markdown import Text.Pandoc.Readers.MediaWiki import Text.Pandoc.Readers.Muse import Text.Pandoc.Readers.Native@@ -101,59 +103,60 @@ import Text.Pandoc.Readers.CslJson import Text.Pandoc.Readers.BibTeX import qualified Text.Pandoc.UTF8 as UTF8-import Text.Parsec.Error+import Text.Pandoc.Sources (ToSources(..), sourcesToText) -data Reader m = TextReader (ReaderOptions -> Text -> m Pandoc)+data Reader m = TextReader (forall a . ToSources a =>+ ReaderOptions -> a -> m Pandoc) | ByteStringReader (ReaderOptions -> BL.ByteString -> m Pandoc) -- | Association list of formats and readers. readers :: PandocMonad m => [(Text, Reader m)]-readers = [ ("native" , TextReader readNative)- ,("json" , TextReader readJSON)- ,("markdown" , TextReader readMarkdown)- ,("markdown_strict" , TextReader readMarkdown)- ,("markdown_phpextra" , TextReader readMarkdown)- ,("markdown_github" , TextReader readMarkdown)- ,("markdown_mmd", TextReader readMarkdown)- ,("commonmark" , TextReader readCommonMark)- ,("commonmark_x" , TextReader readCommonMark)- ,("creole" , TextReader readCreole)- ,("dokuwiki" , TextReader readDokuWiki)- ,("gfm" , TextReader readCommonMark)- ,("rst" , TextReader readRST)- ,("mediawiki" , TextReader readMediaWiki)- ,("vimwiki" , TextReader readVimwiki)- ,("docbook" , TextReader readDocBook)- ,("opml" , TextReader readOPML)- ,("org" , TextReader readOrg)- ,("textile" , TextReader readTextile) -- TODO : textile+lhs- ,("html" , TextReader readHtml)- ,("jats" , TextReader readJATS)- ,("jira" , TextReader readJira)- ,("latex" , TextReader readLaTeX)- ,("haddock" , TextReader readHaddock)- ,("twiki" , TextReader readTWiki)- ,("tikiwiki" , TextReader readTikiWiki)- ,("docx" , ByteStringReader readDocx)- ,("odt" , ByteStringReader readOdt)- ,("t2t" , TextReader readTxt2Tags)- ,("epub" , ByteStringReader readEPUB)- ,("muse" , TextReader readMuse)- ,("man" , TextReader readMan)- ,("fb2" , TextReader readFB2)- ,("ipynb" , TextReader readIpynb)- ,("csv" , TextReader readCSV)- ,("csljson" , TextReader readCslJson)- ,("bibtex" , TextReader readBibTeX)- ,("biblatex" , TextReader readBibLaTeX)+readers = [("native" , TextReader readNative)+ ,("json" , TextReader readJSON)+ ,("markdown" , TextReader readMarkdown)+ ,("markdown_strict" , TextReader readMarkdown)+ ,("markdown_phpextra" , TextReader readMarkdown)+ ,("markdown_github" , TextReader readMarkdown)+ ,("markdown_mmd", TextReader readMarkdown)+ ,("commonmark" , TextReader readCommonMark)+ ,("commonmark_x" , TextReader readCommonMark)+ ,("creole" , TextReader readCreole)+ ,("dokuwiki" , TextReader readDokuWiki)+ ,("gfm" , TextReader readCommonMark)+ ,("rst" , TextReader readRST)+ ,("mediawiki" , TextReader readMediaWiki)+ ,("vimwiki" , TextReader readVimwiki)+ ,("docbook" , TextReader readDocBook)+ ,("opml" , TextReader readOPML)+ ,("org" , TextReader readOrg)+ ,("textile" , TextReader readTextile) -- TODO : textile+lhs+ ,("html" , TextReader readHtml)+ ,("jats" , TextReader readJATS)+ ,("jira" , TextReader readJira)+ ,("latex" , TextReader readLaTeX)+ ,("haddock" , TextReader readHaddock)+ ,("twiki" , TextReader readTWiki)+ ,("tikiwiki" , TextReader readTikiWiki)+ ,("docx" , ByteStringReader readDocx)+ ,("odt" , ByteStringReader readOdt)+ ,("t2t" , TextReader readTxt2Tags)+ ,("epub" , ByteStringReader readEPUB)+ ,("muse" , TextReader readMuse)+ ,("man" , TextReader readMan)+ ,("fb2" , TextReader readFB2)+ ,("ipynb" , TextReader readIpynb)+ ,("csv" , TextReader readCSV)+ ,("csljson" , TextReader readCslJson)+ ,("bibtex" , TextReader readBibTeX)+ ,("biblatex" , TextReader readBibLaTeX) ] -- | 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- $ T.intercalate "\n" [T.pack m | Message m <- errorMessages e]+ Left e -> throwError $ PandocAppError $+ "Error parsing reader format " <> tshow s <> ": " <> tshow e Right (readerName, extsToEnable, extsToDisable) -> case lookup readerName readers of Nothing -> throwError $ PandocUnknownReaderError@@ -173,9 +176,13 @@ return (r, exts) -- | Read pandoc document from JSON format.-readJSON :: PandocMonad m- => ReaderOptions -> Text -> m Pandoc-readJSON _ t =- case eitherDecode' . BL.fromStrict . UTF8.fromText $ t of+readJSON :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc+readJSON _ s =+ case eitherDecode' . BL.fromStrict . UTF8.fromText+ . sourcesToText . toSources $ s of Right doc -> return doc- Left e -> throwError $ PandocParseError ("JSON parse error: " <> T.pack e)+ Left e -> throwError $ PandocParseError ("JSON parse error: "+ <> T.pack e)
@@ -23,41 +23,47 @@ import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Builder (setMeta, cite, str)-import Data.Text (Text) import Citeproc (Lang(..), parseLang) import Citeproc.Locale (getLocale) import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Class (PandocMonad, lookupEnv) import Text.Pandoc.Citeproc.BibTeX as BibTeX import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue)+import Text.Pandoc.Sources (ToSources(..)) import Control.Monad.Except (throwError) -- | Read BibTeX from an input string and return a Pandoc document. -- The document will have only metadata, with an empty body. -- The metadata will contain a `references` field with the -- bibliography entries, and a `nocite` field with the wildcard `[@*]`.-readBibTeX :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readBibTeX :: (PandocMonad m, ToSources a)+ => ReaderOptions -> a -> m Pandoc readBibTeX = readBibTeX' BibTeX.Bibtex -- | Read BibLaTeX from an input string and return a Pandoc document. -- The document will have only metadata, with an empty body. -- The metadata will contain a `references` field with the -- bibliography entries, and a `nocite` field with the wildcard `[@*]`.-readBibLaTeX :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readBibLaTeX :: (PandocMonad m, ToSources a)+ => ReaderOptions -> a -> m Pandoc readBibLaTeX = readBibTeX' BibTeX.Biblatex -readBibTeX' :: PandocMonad m => Variant -> ReaderOptions -> Text -> m Pandoc+readBibTeX' :: (PandocMonad m, ToSources a)+ => Variant -> ReaderOptions -> a -> m Pandoc readBibTeX' variant _opts t = do- lang <- maybe (Lang "en" (Just "US")) parseLang- <$> lookupEnv "LANG"+ mblangEnv <- lookupEnv "LANG"+ let defaultLang = Lang "en" Nothing (Just "US") [] [] []+ let lang = case mblangEnv of+ Nothing -> defaultLang+ Just l -> either (const defaultLang) id $ parseLang l locale <- case getLocale lang of Left e ->- case getLocale (Lang "en" (Just "US")) of+ case getLocale (Lang "en" Nothing (Just "US") [] [] []) of Right l -> return l Left _ -> throwError $ PandocCiteprocError e Right l -> return l case BibTeX.readBibtexString variant locale (const True) t of- Left e -> throwError $ PandocParsecError t e+ Left e -> throwError $ PandocParsecError (toSources t) e Right refs -> return $ setMeta "references" (map referenceToMetaValue refs) . setMeta "nocite"
@@ -13,23 +13,23 @@ Conversion from CSV to a 'Pandoc' table. -} module Text.Pandoc.Readers.CSV ( readCSV ) where-import Data.Text (Text) import qualified Data.Text as T import Text.Pandoc.CSV (parseCSV, defaultCSVOptions) import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class (PandocMonad)-import Text.Pandoc.Shared (crFilter) import Text.Pandoc.Error+import Text.Pandoc.Sources (ToSources(..), sourcesToText) import Text.Pandoc.Options (ReaderOptions) import Control.Monad.Except (throwError) -readCSV :: PandocMonad m+readCSV :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ Text to parse (assuming @'\n'@ line endings)+ -> a -> m Pandoc-readCSV _opts s =- case parseCSV defaultCSVOptions (crFilter s) of+readCSV _opts s = do+ let txt = sourcesToText $ toSources s+ case parseCSV defaultCSVOptions txt of Right (r:rs) -> return $ B.doc $ B.table capt (zip aligns widths) (TableHead nullAttr hdrs)@@ -45,4 +45,4 @@ aligns = replicate numcols AlignDefault widths = replicate numcols ColWidthDefault Right [] -> return $ B.doc mempty- Left e -> throwError $ PandocParsecError s e+ Left e -> throwError $ PandocParsecError (toSources [("",txt)]) e
@@ -30,45 +30,55 @@ import Control.Monad.Except import Data.Functor.Identity (runIdentity) import Data.Typeable-import Text.Pandoc.Parsing (runParserT, getPosition, sourceLine,- runF, defaultParserState, take1WhileP, option)+import Text.Pandoc.Parsing (runParserT, getPosition,+ runF, defaultParserState, option, many1, anyChar,+ Sources(..), ToSources(..), ParserT, Future,+ sourceName) import qualified Data.Text as T -- | Parse a CommonMark formatted string into a 'Pandoc' structure.-readCommonMark :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readCommonMark :: (PandocMonad m, ToSources a)+ => ReaderOptions -> a -> m Pandoc readCommonMark opts s- | isEnabled Ext_yaml_metadata_block opts- , "---" `T.isPrefixOf` s = do- let metaValueParser = do- inp <- option "" $ take1WhileP (const True)- case runIdentity- (commonmarkWith (specFor opts) "metadata value" inp) of- Left _ -> mzero- Right (Cm bls :: Cm () Blocks)- -> return $ return $ B.toMetaValue bls- res <- runParserT (do meta <- yamlMetaBlock metaValueParser- pos <- getPosition- return (meta, pos))- defaultParserState "YAML metadata" s- case res of- Left _ -> readCommonMarkBody opts s- Right (meta, pos) -> do- let dropLines 0 = id- dropLines n = dropLines (n - 1) . T.drop 1 . T.dropWhile (/='\n')- let metaLines = sourceLine pos - 1- let body = T.replicate metaLines "\n" <> dropLines metaLines s- Pandoc _ bs <- readCommonMarkBody opts body- return $ Pandoc (runF meta defaultParserState) bs- | otherwise = readCommonMarkBody opts s+ | isEnabled Ext_yaml_metadata_block opts = do+ let sources = toSources s+ let toks = concatMap sourceToToks (unSources sources)+ res <- runParserT (do meta <- yamlMetaBlock (metaValueParser opts)+ pos <- getPosition+ return (meta, pos))+ defaultParserState "YAML metadata" (toSources s)+ case res of+ Left _ -> readCommonMarkBody opts sources toks+ Right (meta, pos) -> do+ -- strip off metadata section and parse body+ let body = dropWhile (\t -> tokPos t < pos) toks+ Pandoc _ bs <- readCommonMarkBody opts sources body+ return $ Pandoc (runF meta defaultParserState) bs+ | otherwise = do+ let sources = toSources s+ let toks = concatMap sourceToToks (unSources sources)+ readCommonMarkBody opts sources toks -readCommonMarkBody :: PandocMonad m => ReaderOptions -> Text -> m Pandoc-readCommonMarkBody opts s+sourceToToks :: (SourcePos, Text) -> [Tok]+sourceToToks (pos, s) = tokenize (sourceName pos) s++metaValueParser :: Monad m+ => ReaderOptions -> ParserT Sources st m (Future st MetaValue)+metaValueParser opts = do+ inp <- option "" $ T.pack <$> many1 anyChar+ let toks = concatMap sourceToToks (unSources (toSources inp))+ case runIdentity (parseCommonmarkWith (specFor opts) toks) of+ Left _ -> mzero+ Right (Cm bls :: Cm () Blocks) -> return $ return $ B.toMetaValue bls++readCommonMarkBody :: PandocMonad m => ReaderOptions -> Sources -> [Tok] -> m Pandoc+readCommonMarkBody opts s toks | isEnabled Ext_sourcepos opts =- case runIdentity (commonmarkWith (specFor opts) "" s) of+ case runIdentity (parseCommonmarkWith (specFor opts) toks) of Left err -> throwError $ PandocParsecError s err Right (Cm bls :: Cm SourceRange Blocks) -> return $ B.doc bls | otherwise =- case runIdentity (commonmarkWith (specFor opts) "" s) of+ case runIdentity (parseCommonmarkWith (specFor opts) toks) of Left err -> throwError $ PandocParsecError s err Right (Cm bls :: Cm () Blocks) -> return $ B.doc bls @@ -102,5 +112,7 @@ | isEnabled Ext_implicit_header_references opts ] ++ [ (footnoteSpec <>) | isEnabled Ext_footnotes opts ] ++ [ (definitionListSpec <>) | isEnabled Ext_definition_lists opts ] ++- [ (taskListSpec <>) | isEnabled Ext_task_lists opts ]+ [ (taskListSpec <>) | isEnabled Ext_task_lists opts ] +++ [ (rebaseRelativePathsSpec <>)+ | isEnabled Ext_rebase_relative_paths opts ]
@@ -23,21 +23,20 @@ import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (enclosed)-import Text.Pandoc.Shared (crFilter) - -- | Read creole from an input string and return a Pandoc document.-readCreole :: PandocMonad m+readCreole :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc readCreole opts s = do- res <- readWithM parseCreole def{ stateOptions = opts } $ crFilter s <> "\n\n"+ let sources = ensureFinalNewlines 2 (toSources s)+ res <- readWithM parseCreole def{ stateOptions = opts } sources case res of Left e -> throwError e Right d -> return d -type CRLParser = ParserT Text ParserState+type CRLParser = ParserT Sources ParserState -- -- Utility functions
@@ -24,21 +24,22 @@ import Text.Pandoc.Definition import Text.Pandoc.Builder (setMeta, cite, str) import qualified Text.Pandoc.UTF8 as UTF8-import Data.Text (Text) import qualified Data.Text as T import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Citeproc.CslJson (cslJsonToReferences) import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue) import Control.Monad.Except (throwError)+import Text.Pandoc.Sources (ToSources(..), sourcesToText) -- | Read CSL JSON from an input string and return a Pandoc document. -- The document will have only metadata, with an empty body. -- The metadata will contain a `references` field with the -- bibliography entries, and a `nocite` field with the wildcard `[@*]`.-readCslJson :: PandocMonad m => ReaderOptions -> Text -> m Pandoc-readCslJson _opts t =- case cslJsonToReferences (UTF8.fromText t) of+readCslJson :: (PandocMonad m, ToSources a)+ => ReaderOptions -> a -> m Pandoc+readCslJson _opts x =+ case cslJsonToReferences (UTF8.fromText $ sourcesToText $ toSources x) of Left e -> throwError $ PandocParseError $ T.pack e Right refs -> return $ setMeta "references" (map referenceToMetaValue refs)
@@ -30,7 +30,8 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Options import Text.Pandoc.Logging (LogMessage(..))-import Text.Pandoc.Shared (crFilter, safeRead, extractSpaces)+import Text.Pandoc.Shared (safeRead, extractSpaces)+import Text.Pandoc.Sources (ToSources(..), sourcesToText) import Text.TeXMath (readMathML, writeTeX) import Text.Pandoc.XML.Light @@ -539,11 +540,15 @@ , dbContent = [] } -readDocBook :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readDocBook :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc readDocBook _ inp = do+ let sources = toSources inp tree <- either (throwError . PandocXMLError "") return $ parseXMLContents- (TL.fromStrict . handleInstructions $ crFilter inp)+ (TL.fromStrict . handleInstructions . sourcesToText $ sources) (bs, st') <- flip runStateT (def{ dbContent = tree }) $ mapM parseBlock tree return $ Pandoc (dbMeta st') (toList . mconcat $ bs) @@ -595,16 +600,24 @@ Nothing -> return () Just z -> addMetaField "author" z addMetaField "subtitle" e- addMetaField "author" e+ addAuthor e addMetaField "date" e addMetaField "release" e addMetaField "releaseinfo" e return mempty- where addMetaField fieldname elt =- case filterChildren (named fieldname) elt of- [] -> return ()- [z] -> getInlines z >>= addMeta fieldname- zs -> mapM getInlines zs >>= addMeta fieldname+ where+ addAuthor elt =+ case filterChildren (named "author") elt of+ [] -> return ()+ [z] -> fromAuthor z >>= addMeta "author"+ zs -> mapM fromAuthor zs >>= addMeta "author"+ fromAuthor elt =+ mconcat . intersperse space <$> mapM getInlines (elChildren elt)+ addMetaField fieldname elt =+ case filterChildren (named fieldname) elt of+ [] -> return ()+ [z] -> getInlines z >>= addMeta fieldname+ zs -> mapM getInlines zs >>= addMeta fieldname addMeta :: PandocMonad m => ToMetaValue a => Text -> a -> DB m () addMeta field val = modify (setMeta field val)@@ -1075,7 +1088,7 @@ return $ spanWith (attrValue "id" e, [], []) mempty "phrase" -> do let ident = attrValue "id" e- let classes = T.words $ attrValue "class" e+ let classes = T.words $ attrValue "role" e if ident /= "" || classes /= [] then innerInlines (spanWith (ident,classes,[])) else innerInlines id@@ -1239,7 +1252,8 @@ where mathMLEquations :: [Text] mathMLEquations = map writeTeX $ rights $ readMath- (\x -> qName (elName x) == "math" && qPrefix (elName x) == Just "mml")+ (\x -> qName (elName x) == "math" &&+ qURI (elName x) == Just "http://www.w3.org/1998/Math/MathML") (readMathML . showElement) latexEquations :: [Text]
@@ -61,13 +61,14 @@ import Codec.Archive.Zip import Control.Monad.Reader import Control.Monad.State.Strict+import Data.Bifunctor (bimap, first) import qualified Data.ByteString.Lazy as B import Data.Default (Default)-import Data.List (delete, intersect)+import Data.List (delete, intersect, foldl') import Data.Char (isSpace) import qualified Data.Map as M import qualified Data.Text as T-import Data.Maybe (isJust, fromMaybe)+import Data.Maybe (catMaybes, isJust, fromMaybe) import Data.Sequence (ViewL (..), viewl) import qualified Data.Sequence as Seq import qualified Data.Set as Set@@ -113,6 +114,7 @@ -- restarting , docxListState :: M.Map (T.Text, T.Text) Integer , docxPrevPara :: Inlines+ , docxTableCaptions :: [Blocks] } instance Default DState where@@ -123,6 +125,7 @@ , docxDropCap = mempty , docxListState = M.empty , docxPrevPara = mempty+ , docxTableCaptions = [] } data DEnv = DEnv { docxOptions :: ReaderOptions@@ -491,16 +494,33 @@ singleton $ Plain ils singleParaToPlain blks = blks -cellToBlocks :: PandocMonad m => Docx.Cell -> DocxContext m Blocks-cellToBlocks (Docx.Cell bps) = do+cellToCell :: PandocMonad m => RowSpan -> Docx.Cell -> DocxContext m Pandoc.Cell+cellToCell rowSpan (Docx.Cell gridSpan _ bps) = do blks <- smushBlocks <$> mapM bodyPartToBlocks bps- return $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks+ let blks' = singleParaToPlain $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks+ return (cell AlignDefault rowSpan (ColSpan (fromIntegral gridSpan)) blks') -rowToBlocksList :: PandocMonad m => Docx.Row -> DocxContext m [Blocks]-rowToBlocksList (Docx.Row cells) = do- blksList <- mapM cellToBlocks cells- return $ map singleParaToPlain blksList+rowsToRows :: PandocMonad m => [Docx.Row] -> DocxContext m [Pandoc.Row]+rowsToRows rows = do+ let rowspans = (fmap . fmap) (first RowSpan) (Docx.rowsToRowspans rows)+ cells <- traverse (traverse (uncurry cellToCell)) rowspans+ return (fmap (Pandoc.Row nullAttr) cells) +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+ where+ f ((headerRows, bodyRows), previousRowWasHeader) r@(Docx.Row h cs)+ | h == HasTblHeader || (previousRowWasHeader && any isContinuationCell cs)+ = ((r : headerRows, bodyRows), True)+ | otherwise+ = ((headerRows, r : bodyRows), False)++ isContinuationCell (Docx.Cell _ vm _) = vm == Docx.Continue++ -- like trimInlines, but also take out linebreaks trimSps :: Inlines -> Inlines trimSps (Many ils) = Many $ Seq.dropWhileL isSp $Seq.dropWhileR isSp ils@@ -546,6 +566,11 @@ 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 (Paragraph pPr parparts) | Just True <- pBidi pPr = do@@ -637,49 +662,43 @@ 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 _ look parts@(r:rs)) = do- let cap' = simpleCaption $ plain $ text cap- (hdr, rows) = case firstRowFormatting look of- True | null rs -> (Nothing, [r])- | otherwise -> (Just r, rs)- False -> (Nothing, r:rs)-- cells <- mapM rowToBlocksList rows+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)+ 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) = length c-- let toRow = Pandoc.Row nullAttr . map simpleCell- toHeaderRow l = [toRow l | not (null l)]-- -- pad cells. New Text.Pandoc.Builder will do that for us,- -- so this is for compatibility while we switch over.- let cells' = map (\row -> toRow $ take width (row ++ repeat mempty)) cells+ rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell gridSpan _ _) -> fromIntegral gridSpan) c) - hdrCells <- case hdr of- Just r' -> toHeaderRow <$> rowToBlocksList r'- Nothing -> return []+ headerCells <- rowsToRows hdr+ bodyCells <- rowsToRows rows - -- The two following variables (horizontal column alignment and- -- relative column widths) go to the default at the- -- moment. Width information is in the TblGrid field of the Tbl,- -- so should be possible. Alignment might be more difficult,- -- since there doesn't seem to be a column entity in docx.+ -- 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- widths = replicate width ColWidthDefault+ totalWidth = sum grid+ widths = (\w -> ColWidth (fromInteger w / fromInteger totalWidth)) <$> grid return $ table cap' (zip alignments widths)- (TableHead nullAttr hdrCells)- [TableBody nullAttr 0 [] cells']+ (TableHead nullAttr headerCells)+ [TableBody nullAttr 0 [] bodyCells] (TableFoot nullAttr []) bodyPartToBlocks (OMathPara e) = return $ para $ displayMath (writeTeX e) - -- replace targets with generated anchors. rewriteLink' :: PandocMonad m => Inline -> DocxContext m Inline rewriteLink' l@(Link attr ils (T.uncons -> Just ('#',target), title)) = do@@ -715,6 +734,8 @@ bodyToOutput (Body bps) = do let (metabps, blkbps) = sepBodyParts bps meta <- bodyPartsToMeta metabps+ captions <- catMaybes <$> mapM bodyPartToTableCaption blkbps+ modify (\s -> s { docxTableCaptions = captions }) blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks blks'' <- removeOrphanAnchors blks'
@@ -61,7 +61,7 @@ import Data.Bifunctor import Data.Sequence ( ViewL (..), ViewR (..), viewl, viewr, spanr, spanl , (><), (|>) )-import Text.Pandoc.Builder+import Text.Pandoc.Builder as B data Modifier a = Modifier (a -> a) | AttrModifier (Attr -> a -> a) Attr@@ -116,12 +116,12 @@ inlinesL :: Inlines -> (Inlines, Inlines) inlinesL ils = case viewl $ unMany ils of- (s :< sq) -> (singleton s, Many sq)+ (s :< sq) -> (B.singleton s, Many sq) _ -> (mempty, ils) inlinesR :: Inlines -> (Inlines, Inlines) inlinesR ils = case viewr $ unMany ils of- (sq :> s) -> (Many sq, singleton s)+ (sq :> s) -> (Many sq, B.singleton s) _ -> (ils, mempty) combineInlines :: Inlines -> Inlines -> Inlines
@@ -33,7 +33,9 @@ , ParStyle , CharStyle(cStyleData) , Row(..)+ , TblHeader(..) , Cell(..)+ , VMerge(..) , TrackedChange(..) , ChangeType(..) , ChangeInfo(..)@@ -50,6 +52,7 @@ , pHeading , constructBogusParStyleData , leftBiasedMergeRunStyle+ , rowsToRowspans ) where import Text.Pandoc.Readers.Docx.Parse.Styles import Codec.Archive.Zip@@ -225,6 +228,7 @@ data BodyPart = Paragraph ParagraphStyle [ParPart] | ListItem ParagraphStyle T.Text T.Text (Maybe Level) [ParPart] | Tbl T.Text TblGrid TblLook [Row]+ | TblCaption ParagraphStyle [ParPart] | OMathPara [Exp] deriving Show @@ -236,12 +240,61 @@ defaultTblLook :: TblLook defaultTblLook = TblLook{firstRowFormatting = False} -newtype Row = Row [Cell]- deriving Show+data Row = Row TblHeader [Cell] deriving Show -newtype Cell = Cell [BodyPart]+data TblHeader = HasTblHeader | NoTblHeader deriving (Show, Eq)++data Cell = Cell GridSpan VMerge [BodyPart] deriving Show +type GridSpan = Integer++data VMerge = Continue+ -- ^ This cell should be merged with the one above it+ | Restart+ -- ^ This cell should not be merged with the one above it+ deriving (Show, Eq)++rowsToRowspans :: [Row] -> [[(Int, Cell)]]+rowsToRowspans rows = let+ removeMergedCells = fmap (filter (\(_, Cell _ vmerge _) -> vmerge == Restart))+ in removeMergedCells (foldr f [] rows)+ where+ f :: Row -> [[(Int, Cell)]] -> [[(Int, Cell)]]+ f (Row _ cells) acc = let+ spans = g cells Nothing (listToMaybe acc)+ in spans : acc++ g ::+ -- | The current row+ [Cell] ->+ -- | Number of columns left below+ Maybe Integer ->+ -- | (rowspan so far, cell) for the row below this one+ Maybe [(Int, Cell)] ->+ -- | (rowspan so far, cell) for this row+ [(Int, Cell)]+ g cells _ Nothing = zip (repeat 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 _) : _ ->+ let spanSoFar = case vmerge of+ Restart -> 1+ Continue -> 1 + spanSoFarBelow+ columnsToDrop = thisGridSpan + (gridSpanBelow - fromMaybe gridSpanBelow columnsLeftBelow)+ (newColumnsLeftBelow, restOfRowBelow) = dropColumns columnsToDrop rowBelow+ in (spanSoFar, thisCell) : g restOfRow (Just newColumnsLeftBelow) (Just restOfRowBelow)++ dropColumns :: Integer -> [(a, Cell)] -> (Integer, [(a, Cell)])+ dropColumns n [] = (n, [])+ dropColumns n cells@((_, Cell gridSpan _ _) : otherCells) =+ if n < gridSpan+ then (gridSpan - n, cells)+ else dropColumns (n - gridSpan) otherCells+ leftBiasedMergeRunStyle :: RunStyle -> RunStyle -> RunStyle leftBiasedMergeRunStyle a b = RunStyle { isBold = isBold a <|> isBold b@@ -563,7 +616,7 @@ elemToTblGrid ns element | isElem ns "w" "tblGrid" element = let cols = findChildrenByName ns "w" "gridCol" element in- mapD (\e -> maybeToD (findAttrByName ns "w" "val" e >>= stringToInteger))+ mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>= stringToInteger)) cols elemToTblGrid _ _ = throwError WrongElem @@ -587,14 +640,31 @@ do let cellElems = findChildrenByName ns "w" "tc" element cells <- mapD (elemToCell ns) cellElems- return $ Row cells+ let hasTblHeader = maybe NoTblHeader (const HasTblHeader)+ (findChildByName ns "w" "trPr" element+ >>= findChildByName ns "w" "tblHeader")+ return $ Row hasTblHeader cells elemToRow _ _ = throwError WrongElem elemToCell :: NameSpaces -> Element -> D Cell elemToCell ns element | isElem ns "w" "tc" element = do+ let properties = findChildByName ns "w" "tcPr" element+ let gridSpan = properties+ >>= findChildByName ns "w" "gridSpan"+ >>= findAttrByName ns "w" "val"+ >>= stringToInteger+ let vMerge = case properties >>= findChildByName ns "w" "vMerge" of+ Nothing -> Restart+ Just e ->+ fromMaybe Continue $ do+ s <- findAttrByName ns "w" "val" e+ case s of+ "continue" -> Just Continue+ "restart" -> Just Restart+ _ -> Nothing cellContents <- mapD (elemToBodyPart ns) (elChildren element)- return $ Cell cellContents+ return $ Cell (fromMaybe 1 gridSpan) vMerge cellContents elemToCell _ _ = throwError WrongElem elemToParIndentation :: NameSpaces -> Element -> Maybe ParIndentation@@ -626,10 +696,9 @@ 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+ , (c:_) <- findChildrenByName ns "m" "oMathPara" element = do+ expsLst <- eitherToD $ readOMML $ showElement c+ return $ OMathPara expsLst elemToBodyPart ns element | isElem ns "w" "p" element , Just (numId, lvl) <- getNumInfo ns element = do@@ -647,13 +716,31 @@ Nothing | Just (numId, lvl) <- pNumInfo parstyle -> do levelInfo <- lookupLevel numId lvl <$> asks envNumbering return $ ListItem parstyle numId lvl levelInfo parparts- _ -> return $ Paragraph parstyle 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+ elemToBodyPart ns element | isElem ns "w" "tbl" element = do- let caption' = findChildByName ns "w" "tblPr" element+ let tblProperties = findChildByName ns "w" "tblPr" element+ caption = fromMaybe "" $ tblProperties >>= findChildByName ns "w" "tblCaption" >>= findAttrByName ns "w" "val"- caption = fromMaybe "" caption'+ description = fromMaybe "" $ tblProperties+ >>= findChildByName ns "w" "tblDescription"+ >>= findAttrByName ns "w" "val" grid' = case findChildByName ns "w" "tblGrid" element of Just g -> elemToTblGrid ns g Nothing -> return []@@ -666,7 +753,7 @@ grid <- grid' tblLook <- tblLook' rows <- mapD (elemToRow ns) (elChildren element)- return $ Tbl caption grid tblLook rows+ return $ Tbl (caption <> description) grid tblLook rows elemToBodyPart _ _ = throwError WrongElem lookupRelationship :: DocumentLocation -> RelId -> [Relationship] -> Maybe Target@@ -709,7 +796,8 @@ case drawing of Just s -> expandDrawingId s >>= (\(fp, bs) -> return $ Drawing fp title alt bs $ elemToExtent drawingElem) Nothing -> throwError WrongElem--- The below is an attempt to deal with images in deprecated vml format.+-- The two cases below are an attempt to deal with images in deprecated vml format.+-- Todo: check out title and attr for deprecated format. elemToParPart ns element | isElem ns "w" "r" element , Just _ <- findChildByName ns "w" "pict" element =@@ -717,9 +805,15 @@ >>= findAttrByName ns "r" "id" in case drawing of- -- Todo: check out title and attr for deprecated format. Just s -> expandDrawingId s >>= (\(fp, bs) -> return $ Drawing fp "" "" bs Nothing) Nothing -> throwError WrongElem+elemToParPart ns element+ | isElem ns "w" "r" element+ , Just objectElem <- findChildByName ns "w" "object" element+ , Just shapeElem <- findChildByName ns "v" "shape" objectElem+ , Just imagedataElem <- findChildByName ns "v" "imagedata" shapeElem+ , Just drawingId <- findAttrByName ns "r" "id" imagedataElem+ = expandDrawingId drawingId >>= (\(fp, bs) -> return $ Drawing fp "" "" bs Nothing) -- Chart elemToParPart ns element | isElem ns "w" "r" element
@@ -19,6 +19,7 @@ , elemToNameSpaces , findChildByName , findChildrenByName+ , findElementByName , findAttrByName ) where @@ -55,6 +56,12 @@ 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 =
@@ -29,26 +29,27 @@ import Text.Pandoc.Error (PandocError (PandocParsecError)) import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (enclosed, nested)-import Text.Pandoc.Shared (crFilter, trim, stringify, tshow)+import Text.Pandoc.Shared (trim, stringify, tshow) -- | Read DokuWiki from an input string and return a Pandoc document.-readDokuWiki :: PandocMonad m+readDokuWiki :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc readDokuWiki opts s = do- let input = crFilter s- res <- runParserT parseDokuWiki def {stateOptions = opts } "source" input+ let sources = toSources s+ res <- runParserT parseDokuWiki def {stateOptions = opts }+ (initialSourceName sources) sources case res of- Left e -> throwError $ PandocParsecError input e+ Left e -> throwError $ PandocParsecError sources e Right d -> return d -type DWParser = ParserT Text ParserState+type DWParser = ParserT Sources ParserState -- * Utility functions -- | Parse end-of-line, which can be either a newline or end-of-file.-eol :: Stream s m Char => ParserT s st m ()+eol :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () eol = void newline <|> eof nested :: PandocMonad m => DWParser m a -> DWParser m a
@@ -40,9 +40,9 @@ import Text.Pandoc.Error import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Shared (crFilter) import Text.Pandoc.XML.Light import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Sources (ToSources(..), sourcesToText) type FB2 m = StateT FB2State m @@ -63,9 +63,12 @@ setMeta field v s = s {fb2Meta = setMeta field v (fb2Meta s)} deleteMeta field s = s {fb2Meta = deleteMeta field (fb2Meta s)} -readFB2 :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readFB2 :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc readFB2 _ inp =- case parseXMLElement $ TL.fromStrict $ crFilter inp of+ case parseXMLElement $ TL.fromStrict $ sourcesToText $ toSources inp of Left msg -> throwError $ PandocXMLError "" msg Right el -> do (bs, st) <- runStateT (parseRootElement el) def
@@ -62,21 +62,21 @@ extensionEnabled) import Text.Pandoc.Parsing hiding ((<|>)) import Text.Pandoc.Shared (- addMetaField, blocksToInlines', crFilter, escapeURI, extractSpaces,+ addMetaField, blocksToInlines', escapeURI, extractSpaces, htmlSpanLikeElements, renderTags', safeRead, tshow) import Text.Pandoc.Walk import Text.Parsec.Error import Text.TeXMath (readMathML, writeTeX) -- | Convert HTML-formatted string to 'Pandoc' document.-readHtml :: PandocMonad m+readHtml :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ String to parse (assumes @'\n'@ line endings)+ -> a -- ^ Input to parse -> m Pandoc readHtml opts inp = do let tags = stripPrefixes $ canonicalizeTags $ parseTagsOptions parseOptions{ optTagPosition = True }- (crFilter inp)+ (sourcesToText $ toSources inp) parseDoc = do blocks <- fixPlains False . mconcat <$> manyTill block eof meta <- stateMeta . parserState <$> getState@@ -205,6 +205,7 @@ | otherwise -> pDiv "section" -> pDiv+ "header" -> pDiv "main" -> pDiv "figure" -> pFigure "iframe" -> pIframe@@ -404,6 +405,7 @@ isDivLike :: Text -> Bool isDivLike "div" = True isDivLike "section" = True+isDivLike "header" = True isDivLike "main" = True isDivLike _ = False @@ -499,17 +501,13 @@ tagOpen (`elem` ["h1","h2","h3","h4","h5","h6"]) (const True) let attr = toStringAttr attr'- let bodyTitle = TagOpen tagtype attr' ~== TagOpen ("h1" :: Text)- [("class","title")] level <- headerLevel tagtype contents <- trimInlines . mconcat <$> manyTill inline (pCloses tagtype <|> eof) let ident = fromMaybe "" $ lookup "id" attr let classes = maybe [] T.words $ lookup "class" attr let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"] attr'' <- registerHeader (ident, classes, keyvals) contents- return $ if bodyTitle- then mempty -- skip a representation of the title in the body- else B.headerWith attr'' level contents+ return $ B.headerWith attr'' level contents pHrule :: PandocMonad m => TagParser m Blocks pHrule = do@@ -559,7 +557,18 @@ pCodeBlock :: PandocMonad m => TagParser m Blocks pCodeBlock = try $ do TagOpen _ attr' <- pSatisfy (matchTagOpen "pre" [])- let attr = toAttr attr'+ -- if the `pre` has no attributes, try if it is followed by a `code`+ -- element and use those attributes if possible.+ attr <- case attr' of+ _:_ -> pure (toAttr attr')+ [] -> option nullAttr $ do+ TagOpen _ codeAttr <- pSatisfy (matchTagOpen "code" [])+ pure $ toAttr+ [ (k, v') | (k, v) <- codeAttr+ -- strip language from class+ , let v' = if k == "class"+ then fromMaybe v (T.stripPrefix "language-" v)+ else v ] contents <- manyTill pAny (pCloses "pre" <|> eof) let rawText = T.concat $ map tagToText contents -- drop leading newline if any@@ -830,17 +839,19 @@ pTagText :: PandocMonad m => TagParser m Inlines pTagText = try $ do+ pos <- getPosition (TagText str) <- pSatisfy isTagText st <- getState qu <- ask parsed <- lift $ lift $- flip runReaderT qu $ runParserT (many pTagContents) st "text" str+ flip runReaderT qu $ runParserT (many pTagContents) st "text"+ (Sources [(pos, str)]) case parsed of Left _ -> throwError $ PandocParseError $ "Could not parse `" <> str <> "'" Right result -> return $ mconcat result -type InlinesParser m = HTMLParser m Text+type InlinesParser m = HTMLParser m Sources pTagContents :: PandocMonad m => InlinesParser m Inlines pTagContents =@@ -940,13 +951,15 @@ getTagName _ = Nothing isInlineTag :: Tag Text -> Bool-isInlineTag t =- isCommentTag t ||- case getTagName t of- Nothing -> False- Just "script" -> "math/tex" `T.isPrefixOf` fromAttrib "type" t- Just x -> x `Set.notMember` blockTags ||- T.take 1 x == "?" -- processing instr.+isInlineTag t = isCommentTag t || case t of+ TagOpen "script" _ -> "math/tex" `T.isPrefixOf` fromAttrib "type" t+ TagClose "script" -> True+ TagOpen name _ -> isInlineTagName name+ TagClose name -> isInlineTagName name+ _ -> False+ where isInlineTagName x =+ x `Set.notMember` blockTags ||+ T.take 1 x == "?" -- processing instr. isBlockTag :: Tag Text -> Bool isBlockTag t = isBlockTagName || isTagComment t@@ -970,13 +983,14 @@ -- | Matches a stretch of HTML in balanced tags. htmlInBalanced :: Monad m => (Tag Text -> Bool)- -> ParserT Text st m Text+ -> ParserT Sources st m Text htmlInBalanced f = try $ do lookAhead (char '<')- inp <- getInput- let ts = canonicalizeTags $- parseTagsOptions parseOptions{ optTagWarning = True,- optTagPosition = True } inp+ sources <- getInput+ let ts = canonicalizeTags+ $ parseTagsOptions parseOptions{ optTagWarning = True,+ optTagPosition = True }+ $ sourcesToText sources case ts of (TagPosition sr sc : t@(TagOpen tn _) : rest) -> do guard $ f t@@ -1018,15 +1032,17 @@ -- | Matches a tag meeting a certain condition. htmlTag :: (HasReaderOptions st, Monad m) => (Tag Text -> Bool)- -> ParserT Text st m (Tag Text, Text)+ -> ParserT Sources st m (Tag Text, Text) htmlTag f = try $ do lookAhead (char '<') startpos <- getPosition- inp <- getInput+ sources <- getInput+ let inp = sourcesToText sources let ts = canonicalizeTags $ parseTagsOptions parseOptions{ optTagWarning = False , optTagPosition = True }- (inp <> " ") -- add space to ensure that+ (inp <> " ")+ -- add space to ensure that -- we get a TagPosition after the tag (next, ln, col) <- case ts of (TagPosition{} : next : TagPosition ln col : _)
@@ -17,6 +17,7 @@ import Control.Applicative ((<|>)) import Data.Maybe (fromMaybe)+import Data.Either (lefts, rights) import Data.List.NonEmpty (nonEmpty) import Data.Text (Text) import Text.HTML.TagSoup@@ -33,34 +34,51 @@ import qualified Data.Text as T import qualified Text.Pandoc.Builder as B --- | Parses a @<col>@ element, returning the column's width. Defaults to--- @'ColWidthDefault'@ if the width is not set or cannot be determined.-pCol :: PandocMonad m => TagParser m ColWidth+-- | Parses a @<col>@ element, returning the column's width.+-- An Either value is used: Left i means a "relative length" with+-- integral value i (see https://www.w3.org/TR/html4/types.html#h-6.6);+-- Right w means a regular width. Defaults to @'Right ColWidthDefault'@+-- if the width is not set or cannot be determined.+pCol :: PandocMonad m => TagParser m (Either Int ColWidth) pCol = try $ do TagOpen _ attribs' <- pSatisfy (matchTagOpen "col" []) let attribs = toStringAttr attribs' skipMany pBlank optional $ pSatisfy (matchTagClose "col") skipMany pBlank- let width = case lookup "width" attribs of+ return $ case lookup "width" attribs of Nothing -> case lookup "style" attribs of Just (T.stripPrefix "width:" -> Just xs) | T.any (== '%') xs ->- fromMaybe 0.0 $ safeRead (T.filter- (`notElem` (" \t\r\n%'\";" :: [Char])) xs)- _ -> 0.0+ maybe (Right ColWidthDefault) (Right . ColWidth)+ $ safeRead (T.filter+ (`notElem` (" \t\r\n%'\";" :: [Char])) xs)+ _ -> Right ColWidthDefault+ Just (T.unsnoc -> Just (xs, '*')) ->+ maybe (Left 1) Left $ safeRead xs Just (T.unsnoc -> Just (xs, '%')) ->- fromMaybe 0.0 $ safeRead xs- _ -> 0.0- if width > 0.0- then return $ ColWidth $ width / 100.0- else return ColWidthDefault+ maybe (Right ColWidthDefault)+ (Right . ColWidth . (/ 100.0)) $ safeRead xs+ _ -> Right ColWidthDefault -pColgroup :: PandocMonad m => TagParser m [ColWidth]+pColgroup :: PandocMonad m => TagParser m [Either Int ColWidth] pColgroup = try $ do pSatisfy (matchTagOpen "colgroup" []) skipMany pBlank manyTill pCol (pCloses "colgroup" <|> eof) <* skipMany pBlank +resolveRelativeLengths :: [Either Int ColWidth] -> [ColWidth]+resolveRelativeLengths ws =+ let remaining = 1 - sum (map getColWidth $ rights ws)+ relatives = sum $ lefts ws+ relUnit = remaining / fromIntegral relatives+ toColWidth (Right x) = x+ toColWidth (Left i) = ColWidth (fromIntegral i * relUnit)+ in map toColWidth ws++getColWidth :: ColWidth -> Double+getColWidth ColWidthDefault = 0+getColWidth (ColWidth w) = w+ data CellType = HeaderCell | BodyCell@@ -182,7 +200,8 @@ pTable block = try $ do TagOpen _ attribs <- pSatisfy (matchTagOpen "table" []) <* skipMany pBlank caption <- option mempty $ pInTags "caption" block <* skipMany pBlank- widths <- ((mconcat <$> many1 pColgroup) <|> many pCol) <* skipMany pBlank+ widths <- resolveRelativeLengths <$>+ ((mconcat <$> many1 pColgroup) <|> many pCol) <* skipMany pBlank thead <- pTableHead block <* skipMany pBlank topfoot <- optionMaybe (pTableFoot block) <* skipMany pBlank tbodies <- many (pTableBody block) <* skipMany pBlank
@@ -19,7 +19,7 @@ import Data.List (intersperse) import Data.List.NonEmpty (nonEmpty) import Data.Maybe (fromMaybe)-import Data.Text (Text, unpack)+import Data.Text (unpack) import qualified Data.Text as T import Documentation.Haddock.Parser import Documentation.Haddock.Types as H@@ -29,15 +29,17 @@ import Text.Pandoc.Definition import Text.Pandoc.Error import Text.Pandoc.Options-import Text.Pandoc.Shared (crFilter, splitTextBy, trim)+import Text.Pandoc.Sources (ToSources(..), sourcesToText)+import Text.Pandoc.Shared (splitTextBy, trim) -- | Parse Haddock markup and return a 'Pandoc' document.-readHaddock :: PandocMonad m+readHaddock :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc-readHaddock opts s = case readHaddockEither opts (unpack (crFilter s)) of+readHaddock opts s = case readHaddockEither opts+ (unpack . sourcesToText . toSources $ s) of Right result -> return result Left e -> throwError e @@ -129,7 +131,8 @@ DocIdentifier s -> B.codeWith ("",["haskell","identifier"],[]) $ T.pack s _ -> mempty DocIdentifierUnchecked s -> B.codeWith ("",["haskell","identifier"],[]) $ T.pack s- DocModule s -> B.codeWith ("",["haskell","module"],[]) $ T.pack s+ DocModule s -> B.codeWith ("",["haskell","module"],[]) $+ T.pack (modLinkName s) DocWarning _ -> mempty -- TODO DocEmphasis d -> B.emph (docHToInlines isCode d) DocMonospaced (DocString s) -> B.code $ T.pack s
@@ -39,10 +39,12 @@ import Control.Monad.Except (throwError) import Text.Pandoc.Readers.Markdown (readMarkdown) import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Sources (ToSources(..), sourcesToText) -readIpynb :: PandocMonad m => ReaderOptions -> Text -> m Pandoc-readIpynb opts t = do- let src = BL.fromStrict (TE.encodeUtf8 t)+readIpynb :: (PandocMonad m, ToSources a)+ => ReaderOptions -> a -> m Pandoc+readIpynb opts x = do+ let src = BL.fromStrict . TE.encodeUtf8 . sourcesToText $ toSources x case eitherDecode src of Right (notebook4 :: Notebook NbV4) -> notebookToPandoc opts notebook4 Left _ ->
@@ -29,11 +29,12 @@ import Text.Pandoc.Builder import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Options-import Text.Pandoc.Shared (crFilter, safeRead, extractSpaces)+import Text.Pandoc.Shared (safeRead, extractSpaces) import Text.TeXMath (readMathML, writeTeX) import Text.Pandoc.XML.Light import qualified Data.Set as S (fromList, member) import Data.Set ((\\))+import Text.Pandoc.Sources (ToSources(..), sourcesToText) type JATS m = StateT JATSState m @@ -52,10 +53,14 @@ , jatsContent = [] } -readJATS :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readJATS :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc readJATS _ inp = do+ let sources = toSources inp tree <- either (throwError . PandocXMLError "") return $- parseXMLContents (TL.fromStrict $ crFilter inp)+ parseXMLContents (TL.fromStrict . sourcesToText $ sources) (bs, st') <- flip runStateT (def{ jatsContent = tree }) $ mapM parseBlock tree return $ Pandoc (jatsMeta st') (toList . mconcat $ bs) @@ -491,7 +496,8 @@ "disp-formula" -> formula displayMath "inline-formula" -> formula math- "math" | qPrefix (elName e) == Just "mml" -> return . math $ mathML e+ "math" | qURI (elName e) == Just "http://www.w3.org/1998/Math/MathML"+ -> return . math $ mathML e "tex-math" -> return . math $ textContent e "email" -> return $ link ("mailto:" <> textContent e) ""@@ -514,8 +520,9 @@ filterChildren isMathML whereToLook return . mconcat . take 1 . map constructor $ texMaths ++ mathMLs - isMathML x = qName (elName x) == "math" &&- qPrefix (elName x) == Just "mml"+ 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
@@ -20,18 +20,20 @@ import Text.Pandoc.Error (PandocError (PandocParseError)) import Text.Pandoc.Options (ReaderOptions) import Text.Pandoc.Shared (stringify)-+import Text.Pandoc.Sources (ToSources(..), sourcesToText) import qualified Text.Jira.Markup as Jira -- | Read Jira wiki markup.-readJira :: PandocMonad m+readJira :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc-readJira _opts s = case parse s of- Right d -> return $ jiraToPandoc d- Left e -> throwError . PandocParseError $- "Jira parse error" `append` pack (show e)+readJira _opts inp = do+ let sources = toSources inp+ case parse (sourcesToText sources) of+ Right d -> return $ jiraToPandoc d+ Left e -> throwError . PandocParseError $+ "Jira parse error" `append` pack (show e) jiraToPandoc :: Jira.Doc -> Pandoc jiraToPandoc (Jira.Doc blks) = doc $ foldMap jiraToPandocBlocks blks@@ -170,6 +172,8 @@ Jira.Email -> link ("mailto:" <> url') "" alias' Jira.Attachment -> linkWith ("", ["attachment"], []) url' "" alias' Jira.User -> linkWith ("", ["user-account"], []) url' "" alias'+ Jira.SmartCard -> linkWith ("", ["smart-card"], []) url' "" alias'+ Jira.SmartLink -> linkWith ("", ["smart-link"], []) url' "" alias' -- | Get unicode representation of a Jira icon. iconUnicode :: Jira.Icon -> Text
@@ -32,8 +32,9 @@ import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T+import Skylighting (defaultSyntaxMap) import System.FilePath (addExtension, replaceExtension, takeExtension)-import Text.Pandoc.BCP47 (renderLang)+import Text.Collate.Lang (renderLang) import Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocPure (PandocPure) import Text.Pandoc.Class.PandocMonad (PandocMonad (..), getResourcePath,@@ -76,16 +77,17 @@ -- import Debug.Trace (traceShowId) -- | Parse LaTeX from string and return 'Pandoc' document.-readLaTeX :: PandocMonad m+readLaTeX :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ String to parse (assumes @'\n'@ line endings)+ -> a -- ^ Input to parse -> m Pandoc readLaTeX opts ltx = do+ let sources = toSources ltx parsed <- runParserT parseLaTeX def{ sOptions = opts } "source"- (tokenize "source" (crFilter ltx))+ (tokenizeSources sources) case parsed of Right result -> return result- Left e -> throwError $ PandocParsecError ltx e+ Left e -> throwError $ PandocParsecError sources e parseLaTeX :: PandocMonad m => LP m Pandoc parseLaTeX = do@@ -131,11 +133,11 @@ rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)- => ParserT Text s m Text+ => ParserT Sources s m Text rawLaTeXBlock = do lookAhead (try (char '\\' >> letter)) inp <- getInput- let toks = tokenize "source" inp+ let toks = tokenizeSources inp snd <$> (rawLaTeXParser toks False (macroDef (const mempty)) blocks <|> rawLaTeXParser toks True (do choice (map controlSeq@@ -162,11 +164,11 @@ (txt <> untokenize rawargs) rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)- => ParserT Text s m Text+ => ParserT Sources s m Text rawLaTeXInline = do lookAhead (try (char '\\' >> letter)) inp <- getInput- let toks = tokenize "source" inp+ let toks = tokenizeSources inp raw <- snd <$> ( rawLaTeXParser toks True (mempty <$ (controlSeq "input" >> skipMany rawopt >> braced))@@ -177,11 +179,11 @@ finalbraces <- mconcat <$> many (try (string "{}")) -- see #5439 return $ raw <> T.pack finalbraces -inlineCommand :: PandocMonad m => ParserT Text ParserState m Inlines+inlineCommand :: PandocMonad m => ParserT Sources ParserState m Inlines inlineCommand = do lookAhead (try (char '\\' >> letter)) inp <- getInput- let toks = tokenize "source" inp+ let toks = tokenizeSources inp fst <$> rawLaTeXParser toks True (inlineEnvironment <|> inlineCommand') inlines @@ -230,16 +232,6 @@ _ -> return src return $ imageWith attr (T.pack src') "" alt -doxspace :: PandocMonad m => LP m Inlines-doxspace =- (space <$ lookAhead (satisfyTok startsWithLetter)) <|> return mempty- where startsWithLetter (Tok _ Word t) =- case T.uncons t of- Just (c, _) | isLetter c -> True- _ -> False- startsWithLetter _ = False-- removeDoubleQuotes :: Text -> Text removeDoubleQuotes t = Data.Maybe.fromMaybe t $ T.stripPrefix "\"" t >>= T.stripSuffix "\""@@ -415,8 +407,6 @@ -- LaTeX colors , ("textcolor", coloredInline "color") , ("colorbox", coloredInline "background-color")- -- xspace- , ("xspace", doxspace) -- etoolbox , ("ifstrequal", ifstrequal) , ("newtoggle", braced >>= newToggle)@@ -640,7 +630,7 @@ parsed <- runParserT (mconcat <$> many inline) st "bracketed option" toks case parsed of Right result -> return result- Left e -> throwError $ PandocParsecError (untokenize toks) e+ Left e -> throwError $ PandocParsecError (toSources toks) e -- block elements: @@ -1170,7 +1160,8 @@ let (ident,classes,kvs) = parseListingsOptions options let classes' = (case listingsLanguage options of- Nothing -> (take 1 (languagesByExtension (T.pack $ takeExtension $ T.unpack f)) <>)+ Nothing -> (take 1 (languagesByExtension defaultSyntaxMap+ (T.pack $ takeExtension $ T.unpack f)) <>) Just _ -> id) classes let firstline = fromMaybe 1 $ lookup "firstline" options >>= safeRead let lastline = fromMaybe (length codeLines) $
@@ -120,7 +120,7 @@ runParserT (mconcat <$> many inline) st "bracketed option" toks case parsed of Right result -> return result- Left e -> throwError $ PandocParsecError (untokenize toks) e+ Left e -> throwError $ PandocParsecError (toSources toks) e
@@ -23,7 +23,7 @@ import Data.Text (Text) import qualified Data.Text as T import Text.Pandoc.Shared (extractSpaces)-import Text.Pandoc.BCP47 (Lang(..), renderLang)+import Text.Collate.Lang (Lang(..), renderLang) import Text.Pandoc.Class (PandocMonad(..), setTranslations) import Text.Pandoc.Readers.LaTeX.Parsing import Text.Pandoc.Parsing (updateState, option, getState, QuoteContext(..),@@ -99,133 +99,136 @@ polyglossiaLangToBCP47 :: M.Map T.Text (T.Text -> Lang) polyglossiaLangToBCP47 = M.fromList [ ("arabic", \o -> case T.filter (/=' ') o of- "locale=algeria" -> Lang "ar" "" "DZ" []- "locale=mashriq" -> Lang "ar" "" "SY" []- "locale=libya" -> Lang "ar" "" "LY" []- "locale=morocco" -> Lang "ar" "" "MA" []- "locale=mauritania" -> Lang "ar" "" "MR" []- "locale=tunisia" -> Lang "ar" "" "TN" []- _ -> Lang "ar" "" "" [])+ "locale=algeria" -> Lang "ar" Nothing (Just "DZ") [] [] []+ "locale=mashriq" -> Lang "ar" Nothing (Just "SY") [] [] []+ "locale=libya" -> Lang "ar" Nothing (Just "LY") [] [] []+ "locale=morocco" -> Lang "ar" Nothing (Just "MA") [] [] []+ "locale=mauritania" -> Lang "ar" Nothing (Just "MR") [] [] []+ "locale=tunisia" -> Lang "ar" Nothing (Just "TN") [] [] []+ _ -> Lang "ar" Nothing (Just "") [] [] []) , ("german", \o -> case T.filter (/=' ') o of- "spelling=old" -> Lang "de" "" "DE" ["1901"]+ "spelling=old" -> Lang "de" Nothing (Just "DE") ["1901"] [] [] "variant=austrian,spelling=old"- -> Lang "de" "" "AT" ["1901"]- "variant=austrian" -> Lang "de" "" "AT" []+ -> Lang "de" Nothing (Just "AT") ["1901"] [] []+ "variant=austrian" -> Lang "de" Nothing (Just "AT") [] [] [] "variant=swiss,spelling=old"- -> Lang "de" "" "CH" ["1901"]- "variant=swiss" -> Lang "de" "" "CH" []- _ -> Lang "de" "" "" [])- , ("lsorbian", \_ -> Lang "dsb" "" "" [])+ -> Lang "de" Nothing (Just "CH") ["1901"] [] []+ "variant=swiss" -> Lang "de" Nothing (Just "CH") [] [] []+ _ -> Lang "de" Nothing Nothing [] [] [])+ , ("lsorbian", \_ -> Lang "dsb" Nothing Nothing [] [] []) , ("greek", \o -> case T.filter (/=' ') o of- "variant=poly" -> Lang "el" "" "polyton" []- "variant=ancient" -> Lang "grc" "" "" []- _ -> Lang "el" "" "" [])+ "variant=poly" -> Lang "el" Nothing (Just "polyton") [] [] []+ "variant=ancient" -> Lang "grc" Nothing Nothing [] [] []+ _ -> Lang "el" Nothing Nothing [] [] []) , ("english", \o -> case T.filter (/=' ') o of- "variant=australian" -> Lang "en" "" "AU" []- "variant=canadian" -> Lang "en" "" "CA" []- "variant=british" -> Lang "en" "" "GB" []- "variant=newzealand" -> Lang "en" "" "NZ" []- "variant=american" -> Lang "en" "" "US" []- _ -> Lang "en" "" "" [])- , ("usorbian", \_ -> Lang "hsb" "" "" [])+ "variant=australian" -> Lang "en" Nothing (Just "AU") [] [] []+ "variant=canadian" -> Lang "en" Nothing (Just "CA") [] [] []+ "variant=british" -> Lang "en" Nothing (Just "GB") [] [] []+ "variant=newzealand" -> Lang "en" Nothing (Just "NZ") [] [] []+ "variant=american" -> Lang "en" Nothing (Just "US") [] [] []+ _ -> Lang "en" Nothing (Just "") [] [] [])+ , ("usorbian", \_ -> Lang "hsb" Nothing Nothing [] [] []) , ("latin", \o -> case T.filter (/=' ') o of- "variant=classic" -> Lang "la" "" "" ["x-classic"]- _ -> Lang "la" "" "" [])- , ("slovenian", \_ -> Lang "sl" "" "" [])- , ("serbianc", \_ -> Lang "sr" "cyrl" "" [])- , ("pinyin", \_ -> Lang "zh" "Latn" "" ["pinyin"])- , ("afrikaans", \_ -> Lang "af" "" "" [])- , ("amharic", \_ -> Lang "am" "" "" [])- , ("assamese", \_ -> Lang "as" "" "" [])- , ("asturian", \_ -> Lang "ast" "" "" [])- , ("bulgarian", \_ -> Lang "bg" "" "" [])- , ("bengali", \_ -> Lang "bn" "" "" [])- , ("tibetan", \_ -> Lang "bo" "" "" [])- , ("breton", \_ -> Lang "br" "" "" [])- , ("catalan", \_ -> Lang "ca" "" "" [])- , ("welsh", \_ -> Lang "cy" "" "" [])- , ("czech", \_ -> Lang "cs" "" "" [])- , ("coptic", \_ -> Lang "cop" "" "" [])- , ("danish", \_ -> Lang "da" "" "" [])- , ("divehi", \_ -> Lang "dv" "" "" [])- , ("esperanto", \_ -> Lang "eo" "" "" [])- , ("spanish", \_ -> Lang "es" "" "" [])- , ("estonian", \_ -> Lang "et" "" "" [])- , ("basque", \_ -> Lang "eu" "" "" [])- , ("farsi", \_ -> Lang "fa" "" "" [])- , ("finnish", \_ -> Lang "fi" "" "" [])- , ("french", \_ -> Lang "fr" "" "" [])- , ("friulan", \_ -> Lang "fur" "" "" [])- , ("irish", \_ -> Lang "ga" "" "" [])- , ("scottish", \_ -> Lang "gd" "" "" [])- , ("ethiopic", \_ -> Lang "gez" "" "" [])- , ("galician", \_ -> Lang "gl" "" "" [])- , ("hebrew", \_ -> Lang "he" "" "" [])- , ("hindi", \_ -> Lang "hi" "" "" [])- , ("croatian", \_ -> Lang "hr" "" "" [])- , ("magyar", \_ -> Lang "hu" "" "" [])- , ("armenian", \_ -> Lang "hy" "" "" [])- , ("interlingua", \_ -> Lang "ia" "" "" [])- , ("indonesian", \_ -> Lang "id" "" "" [])- , ("icelandic", \_ -> Lang "is" "" "" [])- , ("italian", \_ -> Lang "it" "" "" [])- , ("japanese", \_ -> Lang "jp" "" "" [])- , ("khmer", \_ -> Lang "km" "" "" [])- , ("kurmanji", \_ -> Lang "kmr" "" "" [])- , ("kannada", \_ -> Lang "kn" "" "" [])- , ("korean", \_ -> Lang "ko" "" "" [])- , ("lao", \_ -> Lang "lo" "" "" [])- , ("lithuanian", \_ -> Lang "lt" "" "" [])- , ("latvian", \_ -> Lang "lv" "" "" [])- , ("malayalam", \_ -> Lang "ml" "" "" [])- , ("mongolian", \_ -> Lang "mn" "" "" [])- , ("marathi", \_ -> Lang "mr" "" "" [])- , ("dutch", \_ -> Lang "nl" "" "" [])- , ("nynorsk", \_ -> Lang "nn" "" "" [])- , ("norsk", \_ -> Lang "no" "" "" [])- , ("nko", \_ -> Lang "nqo" "" "" [])- , ("occitan", \_ -> Lang "oc" "" "" [])- , ("panjabi", \_ -> Lang "pa" "" "" [])- , ("polish", \_ -> Lang "pl" "" "" [])- , ("piedmontese", \_ -> Lang "pms" "" "" [])- , ("portuguese", \_ -> Lang "pt" "" "" [])- , ("romansh", \_ -> Lang "rm" "" "" [])- , ("romanian", \_ -> Lang "ro" "" "" [])- , ("russian", \_ -> Lang "ru" "" "" [])- , ("sanskrit", \_ -> Lang "sa" "" "" [])- , ("samin", \_ -> Lang "se" "" "" [])- , ("slovak", \_ -> Lang "sk" "" "" [])- , ("albanian", \_ -> Lang "sq" "" "" [])- , ("serbian", \_ -> Lang "sr" "" "" [])- , ("swedish", \_ -> Lang "sv" "" "" [])- , ("syriac", \_ -> Lang "syr" "" "" [])- , ("tamil", \_ -> Lang "ta" "" "" [])- , ("telugu", \_ -> Lang "te" "" "" [])- , ("thai", \_ -> Lang "th" "" "" [])- , ("turkmen", \_ -> Lang "tk" "" "" [])- , ("turkish", \_ -> Lang "tr" "" "" [])- , ("ukrainian", \_ -> Lang "uk" "" "" [])- , ("urdu", \_ -> Lang "ur" "" "" [])- , ("vietnamese", \_ -> Lang "vi" "" "" [])+ "variant=classic" -> Lang "la" Nothing Nothing ["x-classic"] [] []+ _ -> Lang "la" Nothing Nothing [] [] [])+ , ("slovenian", \_ -> Lang "sl" Nothing Nothing [] [] [])+ , ("serbianc", \_ -> Lang "sr" (Just "Cyrl") Nothing [] [] [])+ , ("pinyin", \_ -> Lang "zh" (Just "Latn") Nothing ["pinyin"] [] [])+ , ("afrikaans", \_ -> simpleLang "af")+ , ("amharic", \_ -> simpleLang "am")+ , ("assamese", \_ -> simpleLang "as")+ , ("asturian", \_ -> simpleLang "ast")+ , ("bulgarian", \_ -> simpleLang "bg")+ , ("bengali", \_ -> simpleLang "bn")+ , ("tibetan", \_ -> simpleLang "bo")+ , ("breton", \_ -> simpleLang "br")+ , ("catalan", \_ -> simpleLang "ca")+ , ("welsh", \_ -> simpleLang "cy")+ , ("czech", \_ -> simpleLang "cs")+ , ("coptic", \_ -> simpleLang "cop")+ , ("danish", \_ -> simpleLang "da")+ , ("divehi", \_ -> simpleLang "dv")+ , ("esperanto", \_ -> simpleLang "eo")+ , ("spanish", \_ -> simpleLang "es")+ , ("estonian", \_ -> simpleLang "et")+ , ("basque", \_ -> simpleLang "eu")+ , ("farsi", \_ -> simpleLang "fa")+ , ("finnish", \_ -> simpleLang "fi")+ , ("french", \_ -> simpleLang "fr")+ , ("friulan", \_ -> simpleLang "fur")+ , ("irish", \_ -> simpleLang "ga")+ , ("scottish", \_ -> simpleLang "gd")+ , ("ethiopic", \_ -> simpleLang "gez")+ , ("galician", \_ -> simpleLang "gl")+ , ("hebrew", \_ -> simpleLang "he")+ , ("hindi", \_ -> simpleLang "hi")+ , ("croatian", \_ -> simpleLang "hr")+ , ("magyar", \_ -> simpleLang "hu")+ , ("armenian", \_ -> simpleLang "hy")+ , ("interlingua", \_ -> simpleLang "ia")+ , ("indonesian", \_ -> simpleLang "id")+ , ("icelandic", \_ -> simpleLang "is")+ , ("italian", \_ -> simpleLang "it")+ , ("japanese", \_ -> simpleLang "jp")+ , ("khmer", \_ -> simpleLang "km")+ , ("kurmanji", \_ -> simpleLang "kmr")+ , ("kannada", \_ -> simpleLang "kn")+ , ("korean", \_ -> simpleLang "ko")+ , ("lao", \_ -> simpleLang "lo")+ , ("lithuanian", \_ -> simpleLang "lt")+ , ("latvian", \_ -> simpleLang "lv")+ , ("malayalam", \_ -> simpleLang "ml")+ , ("mongolian", \_ -> simpleLang "mn")+ , ("marathi", \_ -> simpleLang "mr")+ , ("dutch", \_ -> simpleLang "nl")+ , ("nynorsk", \_ -> simpleLang "nn")+ , ("norsk", \_ -> simpleLang "no")+ , ("nko", \_ -> simpleLang "nqo")+ , ("occitan", \_ -> simpleLang "oc")+ , ("panjabi", \_ -> simpleLang "pa")+ , ("polish", \_ -> simpleLang "pl")+ , ("piedmontese", \_ -> simpleLang "pms")+ , ("portuguese", \_ -> simpleLang "pt")+ , ("romansh", \_ -> simpleLang "rm")+ , ("romanian", \_ -> simpleLang "ro")+ , ("russian", \_ -> simpleLang "ru")+ , ("sanskrit", \_ -> simpleLang "sa")+ , ("samin", \_ -> simpleLang "se")+ , ("slovak", \_ -> simpleLang "sk")+ , ("albanian", \_ -> simpleLang "sq")+ , ("serbian", \_ -> simpleLang "sr")+ , ("swedish", \_ -> simpleLang "sv")+ , ("syriac", \_ -> simpleLang "syr")+ , ("tamil", \_ -> simpleLang "ta")+ , ("telugu", \_ -> simpleLang "te")+ , ("thai", \_ -> simpleLang "th")+ , ("turkmen", \_ -> simpleLang "tk")+ , ("turkish", \_ -> simpleLang "tr")+ , ("ukrainian", \_ -> simpleLang "uk")+ , ("urdu", \_ -> simpleLang "ur")+ , ("vietnamese", \_ -> simpleLang "vi") ] +simpleLang :: Text -> Lang+simpleLang l = Lang l Nothing Nothing [] [] []+ babelLangToBCP47 :: T.Text -> Maybe Lang babelLangToBCP47 s = case s of- "austrian" -> Just $ Lang "de" "" "AT" ["1901"]- "naustrian" -> Just $ Lang "de" "" "AT" []- "swissgerman" -> Just $ Lang "de" "" "CH" ["1901"]- "nswissgerman" -> Just $ Lang "de" "" "CH" []- "german" -> Just $ Lang "de" "" "DE" ["1901"]- "ngerman" -> Just $ Lang "de" "" "DE" []- "lowersorbian" -> Just $ Lang "dsb" "" "" []- "uppersorbian" -> Just $ Lang "hsb" "" "" []- "polutonikogreek" -> Just $ Lang "el" "" "" ["polyton"]- "slovene" -> Just $ Lang "sl" "" "" []- "australian" -> Just $ Lang "en" "" "AU" []- "canadian" -> Just $ Lang "en" "" "CA" []- "british" -> Just $ Lang "en" "" "GB" []- "newzealand" -> Just $ Lang "en" "" "NZ" []- "american" -> Just $ Lang "en" "" "US" []- "classiclatin" -> Just $ Lang "la" "" "" ["x-classic"]+ "austrian" -> Just $ Lang "de" Nothing (Just "AT") ["1901"] [] []+ "naustrian" -> Just $ Lang "de" Nothing (Just "AT") [] [] []+ "swissgerman" -> Just $ Lang "de" Nothing (Just "CH") ["1901"] [] []+ "nswissgerman" -> Just $ Lang "de" Nothing (Just "CH") [] [] []+ "german" -> Just $ Lang "de" Nothing (Just "DE") ["1901"] [] []+ "ngerman" -> Just $ Lang "de" Nothing (Just "DE") [] [] []+ "lowersorbian" -> Just $ Lang "dsb" Nothing Nothing [] [] []+ "uppersorbian" -> Just $ Lang "hsb" Nothing Nothing [] [] []+ "polutonikogreek" -> Just $ Lang "el" Nothing Nothing ["polyton"] [] []+ "slovene" -> Just $ simpleLang "sl"+ "australian" -> Just $ Lang "en" Nothing (Just "AU") [] [] []+ "canadian" -> Just $ Lang "en" Nothing (Just "CA") [] [] []+ "british" -> Just $ Lang "en" Nothing (Just "GB") [] [] []+ "newzealand" -> Just $ Lang "en" Nothing (Just "NZ") [] [] []+ "american" -> Just $ Lang "en" Nothing (Just "US") [] [] []+ "classiclatin" -> Just $ Lang "la" Nothing Nothing ["x-classic"] [] [] _ -> ($ "") <$> M.lookup s polyglossiaLangToBCP47
@@ -14,6 +14,7 @@ import Control.Applicative ((<|>), optional) import qualified Data.Map as M import Data.Text (Text)+import qualified Data.Text as T macroDef :: (PandocMonad m, Monoid a) => (Text -> a) -> LP m a macroDef constructor = do@@ -22,9 +23,11 @@ guardDisabled Ext_latex_macros) <|> return mempty where commandDef = do- (name, macro') <- newcommand <|> letmacro <|> defmacro+ nameMacroPairs <- newcommand <|> letmacro <|> defmacro <|> newif guardDisabled Ext_latex_macros <|>- updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })+ mapM_ (\(name, macro') ->+ updateState (\s -> s{ sMacros = M.insert name macro'+ (sMacros s) })) nameMacroPairs environmentDef = do mbenv <- newenvironment case mbenv of@@ -40,7 +43,7 @@ -- @\newcommand{\envname}[n-args][default]{begin}@ -- @\newcommand{\endenvname}@ -letmacro :: PandocMonad m => LP m (Text, Macro)+letmacro :: PandocMonad m => LP m [(Text, Macro)] letmacro = do controlSeq "let" (name, contents) <- withVerbatimMode $ do@@ -53,19 +56,48 @@ contents <- bracedOrToken return (name, contents) contents' <- doMacros' 0 contents- return (name, Macro ExpandWhenDefined [] Nothing contents')+ return [(name, Macro ExpandWhenDefined [] Nothing contents')] -defmacro :: PandocMonad m => LP m (Text, Macro)-defmacro = try $+defmacro :: PandocMonad m => LP m [(Text, Macro)]+defmacro = do -- we use withVerbatimMode, because macros are to be expanded -- at point of use, not point of definition+ controlSeq "def" withVerbatimMode $ do- controlSeq "def" Tok _ (CtrlSeq name) _ <- anyControlSeq argspecs <- many (argspecArg <|> argspecPattern) contents <- bracedOrToken- return (name, Macro ExpandWhenUsed argspecs Nothing contents)+ return [(name, Macro ExpandWhenUsed argspecs Nothing contents)] +-- \newif\iffoo' defines:+-- \iffoo to be \iffalse+-- \footrue to be a command that defines \iffoo to be \iftrue+-- \foofalse to be a command that defines \iffoo to be \iffalse+newif :: PandocMonad m => LP m [(Text, Macro)]+newif = do+ controlSeq "newif"+ withVerbatimMode $ do+ Tok pos (CtrlSeq name) _ <- anyControlSeq+ -- \def\iffoo\iffalse+ -- \def\footrue{\def\iffoo\iftrue}+ -- \def\foofalse{\def\iffoo\iffalse}+ let base = T.drop 2 name+ return [ (name, Macro ExpandWhenUsed [] Nothing+ [Tok pos (CtrlSeq "iffalse") "\\iffalse"])+ , (base <> "true",+ Macro ExpandWhenUsed [] Nothing+ [ Tok pos (CtrlSeq "def") "\\def"+ , Tok pos (CtrlSeq name) ("\\" <> name)+ , Tok pos (CtrlSeq "iftrue") "\\iftrue"+ ])+ , (base <> "false",+ Macro ExpandWhenUsed [] Nothing+ [ Tok pos (CtrlSeq "def") "\\def"+ , Tok pos (CtrlSeq name) ("\\" <> name)+ , Tok pos (CtrlSeq "iffalse") "\\iffalse"+ ])+ ]+ argspecArg :: PandocMonad m => LP m ArgSpec argspecArg = do Tok _ (Arg i) _ <- satisfyTok isArgTok@@ -77,10 +109,9 @@ (toktype' == Symbol || toktype' == Word) && (txt /= "{" && txt /= "\\" && txt /= "}"))) -newcommand :: PandocMonad m => LP m (Text, Macro)+newcommand :: PandocMonad m => LP m [(Text, Macro)] newcommand = do- pos <- getPosition- Tok _ (CtrlSeq mtype) _ <- controlSeq "newcommand" <|>+ Tok pos (CtrlSeq mtype) _ <- controlSeq "newcommand" <|> controlSeq "renewcommand" <|> controlSeq "providecommand" <|> controlSeq "DeclareMathOperator" <|>@@ -112,9 +143,9 @@ Just macro | mtype == "newcommand" -> do report $ MacroAlreadyDefined txt pos- return (name, macro)- | mtype == "providecommand" -> return (name, macro)- _ -> return (name, Macro ExpandWhenUsed argspecs optarg contents)+ return [(name, macro)]+ | mtype == "providecommand" -> return [(name, macro)]+ _ -> return [(name, Macro ExpandWhenUsed argspecs optarg contents)] newenvironment :: PandocMonad m => LP m (Maybe (Text, Macro, Macro)) newenvironment = do
@@ -27,6 +27,7 @@ , rawLaTeXParser , applyMacros , tokenize+ , tokenizeSources , untokenize , untoken , totoks@@ -112,7 +113,6 @@ ArgSpec (..), Tok (..), TokType (..)) import Text.Pandoc.Shared import Text.Parsec.Pos--- import Debug.Trace newtype DottedNum = DottedNum [Int] deriving (Show, Eq)@@ -248,7 +248,7 @@ rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s) => [Tok] -> Bool -> LP m a -> LP m a- -> ParserT Text s m (a, Text)+ -> ParserT Sources s m (a, Text) rawLaTeXParser toks retokenize parser valParser = do pstate <- getState let lstate = def{ sOptions = extractReaderOptions pstate }@@ -268,7 +268,7 @@ Left _ -> mzero Right ((val, raw), st) -> do updateState (updateMacros (sMacros st <>))- _ <- takeP (T.length (untokenize toks'))+ void $ count (T.length (untokenize toks')) anyChar let result = untokenize raw -- ensure we end with space if input did, see #4442 let result' =@@ -281,7 +281,7 @@ return (val, result') applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)- => Text -> ParserT Text s m Text+ => Text -> ParserT Sources s m Text applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|> do let retokenize = untokenize <$> many (satisfyTok (const True)) pstate <- getState@@ -301,6 +301,11 @@ > let t = T.pack s in untokenize (tokenize "random" t) == t -} +tokenizeSources :: Sources -> [Tok]+tokenizeSources = concatMap tokenizeSource . unSources+ where+ tokenizeSource (pos, t) = totoks pos t+ tokenize :: SourceName -> Text -> [Tok] tokenize sourcename = totoks (initialPos sourcename) @@ -458,7 +463,7 @@ doMacros :: PandocMonad m => LP m () doMacros = do st <- getState- unless (sVerbatimMode st || M.null (sMacros st)) $ do+ unless (sVerbatimMode st) $ getInput >>= doMacros' 1 >>= setInput doMacros' :: PandocMonad m => Int -> [Tok] -> LP m [Tok]@@ -520,7 +525,7 @@ $ throwError $ PandocMacroLoop name macros <- sMacros <$> getState case M.lookup name macros of- Nothing -> mzero+ Nothing -> trySpecialMacro name ts Just (Macro expansionPoint argspecs optarg newtoks) -> do let getargs' = do args <-@@ -548,6 +553,41 @@ ExpandWhenUsed -> doMacros' (n' + 1) result ExpandWhenDefined -> return result +-- | Certain macros do low-level tex manipulations that can't+-- be represented in our Macro type, so we handle them here.+trySpecialMacro :: PandocMonad m => Text -> [Tok] -> LP m [Tok]+trySpecialMacro "xspace" ts = do+ ts' <- doMacros' 1 ts+ case ts' of+ 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 _ _ = mzero++handleIf :: PandocMonad m => Bool -> [Tok] -> LP m [Tok]+handleIf b ts = do+ res' <- lift $ runParserT (ifParser b) defaultLaTeXState "tokens" ts+ case res' of+ Left _ -> Prelude.fail "Could not parse conditional"+ Right ts' -> return ts'++ifParser :: PandocMonad m => Bool -> LP m [Tok]+ifParser b = do+ ifToks <- many (notFollowedBy (controlSeq "else" <|> controlSeq "fi")+ *> anyTok)+ elseToks <- (controlSeq "else" >> manyTill anyTok (controlSeq "fi"))+ <|> ([] <$ controlSeq "fi")+ rest <- getInput+ return $ (if b then ifToks else elseToks) ++ rest++startsWithAlphaNum :: Text -> Bool+startsWithAlphaNum t =+ case T.uncons t of+ Just (c, _) | isAlphaNum c -> True+ _ -> False+ setpos :: SourcePos -> Tok -> Tok setpos spos (Tok _ tt txt) = Tok spos tt txt @@ -783,7 +823,8 @@ keyval :: PandocMonad m => LP m (Text, Text) keyval = try $ do- Tok _ Word key <- satisfyTok isWordTok+ key <- untokenize <$> many1 (notFollowedBy (symbol '=') >>+ (symbol '-' <|> symbol '_' <|> satisfyTok isWordTok)) sp val <- option mempty $ do symbol '='
@@ -1,3 +1,4 @@+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} module Text.Pandoc.Readers.LaTeX.SIunitx ( siunitxCommands )@@ -9,27 +10,32 @@ import Text.Pandoc.Parsing hiding (blankline, mathDisplay, mathInline, optional, space, spaces, withRaw, (<|>)) import Control.Applicative ((<|>))+import Control.Monad (void) import qualified Data.Map as M import Data.Char (isDigit) import Data.Text (Text) import qualified Data.Text as T import Data.List (intersperse)-+import qualified Data.Sequence as Seq+import Text.Pandoc.Walk (walk) siunitxCommands :: PandocMonad m => LP m Inlines -> M.Map Text (LP m Inlines) siunitxCommands tok = M.fromList- [ ("si", skipopts *> dosi tok)+ [ ("si", dosi tok) , ("SI", doSI tok) , ("SIrange", doSIrange True tok) , ("numrange", doSIrange False tok) , ("numlist", doSInumlist)+ , ("SIlist", doSIlist tok) , ("num", doSInum) , ("ang", doSIang) ] dosi :: PandocMonad m => LP m Inlines -> LP m Inlines-dosi tok = grouped (siUnit tok) <|> siUnit tok+dosi tok = do+ options <- option [] keyvals+ grouped (siUnit options tok) <|> siUnit options tok -- converts e.g. \SI{1}[\$]{} to "$ 1" or \SI{1}{\euro} to "1 €" doSI :: PandocMonad m => LP m Inlines -> LP m Inlines@@ -64,23 +70,50 @@ mconcat (intersperse (str "," <> space) (init xs)) <> text ", & " <> last xs +doSIlist :: PandocMonad m => LP m Inlines -> LP m Inlines+doSIlist tok = do+ options <- option [] keyvals+ nums <- map tonum . T.splitOn ";" . untokenize <$> braced+ unit <- grouped (siUnit options tok) <|> siUnit options tok+ let xs = map (<> (str "\xa0" <> unit)) nums+ case xs of+ [] -> return mempty+ [x] -> return x+ _ -> return $+ mconcat (intersperse (str "," <> space) (init xs)) <>+ text ", & " <> last xs+ parseNum :: Parser Text () Inlines parseNum = (mconcat <$> many parseNumPart) <* eof +minus :: Text+minus = "\x2212"++hyphenToMinus :: Inline -> Inline+hyphenToMinus (Str t) = Str (T.replace "-" minus t)+hyphenToMinus x = x+ parseNumPart :: Parser Text () Inlines parseNumPart = parseDecimalNum <|> parseComma <|> parsePlusMinus <|>+ parsePM <|> parseI <|> parseExp <|> parseX <|> parseSpace where- parseDecimalNum = do- pref <- option mempty $ (mempty <$ char '+') <|> ("\x2212" <$ char '-')- basenum <- (pref <>) . T.pack- <$> many1 (satisfy (\c -> isDigit c || c == '.'))+ parseDecimalNum, parsePlusMinus, parsePM,+ parseComma, parseI, parseX,+ parseExp, parseSpace :: Parser Text () Inlines+ parseDecimalNum = try $ do+ pref <- option mempty $ (mempty <$ char '+') <|> (minus <$ char '-')+ basenum' <- many1 (satisfy (\c -> isDigit c || c == '.'))+ let basenum = pref <> T.pack+ (case basenum' of+ '.':_ -> '0':basenum'+ _ -> basenum') uncertainty <- option mempty $ T.pack <$> parseParens if T.null uncertainty then return $ str basenum@@ -98,6 +131,7 @@ | otherwise -> "." <> t parseComma = str "." <$ char ',' parsePlusMinus = str "\xa0\xb1\xa0" <$ try (string "+-")+ parsePM = str "\xa0\xb1\xa0" <$ try (string "\\pm") parseParens = char '(' *> many1 (satisfy (\c -> isDigit c || c == '.')) <* char ')' parseI = str "i" <$ char 'i'@@ -110,11 +144,14 @@ doSIang = do skipopts ps <- T.splitOn ";" . untokenize <$> braced+ let dropPlus t = case T.uncons t of+ Just ('+',t') -> t'+ _ -> t case ps ++ repeat "" of (d:m:s:_) -> return $- (if T.null d then mempty else str d <> str "\xb0") <>- (if T.null m then mempty else str m <> str "\x2032") <>- (if T.null s then mempty else str s <> str "\x2033")+ (if T.null d then mempty else str (dropPlus d) <> str "\xb0") <>+ (if T.null m then mempty else str (dropPlus m) <> str "\x2032") <>+ (if T.null s then mempty else str (dropPlus s) <> str "\x2033") _ -> return mempty -- converts e.g. \SIrange{100}{200}{\ms} to "100 ms--200 ms"@@ -143,41 +180,100 @@ emptyOr160 :: Inlines -> Inlines emptyOr160 x = if x == mempty then x else str "\160" -siUnit :: PandocMonad m => LP m Inlines -> LP m Inlines-siUnit tok = try (do- Tok _ (CtrlSeq name) _ <- anyControlSeq- case name of- "square" -> do- unit <- siUnit tok- return $ unit <> superscript "2"- "cubic" -> do- unit <- siUnit tok- return $ unit <> superscript "3"- "raisetothe" -> do- n <- tok- unit <- siUnit tok- return $ unit <> superscript n- _ ->- case M.lookup name siUnitMap of- Just il ->- option il $- choice- [ (il <> superscript "2") <$ controlSeq "squared"- , (il <> superscript "3") <$ controlSeq "cubed"- , (\n -> il <> superscript n) <$> (controlSeq "tothe" *> tok)- ]- Nothing -> fail "not an siunit unit command")- <|> (lookAhead anyControlSeq >> tok)- <|> (do Tok _ Word t <- satisfyTok isWordTok- return $ str t)- <|> (symbol '^' *> (superscript <$> tok))- <|> (symbol '_' *> (subscript <$> tok))- <|> ("\xa0" <$ symbol '.')- <|> ("\xa0" <$ symbol '~')- <|> tok- <|> (do Tok _ _ t <- anyTok- return (str t))+siUnit :: forall m. PandocMonad m => [(Text,Text)] -> LP m Inlines -> LP m Inlines+siUnit options tok = mconcat . intersperse (str "\xa0") <$> many1 siUnitPart+ where+ siUnitPart :: LP m Inlines+ siUnitPart = try $ do+ skipMany (void (symbol '.') <|> void (symbol '~') <|> spaces1)+ x <- ((siPrefix <*> siBase)+ <|> (do u <- siBase <|> tok+ option u $ siSuffix <*> pure u))+ option x (siInfix x)+ siInfix :: Inlines -> LP m Inlines+ siInfix u1 = try $+ (do _ <- controlSeq "per"+ u2 <- siUnitPart+ let useSlash = lookup "per-mode" options == Just "symbol"+ if useSlash+ then return (u1 <> str "/" <> u2)+ else return (u1 <> str "\xa0" <> negateExponent u2))+ <|> (do _ <- symbol '/'+ u2 <- siUnitPart+ return (u1 <> str "/" <> u2))+ siPrefix :: LP m (Inlines -> Inlines)+ siPrefix =+ (do _ <- controlSeq "square"+ skipopts+ return (<> superscript "2"))+ <|> (do _ <- controlSeq "cubic"+ skipopts+ return (<> superscript "3"))+ <|> (do _ <- controlSeq "raisetothe"+ skipopts+ n <- walk hyphenToMinus <$> tok+ return (<> superscript n))+ siSuffix :: LP m (Inlines -> Inlines)+ siSuffix =+ (do _ <- controlSeq "squared"+ skipopts+ return (<> superscript "2"))+ <|> (do _ <- controlSeq "cubed"+ skipopts+ return (<> superscript "3"))+ <|> (do _ <- controlSeq "tothe"+ skipopts+ n <- walk hyphenToMinus <$> tok+ return (<> superscript n))+ <|> (symbol '^' *> (do n <- walk hyphenToMinus <$> tok+ return (<> superscript n)))+ <|> (symbol '_' *> (do n <- walk hyphenToMinus <$> tok+ return (<> subscript n)))+ negateExponent :: Inlines -> Inlines+ negateExponent ils =+ case Seq.viewr (unMany ils) of+ xs Seq.:> Superscript ss -> (Many xs) <>+ superscript (str minus <> fromList ss)+ _ -> ils <> superscript (str (minus <> "1"))+ siBase :: LP m Inlines+ siBase =+ ((try+ (do Tok _ (CtrlSeq name) _ <- anyControlSeq+ case M.lookup name siUnitModifierMap of+ Just il -> (il <>) <$> siBase+ Nothing ->+ case M.lookup name siUnitMap of+ Just il -> pure il+ Nothing -> fail "not a unit command"))+ <|> (do Tok _ Word t <- satisfyTok isWordTok+ return $ str t)+ ) +siUnitModifierMap :: M.Map Text Inlines+siUnitModifierMap = M.fromList+ [ ("atto", str "a")+ , ("centi", str "c")+ , ("deca", str "d")+ , ("deci", str "d")+ , ("deka", str "d")+ , ("exa", str "E")+ , ("femto", str "f")+ , ("giga", str "G")+ , ("hecto", str "h")+ , ("kilo", str "k")+ , ("mega", str "M")+ , ("micro", str "μ")+ , ("milli", str "m")+ , ("nano", str "n")+ , ("peta", str "P")+ , ("pico", str "p")+ , ("tera", str "T")+ , ("yocto", str "y")+ , ("yotta", str "Y")+ , ("zepto", str "z")+ , ("zetta", str "Z")+ ]+ siUnitMap :: M.Map Text Inlines siUnitMap = M.fromList [ ("fg", str "fg")@@ -276,7 +372,6 @@ , ("arcsecond", str "″") , ("astronomicalunit", str "ua") , ("atomicmassunit", str "u")- , ("atto", str "a") , ("bar", str "bar") , ("barn", str "b") , ("becquerel", str "Bq")@@ -284,51 +379,38 @@ , ("bohr", emph (str "a") <> subscript (str "0")) , ("candela", str "cd") , ("celsius", str "°C")- , ("centi", str "c") , ("clight", emph (str "c") <> subscript (str "0")) , ("coulomb", str "C") , ("dalton", str "Da") , ("day", str "d")- , ("deca", str "d")- , ("deci", str "d") , ("decibel", str "db") , ("degreeCelsius",str "°C") , ("degree", str "°")- , ("deka", str "d") , ("electronmass", emph (str "m") <> subscript (str "e")) , ("electronvolt", str "eV") , ("elementarycharge", emph (str "e"))- , ("exa", str "E") , ("farad", str "F")- , ("femto", str "f")- , ("giga", str "G") , ("gram", str "g") , ("gray", str "Gy") , ("hartree", emph (str "E") <> subscript (str "h")) , ("hectare", str "ha")- , ("hecto", str "h") , ("henry", str "H") , ("hertz", str "Hz") , ("hour", str "h") , ("joule", str "J") , ("katal", str "kat") , ("kelvin", str "K")- , ("kilo", str "k") , ("kilogram", str "kg") , ("knot", str "kn") , ("liter", str "L") , ("litre", str "l") , ("lumen", str "lm") , ("lux", str "lx")- , ("mega", str "M") , ("meter", str "m") , ("metre", str "m")- , ("micro", str "μ")- , ("milli", str "m") , ("minute", str "min") , ("mmHg", str "mmHg") , ("mole", str "mol")- , ("nano", str "n") , ("nauticalmile", str "M") , ("neper", str "Np") , ("newton", str "N")@@ -336,25 +418,17 @@ , ("Pa", str "Pa") , ("pascal", str "Pa") , ("percent", str "%")- , ("per", str "/")- , ("peta", str "P")- , ("pico", str "p") , ("planckbar", emph (str "\x210f")) , ("radian", str "rad") , ("second", str "s") , ("siemens", str "S") , ("sievert", str "Sv") , ("steradian", str "sr")- , ("tera", str "T") , ("tesla", str "T") , ("tonne", str "t") , ("volt", str "V") , ("watt", str "W") , ("weber", str "Wb")- , ("yocto", str "y")- , ("yotta", str "Y")- , ("zepto", str "z")- , ("zetta", str "Z") ]
@@ -1,3 +1,4 @@+{-# LANGUAGE FlexibleInstances #-} {- | Module : Text.Pandoc.Readers.LaTeX.Types Copyright : Copyright (C) 2017-2021 John MacFarlane@@ -18,7 +19,9 @@ ) where import Data.Text (Text)-import Text.Parsec.Pos (SourcePos)+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@@ -26,6 +29,16 @@ 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)
@@ -20,7 +20,7 @@ import Control.Monad.Trans (lift) import Control.Monad.Except (throwError) import Data.Maybe (catMaybes, isJust)-import Data.List (intersperse, intercalate)+import Data.List (intersperse) import qualified Data.Text as T import Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad(..), report)@@ -29,9 +29,8 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Walk (query)-import Text.Pandoc.Shared (crFilter, mapLeft)+import Text.Pandoc.Shared (mapLeft) import Text.Pandoc.Readers.Roff -- TODO explicit imports-import Text.Parsec hiding (tokenPrim) import qualified Text.Parsec as Parsec import Text.Parsec.Pos (updatePosString) import qualified Data.Foldable as Foldable@@ -50,23 +49,31 @@ -- | Read man (troff) from an input string and return a Pandoc document.-readMan :: PandocMonad m => ReaderOptions -> T.Text -> m Pandoc-readMan opts txt = do- tokenz <- lexRoff (initialPos "input") (crFilter txt)+readMan :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc+readMan opts s = do+ 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 return eitherdoc+ either (throwError . fixError) return eitherdoc + readWithMTokens :: PandocMonad m => ParserT [RoffToken] ManState m a -- ^ parser -> ManState -- ^ initial state -> [RoffToken] -- ^ input -> m (Either PandocError a) readWithMTokens parser state input =- let leftF = PandocParsecError . T.pack . intercalate "\n" $ show <$> input+ let leftF = PandocParsecError mempty in mapLeft leftF `liftM` runParserT parser state "source" input + parseMan :: PandocMonad m => ManParser m Pandoc parseMan = do bs <- many parseBlock <* eof@@ -89,7 +96,7 @@ parseTable :: PandocMonad m => ManParser m Blocks parseTable = do- modifyState $ \st -> st { tableCellsPlain = True }+ updateState $ \st -> st { tableCellsPlain = True } let isTbl Tbl{} = True isTbl _ = False Tbl _opts rows pos <- msatisfy isTbl@@ -135,7 +142,7 @@ case res' of Left _ -> Prelude.fail "Could not parse table cell" Right x -> do- modifyState $ \s -> s{ tableCellsPlain = False }+ updateState $ \s -> s{ tableCellsPlain = False } return x Right x -> return x @@ -222,7 +229,7 @@ setMeta "section" (linePartsToInlines y) [x] -> setMeta "title" (linePartsToInlines x) [] -> id- modifyState $ \st -> st{ metadata = adjustMeta $ metadata st }+ updateState $ \st -> st{ metadata = adjustMeta $ metadata st } return mempty linePartsToInlines :: [LinePart] -> Inlines
@@ -29,7 +29,7 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.ByteString.Lazy as BL-import System.FilePath (addExtension, takeExtension)+import System.FilePath (addExtension, takeExtension, isAbsolute, takeDirectory) import Text.HTML.TagSoup hiding (Row) import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B@@ -47,19 +47,20 @@ import Text.Pandoc.Shared import Text.Pandoc.XML (fromEntities) import Text.Pandoc.Readers.Metadata (yamlBsToMeta, yamlBsToRefs, yamlMetaBlock)+-- import Debug.Trace (traceShowId) -type MarkdownParser m = ParserT Text ParserState m+type MarkdownParser m = ParserT Sources ParserState m type F = Future ParserState -- | Read markdown from an input string and return a Pandoc document.-readMarkdown :: PandocMonad m+readMarkdown :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ String to parse (assuming @'\n'@ line endings)+ -> a -- ^ Input -> m Pandoc readMarkdown opts s = do parsed <- readWithM parseMarkdown def{ stateOptions = opts }- (crFilter s <> "\n\n")+ (ensureFinalNewlines 3 (toSources s)) case parsed of Right result -> return result Left e -> throwError e@@ -80,7 +81,7 @@ meta <- yamlBsToMeta (fmap B.toMetaValue <$> parseBlocks) bstr setPosition oldPos return $ runF meta defaultParserState- parsed <- readWithM parser def{ stateOptions = opts } ""+ parsed <- readWithM parser def{ stateOptions = opts } ("" :: Text) case parsed of Right result -> return result Left e -> throwError e@@ -96,14 +97,12 @@ -> m [MetaValue] yamlToRefs idpred opts mbfp bstr = do let parser = do- oldPos <- getPosition case mbfp of Nothing -> return () Just fp -> setPosition $ initialPos fp refs <- yamlBsToRefs (fmap B.toMetaValue <$> parseBlocks) idpred bstr- setPosition oldPos return $ runF refs defaultParserState- parsed <- readWithM parser def{ stateOptions = opts } ""+ parsed <- readWithM parser def{ stateOptions = opts } ("" :: Text) case parsed of Right result -> return result Left e -> throwError e@@ -146,14 +145,14 @@ ctx <- stateParserContext <$> getState guard (ctx == ListItemState) -spnl :: PandocMonad m => ParserT Text st m ()+spnl :: PandocMonad m => ParserT Sources st m () spnl = try $ do skipSpaces optional newline skipSpaces notFollowedBy (char '\n') -spnl' :: PandocMonad m => ParserT Text st m Text+spnl' :: PandocMonad m => ParserT Sources st m Text spnl' = try $ do xs <- many spaceChar ys <- option "" $ try $ (:) <$> newline@@ -298,7 +297,7 @@ (try $ newline >> lookAhead (blankline <|> nonspaceChar)) guard $ allowEmpty || not (T.null val) let key' = T.concat $ T.words $ T.toLower key- let val' = MetaBlocks $ B.toList $ B.plain $ B.text val+ let val' = MetaInlines $ B.toList $ B.text val return (key',val') parseMarkdown :: PandocMonad m => MarkdownParser m Pandoc@@ -337,7 +336,9 @@ notFollowedBy' (() <$ reference) many1Char $ notFollowedBy space >> litChar let betweenAngles = try $ char '<' >> manyTillChar litChar (char '>')- src <- try betweenAngles <|> sourceURL+ rebase <- option False (True <$ guardEnabled Ext_rebase_relative_paths)+ src <- (if rebase then rebasePath pos else id) <$>+ (try betweenAngles <|> sourceURL) tit <- option "" referenceTitle attr <- option nullAttr $ try $ do guardEnabled Ext_link_attributes@@ -568,7 +569,7 @@ -- hrule block -- -hrule :: PandocMonad m => ParserT Text st m (F Blocks)+hrule :: PandocMonad m => ParserT Sources st m (F Blocks) hrule = try $ do skipSpaces start <- satisfy isHruleChar@@ -588,7 +589,7 @@ blockDelimiter :: PandocMonad m => (Char -> Bool) -> Maybe Int- -> ParserT Text ParserState m Int+ -> ParserT Sources ParserState m Int blockDelimiter f len = try $ do skipNonindentSpaces c <- lookAhead (satisfy f)@@ -732,7 +733,7 @@ blanklines return $ T.intercalate "\n" lns' -birdTrackLine :: PandocMonad m => Char -> ParserT Text st m Text+birdTrackLine :: PandocMonad m => Char -> ParserT Sources st m Text birdTrackLine c = try $ do char c -- allow html tags on left margin:@@ -1025,7 +1026,7 @@ option (B.plain <$> result) $ try $ do newline- (blanklines >> return mempty)+ (mempty <$ blanklines) <|> (guardDisabled Ext_blank_before_blockquote >> () <$ lookAhead blockQuote) <|> (guardEnabled Ext_backtick_code_blocks >> () <$ lookAhead codeBlockFenced) <|> (guardDisabled Ext_blank_before_header >> () <$ lookAhead header)@@ -1170,7 +1171,7 @@ -- and the length including trailing space. dashedLine :: PandocMonad m => Char- -> ParserT Text st m (Int, Int)+ -> ParserT Sources st m (Int, Int) dashedLine ch = do dashes <- many1 (char ch) sp <- many spaceChar@@ -1239,7 +1240,7 @@ -> MarkdownParser m [Text] rawTableLine indices = do notFollowedBy' (blanklines' <|> tableFooter)- line <- take1WhileP (/='\n') <* newline+ line <- anyLine return $ map trim $ tail $ splitTextByIndices (init indices) line @@ -1390,7 +1391,7 @@ return $ B.plain <$> result) <|> return mempty -pipeTableHeaderPart :: PandocMonad m => ParserT Text st m (Alignment, Int)+pipeTableHeaderPart :: PandocMonad m => ParserT Sources st m (Alignment, Int) pipeTableHeaderPart = try $ do skipMany spaceChar left <- optionMaybe (char ':')@@ -1406,10 +1407,14 @@ (Just _,Just _) -> AlignCenter, len) -- Succeed only if current line contains a pipe.-scanForPipe :: PandocMonad m => ParserT Text st m ()+scanForPipe :: PandocMonad m => ParserT Sources st m () scanForPipe = do- inp <- getInput- case T.break (\c -> c == '\n' || c == '|') inp of+ Sources inps <- getInput+ let ln = case inps of+ [] -> ""+ ((_,t):(_,t'):_) | T.null t -> t'+ ((_,t):_) -> t+ case T.break (\c -> c == '\n' || c == '|') ln of (_, T.uncons -> Just ('|', _)) -> return () _ -> mzero @@ -1703,13 +1708,13 @@ where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak) regsp = skipMany spaceChar >> return B.space -nonEndline :: PandocMonad m => ParserT Text st m Char+nonEndline :: PandocMonad m => ParserT Sources st m Char nonEndline = satisfy (/='\n') str :: PandocMonad m => MarkdownParser m (F Inlines) str = do result <- mconcat <$> many1- ( take1WhileP isAlphaNum+ ( T.pack <$> (many1 alphaNum) <|> "." <$ try (char '.' <* notFollowedBy (char '.')) ) updateLastStrPos (do guardEnabled Ext_smart@@ -1833,9 +1838,12 @@ -> MarkdownParser m (F Inlines) regLink constructor lab = try $ do (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- return $ constructor attr src tit <$> lab+ return $ constructor attr src' tit <$> lab -- a link like [this][ref] or [this][] or [this] referenceLink :: PandocMonad m@@ -1875,7 +1883,8 @@ Just ((src, tit), _) -> constructor nullAttr src tit <$> lab Nothing -> makeFallback else makeFallback- Just ((src,tit), attr) -> constructor attr src tit <$> lab+ Just ((src,tit), attr) ->+ constructor attr src tit <$> lab dropBrackets :: Text -> Text dropBrackets = dropRB . dropLB@@ -1908,15 +1917,31 @@ return $ return $ B.linkWith attr (src <> escapeURI extra) "" (B.str $ orig <> extra) +-- | Rebase a relative path, by adding the (relative) directory+-- of the containing source position. Absolute links and URLs+-- are untouched.+rebasePath :: SourcePos -> Text -> Text+rebasePath pos path = do+ let fp = sourceName pos+ isFragment = T.take 1 path == "#"+ in if T.null path || isFragment || isAbsolute (T.unpack path) || isURI path+ then path+ else+ case takeDirectory fp of+ "" -> path+ "." -> path+ d -> T.pack d <> "/" <> path+ 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+ 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) note :: PandocMonad m => MarkdownParser m (F Inlines)@@ -1962,7 +1987,7 @@ s <- rawLaTeXInline return $ return $ B.rawInline "tex" s -- "tex" because it might be context -rawConTeXtEnvironment :: PandocMonad m => ParserT Text st m Text+rawConTeXtEnvironment :: PandocMonad m => ParserT Sources st m Text rawConTeXtEnvironment = try $ do string "\\start" completion <- inBrackets (letter <|> digit <|> spaceChar)@@ -1971,7 +1996,7 @@ (try $ string "\\stop" >> textStr completion) return $ "\\start" <> completion <> T.concat contents <> "\\stop" <> completion -inBrackets :: PandocMonad m => ParserT Text st m Char -> ParserT Text st m Text+inBrackets :: PandocMonad m => ParserT Sources st m Char -> ParserT Sources st m Text inBrackets parser = do char '[' contents <- manyChar parser@@ -2091,7 +2116,7 @@ textualCite :: PandocMonad m => MarkdownParser m (F Inlines) textualCite = try $ do- (suppressAuthor, key) <- citeKey+ (suppressAuthor, key) <- citeKey True -- If this is a reference to an earlier example list item, -- then don't parse it as a citation. If the example list -- item comes later, we'll parse it here and figure out in@@ -2171,7 +2196,7 @@ manyTill inline (char ']' <|> lookAhead (try $ do optional (try (char ';' >> spnl))- citeKey+ citeKey True return ']')) citeList :: PandocMonad m => MarkdownParser m (F [Citation])@@ -2180,7 +2205,7 @@ citation :: PandocMonad m => MarkdownParser m (F Citation) citation = try $ do pref <- prefix- (suppress_author, key) <- citeKey+ (suppress_author, key) <- citeKey True suff <- suffix noteNum <- stateNoteNumber <$> getState return $ do@@ -2199,25 +2224,27 @@ smart :: PandocMonad m => MarkdownParser m (F Inlines) smart = do guardEnabled Ext_smart- doubleQuoted <|> singleQuoted <|>- choice (map (return <$>) [apostrophe, dash, ellipses])+ doubleQuoted <|> singleQuoted <|> (return <$> doubleCloseQuote) <|>+ (return <$> apostrophe) <|> (return <$> dash) <|> (return <$> ellipses) singleQuoted :: PandocMonad m => MarkdownParser m (F Inlines)-singleQuoted = try $ do+singleQuoted = do singleQuoteStart- withQuoteContext InSingleQuote $+ (try (withQuoteContext InSingleQuote $ fmap B.singleQuoted . trimInlinesF . mconcat <$>- many1Till inline singleQuoteEnd+ many1Till inline singleQuoteEnd))+ <|> (return (return (B.str "\8217"))) -- doubleQuoted will handle regular double-quoted sections, as well -- as dialogues with an open double-quote without a close double-quote -- in the same paragraph. doubleQuoted :: PandocMonad m => MarkdownParser m (F Inlines)-doubleQuoted = try $ do+doubleQuoted = do doubleQuoteStart- withQuoteContext InDoubleQuote $+ (try (withQuoteContext InDoubleQuote $ fmap B.doubleQuoted . trimInlinesF . mconcat <$>- many1Till inline doubleQuoteEnd+ many1Till inline doubleQuoteEnd))+ <|> (return (return (B.str "\8220"))) toRow :: [Blocks] -> Row toRow = Row nullAttr . map B.simpleCell
@@ -36,17 +36,18 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (nested) import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isCommentTag)-import Text.Pandoc.Shared (crFilter, safeRead, stringify, stripTrailingNewlines,+import Text.Pandoc.Shared (safeRead, stringify, stripTrailingNewlines, trim, splitTextBy, tshow) import Text.Pandoc.Walk (walk) import Text.Pandoc.XML (fromEntities) -- | Read mediawiki from an input string and return a Pandoc document.-readMediaWiki :: PandocMonad m- => ReaderOptions -- ^ Reader options- -> Text -- ^ String to parse (assuming @'\n'@ line endings)+readMediaWiki :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a -> m Pandoc readMediaWiki opts s = do+ let sources = toSources s parsed <- readWithM parseMediaWiki MWState{ mwOptions = opts , mwMaxNestingLevel = 4 , mwNextLinkNumber = 1@@ -55,7 +56,7 @@ , mwLogMessages = [] , mwInTT = False }- (crFilter s <> "\n")+ sources case parsed of Right result -> return result Left e -> throwError e@@ -69,7 +70,7 @@ , mwInTT :: Bool } -type MWParser m = ParserT Text MWState m+type MWParser m = ParserT Sources MWState m instance HasReaderOptions MWState where extractReaderOptions = mwOptions
@@ -35,9 +35,9 @@ import qualified Text.Pandoc.UTF8 as UTF8 yamlBsToMeta :: (PandocMonad m, HasLastStrPosition st)- => ParserT Text st m (Future st MetaValue)+ => ParserT Sources st m (Future st MetaValue) -> BL.ByteString- -> ParserT Text st m (Future st Meta)+ -> ParserT Sources st m (Future st Meta) yamlBsToMeta pMetaValue bstr = do case YAML.decodeNode' YAML.failsafeSchemaResolver False False bstr of Right (YAML.Doc (YAML.Mapping _ _ o):_)@@ -67,10 +67,10 @@ -- Returns filtered list of references. yamlBsToRefs :: (PandocMonad m, HasLastStrPosition st)- => ParserT Text st m (Future st MetaValue)+ => ParserT Sources st m (Future st MetaValue) -> (Text -> Bool) -- ^ Filter for id -> BL.ByteString- -> ParserT Text st m (Future st [MetaValue])+ -> ParserT Sources st m (Future st [MetaValue]) yamlBsToRefs pMetaValue idpred bstr = case YAML.decodeNode' YAML.failsafeSchemaResolver False False bstr of Right (YAML.Doc o@YAML.Mapping{}:_)@@ -98,8 +98,12 @@ Right [YAML.Doc (YAML.Scalar _ YAML.SNull)] -> return . return $ mempty Right _ -> Prelude.fail "expecting YAML object"- Left (_pos, err')- -> Prelude.fail err'+ Left (yamlpos, err')+ -> do pos <- getPosition+ setPosition $ incSourceLine+ (setSourceColumn pos (YE.posColumn yamlpos))+ (YE.posLine yamlpos - 1)+ Prelude.fail err' nodeToKey :: YAML.Node YE.Pos -> Maybe Text@@ -108,9 +112,9 @@ nodeToKey _ = Nothing normalizeMetaValue :: (PandocMonad m, HasLastStrPosition st)- => ParserT Text st m (Future st MetaValue)+ => ParserT Sources st m (Future st MetaValue) -> Text- -> ParserT Text st m (Future st MetaValue)+ -> ParserT 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@@ -133,9 +137,9 @@ | otherwise = Nothing yamlToMetaValue :: (PandocMonad m, HasLastStrPosition st)- => ParserT Text st m (Future st MetaValue)+ => ParserT Sources st m (Future st MetaValue) -> YAML.Node YE.Pos- -> ParserT Text st m (Future st MetaValue)+ -> ParserT Sources st m (Future st MetaValue) yamlToMetaValue pMetaValue (YAML.Scalar _ x) = case x of YAML.SStr t -> normalizeMetaValue pMetaValue t@@ -156,9 +160,9 @@ yamlToMetaValue _ _ = return $ return $ MetaString "" yamlMap :: (PandocMonad m, HasLastStrPosition st)- => ParserT Text st m (Future st MetaValue)+ => ParserT Sources st m (Future st MetaValue) -> M.Map (YAML.Node YE.Pos) (YAML.Node YE.Pos)- -> ParserT Text st m (Future st (M.Map Text MetaValue))+ -> ParserT Sources st m (Future st (M.Map Text MetaValue)) yamlMap pMetaValue o = do kvs <- forM (M.toList o) $ \(key, v) -> do k <- maybe (throwError $ PandocParseError@@ -177,8 +181,8 @@ -- | Parse a YAML metadata block using the supplied 'MetaValue' parser. yamlMetaBlock :: (HasLastStrPosition st, PandocMonad m)- => ParserT Text st m (Future st MetaValue)- -> ParserT Text st m (Future st Meta)+ => ParserT Sources st m (Future st MetaValue)+ -> ParserT Sources st m (Future st Meta) yamlMetaBlock parser = try $ do string "---" blankline@@ -189,5 +193,5 @@ optional blanklines yamlBsToMeta parser $ UTF8.fromTextLazy $ TL.fromStrict rawYaml -stopLine :: Monad m => ParserT Text st m ()+stopLine :: Monad m => ParserT Sources st m () stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
@@ -37,18 +37,19 @@ import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Parsing-import Text.Pandoc.Shared (crFilter, trimr, tshow)+import Text.Pandoc.Shared (trimr, tshow) -- | Read Muse from an input string and return a Pandoc document.-readMuse :: PandocMonad m+readMuse :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc readMuse opts s = do- let input = crFilter s- res <- flip runReaderT def $ runParserT parseMuse def{ museOptions = opts } "source" input+ let sources = toSources s+ res <- flip runReaderT def $ runParserT parseMuse def{ museOptions = opts }+ (initialSourceName sources) sources case res of- Left e -> throwError $ PandocParsecError input e+ Left e -> throwError $ PandocParsecError sources e Right d -> return d type F = Future MuseState@@ -82,7 +83,7 @@ , museInPara = False } -type MuseParser m = ParserT Text MuseState (ReaderT MuseEnv m)+type MuseParser m = ParserT Sources MuseState (ReaderT MuseEnv m) instance HasReaderOptions MuseState where extractReaderOptions = museOptions@@ -155,7 +156,7 @@ -- * Parsers -- | Parse end-of-line, which can be either a newline or end-of-file.-eol :: Stream s m Char => ParserT s st m ()+eol :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m () eol = void newline <|> eof getIndent :: PandocMonad m
@@ -21,6 +21,7 @@ import Data.Text (Text) import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Error+import Text.Pandoc.Sources (ToSources(..), sourcesToText) -- | Read native formatted text and return a Pandoc document. -- The input may be a full pandoc document, a block list, a block,@@ -32,14 +33,15 @@ -- -- > Pandoc nullMeta [Plain [Str "hi"]] ---readNative :: PandocMonad m+readNative :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text -- ^ String to parse (assuming @'\n'@ line endings)+ -> a -> m Pandoc readNative _ s =- case maybe (Pandoc nullMeta <$> readBlocks s) Right (safeRead s) of- Right doc -> return doc- Left _ -> throwError $ PandocParseError "couldn't read native"+ let t = sourcesToText . toSources $ s+ in case maybe (Pandoc nullMeta <$> readBlocks t) Right (safeRead t) of+ Right doc -> return doc+ Left _ -> throwError $ PandocParseError "couldn't read native" readBlocks :: Text -> Either PandocError [Block] readBlocks s = maybe ((:[]) <$> readBlock s) Right (safeRead s)
@@ -24,7 +24,8 @@ import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Readers.HTML (readHtml) import Text.Pandoc.Readers.Markdown (readMarkdown)-import Text.Pandoc.Shared (crFilter, blocksToInlines')+import Text.Pandoc.Shared (blocksToInlines')+import Text.Pandoc.Sources (ToSources(..), sourcesToText) import Text.Pandoc.XML.Light import Control.Monad.Except (throwError) @@ -46,10 +47,14 @@ , opmlOptions = def } -readOPML :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readOPML :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc readOPML opts inp = do- (bs, st') <- runStateT- (case parseXMLContents (TL.fromStrict (crFilter inp)) of+ let sources = toSources inp+ (bs, st') <-+ runStateT (case parseXMLContents (TL.fromStrict . sourcesToText $ sources) of Left msg -> throwError $ PandocXMLError "" msg Right ns -> mapM parseBlock ns) def{ opmlOptions = opts }
@@ -1,4 +1,5 @@ {-# LANGUAGE Arrows #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE PatternGuards #-}@@ -33,7 +34,7 @@ import qualified Data.Map as M import qualified Data.Text as T import Data.Maybe-import Data.Semigroup (First(..), Option(..))+import Data.Monoid (Alt (..)) import Text.TeXMath (readMathML, writeTeX) import qualified Text.Pandoc.XML.Light as XML@@ -505,13 +506,11 @@ type BlockMatcher = ElementMatcher Blocks --newtype FirstMatch a = FirstMatch (Option (First a))- deriving (Foldable, Monoid, Semigroup)+newtype FirstMatch a = FirstMatch (Alt Maybe a)+ deriving (Foldable, Monoid, Semigroup) firstMatch :: a -> FirstMatch a-firstMatch = FirstMatch . Option . Just . First-+firstMatch = FirstMatch . Alt . Just -- matchingElement :: (Monoid e)@@ -577,14 +576,18 @@ 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@@ -604,6 +607,7 @@ $ matchChildContent [ read_span , read_spaces , read_line_break+ , read_tab , read_link , read_note , read_citation@@ -630,6 +634,7 @@ children <- ( matchChildContent [ read_span , read_spaces , read_line_break+ , read_tab , read_link , read_note , read_citation
@@ -18,22 +18,19 @@ import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Parsing (reportLogMessages)-import Text.Pandoc.Shared (crFilter)-+import Text.Pandoc.Sources (ToSources(..), ensureFinalNewlines) import Control.Monad.Except (throwError) import Control.Monad.Reader (runReaderT) -import Data.Text (Text)- -- | Parse org-mode string and return a Pandoc document.-readOrg :: PandocMonad m+readOrg :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ String to parse (assuming @'\n'@ line endings)+ -> a -> m Pandoc readOrg opts s = do parsed <- flip runReaderT def $ readWithM parseOrg (optionsToParserState opts)- (crFilter s <> "\n\n")+ (ensureFinalNewlines 2 (toSources s)) case parsed of Right result -> return result Left e -> throwError e
@@ -40,10 +40,11 @@ import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Text (Text) import Data.List.NonEmpty (nonEmpty)-+import System.FilePath import qualified Data.Text as T import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Walk as Walk+import Text.Pandoc.Sources (ToSources(..)) -- -- parsing blocks@@ -527,7 +528,9 @@ _ -> nullAttr return $ pure . B.codeBlockWith attr <$> parseRaw _ -> return $ return . B.fromList . blockFilter params <$> blockList- insertIncludedFileF blocksParser ["."] filename+ currentDir <- takeDirectory . sourceName <$> getPosition+ insertIncludedFile blocksParser toSources+ [currentDir] filename Nothing Nothing where includeTarget :: PandocMonad m => OrgParser m FilePath includeTarget = do
@@ -29,6 +29,7 @@ import Text.Pandoc.Options import Text.Pandoc.Readers.LaTeX (inlineCommand, rawLaTeXInline) import Text.TeXMath (DisplayType (..), readTeX, writePandoc)+import Text.Pandoc.Sources (ToSources(..)) import qualified Text.TeXMath.Readers.MathML.EntityMap as MathMLEntityMap import Control.Monad (guard, mplus, mzero, unless, void, when)@@ -262,7 +263,7 @@ where citationListPart :: PandocMonad m => OrgParser m (F Inlines) citationListPart = fmap (trimInlinesF . mconcat) . try . many1 $ do- notFollowedBy' citeKey+ notFollowedBy' $ citeKey False notFollowedBy (oneOf ";]") inline @@ -277,7 +278,7 @@ berkeleyTextualCite :: PandocMonad m => OrgParser m (F [Citation]) berkeleyTextualCite = try $ do- (suppressAuthor, key) <- citeKey+ (suppressAuthor, key) <- citeKey False returnF . return $ Citation { citationId = key , citationPrefix = mempty@@ -350,7 +351,7 @@ citation :: PandocMonad m => OrgParser m (F Citation) citation = try $ do pref <- prefix- (suppress_author, key) <- citeKey+ (suppress_author, key) <- citeKey False suff <- suffix return $ do x <- pref@@ -367,7 +368,7 @@ } where prefix = trimInlinesF . mconcat <$>- manyTill inline (char ']' <|> (']' <$ lookAhead citeKey))+ manyTill inline (char ']' <|> (']' <$ lookAhead (citeKey False))) suffix = try $ do hasSpace <- option False (notFollowedBy nonspaceChar >> return True) skipSpaces@@ -802,7 +803,7 @@ parseAsInlineLaTeX :: PandocMonad m => Text -> TeXExport -> OrgParser m (Maybe Inlines) parseAsInlineLaTeX cs = \case- TeXExport -> maybeRight <$> runParserT inlineCommand state "" cs+ TeXExport -> maybeRight <$> runParserT inlineCommand state "" (toSources cs) TeXIgnore -> return (Just mempty) TeXVerbatim -> return (Just $ B.str cs)
@@ -63,8 +63,7 @@ , ellipses , citeKey , gridTableWith- , insertIncludedFileF- -- * Re-exports from Text.Pandoc.Parsec+ , insertIncludedFile , runParser , runParserT , getInput@@ -100,6 +99,7 @@ , getState , updateState , SourcePos+ , sourceName , getPosition ) where @@ -114,7 +114,7 @@ import Control.Monad.Reader (ReaderT) -- | The parser used to read org files.-type OrgParser m = ParserT Text OrgParserState (ReaderT OrgParserLocal m)+type OrgParser m = ParserT Sources OrgParserState (ReaderT OrgParserLocal m) -- -- Adaptions and specializations of parsing utilities
@@ -27,8 +27,7 @@ import qualified Data.Text as T import Text.Pandoc.Builder (Blocks, Inlines, fromList, setMeta, trimInlines) import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem,- readFileFromDirs, getTimestamp)+import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem, getTimestamp) import Text.Pandoc.CSV (CSVOptions (..), defaultCSVOptions, parseCSV) import Text.Pandoc.Definition import Text.Pandoc.Error@@ -38,25 +37,25 @@ import Text.Pandoc.Parsing import Text.Pandoc.Shared import qualified Text.Pandoc.UTF8 as UTF8-import Text.Printf (printf) import Data.Time.Format+import System.FilePath (takeDirectory) -- TODO: -- [ ] .. parsed-literal -- | Parse reStructuredText string and return Pandoc document.-readRST :: PandocMonad m+readRST :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ Text to parse (assuming @'\n'@ line endings)+ -> a -> m Pandoc readRST opts s = do parsed <- readWithM parseRST def{ stateOptions = opts }- (crFilter s <> "\n\n")+ (ensureFinalNewlines 2 (toSources s)) case parsed of Right result -> return result Left e -> throwError e -type RSTParser m = ParserT Text ParserState m+type RSTParser m = ParserT Sources ParserState m -- -- Constants and data structure definitions@@ -151,11 +150,19 @@ 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...- docMinusKeys <- T.concat <$>- manyTill (referenceKey <|> anchorDef <|>- noteBlock <|> citationBlock <|>- (snd <$> withRaw comment) <|>- headerBlock <|> lineClump) eof+ 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@@ -348,7 +355,7 @@ -- hrule block -- -hrule :: Monad m => ParserT Text st m Blocks+hrule :: Monad m => ParserT Sources st m Blocks hrule = try $ do chr <- oneOf underlineChars count 3 (char chr)@@ -363,7 +370,7 @@ -- read a line indented by a given string indentedLine :: (HasReaderOptions st, Monad m)- => Int -> ParserT Text st m Text+ => Int -> ParserT Sources st m Text indentedLine indents = try $ do lookAhead spaceChar gobbleAtMostSpaces indents@@ -372,7 +379,7 @@ -- one or more indented lines, possibly separated by blank lines. -- any amount of indentation will work. indentedBlock :: (HasReaderOptions st, Monad m)- => ParserT Text st m Text+ => ParserT Sources st m Text indentedBlock = try $ do indents <- length <$> lookAhead (many1 spaceChar) lns <- many1 $ try $ do b <- option "" blanklines@@ -381,20 +388,20 @@ optional blanklines return $ T.unlines lns -quotedBlock :: Monad m => ParserT Text st m Text+quotedBlock :: Monad m => ParserT 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 Text st m Char+codeBlockStart :: Monad m => ParserT Sources st m Char codeBlockStart = string "::" >> blankline >> blankline -codeBlock :: Monad m => ParserT Text ParserState m Blocks+codeBlock :: Monad m => ParserT Sources ParserState m Blocks codeBlock = try $ codeBlockStart >> codeBlockBody -codeBlockBody :: Monad m => ParserT Text ParserState m Blocks+codeBlockBody :: Monad m => ParserT Sources ParserState m Blocks codeBlockBody = do lang <- stateRstHighlight <$> getState try $ B.codeBlockWith ("", maybeToList lang, []) . stripTrailingNewlines <$>@@ -410,14 +417,14 @@ return $ B.codeBlockWith ("", ["haskell","literate"], []) $ T.intercalate "\n" lns -latexCodeBlock :: Monad m => ParserT Text st m [Text]+latexCodeBlock :: Monad m => ParserT 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 Text st m [Text]+birdCodeBlock :: Monad m => ParserT Sources st m [Text] birdCodeBlock = filterSpace <$> many1 birdTrackLine where filterSpace lns = -- if (as is normal) there is always a space after >, drop it@@ -425,7 +432,7 @@ then map (T.drop 1) lns else lns -birdTrackLine :: Monad m => ParserT Text st m Text+birdTrackLine :: Monad m => ParserT Sources st m Text birdTrackLine = char '>' >> anyLine --@@ -446,64 +453,39 @@ -} includeDirective :: PandocMonad m- => Text -> [(Text, Text)] -> Text+ => Text+ -> [(Text, Text)]+ -> Text -> RSTParser m Blocks includeDirective top fields body = do- let f = trim top- guard $ not (T.null f)+ let f = T.unpack $ trim top+ guard $ not $ null f guard $ T.null (trim body)- -- options- let (startLine :: Maybe Int) = lookup "start-line" fields >>= safeRead- let (endLine :: Maybe Int) = lookup "end-line" fields >>= safeRead- oldPos <- getPosition- oldInput <- getInput- containers <- stateContainers <$> getState- when (f `elem` containers) $- throwError $ PandocParseError $ "Include file loop at " <> tshow oldPos- updateState $ \s -> s{ stateContainers = f : stateContainers s }- mbContents <- readFileFromDirs ["."] $ T.unpack f- contentLines <- case mbContents of- Just s -> return $ T.lines s- Nothing -> do- logMessage $ CouldNotLoadIncludeFile f oldPos- return []- let numLines = length contentLines- let startLine' = case startLine of- Nothing -> 1- Just x | x >= 0 -> x- | otherwise -> numLines + x -- negative from end- let endLine' = case endLine of- Nothing -> numLines + 1- Just x | x >= 0 -> x- | otherwise -> numLines + x -- negative from end- let contentLines' = drop (startLine' - 1)- $ take (endLine' - 1) contentLines- let contentLines'' = (case trim <$> lookup "end-before" fields of- Just patt -> takeWhile (not . (patt `T.isInfixOf`))- Nothing -> id) .- (case trim <$> lookup "start-after" fields of- Just patt -> drop 1 .- dropWhile (not . (patt `T.isInfixOf`))- Nothing -> id) $ contentLines'- let contents' = T.unlines contentLines''- case lookup "code" fields of- Just lang -> do- let classes = maybe [] T.words (lookup "class" fields)- let ident = maybe "" trimr $ lookup "name" fields- codeblock ident classes fields (trimr lang) contents' False- Nothing -> case lookup "literal" fields of- Just _ -> return $ B.rawBlock "rst" contents'- Nothing -> do- setPosition $ newPos (T.unpack f) 1 1- setInput $ contents' <> "\n"- bs <- optional blanklines >>- (mconcat <$> many block)- setInput oldInput- setPosition oldPos- updateState $ \s -> s{ stateContainers =- tail $ stateContainers s }- return bs-+ let startLine = lookup "start-line" fields >>= safeRead+ let endLine = lookup "end-line" fields >>= safeRead+ let classes = maybe [] T.words (lookup "class" fields)+ let ident = maybe "" trimr $ lookup "name" fields+ let parser =+ case lookup "code" fields of+ Just lang ->+ (codeblock ident classes fields (trimr lang) False+ . sourcesToText) <$> getInput+ Nothing ->+ case lookup "literal" fields of+ Just _ -> B.rawBlock "rst" . sourcesToText <$> getInput+ Nothing -> parseBlocks+ let selectLines =+ (case trim <$> lookup "end-before" fields of+ Just patt -> takeWhile (not . (patt `T.isInfixOf`))+ Nothing -> id) .+ (case trim <$> lookup "start-after" fields of+ Just patt -> drop 1 .+ dropWhile (not . (patt `T.isInfixOf`))+ Nothing -> id)+ let toStream t =+ toSources [(f, T.unlines . selectLines . T.lines $ t)]+ currentDir <- takeDirectory . sourceName <$> getPosition+ insertIncludedFile parser toStream [currentDir] f startLine endLine -- -- list blocks@@ -526,7 +508,7 @@ definitionList = B.definitionList <$> many1 definitionListItem -- parses bullet list start and returns its length (inc. following whitespace)-bulletListStart :: Monad m => ParserT Text st m Int+bulletListStart :: Monad m => ParserT Sources st m Int bulletListStart = try $ do notFollowedBy' hrule -- because hrules start out just like lists marker <- oneOf bulletListMarkers@@ -732,8 +714,8 @@ "" -> stateRstHighlight def lang -> Just lang }) x | x == "code" || x == "code-block" || x == "sourcecode" ->- codeblock name classes (map (second trimr) fields)- (trim top) body True+ return $ codeblock name classes (map (second trimr) fields)+ (trim top) True body "aafig" -> do let attribs = (name, ["aafig"], map (second trimr) fields) return $ B.codeBlockWith attribs $ stripTrailingNewlines body@@ -1019,10 +1001,10 @@ then "\\begin{aligned}\n" <> s <> "\n\\end{aligned}" else s -codeblock :: Text -> [Text] -> [(Text, Text)] -> Text -> Text -> Bool- -> RSTParser m Blocks-codeblock ident classes fields lang body rmTrailingNewlines =- return $ B.codeBlockWith attribs $ stripTrailingNewlines' body+codeblock :: Text -> [Text] -> [(Text, Text)] -> Text -> Bool -> Text+ -> Blocks+codeblock ident classes fields lang rmTrailingNewlines body =+ B.codeBlockWith attribs $ stripTrailingNewlines' body where stripTrailingNewlines' = if rmTrailingNewlines then stripTrailingNewlines else id@@ -1103,7 +1085,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 Text st m Text+simpleReferenceName :: Monad m => ParserT Sources st m Text simpleReferenceName = do x <- alphaNum xs <- many $ alphaNum@@ -1122,7 +1104,7 @@ -- return enough blanks to replace key return $ T.replicate (sourceLine endPos - sourceLine startPos) "\n" -targetURI :: Monad m => ParserT Text st m Text+targetURI :: Monad m => ParserT Sources st m Text targetURI = do skipSpaces optional $ try $ newline >> notFollowedBy blankline@@ -1160,8 +1142,10 @@ anonymousKey = try $ do oneOfStrings [".. __:", "__"] src <- targetURI- pos <- getPosition- let key = toKey $ "_" <> T.pack (printf "%09d" (sourceLine pos))+ -- 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) updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $ stateKeys s } @@ -1250,13 +1234,13 @@ -- Grid tables TODO: -- - column spans -dashedLine :: Monad m => Char -> ParserT Text st m (Int, Int)+dashedLine :: Monad m => Char -> ParserT Sources st m (Int, Int) dashedLine ch = do dashes <- many1 (char ch) sp <- many (char ' ') return (length dashes, length $ dashes ++ sp) -simpleDashedLines :: Monad m => Char -> ParserT Text st m [(Int,Int)]+simpleDashedLines :: Monad m => Char -> ParserT Sources st m [(Int,Int)] simpleDashedLines ch = try $ many1 (dashedLine ch) -- Parse a table row separator@@ -1382,7 +1366,7 @@ -- don't want to treat endline after hyphen or dash as a space return $ B.str result -escapedChar :: Monad m => ParserT Text st m Inlines+escapedChar :: Monad m => ParserT Sources st m Inlines escapedChar = do c <- escaped anyChar return $ if c == ' ' || c == '\n' || c == '\r' -- '\ ' is null in RST@@ -1658,21 +1642,4 @@ return $ B.note contents smart :: PandocMonad m => RSTParser m Inlines-smart = do- guardEnabled Ext_smart- doubleQuoted <|> singleQuoted <|>- choice [apostrophe, dash, ellipses]--singleQuoted :: PandocMonad m => RSTParser m Inlines-singleQuoted = try $ do- singleQuoteStart- withQuoteContext InSingleQuote $- B.singleQuoted . trimInlines . mconcat <$>- many1Till inline singleQuoteEnd--doubleQuoted :: PandocMonad m => RSTParser m Inlines-doubleQuoted = try $ do- doubleQuoteStart- withQuoteContext InDoubleQuote $- B.doubleQuoted . trimInlines . mconcat <$>- many1Till inline doubleQuoteEnd+smart = smartPunctuation inline
@@ -42,7 +42,6 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Shared (safeRead)-import Text.Parsec hiding (tokenPrim) import Text.Pandoc.RoffChar (characterCodes, combiningAccents) import qualified Data.Sequence as Seq import qualified Data.Foldable as Foldable@@ -122,16 +121,16 @@ , afterConditional = False } -type RoffLexer m = ParserT T.Text RoffState m+type RoffLexer m = ParserT Sources RoffState m -- -- Lexer: T.Text -> RoffToken -- -eofline :: Stream s m Char => ParsecT s u m ()+eofline :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s u m () eofline = void newline <|> eof <|> () <$ lookAhead (string "\\}") -spacetab :: Stream s m Char => ParsecT s u m Char+spacetab :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s u m Char spacetab = char ' ' <|> char '\t' characterCodeMap :: M.Map T.Text Char@@ -303,8 +302,7 @@ char '*' cs <- escapeArg <|> countChar 1 anyChar s <- linePartsToText <$> resolveText cs pos- getInput >>= setInput . (s <>)- return ()+ addToInput s -- Parses: '..' quoteArg :: PandocMonad m => RoffLexer m T.Text@@ -316,7 +314,7 @@ font' <- if T.null font || font == "P" then prevFont <$> getState else return $ foldr processFontLetter defaultFontSpec $ T.unpack font- modifyState $ \st -> st{ prevFont = currentFont st+ updateState $ \st -> st{ prevFont = currentFont st , currentFont = font' } return [Font font'] where@@ -372,8 +370,8 @@ spaces opts <- try tableOptions <|> [] <$ optional (char ';') case lookup "tab" opts of- Just (T.uncons -> Just (c, _)) -> modifyState $ \st -> st{ tableTabChar = c }- _ -> modifyState $ \st -> st{ tableTabChar = '\t' }+ Just (T.uncons -> Just (c, _)) -> updateState $ \st -> st{ tableTabChar = c }+ _ -> updateState $ \st -> st{ tableTabChar = '\t' } spaces skipMany lexComment spaces@@ -489,18 +487,18 @@ ifPart <- do optional $ try $ char '\\' >> newline lexGroup- <|> do modifyState $ \s -> s{ afterConditional = True }+ <|> do updateState $ \s -> s{ afterConditional = True } t <- manToken- modifyState $ \s -> s{ afterConditional = False }+ updateState $ \s -> s{ afterConditional = False } return t case mbtest of Nothing -> do- putState st -- reset state, so we don't record macros in skipped section+ setState st -- reset state, so we don't record macros in skipped section report $ SkippedContent (T.cons '.' mname) pos return mempty Just True -> return ifPart Just False -> do- putState st+ setState st return mempty expression :: PandocMonad m => RoffLexer m (Maybe Bool)@@ -515,7 +513,7 @@ _ -> Nothing where returnValue v = do- modifyState $ \st -> st{ lastExpression = v }+ updateState $ \st -> st{ lastExpression = v } return v lexGroup :: PandocMonad m => RoffLexer m RoffTokens@@ -536,7 +534,7 @@ result <- readFileFromDirs dirs $ T.unpack fp case result of Nothing -> report $ CouldNotLoadIncludeFile fp pos- Just s -> getInput >>= setInput . (s <>)+ Just s -> addToInput s return mempty [] -> return mempty @@ -564,13 +562,13 @@ (x:ys) -> do let ts = singleTok $ TextLine (intercalate [RoffStr " " ] ys) let stringName = linePartsToText x- modifyState $ \st ->+ updateState $ \st -> st{ customMacros = M.insert stringName ts (customMacros st) } return mempty lexMacroDef :: PandocMonad m => [Arg] -> RoffLexer m RoffTokens lexMacroDef args = do -- macro definition- modifyState $ \st -> st{ roffMode = CopyMode }+ updateState $ \st -> st{ roffMode = CopyMode } (macroName, stopMacro) <- case args of (x : y : _) -> return (linePartsToText x, linePartsToText y)@@ -584,7 +582,7 @@ _ <- lexArgs return () ts <- mconcat <$> manyTill manToken stop- modifyState $ \st ->+ updateState $ \st -> st{ customMacros = M.insert macroName ts (customMacros st) , roffMode = NormalMode } return mempty
@@ -28,22 +28,22 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (enclosed, nested) import Text.Pandoc.Readers.HTML (htmlTag, isCommentTag)-import Text.Pandoc.Shared (crFilter, tshow)+import Text.Pandoc.Shared (tshow) import Text.Pandoc.XML (fromEntities) -- | Read twiki from an input string and return a Pandoc document.-readTWiki :: PandocMonad m+readTWiki :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc readTWiki opts s = do- res <- readWithM parseTWiki def{ stateOptions = opts }- (crFilter s <> "\n\n")+ let sources = ensureFinalNewlines 2 (toSources s)+ res <- readWithM parseTWiki def{ stateOptions = opts } sources case res of Left e -> throwError e Right d -> return d -type TWParser = ParserT Text ParserState+type TWParser = ParserT Sources ParserState -- -- utility functions@@ -469,27 +469,7 @@ symbol = B.str <$> countChar 1 nonspaceChar smart :: PandocMonad m => TWParser m B.Inlines-smart = do- guardEnabled Ext_smart- doubleQuoted <|> singleQuoted <|>- choice [ apostrophe- , dash- , ellipses- ]--singleQuoted :: PandocMonad m => TWParser m B.Inlines-singleQuoted = try $ do- singleQuoteStart- withQuoteContext InSingleQuote- (B.singleQuoted . B.trimInlines . mconcat <$> many1Till inline singleQuoteEnd)--doubleQuoted :: PandocMonad m => TWParser m B.Inlines-doubleQuoted = try $ do- doubleQuoteStart- contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)- withQuoteContext InDoubleQuote (doubleQuoteEnd >>- return (B.doubleQuoted $ B.trimInlines contents))- <|> return (B.str "\8220" B.<> contents)+smart = smartPunctuation inline link :: PandocMonad m => TWParser m B.Inlines link = try $ do
@@ -53,30 +53,34 @@ import Text.Pandoc.Parsing import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isInlineTag) import Text.Pandoc.Readers.LaTeX (rawLaTeXBlock, rawLaTeXInline)-import Text.Pandoc.Shared (crFilter, trim, tshow)+import Text.Pandoc.Shared (trim, tshow) -- | Parse a Textile text and return a Pandoc document.-readTextile :: PandocMonad m+readTextile :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options- -> Text -- ^ String to parse (assuming @'\n'@ line endings)+ -> a -> m Pandoc readTextile opts s = do- parsed <- readWithM parseTextile def{ stateOptions = opts }- (crFilter s <> "\n\n")+ let sources = ensureFinalNewlines 2 (toSources s)+ parsed <- readWithM parseTextile def{ stateOptions = opts } sources case parsed of Right result -> return result Left e -> throwError e +type TextileParser = ParserT Sources ParserState -- | Generate a Pandoc ADT from a textile document-parseTextile :: PandocMonad m => ParserT Text ParserState m Pandoc+parseTextile :: PandocMonad m => TextileParser m Pandoc parseTextile = do many blankline startPos <- getPosition -- go through once just to get list of reference keys and notes -- docMinusKeys is the raw document with blanks where the keys/notes were...- let firstPassParser = noteBlock <|> lineClump- manyTill firstPassParser eof >>= setInput . T.concat+ let firstPassParser = do+ pos <- getPosition+ t <- noteBlock <|> lineClump+ return (pos, t)+ manyTill firstPassParser eof >>= setInput . Sources setPosition startPos st' <- getState let reversedNotes = stateNotes st'@@ -84,10 +88,10 @@ -- now parse it for real... Pandoc nullMeta . B.toList <$> parseBlocks -- FIXME -noteMarker :: PandocMonad m => ParserT Text ParserState m Text+noteMarker :: PandocMonad m => TextileParser m Text noteMarker = skipMany spaceChar >> string "fn" >> T.pack <$> manyTill digit (char '.') -noteBlock :: PandocMonad m => ParserT Text ParserState m Text+noteBlock :: PandocMonad m => TextileParser m Text noteBlock = try $ do startPos <- getPosition ref <- noteMarker@@ -102,11 +106,11 @@ return $ T.replicate (sourceLine endPos - sourceLine startPos) "\n" -- | Parse document blocks-parseBlocks :: PandocMonad m => ParserT Text ParserState m Blocks+parseBlocks :: PandocMonad m => TextileParser m Blocks parseBlocks = mconcat <$> manyTill block eof -- | Block parsers list tried in definition order-blockParsers :: PandocMonad m => [ParserT Text ParserState m Blocks]+blockParsers :: PandocMonad m => [TextileParser m Blocks] blockParsers = [ codeBlock , header , blockQuote@@ -121,22 +125,22 @@ ] -- | Any block in the order of definition of blockParsers-block :: PandocMonad m => ParserT Text ParserState m Blocks+block :: PandocMonad m => TextileParser m Blocks block = do res <- choice blockParsers <?> "block" trace (T.take 60 $ tshow $ B.toList res) return res -commentBlock :: PandocMonad m => ParserT Text ParserState m Blocks+commentBlock :: PandocMonad m => TextileParser m Blocks commentBlock = try $ do string "###." manyTill anyLine blanklines return mempty -codeBlock :: PandocMonad m => ParserT Text ParserState m Blocks+codeBlock :: PandocMonad m => TextileParser m Blocks codeBlock = codeBlockTextile <|> codeBlockHtml -codeBlockTextile :: PandocMonad m => ParserT Text ParserState m Blocks+codeBlockTextile :: PandocMonad m => TextileParser m Blocks codeBlockTextile = try $ do string "bc." <|> string "pre." extended <- option False (True <$ char '.')@@ -156,7 +160,7 @@ trimTrailingNewlines = T.dropWhileEnd (=='\n') -- | Code Blocks in Textile are between <pre> and </pre>-codeBlockHtml :: PandocMonad m => ParserT Text ParserState m Blocks+codeBlockHtml :: PandocMonad m => TextileParser m Blocks codeBlockHtml = try $ do (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True)) result' <- T.pack <$> manyTill anyChar (htmlTag (tagClose (=="pre")))@@ -174,7 +178,7 @@ return $ B.codeBlockWith (ident,classes,kvs) result''' -- | Header of the form "hN. content" with N in 1..6-header :: PandocMonad m => ParserT Text ParserState m Blocks+header :: PandocMonad m => TextileParser m Blocks header = try $ do char 'h' level <- digitToInt <$> oneOf "123456"@@ -186,14 +190,14 @@ return $ B.headerWith attr' level name -- | Blockquote of the form "bq. content"-blockQuote :: PandocMonad m => ParserT Text ParserState m Blocks+blockQuote :: PandocMonad m => TextileParser m Blocks blockQuote = try $ do string "bq" >> attributes >> char '.' >> whitespace B.blockQuote <$> para -- Horizontal rule -hrule :: PandocMonad m => ParserT Text st m Blocks+hrule :: PandocMonad m => TextileParser m Blocks hrule = try $ do skipSpaces start <- oneOf "-*"@@ -208,39 +212,39 @@ -- | Can be a bullet list or an ordered list. This implementation is -- strict in the nesting, sublist must start at exactly "parent depth -- plus one"-anyList :: PandocMonad m => ParserT Text ParserState m Blocks+anyList :: PandocMonad m => TextileParser m Blocks anyList = try $ anyListAtDepth 1 <* blanklines -- | This allow one type of list to be nested into an other type, -- provided correct nesting-anyListAtDepth :: PandocMonad m => Int -> ParserT Text ParserState m Blocks+anyListAtDepth :: PandocMonad m => Int -> TextileParser m Blocks anyListAtDepth depth = choice [ bulletListAtDepth depth, orderedListAtDepth depth, definitionList ] -- | Bullet List of given depth, depth being the number of leading '*'-bulletListAtDepth :: PandocMonad m => Int -> ParserT Text ParserState m Blocks+bulletListAtDepth :: PandocMonad m => Int -> TextileParser m Blocks bulletListAtDepth depth = try $ B.bulletList <$> many1 (bulletListItemAtDepth depth) -- | Bullet List Item of given depth, depth being the number of -- leading '*'-bulletListItemAtDepth :: PandocMonad m => Int -> ParserT Text ParserState m Blocks+bulletListItemAtDepth :: PandocMonad m => Int -> TextileParser m Blocks bulletListItemAtDepth = genericListItemAtDepth '*' -- | Ordered List of given depth, depth being the number of -- leading '#'-orderedListAtDepth :: PandocMonad m => Int -> ParserT Text ParserState m Blocks+orderedListAtDepth :: PandocMonad m => Int -> TextileParser m Blocks orderedListAtDepth depth = try $ do items <- many1 (orderedListItemAtDepth depth) return $ B.orderedList items -- | Ordered List Item of given depth, depth being the number of -- leading '#'-orderedListItemAtDepth :: PandocMonad m => Int -> ParserT Text ParserState m Blocks+orderedListItemAtDepth :: PandocMonad m => Int -> TextileParser m Blocks orderedListItemAtDepth = genericListItemAtDepth '#' -- | Common implementation of list items-genericListItemAtDepth :: PandocMonad m => Char -> Int -> ParserT Text ParserState m Blocks+genericListItemAtDepth :: PandocMonad m => Char -> Int -> TextileParser m Blocks genericListItemAtDepth c depth = try $ do count depth (char c) >> attributes >> whitespace contents <- mconcat <$> many ((B.plain . mconcat <$> many1 inline) <|>@@ -250,25 +254,25 @@ return $ contents <> sublist -- | A definition list is a set of consecutive definition items-definitionList :: PandocMonad m => ParserT Text ParserState m Blocks+definitionList :: PandocMonad m => TextileParser m Blocks definitionList = try $ B.definitionList <$> many1 definitionListItem -- | List start character.-listStart :: PandocMonad m => ParserT Text ParserState m ()+listStart :: PandocMonad m => TextileParser m () listStart = genericListStart '*' <|> () <$ genericListStart '#' <|> () <$ definitionListStart -genericListStart :: PandocMonad m => Char -> ParserT Text st m ()+genericListStart :: PandocMonad m => Char -> TextileParser m () genericListStart c = () <$ try (many1 (char c) >> whitespace) -basicDLStart :: PandocMonad m => ParserT Text ParserState m ()+basicDLStart :: PandocMonad m => TextileParser m () basicDLStart = do char '-' whitespace notFollowedBy newline -definitionListStart :: PandocMonad m => ParserT Text ParserState m Inlines+definitionListStart :: PandocMonad m => TextileParser m Inlines definitionListStart = try $ do basicDLStart trimInlines . mconcat <$>@@ -281,15 +285,15 @@ -- the term defined, then spaces and ":=". The definition follows, on -- the same single line, or spaned on multiple line, after a line -- break.-definitionListItem :: PandocMonad m => ParserT Text ParserState m (Inlines, [Blocks])+definitionListItem :: PandocMonad m => TextileParser m (Inlines, [Blocks]) definitionListItem = try $ do term <- mconcat . intersperse B.linebreak <$> many1 definitionListStart def' <- string ":=" *> optional whitespace *> (multilineDef <|> inlineDef) return (term, def')- where inlineDef :: PandocMonad m => ParserT Text ParserState m [Blocks]+ where inlineDef :: PandocMonad m => TextileParser m [Blocks] inlineDef = liftM (\d -> [B.plain d]) $ optional whitespace >> (trimInlines . mconcat <$> many inline) <* newline- multilineDef :: PandocMonad m => ParserT Text ParserState m [Blocks]+ multilineDef :: PandocMonad m => TextileParser m [Blocks] multilineDef = try $ do optional whitespace >> newline s <- T.pack <$> many1Till anyChar (try (string "=:" >> newline))@@ -300,7 +304,7 @@ -- raw content -- | A raw Html Block, optionally followed by blanklines-rawHtmlBlock :: PandocMonad m => ParserT Text ParserState m Blocks+rawHtmlBlock :: PandocMonad m => TextileParser m Blocks rawHtmlBlock = try $ do skipMany spaceChar (_,b) <- htmlTag isBlockTag@@ -308,14 +312,14 @@ return $ B.rawBlock "html" b -- | Raw block of LaTeX content-rawLaTeXBlock' :: PandocMonad m => ParserT Text ParserState m Blocks+rawLaTeXBlock' :: PandocMonad m => TextileParser m Blocks rawLaTeXBlock' = do guardEnabled Ext_raw_tex B.rawBlock "latex" <$> (rawLaTeXBlock <* spaces) -- | In textile, paragraphs are separated by blank lines.-para :: PandocMonad m => ParserT Text ParserState m Blocks+para :: PandocMonad m => TextileParser m Blocks para = B.para . trimInlines . mconcat <$> many1 inline -- Tables@@ -326,7 +330,7 @@ toAlignment '=' = AlignCenter toAlignment _ = AlignDefault -cellAttributes :: PandocMonad m => ParserT Text ParserState m (Bool, Alignment)+cellAttributes :: PandocMonad m => TextileParser m (Bool, Alignment) cellAttributes = try $ do isHeader <- option False (True <$ char '_') -- we just ignore colspan and rowspan markers:@@ -339,7 +343,7 @@ return (isHeader, alignment) -- | A table cell spans until a pipe |-tableCell :: PandocMonad m => ParserT Text ParserState m ((Bool, Alignment), Blocks)+tableCell :: PandocMonad m => TextileParser m ((Bool, Alignment), Blocks) tableCell = try $ do char '|' (isHeader, alignment) <- option (False, AlignDefault) cellAttributes@@ -350,7 +354,7 @@ return ((isHeader, alignment), B.plain content) -- | A table row is made of many table cells-tableRow :: PandocMonad m => ParserT Text ParserState m [((Bool, Alignment), Blocks)]+tableRow :: PandocMonad m => TextileParser m [((Bool, Alignment), Blocks)] tableRow = try $ do -- skip optional row attributes optional $ try $ do@@ -360,7 +364,7 @@ many1 tableCell <* char '|' <* blankline -- | A table with an optional header.-table :: PandocMonad m => ParserT Text ParserState m Blocks+table :: PandocMonad m => TextileParser m Blocks table = try $ do -- ignore table attributes caption <- option mempty $ try $ do@@ -388,7 +392,7 @@ (TableFoot nullAttr []) -- | Ignore markers for cols, thead, tfoot.-ignorableRow :: PandocMonad m => ParserT Text ParserState m ()+ignorableRow :: PandocMonad m => TextileParser m () ignorableRow = try $ do char '|' oneOf ":^-~"@@ -397,7 +401,7 @@ _ <- anyLine return () -explicitBlockStart :: PandocMonad m => Text -> ParserT Text ParserState m ()+explicitBlockStart :: PandocMonad m => Text -> TextileParser m () explicitBlockStart name = try $ do string (T.unpack name) attributes@@ -409,8 +413,8 @@ -- However, they can be used to set HTML/CSS attributes when needed. maybeExplicitBlock :: PandocMonad m => Text -- ^ block tag name- -> ParserT Text ParserState m Blocks -- ^ implicit block- -> ParserT Text ParserState m Blocks+ -> TextileParser m Blocks -- ^ implicit block+ -> TextileParser m Blocks maybeExplicitBlock name blk = try $ do optional $ explicitBlockStart name blk@@ -423,11 +427,11 @@ -- | Any inline element-inline :: PandocMonad m => ParserT Text ParserState m Inlines+inline :: PandocMonad m => TextileParser m Inlines inline = choice inlineParsers <?> "inline" -- | Inline parsers tried in order-inlineParsers :: PandocMonad m => [ParserT Text ParserState m Inlines]+inlineParsers :: PandocMonad m => [TextileParser m Inlines] inlineParsers = [ str , whitespace , endline@@ -447,7 +451,7 @@ ] -- | Inline markups-inlineMarkup :: PandocMonad m => ParserT Text ParserState m Inlines+inlineMarkup :: PandocMonad m => TextileParser m Inlines inlineMarkup = choice [ simpleInline (string "??") (B.cite []) , simpleInline (string "**") B.strong , simpleInline (string "__") B.emph@@ -461,29 +465,29 @@ ] -- | Trademark, registered, copyright-mark :: PandocMonad m => ParserT Text st m Inlines+mark :: PandocMonad m => TextileParser m Inlines mark = try $ char '(' >> (try tm <|> try reg <|> copy) -reg :: PandocMonad m => ParserT Text st m Inlines+reg :: PandocMonad m => TextileParser m Inlines reg = do oneOf "Rr" char ')' return $ B.str "\174" -tm :: PandocMonad m => ParserT Text st m Inlines+tm :: PandocMonad m => TextileParser m Inlines tm = do oneOf "Tt" oneOf "Mm" char ')' return $ B.str "\8482" -copy :: PandocMonad m => ParserT Text st m Inlines+copy :: PandocMonad m => TextileParser m Inlines copy = do oneOf "Cc" char ')' return $ B.str "\169" -note :: PandocMonad m => ParserT Text ParserState m Inlines+note :: PandocMonad m => TextileParser m Inlines note = try $ do ref <- char '[' *> many1 digit <* char ']' notes <- stateNotes <$> getState@@ -507,13 +511,13 @@ wordBoundaries = markupChars <> stringBreakers -- | Parse a hyphened sequence of words-hyphenedWords :: PandocMonad m => ParserT Text ParserState m Text+hyphenedWords :: PandocMonad m => TextileParser m Text hyphenedWords = do x <- wordChunk xs <- many (try $ char '-' >> wordChunk) return $ T.intercalate "-" (x:xs) -wordChunk :: PandocMonad m => ParserT Text ParserState m Text+wordChunk :: PandocMonad m => TextileParser m Text wordChunk = try $ do hd <- noneOf wordBoundaries tl <- many ( noneOf wordBoundaries <|>@@ -522,7 +526,7 @@ return $ T.pack $ hd:tl -- | Any string-str :: PandocMonad m => ParserT Text ParserState m Inlines+str :: PandocMonad m => TextileParser m Inlines str = do baseStr <- hyphenedWords -- RedCloth compliance : if parsed word is uppercase and immediately@@ -535,11 +539,11 @@ return $ B.str fullStr -- | Some number of space chars-whitespace :: PandocMonad m => ParserT Text st m Inlines+whitespace :: PandocMonad m => TextileParser m Inlines whitespace = many1 spaceChar >> return B.space <?> "whitespace" -- | In Textile, an isolated endline character is a line break-endline :: PandocMonad m => ParserT Text ParserState m Inlines+endline :: PandocMonad m => TextileParser m Inlines endline = try $ do newline notFollowedBy blankline@@ -547,18 +551,18 @@ notFollowedBy rawHtmlBlock return B.linebreak -rawHtmlInline :: PandocMonad m => ParserT Text ParserState m Inlines+rawHtmlInline :: PandocMonad m => TextileParser m Inlines rawHtmlInline = B.rawInline "html" . snd <$> htmlTag isInlineTag -- | Raw LaTeX Inline-rawLaTeXInline' :: PandocMonad m => ParserT Text ParserState m Inlines+rawLaTeXInline' :: PandocMonad m => TextileParser m Inlines rawLaTeXInline' = try $ do guardEnabled Ext_raw_tex B.rawInline "latex" <$> rawLaTeXInline -- | Textile standard link syntax is "label":target. But we -- can also have ["label":target].-link :: PandocMonad m => ParserT Text ParserState m Inlines+link :: PandocMonad m => TextileParser m Inlines link = try $ do bracketed <- (True <$ char '[') <|> return False char '"' *> notFollowedBy (oneOf " \t\n\r")@@ -578,7 +582,7 @@ else B.spanWith attr $ B.link url "" name' -- | image embedding-image :: PandocMonad m => ParserT Text ParserState m Inlines+image :: PandocMonad m => TextileParser m Inlines image = try $ do char '!' >> notFollowedBy space (ident, cls, kvs) <- attributes@@ -590,51 +594,51 @@ char '!' return $ B.imageWith attr src alt (B.str alt) -escapedInline :: PandocMonad m => ParserT Text ParserState m Inlines+escapedInline :: PandocMonad m => TextileParser m Inlines escapedInline = escapedEqs <|> escapedTag -escapedEqs :: PandocMonad m => ParserT Text ParserState m Inlines+escapedEqs :: PandocMonad m => TextileParser m Inlines escapedEqs = B.str . T.pack <$> try (string "==" *> manyTill anyChar' (try $ string "==")) -- | literal text escaped btw <notextile> tags-escapedTag :: PandocMonad m => ParserT Text ParserState m Inlines+escapedTag :: PandocMonad m => TextileParser m Inlines escapedTag = B.str . T.pack <$> try (string "<notextile>" *> manyTill anyChar' (try $ string "</notextile>")) -- | Any special symbol defined in wordBoundaries-symbol :: PandocMonad m => ParserT Text ParserState m Inlines+symbol :: PandocMonad m => TextileParser m Inlines symbol = B.str . T.singleton <$> (notFollowedBy newline *> notFollowedBy rawHtmlBlock *> oneOf wordBoundaries) -- | Inline code-code :: PandocMonad m => ParserT Text ParserState m Inlines+code :: PandocMonad m => TextileParser m Inlines code = code1 <|> code2 -- any character except a newline before a blank line-anyChar' :: PandocMonad m => ParserT Text ParserState m Char+anyChar' :: PandocMonad m => TextileParser m Char anyChar' = satisfy (/='\n') <|> try (char '\n' <* notFollowedBy blankline) -code1 :: PandocMonad m => ParserT Text ParserState m Inlines+code1 :: PandocMonad m => TextileParser m Inlines code1 = B.code . T.pack <$> surrounded (char '@') anyChar' -code2 :: PandocMonad m => ParserT Text ParserState m Inlines+code2 :: PandocMonad m => TextileParser m Inlines code2 = do htmlTag (tagOpen (=="tt") null) B.code . T.pack <$> manyTill anyChar' (try $ htmlTag $ tagClose (=="tt")) -- | Html / CSS attributes-attributes :: PandocMonad m => ParserT Text ParserState m Attr+attributes :: PandocMonad m => TextileParser m Attr attributes = foldl' (flip ($)) ("",[],[]) <$> try (do special <- option id specialAttribute attrs <- many attribute return (special : attrs)) -specialAttribute :: PandocMonad m => ParserT Text ParserState m (Attr -> Attr)+specialAttribute :: PandocMonad m => TextileParser m (Attr -> Attr) specialAttribute = do alignStr <- ("center" <$ char '=') <|> ("justify" <$ try (string "<>")) <|>@@ -643,11 +647,11 @@ notFollowedBy spaceChar return $ addStyle $ T.pack $ "text-align:" ++ alignStr -attribute :: PandocMonad m => ParserT Text ParserState m (Attr -> Attr)+attribute :: PandocMonad m => TextileParser m (Attr -> Attr) attribute = try $ (classIdAttr <|> styleAttr <|> langAttr) <* notFollowedBy spaceChar -classIdAttr :: PandocMonad m => ParserT Text ParserState m (Attr -> Attr)+classIdAttr :: PandocMonad m => TextileParser m (Attr -> Attr) classIdAttr = try $ do -- (class class #id) char '(' ws <- T.words `fmap` T.pack <$> manyTill anyChar' (char ')')@@ -659,7 +663,7 @@ classes' -> return $ \(_,_,keyvals) -> ("",classes',keyvals) -styleAttr :: PandocMonad m => ParserT Text ParserState m (Attr -> Attr)+styleAttr :: PandocMonad m => TextileParser m (Attr -> Attr) styleAttr = do style <- try $ enclosed (char '{') (char '}') anyChar' return $ addStyle $ T.pack style@@ -670,23 +674,23 @@ where keyvals' = ("style", style') : [(k,v) | (k,v) <- keyvals, k /= "style"] style' = style <> ";" <> T.concat [v | ("style",v) <- keyvals] -langAttr :: PandocMonad m => ParserT Text ParserState m (Attr -> Attr)+langAttr :: PandocMonad m => TextileParser m (Attr -> Attr) langAttr = do lang <- try $ enclosed (char '[') (char ']') alphaNum return $ \(id',classes,keyvals) -> (id',classes,("lang",T.pack lang):keyvals) -- | Parses material surrounded by a parser. surrounded :: (PandocMonad m, Show t)- => ParserT Text st m t -- ^ surrounding parser- -> ParserT Text st m a -- ^ content parser (to be used repeatedly)- -> ParserT Text st m [a]+ => ParserT Sources st m t -- ^ surrounding parser+ -> ParserT Sources st m a -- ^ content parser (to be used repeatedly)+ -> ParserT Sources st m [a] surrounded border = enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border) simpleInline :: PandocMonad m- => ParserT Text ParserState m t -- ^ surrounding parser+ => TextileParser m t -- ^ surrounding parser -> (Inlines -> Inlines) -- ^ Inline constructor- -> ParserT Text ParserState m Inlines -- ^ content parser (to be used repeatedly)+ -> TextileParser m Inlines -- ^ content parser (to be used repeatedly) simpleInline border construct = try $ do notAfterString border *> notFollowedBy (oneOf " \t\n\r")@@ -700,7 +704,7 @@ then body else B.spanWith attr body -groupedInlineMarkup :: PandocMonad m => ParserT Text ParserState m Inlines+groupedInlineMarkup :: PandocMonad m => TextileParser m Inlines groupedInlineMarkup = try $ do char '[' sp1 <- option mempty $ B.space <$ whitespace@@ -709,5 +713,5 @@ char ']' return $ sp1 <> result <> sp2 -eof' :: Monad m => ParserT Text s m Char+eof' :: Monad m => ParserT Sources s m Char eof' = '\n' <$ eof
@@ -30,23 +30,23 @@ import Text.Pandoc.Logging (Verbosity (..)) import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (enclosed, nested)-import Text.Pandoc.Shared (crFilter, safeRead)+import Text.Pandoc.Shared (safeRead) import Text.Pandoc.XML (fromEntities) import Text.Printf (printf) -- | Read TikiWiki from an input string and return a Pandoc document.-readTikiWiki :: PandocMonad m+readTikiWiki :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc readTikiWiki opts s = do- res <- readWithM parseTikiWiki def{ stateOptions = opts }- (crFilter s <> "\n\n")+ let sources = ensureFinalNewlines 2 (toSources s)+ res <- readWithM parseTikiWiki def{ stateOptions = opts } sources case res of Left e -> throwError e Right d -> return d -type TikiWikiParser = ParserT Text ParserState+type TikiWikiParser = ParserT Sources ParserState -- -- utility functions
@@ -33,9 +33,9 @@ import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (space, spaces, uri)-import Text.Pandoc.Shared (compactify, compactifyDL, crFilter, escapeURI)+import Text.Pandoc.Shared (compactify, compactifyDL, escapeURI) -type T2T = ParserT Text ParserState (Reader T2TMeta)+type T2T = ParserT Sources ParserState (Reader T2TMeta) -- | An object for the T2T macros meta information -- the contents of each field is simply substituted verbatim into the file@@ -68,15 +68,15 @@ (intercalate ", " inps) outp -- | Read Txt2Tags from an input string returning a Pandoc document-readTxt2Tags :: PandocMonad m+readTxt2Tags :: (PandocMonad m, ToSources a) => ReaderOptions- -> Text+ -> a -> m Pandoc readTxt2Tags opts s = do+ let sources = ensureFinalNewlines 2 (toSources s) meta <- getT2TMeta let parsed = flip runReader meta $- readWithM parseT2T (def {stateOptions = opts}) $- crFilter s <> "\n\n"+ readWithM parseT2T (def {stateOptions = opts}) sources case parsed of Right result -> return result Left e -> throwError e
@@ -74,23 +74,28 @@ many1Till, orderedListMarker, readWithM, registerHeader, spaceChar, stateMeta, stateOptions, uri, manyTillChar, manyChar, textStr,- many1Char, countChar, many1TillChar)-import Text.Pandoc.Shared (crFilter, splitTextBy, stringify, stripFirstAndLast,+ many1Char, countChar, many1TillChar,+ alphaNum, anyChar, char, newline, noneOf, oneOf,+ space, spaces, string)+import Text.Pandoc.Sources (ToSources(..), Sources)+import Text.Pandoc.Shared (splitTextBy, stringify, stripFirstAndLast, isURI, tshow)-import Text.Parsec.Char (alphaNum, anyChar, char, newline, noneOf, oneOf, space,- spaces, string) import Text.Parsec.Combinator (between, choice, eof, lookAhead, many1, manyTill, notFollowedBy, option, skipMany1) import Text.Parsec.Prim (getState, many, try, updateState, (<|>)) -readVimwiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readVimwiki :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc readVimwiki opts s = do- res <- readWithM parseVimwiki def{ stateOptions = opts } $ crFilter s+ let sources = toSources s+ res <- readWithM parseVimwiki def{ stateOptions = opts } sources case res of Left e -> throwError e Right result -> return result -type VwParser = ParserT Text ParserState+type VwParser = ParserT Sources ParserState -- constants
@@ -16,7 +16,6 @@ module Text.Pandoc.SelfContained ( makeDataURI, makeSelfContained ) where import Codec.Compression.GZip as Gzip import Control.Applicative ((<|>))-import Control.Monad.Except (throwError) import Control.Monad.Trans (lift) import Data.ByteString (ByteString) import Data.ByteString.Base64@@ -29,7 +28,6 @@ import Text.HTML.TagSoup import Text.Pandoc.Class.PandocMonad (PandocMonad (..), fetchItem, getInputFiles, report, setInputFiles)-import Text.Pandoc.Error import Text.Pandoc.Logging import Text.Pandoc.MIME (MimeType) import Text.Pandoc.Shared (isURI, renderTags', trim)@@ -244,11 +242,10 @@ let raw' = if ext `elem` [".gz", ".svgz"] then B.concat $ L.toChunks $ Gzip.decompress $ L.fromChunks [raw] else raw- mime <- case (mimetype, respMime) of- ("",Nothing) -> throwError $ PandocSomeError- $ "Could not determine mime type for `" <> src <> "'"- (x, Nothing) -> return x- (_, Just x ) -> return x+ let mime = case (mimetype, respMime) of+ ("",Nothing) -> "application/octet-stream"+ (x, Nothing) -> x+ (_, Just x ) -> x result <- if "text/css" `T.isPrefixOf` mime then do oldInputs <- getInputFiles
@@ -123,7 +123,7 @@ import Text.Pandoc.Builder (Blocks, Inlines, ToMetaValue (..)) import qualified Text.Pandoc.Builder as B import Data.Time-import Text.Pandoc.Asciify (toAsciiChar)+import Text.Pandoc.Asciify (toAsciiText) import Text.Pandoc.Definition import Text.Pandoc.Extensions (Extensions, Extension(..), extensionEnabled) import Text.Pandoc.Generic (bottomUp)@@ -153,13 +153,21 @@ in first : splitTextBy isSep (T.dropWhile isSep rest) splitTextByIndices :: [Int] -> T.Text -> [T.Text]-splitTextByIndices ns = splitTextByRelIndices (zipWith (-) ns (0:ns))+splitTextByIndices ns = splitTextByRelIndices (zipWith (-) ns (0:ns)) . T.unpack where- splitTextByRelIndices [] t = [t]- splitTextByRelIndices (x:xs) t =- let (first, rest) = T.splitAt x t- in first : splitTextByRelIndices xs rest+ splitTextByRelIndices [] cs = [T.pack cs]+ splitTextByRelIndices (x:xs) cs =+ let (first, rest) = splitAt' x cs+ in T.pack first : splitTextByRelIndices xs rest +-- Note: don't replace this with T.splitAt, which is not sensitive+-- to character widths!+splitAt' :: Int -> [Char] -> ([Char],[Char])+splitAt' _ [] = ([],[])+splitAt' n xs | n <= 0 = ([],xs)+splitAt' n (x:xs) = (x:ys,zs)+ where (ys,zs) = splitAt' (n - charWidth x) xs+ ordNub :: (Ord a) => [a] -> [a] ordNub l = go Set.empty l where@@ -290,6 +298,7 @@ (tabStop - (T.length s1 `mod` tabStop)) (T.pack " ") <> 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')@@ -478,7 +487,7 @@ | otherwise = T.dropWhile (not . isAlpha) filterAscii | extensionEnabled Ext_ascii_identifiers exts- = T.pack . mapMaybe toAsciiChar . T.unpack+ = toAsciiText | otherwise = id toIdent | extensionEnabled Ext_gfm_auto_identifiers exts =@@ -843,7 +852,6 @@ where fileAndBinary :: Archive -> FilePath -> Maybe (FilePath, BL.ByteString) fileAndBinary a fp = findEntryByPath fp a >>= \e -> Just (fp, fromEntry e)- -- -- IANA URIs
@@ -0,0 +1,195 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Sources+ Copyright : Copyright (C) 2021 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Defines Sources object to be used as input to pandoc parsers and redefines Char+parsers so they get source position information from it.+-}++module Text.Pandoc.Sources+ ( Sources(..)+ , ToSources(..)+ , UpdateSourcePos(..)+ , sourcesToText+ , initialSourceName+ , addToSources+ , ensureFinalNewlines+ , addToInput+ , satisfy+ , oneOf+ , noneOf+ , anyChar+ , char+ , string+ , newline+ , space+ , spaces+ , letter+ , digit+ , hexDigit+ , alphaNum+ )+where+import qualified Text.Parsec as P+import Text.Parsec (Stream(..), ParsecT)+import Text.Parsec.Pos as P+import Data.Text (Text)+import qualified Data.Text as T+import Data.Char (isSpace, isLetter, isAlphaNum, isDigit, isHexDigit)+import Data.String (IsString(..))+import qualified Data.List.NonEmpty as NonEmpty++-- | A list of inputs labeled with source positions. It is assumed+-- that the 'Text's have @\n@ line endings.+newtype Sources = Sources { unSources :: [(SourcePos, Text)] }+ deriving (Show, Semigroup, Monoid)++instance Monad m => Stream Sources m Char where+ uncons (Sources []) = return Nothing+ uncons (Sources ((pos,t):rest)) =+ case T.uncons t of+ Nothing -> uncons (Sources rest)+ Just (c,t') -> return $ Just (c, Sources ((pos,t'):rest))++instance IsString Sources where+ fromString s = Sources [(P.initialPos "", T.pack (filter (/='\r') s))]++class ToSources a where+ toSources :: a -> Sources++instance ToSources Text where+ toSources t = Sources [(P.initialPos "", T.filter (/='\r') t)]++instance ToSources [(FilePath, Text)] where+ toSources = Sources+ . map (\(fp,t) ->+ (P.initialPos fp, T.snoc (T.filter (/='\r') t) '\n'))++instance ToSources Sources where+ toSources = id++sourcesToText :: Sources -> Text+sourcesToText (Sources xs) = mconcat $ map snd xs++addToSources :: Monad m => SourcePos -> Text -> ParsecT Sources u m ()+addToSources pos t = do+ curpos <- P.getPosition+ Sources xs <- P.getInput+ let xs' = case xs of+ [] -> []+ ((_,t'):rest) -> (curpos,t'):rest+ P.setInput $ Sources ((pos, T.filter (/='\r') t):xs')++ensureFinalNewlines :: Int -- ^ number of trailing newlines+ -> Sources+ -> Sources+ensureFinalNewlines n (Sources xs) =+ case NonEmpty.nonEmpty xs of+ Nothing -> Sources [(initialPos "", T.replicate n "\n")]+ Just lst ->+ case NonEmpty.last lst of+ (spos, t) ->+ case T.length (T.takeWhileEnd (=='\n') t) of+ len | len >= n -> Sources xs+ | otherwise -> Sources (NonEmpty.init lst +++ [(spos,+ t <> T.replicate (n - len) "\n")])++class UpdateSourcePos s c where+ updateSourcePos :: SourcePos -> c -> s -> SourcePos++instance UpdateSourcePos Text Char where+ updateSourcePos pos c _ = updatePosChar pos c++instance UpdateSourcePos Sources Char where+ updateSourcePos pos c sources =+ case sources of+ Sources [] -> updatePosChar pos c+ Sources ((_,t):(pos',_):_)+ | T.null t -> pos'+ Sources _ ->+ case c of+ '\n' -> incSourceLine (setSourceColumn pos 1) 1+ '\t' -> incSourceColumn pos (4 - ((sourceColumn pos - 1) `mod` 4))+ _ -> incSourceColumn pos 1++-- | Get name of first source in 'Sources'.+initialSourceName :: Sources -> FilePath+initialSourceName (Sources []) = ""+initialSourceName (Sources ((pos,_):_)) = sourceName pos++-- | Add some text to the beginning of the input sources.+-- This simplifies code that expands macros.+addToInput :: Monad m => Text -> ParsecT Sources u m ()+addToInput t = do+ Sources xs <- P.getInput+ case xs of+ [] -> P.setInput $ Sources [(initialPos "",t)]+ (pos,t'):rest -> P.setInput $ Sources ((pos, t <> t'):rest)++-- We need to redefine the parsers in Text.Parsec.Char so that they+-- update source positions properly from the Sources stream.++satisfy :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => (Char -> Bool) -> ParsecT s u m Char+satisfy f = P.tokenPrim show updateSourcePos matcher+ where+ matcher c = if f c then Just c else Nothing++oneOf :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => [Char] -> ParsecT s u m Char+oneOf cs = satisfy (`elem` cs)++noneOf :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => [Char] -> ParsecT s u m Char+noneOf cs = satisfy (`notElem` cs)++anyChar :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+anyChar = satisfy (const True)++char :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => Char -> ParsecT s u m Char+char c = satisfy (== c)++string :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => [Char] -> ParsecT s u m [Char]+string = mapM char++newline :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+newline = satisfy (== '\n')++space :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+space = satisfy isSpace++spaces :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m ()+spaces = P.skipMany space P.<?> "white space"++letter :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+letter = satisfy isLetter++alphaNum :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+alphaNum = satisfy isAlphaNum++digit :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+digit = satisfy isDigit++hexDigit :: (Monad m, Stream s m Char, UpdateSourcePos s Char)+ => ParsecT s u m Char+hexDigit = satisfy isHexDigit
@@ -81,6 +81,7 @@ 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.Options@@ -122,7 +123,6 @@ import Text.Pandoc.Writers.Textile import Text.Pandoc.Writers.XWiki import Text.Pandoc.Writers.ZimWiki-import Text.Parsec.Error data Writer m = TextWriter (WriterOptions -> Pandoc -> m Text) | ByteStringWriter (WriterOptions -> Pandoc -> m BL.ByteString)@@ -196,8 +196,8 @@ getWriter :: PandocMonad m => Text -> m (Writer m, Extensions) getWriter s = case parseFormatSpec s of- Left e -> throwError $ PandocAppError- $ T.intercalate "\n" [T.pack m | Message m <- errorMessages e]+ Left e -> throwError $ PandocAppError $+ "Error parsing writer format " <> tshow s <> ": " <> tshow e Right (writerName, extsToEnable, extsToDisable) -> case lookup writerName writers of Nothing -> throwError $
@@ -43,7 +43,7 @@ writeBibTeX' variant opts (Pandoc meta _) = do let mblang = case lookupMetaString "lang" meta of "" -> Nothing- t -> Just $ parseLang t+ t -> either (const Nothing) Just $ parseLang t let refs = case lookupMeta "references" meta of Just (MetaList xs) -> mapMaybe metaValueToReference xs _ -> []
@@ -16,12 +16,11 @@ import Control.Monad.State.Strict import Data.Char (ord, isDigit) import Data.List (intersperse)-import Data.List.NonEmpty (nonEmpty) import Data.Maybe (mapMaybe) import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString)-import Text.Pandoc.BCP47+import Text.Collate.Lang (Lang(..)) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import Text.Pandoc.Definition import Text.Pandoc.ImageSize@@ -178,8 +177,12 @@ contents <- inlineListToConTeXt lst return $ contents <> blankline blockToConTeXt (LineBlock lns) = do- doclines <- nowrap . vcat <$> mapM inlineListToConTeXt lns- return $ "\\startlines" $$ doclines $$ "\\stoplines" <> blankline+ let emptyToBlankline doc = if isEmpty doc+ then blankline+ else doc+ doclines <- mapM inlineListToConTeXt lns+ let contextLines = vcat . map emptyToBlankline $ doclines+ return $ "\\startlines" $$ contextLines $$ "\\stoplines" <> blankline blockToConTeXt (BlockQuote lst) = do contents <- blockListToConTeXt lst return $ "\\startblockquote" $$ nest 0 contents $$ "\\stopblockquote" <> blankline@@ -229,14 +232,7 @@ Period -> "stopper=." OneParen -> "stopper=)" TwoParens -> "left=(,stopper=)"- let width = maybe 0 maximum $ nonEmpty $ map T.length $- take (length contents)- (orderedListMarkers (start, style', delim))- let width' = (toEnum width + 1) / 2- let width'' = if width' > (1.5 :: Double)- then "width=" <> tshow width' <> "em"- else ""- let specs2Items = filter (not . T.null) [start', delim', width'']+ let specs2Items = filter (not . T.null) [start', delim'] let specs2 = if null specs2Items then "" else "[" <> T.intercalate "," specs2Items <> "]"@@ -250,8 +246,8 @@ UpperAlpha -> 'A') : if isTightList lst then ",packed]" else "]" let specs = T.pack style'' <> specs2- return $ "\\startitemize" <> literal specs $$ vcat contents $$- "\\stopitemize" <> blankline+ return $ "\\startenumerate" <> literal specs $$ vcat contents $$+ "\\stopenumerate" <> blankline blockToConTeXt (DefinitionList lst) = liftM vcat $ mapM defListItemToConTeXt lst blockToConTeXt HorizontalRule = return $ "\\thinrule" <> blankline@@ -483,7 +479,7 @@ then literal "\\footnote{" <> nest 2 (chomp contents') <> char '}' else literal "\\startbuffer " <> nest 2 (chomp contents') <> literal "\\stopbuffer\\footnote{\\getbuffer}"-inlineToConTeXt (Span (_,_,kvs) ils) = do+inlineToConTeXt (Span (ident,_,kvs) ils) = do mblang <- fromBCP47 (lookup "lang" kvs) let wrapDir txt = case lookup "dir" kvs of Just "rtl" -> braces $ "\\righttoleft " <> txt@@ -493,7 +489,11 @@ Just lng -> braces ("\\language" <> brackets (literal lng) <> txt) Nothing -> txt- wrapLang . wrapDir <$> inlineListToConTeXt ils+ addReference =+ if T.null ident+ then id+ else (("\\reference" <> brackets (literal ident) <> "{}") <>)+ addReference . wrapLang . wrapDir <$> inlineListToConTeXt ils -- | Craft the section header, inserting the section reference, if supplied. sectionHeader :: PandocMonad m@@ -555,26 +555,26 @@ -- https://tools.ietf.org/html/bcp47#section-2.1 -- http://wiki.contextgarden.net/Language_Codes fromBCP47' :: Maybe Lang -> Maybe Text-fromBCP47' (Just (Lang "ar" _ "SY" _) ) = Just "ar-sy"-fromBCP47' (Just (Lang "ar" _ "IQ" _) ) = Just "ar-iq"-fromBCP47' (Just (Lang "ar" _ "JO" _) ) = Just "ar-jo"-fromBCP47' (Just (Lang "ar" _ "LB" _) ) = Just "ar-lb"-fromBCP47' (Just (Lang "ar" _ "DZ" _) ) = Just "ar-dz"-fromBCP47' (Just (Lang "ar" _ "MA" _) ) = Just "ar-ma"-fromBCP47' (Just (Lang "de" _ _ ["1901"]) ) = Just "deo"-fromBCP47' (Just (Lang "de" _ "DE" _) ) = Just "de-de"-fromBCP47' (Just (Lang "de" _ "AT" _) ) = Just "de-at"-fromBCP47' (Just (Lang "de" _ "CH" _) ) = Just "de-ch"-fromBCP47' (Just (Lang "el" _ _ ["poly"]) ) = Just "agr"-fromBCP47' (Just (Lang "en" _ "US" _) ) = Just "en-us"-fromBCP47' (Just (Lang "en" _ "GB" _) ) = Just "en-gb"-fromBCP47' (Just (Lang "grc"_ _ _) ) = Just "agr"-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"-fromBCP47' (Just (Lang l _ _ _) ) = Just l-fromBCP47' Nothing = Nothing+fromBCP47' (Just (Lang "ar" _ (Just "SY") _ _ _)) = Just "ar-sy"+fromBCP47' (Just (Lang "ar" _ (Just "IQ") _ _ _)) = Just "ar-iq"+fromBCP47' (Just (Lang "ar" _ (Just "JO") _ _ _)) = Just "ar-jo"+fromBCP47' (Just (Lang "ar" _ (Just "LB") _ _ _)) = Just "ar-lb"+fromBCP47' (Just (Lang "ar" _ (Just "DZ") _ _ _)) = Just "ar-dz"+fromBCP47' (Just (Lang "ar" _ (Just "MA") _ _ _)) = Just "ar-ma"+fromBCP47' (Just (Lang "de" _ _ ["1901"] _ _)) = Just "deo"+fromBCP47' (Just (Lang "de" _ (Just "DE") _ _ _)) = Just "de-de"+fromBCP47' (Just (Lang "de" _ (Just "AT") _ _ _)) = Just "de-at"+fromBCP47' (Just (Lang "de" _ (Just "CH") _ _ _)) = Just "de-ch"+fromBCP47' (Just (Lang "el" _ _ ["poly"] _ _)) = Just "agr"+fromBCP47' (Just (Lang "en" _ (Just "US") _ _ _)) = Just "en-us"+fromBCP47' (Just (Lang "en" _ (Just "GB") _ _ _)) = Just "en-gb"+fromBCP47' (Just (Lang "grc"_ _ _ _ _)) = Just "agr"+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"+fromBCP47' (Just (Lang l _ _ _ _ _)) = Just l+fromBCP47' Nothing = Nothing
@@ -34,15 +34,16 @@ import Citeproc.Locale (getLocale) import Citeproc.CslJson import Text.Pandoc.Options (WriterOptions)-import Data.Maybe (mapMaybe)+import Data.Maybe (mapMaybe, fromMaybe) import Data.Aeson.Encode.Pretty (Config (..), Indent (Spaces), NumberFormat (Generic), defConfig, encodePretty') writeCslJson :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeCslJson _opts (Pandoc meta _) = do- let lang = maybe (Lang "en" (Just "US")) parseLang- (lookupMeta "lang" meta >>= metaValueToText)+ let lang = fromMaybe (Lang "en" Nothing (Just "US") [] [] [])+ (lookupMeta "lang" meta >>= metaValueToText >>=+ either (const Nothing) Just . parseLang) locale <- case getLocale lang of Left e -> throwError $ PandocCiteprocError e Right l -> return l
@@ -253,17 +253,18 @@ blockToDocbook opts $ linesToPara lns blockToDocbook opts (BlockQuote blocks) = inTagsIndented "blockquote" <$> blocksToDocbook opts blocks-blockToDocbook _ (CodeBlock (_,classes,_) str) = return $+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) <> "\""- isLang l = T.toLower l `elem` map T.toLower languages+ syntaxMap = writerSyntaxMap opts+ isLang l = T.toLower l `elem` map T.toLower (languages syntaxMap) langsFrom s = if isLang s then [s]- else languagesByExtension . T.toLower $ s+ else (languagesByExtension syntaxMap) . T.toLower $ s langs = concatMap langsFrom classes blockToDocbook opts (BulletList lst) = do let attribs = [("spacing", "compact") | isTightList lst]
@@ -22,7 +22,6 @@ import Control.Monad.Except (catchError, throwError) import Control.Monad.Reader import Control.Monad.State.Strict-import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import Data.Char (isSpace, isLetter) import Data.List (intercalate, isPrefixOf, isSuffixOf)@@ -36,7 +35,7 @@ import Data.Time.Clock.POSIX import Data.Digest.Pure.SHA (sha1, showDigest) import Skylighting-import Text.Pandoc.BCP47 (getLang, renderLang)+import Text.Collate.Lang (renderLang) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import qualified Text.Pandoc.Class.PandocMonad as P import Data.Time@@ -47,123 +46,25 @@ import Text.Pandoc.Error import Text.Pandoc.ImageSize import Text.Pandoc.Logging-import Text.Pandoc.MIME (MimeType, extensionFromMimeType, getMimeType,- getMimeTypeDef)+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.Printf (printf) import Text.TeXMath import Text.Pandoc.Writers.OOXML import Text.Pandoc.XML.Light as XML import Data.Generics (mkT, everywhere) -data ListMarker = NoMarker- | BulletMarker- | NumberMarker ListNumberStyle ListNumberDelim Int- deriving (Show, Read, Eq, Ord)--listMarkerToId :: ListMarker -> Text-listMarkerToId NoMarker = "990"-listMarkerToId BulletMarker = "991"-listMarkerToId (NumberMarker sty delim n) = T.pack $- '9' : '9' : styNum : delimNum : show n- where styNum = case sty of- DefaultStyle -> '2'- Example -> '3'- Decimal -> '4'- LowerRoman -> '5'- UpperRoman -> '6'- LowerAlpha -> '7'- UpperAlpha -> '8'- delimNum = case delim of- DefaultDelim -> '0'- Period -> '1'- OneParen -> '2'- TwoParens -> '3'--data EnvProps = EnvProps{ styleElement :: Maybe Element- , otherElements :: [Element]- }--instance Semigroup EnvProps where- EnvProps s es <> EnvProps s' es' = EnvProps (s <|> s') (es ++ es')--instance Monoid EnvProps where- mempty = EnvProps Nothing []- mappend = (<>)- squashProps :: EnvProps -> [Element] squashProps (EnvProps Nothing es) = es squashProps (EnvProps (Just e) es) = e : es -data WriterEnv = WriterEnv{ envTextProperties :: EnvProps- , envParaProperties :: EnvProps- , envRTL :: Bool- , envListLevel :: Int- , envListNumId :: Int- , envInDel :: Bool- , envChangesAuthor :: Text- , envChangesDate :: Text- , envPrintWidth :: Integer- }--defaultWriterEnv :: WriterEnv-defaultWriterEnv = WriterEnv{ envTextProperties = mempty- , envParaProperties = mempty- , envRTL = False- , envListLevel = -1- , envListNumId = 1- , envInDel = False- , envChangesAuthor = "unknown"- , envChangesDate = "1969-12-31T19:00:00Z"- , envPrintWidth = 1- }--data WriterState = WriterState{- stFootnotes :: [Element]- , stComments :: [([(Text, Text)], [Inline])]- , stSectionIds :: Set.Set Text- , stExternalLinks :: M.Map Text Text- , stImages :: M.Map FilePath (String, String, Maybe MimeType, B.ByteString)- , stLists :: [ListMarker]- , stInsId :: Int- , stDelId :: Int- , stStyleMaps :: StyleMaps- , stFirstPara :: Bool- , stInTable :: Bool- , stInList :: Bool- , stTocTitle :: [Inline]- , stDynamicParaProps :: Set.Set ParaStyleName- , stDynamicTextProps :: Set.Set CharStyleName- , stCurId :: Int- }--defaultWriterState :: WriterState-defaultWriterState = WriterState{- stFootnotes = defaultFootnotes- , stComments = []- , stSectionIds = Set.empty- , stExternalLinks = M.empty- , stImages = M.empty- , stLists = [NoMarker]- , stInsId = 1- , stDelId = 1- , stStyleMaps = StyleMaps M.empty M.empty- , stFirstPara = False- , stInTable = False- , stInList = False- , stTocTitle = [Str "Table of Contents"]- , stDynamicParaProps = Set.empty- , stDynamicTextProps = Set.empty- , stCurId = 20- }--type WS m = ReaderT WriterEnv (StateT WriterState m)- renumIdMap :: Int -> [Element] -> M.Map Text Text renumIdMap _ [] = M.empty renumIdMap n (e:es)@@ -568,12 +469,27 @@ -- 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 = [ "w:autoHyphenation"- , "w:consecutiveHyphenLimit"- , "w:hyphenationZone"- , "w:doNotHyphenateCap"- , "w:evenAndOddHeaders"- , "w:proofState"+ 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 @@ -676,16 +592,17 @@ 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 = elContent dist ++ copyContent ref+ elContent = map Elem elsToKeep ++ map Elem elsToCopy } where- strName QName{qName=name, qPrefix=prefix}- | Just p <- prefix = p <> ":" <> name- | otherwise = name- shouldCopy = (`elem` elNames) . strName- cleanElem el@Element{elName=name} = Elem el{elName=name{qURI=Nothing}}- copyContent = map cleanElem . filterChildrenName shouldCopy+ 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@@ -858,12 +775,6 @@ x : RawBlock (Format "openxml") "<w:p />" : separateTables xs separateTables (x:xs) = x : separateTables xs -pStyleM :: (PandocMonad m) => ParaStyleName -> WS m XML.Element-pStyleM styleName = do- pStyleMap <- gets (smParaStyle . stStyleMaps)- let sty' = getStyleIdFromName styleName pStyleMap- return $ mknode "w:pStyle" [("w:val", fromStyleId sty')] ()- rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element rStyleM styleName = do cStyleMap <- gets (smCharStyle . stStyleMaps)@@ -995,78 +906,9 @@ $ mknode "v:rect" [("style","width:0;height:1.5pt"), ("o:hralign","center"), ("o:hrstd","t"),("o:hr","t")] () ]-blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do- let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot- setFirstPara- modify $ \s -> s { stInTable = True }- let captionStr = stringify caption- caption' <- if null caption- then return []- else withParaPropM (pStyleM "Table Caption")- $ blockToOpenXML opts (Para caption)- let alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()- -- 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.- let cellToOpenXML (al, cell) = do- es <- withParaProp (alignmentFor al) $ blocksToOpenXML opts cell- return $- case reverse (onlyElems es) of- b:e:_ | qName (elName b) == "bookmarkEnd"- , qName (elName e) == "p" -> es- e:_ | qName (elName e) == "p" -> es- _ -> es ++ [Elem $ mknode "w:p" [] ()]- headers' <- mapM cellToOpenXML $ zip aligns headers- rows' <- mapM (mapM cellToOpenXML . zip aligns) rows- compactStyle <- pStyleM "Compact"- let emptyCell' = [Elem $ mknode "w:p" [] [mknode "w:pPr" [] [compactStyle]]]- let mkcell contents = mknode "w:tc" []- $ if null contents- then emptyCell'- else contents- let mkrow cells =- mknode "w:tr" [] $- map mkcell cells- let textwidth = 7920 -- 5.5 in in twips, 1/20 pt- let fullrow = 5000 -- 100% specified in pct- let (rowwidth :: Int) = round $ fullrow * sum widths- let mkgridcol w = mknode "w:gridCol"- [("w:w", tshow (floor (textwidth * w) :: Integer))] ()- let hasHeader = not $ all null headers- modify $ \s -> s { stInTable = False }- -- for compatibility with Word <= 2007, we include a val with a bitmask- -- 0×0020 Apply first row conditional formatting- -- 0×0040 Apply last row conditional formatting- -- 0×0080 Apply first column conditional formatting- -- 0×0100 Apply last column conditional formatting- -- 0×0200 Do not apply row banding conditional formatting- -- 0×0400 Do not apply column banding conditional formattin- let tblLookVal :: Int- tblLookVal = if hasHeader then 0x20 else 0- return $- caption' ++- [Elem $- mknode "w:tbl" []- ( mknode "w:tblPr" []- ( mknode "w:tblStyle" [("w:val","Table")] () :- mknode "w:tblW" [("w:type", "pct"), ("w:w", tshow rowwidth)] () :- mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0")- ,("w:lastRow","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 (null caption) ] )- : mknode "w:tblGrid" []- (if all (==0) widths- then []- else map mkgridcol widths)- : [ mkrow headers' | hasHeader ] ++- map mkrow rows'- )]+blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) =+ tableToOpenXML (blocksToOpenXML opts)+ (Grid.toTable attr caption colspecs thead tbodies tfoot) blockToOpenXML' opts el | BulletList lst <- el = addOpenXMLList BulletMarker lst | OrderedList (start, numstyle, numdelim) lst <- el@@ -1121,13 +963,6 @@ modify $ \st -> st{ stInList = oldInList } return $ first'' ++ rest'' -alignmentToString :: Alignment -> Text-alignmentToString alignment = case alignment of- AlignLeft -> "left"- AlignRight -> "right"- AlignCenter -> "center"- AlignDefault -> "left"- -- | 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@@ -1138,10 +973,6 @@ asList :: (PandocMonad m) => WS m a -> WS m a asList = local $ \env -> env{ envListLevel = envListLevel env + 1 } -isStyle :: Element -> Bool-isStyle e = isElem [] "w" "rStyle" e ||- isElem [] "w" "pStyle" e- getTextProps :: (PandocMonad m) => WS m [Element] getTextProps = do props <- asks envTextProperties@@ -1170,16 +1001,6 @@ [] -> [] ps -> [mknode "w:pPr" [] ps] -withParaProp :: PandocMonad m => Element -> WS m a -> WS m a-withParaProp d p =- local (\env -> env {envParaProperties = ep <> envParaProperties env}) p- where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]--withParaPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a-withParaPropM md p = do- d <- md- withParaProp d p- formattedString :: PandocMonad m => Text -> WS m [Element] formattedString str = -- properly handle soft hyphens@@ -1200,9 +1021,6 @@ props <- getTextProps return [ mknode "w:r" [] $ props ++ els ] -setFirstPara :: PandocMonad m => WS m ()-setFirstPara = modify $ \s -> s { stFirstPara = True }- -- | Convert an inline element to OpenXML. inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content] inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il@@ -1493,22 +1311,6 @@ br :: Element br = mknode "w:r" [] [mknode "w:br" [] ()]---- Word will insert these footnotes into the settings.xml file--- (whether or not they're visible in the document). If they're in the--- file, but not in the footnotes.xml file, it will produce--- problems. So we want to make sure we insert them into our document.-defaultFootnotes :: [Element]-defaultFootnotes = [ mknode "w:footnote"- [("w:type", "separator"), ("w:id", "-1")]- [ mknode "w:p" []- [mknode "w:r" []- [ mknode "w:separator" [] ()]]]- , mknode "w:footnote"- [("w:type", "continuationSeparator"), ("w:id", "0")]- [ mknode "w:p" []- [ mknode "w:r" []- [ mknode "w:continuationSeparator" [] ()]]]] withDirection :: PandocMonad m => WS m a -> WS m a
@@ -0,0 +1,200 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{- |+Module : Text.Pandoc.Writers.Docx.Table+Copyright : Copyright (C) 2012-2021 John MacFarlane+License : GNU GPL, version 2 or above+Maintainer : John MacFarlane <jgm@berkeley.edu>++Conversion of table blocks to docx.+-}+module Text.Pandoc.Writers.Docx.Table+ ( tableToOpenXML+ ) where++import Control.Monad.State.Strict+import Data.Array+import Data.Text (Text)+import Text.Pandoc.Definition+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Shared+import Text.Printf (printf)+import Text.Pandoc.Writers.GridTable hiding (Table)+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML hiding (Attr)+import qualified Data.Text as T+import qualified Text.Pandoc.Writers.GridTable as Grid++tableToOpenXML :: PandocMonad m+ => ([Block] -> WS m [Content])+ -> Grid.Table+ -> WS m [Content]+tableToOpenXML blocksToOpenXML gridTable = do+ setFirstPara+ modify $ \s -> s { stInTable = True }+ let (Grid.Table _attr caption colspecs _rowheads thead tbodies tfoot) =+ gridTable+ let (Caption _maybeShortCaption captionBlocks) = caption+ let captionStr = stringify captionBlocks+ let aligns = map fst $ elems colspecs+ captionXml <- if null captionBlocks+ then return []+ else withParaPropM (pStyleM "Table Caption")+ $ blocksToOpenXML captionBlocks+ head' <- cellGridToOpenXML blocksToOpenXML HeadRow aligns thead+ bodies <- mapM (cellGridToOpenXML blocksToOpenXML BodyRow aligns) tbodies+ foot' <- cellGridToOpenXML blocksToOpenXML FootRow aligns tfoot++ let hasHeader = not . null . indices . partRowAttrs $ thead+ let hasFooter = not . null . indices . partRowAttrs $ tfoot+ -- for compatibility with Word <= 2007, we include a val with a bitmask+ -- 0×0020 Apply first row conditional formatting+ -- 0×0040 Apply last row conditional formatting+ -- 0×0080 Apply first column conditional formatting+ -- 0×0100 Apply last column conditional formatting+ -- 0×0200 Do not apply row banding conditional formatting+ -- 0×0400 Do not apply column banding conditional formattin+ let tblLookVal = if hasHeader then (0x20 :: Int) else 0+ let (gridCols, tblWattr) = tableLayout (elems 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:tblCaption" [("w:val", captionStr)] ()+ | not (T.null captionStr) ]+ )+ : mknode "w:tblGrid" [] gridCols+ : head' ++ mconcat bodies ++ foot'+ )+ modify $ \s -> s { stInTable = False }+ return $ captionXml ++ [Elem tbl]++-- | Parts of a table+data RowType = HeadRow | BodyRow | FootRow++alignmentToString :: Alignment -> Text+alignmentToString = \case+ AlignLeft -> "left"+ AlignRight -> "right"+ AlignCenter -> "center"+ AlignDefault -> "left"++tableLayout :: [ColSpec] -> ([Element], [(Text, Text)])+tableLayout specs =+ let+ textwidth = 7920 -- 5.5 in in twips (1 twip == 1/20 pt)+ fullrow = 5000 -- 100% specified in pct (1 pct == 1/50th of a percent)+ ncols = length specs+ getWidth = \case+ ColWidth n -> n+ _ -> 0+ widths = map (getWidth . snd) specs+ rowwidth = round (fullrow * sum widths) :: Int+ widthToTwips w = floor (textwidth * w) :: Int+ mkGridCol w = mknode "w:gridCol" [("w:w", tshow (widthToTwips w))] ()+ in if all (== 0) widths+ then ( replicate ncols $ mkGridCol (1.0 / fromIntegral ncols)+ , [ ("w:type", "auto"), ("w:w", "0")])+ else ( map mkGridCol widths+ , [ ("w:type", "pct"), ("w:w", tshow rowwidth) ])++cellGridToOpenXML :: PandocMonad m+ => ([Block] -> WS m [Content])+ -> RowType+ -> [Alignment]+ -> Part+ -> WS m [Element]+cellGridToOpenXML blocksToOpenXML rowType aligns part@(Part _ _ rowAttrs) =+ if null (indices rowAttrs)+ then return mempty+ else mapM (rowToOpenXML blocksToOpenXML) $+ partToRows rowType aligns part++data OOXMLCell+ = OOXMLCell Attr Alignment RowSpan ColSpan [Block]+ | OOXMLCellMerge ColSpan++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)++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)++ooxmlCellToOpenXML :: PandocMonad m+ => ([Block] -> WS m [Content])+ -> OOXMLCell+ -> WS m Element+ooxmlCellToOpenXML blocksToOpenXML = \case+ OOXMLCellMerge (ColSpan colspan) -> do+ return $ mknode "w:tc" []+ [ mknode "w:tcPr" [] [ mknode "w:gridSpan" [("w:val", tshow colspan)] ()+ , mknode "w:vMerge" [("w:val", "continue")] () ]+ , mknode "w:p" [] [mknode "w:pPr" [] ()]]+ OOXMLCell _attr align rowspan (ColSpan colspan) contents -> do+ compactStyle <- pStyleM "Compact"+ es <- 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.+ return . mknode "w:tc" [] $+ Elem+ (mknode "w:tcPr" [] ([ mknode "w:gridSpan" [("w:val", tshow colspan)] ()+ | colspan > 1] +++ [ mknode "w:vMerge" [("w:val", "restart")] ()+ | rowspan > RowSpan 1 ])) :+ if null contents+ then [Elem $ mknode "w:p" [] [mknode "w:pPr" [] [compactStyle]]]+ else case reverse (onlyElems es) of+ b:e:_ | qName (elName b) == "bookmarkEnd" -- y tho?+ , qName (elName e) == "p" -> es+ e:_ | qName (elName e) == "p" -> es+ _ -> es ++ [Elem $ mknode "w:p" [] ()]++alignmentFor :: Alignment -> Element+alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()
@@ -0,0 +1,181 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+Module : Text.Pandoc.Writers.Docx+Copyright : Copyright (C) 2012-2021 John MacFarlane+License : GNU GPL, version 2 or above+Maintainer : John MacFarlane <jgm@berkeley.edu>++Conversion of table blocks to docx.+-}+module Text.Pandoc.Writers.Docx.Types+ ( EnvProps (..)+ , WriterEnv (..)+ , defaultWriterEnv+ , WriterState (..)+ , defaultWriterState+ , WS+ , ListMarker (..)+ , listMarkerToId+ , pStyleM+ , isStyle+ , setFirstPara+ , withParaProp+ , withParaPropM+ ) where++import Control.Applicative ((<|>))+import Control.Monad.Reader+import Control.Monad.State.Strict+import Data.Text (Text)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.MIME (MimeType)+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import qualified Data.ByteString as B+import qualified Data.Map as M+import qualified Data.Set as Set+import qualified Data.Text as T++data ListMarker = NoMarker+ | BulletMarker+ | NumberMarker ListNumberStyle ListNumberDelim Int+ deriving (Show, Read, Eq, Ord)++listMarkerToId :: ListMarker -> Text+listMarkerToId NoMarker = "990"+listMarkerToId BulletMarker = "991"+listMarkerToId (NumberMarker sty delim n) = T.pack $+ '9' : '9' : styNum : delimNum : show n+ where styNum = case sty of+ DefaultStyle -> '2'+ Example -> '3'+ Decimal -> '4'+ LowerRoman -> '5'+ UpperRoman -> '6'+ LowerAlpha -> '7'+ UpperAlpha -> '8'+ delimNum = case delim of+ DefaultDelim -> '0'+ Period -> '1'+ OneParen -> '2'+ TwoParens -> '3'+++data EnvProps = EnvProps{ styleElement :: Maybe Element+ , otherElements :: [Element]+ }++instance Semigroup EnvProps where+ EnvProps s es <> EnvProps s' es' = EnvProps (s <|> s') (es ++ es')++instance Monoid EnvProps where+ mempty = EnvProps Nothing []+ mappend = (<>)++data WriterEnv = WriterEnv+ { envTextProperties :: EnvProps+ , envParaProperties :: EnvProps+ , envRTL :: Bool+ , envListLevel :: Int+ , envListNumId :: Int+ , envInDel :: Bool+ , envChangesAuthor :: Text+ , envChangesDate :: Text+ , envPrintWidth :: Integer+ }++defaultWriterEnv :: WriterEnv+defaultWriterEnv = WriterEnv+ { envTextProperties = mempty+ , envParaProperties = mempty+ , envRTL = False+ , envListLevel = -1+ , envListNumId = 1+ , envInDel = False+ , envChangesAuthor = "unknown"+ , envChangesDate = "1969-12-31T19:00:00Z"+ , envPrintWidth = 1+ }+++data WriterState = WriterState{+ stFootnotes :: [Element]+ , stComments :: [([(Text, Text)], [Inline])]+ , stSectionIds :: Set.Set Text+ , stExternalLinks :: M.Map Text Text+ , stImages :: M.Map FilePath (String, String, Maybe MimeType, B.ByteString)+ , stLists :: [ListMarker]+ , stInsId :: Int+ , stDelId :: Int+ , stStyleMaps :: StyleMaps+ , stFirstPara :: Bool+ , stInTable :: Bool+ , stInList :: Bool+ , stTocTitle :: [Inline]+ , stDynamicParaProps :: Set.Set ParaStyleName+ , stDynamicTextProps :: Set.Set CharStyleName+ , stCurId :: Int+ }++defaultWriterState :: WriterState+defaultWriterState = WriterState{+ stFootnotes = defaultFootnotes+ , stComments = []+ , stSectionIds = Set.empty+ , stExternalLinks = M.empty+ , stImages = M.empty+ , stLists = [NoMarker]+ , stInsId = 1+ , stDelId = 1+ , stStyleMaps = StyleMaps M.empty M.empty+ , stFirstPara = False+ , stInTable = False+ , stInList = False+ , stTocTitle = [Str "Table of Contents"]+ , stDynamicParaProps = Set.empty+ , stDynamicTextProps = Set.empty+ , stCurId = 20+ }++setFirstPara :: PandocMonad m => WS m ()+setFirstPara = modify $ \s -> s { stFirstPara = True }++type WS m = ReaderT WriterEnv (StateT WriterState m)++-- Word will insert these footnotes into the settings.xml file+-- (whether or not they're visible in the document). If they're in the+-- file, but not in the footnotes.xml file, it will produce+-- problems. So we want to make sure we insert them into our document.+defaultFootnotes :: [Element]+defaultFootnotes = [ mknode "w:footnote"+ [("w:type", "separator"), ("w:id", "-1")]+ [ mknode "w:p" []+ [mknode "w:r" []+ [ mknode "w:separator" [] ()]]]+ , mknode "w:footnote"+ [("w:type", "continuationSeparator"), ("w:id", "0")]+ [ mknode "w:p" []+ [ mknode "w:r" []+ [ mknode "w:continuationSeparator" [] ()]]]]++pStyleM :: (PandocMonad m) => ParaStyleName -> WS m XML.Element+pStyleM styleName = do+ pStyleMap <- gets (smParaStyle . stStyleMaps)+ let sty' = getStyleIdFromName styleName pStyleMap+ return $ mknode "w:pStyle" [("w:val", fromStyleId sty')] ()++withParaProp :: PandocMonad m => Element -> WS m a -> WS m a+withParaProp d p =+ local (\env -> env {envParaProperties = ep <> envParaProperties env}) p+ where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]++withParaPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a+withParaPropM md p = do+ d <- md+ withParaProp d p++isStyle :: Element -> Bool+isStyle e = isElem [] "w" "rStyle" e ||+ isElem [] "w" "pStyle" e
@@ -991,12 +991,12 @@ showDateTimeISO8601 currentTime | version == EPUB3 ] belongsToCollectionNodes = maybe []- (\belongsToCollection -> (unode "meta" ! [("property", "belongs-to-collection"), ("id", "epub-id-1")] $ belongsToCollection )+ (\belongsToCollection -> (unode "meta" ! [("property", "belongs-to-collection"), ("id", "epub-collection-1")] $ belongsToCollection ) :- [unode "meta" ! [("refines", "#epub-id-1"), ("property", "collection-type")] $ ("series" :: Text) ])+ [unode "meta" ! [("refines", "#epub-collection-1"), ("property", "collection-type")] $ ("series" :: Text) ]) (epubBelongsToCollection md)++ maybe []- (\groupPosition -> [unode "meta" ! [("refines", "#epub-id-1"), ("property", "group-position")] $ groupPosition ])+ (\groupPosition -> [unode "meta" ! [("refines", "#epub-collection-1"), ("property", "group-position")] $ groupPosition ]) (epubGroupPosition md) dcTag n s = unode ("dc:" <> n) s dcTag' n s = [dcTag n s]
@@ -0,0 +1,157 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TupleSections #-}++{- |+Module : Text.Pandoc.Writers.GridTable+Copyright : © 2020-2021 Albert Krewinkel+License : GNU GPL, version 2 or above++Maintainer : Albert Krewinkel <albert@zeitkraut.de>++Grid representation of pandoc tables.+-}+module Text.Pandoc.Writers.GridTable+ ( Table (..)+ , GridCell (..)+ , RowIndex (..)+ , ColIndex (..)+ , CellIndex+ , Part (..)+ , toTable+ , rowArray+ ) where++import Control.Monad (forM_)+import Control.Monad.ST+import Data.Array+import Data.Array.MArray+import Data.Array.ST+import Data.Maybe (listToMaybe)+import Data.STRef+import Text.Pandoc.Definition hiding (Table)+import qualified Text.Pandoc.Builder as B++-- | A grid cell contains either a real table cell, or is the+-- continuation of a column or row-spanning cell. In the latter case,+-- the index of the continued cell is provided.+data GridCell+ = ContentCell Attr Alignment RowSpan ColSpan [Block]+ | ContinuationCell CellIndex+ deriving (Show)++-- | Row index in a table part.+newtype RowIndex = RowIndex Int deriving (Enum, Eq, Ix, Ord, Show)+-- | Column index in a table part.+newtype ColIndex = ColIndex Int deriving (Enum, Eq, Ix, Ord, Show)++-- | Index to a cell in a table part.+type CellIndex = (RowIndex, ColIndex)++-- | Cells are placed on a grid. Row attributes are stored in a separate+-- array.+data Part = Part+ { partAttr :: Attr+ , partCellArray :: Array (RowIndex,ColIndex) GridCell+ , partRowAttrs :: Array RowIndex Attr+ }++data Table = Table+ { tableAttr :: Attr+ , tableCaption :: Caption+ , tableColSpecs :: Array ColIndex ColSpec+ , tableRowHeads :: RowHeadColumns+ , tableHead :: Part+ , tableBodies :: [Part]+ , tableFoot :: Part+ }++toTable+ :: B.Attr+ -> B.Caption+ -> [B.ColSpec]+ -> B.TableHead+ -> [B.TableBody]+ -> B.TableFoot+ -> Table+toTable attr caption colSpecs thead tbodies tfoot =+ Table attr caption colSpecs' rowHeads thGrid tbGrids tfGrid+ where+ colSpecs' = listArray (ColIndex 1, ColIndex $ length colSpecs) colSpecs+ rowHeads = case listToMaybe tbodies of+ Nothing -> RowHeadColumns 0+ Just (TableBody _attr rowHeadCols _headerRows _rows) -> rowHeadCols+ thGrid = let (TableHead headAttr rows) = thead+ in rowsToPart headAttr rows+ tbGrids = map bodyToGrid tbodies+ tfGrid = let (TableFoot footAttr rows) = tfoot+ in rowsToPart footAttr rows+ bodyToGrid (TableBody bodyAttr _rowHeadCols headRows rows) =+ rowsToPart bodyAttr (headRows ++ rows)++data BuilderCell+ = FilledCell GridCell+ | FreeCell++fromBuilderCell :: BuilderCell -> GridCell+fromBuilderCell = \case+ FilledCell c -> c+ FreeCell -> error "Found an unassigned cell."++rowsToPart :: Attr -> [B.Row] -> Part+rowsToPart attr = \case+ [] -> Part+ attr+ (listArray ((RowIndex 1, ColIndex 1), (RowIndex 0, ColIndex 0)) [])+ (listArray (RowIndex 1, RowIndex 0) [])+ rows@(Row _attr firstRow:_) ->+ let nrows = length rows+ ncols = sum $ map (\(Cell _ _ _ (ColSpan cs) _) -> cs) firstRow+ gbounds = ((RowIndex 1, ColIndex 1), (RowIndex nrows, ColIndex ncols))+ mutableGrid :: ST s (STArray s CellIndex GridCell)+ mutableGrid = do+ grid <- newArray gbounds FreeCell+ ridx <- newSTRef (RowIndex 1)+ forM_ rows $ \(Row _attr cells) -> do+ cidx <- newSTRef (ColIndex 1)+ forM_ cells $ \(Cell cellAttr align rs cs blks) -> do+ ridx' <- readSTRef ridx+ let nextFreeInRow colindex@(ColIndex c) = do+ readArray grid (ridx', colindex) >>= \case+ FreeCell -> pure colindex+ _ -> nextFreeInRow $ ColIndex (c + 1)+ cidx' <- readSTRef cidx >>= nextFreeInRow+ writeArray grid (ridx', cidx') . FilledCell $+ ContentCell cellAttr align rs cs blks+ forM_ (continuationIndices ridx' cidx' rs cs) $ \idx -> do+ writeArray grid idx . FilledCell $+ ContinuationCell (ridx', cidx')+ -- go to new column+ writeSTRef cidx cidx'+ -- go to next row+ modifySTRef ridx (incrRowIndex 1)+ -- Swap BuilderCells with normal GridCells.+ mapArray fromBuilderCell grid+ in Part+ { partCellArray = runSTArray mutableGrid+ , partRowAttrs = listArray (RowIndex 1, RowIndex nrows) $+ map (\(Row rowAttr _) -> rowAttr) rows+ , partAttr = attr+ }++continuationIndices :: RowIndex -> ColIndex -> RowSpan -> ColSpan -> [CellIndex]+continuationIndices (RowIndex ridx) (ColIndex cidx) rowspan colspan =+ let (RowSpan rs) = rowspan+ (ColSpan cs) = colspan+ in [ (RowIndex r, ColIndex c) | r <- [ridx..(ridx + rs - 1)]+ , c <- [cidx..(cidx + cs - 1)]+ , (r, c) /= (ridx, cidx)]++rowArray :: RowIndex -> Array CellIndex GridCell -> Array ColIndex GridCell+rowArray ridx grid =+ let ((_minRidx, minCidx), (_maxRidx, maxCidx)) = bounds grid+ in ixmap (minCidx, maxCidx) (ridx,) grid++incrRowIndex :: RowSpan -> RowIndex -> RowIndex+incrRowIndex (RowSpan n) (RowIndex r) = RowIndex $ r + n
@@ -882,7 +882,7 @@ else do contents <- blockListToHtml opts blocks return $ H.blockquote $ nl opts >> contents >> nl opts-blockToHtml opts (Header level attr@(_,classes,kvs) lst) = do+blockToHtml opts (Header level (ident,classes,kvs) lst) = do contents <- inlineListToHtml opts lst let secnum = fromMaybe mempty $ lookup "number" kvs let contents' = if writerNumberSections opts && not (T.null secnum)@@ -890,7 +890,13 @@ then (H.span ! A.class_ "header-section-number" $ toHtml secnum) >> strToHtml " " >> contents else contents- addAttrs opts attr+ html5 <- gets stHtml5+ let kvs' = if html5+ then kvs+ else [ (k, v) | (k, v) <- kvs+ , k `elem` (["lang", "dir", "title", "style"+ , "align"] ++ intrinsicEventsHTML4)]+ addAttrs opts (ident,classes,kvs') $ case level of 1 -> H.h1 contents' 2 -> H.h2 contents'@@ -1525,6 +1531,12 @@ allowsMathEnvironments MathML = True allowsMathEnvironments (WebTeX _) = True allowsMathEnvironments _ = False++-- | List of intrinsic event attributes allowed on all elements in HTML4.+intrinsicEventsHTML4 :: [Text]+intrinsicEventsHTML4 =+ [ "onclick", "ondblclick", "onmousedown", "onmouseup", "onmouseover"+ , "onmouseout", "onmouseout", "onkeypress", "onkeydown", "onkeyup"] isRawHtml :: PandocMonad m => Format -> StateT WriterState m Bool isRawHtml f = do
@@ -1,6 +1,7 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.JATS Copyright : 2017-2021 John MacFarlane@@ -20,12 +21,13 @@ , writeJatsPublishing , writeJatsArticleAuthoring ) where+import Control.Applicative ((<|>)) 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)+import Data.Maybe (fromMaybe, listToMaybe) import Data.Time (toGregorian, Day, parseTimeM, defaultTimeLocale, formatTime) import qualified Data.Text as T import Data.Text (Text)@@ -80,7 +82,7 @@ let environment = JATSEnv { jatsTagSet = tagSet , jatsInlinesWriter = inlinesToJATS- , jatsBlockWriter = blockToJATS+ , jatsBlockWriter = wrappedBlocksToJATS , jatsReferences = refs } let initialState = JATSState { jatsNotes = [] }@@ -162,11 +164,9 @@ wrappedBlockToJATS b = do inner <- blockToJATS opts b return $- if needsWrap b || isBlockQuote b -- see #7041+ if needsWrap b then inTags True "p" [("specific-use","wrapper")] inner else inner- isBlockQuote (BlockQuote _) = True- isBlockQuote _ = False -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block@@ -225,33 +225,36 @@ (T.drop 1 . T.dropWhile (/='/') <$> mbMT) in (maintype, subtype) -languageFor :: [Text] -> Text-languageFor classes =+languageFor :: WriterOptions -> [Text] -> Text+languageFor opts classes = case langs of (l:_) -> escapeStringForXML l [] -> ""- where isLang l = T.toLower l `elem` map T.toLower languages+ where+ syntaxMap = writerSyntaxMap opts+ isLang l = T.toLower l `elem` map T.toLower (languages syntaxMap) langsFrom s = if isLang s then [s]- else languagesByExtension . T.toLower $ s+ else (languagesByExtension syntaxMap) . T.toLower $ s langs = concatMap langsFrom classes -codeAttr :: Attr -> (Text, [(Text, Text)])-codeAttr (ident,classes,kvs) = (lang, attr)+codeAttr :: WriterOptions -> Attr -> (Text, [(Text, Text)])+codeAttr opts (ident,classes,kvs) = (lang, attr) where- attr = [("id",ident) | not (T.null ident)] +++ attr = [("id", escapeNCName ident) | not (T.null ident)] ++ [("language",lang) | not (T.null lang)] ++ [(k,v) | (k,v) <- kvs, k `elem` ["code-type", "code-version", "executable", "language-version", "orientation", "platforms", "position", "specific-use"]]- lang = languageFor classes+ lang = languageFor opts classes -- | 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- let idAttr = [("id", writerIdentifierPrefix opts <> id') | not (T.null id')]+ 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@@ -260,7 +263,7 @@ inTagsSimple "title" title' $$ contents -- Bibliography reference: blockToJATS opts (Div (ident,_,_) [Para lst]) | "ref-" `T.isPrefixOf` ident =- inTags True "ref" [("id", ident)] .+ inTags True "ref" [("id", escapeNCName ident)] . inTagsSimple "mixed-citation" <$> inlinesToJATS opts lst blockToJATS opts (Div ("refs",_,_) xs) = do@@ -271,14 +274,14 @@ return $ inTagsIndented "ref-list" contents blockToJATS opts (Div (ident,[cls],kvs) bs) | cls `elem` ["fig", "caption", "table-wrap"] = do contents <- blocksToJATS opts bs- let attr = [("id", ident) | not (T.null ident)] +++ 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 cls attr contents blockToJATS opts (Div (ident,_,kvs) bs) = do contents <- blocksToJATS opts bs- let attr = [("id", ident) | not (T.null ident)] +++ 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"]]@@ -296,7 +299,7 @@ let capt = if null txt then empty else inTagsSimple "caption" $ inTagsSimple "p" alt- let attr = [("id", ident) | not (T.null ident)] +++ 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),@@ -307,7 +310,7 @@ capt $$ selfClosingTag "graphic" graphicattr blockToJATS _ (Para [Image (ident,_,kvs) _ (src, tit)]) = do let (maintype, subtype) = imageMimeType src kvs- let attr = [("id", ident) | not (T.null ident)] +++ let attr = [("id", escapeNCName ident) | not (T.null ident)] ++ [("mimetype", maintype), ("mime-subtype", subtype), ("xlink:href", src)] ++@@ -323,13 +326,16 @@ blockToJATS opts $ linesToPara lns blockToJATS opts (BlockQuote blocks) = do tagSet <- asks jatsTagSet- let blocksToJats' = if tagSet == TagSetArticleAuthoring- then wrappedBlocksToJATS (not . isPara)- else blocksToJATS- inTagsIndented "disp-quote" <$> blocksToJats' opts blocks-blockToJATS _ (CodeBlock a str) = return $+ let needsWrap = if tagSet == TagSetArticleAuthoring+ then not . isPara+ else \case+ Header{} -> True+ HorizontalRule -> True+ _ -> False+ inTagsIndented "disp-quote" <$> wrappedBlocksToJATS needsWrap opts blocks+blockToJATS opts (CodeBlock a str) = return $ inTags False tag attr (flush (text (T.unpack $ escapeStringForXML str)))- where (lang, attr) = codeAttr a+ where (lang, attr) = codeAttr opts a tag = if T.null lang then "preformat" else "code" blockToJATS _ (BulletList []) = return empty blockToJATS opts (BulletList lst) =@@ -409,9 +415,9 @@ inlineToJATS opts (Quoted DoubleQuote lst) = do contents <- inlinesToJATS opts lst return $ char '“' <> contents <> char '”'-inlineToJATS _ (Code a str) =+inlineToJATS opts (Code a str) = return $ inTags False tag attr $ literal (escapeStringForXML str)- where (lang, attr) = codeAttr a+ where (lang, attr) = codeAttr opts a tag = if T.null lang then "monospace" else "code" inlineToJATS _ il@(RawInline f x) | f == "jats" = return $ literal x@@ -434,7 +440,8 @@ let notenum = case notes of (n, _):_ -> n + 1 [] -> 1- thenote <- inTags True "fn" [("id","fn" <> tshow notenum)]+ thenote <- inTags True "fn" [("id", "fn" <> tshow notenum)]+ . (inTagsSimple "label" (literal $ tshow notenum) <>) <$> wrappedBlocksToJATS (not . isPara) opts (walk demoteHeaderAndRefs contents) modify $ \st -> st{ jatsNotes = (notenum, thenote) : notes }@@ -442,18 +449,34 @@ ("rid", "fn" <> tshow notenum)] $ text (show notenum) inlineToJATS opts (Cite _ lst) =- -- TODO revisit this after examining the jats.csl pipeline inlinesToJATS opts lst-inlineToJATS opts (Span ("",_,[]) ils) = inlinesToJATS opts ils-inlineToJATS opts (Span (ident,_,kvs) ils) = do+inlineToJATS opts (Span (ident,classes,kvs) ils) = do contents <- inlinesToJATS opts ils- let attr = [("id",ident) | not (T.null ident)] ++- [("xml:lang",l) | ("lang",l) <- kvs] ++- [(k,v) | (k,v) <- kvs- , k `elem` ["content-type", "rationale",- "rid", "specific-use"]]- return $ selfClosingTag "milestone-start" attr <> contents <>- selfClosingTag "milestone-end" []+ let commonAttr = [("id", escapeNCName ident) | not (T.null ident)] +++ [("xml:lang",l) | ("lang",l) <- kvs] +++ [(k,v) | (k,v) <- kvs, k `elem` ["alt", "specific-use"]]+ -- A named-content element is a good fit for spans, but requires a+ -- content-type attribute to be present. We use either the explicit+ -- attribute or the first class as content type. If neither is+ -- available, then we fall back to using a @styled-content@ element.+ let (tag, specificAttr) =+ case lookup "content-type" kvs <|> listToMaybe classes of+ Just ct -> ( "named-content"+ , ("content-type", ct) :+ [(k, v) | (k, v) <- kvs+ , k `elem` ["rid", "vocab", "vocab-identifier",+ "vocab-term", "vocab-term-identifier"]])+ -- Fall back to styled-content+ Nothing -> ("styled-content"+ , [(k, v) | (k,v) <- kvs+ , k `elem` ["style", "style-type", "style-detail",+ "toggle"]])+ let attr = commonAttr ++ specificAttr+ -- unwrap if wrapping element would have no attributes+ return $+ if null attr+ then contents+ else inTags False tag attr contents inlineToJATS _ (Math t str) = do let addPref (Xml.Attr q v) | Xml.qName q == "xmlns" = Xml.Attr q{ Xml.qName = "xmlns:mml" } v@@ -488,9 +511,9 @@ return $ inTagsSimple "email" $ literal (escapeStringForXML email) inlineToJATS opts (Link (ident,_,kvs) txt (T.uncons -> Just ('#', src), _)) = do let attr = mconcat- [ [("id", ident) | not (T.null ident)]+ [ [("id", escapeNCName ident) | not (T.null ident)] , [("alt", stringify txt) | not (null txt)]- , [("rid", src)]+ , [("rid", escapeNCName src)] , [(k,v) | (k,v) <- kvs, k `elem` ["ref-type", "specific-use"]] , [("ref-type", "bibr") | "ref-" `T.isPrefixOf` src] ]@@ -500,7 +523,7 @@ contents <- inlinesToJATS opts txt return $ inTags False "xref" attr contents inlineToJATS opts (Link (ident,_,kvs) txt (src, tit)) = do- let attr = [("id", ident) | not (T.null ident)] +++ let attr = [("id", escapeNCName ident) | not (T.null ident)] ++ [("ext-link-type", "uri"), ("xlink:href", src)] ++ [("xlink:title", tit) | not (T.null tit)] ++@@ -518,7 +541,7 @@ let subtype = fromMaybe "" $ lookup "mime-subtype" kvs `mplus` (T.drop 1 . T.dropWhile (/='/') <$> mbMT)- let attr = [("id", ident) | not (T.null ident)] +++ let attr = [("id", escapeNCName ident) | not (T.null ident)] ++ [("mimetype", maintype), ("mime-subtype", subtype), ("xlink:href", src)] ++
@@ -29,7 +29,7 @@ import Text.Pandoc.Options (WriterOptions) import Text.Pandoc.Shared (tshow) import Text.Pandoc.Writers.JATS.Types-import Text.Pandoc.XML (escapeStringForXML, inTags)+import Text.Pandoc.XML (escapeNCName, escapeStringForXML, inTags) import qualified Data.Text as T referencesToJATS :: PandocMonad m@@ -46,7 +46,8 @@ referenceToJATS _opts ref = do let refType = referenceType ref let pubType = [("publication-type", refType) | not (T.null refType)]- let wrap = inTags True "ref" [("id", "ref-" <> unItemId (referenceId ref))]+ let ident = escapeNCName $ "ref-" <> unItemId (referenceId ref)+ let wrap = inTags True "ref" [("id", ident)] . inTags True "element-citation" pubType return . wrap . vcat $ [ authors
@@ -24,7 +24,7 @@ import Text.Pandoc.Options (WriterOptions) import Text.Pandoc.Shared (tshow) import Text.Pandoc.Writers.JATS.Types-import Text.Pandoc.XML (inTags, inTagsIndented, selfClosingTag)+import Text.Pandoc.XML (escapeNCName, inTags, inTagsIndented, selfClosingTag) import qualified Data.Text as T import qualified Text.Pandoc.Writers.AnnotatedTable as Ann @@ -34,13 +34,19 @@ -> JATS m (Doc Text) tableToJATS opts (Ann.Table attr caption colspecs thead tbodies tfoot) = do let (Caption _maybeShortCaption captionBlocks) = caption+ -- Only paragraphs are allowed in captions, all other blocks must be+ -- wrapped in @<p>@ elements.+ let needsWrapping = \case+ Plain{} -> False+ Para{} -> False+ _ -> True tbl <- captionlessTable opts attr colspecs thead tbodies tfoot captionDoc <- if null captionBlocks then return empty else do blockToJATS <- asks jatsBlockWriter- inTagsIndented "caption" . vcat <$>- mapM (blockToJATS opts) captionBlocks+ inTagsIndented "caption" <$>+ blockToJATS needsWrapping opts captionBlocks return $ inTags True "table-wrap" [] $ captionDoc $$ tbl captionlessTable :: PandocMonad m@@ -216,7 +222,7 @@ toAttribs :: Attr -> [Text] -> [(Text, Text)] toAttribs (ident, _classes, kvs) knownAttribs =- (if T.null ident then id else (("id", ident) :)) $+ (if T.null ident then id else (("id", escapeNCName ident) :)) $ filter ((`elem` knownAttribs) . fst) kvs tableCellToJats :: PandocMonad m@@ -230,7 +236,7 @@ inlinesToJats <- asks jatsInlinesWriter let cellContents = \case [Plain inlines] -> inlinesToJats opts inlines- blocks -> vcat <$> mapM (blockToJats opts) blocks+ blocks -> blockToJats needsWrapInCell opts blocks let tag' = case ctype of BodyCell -> "td" HeaderCell -> "th"@@ -246,3 +252,17 @@ . maybeCons (colspanAttrib colspan) $ toAttribs attr validAttribs inTags False tag' attribs <$> cellContents item++-- | Whether the JATS produced from this block should be wrapped in a+-- @<p>@ element when put directly below a @<td>@ element.+needsWrapInCell :: Block -> Bool+needsWrapInCell = \case+ Plain{} -> False -- should be unwrapped anyway+ Para{} -> False+ BulletList{} -> False+ OrderedList{} -> False+ DefinitionList{} -> False+ HorizontalRule -> False+ CodeBlock{} -> False+ RawBlock{} -> False -- responsibility of the user+ _ -> True
@@ -37,11 +37,20 @@ { jatsNotes :: [(Int, Doc Text)] } +-- | Environment containing all information relevant for rendering. data JATSEnv m = JATSEnv- { jatsTagSet :: JATSTagSet+ { jatsTagSet :: JATSTagSet -- ^ The tag set that's being ouput++ , jatsBlockWriter :: (Block -> Bool)+ -> WriterOptions -> [Block] -> JATS m (Doc Text)+ -- ^ Converts a block list to JATS, wrapping top-level blocks into a+ -- @<p>@ element if the property evaluates to @True@.+ -- See #7227.+ , jatsInlinesWriter :: WriterOptions -> [Inline] -> JATS m (Doc Text)- , jatsBlockWriter :: WriterOptions -> Block -> JATS m (Doc Text)- , jatsReferences :: [Reference Inlines]+ -- ^ Converts an inline list to JATS.++ , jatsReferences :: [Reference Inlines] -- ^ List of references } -- | JATS writer type
@@ -280,6 +280,8 @@ | Just email <- T.stripPrefix "mailto:" url' = (Jira.Email, email) | "user-account" `elem` classes = (Jira.User, dropTilde url) | "attachment" `elem` classes = (Jira.Attachment, url)+ | "smart-card" `elem` classes = (Jira.SmartCard, url)+ | "smart-link" `elem` classes = (Jira.SmartLink, url) | otherwise = (Jira.External, url) dropTilde txt = case T.uncons txt of Just ('~', username) -> username@@ -309,9 +311,13 @@ spanToJira :: PandocMonad m => Attr -> [Inline] -> JiraConverter m [Jira.Inline]-spanToJira (ident, _classes, _attribs) inls = case ident of- "" -> toJiraInlines inls- _ -> (Jira.Anchor ident :) <$> toJiraInlines inls+spanToJira (ident, _classes, attribs) inls =+ let wrap = case lookup "color" attribs of+ Nothing -> id+ Just color -> singleton . Jira.ColorInline (Jira.ColorName color)+ in wrap <$> case ident of+ "" -> toJiraInlines inls+ _ -> (Jira.Anchor ident :) <$> toJiraInlines inls registerNotes :: PandocMonad m => [Block] -> JiraConverter m [Jira.Inline] registerNotes contents = do
@@ -29,7 +29,7 @@ import Network.URI (unEscapeString) import Text.DocTemplates (FromContext(lookupContext), renderTemplate, Val(..), Context(..))-import Text.Pandoc.BCP47 (Lang (..), getLang, renderLang)+import Text.Collate.Lang (Lang (..), renderLang) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import Text.Pandoc.Definition import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,@@ -173,6 +173,7 @@ defField "has-chapters" (stHasChapters st) $ defField "has-frontmatter" (documentClass `elem` frontmatterClasses) $ defField "listings" (writerListings options || stLHS st) $+ defField "zero-width-non-joiner" (stZwnj st) $ defField "beamer" beamer $ (if stHighlighting st then case writerHighlightStyle options of@@ -290,7 +291,12 @@ => Block -- ^ Block to convert -> LW m (Doc Text) blockToLaTeX Null = return empty-blockToLaTeX (Div attr@(identifier,"block":_,_) (Header _ _ ils : bs)) = do+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@@ -298,8 +304,8 @@ braces (literal ref) <> braces empty title' <- inlineListToLaTeX ils contents <- blockListToLaTeX bs- wrapDiv attr $ ("\\begin{block}" <> braces title' <> anchor) $$- contents $$ "\\end{block}"+ wrapDiv attr $ ("\\begin" <> braces blockname <> braces title' <> anchor) $$+ contents $$ "\\end" <> braces blockname blockToLaTeX (Div (identifier,"slide":dclasses,dkvs) (Header _ (_,hclasses,hkvs) ils : bs)) = do -- note: [fragile] is required or verbatim breaks@@ -888,8 +894,9 @@ then char '`' <> inner <> char '\'' else char '\x2018' <> inner <> char '\x2019' where- isQuoted (Quoted _ _) = True- isQuoted _ = False+ isQuoted (Span _ (x:_)) = isQuoted x+ isQuoted (Quoted _ _) = True+ isQuoted _ = False inlineToLaTeX (Str str) = do setEmptyLine False liftM literal $ stringToLaTeX TextString str@@ -1043,5 +1050,3 @@ -- 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--
@@ -15,7 +15,7 @@ toBabel ) where import Data.Text (Text)-import Text.Pandoc.BCP47 (Lang (..))+import Text.Collate.Lang (Lang(..)) -- In environments \Arabic instead of \arabic is used@@ -25,88 +25,89 @@ ("arabic", o) -> ("Arabic", o) x -> x --- Takes a list of the constituents of a BCP 47 language code and+-- Takes a list of the constituents of a BCP47 language code and -- converts it to a Polyglossia (language, options) tuple -- http://mirrors.ctan.org/macros/latex/contrib/polyglossia/polyglossia.pdf toPolyglossia :: Lang -> (Text, Text)-toPolyglossia (Lang "ar" _ "DZ" _) = ("arabic", "locale=algeria")-toPolyglossia (Lang "ar" _ "IQ" _) = ("arabic", "locale=mashriq")-toPolyglossia (Lang "ar" _ "JO" _) = ("arabic", "locale=mashriq")-toPolyglossia (Lang "ar" _ "LB" _) = ("arabic", "locale=mashriq")-toPolyglossia (Lang "ar" _ "LY" _) = ("arabic", "locale=libya")-toPolyglossia (Lang "ar" _ "MA" _) = ("arabic", "locale=morocco")-toPolyglossia (Lang "ar" _ "MR" _) = ("arabic", "locale=mauritania")-toPolyglossia (Lang "ar" _ "PS" _) = ("arabic", "locale=mashriq")-toPolyglossia (Lang "ar" _ "SY" _) = ("arabic", "locale=mashriq")-toPolyglossia (Lang "ar" _ "TN" _) = ("arabic", "locale=tunisia")-toPolyglossia (Lang "de" _ _ vars)- | "1901" `elem` vars = ("german", "spelling=old")-toPolyglossia (Lang "de" _ "AT" vars)- | "1901" `elem` vars = ("german", "variant=austrian, spelling=old")-toPolyglossia (Lang "de" _ "AT" _) = ("german", "variant=austrian")-toPolyglossia (Lang "de" _ "CH" vars)- | "1901" `elem` vars = ("german", "variant=swiss, spelling=old")-toPolyglossia (Lang "de" _ "CH" _) = ("german", "variant=swiss")-toPolyglossia (Lang "de" _ _ _) = ("german", "")-toPolyglossia (Lang "dsb" _ _ _) = ("lsorbian", "")-toPolyglossia (Lang "el" _ "polyton" _) = ("greek", "variant=poly")-toPolyglossia (Lang "en" _ "AU" _) = ("english", "variant=australian")-toPolyglossia (Lang "en" _ "CA" _) = ("english", "variant=canadian")-toPolyglossia (Lang "en" _ "GB" _) = ("english", "variant=british")-toPolyglossia (Lang "en" _ "NZ" _) = ("english", "variant=newzealand")-toPolyglossia (Lang "en" _ "UK" _) = ("english", "variant=british")-toPolyglossia (Lang "en" _ "US" _) = ("english", "variant=american")-toPolyglossia (Lang "grc" _ _ _) = ("greek", "variant=ancient")-toPolyglossia (Lang "hsb" _ _ _) = ("usorbian", "")-toPolyglossia (Lang "la" _ _ vars)- | "x-classic" `elem` vars = ("latin", "variant=classic")-toPolyglossia (Lang "pt" _ "BR" _) = ("portuguese", "variant=brazilian")-toPolyglossia (Lang "sl" _ _ _) = ("slovenian", "")-toPolyglossia x = (commonFromBcp47 x, "")+toPolyglossia (Lang "ar" _ (Just "DZ") _ _ _) = ("arabic", "locale=algeria")+toPolyglossia (Lang "ar" _ (Just "IQ") _ _ _) = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ (Just "JO") _ _ _) = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ (Just "LB") _ _ _) = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ (Just "LY") _ _ _) = ("arabic", "locale=libya")+toPolyglossia (Lang "ar" _ (Just "MA") _ _ _) = ("arabic", "locale=morocco")+toPolyglossia (Lang "ar" _ (Just "MR") _ _ _) = ("arabic", "locale=mauritania")+toPolyglossia (Lang "ar" _ (Just "PS") _ _ _) = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ (Just "SY") _ _ _) = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ (Just "TN") _ _ _) = ("arabic", "locale=tunisia")+toPolyglossia (Lang "de" _ _ vars _ _)+ | "1901" `elem` vars = ("german", "spelling=old")+toPolyglossia (Lang "de" _ (Just "AT") vars _ _)+ | "1901" `elem` vars = ("german", "variant=austrian, spelling=old")+toPolyglossia (Lang "de" _ (Just "AT") _ _ _) = ("german", "variant=austrian")+toPolyglossia (Lang "de" _ (Just "CH") vars _ _)+ | "1901" `elem` vars = ("german", "variant=swiss, spelling=old")+toPolyglossia (Lang "de" _ (Just "CH") _ _ _) = ("german", "variant=swiss")+toPolyglossia (Lang "de" _ _ _ _ _) = ("german", "")+toPolyglossia (Lang "dsb" _ _ _ _ _) = ("lsorbian", "")+toPolyglossia (Lang "el" _ _ vars _ _)+ | "polyton" `elem` vars = ("greek", "variant=poly")+toPolyglossia (Lang "en" _ (Just "AU") _ _ _) = ("english", "variant=australian")+toPolyglossia (Lang "en" _ (Just "CA") _ _ _) = ("english", "variant=canadian")+toPolyglossia (Lang "en" _ (Just "GB") _ _ _) = ("english", "variant=british")+toPolyglossia (Lang "en" _ (Just "NZ") _ _ _) = ("english", "variant=newzealand")+toPolyglossia (Lang "en" _ (Just "UK") _ _ _) = ("english", "variant=british")+toPolyglossia (Lang "en" _ (Just "US") _ _ _) = ("english", "variant=american")+toPolyglossia (Lang "grc" _ _ _ _ _) = ("greek", "variant=ancient")+toPolyglossia (Lang "hsb" _ _ _ _ _) = ("usorbian", "")+toPolyglossia (Lang "la" _ _ vars _ _)+ | "x-classic" `elem` vars = ("latin", "variant=classic")+toPolyglossia (Lang "pt" _ (Just "BR") _ _ _) = ("portuguese", "variant=brazilian")+toPolyglossia (Lang "sl" _ _ _ _ _) = ("slovenian", "")+toPolyglossia x = (commonFromBcp47 x, "") --- Takes a list of the constituents of a BCP 47 language code and+-- Takes a list of the constituents of a BCP47 language code and -- converts it to a Babel language string. -- 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 "de" _ "AT" vars)+toBabel (Lang "de" _ (Just "AT") vars _ _) | "1901" `elem` vars = "austrian" | otherwise = "naustrian"-toBabel (Lang "de" _ "CH" vars)+toBabel (Lang "de" _ (Just "CH") vars _ _) | "1901" `elem` vars = "swissgerman" | otherwise = "nswissgerman"-toBabel (Lang "de" _ _ vars)+toBabel (Lang "de" _ _ vars _ _) | "1901" `elem` vars = "german" | otherwise = "ngerman"-toBabel (Lang "dsb" _ _ _) = "lowersorbian"-toBabel (Lang "el" _ _ vars)+toBabel (Lang "dsb" _ _ _ _ _) = "lowersorbian"+toBabel (Lang "el" _ _ vars _ _) | "polyton" `elem` vars = "polutonikogreek"-toBabel (Lang "en" _ "AU" _) = "australian"-toBabel (Lang "en" _ "CA" _) = "canadian"-toBabel (Lang "en" _ "GB" _) = "british"-toBabel (Lang "en" _ "NZ" _) = "newzealand"-toBabel (Lang "en" _ "UK" _) = "british"-toBabel (Lang "en" _ "US" _) = "american"-toBabel (Lang "fr" _ "CA" _) = "canadien"-toBabel (Lang "fra" _ _ vars)+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"+toBabel (Lang "fra" _ _ vars _ _) | "aca" `elem` vars = "acadian"-toBabel (Lang "grc" _ _ _) = "polutonikogreek"-toBabel (Lang "hsb" _ _ _) = "uppersorbian"-toBabel (Lang "la" _ _ vars)+toBabel (Lang "grc" _ _ _ _ _) = "polutonikogreek"+toBabel (Lang "hsb" _ _ _ _ _) = "uppersorbian"+toBabel (Lang "la" _ _ vars _ _) | "x-classic" `elem` vars = "classiclatin"-toBabel (Lang "pt" _ "BR" _) = "brazilian"-toBabel (Lang "sl" _ _ _) = "slovene"+toBabel (Lang "pt" _ (Just "BR") _ _ _) = "brazilian"+toBabel (Lang "sl" _ _ _ _ _) = "slovene" toBabel x = commonFromBcp47 x --- Takes a list of the constituents of a BCP 47 language code+-- 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" "Cyrl" _ _) = "serbianc"-commonFromBcp47 (Lang "zh" "Latn" _ vars)- | "pinyin" `elem` vars = "pinyin"-commonFromBcp47 (Lang l _ _ _) = fromIso l+commonFromBcp47 (Lang "sr" (Just "Cyrl") _ _ _ _) = "serbianc"+commonFromBcp47 (Lang "zh" (Just "Latn") _ vars _ _)+ | "pinyin" `elem` vars = "pinyin"+commonFromBcp47 (Lang l _ _ _ _ _) = fromIso l where fromIso "af" = "afrikaans" fromIso "am" = "amharic"
@@ -219,9 +219,7 @@ -- we need to go to some lengths to get line breaks working: -- as LineBreak bs = \vtop{\hbox{\strut as}\hbox{\strut bs}}. fixLineBreaks :: Block -> Block-fixLineBreaks (Para ils) = Para $ fixLineBreaks' ils-fixLineBreaks (Plain ils) = Plain $ fixLineBreaks' ils-fixLineBreaks x = x+fixLineBreaks = walk fixLineBreaks' fixLineBreaks' :: [Inline] -> [Inline] fixLineBreaks' ils = case splitBy (== LineBreak) ils of
@@ -40,7 +40,7 @@ , stCsquotes :: Bool -- ^ true if document uses csquotes , stHighlighting :: Bool -- ^ true if document has highlighted code , stIncremental :: Bool -- ^ true if beamer lists should be- -- displayed bit by bit+ , stZwnj :: Bool -- ^ true if document has a ZWNJ character , stInternalLinks :: [Text] -- ^ list of internal link targets , stBeamer :: Bool -- ^ produce beamer , stEmptyLine :: Bool -- ^ true if no content on line@@ -74,6 +74,7 @@ , stCsquotes = False , stHighlighting = False , stIncremental = writerIncremental options+ , stZwnj = False , stInternalLinks = [] , stBeamer = False , stEmptyLine = True
@@ -22,6 +22,7 @@ where import Control.Applicative ((<|>))+import Control.Monad (when) import Text.Pandoc.Class (PandocMonad, toLang) import Text.Pandoc.Options (WriterOptions(..), isEnabled) import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState(..))@@ -30,7 +31,7 @@ import Text.DocLayout import Text.Pandoc.Definition import Text.Pandoc.ImageSize (showFl)-import Control.Monad.State.Strict (gets)+import Control.Monad.State.Strict (gets, modify) import Data.Text (Text) import qualified Data.Text as T import Text.Pandoc.Extensions (Extension(Ext_smart))@@ -49,6 +50,8 @@ stringToLaTeX :: PandocMonad m => StringContext -> Text -> LW m Text stringToLaTeX context zs = do opts <- gets stOptions+ when ('\x200c' `elemText` zs) $+ modify (\s -> s { stZwnj = True }) return $ T.pack $ foldr (go opts context) mempty $ T.unpack $ if writerPreferAscii opts@@ -270,5 +273,3 @@ mbBraced x = if not (T.all isAlphaNum x) then "{" <> x <> "}" else x--
@@ -26,7 +26,7 @@ import Data.List (intersperse, sortOn, transpose) import Data.List.NonEmpty (nonEmpty, NonEmpty(..)) import qualified Data.Map as M-import Data.Maybe (fromMaybe, mapMaybe)+import Data.Maybe (fromMaybe, mapMaybe, isNothing) import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T@@ -67,7 +67,17 @@ -- | Convert Pandoc to Commonmark. writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeCommonMark opts document =- evalMD (pandocToMarkdown opts document) def{ envVariant = Commonmark } def+ evalMD (pandocToMarkdown opts' document) def{ envVariant = Commonmark } def+ where+ opts' = opts{ writerExtensions =+ -- These extensions can't be enabled or disabled+ -- for commonmark because they're part of the core;+ -- we set them here so that escapeText will behave+ -- properly.+ enableExtension Ext_all_symbols_escapable $+ enableExtension Ext_pipe_tables $+ enableExtension Ext_intraword_underscores $+ writerExtensions opts } pandocTitleBlock :: Doc Text -> [Doc Text] -> Doc Text -> Doc Text pandocTitleBlock tit auths dat =@@ -132,18 +142,17 @@ | otherwise = if hasNewlines x then hang 0 ("|" <> cr) x- else if fst $ foldr needsDoubleQuotes (False, True) x+ else if isNothing $ foldM needsDoubleQuotes True x then "\"" <> fmap escapeInDoubleQuotes x <> "\"" else x where- needsDoubleQuotes t (positive, isFirst)+ needsDoubleQuotes isFirst t = if T.any isBadAnywhere t || (isFirst && T.any isYamlPunct (T.take 1 t))- then (True, False)- else (positive, False)+ then Nothing+ else Just False isBadAnywhere '#' = True isBadAnywhere ':' = True- isBadAnywhere '`' = False isBadAnywhere _ = False hasNewlines NewLine = True hasNewlines BlankLines{} = True@@ -269,6 +278,12 @@ escAttrChar '\\' = literal "\\\\" escAttrChar c = literal $ T.singleton c +-- | (Code) blocks with a single class can just use it standalone,+-- no need to bother with curly braces.+classOrAttrsToMarkdown :: Attr -> Doc Text+classOrAttrsToMarkdown ("",[cls],_) = literal cls+classOrAttrsToMarkdown attrs = attrsToMarkdown attrs+ linkAttributes :: WriterOptions -> Attr -> Doc Text linkAttributes opts attr = if isEnabled Ext_link_attributes opts && attr /= nullAttr@@ -334,7 +349,7 @@ case () of _ | isEnabled Ext_fenced_divs opts && attrs /= nullAttr ->- nowrap (literal ":::" <+> attrsToMarkdown attrs) $$+ nowrap (literal ":::" <+> classOrAttrsToMarkdown attrs) $$ chomp contents $$ literal ":::" <> blankline | isEnabled Ext_native_divs opts ||@@ -503,7 +518,7 @@ backticks = endline '`' tildes = endline '~' attrs = if isEnabled Ext_fenced_code_attributes opts- then nowrap $ " " <> attrsToMarkdown attribs+ then nowrap $ " " <> classOrAttrsToMarkdown attribs else case attribs of (_,cls:_,_) -> " " <> literal cls _ -> empty
@@ -43,7 +43,11 @@ -- | Escape special characters for Markdown. escapeText :: WriterOptions -> Text -> Text escapeText opts = T.pack . go . T.unpack- where+ where+ startsWithSpace (' ':_) = True+ startsWithSpace ('\t':_) = True+ startsWithSpace [] = True+ startsWithSpace _ = False go [] = [] go (c:cs) = case c of@@ -56,10 +60,13 @@ '@' | isEnabled Ext_citations opts -> case cs of (d:_)- | isAlphaNum d || d == '_'+ | isAlphaNum d || d == '_' || d == '{' -> '\\':'@':go cs _ -> '@':go cs- _ | c `elem` ['\\','`','*','_','[',']','#'] ->+ '#' | isEnabled Ext_space_in_atx_header opts+ , startsWithSpace cs+ -> '\\':'#':go cs+ _ | c `elem` ['\\','`','*','_','[',']'] -> '\\':c:go cs '|' | isEnabled Ext_pipe_tables opts -> '\\':'|':go cs '^' | isEnabled Ext_superscript opts -> '\\':'^':go cs@@ -81,6 +88,8 @@ | isEnabled Ext_intraword_underscores opts , isAlphaNum c , isAlphaNum x -> c : '_' : x : go xs+ '#':xs -> c : '#' : go xs+ '>':xs -> c : '>' : go xs _ -> c : go cs attrsToMarkdown :: Attr -> Doc Text@@ -491,11 +500,16 @@ rest <- mapM convertOne cs let inbr = suffs <+> joincits rest br = if isEmpty inbr then empty else char '[' <> inbr <> char ']'- return $ literal ("@" <> citationId c) <+> br+ return $ literal ("@" <> maybeInBraces (citationId c)) <+> br else do cits <- mapM convertOne (c:cs) return $ literal "[" <> joincits cits <> literal "]" where+ maybeInBraces key =+ case readWith (citeKey False >> spaces >> eof)+ defaultParserState ("@" <> key) of+ Left _ -> "{" <> key <> "}"+ Right _ -> key joincits = hcat . intersperse (literal "; ") . filter (not . isEmpty) convertOne Citation { citationId = k , citationPrefix = pinlines@@ -504,7 +518,7 @@ = do pdoc <- inlineListToMarkdown opts pinlines sdoc <- inlineListToMarkdown opts sinlines- let k' = literal (modekey m <> "@" <> k)+ let k' = literal (modekey m <> "@" <> maybeInBraces k) r = case sinlines of Str (T.uncons -> Just (y,_)):_ | y `elem` (",;]@" :: String) -> k' <> sdoc _ -> k' <+> sdoc
@@ -245,13 +245,17 @@ aligncode AlignDefault = "l" in do caption' <- inlineListToMs' opts caption- let iwidths = if all (== 0) widths- then repeat ""- else map (T.pack . printf "w(%0.1fn)" . (70 *)) widths+ let isSimple = all (== 0) widths+ let totalWidth = 70 -- 78n default width - 8n indent = 70n let coldescriptions = literal $ T.unwords- (zipWith (\align width -> aligncode align <> width)- alignments iwidths) <> "."+ (zipWith (\align width -> aligncode align <>+ if width == 0+ then ""+ else T.pack $+ printf "w(%0.1fn)"+ (totalWidth * width))+ alignments widths) <> "." colheadings <- mapM (blockListToMs opts) headers let makeRow cols = literal "T{" $$ vcat (intersperse (literal "T}\tT{") cols) $$@@ -260,13 +264,25 @@ then empty else makeRow colheadings $$ char '_' body <- mapM (\row -> do- cols <- mapM (blockListToMs opts) row+ cols <- mapM (\(cell, w) ->+ (if isSimple+ then id+ else (literal (".nr LL " <>+ T.pack (printf "%0.1fn"+ (w * totalWidth))) $$)) <$>+ blockListToMs opts cell) (zip row widths) return $ makeRow cols) rows setFirstPara return $ literal ".PP" $$ caption' $$ literal ".na" $$ -- we don't want justification in table cells+ (if isSimple+ then ""+ else ".nr LLold \\n[LL]") $$ literal ".TS" $$ literal "delim(@@) tab(\t);" $$ coldescriptions $$ colheadings' $$ vcat body $$ literal ".TE" $$+ (if isSimple+ then ""+ else ".nr LL \\n[LLold]") $$ literal ".ad" blockToMs opts (BulletList items) = do
@@ -16,6 +16,7 @@ import Control.Monad.Except (catchError, throwError) import Control.Monad.State.Strict import qualified Data.ByteString.Lazy as B+import Data.Maybe (fromMaybe) import Data.Generics (everywhere', mkT) import Data.List (isPrefixOf) import qualified Data.Map as Map@@ -23,7 +24,7 @@ import qualified Data.Text.Lazy as TL import Data.Time import System.FilePath (takeDirectory, takeExtension, (<.>))-import Text.Pandoc.BCP47 (Lang (..), getLang, renderLang)+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.Definition@@ -35,7 +36,7 @@ import Text.DocLayout import Text.Pandoc.Shared (stringify, pandocVersion, tshow) import Text.Pandoc.Writers.Shared (lookupMetaString, lookupMetaBlocks,- fixDisplayMath)+ fixDisplayMath, getLang) import Text.Pandoc.UTF8 (fromStringLazy, fromTextLazy, toTextLazy) import Text.Pandoc.Walk import Text.Pandoc.Writers.OpenDocument (writeOpenDocument)@@ -194,7 +195,7 @@ where updateLangAttr (Attr n@(QName "language" _ (Just "fo")) _) = Attr n (langLanguage lang) updateLangAttr (Attr n@(QName "country" _ (Just "fo")) _)- = Attr n (langRegion lang)+ = Attr n (fromMaybe "" $ langRegion lang) updateLangAttr x = x -- | transform both Image and Math elements
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE ViewPatterns #-}@@ -25,7 +26,7 @@ import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T-import Text.Pandoc.BCP47 (Lang (..), parseBCP47)+import Text.Collate.Lang (Lang (..), parseLang) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, translateTerm, setTranslations, toLang) import Text.Pandoc.Definition@@ -236,7 +237,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" "US" "" []+ let defLang = Lang "en" (Just "US") Nothing [] [] [] lang <- case lookupMetaString "lang" meta of "" -> pure defLang s -> fromMaybe defLang <$> toLang (Just s)@@ -372,36 +373,32 @@ -- | Convert a Pandoc block element to OpenDocument. blockToOpenDocument :: PandocMonad m => WriterOptions -> Block -> OD m (Doc Text)-blockToOpenDocument o bs- | Plain b <- bs = if null b- then return empty- else inParagraphTags =<< inlinesToOpenDocument o b- | Para [Image attr c (s,T.stripPrefix "fig:" -> Just t)] <- bs- = figure attr c s t- | Para b <- bs = if null b &&- not (isEnabled Ext_empty_paragraphs o)- then return empty- else inParagraphTags =<< inlinesToOpenDocument o b- | LineBlock b <- bs = blockToOpenDocument o $ linesToPara b- | Div attr xs <- bs = mkDiv attr xs- | Header i (ident,_,_) b- <- bs = setFirstPara >> (inHeaderTags i ident- =<< inlinesToOpenDocument o b)- | BlockQuote b <- bs = setFirstPara >> mkBlockQuote b- | DefinitionList b <- bs = setFirstPara >> defList b- | BulletList b <- bs = setFirstPara >> bulletListToOpenDocument o b- | OrderedList a b <- bs = setFirstPara >> orderedList a b- | CodeBlock _ s <- bs = setFirstPara >> preformatted s- | Table a bc s th tb tf <- bs = setFirstPara >> table (Ann.toTable a bc s th tb tf)- | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p"- [ ("text:style-name", "Horizontal_20_Line") ])- | RawBlock f s <- bs = if f == Format "opendocument"- then return $ text $ T.unpack s- else do- report $ BlockNotRendered bs- return empty- | Null <- bs = return empty- | otherwise = return empty+blockToOpenDocument o = \case+ Plain b -> if null b+ then return empty+ else inParagraphTags =<< inlinesToOpenDocument o b+ Para [Image attr c (s,T.stripPrefix "fig:" -> Just t)] -> figure attr c s t+ Para b -> if null b &&+ not (isEnabled Ext_empty_paragraphs o)+ then return empty+ else inParagraphTags =<< inlinesToOpenDocument o b+ LineBlock b -> blockToOpenDocument o $ linesToPara b+ Div attr xs -> mkDiv attr xs+ Header i (ident,_,_) b -> do+ setFirstPara+ inHeaderTags i ident =<< inlinesToOpenDocument o b+ BlockQuote b -> setFirstPara >> mkBlockQuote b+ 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)+ 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 where defList b = do setInDefinitionList True r <- vcat <$> mapM (deflistItemToOpenDocument o) b@@ -874,34 +871,33 @@ textStyleAttr :: Map.Map Text Text -> TextStyle -> Map.Map Text Text-textStyleAttr m s- | Italic <- s = Map.insert "fo:font-style" "italic" .- Map.insert "style:font-style-asian" "italic" .- Map.insert "style:font-style-complex" "italic" $ m- | Bold <- s = Map.insert "fo:font-weight" "bold" .- Map.insert "style:font-weight-asian" "bold" .- Map.insert "style:font-weight-complex" "bold" $ m- | Under <- s = Map.insert "style:text-underline-style" "solid" .- Map.insert "style:text-underline-width" "auto" .- Map.insert "style:text-underline-color" "font-color" $ m- | Strike <- s = Map.insert "style:text-line-through-style" "solid" m- | Sub <- s = Map.insert "style:text-position" "sub 58%" m- | Sup <- s = Map.insert "style:text-position" "super 58%" m- | SmallC <- s = Map.insert "fo:font-variant" "small-caps" m- | Pre <- s = Map.insert "style:font-name" "Courier New" .- Map.insert "style:font-name-asian" "Courier New" .- Map.insert "style:font-name-complex" "Courier New" $ m- | Language lang <- s- = Map.insert "fo:language" (langLanguage lang) .- Map.insert "fo:country" (langRegion lang) $ m- | otherwise = m+textStyleAttr m = \case+ Italic -> Map.insert "fo:font-style" "italic" .+ Map.insert "style:font-style-asian" "italic" .+ Map.insert "style:font-style-complex" "italic" $ m+ Bold -> Map.insert "fo:font-weight" "bold" .+ Map.insert "style:font-weight-asian" "bold" .+ Map.insert "style:font-weight-complex" "bold" $ m+ Under -> Map.insert "style:text-underline-style" "solid" .+ Map.insert "style:text-underline-width" "auto" .+ Map.insert "style:text-underline-color" "font-color" $ m+ Strike -> Map.insert "style:text-line-through-style" "solid" m+ Sub -> Map.insert "style:text-position" "sub 58%" m+ Sup -> Map.insert "style:text-position" "super 58%" m+ SmallC -> Map.insert "fo:font-variant" "small-caps" m+ Pre -> Map.insert "style:font-name" "Courier New" .+ Map.insert "style:font-name-asian" "Courier New" .+ Map.insert "style:font-name-complex" "Courier New" $ m+ Language lang ->+ Map.insert "fo:language" (langLanguage lang) .+ maybe id (Map.insert "fo:country") (langRegion lang) $ m withLangFromAttr :: PandocMonad m => Attr -> OD m a -> OD m a withLangFromAttr (_,_,kvs) action = case lookup "lang" kvs of Nothing -> action Just l ->- case parseBCP47 l of+ case parseLang l of Right lang -> withTextStyle (Language lang) action Left _ -> do report $ InvalidLang l
@@ -404,9 +404,11 @@ inlineToOrg (Math t str) = do modify $ \st -> st{ stHasMath = True } return $ if t == InlineMath- then "$" <> literal str <> "$"- else "$$" <> literal str <> "$$"+ then "\\(" <> literal str <> "\\)"+ else "\\[" <> literal str <> "\\]" inlineToOrg il@(RawInline f str)+ | elem f ["tex", "latex"] && T.isPrefixOf "\\begin" str =+ return $ cr <> literal str <> cr | isRawFormat f = return $ literal str | otherwise = do report $ InlineNotRendered il
@@ -39,5 +39,5 @@ let blks' = walk fixDisplayMath blks let (pres, logMsgs) = documentToPresentation opts (Pandoc meta blks') mapM_ report logMsgs- archv <- presentationToArchive opts pres+ archv <- presentationToArchive opts meta pres return $ fromArchive archv
@@ -38,17 +38,19 @@ import Text.Pandoc.Options import Text.Pandoc.MIME import qualified Data.ByteString.Lazy as BL+import Text.Pandoc.Writers.Shared (metaToContext) import Text.Pandoc.Writers.OOXML import qualified Data.Map as M import Data.Maybe (mapMaybe, listToMaybe, fromMaybe, maybeToList, catMaybes, isJust) import Text.Pandoc.ImageSize import Control.Applicative ((<|>)) import System.FilePath.Glob-import Text.DocTemplates (FromContext(lookupContext))+import Text.DocTemplates (FromContext(lookupContext), Context)+import Text.DocLayout (literal) import Text.TeXMath import Text.Pandoc.Writers.Math (convertMath) import Text.Pandoc.Writers.Powerpoint.Presentation-import Text.Pandoc.Shared (tshow)+import Text.Pandoc.Shared (tshow, stringify) import Skylighting (fromColor) import Data.List.NonEmpty (nonEmpty) @@ -97,6 +99,7 @@ , envDistArchive :: Archive , envUTCTime :: UTCTime , envOpts :: WriterOptions+ , envContext :: Context Text , envPresentationSize :: (Integer, Integer) , envSlideHasHeader :: Bool , envInList :: Bool@@ -122,6 +125,7 @@ , envDistArchive = emptyArchive , envUTCTime = posixSecondsToUTCTime 0 , envOpts = def+ , envContext = mempty , envPresentationSize = (720, 540) , envSlideHasHeader = False , envInList = False@@ -168,7 +172,7 @@ monospaceFont :: Monad m => P m T.Text monospaceFont = do- vars <- writerVariables <$> asks envOpts+ vars <- asks envContext case lookupContext "monofont" vars of Just s -> return s Nothing -> return "Courier"@@ -304,8 +308,9 @@ then Nothing else Just n -presentationToArchive :: PandocMonad m => WriterOptions -> Presentation -> m Archive-presentationToArchive opts pres = do+presentationToArchive :: PandocMonad m+ => WriterOptions -> Meta -> Presentation -> m Archive+presentationToArchive opts meta pres = do distArchive <- toArchive . BL.fromStrict <$> P.readDefaultDataFile "reference.pptx" refArchive <- case writerReferenceDoc opts of@@ -321,10 +326,18 @@ PandocSomeError "Could not determine presentation size" + -- note, we need writerTemplate to be Just _ or metaToContext does+ -- nothing+ context <- metaToContext opts{ writerTemplate =+ writerTemplate opts <|> Just mempty }+ (return . literal . stringify)+ (return . literal . stringify) meta+ let env = def { envRefArchive = refArchive , envDistArchive = distArchive , envUTCTime = utctime , envOpts = opts+ , envContext = context , envPresentationSize = presSize , envSlideIdMap = makeSlideIdMap pres , envSpeakerNotesIdMap = makeSpeakerNotesMap pres
@@ -20,6 +20,7 @@ , setField , resetField , defField+ , getLang , tagWithAttrs , isDisplayMath , fixDisplayMath@@ -147,6 +148,19 @@ where f _newval oldval = oldval +-- | Get the contents of the `lang` metadata field or variable.+getLang :: WriterOptions -> Meta -> Maybe T.Text+getLang opts meta =+ case lookupContext "lang" (writerVariables opts) of+ Just s -> Just s+ _ ->+ case lookupMeta "lang" meta of+ Just (MetaBlocks [Para [Str s]]) -> Just s+ Just (MetaBlocks [Plain [Str s]]) -> Just s+ Just (MetaInlines [Str s]) -> Just s+ Just (MetaString s) -> Just s+ _ -> Nothing+ -- | Produce an HTML tag with the given pandoc attributes. tagWithAttrs :: HasChars a => T.Text -> Attr -> Doc a tagWithAttrs tag (ident,classes,kvs) = hsep@@ -380,6 +394,7 @@ toSuperscript '3' = Just '\x00B3' toSuperscript '+' = Just '\x207A' toSuperscript '-' = Just '\x207B'+toSuperscript '\x2212' = Just '\x207B' -- unicode minus toSuperscript '=' = Just '\x207C' toSuperscript '(' = Just '\x207D' toSuperscript ')' = Just '\x207E'
@@ -146,16 +146,17 @@ blockToTEI opts $ linesToPara lns blockToTEI opts (BlockQuote blocks) = inTagsIndented "quote" <$> blocksToTEI opts blocks-blockToTEI _ (CodeBlock (_,classes,_) str) =+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)- isLang l = T.toLower l `elem` map T.toLower languages+ syntaxMap = writerSyntaxMap opts+ isLang l = T.toLower l `elem` map T.toLower (languages syntaxMap) langsFrom s = if isLang s then [s]- else languagesByExtension . T.toLower $ s+ else (languagesByExtension syntaxMap) . T.toLower $ s langs = concatMap langsFrom classes blockToTEI opts (BulletList lst) = do let attribs = [("type", "unordered")]
@@ -116,7 +116,7 @@ blockToZimWiki _ HorizontalRule = return "\n----\n" blockToZimWiki opts (Header level _ inlines) = do- contents <- inlineListToZimWiki opts $ removeFormatting inlines -- emphasis, links etc. not allowed in headers+ contents <- inlineListToZimWiki opts inlines let eqs = T.replicate ( 7 - level ) "=" return $ eqs <> " " <> contents <> " " <> eqs <> "\n"
@@ -13,6 +13,7 @@ -} module Text.Pandoc.XML ( escapeCharForXML, escapeStringForXML,+ escapeNCName, inTags, selfClosingTag, inTagsSimple,@@ -24,7 +25,7 @@ html5Attributes, rdfaAttributes ) where -import Data.Char (isAscii, isSpace, ord)+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)@@ -119,8 +120,33 @@ 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+-- hexadecimal unicode identifier of the escaped character.+escapeNCName :: Text -> Text+escapeNCName t = case T.uncons t of+ Nothing -> T.empty+ Just (c, cs) -> escapeStartChar c <> T.concatMap escapeNCNameChar cs+ where+ escapeStartChar :: Char -> Text+ escapeStartChar c = if isLetter c || c == '_'+ then T.singleton c+ else escapeChar c --- Unescapes XML entities+ escapeNCNameChar :: Char -> Text+ escapeNCNameChar c = if isNCNameChar c+ then T.singleton c+ else escapeChar c++ isNCNameChar :: Char -> Bool+ isNCNameChar c = isLetter c || c `elem` ("_-.·" :: String) || isDigit c+ || '\x0300' <= c && c <= '\x036f'+ || '\x203f' <= c && c <= '\x2040'++ escapeChar :: Char -> Text+ escapeChar = T.pack . printf "U%04X" . ord++-- | Unescapes XML entities fromEntities :: Text -> Text fromEntities t = let (x, y) = T.break (== '&') t
@@ -53,7 +53,7 @@ data Content = Elem Element | Text CData | CRef Text- deriving (Show, Typeable, Data)+ deriving (Show, Typeable, Data, Ord, Eq) -- | XML elements data Element = Element {@@ -61,7 +61,7 @@ elAttribs :: [Attr], elContent :: [Content], elLine :: Maybe Line- } deriving (Show, Typeable, Data)+ } deriving (Show, Typeable, Data, Ord, Eq) -- | XML attributes data Attr = Attr {@@ -74,13 +74,13 @@ cdVerbatim :: CDataKind, cdData :: Text, cdLine :: Maybe Line- } deriving (Show, Typeable, Data)+ } 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, Show, Typeable, Data )+ deriving ( Eq, Ord, Show, Typeable, Data ) -- | XML qualified names data QName = QName {
@@ -7,17 +7,18 @@ packages: - '.' extra-deps:+- haddock-library-1.10.0 - hslua-1.3.0 - hslua-module-path-0.1.0-- jira-wiki-markup-1.3.4-- skylighting-core-0.10.5-- skylighting-0.10.5-- doclayout-0.3.0.2-- citeproc-0.3.0.9-- texmath-0.12.2+- jira-wiki-markup-1.4.0 - random-1.2.0+- unicode-collation-0.1.3+- citeproc-0.4+- commonmark-0.2+- commonmark-extensions-0.2.1+- commonmark-pandoc-0.2.1 ghc-options: "$locals": -fhide-source-paths -Wno-missing-home-modules-resolver: lts-17.5+resolver: lts-17.12 nix: packages: [zlib]
@@ -130,4 +130,7 @@ def{ readerExtensions = pandocExtensions } contents) let codeblocks = map extractCode $ filter isCodeBlock blocks let cases = zipWith (runCommandTest testExePath fp) [1..] codeblocks- return $ testGroup fp cases+ return $ testGroup fp+ $ if null cases+ then [testCase "!!" $ assertFailure "No command tests defined"]+ else cases
@@ -24,7 +24,7 @@ import Tests.Helpers import Text.Pandoc import qualified Text.Pandoc.Class as P-import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)+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@@ -91,11 +91,11 @@ getMedia archivePath mediaPath = fmap fromEntry . findEntryByPath ("word/" ++ mediaPath) . toArchive <$> B.readFile archivePath -compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool+compareMediaPathIO :: FilePath -> MB.MediaBag -> FilePath -> IO Bool compareMediaPathIO mediaPath mediaBag docxPath = do docxMedia <- getMedia docxPath mediaPath- let mbBS = case lookupMedia mediaPath mediaBag of- Just (_, bs) -> bs+ let mbBS = case MB.lookupMedia mediaPath mediaBag of+ Just item -> MB.mediaContents item Nothing -> error ("couldn't find " ++ mediaPath ++ " in media bag")@@ -110,7 +110,7 @@ mb <- runIOorExplode $ readDocx defopts df >> P.getMediaBag bools <- mapM (\(fp, _, _) -> compareMediaPathIO fp mb docxFile)- (mediaDirectory mb)+ (MB.mediaDirectory mb) return $ and bools testMediaBagIO :: String -> FilePath -> IO TestTree@@ -156,6 +156,10 @@ "docx/image_vml.docx" "docx/image_vml.native" , testCompare+ "VML image as object"+ "docx/image_vml_as_object.docx"+ "docx/image_vml_as_object.native"+ , testCompare "inline image in links" "docx/inline_images.docx" "docx/inline_images.native"@@ -314,13 +318,29 @@ "docx/table_with_list_cell.docx" "docx/table_with_list_cell.native" , testCompare+ "a table with a header which contains rowspans greater than 1"+ "docx/table_header_rowspan.docx"+ "docx/table_header_rowspan.native"+ , testCompare "tables with one row" "docx/table_one_row.docx" "docx/table_one_row.native" , testCompare+ "tables with just one row, which is a header"+ "docx/table_one_header_row.docx"+ "docx/table_one_header_row.native"+ , testCompare "tables with variable width" "docx/table_variable_width.docx" "docx/table_variable_width.native"+ , testCompare+ "tables with captions which contain a Table field"+ "docx/table_captions_with_field.docx"+ "docx/table_captions_with_field.native"+ , testCompare+ "tables with captions which don't contain a Table field"+ "docx/table_captions_no_field.docx"+ "docx/table_captions_no_field.native" , testCompare "code block" "docx/codeblock.docx"
@@ -47,7 +47,7 @@ -- with additional meta tag for cover in EPUB2 format epub3CoverBag :: [(String, String, Int)]-epub3CoverBag = [("wasteland-cover.jpg","image/jpeg",103477)]+epub3CoverBag = [("wasteland-cover.jpg","image/jpeg", 16586)] epub3NoCoverBag :: [(String, String, Int)] epub3NoCoverBag = [("img/check.gif","image/gif",1340)
@@ -99,11 +99,26 @@ plain (codeWith ("",["sample"],[]) "Answer is 42") ] , testGroup "var"- [- test html "inline var block" $- "<var>result</var>" =?>- plain (codeWith ("",["variable"],[]) "result")- ]+ [ test html "inline var block" $+ "<var>result</var>" =?>+ plain (codeWith ("",["variable"],[]) "result")+ ]+ , testGroup "header"+ [ test htmlNativeDivs "<header> is parsed as a div" $+ "<header id=\"title\">Title</header>" =?>+ divWith ("title", mempty, 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')"++ , test html "attributes in pre take precendence" $+ "<pre id=\"c\"><code id=\"d\">\nprint('hi mom!')\n</code></pre>"+ =?>+ codeBlockWith ("c", [], []) "print('hi mom!')"+ ] , askOption $ \(QuickCheckTests numtests) -> testProperty "Round trip" $ withMaxSuccess (if QuickCheckTests numtests == defaultValue
@@ -167,6 +167,14 @@ , "user with description" =: "[John Doe|~johndoe]" =?> para (linkWith ("", ["user-account"], []) "~johndoe" "" "John Doe")++ , "'smart' link" =:+ "[x|http://example.com|smart-link]" =?>+ para (linkWith ("", ["smart-link"], []) "http://example.com" "" "x")++ , "'smart' card" =:+ "[x|http://example.com|smart-card]" =?>+ para (linkWith ("", ["smart-card"], []) "http://example.com" "" "x") ] , "image" =:
@@ -358,7 +358,7 @@ para (text "The value of the " <> math "x" <> text "\8217s and the systems\8217 condition.") , test markdownSmart "unclosed double quote" ("**this should \"be bold**"- =?> para (strong "this should \"be bold"))+ =?> para (strong "this should \8220be bold")) ] , testGroup "footnotes" [ "indent followed by newline and flush-left text" =:@@ -374,8 +374,8 @@ , testGroup "lhs" [ test (purely $ readMarkdown def{ readerExtensions = enableExtension Ext_literate_haskell pandocExtensions })- "inverse bird tracks and html" $- "> a\n\n< b\n\n<div>\n"+ "inverse bird tracks and html"+ $ ("> a\n\n< b\n\n<div>\n" :: Text) =?> codeBlockWith ("",["haskell","literate"],[]) "a" <> codeBlockWith ("",["haskell"],[]) "b"
@@ -176,6 +176,7 @@ , "referenceToText" , "simpleTable" , "simpleTableWithCaption"+ , "tab" -- , "table" , "textMixedStyles" , "tableWithContents"
@@ -39,116 +39,125 @@ (=:) = test context tests :: [TestTree]-tests = [ testGroup "inline code"- [ "with '}'" =: code "}" =?> "\\mono{\\}}"- , "without '}'" =: code "]" =?> "\\type{]}"- , 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 ++ "}"- ]- , testGroup "headers"- [ "level 1" =:- headerWith ("my-header",[],[]) 1 "My header" =?> "\\section[title={My header},reference={my-header}]"- , test contextDiv "section-divs" $- ( headerWith ("header1", [], []) 1 (text "Header1")- <> headerWith ("header2", [], []) 2 (text "Header2")- <> headerWith ("header3", [], []) 3 (text "Header3")- <> headerWith ("header4", [], []) 4 (text "Header4")- <> headerWith ("header5", [], []) 5 (text "Header5")- <> headerWith ("header6", [], []) 6 (text "Header6"))- =?>- unlines [ "\\startsection[title={Header1},reference={header1}]\n"- , "\\startsubsection[title={Header2},reference={header2}]\n"- , "\\startsubsubsection[title={Header3},reference={header3}]\n"- , "\\startsubsubsubsection[title={Header4},reference={header4}]\n"- , "\\startsubsubsubsubsection[title={Header5},reference={header5}]\n"- , "\\startsubsubsubsubsubsection[title={Header6},reference={header6}]\n"- , "\\stopsubsubsubsubsubsection\n"- , "\\stopsubsubsubsubsection\n"- , "\\stopsubsubsubsection\n"- , "\\stopsubsubsection\n"- , "\\stopsubsection\n"- , "\\stopsection" ]- ]- , testGroup "bullet lists"- [ "nested" =:- bulletList [- plain (text "top")- <> bulletList [- plain (text "next")- <> bulletList [plain (text "bot")]- ]- ] =?> unlines- [ "\\startitemize[packed]"- , "\\item"- , " top"- , " \\startitemize[packed]"- , " \\item"- , " next"- , " \\startitemize[packed]"- , " \\item"- , " bot"- , " \\stopitemize"- , " \\stopitemize"- , "\\stopitemize" ]- ]- , testGroup "natural tables"- [ test contextNtb "table with header and caption" $- let capt = text "Table 1"- aligns = [(AlignRight, ColWidthDefault), (AlignLeft, ColWidthDefault), (AlignCenter, ColWidthDefault), (AlignDefault, ColWidthDefault)]- headers = [plain $ text "Right",- plain $ text "Left",- plain $ text "Center",- plain $ text "Default"]- rows = [[plain $ text "1.1",- plain $ text "1.2",- plain $ text "1.3",- plain $ text "1.4"]- ,[plain $ text "2.1",- plain $ text "2.2",- plain $ text "2.3",- plain $ text "2.4"]- ,[plain $ text "3.1",- plain $ text "3.2",- plain $ text "3.3",- plain $ text "3.4"]]- toRow = Row nullAttr . map simpleCell- in table (simpleCaption $ plain capt)- aligns- (TableHead nullAttr [toRow headers])- [TableBody nullAttr 0 [] $ map toRow rows]- (TableFoot nullAttr [])- =?> unlines [ "\\startplacetable[title={Table 1}]"- , "\\startTABLE"- , "\\startTABLEhead"- , "\\NC[align=left] Right"- , "\\NC[align=right] Left"- , "\\NC[align=middle] Center"- , "\\NC Default"- , "\\NC\\NR"- , "\\stopTABLEhead"- , "\\startTABLEbody"- , "\\NC[align=left] 1.1"- , "\\NC[align=right] 1.2"- , "\\NC[align=middle] 1.3"- , "\\NC 1.4"- , "\\NC\\NR"- , "\\NC[align=left] 2.1"- , "\\NC[align=right] 2.2"- , "\\NC[align=middle] 2.3"- , "\\NC 2.4"- , "\\NC\\NR"- , "\\stopTABLEbody"- , "\\startTABLEfoot"- , "\\NC[align=left] 3.1"- , "\\NC[align=right] 3.2"- , "\\NC[align=middle] 3.3"- , "\\NC 3.4"- , "\\NC\\NR"- , "\\stopTABLEfoot"- , "\\stopTABLE"- , "\\stopplacetable" ]- ]- ]+tests =+ [ testGroup "inline code"+ [ "with '}'" =: code "}" =?> "\\mono{\\}}"+ , "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 ++ "}"+ ]+ , testGroup "headers"+ [ "level 1" =:+ headerWith ("my-header",[],[]) 1 "My header" =?>+ "\\section[title={My header},reference={my-header}]"+ , test contextDiv "section-divs" $+ ( headerWith ("header1", [], []) 1 (text "Header1")+ <> headerWith ("header2", [], []) 2 (text "Header2")+ <> headerWith ("header3", [], []) 3 (text "Header3")+ <> headerWith ("header4", [], []) 4 (text "Header4")+ <> headerWith ("header5", [], []) 5 (text "Header5")+ <> headerWith ("header6", [], []) 6 (text "Header6"))+ =?>+ unlines+ [ "\\startsection[title={Header1},reference={header1}]\n"+ , "\\startsubsection[title={Header2},reference={header2}]\n"+ , "\\startsubsubsection[title={Header3},reference={header3}]\n"+ , "\\startsubsubsubsection[title={Header4},reference={header4}]\n"+ , "\\startsubsubsubsubsection[title={Header5},reference={header5}]\n"+ , "\\startsubsubsubsubsubsection[title={Header6},reference={header6}]\n"+ , "\\stopsubsubsubsubsubsection\n"+ , "\\stopsubsubsubsubsection\n"+ , "\\stopsubsubsubsection\n"+ , "\\stopsubsubsection\n"+ , "\\stopsubsection\n"+ , "\\stopsection" ]+ ]+ , testGroup "bullet lists"+ [ "nested" =:+ bulletList [+ plain (text "top")+ <> bulletList [+ plain (text "next")+ <> bulletList [plain (text "bot")]+ ]+ ] =?> unlines+ [ "\\startitemize[packed]"+ , "\\item"+ , " top"+ , " \\startitemize[packed]"+ , " \\item"+ , " next"+ , " \\startitemize[packed]"+ , " \\item"+ , " bot"+ , " \\stopitemize"+ , " \\stopitemize"+ , "\\stopitemize" ]+ ]+ , testGroup "natural tables"+ [ test contextNtb "table with header and caption" $+ let capt = text "Table 1"+ aligns = [ (AlignRight, ColWidthDefault)+ , (AlignLeft, ColWidthDefault)+ , (AlignCenter, ColWidthDefault)+ , (AlignDefault, ColWidthDefault) ]+ headers = [plain $ text "Right",+ plain $ text "Left",+ plain $ text "Center",+ plain $ text "Default"]+ rows = [[plain $ text "1.1",+ plain $ text "1.2",+ plain $ text "1.3",+ plain $ text "1.4"]+ ,[plain $ text "2.1",+ plain $ text "2.2",+ plain $ text "2.3",+ plain $ text "2.4"]+ ,[plain $ text "3.1",+ plain $ text "3.2",+ plain $ text "3.3",+ plain $ text "3.4"]]+ toRow = Row nullAttr . map simpleCell+ in table (simpleCaption $ plain capt)+ aligns+ (TableHead nullAttr [toRow headers])+ [TableBody nullAttr 0 [] $ map toRow rows]+ (TableFoot nullAttr [])+ =?> unlines [ "\\startplacetable[title={Table 1}]"+ , "\\startTABLE"+ , "\\startTABLEhead"+ , "\\NC[align=left] Right"+ , "\\NC[align=right] Left"+ , "\\NC[align=middle] Center"+ , "\\NC Default"+ , "\\NC\\NR"+ , "\\stopTABLEhead"+ , "\\startTABLEbody"+ , "\\NC[align=left] 1.1"+ , "\\NC[align=right] 1.2"+ , "\\NC[align=middle] 1.3"+ , "\\NC 1.4"+ , "\\NC\\NR"+ , "\\NC[align=left] 2.1"+ , "\\NC[align=right] 2.2"+ , "\\NC[align=middle] 2.3"+ , "\\NC 2.4"+ , "\\NC\\NR"+ , "\\stopTABLEbody"+ , "\\startTABLEfoot"+ , "\\NC[align=left] 3.1"+ , "\\NC[align=right] 3.2"+ , "\\NC[align=middle] 3.3"+ , "\\NC 3.4"+ , "\\NC\\NR"+ , "\\stopTABLEfoot"+ , "\\stopTABLE"+ , "\\stopplacetable" ]+ ]+ ]
@@ -112,6 +112,11 @@ "docx/tables.native" "docx/golden/tables.docx" , docxTest+ "tables without explicit column widths"+ def+ "docx/tables-default-widths.native"+ "docx/golden/tables-default-widths.docx"+ , docxTest "tables with lists in cells" def "docx/table_with_list_cell.native"
@@ -34,55 +34,60 @@ (=:) = test html tests :: [TestTree]-tests = [ testGroup "inline code"- [ "basic" =: code "@&" =?> "<code>@&</code>"- , "haskell" =: codeWith ("",["haskell"],[]) ">>="- =?> "<code class=\"sourceCode haskell\"><span class=\"op\">>>=</span></code>"- , "nolanguage" =: codeWith ("",["nolanguage"],[]) ">>="- =?> "<code class=\"nolanguage\">>>=</code>"- ]- , testGroup "images"- [ "alt with formatting" =:- image "/url" "title" ("my " <> emph "image")- =?> "<img src=\"/url\" title=\"title\" alt=\"my image\" />"- ]- , testGroup "blocks"- [ "definition list with empty <dt>" =:- definitionList [(mempty, [para $ text "foo bar"])]- =?> "<dl><dt></dt><dd><p>foo bar</p></dd></dl>"- ]- , testGroup "quotes"- [ "quote with cite attribute (without q-tags)" =:- doubleQuoted (spanWith ("", [], [("cite", "http://example.org")]) (str "examples"))- =?> "“<span cite=\"http://example.org\">examples</span>”"- , tQ "quote with cite attribute (with q-tags)" $- doubleQuoted (spanWith ("", [], [("cite", "http://example.org")]) (str "examples"))- =?> "<q cite=\"http://example.org\">examples</q>"- ]- , testGroup "sample"- [ "sample should be rendered correctly" =:- plain (codeWith ("",["sample"],[]) "Answer is 42") =?>- "<samp>Answer is 42</samp>"- ]- , testGroup "variable"- [ "variable should be rendered correctly" =:- plain (codeWith ("",["variable"],[]) "result") =?>- "<var>result</var>"- ]- , testGroup "sample with style"- [ "samp should wrap highlighted code" =:- codeWith ("",["sample","haskell"],[]) ">>="- =?> ("<samp><code class=\"sourceCode haskell\">" ++- "<span class=\"op\">>>=</span></code></samp>")- ]- , testGroup "variable with style"- [ "var should wrap highlighted code" =:- codeWith ("",["haskell","variable"],[]) ">>="- =?> ("<var><code class=\"sourceCode haskell\">" ++- "<span class=\"op\">>>=</span></code></var>")- ]- ]- where- tQ :: (ToString a, ToPandoc a)- => String -> (a, String) -> TestTree- tQ = test htmlQTags+tests =+ [ testGroup "inline code"+ [ "basic" =: code "@&" =?> "<code>@&</code>"+ , "haskell" =: codeWith ("",["haskell"],[]) ">>="+ =?> "<code class=\"sourceCode haskell\"><span class=\"op\">>>=</span></code>"+ , "nolanguage" =: codeWith ("",["nolanguage"],[]) ">>="+ =?> "<code class=\"nolanguage\">>>=</code>"+ ]+ , testGroup "images"+ [ "alt with formatting" =:+ image "/url" "title" ("my " <> emph "image")+ =?> "<img src=\"/url\" title=\"title\" alt=\"my image\" />"+ ]+ , testGroup "blocks"+ [ "definition list with empty <dt>" =:+ definitionList [(mempty, [para $ text "foo bar"])]+ =?> "<dl><dt></dt><dd><p>foo bar</p></dd></dl>"+ , "heading with disallowed attributes" =:+ headerWith ("", [], [("invalid","1"), ("lang", "en")]) 1 "test"+ =?>+ "<h1 lang=\"en\">test</h1>"+ ]+ , testGroup "quotes"+ [ "quote with cite attribute (without q-tags)" =:+ doubleQuoted (spanWith ("", [], [("cite", "http://example.org")]) (str "examples"))+ =?> "“<span cite=\"http://example.org\">examples</span>”"+ , tQ "quote with cite attribute (with q-tags)" $+ doubleQuoted (spanWith ("", [], [("cite", "http://example.org")]) (str "examples"))+ =?> "<q cite=\"http://example.org\">examples</q>"+ ]+ , testGroup "sample"+ [ "sample should be rendered correctly" =:+ plain (codeWith ("",["sample"],[]) "Answer is 42") =?>+ "<samp>Answer is 42</samp>"+ ]+ , testGroup "variable"+ [ "variable should be rendered correctly" =:+ plain (codeWith ("",["variable"],[]) "result") =?>+ "<var>result</var>"+ ]+ , testGroup "sample with style"+ [ "samp should wrap highlighted code" =:+ codeWith ("",["sample","haskell"],[]) ">>="+ =?> ("<samp><code class=\"sourceCode haskell\">" +++ "<span class=\"op\">>>=</span></code></samp>")+ ]+ , testGroup "variable with style"+ [ "var should wrap highlighted code" =:+ codeWith ("",["haskell","variable"],[]) ">>="+ =?> ("<var><code class=\"sourceCode haskell\">" +++ "<span class=\"op\">>>=</span></code></var>")+ ]+ ]+ where+ tQ :: (ToString a, ToPandoc a)+ => String -> (a, String) -> TestTree+ tQ = test htmlQTags
@@ -1,21 +1,21 @@ {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.JATS (tests) where -import Data.Text (unpack)+import Data.Text (Text) import Test.Tasty import Tests.Helpers import Text.Pandoc import Text.Pandoc.Arbitrary () import Text.Pandoc.Builder+import qualified Data.Text as T -jats :: (ToPandoc a) => a -> String-jats = unpack- . purely (writeJATS def{ writerWrapText = WrapNone })- . toPandoc+jats :: (ToPandoc a) => a -> Text+jats = purely (writeJATS def{ writerWrapText = WrapNone })+ . toPandoc -jatsArticleAuthoring :: (ToPandoc a) => a -> String-jatsArticleAuthoring = unpack- . purely (writeJatsArticleAuthoring def{ writerWrapText = WrapNone })+jatsArticleAuthoring :: (ToPandoc a) => a -> Text+jatsArticleAuthoring =+ purely (writeJatsArticleAuthoring def{ writerWrapText = WrapNone }) . toPandoc {-@@ -32,89 +32,133 @@ infix 4 =: (=:) :: (ToString a, ToPandoc a)- => String -> (a, String) -> TestTree+ => String -> (a, Text) -> TestTree (=:) = test jats tests :: [TestTree]-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>"- , "lang" =: codeBlockWith ("", ["c"], []) "@&" =?> "<code language=\"c\">@&</code>"- ]- , testGroup "images"- [ "basic" =:- image "/url" "title" mempty- =?> "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />"- ]- , testGroup "inlines"- [ "Emphasis" =: emph "emphasized"- =?> "<p><italic>emphasized</italic></p>"+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>"+ , "lang" =: codeBlockWith ("", ["c"], []) "@&" =?> "<code language=\"c\">@&</code>"+ ]+ , testGroup "images"+ [ "basic" =:+ image "/url" "title" mempty+ =?> "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />"+ ]+ , testGroup "inlines"+ [ "Emphasis" =: emph "emphasized"+ =?> "<p><italic>emphasized</italic></p>" - , test jatsArticleAuthoring "footnote in articleauthoring tag set"- ("test" <> note (para "footnote") =?>- unlines [ "<p>test<fn>"- , " <p>footnote</p>"- , "</fn></p>"- ])- ]- , "bullet list" =: bulletList [ plain $ text "first"- , plain $ text "second"- , plain $ text "third"- ]- =?> "<list list-type=\"bullet\">\n\- \ <list-item>\n\- \ <p>first</p>\n\- \ </list-item>\n\- \ <list-item>\n\- \ <p>second</p>\n\- \ </list-item>\n\- \ <list-item>\n\- \ <p>third</p>\n\- \ </list-item>\n\- \</list>"- , testGroup "definition lists"- [ "with internal link" =: definitionList [(link "#go" "" (str "testing"),- [plain (text "hi there")])] =?>- "<def-list>\n\- \ <def-item>\n\- \ <term><xref alt=\"testing\" rid=\"go\">testing</xref></term>\n\- \ <def>\n\- \ <p>hi there</p>\n\- \ </def>\n\- \ </def-item>\n\- \</def-list>"- ]- , testGroup "math"- [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>- "<p><inline-formula><alternatives>\n\- \<tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\- \<mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula></p>"- ]- , testGroup "headers"- [ "unnumbered header" =:- headerWith ("foo",["unnumbered"],[]) 1- (text "Header 1" <> note (plain $ text "note")) =?>- "<sec id=\"foo\">\n\- \ <title>Header 1<xref ref-type=\"fn\" rid=\"fn1\">1</xref></title>\n\- \</sec>"- , "unnumbered sub header" =:- headerWith ("foo",["unnumbered"],[]) 1- (text "Header")- <> headerWith ("foo",["unnumbered"],[]) 2- (text "Sub-Header") =?>- "<sec id=\"foo\">\n\- \ <title>Header</title>\n\- \ <sec id=\"foo\">\n\- \ <title>Sub-Header</title>\n\- \ </sec>\n\- \</sec>"- , "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\- \</sec>"- ]- ]+ , test jatsArticleAuthoring "footnote in articleauthoring tag set"+ ("test" <> note (para "footnote") =?>+ unlines [ "<p>test<fn>"+ , " <p>footnote</p>"+ , "</fn></p>"+ ])+ ]+ , "bullet list" =: bulletList [ plain $ text "first"+ , plain $ text "second"+ , plain $ text "third"+ ]+ =?> "<list list-type=\"bullet\">\n\+ \ <list-item>\n\+ \ <p>first</p>\n\+ \ </list-item>\n\+ \ <list-item>\n\+ \ <p>second</p>\n\+ \ </list-item>\n\+ \ <list-item>\n\+ \ <p>third</p>\n\+ \ </list-item>\n\+ \</list>"+ , testGroup "definition lists"+ [ "with internal link" =: definitionList [(link "#go" "" (str "testing"),+ [plain (text "hi there")])] =?>+ "<def-list>\n\+ \ <def-item>\n\+ \ <term><xref alt=\"testing\" rid=\"go\">testing</xref></term>\n\+ \ <def>\n\+ \ <p>hi there</p>\n\+ \ </def>\n\+ \ </def-item>\n\+ \</def-list>"+ ]+ , testGroup "math"+ [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>+ "<p><inline-formula><alternatives>\n\+ \<tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\+ \<mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula></p>"+ ]+ , testGroup "headers"+ [ "unnumbered header" =:+ headerWith ("foo",["unnumbered"],[]) 1+ (text "Header 1" <> note (plain $ text "note")) =?>+ "<sec id=\"foo\">\n\+ \ <title>Header 1<xref ref-type=\"fn\" rid=\"fn1\">1</xref></title>\n\+ \</sec>"+ , "unnumbered sub header" =:+ headerWith ("foo",["unnumbered"],[]) 1+ (text "Header")+ <> headerWith ("foo",["unnumbered"],[]) 2+ (text "Sub-Header") =?>+ "<sec id=\"foo\">\n\+ \ <title>Header</title>\n\+ \ <sec id=\"foo\">\n\+ \ <title>Sub-Header</title>\n\+ \ </sec>\n\+ \</sec>"+ , "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\+ \</sec>"+ ]++ , testGroup "ids"+ [ "non-ASCII in header ID" =:+ headerWith ("smørbrød",[],[]) 1 (text "smørbrød") =?>+ T.unlines [ "<sec id=\"smørbrød\">"+ , " <title>smørbrød</title>"+ , "</sec>"+ ]++ , "disallowed symbol in header id" =:+ headerWith ("i/o",[],[]) 1 (text "I/O") =?>+ T.unlines [ "<sec id=\"iU002Fo\">"+ , " <title>I/O</title>"+ , "</sec>"+ ]++ , "disallowed symbols in internal link target" =:+ link "#foo:bar" "" "baz" =?>+ "<p><xref alt=\"baz\" rid=\"fooU003Abar\">baz</xref></p>"++ , "code id starting with a number" =:+ codeWith ("7y",[],[]) "print 5" =?>+ "<p><monospace id=\"U0037y\">print 5</monospace></p>"+ ]++ , testGroup "spans"+ [ "unwrapped if no attributes given" =:+ spanWith nullAttr "text in span" =?>+ "<p>text in span</p>"++ , "converted to named-content element if class given" =:+ spanWith ("a", ["genus-species"], [("alt", "aa")]) "C. elegans" =?>+ ("<p><named-content id=\"a\" alt=\"aa\" content-type=\"genus-species\">"+ <> "C. elegans</named-content></p>")++ , "unwrapped if styled-content element would have no attributes" =:+ spanWith ("", [], [("hidden", "true")]) "text in span" =?>+ "<p>text in span</p>"++ , "use content-type attribute if present" =:+ spanWith ("", [], [("content-type", "species")]) "E. coli" =?>+ "<p><named-content content-type=\"species\">E. coli</named-content></p>"+ ]+ ]
@@ -61,12 +61,24 @@ , "user link with user as description" =: linkWith ("", ["user-account"], []) "~johndoe" "" "~johndoe" =?> "[~johndoe]"++ , "'smart' link" =:+ para (linkWith ("", ["smart-link"], []) "http://example.com" "" "x") =?>+ "[x|http://example.com|smart-link]"++ , "'smart' card" =:+ para (linkWith ("", ["smart-card"], []) "http://example.org" "" "x") =?>+ "[x|http://example.org|smart-card]" ] , testGroup "spans" [ "id is used as anchor" =: spanWith ("unicorn", [], []) (str "Unicorn") =?> "{anchor:unicorn}Unicorn"++ , "use `color` attribute" =:+ spanWith ("",[],[("color","red")]) "ruby" =?>+ "{color:red}ruby{color}" ] , testGroup "code"
@@ -9,7 +9,7 @@ [^1]: Dept. of This and That ^D ----author: "John Doe[^1]"+author: John Doe[^1] date: 2014 title: My Article ---
@@ -0,0 +1,8 @@+```+pandoc -t latex+| A happy pandoc user said "fix this bug please+| or I'll go crazy!"+^D+A happy pandoc user said ``fix this bug please\\+or I'll go crazy!''+```
@@ -0,0 +1,60 @@+```+% pandoc command/chap1/text.md command/chap2/text.md -f markdown+rebase_relative_paths --verbose -t docx | pandoc -f docx -t plain+^D+[INFO] Loaded command/chap1/spider.png from ./command/chap1/spider.png+[INFO] Loaded command/chap2/spider.png from ./command/chap2/spider.png+[INFO] Loaded command/chap1/../../lalune.jpg from ./command/chap1/../../lalune.jpg+Chapter one++A spider: [spider]++Another spider: [another spider]++The moon: [moon]++Link to spider picture.++URL left alone: manual.++Absolute path left alone: absolute.++Link to fragment: chapter two.++Empty path: empty.++Chapter two++A spider: [spider]+```++```+% pandoc command/chap1/text.md command/chap2/text.md -f markdown+rebase_relative_paths -t html+^D+<h1 id="chapter-one">Chapter one</h1>+<p>A spider: <img src="command/chap1/spider.png" alt="spider" /></p>+<p>Another spider: <img src="command/chap2/spider.png" alt="another spider" /></p>+<p>The moon: <img src="command/chap1/../../lalune.jpg" alt="moon" /></p>+<p>Link to <a href="command/chap1/spider.png">spider picture</a>.</p>+<p>URL left alone: <a href="https://pandoc.org/MANUAL.html">manual</a>.</p>+<p>Absolute path left alone: <a href="/foo/bar/baz.png">absolute</a>.</p>+<p>Link to fragment: <a href="#chapter-two">chapter two</a>.</p>+<p>Empty path: <a href="">empty</a>.</p>+<h1 id="chapter-two">Chapter two</h1>+<p>A spider: <img src="command/chap2/spider.png" alt="spider" /></p>+```++```+% pandoc command/chap1/text.md command/chap2/text.md -f commonmark+rebase_relative_paths -t html+^D+<h1>Chapter one</h1>+<p>A spider: <img src="command/chap1/spider.png" alt="spider" /></p>+<p>Another spider: <img src="command/chap2/spider.png" alt="another spider" /></p>+<p>The moon: <img src="command/chap1/../../lalune.jpg" alt="moon" /></p>+<p>Link to <a href="command/chap1/spider.png">spider picture</a>.</p>+<p>URL left alone: <a href="https://pandoc.org/MANUAL.html">manual</a>.</p>+<p>Absolute path left alone: <a href="/foo/bar/baz.png">absolute</a>.</p>+<p>Link to fragment: <a href="#chapter-two">chapter two</a>.</p>+<p>Empty path: <a href="">empty</a>.</p>+<h1>Chapter two</h1>+<p>A spider: <img src="command/chap2/spider.png" alt="spider" /></p>+```
@@ -6,7 +6,7 @@ ok ^D ----title: \<this\> \*that\*+title: \<this> \*that\* --- ok
@@ -0,0 +1,29 @@+```+% pandoc -f html -t native+<table>+<colgroup>+ <col width="30%" />+ <col width="*" />+</colgroup>+<tr>+ <td>1</td>+ <td>2</td>+</tr>+</table>+^D+[Table ("",[],[]) (Caption Nothing+ [])+ [(AlignDefault,ColWidth 0.3)+ ,(AlignDefault,ColWidth 0.7)]+ (TableHead ("",[],[])+ [])+ [(TableBody ("",[],[]) (RowHeadColumns 0)+ []+ [Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "1"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "2"]]]])]+ (TableFoot ("",[],[])+ [])]+```
@@ -26,6 +26,6 @@ Here is inline html: -\<div\> \<balise\> bla bla \</div\>+\<div> \<balise> bla bla \</div> ```
@@ -5,5 +5,5 @@ ^D \newcommand{\myFruit}{Mango\xspace} -Mango\xspace is the king of fruits.+Mango is the king of fruits. ```
@@ -11,7 +11,7 @@ ... ``` ^D-``` {.markdown}+``` markdown `«sträng»` `` «sträng» ``
@@ -6,7 +6,7 @@ ``` `````` ^D-```` {.attr}+```` attr ``` code ```
@@ -0,0 +1,19 @@+```+% pandoc -t native+@{https://openreview.net/forum?id=HkwoSDPgg}++@https://openreview.net/forum?id=HkwoSDPgg+^D+[Para [Cite [Citation {citationId = "https://openreview.net/forum?id=HkwoSDPgg", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 1, citationHash = 0}] [Str "@https://openreview.net/forum?id=HkwoSDPgg"]]+,Para [Cite [Citation {citationId = "https://openreview.net/forum?id", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 2, citationHash = 0}] [Str "@https://openreview.net/forum?id"],Str "=HkwoSDPgg"]]+```+```+% pandoc -t markdown+@{https://openreview.net/forum?id=HkwoSDPgg}++@https://openreview.net/forum?id=HkwoSDPgg+^D+@{https://openreview.net/forum?id=HkwoSDPgg}++@https://openreview.net/forum?id=HkwoSDPgg+```
@@ -0,0 +1,27 @@+```+% pandoc -f docbook -t markdown -s+<?xml version="1.0"?>+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">+<book>++<bookinfo>+<title>Title</title>+<author>+<firstname>Firstname</firstname><surname>Lastname</surname>+</author>+<releaseinfo>1.17</releaseinfo>+</bookinfo>++<para>Text.</para>++</book>+^D+---+author: Firstname Lastname+releaseinfo: 1.17+title: Title+---++Text.+```
@@ -7,9 +7,12 @@ \SI{0.135(21)}{\m} \SI{12.3(60)}{\m}++\SI{10.0 \pm 3.3}{\ms} ^D <p>23 ± 2 m</p> <p>125 ± 12 m</p> <p>0.135 ± 0.021 m</p> <p>12.3 ± 6 m</p>+<p>10.0 ± 3.3 ms</p> ```
@@ -0,0 +1,75 @@+```+pandoc -f latex -t html+\num{12345,67890}++\num{1+-2i}++\num{.3e45}++\num{1.654 x 2.34 x 3.430}++\si{kg.m.s^{-1}}++\si{\kilogram\metre\per\second}++\si[per-mode=symbol]{\kilogram\metre\per\second}++\si[per-mode=symbol]{\kilogram\metre\per\ampere\per\second}++\numlist{10;20;30}++\SIlist{0.13;0.67;0.80}{\milli\metre}++\numrange{10}{20}++\SIrange{0.13}{0.67}{\milli\metre}++\ang{10}++\ang{1;2;3}++\ang{;;1}++\ang{+10;;}++\ang{-0;1;}++\si{kg.m/s^2}++\si{g_{polymer}~mol_{cat}.s^{-1}}++\si{\kilo\gram\metre\per\square\second}++\si{\gram\per\cubic\centi\metre}++\si{\square\volt\cubic\lumen\per\farad}++\si{\metre\squared\per\gray\cubic\lux}++\si{\henry\second}+^D+<p>12345.67890</p>+<p>1 ± 2i</p>+<p>0.3 × 10<sup>45</sup></p>+<p>1.654 × 2.34 × 3.430</p>+<p>kg m s<sup>−1</sup></p>+<p>kg m s<sup>−1</sup></p>+<p>kg m/s</p>+<p>kg m/A/s</p>+<p>10, 20, & 30</p>+<p>0.13 mm, 0.67 mm, & 0.80 mm</p>+<p>10–20</p>+<p>0.13 mm–0.67 mm</p>+<p>10°</p>+<p>1°2′3″</p>+<p>1″</p>+<p>10°</p>+<p>-0°1′</p>+<p>kg m/s<sup>2</sup></p>+<p>g<sub>polymer</sub> mol<sub>cat</sub> s<sup>−1</sup></p>+<p>kg m s<sup>−2</sup></p>+<p>g cm<sup>−3</sup></p>+<p>V<sup>2</sup> lm<sup>3</sup> F<sup>−1</sup></p>+<p>m<sup>2</sup> Gy<sup>−1</sup> lx<sup>3</sup></p>+<p>H s</p>+```
@@ -0,0 +1,11 @@+Tabs must be expanded even if --file-scope is used+````+% pandoc -t native --file-scope --tab-stop=2+```+if true; then+ echo "yup"+fi+```+^D+[CodeBlock ("",[],[]) "if true; then\n echo \"yup\"\nfi"]+````
@@ -20,13 +20,13 @@ \end{thm2} \end{document} ^D-::: {.thm}+::: thm **Theorem 1**. *a*  ::: -::: {.thm2}+::: thm2 **Theorem 1**. a 
@@ -0,0 +1,10 @@+Add thin space between single and double quotes.+```+% pandoc -t latex+smart+---+lang: en-GB+---+'["On the Outside"]{}: Constructing Cycling Citizenship.'+^D+`\,{``On the Outside''}: Constructing Cycling Citizenship.'+```
@@ -0,0 +1,23 @@+```+% pandoc -f html -t jats+<table>+ <tr><td><blockquote>Fly, you fools!</blockquote></td></tr>+</table>+^D+<table-wrap>+ <table>+ <colgroup>+ <col width="100%" />+ </colgroup>+ <tbody>+ <tr>+ <td><p specific-use="wrapper">+ <disp-quote>+ <p>Fly, you fools!</p>+ </disp-quote>+ </p></td>+ </tr>+ </tbody>+ </table>+</table-wrap>+```
@@ -11,7 +11,7 @@ <iframe src="h:invalid@url"></iframe> ^D [INFO] Fetching h:invalid@url...-[WARNING] Could not fetch resource 'h:invalid@url': Could not fetch h:invalid@url+[WARNING] Could not fetch resource h:invalid@url: Could not fetch h:invalid@url InvalidUrlException "h:invalid@url" "Invalid scheme" [INFO] Skipped '<iframe src="h:invalid@url"></iframe>' at input line 1 column 29 []
@@ -0,0 +1,137 @@+```+% pandoc -f docbook -t latex+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE article PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">+<?xml-model href="http://www.oxygenxml.com/docbook/xml/5.0/rng/dbmathml.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>+<?xml-model href="http://docbook.org/xml/5.0/rng/docbook.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>+<article xmlns="http://docbook.org/ns/docbook"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ version="5.1">+ <title>Untitled Document</title>+ <para>Word</para>+ <informalequation>+ <alt role='tex'>1+2</alt>+ <m:math xmlns:m="http://www.w3.org/1998/Math/MathML">+ <m:mrow>+ <m:mrow><m:mn>1</m:mn><m:mo>+</m:mo><m:mn>2</m:mn>+ </m:mrow>+ </m:mrow>+ </m:math>+ </informalequation>+</article>+^D+Word++\[1 + 2\]+```++```+% pandoc -f docbook -t latex+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE article PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">+<?xml-model href="http://www.oxygenxml.com/docbook/xml/5.0/rng/dbmathml.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>+<?xml-model href="http://docbook.org/xml/5.0/rng/docbook.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>+<article xmlns="http://docbook.org/ns/docbook"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ version="5.1">+ <title>Untitled Document</title>+ <para>Word</para>+ <informalequation>+ <alt role='tex'>1+2</alt>+ <mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML">+ <mml:mrow>+ <mml:mrow><mml:mn>1</mml:mn><mml:mo>+</mml:mo><mml:mn>2</mml:mn>+ </mml:mrow>+ </mml:mrow>+ </mml:math>+ </informalequation>+</article>+^D+Word++\[1 + 2\]+```++```+% pandoc -f docbook -t latex+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE article PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">+<?xml-model href="http://www.oxygenxml.com/docbook/xml/5.0/rng/dbmathml.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>+<?xml-model href="http://docbook.org/xml/5.0/rng/docbook.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>+<article xmlns="http://docbook.org/ns/docbook"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ version="5.1">+ <title>Untitled Document</title>+ <para>Word</para>+ <informalequation>+ <alt role='tex'>1+2</alt>+ <math xmlns="http://www.w3.org/1998/Math/MathML">+ <mrow>+ <mrow><mn>1</mn><mo>+</mo><mn>2</mn>+ </mrow>+ </mrow>+ </math>+ </informalequation>+</article>+^D+Word++\[1 + 2\]+```++```+% pandoc -f docbook -t latex+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE article PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">+<?xml-model href="http://www.oxygenxml.com/docbook/xml/5.0/rng/dbmathml.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>+<?xml-model href="http://docbook.org/xml/5.0/rng/docbook.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>+<article xmlns="http://docbook.org/ns/docbook"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:m="http://www.w3.org/1998/Math/MathML"+ version="5.1">+ <title>Untitled Document</title>+ <para>Word</para>+ <informalequation>+ <alt role='tex'>1+2</alt>+ <m:math>+ <m:mrow>+ <m:mrow><m:mn>1</m:mn><m:mo>+</m:mo><m:mn>2</m:mn>+ </m:mrow>+ </m:mrow>+ </m:math>+ </informalequation>+</article>+^D+Word++\[1 + 2\]+```++```+% pandoc -f docbook -t latex+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE article PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">+<?xml-model href="http://www.oxygenxml.com/docbook/xml/5.0/rng/dbmathml.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>+<?xml-model href="http://docbook.org/xml/5.0/rng/docbook.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>+<article xmlns="http://docbook.org/ns/docbook"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:mml="http://www.w3.org/1998/Math/MathML"+ version="5.1">+ <title>Untitled Document</title>+ <para>Word</para>+ <informalequation>+ <alt role='tex'>1+2</alt>+ <mml:math>+ <mml:mrow>+ <mml:mrow><mml:mn>1</mml:mn><mml:mo>+</mml:mo><mml:mn>2</mml:mn>+ </mml:mrow>+ </mml:mrow>+ </mml:math>+ </informalequation>+</article>+^D+Word++\[1 + 2\]+```+
@@ -0,0 +1,6 @@+```+% pandoc -t gfm+\<hi\>+^D+\<hi>+```
@@ -0,0 +1,28 @@+```+% pandoc++------------+----------+------------------++|日本語 | の文字列 | words in english |++------------+----------+------------------++|abc defghij | def | xyz |++------------+----------+------------------++^D+<table style="width:60%;">+<colgroup>+<col style="width: 18%" />+<col style="width: 15%" />+<col style="width: 26%" />+</colgroup>+<tbody>+<tr class="odd">+<td>日本語</td>+<td>の文字列</td>+<td>words in english</td>+</tr>+<tr class="even">+<td>abc defghij</td>+<td>def</td>+<td>xyz</td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,19 @@+```+pandoc -t latex+"This is some text in quotes. Another paragraph by the same speaker follows. The first paragraph should have no close quote.++"The second paragraph should have open and close quotes."++| "Open quote on this line,+| Close quote on the next line."+| "Quotes on the same line."+^D+``This is some text in quotes. Another paragraph by the same speaker+follows. The first paragraph should have no close quote.++``The second paragraph should have open and close quotes.''++``Open quote on this line,\\+Close quote on the next line.''\\+``Quotes on the same line.''+```
@@ -0,0 +1,10 @@+```+% pandoc -f biblatex -t biblatex -s+@article{id,+ annote = "annotation"+}+^D+@article{id,+ annote = {annotation}+}+```
@@ -0,0 +1,24 @@+```+% pandoc -t latex -f html+<table>+ <tbody>+ <tr>+ <td>+ <span>+ text+ <br />+ text2+ </span>+ </td>+ </tr>+ </tbody>+</table>+^D+\begin{longtable}[]{@{}+ >{\raggedright\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{1.00}}@{}}+\toprule+\endhead+{\vtop{\hbox{\strut text}\hbox{\strut text2 }}} \\+\bottomrule+\end{longtable}+```
@@ -0,0 +1,38 @@+```+% pandoc -t beamer+# Slide++Some blocks:++## example block title {.example}++text in block++## alert block title {.alert}++text in block++## block title++text in block+^D+\begin{frame}{Slide}+\protect\hypertarget{slide}{}+Some blocks:++\begin{exampleblock}{example block title}+\protect\hypertarget{example-block-title}{}+text in block+\end{exampleblock}++\begin{alertblock}{alert block title}+\protect\hypertarget{alert-block-title}{}+text in block+\end{alertblock}++\begin{block}{block title}+\protect\hypertarget{block-title}{}+text in block+\end{block}+\end{frame}+```
@@ -0,0 +1,7 @@+Don't crash on unmatched closing tag.+```+% pandoc -f html -t native+</script>+^D+[]+```
@@ -0,0 +1,40 @@+```+% pandoc -f rst -t ms+.. list-table::+ :widths: 50 50+ :header-rows: 1++ * - Left+ - Right+ * - Long text that should be easy to break up into multiple lines+ - Another long text that should be easy to break up into multiple lines++ Bar+^D+.PP+.na+.nr LLold \n[LL]+.TS+delim(@@) tab( );+lw(35.0n) lw(35.0n).+T{+Left+T} T{+Right+T}+_+T{+.nr LL 35.0n+.LP+Long text that should be easy to break up into multiple lines+T} T{+.nr LL 35.0n+.PP+Another long text that should be easy to break up into multiple lines+.PP+Bar+T}+.TE+.nr LL \n[LLold]+.ad+```
@@ -0,0 +1,23 @@+```+% pandoc -f latex -t plain+$1-{\ensuremath{r}\xspace}$+^D+1 − r+```++```+% pandoc -f latex -t plain+\newcommand{\foo}{Foo\xspace}++$\text{\foo bar}$+^D+Foo bar+```++```+% pandoc -f latex -t plain+a\xspace b+^D+a b+```+
@@ -0,0 +1,24 @@+```+% pandoc -t plain --citeproc --wrap=none+---+references:+- id: fenner2012a+ title: One-click science marketing+ author:+ - family: Fenner+ given: Martin+ container-title: Nature Materials+ volume: 11+ issue: 4+ publisher: Nature Publishing Group+ type: article-journal+ issued:+ year: 2012+---++[@fenner2012a, $a^2+b^2=c^2$]+^D+(Fenner 2012, a² + b² = c²)++Fenner, Martin. 2012. “One-Click Science Marketing.” Nature Materials 11 (4).+```
@@ -0,0 +1,29 @@+```+% pandoc --citeproc -t plain+---+references:+- id: smith+ author: John Smith+ issued: 2019+ title: Insects+ type: book+...++@smith [chap. 6]++@smith [chapter 6]++@smith [Chap. 6]++@smith [Chapter 6]+^D+John Smith (2019, chap. 6)++John Smith (2019, chap. 6)++John Smith (2019, chap. 6)++John Smith (2019, chap. 6)++John Smith. 2019. Insects.+```
@@ -0,0 +1,25 @@+```+% pandoc --citeproc -t plain+---+references:+- id: smith+ author: John Smith+ issued: 2019+ title: Insects+ type: book+...++@smith [, among others]++@smith [ among others]++@smith [among others]+^D+John Smith (2019, among others)++John Smith (2019 among others)++John Smith (2019, among others)++John Smith. 2019. Insects.+```
@@ -0,0 +1,95 @@+@string{anch-ie = {Angew.~Chem. Int.~Ed.}}+@string{cup = {Cambridge University Press}}+@string{dtv = {Deutscher Taschenbuch-Verlag}}+@string{hup = {Harvard University Press}}+@string{jams = {J.~Amer. Math. Soc.}}+@string{jchph = {J.~Chem. Phys.}}+@string{jomch = {J.~Organomet. Chem.}}+@string{pup = {Princeton University Press}}++@book{averroes/bland,+ author = {Averroes},+ title = {The Epistle on the Possibility of Conjunction with the Active+ Intellect by {Ibn Rushd} with the Commentary of {Moses Narboni}},+ date = 1982,+ editor = {Bland, Kalman P.},+ translator = {Bland, Kalman P.},+ series = {Moreshet: Studies in {Jewish} History, Literature and Thought},+ number = 7,+ publisher = {Jewish Theological Seminary of America},+ location = {New York},+ keywords = {primary},+ langid = {english},+ langidopts = {variant=american},+ indextitle = {Epistle on the Possibility of Conjunction, The},+ shorttitle = {Possibility of Conjunction},+ annotation = {A \texttt{book} entry with a \texttt{series} and a+ \texttt{number}. Note the concatenation of the \texttt{editor}+ and \texttt{translator} fields as well as the+ \texttt{indextitle} field},+}++@book{averroes/hannes,+ author = {Averroes},+ title = {Des Averro{\"e}s Abhandlung: \mkbibquote{{\"U}ber die+ M{\"o}glichkeit der Conjunktion} oder \mkbibquote{{\"U}ber den+ materiellen Intellekt}},+ date = 1892,+ editor = {Hannes, Ludwig},+ translator = {Hannes, Ludwig},+ annotator = {Hannes, Ludwig},+ publisher = {C.~A. Kaemmerer},+ location = {Halle an der Saale},+ keywords = {primary},+ langid = {german},+ sorttitle = {Uber die Moglichkeit der Conjunktion},+ indexsorttitle= {Uber die Moglichkeit der Conjunktion},+ indextitle = {{\"U}ber die M{\"o}glichkeit der Conjunktion},+ shorttitle = {{\"U}ber die M{\"o}glichkeit der Conjunktion},+ annotation = {An annotated edition. Note the concatenation of the+ \texttt{editor}, \texttt{translator}, and \texttt{annotator}+ fields. Also note the \texttt{shorttitle},+ \texttt{indextitle}, \texttt{sorttitle}, and+ \texttt{indexsorttitle} fields},+}++@book{averroes/hercz,+ author = {Averroes},+ title = {Drei Abhandlungen {\"u}ber die Conjunction des separaten+ Intellects mit dem Menschen},+ date = 1869,+ editor = {Hercz, J.},+ translator = {Hercz, J.},+ publisher = {S.~Hermann},+ location = {Berlin},+ keywords = {primary},+ langid = {german},+ indexsorttitle= {Drei Abhandlungen uber die Conjunction},+ indextitle = {Drei Abhandlungen {\"u}ber die Conjunction},+ subtitle = {Von Averroes (Vater und Sohn), aus dem Arabischen+ {\"u}bersetzt von Samuel Ibn Tibbon},+ shorttitle = {Drei Abhandlungen},+ annotation = {A \texttt{book} entry. Note the concatenation of the+ \texttt{editor} and \texttt{translator} fields as well as the+ \texttt{indextitle} and \texttt{indexsorttitle} fields},+}++@book{cicero,+ author = {Cicero, Marcus Tullius},+ title = {De natura deorum. {\"U}ber das Wesen der G{\"o}tter},+ date = 1995,+ editor = {Blank-Sangmeister, Ursula},+ translator = {Blank-Sangmeister, Ursula},+ afterword = {Thraede, Klaus},+ language = {langlatin and langgerman},+ publisher = {Reclam},+ location = {Stuttgart},+ langid = {german},+ indextitle = {De natura deorum},+ shorttitle = {De natura deorum},+ annotation = {A bilingual edition of Cicero's \emph{De natura deorum}, with+ a German translation. Note the format of the \texttt{language}+ field in the database file, the concatenation of the+ \texttt{editor} and \texttt{translator} fields, and the+ \texttt{afterword} field},+}
@@ -1,3 +1,5 @@+```+% pandoc -f biblatex -t markdown -s @Book{item1, author="John Doe", title="First Book",@@ -27,7 +29,7 @@ ^D ----nocite: '[@*]'+nocite: "[@*]" references: - author: - family: Doe@@ -44,9 +46,9 @@ container-title: Journal of Generic Studies id: item2 issued: 2006- page: '33-34'+ page: 33-34 title: Article- type: 'article-journal'+ type: article-journal volume: 6 - author: - family: Doe
@@ -1,1674 +0,0 @@-@string{anch-ie = {Angew.~Chem. Int.~Ed.}}-@string{cup = {Cambridge University Press}}-@string{dtv = {Deutscher Taschenbuch-Verlag}}-@string{hup = {Harvard University Press}}-@string{jams = {J.~Amer. Math. Soc.}}-@string{jchph = {J.~Chem. Phys.}}-@string{jomch = {J.~Organomet. Chem.}}-@string{pup = {Princeton University Press}}--@incollection{westfahl:space,- author = {Westfahl, Gary},- title = {The True Frontier},- subtitle = {Confronting and Avoiding the Realities of Space in {American}- Science Fiction Films},- pages = {55-65},- crossref = {westfahl:frontier},- langid = {english},- langidopts = {variant=american},- indextitle = {True Frontier, The},- annotation = {A cross-referenced article from a \texttt{collection}. This is- an \texttt{incollection} entry with a \texttt{crossref}- field. Note the \texttt{subtitle} and \texttt{indextitle}- fields},-}--@set{set,- entryset = {herrmann,aksin,yoon},- annotation = {A \texttt{set} with three members. The \texttt{crossref} field- in the \texttt{@set} entry and the \texttt{entryset} field in- each set member entry is needed only when using BibTeX as the- backend},-}--@set{stdmodel,- entryset = {glashow,weinberg,salam},- annotation = {A \texttt{set} with three members discussing the standard- model of particle physics. The \texttt{crossref} field- in the \texttt{@set} entry and the \texttt{entryset} field in- each set member entry is needed only when using BibTeX as the- backend},-}--@article{aksin,- author = {Aks{\i}n, {\"O}zge and T{\"u}rkmen, Hayati and Artok, Levent- and {\c{C}}etinkaya, Bekir and Ni, Chaoying and- B{\"u}y{\"u}kg{\"u}ng{\"o}r, Orhan and {\"O}zkal, Erhan},- title = {Effect of immobilization on catalytic characteristics of- saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck}- reactions},- journaltitle = jomch,- date = 2006,- volume = 691,- number = 13,- pages = {3027-3036},- indextitle = {Effect of immobilization on catalytic characteristics},-}--@article{angenendt,- author = {Angenendt, Arnold},- title = {In Honore Salvatoris~-- Vom Sinn und Unsinn der- Patrozinienkunde},- journaltitle = {Revue d'Histoire Eccl{\'e}siastique},- date = 2002,- volume = 97,- pages = {431--456, 791--823},- langid = {german},- indextitle = {In Honore Salvatoris},- shorttitle = {In Honore Salvatoris},- annotation = {A German article in a French journal. Apart from that, a- typical \texttt{article} entry. Note the \texttt{indextitle}- field},-}--@article{baez/article,- author = {Baez, John C. and Lauda, Aaron D.},- title = {Higher-Dimensional Algebra {V}: 2-Groups},- journaltitle = {Theory and Applications of Categories},- date = 2004,- volume = 12,- pages = {423-491},- version = 3,- eprint = {math/0307200v3},- eprinttype = {arxiv},- langid = {english},- langidopts = {variant=american},- annotation = {An \texttt{article} with \texttt{eprint} and- \texttt{eprinttype} fields. Note that the arXiv reference is- transformed into a clickable link if \texttt{hyperref} support- has been enabled. Compare \texttt{baez\slash online}, which- is the same item given as an \texttt{online} entry},-}--@article{bertram,- author = {Bertram, Aaron and Wentworth, Richard},- title = {Gromov invariants for holomorphic maps on {Riemann} surfaces},- journaltitle = jams,- date = 1996,- volume = 9,- number = 2,- pages = {529-571},- langid = {english},- langidopts = {variant=american},- shorttitle = {Gromov invariants},- annotation = {An \texttt{article} entry with a \texttt{volume} and a- \texttt{number} field},-}--@article{doody,- author = {Doody, Terrence},- title = {Hemingway's Style and {Jake's} Narration},- year = 1974,- volume = 4,- number = 3,- pages = {212-225},- langid = {english},- langidopts = {variant=american},- related = {matuz:doody},- relatedstring= {\autocap{e}xcerpt in},- journal = {The Journal of Narrative Technique},- annotation = {An \texttt{article} entry cited as an excerpt from a- \texttt{collection} entry. Note the format of the- \texttt{related} and \texttt{relatedstring} fields},-}--@collection{matuz:doody,- editor = {Matuz, Roger},- title = {Contemporary Literary Criticism},- year = 1990,- volume = 61,- publisher = {Gale},- location = {Detroit},- pages = {204-208},- langid = {english},- langidopts = {variant=american},- annotation = {A \texttt{collection} entry providing the excerpt information- for the \texttt{doody} entry. Note the format of the- \texttt{pages} field},-}--@article{gillies,- author = {Gillies, Alexander},- title = {Herder and the Preparation of {Goethe's} Idea of World- Literature},- journaltitle = {Publications of the English Goethe Society},- date = 1933,- series = {newseries},- volume = 9,- pages = {46-67},- langid = {english},- langidopts = {variant=british},- annotation = {An \texttt{article} entry with a \texttt{series} and a- \texttt{volume} field. Note that format of the \texttt{series}- field in the database file},-}--@article{glashow,- author = {Glashow, Sheldon},- title = {Partial Symmetries of Weak Interactions},- journaltitle = {Nucl.~Phys.},- date = 1961,- volume = 22,- pages = {579-588},-}--@article{herrmann,- author = {Herrmann, Wolfgang A. and {\"O}fele, Karl and Schneider,- Sabine K. and Herdtweck, Eberhardt and Hoffmann, Stephan D.},- title = {A carbocyclic carbene as an efficient catalyst ligand for {C--C}- coupling reactions},- journaltitle = anch-ie,- date = 2006,- volume = 45,- number = 23,- pages = {3859-3862},- indextitle = {Carbocyclic carbene as an efficient catalyst, A},-}--@article{kastenholz,- author = {Kastenholz, M. A. and H{\"u}nenberger, Philippe H.},- title = {Computation of methodology\hyphen independent ionic solvation- free energies from molecular simulations},- journaltitle = jchph,- date = 2006,- subtitle = {{I}. {The} electrostatic potential in molecular liquids},- volume = 124,- eid = 124106,- doi = {10.1063/1.2172593},- langid = {english},- langidopts = {variant=american},- indextitle = {Computation of ionic solvation free energies},- annotation = {An \texttt{article} entry with an \texttt{eid} and a- \texttt{doi} field. Note that the \textsc{doi} is transformed- into a clickable link if \texttt{hyperref} support has been- enabled},- abstract = {The computation of ionic solvation free energies from- atomistic simulations is a surprisingly difficult problem that- has found no satisfactory solution for more than 15 years. The- reason is that the charging free energies evaluated from such- simulations are affected by very large errors. One of these is- related to the choice of a specific convention for summing up- the contributions of solvent charges to the electrostatic- potential in the ionic cavity, namely, on the basis of point- charges within entire solvent molecules (M scheme) or on the- basis of individual point charges (P scheme). The use of an- inappropriate convention may lead to a charge-independent- offset in the calculated potential, which depends on the- details of the summation scheme, on the quadrupole-moment- trace of the solvent molecule, and on the approximate form- used to represent electrostatic interactions in the- system. However, whether the M or P scheme (if any) represents- the appropriate convention is still a matter of on-going- debate. The goal of the present article is to settle this- long-standing controversy by carefully analyzing (both- analytically and numerically) the properties of the- electrostatic potential in molecular liquids (and inside- cavities within them).},-}--@article{murray,- author = {Hostetler, Michael J. and Wingate, Julia E. and Zhong,- Chuan-Jian and Harris, Jay E. and Vachet, Richard W. and- Clark, Michael R. and Londono, J. David and Green, Stephen- J. and Stokes, Jennifer J. and Wignall, George D. and Glish,- Gary L. and Porter, Marc D. and Evans, Neal D. and Murray,- Royce W.},- title = {Alkanethiolate gold cluster molecules with core diameters from- 1.5 to 5.2~{nm}},- journaltitle = {Langmuir},- date = 1998,- subtitle = {Core and monolayer properties as a function of core size},- volume = 14,- number = 1,- pages = {17-30},- langid = {english},- langidopts = {variant=american},- indextitle = {Alkanethiolate gold cluster molecules},- shorttitle = {Alkanethiolate gold cluster molecules},- annotation = {An \texttt{article} entry with \arabic{author} authors. By- default, long author and editor lists are automatically- truncated. This is configurable},-}--@article{reese,- author = {Reese, Trevor R.},- title = {Georgia in {Anglo-Spanish} Diplomacy, 1736--1739},- journaltitle = {William and Mary Quarterly},- date = 1958,- series = 3,- volume = 15,- pages = {168-190},- langid = {english},- langidopts = {variant=american},- annotation = {An \texttt{article} entry with a \texttt{series} and a- \texttt{volume} field. Note the format of the series. If the- value of the \texttt{series} field is an integer, this number- is printed as an ordinal and the string \enquote*{series} is- appended automatically},-}--@article{sarfraz,- author = {M. Sarfraz and M. F. A. Razzak},- title = {Technical section: {An} algorithm for automatic capturing of- the font outlines},- year = 2002,- volume = 26,- number = 5,- pages = {795-804},- issn = {0097-8493},- journal = {Computers and Graphics},- annotation = {An \texttt{article} entry with an \texttt{issn} field},-}--@article{shore,- author = {Shore, Bradd},- title = {Twice-Born, Once Conceived},- journaltitle = {American Anthropologist},- date = {1991-03},- subtitle = {Meaning Construction and Cultural Cognition},- series = {newseries},- volume = 93,- number = 1,- pages = {9-27},- annotation = {An \texttt{article} entry with \texttt{series},- \texttt{volume}, and \texttt{number} fields. Note the format- of the \texttt{series} which is a localization key},-}--@article{sigfridsson,- author = {Sigfridsson, Emma and Ryde, Ulf},- title = {Comparison of methods for deriving atomic charges from the- electrostatic potential and moments},- journaltitle = {Journal of Computational Chemistry},- date = 1998,- volume = 19,- number = 4,- pages = {377-395},- doi = {10.1002/(SICI)1096-987X(199803)19:4<377::AID-JCC1>3.0.CO;2-P},- langid = {english},- langidopts = {variant=american},- indextitle = {Methods for deriving atomic charges},- annotation = {An \texttt{article} entry with \texttt{volume},- \texttt{number}, and \texttt{doi} fields. Note that the- \textsc{doi} is transformed into a clickable link if- \texttt{hyperref} support has been enabled},- abstract = {Four methods for deriving partial atomic charges from the- quantum chemical electrostatic potential (CHELP, CHELPG,- Merz-Kollman, and RESP) have been compared and critically- evaluated. It is shown that charges strongly depend on how and- where the potential points are selected. Two alternative- methods are suggested to avoid the arbitrariness in the- point-selection schemes and van der Waals exclusion radii:- CHELP-BOW, which also estimates the charges from the- electrostatic potential, but with potential points that are- Boltzmann-weighted after their occurrence in actual- simulations using the energy function of the program in which- the charges will be used, and CHELMO, which estimates the- charges directly from the electrostatic multipole- moments. Different criteria for the quality of the charges are- discussed.},-}--@article{spiegelberg,- author = {Spiegelberg, Herbert},- title = {\mkbibquote{Intention} und \mkbibquote{Intentionalit{\"a}t} in- der Scholastik, bei Brentano und Husserl},- journaltitle = {Studia Philosophica},- date = 1969,- volume = 29,- pages = {189-216},- langid = {german},- sorttitle = {Intention und Intentionalitat in der Scholastik, bei Brentano- und Husserl},- indexsorttitle= {Intention und Intentionalitat in der Scholastik, bei Brentano- und Husserl},- shorttitle = {Intention und Intentionalit{\"a}t},- annotation = {An \texttt{article} entry. Note the \texttt{sorttitle} and- \texttt{indexsorttitle} fields and the markup of the quotes in- the database file},-}--@article{springer,- author = {Springer, Otto},- title = {Mediaeval Pilgrim Routes from {Scandinavia} to {Rome}},- journaltitle = {Mediaeval Studies},- date = 1950,- volume = 12,- pages = {92-122},- langid = {english},- langidopts = {variant=british},- shorttitle = {Mediaeval Pilgrim Routes},- annotation = {A plain \texttt{article} entry},-}--@article{weinberg,- author = {Weinberg, Steven},- title = {A Model of Leptons},- journaltitle = {Phys.~Rev.~Lett.},- date = 1967,- volume = 19,- pages = {1264-1266},-}--@article{yoon,- author = {Yoon, Myeong S. and Ryu, Dowook and Kim, Jeongryul and Ahn,- Kyo Han},- title = {Palladium pincer complexes with reduced bond angle strain:- efficient catalysts for the {Heck} reaction},- journaltitle = {Organometallics},- date = 2006,- volume = 25,- number = 10,- pages = {2409-2411},- indextitle = {Palladium pincer complexes},-}--@book{aristotle:anima,- author = {Aristotle},- title = {De Anima},- date = 1907,- editor = {Hicks, Robert Drew},- publisher = cup,- location = {Cambridge},- keywords = {primary},- langid = {english},- langidopts = {variant=british},- annotation = {A \texttt{book} entry with an \texttt{author} and an- \texttt{editor}},-}--@book{aristotle:physics,- author = {Aristotle},- title = {Physics},- date = 1929,- translator = {Wicksteed, P. H. and Cornford, F. M.},- publisher = {G. P. Putnam},- location = {New York},- keywords = {primary},- langid = {english},- langidopts = {variant=american},- shorttitle = {Physics},- annotation = {A \texttt{book} entry with a \texttt{translator} field},-}--@book{aristotle:poetics,- author = {Aristotle},- title = {Poetics},- date = 1968,- editor = {Lucas, D. W.},- series = {Clarendon {Aristotle}},- publisher = {Clarendon Press},- location = {Oxford},- keywords = {primary},- langid = {english},- langidopts = {variant=british},- shorttitle = {Poetics},- annotation = {A \texttt{book} entry with an \texttt{author} and an- \texttt{editor} as well as a \texttt{series} field},-}--@book{aristotle:rhetoric,- author = {Aristotle},- title = {The Rhetoric of {Aristotle} with a commentary by the late {Edward- Meredith Cope}},- date = 1877,- editor = {Cope, Edward Meredith},- commentator = {Cope, Edward Meredith},- volumes = 3,- publisher = cup,- keywords = {primary},- langid = {english},- langidopts = {variant=british},- sorttitle = {Rhetoric of Aristotle},- indextitle = {Rhetoric of {Aristotle}, The},- shorttitle = {Rhetoric},- annotation = {A commented edition. Note the concatenation of the- \texttt{editor} and \texttt{commentator} fields as well as the- \texttt{volumes}, \texttt{sorttitle}, and \texttt{indextitle}- fields},-}--@book{augustine,- author = {Augustine, Robert L.},- title = {Heterogeneous catalysis for the synthetic chemist},- date = 1995,- publisher = {Marcel Dekker},- location = {New York},- langid = {english},- langidopts = {variant=american},- shorttitle = {Heterogeneous catalysis},- annotation = {A plain \texttt{book} entry},-}--@book{averroes/bland,- author = {Averroes},- title = {The Epistle on the Possibility of Conjunction with the Active- Intellect by {Ibn Rushd} with the Commentary of {Moses Narboni}},- date = 1982,- editor = {Bland, Kalman P.},- translator = {Bland, Kalman P.},- series = {Moreshet: Studies in {Jewish} History, Literature and Thought},- number = 7,- publisher = {Jewish Theological Seminary of America},- location = {New York},- keywords = {primary},- langid = {english},- langidopts = {variant=american},- indextitle = {Epistle on the Possibility of Conjunction, The},- shorttitle = {Possibility of Conjunction},- annotation = {A \texttt{book} entry with a \texttt{series} and a- \texttt{number}. Note the concatenation of the \texttt{editor}- and \texttt{translator} fields as well as the- \texttt{indextitle} field},-}--@book{averroes/hannes,- author = {Averroes},- title = {Des Averro{\"e}s Abhandlung: \mkbibquote{{\"U}ber die- M{\"o}glichkeit der Conjunktion} oder \mkbibquote{{\"U}ber den- materiellen Intellekt}},- date = 1892,- editor = {Hannes, Ludwig},- translator = {Hannes, Ludwig},- annotator = {Hannes, Ludwig},- publisher = {C.~A. Kaemmerer},- location = {Halle an der Saale},- keywords = {primary},- langid = {german},- sorttitle = {Uber die Moglichkeit der Conjunktion},- indexsorttitle= {Uber die Moglichkeit der Conjunktion},- indextitle = {{\"U}ber die M{\"o}glichkeit der Conjunktion},- shorttitle = {{\"U}ber die M{\"o}glichkeit der Conjunktion},- annotation = {An annotated edition. Note the concatenation of the- \texttt{editor}, \texttt{translator}, and \texttt{annotator}- fields. Also note the \texttt{shorttitle},- \texttt{indextitle}, \texttt{sorttitle}, and- \texttt{indexsorttitle} fields},-}--@book{averroes/hercz,- author = {Averroes},- title = {Drei Abhandlungen {\"u}ber die Conjunction des separaten- Intellects mit dem Menschen},- date = 1869,- editor = {Hercz, J.},- translator = {Hercz, J.},- publisher = {S.~Hermann},- location = {Berlin},- keywords = {primary},- langid = {german},- indexsorttitle= {Drei Abhandlungen uber die Conjunction},- indextitle = {Drei Abhandlungen {\"u}ber die Conjunction},- subtitle = {Von Averroes (Vater und Sohn), aus dem Arabischen- {\"u}bersetzt von Samuel Ibn Tibbon},- shorttitle = {Drei Abhandlungen},- annotation = {A \texttt{book} entry. Note the concatenation of the- \texttt{editor} and \texttt{translator} fields as well as the- \texttt{indextitle} and \texttt{indexsorttitle} fields},-}--@book{cicero,- author = {Cicero, Marcus Tullius},- title = {De natura deorum. {\"U}ber das Wesen der G{\"o}tter},- date = 1995,- editor = {Blank-Sangmeister, Ursula},- translator = {Blank-Sangmeister, Ursula},- afterword = {Thraede, Klaus},- language = {langlatin and langgerman},- publisher = {Reclam},- location = {Stuttgart},- langid = {german},- indextitle = {De natura deorum},- shorttitle = {De natura deorum},- annotation = {A bilingual edition of Cicero's \emph{De natura deorum}, with- a German translation. Note the format of the \texttt{language}- field in the database file, the concatenation of the- \texttt{editor} and \texttt{translator} fields, and the- \texttt{afterword} field},-}--@book{coleridge,- author = {Coleridge, Samuel Taylor},- title = {Biographia literaria, or {Biographical} sketches of my literary- life and opinions},- date = 1983,- editor = {Coburn, Kathleen and Engell, James and Bate, W. Jackson},- maintitle = {The collected works of {Samuel Taylor Coleridge}},- volume = 7,- part = 2,- series = {Bollingen Series},- number = 75,- publisher = {Routledge {and} Kegan Paul},- location = {London},- langid = {english},- langidopts = {variant=british},- indextitle = {Biographia literaria},- shorttitle = {Biographia literaria},- annotation = {One (partial) volume of a multivolume book. This is a- \texttt{book} entry with a \texttt{volume} and a \texttt{part}- field which explicitly refers to the second (physical) part of- the seventh (logical) volume. Also note the \texttt{series}- and \texttt{number} fields},-}--@book{companion,- author = {Goossens, Michel and Mittelbach, Frank and Samarin, Alexander},- title = {The {LaTeX} Companion},- date = 1994,- edition = 1,- publisher = {Addison-Wesley},- location = {Reading, Mass.},- pagetotal = 528,- langid = {english},- langidopts = {variant=american},- sorttitle = {LaTeX Companion},- indextitle = {LaTeX Companion, The},- shorttitle = {LaTeX Companion},- annotation = {A book with three authors. Note the formatting of the author- list. By default, only the first name is reversed in the- bibliography},-}--@book{cotton,- author = {Cotton, Frank Albert and Wilkinson, Geoffrey and Murillio,- Carlos A. and Bochmann, Manfred},- title = {Advanced inorganic chemistry},- date = 1999,- edition = 6,- publisher = {Wiley},- location = {Chichester},- langid = {english},- langidopts = {variant=british},- annotation = {A \texttt{book} entry with \arabic{author} authors and an- \texttt{edition} field. By default, long \texttt{author} and- \texttt{editor} lists are automatically truncated. This is- configurable},-}--@book{gerhardt,- author = {Gerhardt, Michael J.},- title = {The Federal Appointments Process},- date = 2000,- publisher = {Duke University Press},- location = {Durham and London},- langid = {english},- langidopts = {variant=american},- sorttitle = {Federal Appointments Process},- indextitle = {Federal Appointments Process, The},- subtitle = {A Constitutional and Historical Analysis},- shorttitle = {Federal Appointments Process},- annotation = {This is a \texttt{book} entry. Note the format of the- \texttt{location} field as well as the \texttt{sorttitle} and- \texttt{indextitle} fields},-}--@book{gonzalez,- author = {Gonzalez, Ray},- title = {The Ghost of {John Wayne} and Other Stories},- date = 2001,- publisher = {The University of Arizona Press},- location = {Tucson},- isbn = {0-816-52066-6},- langid = {english},- langidopts = {variant=american},- sorttitle = {Ghost of John Wayne and Other Stories},- indextitle = {Ghost of {John Wayne} and Other Stories, The},- shorttitle = {Ghost of {John Wayne}},- annotation = {A collection of short stories. This is a \texttt{book} entry.- Note the \texttt{sorttitle} and \texttt{indextitle} fields in- the database file. There's also an \texttt{isbn} field},-}--@book{hammond,- author = {Hammond, Christopher},- title = {The basics of crystallography and diffraction},- date = 1997,- publisher = {International Union of Crystallography and Oxford University- Press},- location = {Oxford},- langid = {english},- langidopts = {variant=british},- sorttitle = {Basics of crystallography and diffraction},- indextitle = {Basics of crystallography and diffraction, The},- shorttitle = {Crystallography and diffraction},- annotation = {A \texttt{book} entry. Note the \texttt{sorttitle} and- \texttt{indextitle} fields as well as the format of the- \texttt{publisher} field},-}--@book{iliad,- author = {Homer},- title = {Die Ilias},- date = 2004,- translator = {Schadewaldt, Wolfgang},- introduction = {Latacz, Joachim},- edition = 3,- publisher = {Artemis \& Winkler},- location = {D{\"u}sseldorf and Z{\"u}rich},- langid = {german},- sorttitle = {Ilias},- indextitle = {Ilias, Die},- shorttitle = {Ilias},- annotation = {A German translation of the \emph{Iliad}. Note the- \texttt{translator} and \texttt{introduction} fields and the- format of the \texttt{location} field in the database- file. Also note the \texttt{sorttitle} and \texttt{indextitle}- fields},-}--@book{knuth:ct,- author = {Knuth, Donald E.},- title = {Computers \& Typesetting},- date = {1984/1986},- volumes = 5,- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1984-0},- sorttitle = {Computers & Typesetting},- indexsorttitle= {Computers & Typesetting},- annotation = {A five-volume book cited as a whole. This is a \texttt{book}- entry, note the \texttt{volumes} field},-}--@book{knuth:ct:a,- author = {Knuth, Donald E.},- title = {The {\TeX} book},- date = 1984,- maintitle = {Computers \& Typesetting},- volume = {A},- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1984-1},- sorttitle = {Computers & Typesetting A},- indexsorttitle= {The TeXbook},- indextitle = {\protect\TeX book, The},- shorttitle = {\TeX book},- annotation = {The first volume of a five-volume book. Note the- \texttt{sorttitle} and \texttt{sortyear} fields. We want this- volume to be listed after the entry referring to the entire- five-volume set. Also note the \texttt{indextitle} and- \texttt{indexsorttitle} fields. Indexing packages that don't- generate robust index entries require some control sequences- to be protected from expansion},-}--@book{knuth:ct:b,- author = {Knuth, Donald E.},- title = {\TeX: The Program},- date = 1986,- maintitle = {Computers \& Typesetting},- volume = {B},- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1986-1},- sorttitle = {Computers & Typesetting B},- indexsorttitle= {TeX: The Program},- shorttitle = {\TeX},- annotation = {The second volume of a five-volume book. Note the- \texttt{sorttitle} and \texttt{sortyear} fields. Also note the- \texttt{indexsorttitle} field},-}--@book{knuth:ct:c,- author = {Knuth, Donald E.},- title = {The {METAFONTbook}},- date = 1986,- maintitle = {Computers \& Typesetting},- volume = {C},- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1986-2},- sorttitle = {Computers & Typesetting C},- indextitle = {METAFONTbook, The},- shorttitle = {METAFONTbook},- annotation = {The third volume of a five-volume book. Note the- \texttt{sorttitle} and \texttt{sortyear} fields as well as the- \texttt{indextitle} field},-}--@book{knuth:ct:d,- author = {Knuth, Donald E.},- title = {METAFONT: The Program},- date = 1986,- maintitle = {Computers \& Typesetting},- volume = {D},- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1986-3},- sorttitle = {Computers & Typesetting D},- shorttitle = {METAFONT},- annotation = {The fourth volume of a five-volume book. Note the- \texttt{sorttitle} and \texttt{sortyear} fields},-}--@book{knuth:ct:e,- author = {Knuth, Donald E.},- title = {{Computer Modern} Typefaces},- date = 1986,- maintitle = {Computers \& Typesetting},- volume = {E},- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1986-4},- sorttitle = {Computers & Typesetting E},- annotation = {The fifth volume of a five-volume book. Note the- \texttt{sorttitle} and \texttt{sortyear} fields},-}--@book{knuth:ct:related,- author = {Knuth, Donald E.},- title = {Computers \& Typesetting},- date = {1984/1986},- volumes = 5,- publisher = {Addison-Wesley},- location = {Reading, Mass.},- langid = {english},- langidopts = {variant=american},- sortyear = {1984-0},- sorttitle = {Computers & Typesetting},- indexsorttitle= {Computers & Typesetting},- related = {knuth:ct:a,knuth:ct:b,knuth:ct:c,knuth:ct:d,knuth:ct:e},- relatedtype = {multivolume},- annotation = {A five-volume book cited as a whole and related to its- individual volumes. Note the \texttt{related} and- \texttt{relatedtype} fields},-}--@book{kullback,- author = {Kullback, Solomon},- title = {Information Theory and Statistics},- year = 1959,- publisher = {John Wiley \& Sons},- location = {New York},- langid = {english},- langidopts = {variant=american},-}--@book{kullback:reprint,- author = {Kullback, Solomon},- title = {Information Theory and Statistics},- year = 1997,- publisher = {Dover Publications},- location = {New York},- origyear = 1959,- origpublisher= {John Wiley \& Sons},- langid = {english},- langidopts = {variant=american},- annotation = {A reprint of the \texttt{kullback} entry. Note the format of- \texttt{origyear} and \texttt{origpublisher}. These fields are- not used by the standard bibliography styles},-}--@book{kullback:related,- author = {Kullback, Solomon},- title = {Information Theory and Statistics},- year = 1997,- publisher = {Dover Publications},- location = {New York},- langid = {english},- langidopts = {variant=american},- related = {kullback},- relatedtype = {origpubin},- annotation = {A reprint of the \texttt{kullback} entry. Note the format of- the \texttt{related} and \texttt{relatedtype} fields},-}--@book{malinowski,- author = {Malinowski, Bronis{\l}aw},- title = {Argonauts of the {Western Pacific}},- date = 1972,- edition = 8,- publisher = {Routledge {and} Kegan Paul},- location = {London},- langid = {english},- langidopts = {variant=british},- subtitle = {An account of native enterprise and adventure in the- Archipelagoes of {Melanesian New Guinea}},- shorttitle = {Argonauts},- annotation = {This is a \texttt{book} entry. Note the format of the- \texttt{publisher} and \texttt{edition} fields as well as the- \texttt{subtitle} field},-}--@book{maron,- author = {Maron, Monika},- title = {Animal Triste},- date = 2000,- translator = {Brigitte Goldstein},- origlanguage = {german},- publisher = {University of Nebraska Press},- location = {Lincoln},- langid = {english},- langidopts = {variant=american},- shorttitle = {Animal Triste},- annotation = {An English translation of a German novel with a French title.- In other words: a \texttt{book} entry with a- \texttt{translator} field. Note the \texttt{origlanguage}- field which is concatenated with the \texttt{translator}},-}--@book{massa,- author = {Werner Massa},- title = {Crystal structure determination},- date = 2004,- edition = 2,- publisher = {Spinger},- location = {Berlin},- langid = {english},- langidopts = {variant=british},- annotation = {A \texttt{book} entry with an \texttt{edition} field},-}--@article{moore,- author = {Moore, Gordon E.},- title = {Cramming more components onto integrated circuits},- journaltitle = {Electronics},- year = 1965,- volume = 38,- number = 8,- pages = {114-117},- langid = {english},- langidopts = {variant=american},-}--@article{moore:related,- author = {Moore, Gordon E.},- title = {Cramming more components onto integrated circuits},- journaltitle = {Proceedings of the {IEEE}},- year = 1998,- volume = 86,- number = 1,- pages = {82-85},- langid = {english},- langidopts = {variant=american},- related = {moore},- relatedtype = {reprintfrom},- annotation = {A reprint of Moore's law. Note the \texttt{related} and- \texttt{relatedtype} fields},-}--@book{nietzsche:ksa,- author = {Nietzsche, Friedrich},- title = {S{\"a}mtliche Werke},- date = 1988,- editor = {Colli, Giorgio and Montinari, Mazzino},- edition = 2,- volumes = 15,- publisher = dtv # { and Walter de Gruyter},- location = {M{\"u}nchen and Berlin and New York},- langid = {german},- sortyear = {1988-0},- sorttitle = {Werke-00-000},- indexsorttitle= {Samtliche Werke},- subtitle = {Kritische Studienausgabe},- annotation = {The critical edition of Nietzsche's works. This is a- \texttt{book} entry referring to a 15-volume work as a- whole. Note the \texttt{volumes} field and the format of the- \texttt{publisher} and \texttt{location} fields in the- database file. Also note the \texttt{sorttitle} and- \texttt{sortyear} fields which are used to fine-tune the- sorting order of the bibliography. We want this item listed- first in the bibliography},-}--@book{nietzsche:ksa1,- author = {Nietzsche, Friedrich},- title = {Die Geburt der Trag{\"o}die. Unzeitgem{\"a}{\ss}e- Betrachtungen I--IV. Nachgelassene Schriften 1870--1973},- date = 1988,- editor = {Colli, Giorgio and Montinari, Mazzino},- maintitle = {S{\"a}mtliche Werke},- mainsubtitle = {Kritische Studienausgabe},- volume = 1,- edition = 2,- publisher = dtv # { and Walter de Gruyter},- location = {M{\"u}nchen and Berlin and New York},- langid = {german},- sortyear = {1988-1},- sorttitle = {Werke-01-000},- indexsorttitle= {Samtliche Werke I},- bookauthor = {Nietzsche, Friedrich},- indextitle = {S{\"a}mtliche Werke I},- shorttitle = {S{\"a}mtliche Werke I},- annotation = {A single volume from the critical edition of Nietzsche's- works. This \texttt{book} entry explicitly refers to the first- volume only. Note the \texttt{title} and \texttt{maintitle}- fields. Also note the \texttt{sorttitle} and \texttt{sortyear}- fields. We want this entry to be listed after the entry- referring to the entire edition},-}--@book{nussbaum,- author = {Nussbaum, Martha},- title = {Aristotle's \mkbibquote{De Motu Animalium}},- date = 1978,- publisher = pup,- location = {Princeton},- keywords = {secondary},- langid = {english},- langidopts = {variant=american},- sorttitle = {Aristotle's De Motu Animalium},- indexsorttitle= {Aristotle's De Motu Animalium},- annotation = {A \texttt{book} entry. Note the \texttt{sorttitle} and- \texttt{indexsorttitle} fields and the markup of the quotes in- the database file},-}--@book{piccato,- author = {Piccato, Pablo},- title = {City of Suspects},- date = 2001,- publisher = {Duke University Press},- location = {Durham and London},- langid = {english},- langidopts = {variant=american},- subtitle = {Crime in {Mexico City}, 1900--1931},- shorttitle = {City of Suspects},- annotation = {This is a \texttt{book} entry. Note the format of the- \texttt{location} field in the database file},-}--@book{vangennep,- author = {van Gennep, Arnold},- title = {Les rites de passage},- date = 1909,- publisher = {Nourry},- location = {Paris},- options = {useprefix},- langid = {french},- sorttitle = {Rites de passage},- indextitle = {Rites de passage, Les},- shorttitle = {Rites de passage},- annotation = {A \texttt{book} entry. Note the format of the printed name and- compare the \texttt{useprefix} option in the \texttt{options}- field as well as \texttt{brandt} and \texttt{geer}},-}--@book{vangennep:trans,- author = {van Gennep, Arnold},- title = {The Rites of Passage},- year = 1960,- translator = {Vizedom, Monika B. and Caffee, Gabrielle L.},- language = {english},- origlanguage = {french},- publisher = {University of Chicago Press},- options = {useprefix},- indextitle = {Rites of Passage, The},- sorttitle = {Rites of Passage},- shorttitle = {Rites of Passage},- langid = {english},- langidopts = {variant=american},- annotation = {A translation of the \texttt{vangennep} entry. Note the- \texttt{translator} and \texttt{origlanguage} fields. Compare- with the \texttt{vangennep:related} entry.},-}--@book{vangennep:related,- author = {van Gennep, Arnold},- title = {Les rites de passage},- date = 1909,- publisher = {Nourry},- location = {Paris},- options = {useprefix},- langid = {french},- related = {vizedom:related},- relatedtype = {bytranslator},- sorttitle = {Rites de passage},- indextitle = {Rites de passage, Les},- shorttitle = {Rites de passage},- annotation = {A variant of the \texttt{vangennep} entry related to its- translation. Note the format of the \texttt{related} and- \texttt{relatedtype} fields},-}--@book{vizedom:related,- title = {The Rites of Passage},- year = 1960,- translator = {Vizedom, Monika B. and Caffee, Gabrielle L.},- language = {english},- publisher = {University of Chicago Press},- langid = {english},- langidopts = {variant=american},- options = {usetranslator},- related = {vangennep},- relatedtype = {translationof},- indextitle = {Rites of Passage, The},- sorttitle = {Rites of Passage},- shorttitle = {Rites of Passage},- annotation = {A translated work from \texttt{vangennep}. Note the format of- the \texttt{related} and \texttt{relatedtype} fields},-}--@book{vazques-de-parga,- author = {V{\'a}zques{ de }Parga, Luis and Lacarra, Jos{\'e} Mar{\'i}a- and Ur{\'i}a R{\'i}u, Juan},- title = {Las Peregrinaciones a Santiago de Compostela},- date = 1993,- volumes = 3,- note = {Ed. facs. de la realizada en 1948--49},- publisher = {Iberdrola},- location = {Pamplona},- langid = {spanish},- sorttitle = {Peregrinaciones a Santiago de Compostela},- indextitle = {Peregrinaciones a Santiago de Compostela, Las},- shorttitle = {Peregrinaciones},- annotation = {A multivolume book cited as a whole. This is a \texttt{book}- entry with \texttt{volumes}, \texttt{note},- \texttt{sorttitle}, and \texttt{indextitle} fields},-}--@book{wilde,- author = {Wilde, Oscar},- title = {The Importance of Being Earnest: A Trivial Comedy for Serious- People},- year = 1899,- series = {English and {American} drama of the Nineteenth Century},- publisher = {Leonard Smithers {and} Company},- eprint = {4HIWAAAAYAAJ},- eprinttype = {googlebooks},- annotation = {A \texttt{book} with \texttt{eprint} and \texttt{eprinttype}- fields.},-}--@book{worman,- author = {Worman, Nancy},- title = {The Cast of Character},- date = 2002,- publisher = {University of Texas Press},- location = {Austin},- langid = {english},- langidopts = {variant=american},- sorttitle = {Cast of Character},- indextitle = {Cast of Character, The},- subtitle = {Style in {Greek} Literature},- shorttitle = {Cast of Character},- annotation = {A \texttt{book} entry. Note the \texttt{sorttitle} and- \texttt{indextitle} fields},-}--@collection{britannica,- editor = {Preece, Warren E.},- title = {The {New Encyclop{\ae}dia Britannica}},- date = 2003,- edition = 15,- volumes = 32,- publisher = {Encyclop{\ae}dia Britannica},- location = {Chicago, Ill.},- options = {useeditor=false},- label = {EB},- langid = {english},- langidopts = {variant=british},- sorttitle = {Encyclop{\ae}dia Britannica},- indextitle = {{Encyclop{\ae}dia Britannica}, The {New}},- shorttitle = {{Encyclop{\ae}dia Britannica}},- annotation = {This is a \texttt{collection} entry for an encyclopedia. Note- the \texttt{useeditor} option in the \texttt{options} field as- well as the \texttt{sorttitle} field. We want this entry to be- cited and alphabetized by title even though there is an- editor. In addition to that, we want the title to be- alphabetized under \enquote*{E} rather than \enquote*{T}. Also- note the \texttt{label} field which is provided for- author-year citation styles},-}--@collection{gaonkar,- editor = {Gaonkar, Dilip Parameshwar},- title = {Alternative Modernities},- date = 2001,- publisher = {Duke University Press},- location = {Durham and London},- isbn = {0-822-32714-7},- langid = {english},- langidopts = {variant=american},- annotation = {This is a \texttt{collection} entry. Note the format of the- \texttt{location} field in the database file as well as the- \texttt{isbn} field},-}--@InCollection{gaonkar:in,- author = {Gaonkar, Dilip Parameshwar},- editor = {Gaonkar, Dilip Parameshwar},- title = {On Alternative Modernities},- date = 2001,- booktitle = {Alternative Modernities},- publisher = {Duke University Press},- location = {Durham and London},- isbn = {0-822-32714-7},- pages = {1-23},-}--@collection{jaffe,- editor = {Jaff{\'e}, Philipp},- title = {Regesta Pontificum Romanorum ab condita ecclesia ad annum post- Christum natum \textsc{mcxcviii}},- date = {1885/1888},- editora = {Loewenfeld, Samuel and Kaltenbrunner, Ferdinand and Ewald,- Paul},- edition = 2,- volumes = 2,- location = {Leipzig},- langid = {latin},- editoratype = {redactor},- indextitle = {Regesta Pontificum Romanorum},- shorttitle = {Regesta Pontificum Romanorum},- annotation = {A \texttt{collection} entry with \texttt{edition} and- \texttt{volumes} fields. Note the \texttt{editora} and- \texttt{editoratype} fields},-}--@collection{westfahl:frontier,- editor = {Westfahl, Gary},- title = {Space and Beyond},- date = 2000,- subtitle = {The Frontier Theme in Science Fiction},- publisher = {Greenwood},- location = {Westport, Conn. and London},- langid = {english},- langidopts = {variant=american},- booktitle = {Space and Beyond},- booksubtitle = {The Frontier Theme in Science Fiction},- annotation = {This is a \texttt{collection} entry. Note the format of the- \texttt{location} field as well as the \texttt{subtitle} and- \texttt{booksubtitle} fields},-}--@inbook{kant:kpv,- title = {Kritik der praktischen Vernunft},- date = 1968,- author = {Kant, Immanuel},- booktitle = {Kritik der praktischen Vernunft. Kritik der Urtheilskraft},- bookauthor = {Kant, Immanuel},- maintitle = {Kants Werke. Akademie Textausgabe},- volume = 5,- publisher = {Walter de Gruyter},- location = {Berlin},- pages = {1-163},- shorthand = {KpV},- langid = {german},- shorttitle = {Kritik der praktischen Vernunft},- annotation = {An edition of Kant's \emph{Collected Works}, volume five. This- is an \texttt{inbook} entry which explicitly refers to the- \emph{Critique of Practical Reason} only, not to the entire- fifth volume. Note the \texttt{author} and \texttt{bookauthor}- fields in the database file. By default, the- \texttt{bookauthor} is omitted if the values of the- \texttt{author} and \texttt{bookauthor} fields are identical},-}--@inbook{kant:ku,- title = {Kritik der Urtheilskraft},- date = 1968,- author = {Kant, Immanuel},- booktitle = {Kritik der praktischen Vernunft. Kritik der Urtheilskraft},- bookauthor = {Kant, Immanuel},- maintitle = {Kants Werke. Akademie Textausgabe},- volume = 5,- publisher = {Walter de Gruyter},- location = {Berlin},- pages = {165-485},- shorthand = {KU},- langid = {german},- annotation = {An edition of Kant's \emph{Collected Works}, volume five. This- is an \texttt{inbook} entry which explicitly refers to the- \emph{Critique of Judgment} only, not to the entire fifth- volume},-}--@inbook{nietzsche:historie,- title = {Unzeitgem{\"a}sse Betrachtungen. Zweites St{\"u}ck},- date = 1988,- author = {Nietzsche, Friedrich},- booktitle = {Die Geburt der Trag{\"o}die. Unzeitgem{\"a}{\ss}e- Betrachtungen I--IV. Nachgelassene Schriften 1870--1973},- bookauthor = {Nietzsche, Friedrich},- editor = {Colli, Giorgio and Montinari, Mazzino},- subtitle = {Vom Nutzen und Nachtheil der Historie f{\"u}r das Leben},- maintitle = {S{\"a}mtliche Werke},- mainsubtitle = {Kritische Studienausgabe},- volume = 1,- publisher = dtv # { and Walter de Gruyter},- location = {M{\"u}nchen and Berlin and New York},- pages = {243-334},- langid = {german},- sortyear = {1988-2},- sorttitle = {Werke-01-243},- indexsorttitle= {Vom Nutzen und Nachtheil der Historie fur das Leben},- indextitle = {Vom Nutzen und Nachtheil der Historie f{\"u}r das Leben},- shorttitle = {Vom Nutzen und Nachtheil der Historie},- annotation = {A single essay from the critical edition of Nietzsche's works.- This \texttt{inbook} entry explicitly refers to an essay found- in the first volume. Note the \texttt{title},- \texttt{booktitle}, and \texttt{maintitle} fields. Also note- the \texttt{sorttitle} and \texttt{sortyear} fields. We want- this entry to be listed after the entry referring to the- entire first volume},-}--@incollection{brandt,- author = {von Brandt, Ahasver and Erich Hoffmann},- editor = {Ferdinand Seibt},- title = {Die nordischen L{\"a}nder von der Mitte des 11.~Jahrhunderts- bis 1448},- date = 1987,- booktitle = {Europa im Hoch- und Sp{\"a}tmittelalter},- series = {Handbuch der europ{\"a}ischen Geschichte},- number = 2,- publisher = {Klett-Cotta},- location = {Stuttgart},- pages = {884-917},- options = {useprefix=false},- langid = {german},- indexsorttitle= {Nordischen Lander von der Mitte des 11. Jahrhunderts bis- 1448},- indextitle = {Nordischen L{\"a}nder von der Mitte des 11.~Jahrhunderts bis- 1448, Die},- shorttitle = {Die nordischen L{\"a}nder},- annotation = {An \texttt{incollection} entry with a \texttt{series} and a- \texttt{number}. Note the format of the printed name and- compare the \texttt{useprefix} option in the \texttt{options}- field as well as \texttt{vangennep}. Also note the- \texttt{indextitle, and \texttt{indexsorttitle} fields}},-}--@incollection{hyman,- author = {Arthur Hyman},- editor = {O'Meara, Dominic J.},- title = {Aristotle's Theory of the Intellect and its Interpretation by- {Averroes}},- date = 1981,- booktitle = {Studies in {Aristotle}},- series = {Studies in Philosophy and the History of Philosophy},- number = 9,- publisher = {The Catholic University of America Press},- location = {Washington, D.C.},- pages = {161-191},- keywords = {secondary},- langid = {english},- langidopts = {variant=american},- indextitle = {Aristotle's Theory of the Intellect},- shorttitle = {Aristotle's Theory of the Intellect},- annotation = {An \texttt{incollection} entry with a \texttt{series} and- \texttt{number} field},-}--@incollection{pines,- author = {Pines, Shlomo},- editor = {Twersky, Isadore},- title = {The Limitations of Human Knowledge According to {Al-Farabi}, {ibn- Bajja}, and {Maimonides}},- date = 1979,- booktitle = {Studies in Medieval {Jewish} History and Literature},- publisher = hup,- location = {Cambridge, Mass.},- pages = {82-109},- keywords = {secondary},- langid = {english},- langidopts = {variant=american},- indextitle = {Limitations of Human Knowledge According to {Al-Farabi}, {ibn- Bajja}, and {Maimonides}, The},- shorttitle = {Limitations of Human Knowledge},- annotation = {A typical \texttt{incollection} entry. Note the- \texttt{indextitle} field},-}--@inproceedings{moraux,- author = {Moraux, Paul},- editor = {Lloyd, G. E. R. and Owen, G. E. L.},- title = {Le \emph{De Anima} dans la tradition gr{\`e}cque},- date = 1979,- booktitle = {Aristotle on Mind and the Senses},- subtitle = {Quelques aspects de l'interpretation du trait{\'e}, de- Theophraste {\`a} Themistius},- booktitleaddon= {Proceedings of the Seventh Symposium Aristotelicum},- eventdate = 1975,- publisher = cup,- location = {Cambridge},- pages = {281-324},- keywords = {secondary},- langid = {french},- indexsorttitle= {De Anima dans la tradition grecque},- indextitle = {\emph{De Anima} dans la tradition gr{\`e}cque, Le},- shorttitle = {\emph{De Anima} dans la tradition gr{\`e}cque},- annotation = {This is a typical \texttt{inproceedings} entry. Note the- \texttt{booksubtitle}, \texttt{shorttitle},- \texttt{indextitle}, and \texttt{indexsorttitle} fields. Also- note the \texttt{eventdate} field.},-}--@inproceedings{salam,- author = {Salam, Abdus},- editor = {Svartholm, Nils},- title = {Weak and Electromagnetic Interactions},- date = 1968,- booktitle = {Elementary particle theory},- booksubtitle = {Relativistic groups and analyticity},- booktitleaddon= {Proceedings of the {Eighth Nobel Symposium}},- eventdate = {1968-05-19/1968-05-25},- venue = {Aspen{\"a}sgarden, Lerum},- publisher = {Almquist \& Wiksell},- location = {Stockholm},- pages = {367-377},-}--@manual{cms,- title = {The {Chicago} Manual of Style},- date = 2003,- subtitle = {The Essential Guide for Writers, Editors, and Publishers},- edition = 15,- publisher = {University of Chicago Press},- location = {Chicago, Ill.},- isbn = {0-226-10403-6},- label = {CMS},- langid = {english},- langidopts = {variant=american},- sorttitle = {Chicago Manual of Style},- indextitle = {Chicago Manual of Style, The},- shorttitle = {Chicago Manual of Style},- annotation = {This is a \texttt{manual} entry without an \texttt{author} or- \texttt{editor}. Note the \texttt{label} field in the database- file which is provided for author-year citation styles. Also- note the \texttt{sorttitle} and \texttt{indextitle} fields. By- default, all entries without an \texttt{author} or- \texttt{editor} are alphabetized by \texttt{title} but we want- this entry to be alphabetized under \enquote*{C} rather than- \enquote*{T}. There's also an \texttt{isbn} field},-}--@online{baez/online,- author = {Baez, John C. and Lauda, Aaron D.},- title = {Higher-Dimensional Algebra {V}: 2-Groups},- date = {2004-10-27},- version = 3,- langid = {english},- langidopts = {variant=american},- eprinttype = {arxiv},- eprint = {math/0307200v3},- annotation = {An \texttt{online} reference from arXiv. Note the- \texttt{eprint} and \texttt{eprinttype} fields. Compare- \texttt{baez\slash article} which is the same item given as an- \texttt{article} entry with eprint information},-}--@online{ctan,- title = {CTAN},- date = 2006,- url = {http://www.ctan.org},- subtitle = {The {Comprehensive TeX Archive Network}},- urldate = {2006-10-01},- label = {CTAN},- langid = {english},- langidopts = {variant=american},- annotation = {This is an \texttt{online} entry. The \textsc{url}, which is- given in the \texttt{url} field, is transformed into a- clickable link if \texttt{hyperref} support has been- enabled. Note the format of the \texttt{urldate} field- (\texttt{yyyy-mm-dd}) in the database file. Also note the- \texttt{label} field which may be used as a fallback by- citation styles which need an \texttt{author} and\slash or a- \texttt{year}},-}--@online{itzhaki,- author = {Itzhaki, Nissan},- title = {Some remarks on {'t Hooft's} {S}-matrix for black holes},- date = {1996-03-11},- version = 1,- langid = {english},- langidopts = {variant=american},- eprinttype = {arxiv},- eprint = {hep-th/9603067},- annotation = {An \texttt{online} reference from arXiv. Note the- \texttt{eprint} and \texttt{eprinttype} fields. Also note that- the arXiv reference is transformed into a clickable link if- \texttt{hyperref} support has been enabled},- abstract = {We discuss the limitations of 't Hooft's proposal for the- black hole S-matrix. We find that the validity of the S-matrix- implies violation of the semi-classical approximation at- scales large compared to the Planck scale. We also show that- the effect of the centrifugal barrier on the S-matrix is- crucial even for large transverse distances.},-}--@online{markey,- author = {Markey, Nicolas},- title = {Tame the {BeaST}},- date = {2005-10-16},- url = {http://mirror.ctan.org/info/bibtex/tamethebeast/ttb_en.pdf},- subtitle = {The {B} to {X} of {BibTeX}},- version = {1.3},- urldate = {2006-10-01},- langid = {english},- langidopts = {variant=american},- sorttitle = {Tame the Beast},- annotation = {An \texttt{online} entry for a tutorial. Note the format of- the \texttt{date} field (\texttt{yyyy-mm-dd}) in the database- file.},-}--@online{wassenberg,- author = {Wassenberg, Jan and Sanders, Peter},- title = {Faster Radix Sort via Virtual Memory and Write-Combining},- date = {2010-08-17},- version = 1,- langid = {english},- langidopts = {variant=american},- eprinttype = {arxiv},- eprintclass = {cs.DS},- eprint = {1008.2849v1},- annotation = {A recent \texttt{online} reference from arXiv using the new- (April 2007 onward) identifier format. Note the- \texttt{eprint}, \texttt{eprinttype}, and \texttt{eprintclass}- fields. Also note that the arXiv reference is transformed into- a clickable link if \texttt{hyperref} support has been- enabled},- abstract = {Sorting algorithms are the deciding factor for the performance- of common operations such as removal of duplicates or database- sort-merge joins. This work focuses on 32-bit integer keys,- optionally paired with a 32-bit value. We present a fast radix- sorting algorithm that builds upon a microarchitecture-aware- variant of counting sort},-}--@patent{almendro,- author = {Almendro, Jos{\'e} L. and Mart{\'i}n, Jacinto and S{\'a}nchez,- Alberto and Nozal, Fernando},- title = {Elektromagnetisches Signalhorn},- number = {EU-29702195U},- date = 1998,- location = {countryfr and countryuk and countryde},- langid = {german},- annotation = {This is a \texttt{patent} entry with a \texttt{location}- field. The number is given in the \texttt{number} field. Note- the format of the \texttt{location} field in the database- file. Compare \texttt{laufenberg}, \texttt{sorace}, and- \texttt{kowalik}},-}--@patent{kowalik,- author = {Kowalik, F. and Isard, M.},- title = {Estimateur d'un d{\'e}faut de fonctionnement d'un modulateur- en quadrature et {\'e}tage de modulation l'utilisant},- number = 9500261,- date = {1995-01-11},- type = {patreqfr},- langid = {french},- indextitle = {Estimateur d'un d{\'e}faut de fonctionnement},- annotation = {This is a \texttt{patent} entry for a French patent request- with a full date. The number is given in the \texttt{number}- field. Note the format of the \texttt{type} and \texttt{date}- fields in the database file. Compare \texttt{almendro},- \texttt{laufenberg}, and \texttt{sorace}},-}--@patent{laufenberg,- author = {Laufenberg, Xaver and Eynius, Dominique and Suelzle, Helmut- and Usbeck, Stephan and Spaeth, Matthias and Neuser-Hoffmann,- Miriam and Myrzik, Christian and Schmid, Manfred and Nietfeld,- Franz and Thiel, Alexander and Braun, Harald and Ebner,- Norbert},- title = {Elektrische Einrichtung und Betriebsverfahren},- number = 1700367,- date = {2006-09-13},- holder = {{Robert Bosch GmbH} and {Daimler Chrysler AG} and {Bayerische- Motoren Werke AG}},- type = {patenteu},- langid = {german},- annotation = {This is a \texttt{patent} entry with a \texttt{holder} field.- Note the format of the \texttt{type} and \texttt{location}- fields in the database file. Compare \texttt{almendro},- \texttt{sorace}, and \texttt{kowalik}},- abstract = {The invention relates to an electric device comprising a- generator, in particular for use in the vehicle electric- system of a motor vehicle and a controller for controlling the- generator voltage. The device is equipped with a control zone,- in which the voltage is controlled and zones, in which the- torque is controlled. The invention also relates to methods- for operating a device of this type.},- file = {http://v3.espacenet.com/textdoc?IDX=EP1700367},-}--@patent{sorace,- author = {Sorace, Ronald E. and Reinhardt, Victor S. and Vaughn, Steven- A.},- title = {High-Speed Digital-to-{RF} Converter},- number = 5668842,- date = {1997-09-16},- holder = {{Hughes Aircraft Company}},- type = {patentus},- langid = {english},- langidopts = {variant=american},- annotation = {This is a \texttt{patent} entry with a \texttt{holder} field.- Note the format of the \texttt{type} and \texttt{date} fields- in the database file. Compare \texttt{almendro},- \texttt{laufenberg}, and \texttt{kowalik}},-}--@periodical{jcg,- title = {Computers and Graphics},- year = 2011,- issuetitle = {Semantic {3D} Media and Content},- volume = 35,- number = 4,- issn = {0097-8493},- annotation = {This is a \texttt{periodical} entry with an \texttt{issn}- field.},-}--@report{chiu,- author = {Chiu, Willy W. and Chow, We Min},- title = {A Hybrid Hierarchical Model of a {Multiple Virtual Storage}- ({MVS}) Operating System},- type = {resreport},- institution = {IBM},- date = 1978,- number = {RC-6947},- langid = {english},- langidopts = {variant=american},- sorttitle = {Hybrid Hierarchical Model of a Multiple Virtual Storage (MVS)- Operating System},- indextitle = {Hybrid Hierarchical Model, A},- annotation = {This is a \texttt{report} entry for a research report. Note- the format of the \texttt{type} field in the database file- which uses a localization key. The number of the report is- given in the \texttt{number} field. Also note the- \texttt{sorttitle} and \texttt{indextitle} fields},-}--@report{padhye,- author = {Padhye, Jitendra and Firoiu, Victor and Towsley, Don},- title = {A Stochastic Model of {TCP Reno} Congestion Avoidance and- Control},- type = {techreport},- institution = {University of Massachusetts},- date = 1999,- number = {99-02},- location = {Amherst, Mass.},- langid = {english},- langidopts = {variant=american},- sorttitle = {A Stochastic Model of TCP Reno Congestion Avoidance and- Control},- indextitle = {Stochastic Model of {TCP Reno} Congestion Avoidance and Control,- A},- annotation = {This is a \texttt{report} entry for a technical report. Note- the format of the \texttt{type} field in the database file- which uses a localization key. The number of the report is- given in the \texttt{number} field. Also note the- \texttt{sorttitle} and \texttt{indextitle} fields},- abstract = {The steady state performance of a bulk transfer TCP flow- (i.e. a flow with a large amount of data to send, such as FTP- transfers) may be characterized by three quantities. The first- is the send rate, which is the amount of data sent by the- sender in unit time. The second is the throughput, which is- the amount of data received by the receiver in unit time. Note- that the throughput will always be less than or equal to the- send rate due to losses. Finally, the number of non-duplicate- packets received by the receiver in unit time gives us the- goodput of the connection. The goodput is always less than or- equal to the throughput, since the receiver may receive two- copies of the same packet due to retransmissions by the- sender. In a previous paper, we presented a simple model for- predicting the steady state send rate of a bulk transfer TCP- flow as a function of loss rate and round trip time. In this- paper, we extend that work in two ways. First, we analyze the- performance of bulk transfer TCP flows using more precise,- stochastic analysis. Second, we build upon the previous- analysis to provide both an approximate formula as well as a- more accurate stochastic model for the steady state throughput- of a bulk transfer TCP flow.},- file = {ftp://gaia.cs.umass.edu/pub/Padhey99-markov.ps},-}--@thesis{geer,- author = {de Geer, Ingrid},- title = {Earl, Saint, Bishop, Skald~-- and Music},- type = {phdthesis},- institution = {Uppsala Universitet},- date = 1985,- subtitle = {The {Orkney Earldom} of the Twelfth Century. {A} Musicological- Study},- location = {Uppsala},- options = {useprefix=false},- langid = {english},- langidopts = {variant=british},- annotation = {This is a typical \texttt{thesis} entry for a PhD thesis. Note- the \texttt{type} field in the database file which uses a- localization key. Also note the format of the printed name and- compare the \texttt{useprefix} option in the \texttt{options}- field as well as \texttt{vangennep}},-}--@thesis{loh,- author = {Loh, Nin C.},- title = {High-Resolution Micromachined Interferometric Accelerometer},- type = {mathesis},- institution = {Massachusetts Institute of Technology},- date = 1992,- location = {Cambridge, Mass.},- langid = {english},- langidopts = {variant=american},- annotation = {This is a typical \texttt{thesis} entry for an MA thesis. Note- the \texttt{type} field in the database file which uses a- localization key},-}
@@ -63,7 +63,7 @@ publisher-place: Cambridge title: "Le *De Anima* dans la tradition grècque: Quelques aspects de l'interpretation du traité, de Theophraste à Themistius"- title-short: *De Anima* dans la tradition grècque+ title-short: "*De Anima* dans la tradition grècque" type: paper-conference - author: - family: Salam
@@ -72,8 +72,8 @@ language: la number-of-volumes: 2 publisher-place: Leipzig- title: "Regesta Pontificum Romanorum ab condita ecclesia ad annum post- Christum natum [mcxcviii]{.smallcaps}"+ title: Regesta Pontificum Romanorum ab condita ecclesia ad annum post+ Christum natum [mcxcviii]{.smallcaps} title-short: Regesta Pontificum Romanorum type: book ---
@@ -86,7 +86,7 @@ publisher-place: Cambridge title: "Le *De Anima* dans la tradition grècque: Quelques aspects de l'interpretation du traité, de Theophraste à Themistius"- title-short: *De Anima* dans la tradition grècque+ title-short: "*De Anima* dans la tradition grècque" type: paper-conference ---
@@ -1,63 +0,0 @@-```-% pandoc -f biblatex -t markdown -s-@comment{--Adapted from biblatex-example.bib---Formatted with pandoc and chicago-author-date.csl, 2013-10-23:--(Nussbaum 1978)--Nussbaum, Martha. 1978. *Aristotle’s “De Motu Animalium”*. Princeton:-Princeton University Press.---Formatted with pandoc and apa.csl, 2013-10-23:--(Nussbaum, 1978)--Nussbaum, M. (1978). *Aristotle’s “De Motu Animalium”*. Princeton:-Princeton University Press.---}--@string{ pup = {Princeton University Press} }--@Book{nussbaum,- author = {Nussbaum, Martha},- title = {Aristotle's \mkbibquote{De Motu Animalium}},- date = 1978,- publisher = pup,- location = {Princeton},- keywords = {secondary},- hyphenation = {american},- sorttitle = {Aristotle's De Motu Animalium},- indexsorttitle= {Aristotle's De Motu Animalium},- annotation = {A book entry. Note the sorttitle and- indexsorttitle fields and the markup of the quotes in- the database file},-}--^D-----nocite: "[@*]"-references:-- annote: A book entry. Note the sorttitle and indexsorttitle fields and- the markup of the quotes in the database file- author:- - family: Nussbaum- given: Martha- id: nussbaum- issued: 1978- keyword: secondary- language: en-US- publisher: Princeton University Press- publisher-place: Princeton- title: "Aristotle's \"De Motu Animalium\""- type: book-------```
@@ -36,7 +36,7 @@ language: en-US publisher: Princeton University Press publisher-place: Princeton- title: "Aristotle's \"De Motu Animalium\""+ title: Aristotle's "De Motu Animalium" type: book ---
@@ -90,7 +90,7 @@ - family: Ryde given: Ulf container-title: Journal of Computational Chemistry- doi: "10.1002/(SICI)1096-987X(199803)19:4\\<377::AID-JCC1\\>3.0.CO;2-P"+ doi: "10.1002/(SICI)1096-987X(199803)19:4\\<377::AID-JCC1>3.0.CO;2-P" id: sigfridsson issue: 4 issued: 1998
@@ -63,8 +63,8 @@ issued: 1969 language: de-DE page: 189-216- title: "Intention" und "Intentionalität" in der Scholastik, bei- Brentano und Husserl+ title: "\"Intention\" und \"Intentionalität\" in der Scholastik, bei+ Brentano und Husserl" title-short: Intention und Intentionalität type: article-journal volume: 29
@@ -63,9 +63,9 @@ id: item1 issued: 2013 language: en-US- title: "A title, in English, with a Proper Name and an ACRONYM and a+ title: A title, in English, with a Proper Name and an ACRONYM and a [camelCase]{.nocase} word and some units, 400 [nm]{.nocase},- 3 [cm]{.nocase}, and a quote, *Alea [iacta est]{.nocase}*"+ 3 [cm]{.nocase}, and a quote, *Alea [iacta est]{.nocase}* type: article-journal ---
@@ -9,7 +9,7 @@ nocite: "[@*]" references: - id: item1- title: "The title [of this book]{.nodecor}"+ title: The title [of this book]{.nodecor} type: book ---
binary file changed (absent → 8758 bytes)
@@ -0,0 +1,17 @@+# Chapter one++A spider: ++Another spider: ![another spider][refspider]++The moon: ++Link to [spider picture](spider.png).++URL left alone: [manual](https://pandoc.org/MANUAL.html).++Absolute path left alone: [absolute](/foo/bar/baz.png).++Link to fragment: [chapter two](#chapter-two).++Empty path: [empty]().
binary file changed (absent → 2921 bytes)
@@ -0,0 +1,5 @@+# Chapter two++A spider: ++[refspider]: spider.png
@@ -1,5 +1,5 @@ ```-% pandoc -d command/defaults6+% pandoc -d command/defaults6 2>&1 ^D Error: Circular defaults file reference in 'command/defaults7.yaml' ```
@@ -0,0 +1,20 @@+```+% pandoc -f markdown_mmd -t markdown -s+Title: Blah blah blah+Author: Doo de Doo+Base Header Level: 1+Bibliography: Pubs.bib+Lang: en-GB++body+^D+---+author: Doo de Doo+baseheaderlevel: 1+bibliography: Pubs.bib+lang: en-GB+title: Blah blah blah+---++body+```
@@ -0,0 +1,55 @@+```+% pandoc -f latex -t plain+\iftrue+should print+\iftrue+should print+\else+should not print+\fi+\else+should not print+\fi++\iffalse+should not print+\else+\iftrue+should print+\else+should not print+\fi+\fi++\newif\ifepub++\ifepub+should not print+\fi++\epubtrue++\ifepub+should print+\else+should not print+\fi++\epubfalse++\ifepub+should not print+\else+should print+\fi+^D+should print++should print++should print++should print++should print+```
@@ -1,7 +1,7 @@ ``` % pandoc --citeproc -t markdown-citations ----bibliography: 'command/biblatex-examples.bib'+bibliography: 'command/averroes.bib' csl: command/apa.csl ---
@@ -49,7 +49,7 @@ 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.; al-'Udhrī, n.d.; Uch, n.d.; Uebel, n.d.; Zzz, n.d.).+n.d.a, n.d.b; Uch, n.d.; Uebel, n.d.; Zzz, n.d.). ::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item6 .csl-entry}@@ -69,11 +69,11 @@ ::: ::: {#ref-item4 .csl-entry}-'Udhrī, Jamīl al-. n.d.+'Udhrī, Jamīl al-. n.d.a. ::: ::: {#ref-item5 .csl-entry}-'Udhrī, Jamīl al-. n.d.+---------. n.d.b. ::: ::: {#ref-item7 .csl-entry}
@@ -14,7 +14,7 @@ id: 'stotz:1996handbuch' issued: literal: 1996_2004- language: German+ language: de number-of-volumes: 5 publisher: Beck publisher-place: Munich
@@ -22,7 +22,7 @@ issued: date-parts: - - 2009- language: French+ language: fr page: '155--174' publisher: 'Fédération Internationale des Instituts d''Études Médiévales'@@ -42,7 +42,7 @@ issued: date-parts: - - 1955- language: Latin+ language: la note: 'ArticleType: research-article / Full publication date: 1955 / Copyright © 1955 Fordham University' page: '163--193'
@@ -2,7 +2,7 @@ % pandoc -f latex -t icml \includegraphics{command/corrupt.svg} ^D-[WARNING] Could not determine image size for 'command/corrupt.svg': could not determine image type+[WARNING] Could not determine image size for command/corrupt.svg: could not determine image type <ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph"> <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle"> <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 150 -100">
@@ -31,7 +31,7 @@ ## b -::: {.interior}+::: interior # C ## cc@@ -39,7 +39,7 @@ # D ::: -::: {.blue}+::: blue # E ## e
@@ -0,0 +1,130 @@+```+% pandoc --citeproc -t plain+---+lang: en-US+csl: command/apa.csl+references:+- id: a1+ type: book+ author:+ - family: Ubina+ given: A. John+ issued: 1985+- id: a2+ type: book+ author:+ - family: Über+ given: Aglaia+ issued: 1996+- id: a3+ type: book+ author:+ - family: Oñate+ given: José+ issued: 1985+- id: a4+ type: book+ author:+ - family: Onush+ given: Frank+ issued: 2002+- id: a5+ type: book+ author:+ - family: O'Neil+ given: Timothy+ issued: 2010+---++[@a1;@a2;@a3;@a4;@a5]+^D+(O’Neil, 2010; Oñate, 1985; Onush, 2002; Über, 1996; Ubina, 1985)++O’Neil, T. (2010).++Oñate, J. (1985).++Onush, F. (2002).++Über, A. (1996).++Ubina, A. J. (1985).+```++```+% pandoc --citeproc -t plain+---+lang: es+csl: command/apa.csl+references:+- id: a1+ type: book+ author:+ - family: Ubina+ given: A. John+ issued: 1985+- id: a2+ type: book+ author:+ - family: Über+ given: Aglaia+ issued: 1996+- id: a3+ type: book+ author:+ - family: Oñate+ given: José+ issued: 1985+- id: a4+ type: book+ author:+ - family: Onush+ given: Frank+ issued: 2002+- id: a5+ type: book+ author:+ - family: O'Neil+ given: Timothy+ issued: 2010+---++[@a1;@a2;@a3;@a4;@a5]+^D+(O’Neil, 2010; Onush, 2002; Oñate, 1985; Über, 1996; Ubina, 1985)++O’Neil, T. (2010).++Onush, F. (2002).++Oñate, J. (1985).++Über, A. (1996).++Ubina, A. J. (1985).+```++```+% pandoc -C -t plain+---+nocite: '@*'+lang: fr-FR-u-kb-true+references:+- id: cote+ author: cote+- id: côte+ author: côte+- id: coté+ author: coté+- id: côté+ author: côté+...+^D+cote. s. d.++côte. s. d.++coté. s. d.++côté. s. d.+```
@@ -6,7 +6,9 @@ <!ENTITY let "LET" > <!ENTITY case "CASE" > ]>-<article>+<article xmlns="http://docbook.org/ns/docbook"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:mml="http://www.w3.org/1998/Math/MathML"> <articleinfo> <title>Pandoc Test Suite</title> <authorgroup>
@@ -1,6 +1,6 @@ [Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 1.0)] (TableHead ("",[],[]) []) [(TableBody ("",[],[]) (RowHeadColumns 0)
binary file changed (10067 → 9981 bytes)
binary file changed (9916 → 9830 bytes)
binary file changed (10254 → 10168 bytes)
binary file changed (10017 → 9931 bytes)
binary file changed (10646 → 10560 bytes)
binary file changed (12400 → 12368 bytes)
binary file changed (9916 → 9830 bytes)
binary file changed (9922 → 9835 bytes)
binary file changed (10399 → 10314 bytes)
binary file changed (10055 → 9969 bytes)
binary file changed (26733 → 26647 bytes)
binary file changed (9855 → 9769 bytes)
binary file changed (10035 → 9949 bytes)
binary file changed (26789 → 26703 bytes)
binary file changed (10077 → 9991 bytes)
binary file changed (10248 → 10162 bytes)
binary file changed (10314 → 10228 bytes)
binary file changed (10110 → 10024 bytes)
binary file changed (10192 → 10106 bytes)
binary file changed (10108 → 10022 bytes)
binary file changed (10212 → 10126 bytes)
binary file changed (10024 → 9938 bytes)
binary file changed (9956 → 9870 bytes)
binary file changed (10090 → 10004 bytes)
binary file changed (9903 → 9840 bytes)
binary file changed (10212 → 10162 bytes)
binary file changed (absent → 10200 bytes)
binary file changed (10238 → 10202 bytes)
binary file changed (9899 → 9813 bytes)
binary file changed (9882 → 9796 bytes)
binary file changed (9916 → 9830 bytes)
binary file changed (10028 → 9942 bytes)
binary file changed (9841 → 9755 bytes)
binary file changed (9888 → 9802 bytes)
binary file changed (absent → 74199 bytes)
@@ -0,0 +1,2 @@+[Para [Str "Test",Space,Str "with",Space,Str "object",Space,Str "as",Space,Str "image:"]+,Para [Image ("",[],[]) [] ("media/image1.emf","")]]
@@ -1,20 +1,19 @@ [Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 0.22069570301081556)+ ,(AlignDefault,ColWidth 0.22069570301081556)+ ,(AlignDefault,ColWidth 0.5586085939783689)] (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])+ [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"]]]]- ,Row ("",[],[])+ [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)
binary file changed (absent → 40482 bytes)
@@ -0,0 +1,34 @@+[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", [], []) []]
binary file changed (absent → 41091 bytes)
@@ -0,0 +1,54 @@+[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."]]
binary file changed (absent → 15826 bytes)
@@ -0,0 +1,189 @@+[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 ("",[],[])+ [])]
binary file changed (absent → 12185 bytes)
@@ -0,0 +1,18 @@+[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 ("",[],[])+ [])]
binary file changed (25251 → 12148 bytes)
@@ -1,8 +1,8 @@ [Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 0.3333333333333333)+ ,(AlignDefault,ColWidth 0.3333333333333333)+ ,(AlignDefault,ColWidth 0.3333333333333333)] (TableHead ("",[],[]) []) [(TableBody ("",[],[]) (RowHeadColumns 0)
@@ -1,10 +1,11 @@ [Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(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)@@ -13,33 +14,27 @@ [] ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "h3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ ,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 1)+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3) [Plain [Str "c11"]] ,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 2) []] ,Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []- ,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 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2) []]])] (TableFoot ("",[],[]) [])]
@@ -1,7 +1,7 @@ [Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 0.5)+ ,(AlignDefault,ColWidth 0.5)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
@@ -0,0 +1,92 @@+[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,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)]+ (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,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)]+ (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,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)]+ (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 ("",[],[])+ [])]
@@ -1,10 +1,10 @@ [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,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 0.25)+ ,(AlignDefault,ColWidth 0.25)+ ,(AlignDefault,ColWidth 0.25)+ ,(AlignDefault,ColWidth 0.25)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)@@ -48,8 +48,8 @@ []) ,Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 0.5)+ ,(AlignDefault,ColWidth 0.5)] (TableHead ("",[],[]) []) [(TableBody ("",[],[]) (RowHeadColumns 0)@@ -68,8 +68,8 @@ []) ,Table ("",[],[]) (Caption Nothing [])- [(AlignDefault,ColWidthDefault)- ,(AlignDefault,ColWidthDefault)]+ [(AlignDefault,ColWidth 0.5)+ ,(AlignDefault,ColWidth 0.5)] (TableHead ("",[],[]) []) [(TableBody ("",[],[]) (RowHeadColumns 0)
binary file changed (101870 → 35496 bytes)
@@ -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><p>This example test if Pandoc correctly embeds images into FictionBook.</p><p>Small inline image: <image l:href="#image1" l:type="inlineImageType" alt="alt text a small PNG image" />.</p><p>Paragraph image:</p><image l:href="#image2" l:type="imageType" alt="alt text of a big JPEG image" title="image title text" /><p>alt text of a big missing image</p><p>A missing image inline: alt text of missing image.</p></section></body><binary id="image2" content-type="image/jpeg">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</binary><binary id="image1" content-type="image/png">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</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><p>This example test if Pandoc correctly embeds images into FictionBook.</p><p>Small inline image: <image l:href="#image1" l:type="inlineImageType" alt="alt text a small PNG image" />.</p><p>Paragraph image:</p><image l:href="#image2" l:type="imageType" alt="alt text of a big JPEG image" title="image title text" /><p>alt text of a big missing image</p><p>A missing image inline: alt text of missing image.</p></section></body><binary id="image2" content-type="image/jpeg">/9j/4AAQSkZJRgABAQEASABIAAD/4QOoRXhpZgAATU0AKgAAAAgAFgD+AAQAAAABAAAAAQEPAAIAAAAUAAABFgEQAAIAAAAUAAABKgESAAMAAAABAAEAAAExAAIAAAAdAAABPgEyAAIAAAAUAAABXEdGAAkAAAABAAAAAkdJAAkAAAABAAAAKIdpAAQAAAABAAACXMYSAAEAAAAEAQEAAMYTAAEAAAAEAQEAAMYUAAIAAAAMAAABcMYhAAoAAAAJAAABfMYiAAoAAAAJAAABxMYnAAUAAAADAAACDMYoAAUAAAADAAACJMYqAAoAAAABAAACPMYrAAUAAAABAAACRMYsAAUAAAABAAACTMYuAAUAAAABAAACVMZaAAMAAAABABEAAMZbAAMAAAABABUAAAAAAABQRU5UQVggICAgICAgICAgICAgAFBFTlRBWCBLMjBEICAgICAgICAAZGFya3RhYmxlIDAuNy4xKzkxM35nYTA5MzllYQAAMjAxMTowMjowNiAwNzoyOToxNgBQRU5UQVggSzIwRAAAAZM/AAEAAP//NuAAAQAA///jlgABAAD//2viAAEAAAABh0EAAQAAAABNLwABAAD//+62AAEAAAAAKd8AAQAAAAFHQAABAAAAASNbAAEAAP//py8AAQAA///Z7gABAAD//4X3AAEAAAABWGsAAQAAAAAZVgABAAD//9qsAAEAAAAAUBMAAQAAAACr2QABAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAEAAAABdAAAAQAAAAEAAAABAAAAAWX//4AAAAEAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAVgpoABQAAAAEAAANegp0ABQAAAAEAAANmiCIAAwAAAAEAAQAAiCcAAwAAAAEAyAAAkAMAAgAAABQAAANukAQAAgAAABQAAAOCkgQACgAAAAEAAAOWkgcAAwAAAAEABQAAkgkAAwAAAAEAEAAAkgoABQAAAAEAAAOeoAEAAwAAAAEAAQAAohcAAwAAAAEAAgAApAEAAwAAAAEAAAAApAIAAwAAAAEAAQAApAMAAwAAAAEAAAAApAUAAwAAAAEAhwAApAYAAwAAAAEAAAAApAgAAwAAAAEAAAAApAkAAwAAAAEAAAAApAoAAwAAAAEAAAAApAwAAwAAAAEAAwAAAAAAAAAAAAEAAAAyAAAAHAAAAAoyMDExOjAyOjA2IDA3OjI5OjE2ADIwMTE6MDI6MDYgMDc6Mjk6MTYAAAAACgAAAAoAAP/iAxhJQ0NfUFJPRklMRQABAQAAAwhsY21zBCAAAG1udHJSR0IgWFlaIAfbAAIACgAWABAAGmFjc3BBUFBMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD21gABAAAAANMtbGNtcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWRlc2MAAAEgAAAAUGNwcnQAAAFwAAAAgHd0cHQAAAHwAAAAFGNoYWQAAAIEAAAALHJYWVoAAAIwAAAAFGJYWVoAAAJEAAAAFGdYWVoAAAJYAAAAFHJUUkMAAAJsAAAAIGdUUkMAAAKMAAAAIGJUUkMAAAKsAAAAIGNocm0AAALMAAAAJGRtbmQAAALwAAAADWRtZGQAAAMAAAAABW1sdWMAAAAAAAAAAQAAAAxlblVTAAAANAAAABwAUgAAAEcAAABCAAAAIAAAAGIAAAB1AAAAaQAAAGwAAAB0AAAALQAAAGkAAABuAAAAAAAAbWx1YwAAAAAAAAABAAAADGVuVVMAAABkAAAAHABOAAAAbwAAACAAAABjAAAAbwAAAHAAAAB5AAAAcgAAAGkAAABnAAAAaAAAAHQAAAAsAAAAIAAAAHUAAABzAAAAZQAAACAAAABmAAAAcgAAAGUAAABlAAAAbAAAAHkAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLXNmMzIAAAAAAAEMSgAABeP///MqAAAHmwAA/Yf///ui///9owAAA9gAAMCUWFlaIAAAAAAAAG+UAAA47gAAA5BYWVogAAAAAAAAJJ0AAA+DAAC2vlhZWiAAAAAAAABipQAAt5AAABjecGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACltwYXJhAAAAAAADAAAAAmZmAADypwAADVkAABPQAAAKW3BhcmEAAAAAAAMAAAACZmYAAPKnAAANWQAAE9AAAApbY2hybQAAAAAAAwAAAACj1wAAVHsAAEzNAACZmgAAJmYAAA9cKGR0IGludGVybmFsKQAAAHNSR0IAAAAA/9sAQwAbEhQXFBEbFxYXHhwbIChCKyglJShROj0wQmBVZWRfVV1baniZgWpxkHNbXYW1hpCeo6utq2eAvMm6pseZqKuk/9sAQwEcHh4oIyhOKytOpG5dbqSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSk/8AAEQgAgADAAwERAAIRAQMRAf/EABkAAAMBAQEAAAAAAAAAAAAAAAEAAwQCBf/EADIQAAEDAwMDAQYGAgMAAAAAAAEAAhEDEiExE1EEQWEiQpFxI4GxFFLwMqEF0eEkYsH/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAQID/8QAGxEBAQEBAAMBAAAAAAAAAAAAABEBEgIxIUH/2gAMAwEAAhEDEQA/APehabMIGEDCBhAwgYQMoATGdQgQ4GI7oCgEIFAoGEAVAhAoAgYQBAECigqNCwhRSiFBw54aEUWvDhIKDpERqGDMqqg6rIsbr2Co7Y4lrc50Ed8qC4cDjugMogoFAECgUUEAhAoAgEKhQBBoWAoFAHCfiqMtZxaCKhjz2VGShXLPS6QQ3ug1N6gbgaQZicaICKm48lkY0M6oOOoDGupkyWE5xp+iiAWupsYHD1EAADlFdF74ggNdOkIKNJLrSSecILtUBhAECgCBQBAqgIAgCBQaFlCgCDJ1FdzMNJB4wqrhlZrzZVBDoiI1QZOrpOkOa8ENabCRM+CqE1A1jS4EEDMHA+iDU53oaYDT2jUf5UGZ1V0xJudaSD7JDhn9cKjS2s0VxcC5wAjnKg5fdV6p0uAa0DPYKjRRe1lIxmO/KhCOpaHkGdYQXDge6AoGEAQKAIAgUAQBAEGhZQoFBCo2nock9lVQNA33tdLRm3Uqo46mi1/TuioSw5k+yeUEqDTUZ8zBJ26k89j+uQipvApN/Duabg2WPHcDsgl1Nz6FOrTa6bXH08RP+EGiqW0unNYGXO9cHXJwPsglcRSD3ujxMl0qi7XAUjL4GjQ6JKgpSBj0tdkyC46oNNJrvaIlBaFAoFAECiggCBKAIAqLrLJQcvzgIoNZGpKI5exuvqEdwUGd729O4vvDmu/cMSPKqslaqyk8vJ/49QWuH5D2093uQ9KPO70oeS4GnrGsDBQZqrrehaWEQabmEf8Aa0/eFUFkGmKlYkuHpYzsTpJ5RVWU3Bw26bQ4CCT7I+PPj7IK0KT3m4YaDgnNyg2tptmXep3JQdhoGigKAIFFBAoAgUAQBAFRZZQzCDlzgAgQ7X4IIPebvVFvCqpWhziXMf4kf4QQqspNllgdRcYgey49vH68Koy9NVrs6mpRAc5zRJDtXdp90IJdU67pOlptxc4N8yJE/wAomrUKdT8W8UTdTZ6GnWwd/wCZRWi5oI6ZrvDiOOPiUVrY4N0LwYjtCgowOH7iZQWBwiFQKoVFBAoAilAEAQBUVlZZAnCKy1XuktbBPHCKl+IcwAvY4azkH7FUVaWuALXYJmRlB2RTAFznE83FSpGbqdupSfFQ3EYBP/qtIxMu6nrBd8vqqTDkcgj+DJV/Eef1dRzXFjwWPbUJI4mMq4mvV6YGh07KDQQ97cN5Pcnx/pRrMEDp6QABugF1xzn7ZRcaadakykJdaJ0/0oq9PqGVDgzGAiRYOlEgygZQCVFMoFAJQMooSgZQCVR1KyhJkIOQwNGNUHDgACYM+EVnqUHXBzKQBPMEfUK1GZ+410VDafyDv8Ciqsp06jMummYwMZ8oRne/Z/selc4Sc0y8e0IxPmVfxncms398xv4qi4NBLhHxz3V8U8saemfuPcX66uz7m/AKa3mNvUPLg2lSaHVHic+yOSpienNDotl0l7nuOpHpn3JuqtUokmWvLTyM/dKho3NJbUJ8HlFaAUDKhAlCGUIEoplCBKBlCBKLAlCDcoQbkIbkI5JzPCEcl0unhCOKoY8RUAI4KpGDqKh6T1seXUnDLXajyr7SRz1RNb+vp1Wj1sAqN76Jns3LlYeurs6ur04ozI9+VrMjHltkaw5tB220es4lx08lZ9unr439I9tMRfcXZLjqSppy1NqBxQg3IQCQTlCCHQhDcoQLkWG5CBchDchAuRYFyENyEC5UiW8FeWoO8FJpB3gk0h3gkIBqgDukIx9RVvBjLQJE5WsxNZWl7hEkjTOR9VYyFB1nyKl8tGCDqO2EiePz5rA+KXW/KcCA4QSr+OW/PL49I7TAHON9QnLu/wCvCjtMxQVWgztyfphSKvT6m15Gg7JFahVBCkWODW+aMwISI73UindCQDdHKQO4kA3PKQDcSB3UgG6kA3UgG6rBlFUcrpHPsdzykOhvKQ6O4kOk6tUuFo96Q6RqOhoaDMJGenDazGttkDukOk6lQ1HE0yL2SQQYlIm+VY5NSvI18qOdutTasumJI/hWN55K0nuyBE95KRrPJelJ/f7kjXTQHwNUi9OTU+Z9EidO9xIvQbiQ6O55SHTk1Y7pDo7iQ6O4kOg3PKQ6DcKQ6O4eUh0BqFInTFkFbcBDnA4JQd3P/MULoEuOpJQc2lBzUkDRBwAXGFEFzYHhFZSbapjGVn9RSnnAKuC4vGkiOFpape8QbihdHdf+YoXXO48u/cULpudyUKEnlCg57gNShXLajicklCu7jOqFC9w7lCg6s8DBKhdD8Q8nVC6O+7lC6d1x9pUup7zuVmhFZ3KtB33cpSnfdylKd535ilKTWJ1KUEVY0SgGpISjNVy6eVnUVoODW6K4K7ytUd5KBveEoG4JnKUdbyUDdSgGpIhKgMdalB3AlU3jlKOS4FKjlQHEaqgY5QQuKwG8oDeVQ3lShvPCoN6BvShvQckyoC10CFR1egb0DegbwgbwgbggbvKBvHKBuQN/lKG/ygF3lAl3lKOHunRQCFAIKA5QDKBQGUCqFAoplEMoplEFAoFAJQKBQP0QKBQBAoFB/9k=</binary><binary id="image1" content-type="image/png">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</binary></FictionBook>
binary file changed (153610 → 3959 bytes)
@@ -1,5 +1,6 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("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 ("pandoc-test-suite",["title"],[]) [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."] ,HorizontalRule ,Header 1 ("headers",[],[]) [Str "Headers"] ,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link ("",[],[]) [Str "embedded",Space,Str "link"] ("/url","")]
@@ -4,6 +4,9 @@ % \documentclass[ ]{article}+\author{}+\date{}+ \usepackage{amsmath,amssymb} \usepackage{lmodern} \usepackage{iftex}@@ -84,9 +87,6 @@ \ifLuaTeX \usepackage{selnolig} % disable illegal ligatures \fi--\author{}-\date{} \begin{document}
@@ -4,6 +4,9 @@ % \documentclass[ ]{article}+\author{}+\date{}+ \usepackage{amsmath,amssymb} \usepackage{lmodern} \usepackage{iftex}@@ -51,9 +54,6 @@ \ifLuaTeX \usepackage{selnolig} % disable illegal ligatures \fi--\author{}-\date{} \begin{document}
@@ -0,0 +1,1 @@+[Para [Str "Three",Space,Str "tabs",Space,Str "between",Space,Str "A",Space,Str "and",Space,Str "B",Space,Str "will",Space,Str "be",Space,Str "converted",Space,Str "to",Space,Str "one",Space,Str "Space:",Space,Str "A",Space,Str "B."]]
binary file changed (absent → 10170 bytes)
binary file changed (395477 → 41337 bytes)
binary file changed (395477 → 41337 bytes)
binary file changed (394253 → 40113 bytes)
binary file changed (394656 → 40517 bytes)
binary file changed (394219 → 40078 bytes)
binary file changed (395041 → 40899 bytes)
binary file changed (411870 → 57729 bytes)
binary file changed (393412 → 39272 bytes)
binary file changed (394307 → 40166 bytes)
binary file changed (394198 → 40059 bytes)
binary file changed (397502 → 43743 bytes)
binary file changed (411311 → 57172 bytes)
binary file changed (395000 → 40858 bytes)
binary file changed (395825 → 41683 bytes)
binary file changed (396776 → 42634 bytes)
binary file changed (398915 → 44775 bytes)
binary file changed (397943 → 43803 bytes)
binary file changed (418834 → 64695 bytes)
binary file changed (402650 → 48507 bytes)
binary file changed (394283 → 40142 bytes)
binary file changed (394827 → 40686 bytes)
binary file changed (393327 → 39189 bytes)
@@ -143,6 +143,7 @@ .PP Here\[cq]s the caption. It may span multiple lines. .na+.nr LLold \n[LL] .TS delim(@@) tab( ); cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).@@ -157,30 +158,40 @@ T} _ T{+.nr LL 10.5n First T} T{+.nr LL 9.6n row T} T{+.nr LL 11.4n 12.0 T} T{+.nr LL 24.5n Example of a row that spans multiple lines. T} T{+.nr LL 10.5n Second T} T{+.nr LL 9.6n row T} T{+.nr LL 11.4n 5.0 T} T{+.nr LL 24.5n Here\[cq]s another one. Note the blank line between rows. T} .TE+.nr LL \n[LLold] .ad .LP Multiline table without caption: .PP .na+.nr LLold \n[LL] .TS delim(@@) tab( ); cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).@@ -195,25 +206,34 @@ T} _ T{+.nr LL 10.5n First T} T{+.nr LL 9.6n row T} T{+.nr LL 11.4n 12.0 T} T{+.nr LL 24.5n Example of a row that spans multiple lines. T} T{+.nr LL 10.5n Second T} T{+.nr LL 9.6n row T} T{+.nr LL 11.4n 5.0 T} T{+.nr LL 24.5n Here\[cq]s another one. Note the blank line between rows. T} .TE+.nr LL \n[LLold] .ad .LP Table without column headers:@@ -255,27 +275,37 @@ Multiline table without column headers: .PP .na+.nr LLold \n[LL] .TS delim(@@) tab( ); cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n). T{+.nr LL 10.5n First T} T{+.nr LL 9.6n row T} T{+.nr LL 11.4n 12.0 T} T{+.nr LL 24.5n Example of a row that spans multiple lines. T} T{+.nr LL 10.5n Second T} T{+.nr LL 9.6n row T} T{+.nr LL 11.4n 5.0 T} T{+.nr LL 24.5n Here\[cq]s another one. Note the blank line between rows. T} .TE+.nr LL \n[LLold] .ad
@@ -17,6 +17,7 @@ % use microtypography \definefontfeature[default][default][script=latn, protrusion=quality, expansion=quality, itlc=yes, textitalics=yes, onum=yes, pnum=yes]+\definefontfeature[default:tnum][default][tnum=yes, pnum=no] \definefontfeature[smallcaps][script=latn, protrusion=quality, expansion=quality, smcp=yes, onum=yes, pnum=yes] \setupalign[hz,hanging] \setupitaliccorrection[global, always]@@ -48,6 +49,9 @@ \setupitemize[autointro] % prevent orphan list intro \setupitemize[indentnext=no] +\defineitemgroup[enumerate]+\setupenumerate[each][fit][itemalign=left,distance=.5em,style={\feature[+][default:tnum]}]+ \setupfloat[figure][default={here,nonumber}] \setupfloat[table][default={here,nonumber}] @@ -133,12 +137,12 @@ A list: -\startitemize[n,packed][stopper=.]+\startenumerate[n,packed][stopper=.] \item item one \item item two-\stopitemize+\stopenumerate Nested block quotes: @@ -255,51 +259,51 @@ Tight: -\startitemize[n,packed][stopper=.]+\startenumerate[n,packed][stopper=.] \item First \item Second \item Third-\stopitemize+\stopenumerate and: -\startitemize[n,packed][stopper=.]+\startenumerate[n,packed][stopper=.] \item One \item Two \item Three-\stopitemize+\stopenumerate Loose using tabs: -\startitemize[n][stopper=.]+\startenumerate[n][stopper=.] \item First \item Second \item Third-\stopitemize+\stopenumerate and using spaces: -\startitemize[n][stopper=.]+\startenumerate[n][stopper=.] \item One \item Two \item Three-\stopitemize+\stopenumerate Multiple paragraphs: -\startitemize[n][stopper=.]+\startenumerate[n][stopper=.] \item Item 1, graf one. @@ -308,7 +312,7 @@ Item 2. \item Item 3.-\stopitemize+\stopenumerate \subsection[title={Nested},reference={nested}] @@ -327,7 +331,7 @@ Here's another: -\startitemize[n,packed][stopper=.]+\startenumerate[n,packed][stopper=.] \item First \item@@ -342,11 +346,11 @@ \stopitemize \item Third-\stopitemize+\stopenumerate Same thing but with paragraphs: -\startitemize[n][stopper=.]+\startenumerate[n][stopper=.] \item First \item@@ -362,7 +366,7 @@ \stopitemize \item Third-\stopitemize+\stopenumerate \subsection[title={Tabs and spaces},reference={tabs-and-spaces}] @@ -382,7 +386,7 @@ \subsection[title={Fancy list markers},reference={fancy-list-markers}] -\startitemize[n][start=2,left=(,stopper=),width=2.0em]+\startenumerate[n][start=2,left=(,stopper=)] \item begins with 2 \item@@ -390,51 +394,51 @@ with a continuation - \startitemize[r,packed][start=4,stopper=.,width=2.0em]+ \startenumerate[r,packed][start=4,stopper=.] \item sublist with roman numerals, starting with 4 \item more items- \startitemize[A,packed][left=(,stopper=),width=2.0em]+ \startenumerate[A,packed][left=(,stopper=)] \item a subsublist \item a subsublist- \stopitemize- \stopitemize-\stopitemize+ \stopenumerate+ \stopenumerate+\stopenumerate Nesting: -\startitemize[A,packed][stopper=.]+\startenumerate[A,packed][stopper=.] \item Upper Alpha- \startitemize[R,packed][stopper=.]+ \startenumerate[R,packed][stopper=.] \item Upper Roman.- \startitemize[n,packed][start=6,left=(,stopper=),width=2.0em]+ \startenumerate[n,packed][start=6,left=(,stopper=)] \item Decimal start with 6- \startitemize[a,packed][start=3,stopper=)]+ \startenumerate[a,packed][start=3,stopper=)] \item Lower alpha with paren- \stopitemize- \stopitemize- \stopitemize-\stopitemize+ \stopenumerate+ \stopenumerate+ \stopenumerate+\stopenumerate Autonumbering: -\startitemize[n,packed]+\startenumerate[n,packed] \item Autonumber. \item More.- \startitemize[a,packed]+ \startenumerate[a,packed] \item Nested.- \stopitemize-\stopitemize+ \stopenumerate+\stopenumerate Should not be a list item: @@ -547,12 +551,12 @@ \startdescription{orange} orange fruit - \startitemize[n,packed][stopper=.]+ \startenumerate[n,packed][stopper=.] \item sublist \item sublist- \stopitemize+ \stopenumerate \stopdescription \section[title={HTML Blocks},reference={html-blocks}]@@ -897,10 +901,10 @@ Notes can go in quotes.\footnote{In quote.} \stopblockquote -\startitemize[n,packed][stopper=.]+\startenumerate[n,packed][stopper=.] \item And in list items.\footnote{In list.}-\stopitemize+\stopenumerate This paragraph should not be part of the note, as it is not indented.
@@ -78,39 +78,31 @@ <sec id="block-quotes"> <title>Block Quotes</title> <p>E-mail style:</p>- <p specific-use="wrapper">+ <disp-quote>+ <p>This is a block quote. It is pretty short.</p>+ </disp-quote>+ <disp-quote>+ <p>Code in a block quote:</p>+ <preformat>sub status {+ print "working";+}</preformat>+ <p>A list:</p>+ <list list-type="order">+ <list-item>+ <p>item one</p>+ </list-item>+ <list-item>+ <p>item two</p>+ </list-item>+ </list>+ <p>Nested block quotes:</p> <disp-quote>- <p>This is a block quote. It is pretty short.</p>+ <p>nested</p> </disp-quote>- </p>- <p specific-use="wrapper"> <disp-quote>- <p>Code in a block quote:</p>- <preformat>sub status {- print "working";-}</preformat>- <p>A list:</p>- <list list-type="order">- <list-item>- <p>item one</p>- </list-item>- <list-item>- <p>item two</p>- </list-item>- </list>- <p>Nested block quotes:</p>- <p specific-use="wrapper">- <disp-quote>- <p>nested</p>- </disp-quote>- </p>- <p specific-use="wrapper">- <disp-quote>- <p>nested</p>- </disp-quote>- </p>+ <p>nested</p> </disp-quote>- </p>+ </disp-quote> <p>This should not be a block quote: 2 > 1.</p> <p>And a following paragraph.</p> </sec>@@ -837,12 +829,10 @@ </list-item> </list> <p>An e-mail address: <email>nobody@nowhere.net</email></p>- <p specific-use="wrapper">- <disp-quote>- <p>Blockquoted:- <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link></p>- </disp-quote>- </p>+ <disp-quote>+ <p>Blockquoted:+ <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link></p>+ </disp-quote> <p>Auto-links should not occur here: <monospace><http://example.com/></monospace></p> <preformat>or here: <http://example.com/></preformat>@@ -866,11 +856,9 @@ <italic>not</italic> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<xref ref-type="fn" rid="fn3">3</xref></p>- <p specific-use="wrapper">- <disp-quote>- <p>Notes can go in quotes.<xref ref-type="fn" rid="fn4">4</xref></p>- </disp-quote>- </p>+ <disp-quote>+ <p>Notes can go in quotes.<xref ref-type="fn" rid="fn4">4</xref></p>+ </disp-quote> <list list-type="order"> <list-item> <p>And in list items.<xref ref-type="fn" rid="fn5">5</xref></p>@@ -882,11 +870,12 @@ <back> <fn-group> <fn 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.</p>+ <label>1</label><p>Here is the footnote. It can go anywhere after the+ footnote reference. It need not be placed at the end of the document.</p> </fn> <fn id="fn2">- <p>Here’s the long note. This one contains multiple blocks.</p>+ <label>2</label><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> <p specific-use="wrapper">@@ -896,16 +885,17 @@ just indent the first line of each block.</p> </fn> <fn id="fn3">- <p>This is <italic>easier</italic> to type. Inline notes may contain+ <label>3</label><p>This is <italic>easier</italic> to type. Inline notes+ may contain <ext-link ext-link-type="uri" xlink:href="http://google.com">links</ext-link> and <monospace>]</monospace> verbatim characters, as well as [bracketed text].</p> </fn> <fn id="fn4">- <p>In quote.</p>+ <label>4</label><p>In quote.</p> </fn> <fn id="fn5">- <p>In list.</p>+ <label>5</label><p>In list.</p> </fn> </fn-group> </back>
@@ -67,43 +67,39 @@ <sec id="block-quotes"> <title>Block Quotes</title> <p>E-mail style:</p>- <p specific-use="wrapper">- <disp-quote>- <p>This is a block quote. It is pretty short.</p>- </disp-quote>- </p>- <p specific-use="wrapper">- <disp-quote>- <p>Code in a block quote:</p>- <p specific-use="wrapper">- <preformat>sub status {+ <disp-quote>+ <p>This is a block quote. It is pretty short.</p>+ </disp-quote>+ <disp-quote>+ <p>Code in a block quote:</p>+ <p specific-use="wrapper">+ <preformat>sub status { print "working"; }</preformat>- </p>- <p>A list:</p>- <p specific-use="wrapper">- <list list-type="order">- <list-item>- <p>item one</p>- </list-item>- <list-item>- <p>item two</p>- </list-item>- </list>- </p>- <p>Nested block quotes:</p>- <p specific-use="wrapper">- <disp-quote>- <p>nested</p>- </disp-quote>- </p>- <p specific-use="wrapper">- <disp-quote>- <p>nested</p>- </disp-quote>- </p>- </disp-quote>- </p>+ </p>+ <p>A list:</p>+ <p specific-use="wrapper">+ <list list-type="order">+ <list-item>+ <p>item one</p>+ </list-item>+ <list-item>+ <p>item two</p>+ </list-item>+ </list>+ </p>+ <p>Nested block quotes:</p>+ <p specific-use="wrapper">+ <disp-quote>+ <p>nested</p>+ </disp-quote>+ </p>+ <p specific-use="wrapper">+ <disp-quote>+ <p>nested</p>+ </disp-quote>+ </p>+ </disp-quote> <p>This should not be a block quote: 2 > 1.</p> <p>And a following paragraph.</p> </sec>@@ -817,12 +813,10 @@ </list-item> </list> <p>An e-mail address: <email>nobody@nowhere.net</email></p>- <p specific-use="wrapper">- <disp-quote>- <p>Blockquoted:- <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link></p>- </disp-quote>- </p>+ <disp-quote>+ <p>Blockquoted:+ <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link></p>+ </disp-quote> <p>Auto-links should not occur here: <monospace><http://example.com/></monospace></p> <preformat>or here: <http://example.com/></preformat>@@ -860,13 +854,11 @@ and <monospace>]</monospace> verbatim characters, as well as [bracketed text].</p> </fn></p>- <p specific-use="wrapper">- <disp-quote>- <p>Notes can go in quotes.<fn>- <p>In quote.</p>- </fn></p>- </disp-quote>- </p>+ <disp-quote>+ <p>Notes can go in quotes.<fn>+ <p>In quote.</p>+ </fn></p>+ </disp-quote> <list list-type="order"> <list-item> <p>And in list items.<fn>
@@ -78,39 +78,31 @@ <sec id="block-quotes"> <title>Block Quotes</title> <p>E-mail style:</p>- <p specific-use="wrapper">+ <disp-quote>+ <p>This is a block quote. It is pretty short.</p>+ </disp-quote>+ <disp-quote>+ <p>Code in a block quote:</p>+ <preformat>sub status {+ print "working";+}</preformat>+ <p>A list:</p>+ <list list-type="order">+ <list-item>+ <p>item one</p>+ </list-item>+ <list-item>+ <p>item two</p>+ </list-item>+ </list>+ <p>Nested block quotes:</p> <disp-quote>- <p>This is a block quote. It is pretty short.</p>+ <p>nested</p> </disp-quote>- </p>- <p specific-use="wrapper"> <disp-quote>- <p>Code in a block quote:</p>- <preformat>sub status {- print "working";-}</preformat>- <p>A list:</p>- <list list-type="order">- <list-item>- <p>item one</p>- </list-item>- <list-item>- <p>item two</p>- </list-item>- </list>- <p>Nested block quotes:</p>- <p specific-use="wrapper">- <disp-quote>- <p>nested</p>- </disp-quote>- </p>- <p specific-use="wrapper">- <disp-quote>- <p>nested</p>- </disp-quote>- </p>+ <p>nested</p> </disp-quote>- </p>+ </disp-quote> <p>This should not be a block quote: 2 > 1.</p> <p>And a following paragraph.</p> </sec>@@ -837,12 +829,10 @@ </list-item> </list> <p>An e-mail address: <email>nobody@nowhere.net</email></p>- <p specific-use="wrapper">- <disp-quote>- <p>Blockquoted:- <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link></p>- </disp-quote>- </p>+ <disp-quote>+ <p>Blockquoted:+ <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link></p>+ </disp-quote> <p>Auto-links should not occur here: <monospace><http://example.com/></monospace></p> <preformat>or here: <http://example.com/></preformat>@@ -866,11 +856,9 @@ <italic>not</italic> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<xref ref-type="fn" rid="fn3">3</xref></p>- <p specific-use="wrapper">- <disp-quote>- <p>Notes can go in quotes.<xref ref-type="fn" rid="fn4">4</xref></p>- </disp-quote>- </p>+ <disp-quote>+ <p>Notes can go in quotes.<xref ref-type="fn" rid="fn4">4</xref></p>+ </disp-quote> <list list-type="order"> <list-item> <p>And in list items.<xref ref-type="fn" rid="fn5">5</xref></p>@@ -882,11 +870,12 @@ <back> <fn-group> <fn 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.</p>+ <label>1</label><p>Here is the footnote. It can go anywhere after the+ footnote reference. It need not be placed at the end of the document.</p> </fn> <fn id="fn2">- <p>Here’s the long note. This one contains multiple blocks.</p>+ <label>2</label><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> <p specific-use="wrapper">@@ -896,16 +885,17 @@ just indent the first line of each block.</p> </fn> <fn id="fn3">- <p>This is <italic>easier</italic> to type. Inline notes may contain+ <label>3</label><p>This is <italic>easier</italic> to type. Inline notes+ may contain <ext-link ext-link-type="uri" xlink:href="http://google.com">links</ext-link> and <monospace>]</monospace> verbatim characters, as well as [bracketed text].</p> </fn> <fn id="fn4">- <p>In quote.</p>+ <label>4</label><p>In quote.</p> </fn> <fn id="fn5">- <p>In list.</p>+ <label>5</label><p>In list.</p> </fn> </fn-group> </back>
@@ -4,6 +4,10 @@ % \documentclass[ ]{article}+\title{Pandoc Test Suite}+\author{John MacFarlane \and Anonymous}+\date{July 17, 2006}+ \usepackage{amsmath,amssymb} \usepackage{lmodern} \usepackage{iftex}@@ -66,10 +70,6 @@ \ifLuaTeX \usepackage{selnolig} % disable illegal ligatures \fi--\title{Pandoc Test Suite}-\author{John MacFarlane \and Anonymous}-\date{July 17, 2006} \begin{document} \maketitle
@@ -52,7 +52,7 @@ </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>-<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 &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> <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]().">
@@ -600,14 +600,14 @@ :END: - \cite[22-23]{smith.1899}-- $2+2=4$-- $x \in y$-- $\alpha \wedge \omega$-- $223$-- $p$-Tree+- \(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$.+ \[\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:
@@ -8,9 +8,9 @@ ====== Headers ====== -===== Level 2 with an embedded link =====+===== Level 2 with an [[url|embedded link]] ===== -==== Level 3 with emphasis ====+==== Level 3 with //emphasis// ==== === Level 4 === @@ -18,7 +18,7 @@ ====== Level 1 ====== -===== Level 2 with emphasis =====+===== Level 2 with //emphasis// ===== ==== Level 3 ====
@@ -15,6 +15,7 @@ % use microtypography \definefontfeature[default][default][script=latn, protrusion=quality, expansion=quality, itlc=yes, textitalics=yes, onum=yes, pnum=yes]+\definefontfeature[default:tnum][default][tnum=yes, pnum=no] \definefontfeature[smallcaps][script=latn, protrusion=quality, expansion=quality, smcp=yes, onum=yes, pnum=yes] \setupalign[hz,hanging] \setupitaliccorrection[global, always]@@ -45,6 +46,9 @@ \setupitemize[autointro] % prevent orphan list intro \setupitemize[indentnext=no]++\defineitemgroup[enumerate]+\setupenumerate[each][fit][itemalign=left,distance=.5em,style={\feature[+][default:tnum]}] \setupfloat[figure][default={here,nonumber}] \setupfloat[table][default={here,nonumber}]
@@ -5,6 +5,9 @@ \documentclass[ english, ]{article}+\author{}+\date{}+ \usepackage{amsmath,amssymb} \usepackage{lmodern} \usepackage{iftex}@@ -83,9 +86,6 @@ \newenvironment{RTL}{\beginR}{\endR} \newenvironment{LTR}{\beginL}{\endL} \fi--\author{}-\date{} \begin{document}