pandoc 1.16.0.2 → 1.17
raw patch · 58 files changed
+1371/−540 lines, 58 filesdep ~aesondep ~tagsoupdep ~zip-archivebinary-added
Dependency ranges changed: aeson, tagsoup, zip-archive
Files
- CONTRIBUTING.md +25/−4
- COPYRIGHT +1/−1
- INSTALL +5/−1
- README +31/−18
- changelog +151/−0
- data/sample.lua +1/−1
- data/templates/default.beamer +3/−0
- data/templates/default.latex +3/−0
- data/templates/default.tei +39/−0
- man/pandoc.1 +35/−20
- pandoc.cabal +11/−8
- pandoc.hs +27/−4
- src/Text/Pandoc.hs +12/−1
- src/Text/Pandoc/Highlighting.hs +2/−1
- src/Text/Pandoc/Options.hs +2/−1
- src/Text/Pandoc/Parsing.hs +6/−6
- src/Text/Pandoc/Readers/Docx.hs +37/−29
- src/Text/Pandoc/Readers/Docx/Combine.hs +154/−0
- src/Text/Pandoc/Readers/Docx/Parse.hs +64/−26
- src/Text/Pandoc/Readers/Docx/Reducible.hs +0/−181
- src/Text/Pandoc/Readers/HTML.hs +62/−34
- src/Text/Pandoc/Readers/LaTeX.hs +15/−5
- src/Text/Pandoc/Readers/Markdown.hs +28/−26
- src/Text/Pandoc/Readers/MediaWiki.hs +3/−2
- src/Text/Pandoc/Readers/Odt/ContentReader.hs +2/−1
- src/Text/Pandoc/Readers/Org.hs +35/−34
- src/Text/Pandoc/Readers/Textile.hs +19/−2
- src/Text/Pandoc/Shared.hs +7/−5
- src/Text/Pandoc/Writers/ConTeXt.hs +11/−1
- src/Text/Pandoc/Writers/Custom.hs +2/−2
- src/Text/Pandoc/Writers/Docx.hs +6/−5
- src/Text/Pandoc/Writers/DokuWiki.hs +4/−1
- src/Text/Pandoc/Writers/EPUB.hs +3/−2
- src/Text/Pandoc/Writers/HTML.hs +37/−36
- src/Text/Pandoc/Writers/LaTeX.hs +57/−33
- src/Text/Pandoc/Writers/Markdown.hs +5/−4
- src/Text/Pandoc/Writers/Org.hs +7/−2
- src/Text/Pandoc/Writers/TEI.hs +320/−0
- src/Text/Pandoc/Writers/Texinfo.hs +4/−3
- stack.yaml +6/−7
- tests/Tests/Old.hs +1/−1
- tests/Tests/Readers/Docx.hs +9/−1
- tests/Tests/Readers/HTML.hs +4/−1
- tests/Tests/Readers/Org.hs +8/−4
- tests/Tests/Writers/TEI.hs +43/−0
- tests/docx/adjacent_links.docx binary
- tests/docx/adjacent_links.native +1/−0
- tests/docx/enumerated_headings.docx binary
- tests/docx/enumerated_headings.native +4/−0
- tests/pipe-tables.native +15/−1
- tests/pipe-tables.txt +8/−0
- tests/tables.html +14/−14
- tests/tables.latex +7/−7
- tests/test-pandoc.hs +2/−0
- tests/textile-reader.native +5/−2
- tests/textile-reader.textile +6/−0
- tests/writer.dokuwiki +1/−1
- tests/writer.markdown +1/−1
CONTRIBUTING.md view
@@ -145,22 +145,41 @@ Tests can be run as follows: + cabal install --only-dependencies --enable-tests cabal configure --enable-tests cabal build cabal test +or, if you're using [stack],++ stack init+ stack test+ The test program is `tests/test-pandoc.hs`. -Benchmarks can be enabled by passing the `--enable-benchmarks` flag-to `cabal configure`, and run using `cabal bench`.+Benchmarks+---------- +To run benchmarks with cabal:++ cabal configure --enable-benchmarks+ cabal build+ cabal bench++With stack:++ stack bench+ Using the REPL -------------- With a recent version of cabal, you can do `cabal repl` and get-a ghci REPL for working with pandoc. We recommend using the following-`.ghci` file (which can be placed in the source directory):+a ghci REPL for working with pandoc. With [stack], use+`cabal ghci`. +We recommend using the following `.ghci` file (which can be+placed in the source directory):+ ``` :set -fobject-code :set -XTypeSynonymInstances@@ -266,3 +285,5 @@ [inprogress]: https://github.com/jgm/pandoc/labels/inprogress [more discussion needed]: https://github.com/jgm/pandoc/labels/More%20discussion%20needed [more info needed]: https://github.com/jgm/pandoc/labels/More%20info%20needed+[stack]: https://github.com/commercialhaskell/stack+
COPYRIGHT view
@@ -1,5 +1,5 @@ Pandoc-Copyright (C) 2006-2015 John MacFarlane <jgm at berkeley dot edu>+Copyright (C) 2006-2016 John MacFarlane <jgm at berkeley dot edu> This code is released under the [GPL], version 2 or later:
INSTALL view
@@ -11,7 +11,7 @@ Quick install with stack ------------------------ -1. Install [stack](https://github.com/commercialhaskell/stack/wiki/Downloads).+1. Install [stack](http://docs.haskellstack.org/en/stable/install_and_upgrade.html). 2. If you used git to get the pandoc source (as opposed to unpacking a release tarball), do@@ -179,6 +179,10 @@ You can find the pandoc executable in `dist/build/pandoc`. Copy this wherever you please.++Or alternatively with `stack`:++ stack install pandoc --flag pandoc:embed_data_files [zip-archive]: http://hackage.haskell.org/package/zip-archive [highlighting-kate]: http://hackage.haskell.org/package/highlighting-kate
README view
@@ -22,7 +22,7 @@ [OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [DokuWiki markup], [Haddock markup], [EPUB] (v2 or v3), [FictionBook2], [Textile], [groff man] pages, [Emacs Org mode],-[AsciiDoc], [InDesign ICML], and [Slidy], [Slideous], [DZSlides],+[AsciiDoc], [InDesign ICML], [TEI XML], and [Slidy], [Slideous], [DZSlides], [reveal.js] or [S5] HTML slide shows. It can also produce [PDF] output on systems where LaTeX, ConTeXt, or `wkhtmltopdf` is installed. @@ -89,6 +89,7 @@ [reveal.js]: http://lab.hakim.se/reveal-js/ [FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1 [InDesign ICML]: https://www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf+[TEI Simple]: https://github.com/TEIC/TEI-Simple Using `pandoc` --------------@@ -277,11 +278,11 @@ `docx` (Word docx), `haddock` (Haddock markup), `rtf` (rich text format), `epub` (EPUB v2 book), `epub3` (EPUB v3), `fb2` (FictionBook2 e-book), `asciidoc` (AsciiDoc), `icml` (InDesign- ICML), `slidy` (Slidy HTML and javascript slide show), `slideous`- (Slideous HTML and javascript slide show), `dzslides` (DZSlides- HTML5 + javascript slide show), `revealjs` (reveal.js HTML5 +- javascript slide show), `s5` (S5 HTML and javascript slide show),- or the path of a custom lua writer (see [Custom+ ICML), `tei` (TEI Simple), `slidy` (Slidy HTML and javascript slide+ show), `slideous` (Slideous HTML and javascript slide show),+ `dzslides` (DZSlides HTML5 + javascript slide show), `revealjs`+ (reveal.js HTML5 + javascript slide show), `s5` (S5 HTML and javascript+ slide show), or the path of a custom lua writer (see [Custom writers], below). Note that `odt`, `epub`, and `epub3` output will not be directed to *stdout*; an output filename must be specified using the `-o/--output` option. If@@ -387,6 +388,14 @@ require different kinds of images. Currently this option only affects the Markdown and LaTeX readers. +`--file-scope`++: Parse each file individually before combining for multifile+ documents. This will allow footnotes in different files with the+ same identifiers to work as expected. If this option is set,+ footnotes and links will not work across files. Reading binary+ files (docx, odt, epub) implies `--file-scope`.+ `--filter=`*EXECUTABLE* : Specify an executable to be used as a filter transforming the@@ -471,7 +480,7 @@ `-s`, `--standalone` : Produce output with an appropriate header and footer (e.g. a- standalone HTML, LaTeX, or RTF file, not a fragment). This option+ standalone HTML, LaTeX, TEI, or RTF file, not a fragment). This option is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt` output. @@ -536,9 +545,9 @@ `--toc`, `--table-of-contents` : Include an automatically generated table of contents (or, in- the case of `latex`, `context`, and `rst`, an instruction to create+ the case of `latex`, `context`, `docx`, and `rst`, an instruction to create one) in the output document. This option has no effect on `man`,- `docbook`, `slidy`, `slideous`, `s5`, `docx`, or `odt` output.+ `docbook`, `slidy`, `slideous`, `s5`, or `odt` output. `--toc-depth=`*NUMBER* @@ -579,7 +588,7 @@ : Include contents of *FILE*, verbatim, at the end of the document body (before the `</body>` tag in HTML, or the- `\end{document}` command in LaTeX). This option can be be used+ `\end{document}` command in LaTeX). This option can be used repeatedly to include multiple files. They will be included in the order specified. Implies `--standalone`. @@ -627,9 +636,10 @@ `--chapters` : Treat top-level headers as chapters in LaTeX, ConTeXt, and DocBook- output. When the LaTeX document class is set to `report`, `book`, or- `memoir`, this option is implied. If `beamer` is the output- format, top-level headers will become `\part{..}`.+ output. When the LaTeX document class is set to `report`, `book`,+ or `memoir` (unless the `article` option is specified), this+ option is implied. If `beamer` is the output format, top-level+ headers will become `\part{..}`. `-N`, `--number-sections` @@ -715,7 +725,7 @@ `-c` *URL*, `--css=`*URL* -: Link to a CSS style sheet. This option can be be used repeatedly to+: Link to a CSS style sheet. This option can be used repeatedly to include multiple files. They will be included in the order specified. `--reference-odt=`*FILE*@@ -1031,6 +1041,10 @@ `\subtitle`, such as `beamer` or the [KOMA-Script] series (`scrartcl`, `scrreprt`, `scrbook`).[^subtitle] +`institute`+: author affiliations (in LaTeX and Beamer only). Can be a+ list, when there are multiple authors.+ `abstract` : document summary, included in LaTeX, ConTeXt, AsciiDoc, and Word docx @@ -1090,7 +1104,7 @@ in the YAML metadata, according to [BCP 47]. For example: `otherlangs: [en-GB, fr]`. This is automatically generated from the `lang` attributes- in all `span`s and `div`s but can be overriden.+ in all `span`s and `div`s but can be overridden. Currently only used by LaTeX through the generated `babel-otherlangs` and `polyglossia-otherlangs` variables. The LaTeX writer outputs polyglossia commands in the text but@@ -3377,14 +3391,13 @@ `shortcut_reference_links`. `markdown_github` (GitHub-Flavored Markdown)-: `pipe_tables`, `raw_html`, `tex_math_single_backslash`,- `fenced_code_blocks`, `auto_identifiers`,+: `pipe_tables`, `raw_html`, `fenced_code_blocks`, `auto_identifiers`, `ascii_identifiers`, `backtick_code_blocks`, `autolink_bare_uris`, `intraword_underscores`, `strikeout`, `hard_line_breaks`, `emoji`, `shortcut_reference_links`. `markdown_mmd` (MultiMarkdown)-: `pipe_tables` `raw_html`, `markdown_attribute`, `mmd_link_attributes`,+: `pipe_tables`, `raw_html`, `markdown_attribute`, `mmd_link_attributes`, `raw_tex`, `tex_math_double_backslash`, `intraword_underscores`, `mmd_title_block`, `footnotes`, `definition_lists`, `all_symbols_escapable`, `implicit_header_references`,
changelog view
@@ -1,3 +1,154 @@+pandoc (1.17)++ * Added `--file-scope` option (Jesse Rosenthal).+ Traditionally pandoc operates on multiple files by first concatenating+ them (around extra line breaks) and then processing the joined file. So+ it only parses a multi-file document at the document scope. This has the+ benefit that footnotes and links can be in different files, but it also+ introduces some difficulties: (a) it is difficult to join files with+ footnotes without some sort of preprocessing, which makes it difficult+ to write academic documents in small pieces; (b) it makes it impossible+ to process multiple binary input files, which can't be catted; (c) it+ makes it impossible to process files from different input formats.+ The `--file-scope` option causes pandoc to parse the files first,+ and then combine the parsed output, instead of combining before+ parsing. This makes it impossible to have links across multiple files,+ and auto-identified headers won't work correctly if headers in multiple+ files have the same name. On the other hand, footnotes across multiple+ files will work correctly and will allow more freedom for input formats.+ `--file-scope` is selected automatically for binary input files (which+ cannot be concatenated anyway) and for pandoc json.++ * Add TEI Writer (csforste) and `tei` output format.++ * Added a general `ByteStringReader` with warnings, used by the docx+ reader (API change, Jesse Rosenthal).++ * Add `readDocxWithWarnings` (API change, Jesse Rosenthal).++ * Changed type of Shared.uniqueIdent argument from [String] to Set String.+ This avoids performance problems in documents with many identically+ named headers (API change, #2671).++ * Removed `tex_math_single_backslash` from `markdown_github` options+ (#2707).++ * Make language extensions as well as full language names+ trigger syntax highlighting. For example, `py` will now work as+ well as `python` (jgm/highlighting-kate#83).++ * Added `institute` variable to latex, beamer templates (Fraser+ Tweedale, Josef Svenningsson).++ * Docx reader (Jesse Rosenthal):++ + Handle alternate content. Some word functions (especially graphics)+ give various choices for content so there can be backwards compatibility.+ + Don't turn numbered headers into lists.+ + Docx Reader: Add state to the parser, for warnings+ + Update feature checklist in source code.+ + Get rid of `Modifiable` typeclass.+ + Add tests for adjacent hyperlinks.+ + Add a "Link" modifier to `Reducible`. We want to make sure that+ links have their spaces removed, and are appropriately smushed+ together (#2689).++ * HTML reader: Fixed behavior of base tag (#2777).++ + If the base path does not end with slash, the last component+ will be replaced. E.g. base = `http://example.com/foo`+ combines with `bar.html` to give `http://example.com/bar.html`.+ + If the href begins with a slash, the whole path of the base+ is replaced. E.g. base = `http://example.com/foo/` combines+ with `/bar.html` to give `http://example.com/bar.html`.+ + Rewrote `htmlInBalanced`. This version avoids an exponential+ performance problem with `<script>` tags, and it should be faster+ in general (#2730).+ + Properly handle an empty cell in a simple table (#2718).+ + Handle multiple `<meta>` tags with same name. Put them in a list+ in the metadata so they are all preserved, rather than (as before)+ throwing out all but one..++ * Markdown reader:++ + Improved pipe table parsing (#2765).+ + Allow `+` separators in pipe table cells. We already allowed+ them in the header, but not in the body rows, for some reason.+ This gives compatibility with org-mode tables.+ + Don't cross line boundary parsing pipe table row.+ Previously an Emph element could be parsed across the newline+ at the end of the pipe table row.+ + Use `htmlInBalanced` for `rawVerbatimBlock`, for better+ performance (#2730).+ + Fixed bug with smart quotes around tex math.++ * LaTeX reader:++ + Handle interior `$` characters in math (#2743). For example,+ `$$\hbox{$i$}$$`.+ + `inlineCommand` now gobbles an empty `{}` after any command (#2687).+ This gives better results when people write e.g. `\TeX{}` in Markdown.+ + Properly handle LaTeX "math" environment as inline math (#2171).++ * Textile reader: Support `>`, `<`, `=`, `<>` text alignment attributes.+ Closes #2674.++ * Org reader (Albert Krewinkel):++ + Prefix even empty figure names with "fig:" (#2643). The+ convention used by pandoc for figures is to mark them by prefixing+ the name with `fig:`. The org reader failed to do this if a figure+ had no name.+ + Refactor link-target processing (#2684).++ * ConTeXt writer: Fix whitespace at line beginning in line blocks (#2744).+ Thanks to @c-foster.++ * HTML writer: Don't include alignment attribute for default table columns.+ Previously these were given "left" alignment. Better to leave off+ alignment attributes altogether (#2694).++ * Markdown writer: Use hyphens for YAML metadata block bottom line, for+ better compatibility with other Markdown flavors (Henrik Tramberend).++ * LaTeX writer:++ + Use image identifier to create a label and hypertarget for+ figures (Mauro Bieg).+ + Avoid double toprule in headerless table with caption (#2742).+ + Clean up options parser (Jesse Rosenthal).+ + Treat `memoir` template with `article` option as article, instead+ of treating all `memoir` templates as books.+ + Allow more flexible table alignment (Henrik Tramberend, #2665).+ New default is not to include `[c]` option (which is the default+ anyway if no positioning is specified). Now LaTeX emplates can+ control the overall table alignment in a document by setting the+ longtable length variables `LTleft` and `LTright`. For example,++ \setlength\LTleft\parindent+ \setlength\LTright\fill++ will create left-aligned tables that respect paragraph indentation.++ * Docx writer: Handle image alt text (#2754, Mauro Bieg).++ * Org writer - pass through RawInline with format "org".++ * DokuWiki writer: use `$$` for display math.++ * Custom writer: Pass attributes parameter to CaptionedImage (#2697).++ * Make protocol-relative URIs work again (#2737).++ * make_osx_package.sh: Use env variable for developer id certs.++ * Raise `tagsoup` lower bound to 0.13.7 to fix entity-related+ problems (#2734).++ * Allow `zip-archive` 0.3.++ * Allow `aeson` 0.11.+ pandoc (1.16.0.2) * Depend on deepseq rather than deepseq-generics (fpco/stackage#1096).
data/sample.lua view
@@ -255,7 +255,7 @@ end end -function CaptionedImage(src, tit, caption)+function CaptionedImage(src, tit, caption, attr) return '<div class="figure">\n<img src="' .. escape(src,true) .. '" title="' .. escape(tit,true) .. '"/>\n' .. '<p class="caption">' .. caption .. '</p>\n</div>'
data/templates/default.beamer view
@@ -200,6 +200,9 @@ $if(author)$ \author{$for(author)$$author$$sep$ \and $endfor$} $endif$+$if(institute)$+\institute{$for(institute)$$institute$$sep$ \and $endfor$}+$endif$ \date{$date$} \begin{document}
data/templates/default.latex view
@@ -199,6 +199,9 @@ $if(author)$ \author{$for(author)$$author$$sep$ \and $endfor$} $endif$+$if(institute)$+\institute{$for(institute)$$institute$$sep$ \and $endfor$}+$endif$ \date{$date$} \begin{document}
+ data/templates/default.tei view
@@ -0,0 +1,39 @@+<?xml version="1.0" encoding="utf-8"?>+<TEI xmlns="http://www.tei-c.org/ns/1.0"$if(lang)$ xml:lang="$lang$"$endif$>+<teiHeader>+ <fileDesc>+ <titleStmt>+$if(title)$+ <title>$title$</title>+$endif$+$for(author)$+ $author$+$endfor$+ </titleStmt>+ <publicationStmt>+ <p>$if(publicationStmt)$$publicationStmt$$endif$</p>+ $if(license)$+ <availability><licence>$license$</licence></availability>+$endif$+ </publicationStmt>+ <sourceDesc>+$if(sourceDesc)$+ $sourceDesc$+$else$+ <p>Produced by pandoc.</p>+$endif$+ </sourceDesc>+ </fileDesc>+</teiHeader>+<text>+$for(include-before)$+$include-before$+$endfor$+<body>+$body$+</body>+$for(include-after)$+$include-after$+$endfor$+</text>+</TEI>
man/pandoc.1 view
@@ -1,5 +1,5 @@ .\"t-.TH PANDOC 1 "January 12, 2016" "pandoc 1.16.0.2"+.TH PANDOC 1 "January 12, 2016" "pandoc 1.17" .SH NAME pandoc - general markup converter .SH SYNOPSIS@@ -18,8 +18,8 @@ shows), ConTeXt, RTF, OPML, DocBook, OpenDocument, ODT, Word docx, GNU Texinfo, MediaWiki markup, DokuWiki markup, Haddock markup, EPUB (v2 or v3), FictionBook2, Textile, groff man pages, Emacs Org mode, AsciiDoc,-InDesign ICML, and Slidy, Slideous, DZSlides, reveal.js or S5 HTML slide-shows.+InDesign ICML, [TEI XML], and Slidy, Slideous, DZSlides, reveal.js or S5+HTML slide shows. It can also produce PDF output on systems where LaTeX, ConTeXt, or \f[C]wkhtmltopdf\f[] is installed. .PP@@ -253,11 +253,12 @@ (Haddock markup), \f[C]rtf\f[] (rich text format), \f[C]epub\f[] (EPUB v2 book), \f[C]epub3\f[] (EPUB v3), \f[C]fb2\f[] (FictionBook2 e\-book), \f[C]asciidoc\f[] (AsciiDoc), \f[C]icml\f[] (InDesign ICML),-\f[C]slidy\f[] (Slidy HTML and javascript slide show), \f[C]slideous\f[]-(Slideous HTML and javascript slide show), \f[C]dzslides\f[] (DZSlides-HTML5 + javascript slide show), \f[C]revealjs\f[] (reveal.js HTML5 +-javascript slide show), \f[C]s5\f[] (S5 HTML and javascript slide show),-or the path of a custom lua writer (see Custom writers, below).+\f[C]tei\f[] (TEI Simple), \f[C]slidy\f[] (Slidy HTML and javascript+slide show), \f[C]slideous\f[] (Slideous HTML and javascript slide+show), \f[C]dzslides\f[] (DZSlides HTML5 + javascript slide show),+\f[C]revealjs\f[] (reveal.js HTML5 + javascript slide show), \f[C]s5\f[]+(S5 HTML and javascript slide show), or the path of a custom lua writer+(see Custom writers, below). Note that \f[C]odt\f[], \f[C]epub\f[], and \f[C]epub3\f[] output will not be directed to \f[I]stdout\f[]; an output filename must be specified using the \f[C]\-o/\-\-output\f[] option.@@ -401,6 +402,15 @@ .RS .RE .TP+.B \f[C]\-\-file\-scope\f[]+Parse each file individually before combining for multifile documents.+This will allow footnotes in different files with the same identifiers+to work as expected.+If this option is set, footnotes and links will not work across files.+Reading binary files (docx, odt, epub) implies \f[C]\-\-file\-scope\f[].+.RS+.RE+.TP .B \f[C]\-\-filter=\f[]\f[I]EXECUTABLE\f[] Specify an executable to be used as a filter transforming the pandoc AST after the input is parsed and before the output is written.@@ -501,7 +511,7 @@ .TP .B \f[C]\-s\f[], \f[C]\-\-standalone\f[] Produce output with an appropriate header and footer (e.g.-a standalone HTML, LaTeX, or RTF file, not a fragment).+a standalone HTML, LaTeX, TEI, or RTF file, not a fragment). This option is set automatically for \f[C]pdf\f[], \f[C]epub\f[], \f[C]epub3\f[], \f[C]fb2\f[], \f[C]docx\f[], and \f[C]odt\f[] output. .RS@@ -582,11 +592,10 @@ .TP .B \f[C]\-\-toc\f[], \f[C]\-\-table\-of\-contents\f[] Include an automatically generated table of contents (or, in the case of-\f[C]latex\f[], \f[C]context\f[], and \f[C]rst\f[], an instruction to-create one) in the output document.+\f[C]latex\f[], \f[C]context\f[], \f[C]docx\f[], and \f[C]rst\f[], an+instruction to create one) in the output document. This option has no effect on \f[C]man\f[], \f[C]docbook\f[],-\f[C]slidy\f[], \f[C]slideous\f[], \f[C]s5\f[], \f[C]docx\f[], or-\f[C]odt\f[] output.+\f[C]slidy\f[], \f[C]slideous\f[], \f[C]s5\f[], or \f[C]odt\f[] output. .RS .RE .TP@@ -642,7 +651,7 @@ Include contents of \f[I]FILE\f[], verbatim, at the end of the document body (before the \f[C]</body>\f[] tag in HTML, or the \f[C]\\end{document}\f[] command in LaTeX).-This option can be be used repeatedly to include multiple files.+This option can be used repeatedly to include multiple files. They will be included in the order specified. Implies \f[C]\-\-standalone\f[]. .RS@@ -702,7 +711,8 @@ Treat top\-level headers as chapters in LaTeX, ConTeXt, and DocBook output. When the LaTeX document class is set to \f[C]report\f[], \f[C]book\f[],-or \f[C]memoir\f[], this option is implied.+or \f[C]memoir\f[] (unless the \f[C]article\f[] option is specified),+this option is implied. If \f[C]beamer\f[] is the output format, top\-level headers will become \f[C]\\part{..}\f[]. .RS@@ -809,7 +819,7 @@ .TP .B \f[C]\-c\f[] \f[I]URL\f[], \f[C]\-\-css=\f[]\f[I]URL\f[] Link to a CSS style sheet.-This option can be be used repeatedly to include multiple files.+This option can be used repeatedly to include multiple files. They will be included in the order specified. .RS .RE@@ -1191,6 +1201,12 @@ .RS .RE .TP+.B \f[C]institute\f[]+author affiliations (in LaTeX and Beamer only).+Can be a list, when there are multiple authors.+.RS+.RE+.TP .B \f[C]abstract\f[] document summary, included in LaTeX, ConTeXt, AsciiDoc, and Word docx .RS@@ -1260,7 +1276,7 @@ according to BCP 47. For example: \f[C]otherlangs:\ [en\-GB,\ fr]\f[]. This is automatically generated from the \f[C]lang\f[] attributes in all-\f[C]span\f[]s and \f[C]div\f[]s but can be overriden.+\f[C]span\f[]s and \f[C]div\f[]s but can be overridden. Currently only used by LaTeX through the generated \f[C]babel\-otherlangs\f[] and \f[C]polyglossia\-otherlangs\f[] variables.@@ -4214,8 +4230,7 @@ .RE .TP .B \f[C]markdown_github\f[] (GitHub\-Flavored Markdown)-\f[C]pipe_tables\f[], \f[C]raw_html\f[],-\f[C]tex_math_single_backslash\f[], \f[C]fenced_code_blocks\f[],+\f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]fenced_code_blocks\f[], \f[C]auto_identifiers\f[], \f[C]ascii_identifiers\f[], \f[C]backtick_code_blocks\f[], \f[C]autolink_bare_uris\f[], \f[C]intraword_underscores\f[], \f[C]strikeout\f[],@@ -4225,7 +4240,7 @@ .RE .TP .B \f[C]markdown_mmd\f[] (MultiMarkdown)-\f[C]pipe_tables\f[] \f[C]raw_html\f[], \f[C]markdown_attribute\f[],+\f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]markdown_attribute\f[], \f[C]mmd_link_attributes\f[], \f[C]raw_tex\f[], \f[C]tex_math_double_backslash\f[], \f[C]intraword_underscores\f[], \f[C]mmd_title_block\f[], \f[C]footnotes\f[], \f[C]definition_lists\f[],
pandoc.cabal view
@@ -1,5 +1,5 @@ Name: pandoc-Version: 1.16.0.2+Version: 1.17 Cabal-Version: >= 1.10 Build-Type: Custom License: GPL@@ -20,7 +20,7 @@ MediaWiki markup, TWiki markup, Haddock markup, OPML, Emacs Org-Mode, txt2tags, Word Docx, ODT, and Textile, and it can write Markdown, reStructuredText, XHTML, HTML 5,- LaTeX, ConTeXt, DocBook, OPML, OpenDocument, ODT,+ LaTeX, ConTeXt, DocBook, OPML, TEI, OpenDocument, ODT, Word docx, RTF, MediaWiki, DokuWiki, Textile, groff man pages, plain text, Emacs Org-Mode, AsciiDoc, Haddock markup, EPUB (v2 and v3), FictionBook2, InDesign ICML, and several@@ -39,6 +39,7 @@ data/templates/default.html data/templates/default.html5 data/templates/default.docbook+ data/templates/default.tei data/templates/default.beamer data/templates/default.opendocument data/templates/default.icml@@ -252,15 +253,15 @@ directory >= 1 && < 1.3, bytestring >= 0.9 && < 0.11, text >= 0.11 && < 1.3,- zip-archive >= 0.2.3.4 && < 0.3,+ zip-archive >= 0.2.3.4 && < 0.4, HTTP >= 4000.0.5 && < 4000.4, texmath >= 0.8.4.1 && < 0.9, xml >= 1.3.12 && < 1.4, random >= 1 && < 1.2, extensible-exceptions >= 0.1 && < 0.2, pandoc-types >= 1.16 && < 1.17,- aeson >= 0.7 && < 0.11,- tagsoup >= 0.13.1 && < 0.14,+ aeson >= 0.7 && < 0.12,+ tagsoup >= 0.13.7 && < 0.14, base64-bytestring >= 0.1 && < 1.1, zlib >= 0.5 && < 0.7, highlighting-kate >= 0.6.1 && < 0.7,@@ -362,6 +363,7 @@ Text.Pandoc.Writers.Docx, Text.Pandoc.Writers.EPUB, Text.Pandoc.Writers.FB2,+ Text.Pandoc.Writers.TEI, Text.Pandoc.PDF, Text.Pandoc.UTF8, Text.Pandoc.Templates,@@ -370,7 +372,7 @@ Text.Pandoc.Process, Text.Pandoc.CSS Other-Modules: Text.Pandoc.Readers.Docx.Lists,- Text.Pandoc.Readers.Docx.Reducible,+ Text.Pandoc.Readers.Docx.Combine, Text.Pandoc.Readers.Docx.Parse, Text.Pandoc.Readers.Docx.Fonts, Text.Pandoc.Readers.Docx.Util,@@ -414,7 +416,7 @@ bytestring >= 0.9 && < 0.11, extensible-exceptions >= 0.1 && < 0.2, highlighting-kate >= 0.6.1 && < 0.7,- aeson >= 0.7.0.5 && < 0.11,+ aeson >= 0.7.0.5 && < 0.12, yaml >= 0.8.8.2 && < 0.9, containers >= 0.1 && < 0.6, HTTP >= 4000.0.5 && < 4000.4@@ -479,7 +481,7 @@ containers >= 0.1 && < 0.6, ansi-terminal >= 0.5 && < 0.7, executable-path >= 0.0 && < 0.1,- zip-archive >= 0.2.3.4 && < 0.3+ zip-archive >= 0.2.3.4 && < 0.4 Other-Modules: Tests.Old Tests.Helpers Tests.Arbitrary@@ -504,6 +506,7 @@ Tests.Writers.LaTeX Tests.Writers.Docx Tests.Writers.RST+ Tests.Writers.TEI Ghc-Options: -rtsopts -Wall -fno-warn-unused-do-bind -threaded Default-Language: Haskell98
pandoc.hs view
@@ -215,6 +215,7 @@ , optExtractMedia :: Maybe FilePath -- ^ Path to extract embedded media , optTrace :: Bool -- ^ Print debug information , optTrackChanges :: TrackChanges -- ^ Accept or reject MS Word track-changes.+ , optFileScope :: Bool -- ^ Parse input files before combining , optKaTeXStylesheet :: Maybe String -- ^ Path to stylesheet for KaTeX , optKaTeXJS :: Maybe String -- ^ Path to js file for KaTeX }@@ -278,6 +279,7 @@ , optExtractMedia = Nothing , optTrace = False , optTrackChanges = AcceptChanges+ , optFileScope = False , optKaTeXStylesheet = Nothing , optKaTeXJS = Nothing }@@ -387,6 +389,11 @@ "accept|reject|all") "" -- "Accepting or reject MS Word track-changes."" + , Option "" ["file-scope"]+ (NoArg+ (\opt -> return opt { optFileScope = True }))+ "" -- "Parse input files before combining"+ , Option "" ["extract-media"] (ReqArg (\arg opt ->@@ -1009,6 +1016,8 @@ ".fb2" -> "fb2" ".opml" -> "opml" ".icml" -> "icml"+ ".tei.xml" -> "tei"+ ".tei" -> "tei" ['.',y] | y `elem` ['1'..'9'] -> "man" _ -> "html" @@ -1115,6 +1124,7 @@ , optExtractMedia = mbExtractMedia , optTrace = trace , optTrackChanges = trackChanges+ , optFileScope = fileScope , optKaTeXStylesheet = katexStylesheet , optKaTeXJS = katexJS } = opts@@ -1267,6 +1277,7 @@ , readerDefaultImageExtension = defaultImageExtension , readerTrace = trace , readerTrackChanges = trackChanges+ , readerFileScope = fileScope } when (not (isTextFormat format) && outputFile == "-") $@@ -1299,13 +1310,25 @@ then handleIncludes else return . Right - (doc, media) <- fmap handleError $- case reader of+ let sourceToDoc :: [FilePath] -> IO (Pandoc, MediaBag)+ sourceToDoc sources' = fmap handleError $+ case reader of StringReader r-> do- srcs <- convertTabs . intercalate "\n" <$> readSources sources+ srcs <- convertTabs . intercalate "\n" <$> readSources sources' doc <- handleIncludes' srcs either (return . Left) (\s -> fmap (,mempty) <$> r readerOpts s) doc- ByteStringReader r -> readFiles sources >>= r readerOpts+ ByteStringReader r -> readFiles sources' >>= r readerOpts++ -- We parse first if (1) fileScope is set, (2), it's a binary+ -- reader, or (3) we're reading JSON. This is easier to do of an AND+ -- of negatives as opposed to an OR of positives, so we do default+ -- parsing if it's a StringReader AND (fileScope is set AND it's not+ -- a JSON reader).+ (doc, media) <- case reader of+ (StringReader _) | not fileScope && readerName' /= "json" ->+ sourceToDoc sources+ _ -> do pairs <- mapM (\s -> sourceToDoc [s]) sources+ return (mconcat $ map fst pairs, mconcat $ map snd pairs) let writerOptions = def { writerStandalone = standalone', writerTemplate = templ,
src/Text/Pandoc.hs view
@@ -115,6 +115,7 @@ , writeHaddock , writeCommonMark , writeCustom+ , writeTEI -- * Rendering templates and default templates , module Text.Pandoc.Templates -- * Miscellaneous@@ -169,6 +170,7 @@ import Text.Pandoc.Writers.Haddock import Text.Pandoc.Writers.CommonMark import Text.Pandoc.Writers.Custom+import Text.Pandoc.Writers.TEI import Text.Pandoc.Templates import Text.Pandoc.Options import Text.Pandoc.Shared (safeRead, warn, mapLeft, pandocVersion)@@ -221,6 +223,14 @@ mkBSReader :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag)) -> Reader mkBSReader r = ByteStringReader (\o s -> return $ r o s) +mkBSReaderWithWarnings :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag, [String])) -> Reader+mkBSReaderWithWarnings r = ByteStringReader $ \o s ->+ case r o s of+ Left err -> return $ Left err+ Right (doc, mediaBag, warnings) -> do+ mapM_ warn warnings+ return $ Right (doc, mediaBag)+ -- | Association list of formats and readers. readers :: [(String, Reader)] readers = [ ("native" , StringReader $ \_ s -> return $ readNative s)@@ -241,7 +251,7 @@ ,("latex" , mkStringReader readLaTeX) ,("haddock" , mkStringReader readHaddock) ,("twiki" , mkStringReader readTWiki)- ,("docx" , mkBSReader readDocx)+ ,("docx" , mkBSReaderWithWarnings readDocxWithWarnings) ,("odt" , mkBSReader readOdt) ,("t2t" , mkStringReader readTxt2TagsNoMacros) ,("epub" , mkBSReader readEPUB)@@ -304,6 +314,7 @@ ,("asciidoc" , PureStringWriter writeAsciiDoc) ,("haddock" , PureStringWriter writeHaddock) ,("commonmark" , PureStringWriter writeCommonMark)+ ,("tei" , PureStringWriter writeTEI) ] getDefaultExtensions :: String -> Set Extension
src/Text/Pandoc/Highlighting.hs view
@@ -70,7 +70,8 @@ startNumber = firstNum, numberLines = any (`elem` ["number","numberLines", "number-lines"]) classes }- lcclasses = map (map toLower) classes+ lcclasses = map (map toLower)+ (classes ++ concatMap languagesByExtension classes) in case find (`elem` lcLanguages) lcclasses of Nothing | numberLines fmtOpts -> Just
src/Text/Pandoc/Options.hs view
@@ -202,7 +202,6 @@ githubMarkdownExtensions = Set.fromList [ Ext_pipe_tables , Ext_raw_html- , Ext_tex_math_single_backslash , Ext_fenced_code_blocks , Ext_auto_identifiers , Ext_ascii_identifiers@@ -265,6 +264,7 @@ , readerDefaultImageExtension :: String -- ^ Default extension for images , readerTrace :: Bool -- ^ Print debugging info , readerTrackChanges :: TrackChanges+ , readerFileScope :: Bool -- ^ Parse before combining } deriving (Show, Read, Data, Typeable, Generic) instance Default ReaderOptions@@ -281,6 +281,7 @@ , readerDefaultImageExtension = "" , readerTrace = False , readerTrackChanges = AcceptChanges+ , readerFileScope = False } --
src/Text/Pandoc/Parsing.hs view
@@ -915,7 +915,7 @@ stateMeta' :: F Meta, -- ^ Document metadata stateHeaderTable :: [HeaderType], -- ^ Ordered list of header types used stateHeaders :: M.Map Inlines String, -- ^ List of headers and ids (used for implicit ref links)- stateIdentifiers :: [String], -- ^ List of header identifiers used+ stateIdentifiers :: Set.Set String, -- ^ Header identifiers used stateNextExample :: Int, -- ^ Number of next example stateExamples :: M.Map String Int, -- ^ Map from example labels to numbers stateHasChapters :: Bool, -- ^ True if \chapter encountered@@ -973,8 +973,8 @@ updateHeaderMap f st = st{ stateHeaders = f $ stateHeaders st } class HasIdentifierList st where- extractIdentifierList :: st -> [String]- updateIdentifierList :: ([String] -> [String]) -> st -> st+ extractIdentifierList :: st -> Set.Set String+ updateIdentifierList :: (Set.Set String -> Set.Set String) -> st -> st instance HasIdentifierList ParserState where extractIdentifierList = stateIdentifiers@@ -1013,7 +1013,7 @@ stateMeta' = return nullMeta, stateHeaderTable = [], stateHeaders = M.empty,- stateIdentifiers = [],+ stateIdentifiers = Set.empty, stateNextExample = 1, stateExamples = M.empty, stateHasChapters = False,@@ -1092,8 +1092,8 @@ let id'' = if Ext_ascii_identifiers `Set.member` exts then catMaybes $ map toAsciiChar id' else id'- updateState $ updateIdentifierList $- if id' == id'' then (id' :) else ([id', id''] ++)+ updateState $ updateIdentifierList $ Set.insert id'+ updateState $ updateIdentifierList $ Set.insert id'' updateState $ updateHeaderMap $ insert' header' id' return (id'',classes,kvs) else do
src/Text/Pandoc/Readers/Docx.hs view
@@ -50,8 +50,7 @@ * Inlines - [X] Str- - [X] Emph (From italics. `underline` currently read as span. In- future, it might optionally be emph as well)+ - [X] Emph (italics and underline both read as Emph) - [X] Strong - [X] Strikeout - [X] Superscript@@ -62,16 +61,16 @@ - [X] Code (styled with `VerbatimChar`) - [X] Space - [X] LineBreak (these are invisible in Word: entered with Shift-Return)- - [ ] Math+ - [X] Math - [X] Link (links to an arbitrary bookmark create a span with the target as id and "anchor" class)- - [-] Image (Links to path in archive. Future option for- data-encoded URI likely.)+ - [X] Image - [X] Note (Footnotes and Endnotes are silently combined.) -} module Text.Pandoc.Readers.Docx- ( readDocx+ ( readDocxWithWarnings+ , readDocx ) where import Codec.Archive.Zip@@ -81,7 +80,7 @@ import Text.Pandoc.Walk import Text.Pandoc.Readers.Docx.Parse import Text.Pandoc.Readers.Docx.Lists-import Text.Pandoc.Readers.Docx.Reducible+import Text.Pandoc.Readers.Docx.Combine import Text.Pandoc.Shared import Text.Pandoc.MediaBag (insertMedia, MediaBag) import Data.List (delete, (\\), intersect)@@ -89,6 +88,7 @@ import Data.Default (Default) import qualified Data.ByteString.Lazy as B import qualified Data.Map as M+import qualified Data.Set as Set import Control.Monad.Reader import Control.Monad.State import Data.Sequence (ViewL(..), viewl)@@ -97,14 +97,22 @@ import Text.Pandoc.Error import Text.Pandoc.Compat.Except +readDocxWithWarnings :: ReaderOptions+ -> B.ByteString+ -> Either PandocError (Pandoc, MediaBag, [String])+readDocxWithWarnings opts bytes =+ case archiveToDocxWithWarnings (toArchive bytes) of+ Right (docx, warnings) -> do+ (meta, blks, mediaBag) <- docxToOutput opts docx+ return (Pandoc meta blks, mediaBag, warnings)+ Left _ -> Left (ParseFailure "couldn't parse docx file")+ readDocx :: ReaderOptions -> B.ByteString -> Either PandocError (Pandoc, MediaBag)-readDocx opts bytes =- case archiveToDocx (toArchive bytes) of- Right docx -> (\(meta, blks, mediaBag) -> (Pandoc meta blks, mediaBag))- <$> (docxToOutput opts docx)- Left _ -> Left (ParseFailure "couldn't parse docx file")+readDocx opts bytes = do+ (pandoc, mediaBag, _) <- readDocxWithWarnings opts bytes+ return (pandoc, mediaBag) data DState = DState { docxAnchorMap :: M.Map String String , docxMediaBag :: MediaBag@@ -166,7 +174,7 @@ | (Paragraph pPr parParts) <- bp , (c : _)<- intersect (pStyle pPr) (M.keys metaStyles) , (Just metaField) <- M.lookup c metaStyles = do- inlines <- concatReduce <$> mapM parPartToInlines parParts+ inlines <- smushInlines <$> mapM parPartToInlines parParts remaining <- bodyPartsToMeta' bps let f (MetaInlines ils) (MetaInlines ils') = MetaBlocks [Para ils, Para ils']@@ -290,13 +298,13 @@ Just SubScrpt -> subscript codeString _ -> codeString | otherwise = do- let ils = concatReduce (map runElemToInlines runElems)+ let ils = smushInlines (map runElemToInlines runElems) return $ (runStyleToTransform $ resolveDependentRunStyle rs) ils runToInlines (Footnote bps) = do- blksList <- concatReduce <$> (mapM bodyPartToBlocks bps)+ blksList <- smushBlocks <$> (mapM bodyPartToBlocks bps) return $ note blksList runToInlines (Endnote bps) = do- blksList <- concatReduce <$> (mapM bodyPartToBlocks bps)+ blksList <- smushBlocks <$> (mapM bodyPartToBlocks bps) return $ note blksList runToInlines (InlineDrawing fp bs ext) = do mediaBag <- gets docxMediaBag@@ -315,19 +323,19 @@ parPartToInlines (Insertion _ author date runs) = do opts <- asks docxOptions case readerTrackChanges opts of- AcceptChanges -> concatReduce <$> mapM runToInlines runs+ AcceptChanges -> smushInlines <$> mapM runToInlines runs RejectChanges -> return mempty AllChanges -> do- ils <- concatReduce <$> mapM runToInlines runs+ ils <- smushInlines <$> mapM runToInlines runs let attr = ("", ["insertion"], [("author", author), ("date", date)]) return $ spanWith attr ils parPartToInlines (Deletion _ author date runs) = do opts <- asks docxOptions case readerTrackChanges opts of AcceptChanges -> return mempty- RejectChanges -> concatReduce <$> mapM runToInlines runs+ RejectChanges -> smushInlines <$> mapM runToInlines runs AllChanges -> do- ils <- concatReduce <$> mapM runToInlines runs+ ils <- smushInlines <$> mapM runToInlines runs let attr = ("", ["deletion"], [("author", author), ("date", date)]) return $ spanWith attr ils parPartToInlines (BookMark _ anchor) | anchor `elem` dummyAnchors =@@ -350,7 +358,7 @@ -- avoid an extra pass. let newAnchor = if not inHdrBool && anchor `elem` (M.elems anchorMap)- then uniqueIdent [Str anchor] (M.elems anchorMap)+ then uniqueIdent [Str anchor] (Set.fromList $ M.elems anchorMap) else anchor unless inHdrBool (modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})@@ -360,10 +368,10 @@ modify $ \s -> s { docxMediaBag = insertMedia fp Nothing bs mediaBag } return $ imageWith (extentToAttr ext) fp "" "" parPartToInlines (InternalHyperLink anchor runs) = do- ils <- concatReduce <$> mapM runToInlines runs+ ils <- smushInlines <$> mapM runToInlines runs return $ link ('#' : anchor) "" ils parPartToInlines (ExternalHyperLink target runs) = do- ils <- concatReduce <$> mapM runToInlines runs+ ils <- smushInlines <$> mapM runToInlines runs return $ link target "" ils parPartToInlines (PlainOMath exps) = do return $ math $ writeTeX exps@@ -393,7 +401,7 @@ | (c:cs) <- filter isAnchorSpan ils , (Span (ident, ["anchor"], _) _) <- c = do hdrIDMap <- gets docxAnchorMap- let newIdent = uniqueIdent ils (M.elems hdrIDMap)+ let newIdent = uniqueIdent ils (Set.fromList $ M.elems hdrIDMap) modify $ \s -> s {docxAnchorMap = M.insert ident newIdent hdrIDMap} return $ Header n (newIdent, classes, kvs) (ils \\ (c:cs)) -- Otherwise we just give it a name, and register that name (associate@@ -401,7 +409,7 @@ makeHeaderAnchor' (Header n (_, classes, kvs) ils) = do hdrIDMap <- gets docxAnchorMap- let newIdent = uniqueIdent ils (M.elems hdrIDMap)+ let newIdent = uniqueIdent ils (Set.fromList $ M.elems hdrIDMap) modify $ \s -> s {docxAnchorMap = M.insert newIdent newIdent hdrIDMap} return $ Header n (newIdent, classes, kvs) ils makeHeaderAnchor' blk = return blk@@ -416,7 +424,7 @@ cellToBlocks :: Cell -> DocxContext Blocks cellToBlocks (Cell bps) = do- blks <- concatReduce <$> mapM bodyPartToBlocks bps+ blks <- smushBlocks <$> mapM bodyPartToBlocks bps return $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks rowToBlocksList :: Row -> DocxContext [Blocks]@@ -478,11 +486,11 @@ $ concatMap parPartToString parparts | Just (style, n) <- pHeading pPr = do ils <- local (\s-> s{docxInHeaderBlock=True}) $- (concatReduce <$> mapM parPartToInlines parparts)+ (smushInlines <$> mapM parPartToInlines parparts) makeHeaderAnchor $ headerWith ("", delete style (pStyle pPr), []) n ils | otherwise = do- ils <- concatReduce <$> mapM parPartToInlines parparts >>=+ ils <- smushInlines <$> mapM parPartToInlines parparts >>= (return . fromList . trimLineBreaks . normalizeSpaces . toList) dropIls <- gets docxDropCap let ils' = dropIls <> ils@@ -560,7 +568,7 @@ bodyToOutput (Body bps) = do let (metabps, blkbps) = sepBodyParts bps meta <- bodyPartsToMeta metabps- blks <- concatReduce <$> mapM bodyPartToBlocks blkbps+ blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks mediaBag <- gets docxMediaBag return $ (meta,
+ src/Text/Pandoc/Readers/Docx/Combine.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances,+ PatternGuards #-}++module Text.Pandoc.Readers.Docx.Combine ( smushInlines+ , smushBlocks+ )+ where++import Text.Pandoc.Builder+import Data.List+import Data.Sequence (ViewR(..), ViewL(..), viewl, viewr, (><), (|>))+import qualified Data.Sequence as Seq (null)++data Modifier a = Modifier (a -> a)+ | AttrModifier (Attr -> a -> a) Attr+ | NullModifier++spaceOutInlinesL :: Inlines -> (Inlines, Inlines)+spaceOutInlinesL ms = (l, stackInlines fs (m' <> r))+ where (l, m, r) = spaceOutInlines ms+ (fs, m') = unstackInlines m++spaceOutInlinesR :: Inlines -> (Inlines, Inlines)+spaceOutInlinesR ms = (stackInlines fs (l <> m'), r)+ where (l, m, r) = spaceOutInlines ms+ (fs, m') = unstackInlines m++spaceOutInlines :: Inlines -> (Inlines, Inlines, Inlines)+spaceOutInlines ils =+ let (fs, ils') = unstackInlines ils+ contents = unMany ils'+ left = case viewl contents of+ (Space :< _) -> space+ _ -> mempty+ right = case viewr contents of+ (_ :> Space) -> space+ _ -> mempty in+ (left, (stackInlines fs $ trimInlines . Many $ contents), right)++stackInlines :: [Modifier Inlines] -> Inlines -> Inlines+stackInlines [] ms = ms+stackInlines (NullModifier : fs) ms = stackInlines fs ms+stackInlines ((Modifier f) : fs) ms =+ if isEmpty ms+ then stackInlines fs ms+ else f $ stackInlines fs ms+stackInlines ((AttrModifier f attr) : fs) ms = f attr $ stackInlines fs ms++unstackInlines :: Inlines -> ([Modifier Inlines], Inlines)+unstackInlines ms = case ilModifier ms of+ NullModifier -> ([], ms)+ _ -> (f : fs, ms') where+ f = ilModifier ms+ (fs, ms') = unstackInlines $ ilInnards ms++ilModifier :: Inlines -> Modifier Inlines+ilModifier ils = case viewl (unMany ils) of+ (x :< xs) | Seq.null xs -> case x of+ (Emph _) -> Modifier emph+ (Strong _) -> Modifier strong+ (SmallCaps _) -> Modifier smallcaps+ (Strikeout _) -> Modifier strikeout+ (Superscript _) -> Modifier superscript+ (Subscript _) -> Modifier subscript+ (Link attr _ tgt) -> Modifier $ linkWith attr (fst tgt) (snd tgt)+ (Span attr _) -> AttrModifier spanWith attr+ _ -> NullModifier+ _ -> NullModifier++ilInnards :: Inlines -> Inlines+ilInnards ils = case viewl (unMany ils) of+ (x :< xs) | Seq.null xs -> case x of+ (Emph lst) -> fromList lst+ (Strong lst) -> fromList lst+ (SmallCaps lst) -> fromList lst+ (Strikeout lst) -> fromList lst+ (Superscript lst) -> fromList lst+ (Subscript lst) -> fromList lst+ (Link _ lst _) -> fromList lst+ (Span _ lst) -> fromList lst+ _ -> ils+ _ -> ils++inlinesL :: Inlines -> (Inlines, Inlines)+inlinesL ils = case viewl $ unMany ils of+ (s :< sq) -> (singleton s, Many sq)+ _ -> (mempty, ils)++inlinesR :: Inlines -> (Inlines, Inlines)+inlinesR ils = case viewr $ unMany ils of+ (sq :> s) -> (Many sq, singleton s)+ _ -> (ils, mempty)++combineInlines :: Inlines -> Inlines -> Inlines+combineInlines x y =+ let (xs', x') = inlinesR x+ (y', ys') = inlinesL y+ in+ xs' <> (combineSingletonInlines x' y') <> ys'++combineSingletonInlines :: Inlines -> Inlines -> Inlines+combineSingletonInlines x y =+ let (xfs, xs) = unstackInlines x+ (yfs, ys) = unstackInlines y+ shared = xfs `intersect` yfs+ x_remaining = xfs \\ shared+ y_remaining = yfs \\ shared+ x_rem_attr = filter isAttrModifier x_remaining+ y_rem_attr = filter isAttrModifier y_remaining+ in+ case null shared of+ True | isEmpty xs && isEmpty ys ->+ stackInlines (x_rem_attr ++ y_rem_attr) mempty+ | isEmpty xs ->+ let (sp, y') = spaceOutInlinesL y in+ (stackInlines x_rem_attr mempty) <> sp <> y'+ | isEmpty ys ->+ let (x', sp) = spaceOutInlinesR x in+ x' <> sp <> (stackInlines y_rem_attr mempty)+ | otherwise ->+ let (x', xsp) = spaceOutInlinesR x+ (ysp, y') = spaceOutInlinesL y+ in+ x' <> xsp <> ysp <> y'+ False -> stackInlines shared $+ combineInlines+ (stackInlines x_remaining xs)+ (stackInlines y_remaining ys)++combineBlocks :: Blocks -> Blocks -> Blocks+combineBlocks bs cs+ | bs' :> (BlockQuote bs'') <- viewr (unMany bs)+ , (BlockQuote cs'') :< cs' <- viewl (unMany cs) =+ Many $ (bs' |> (BlockQuote (bs'' <> cs''))) >< cs'+combineBlocks bs cs = bs <> cs++instance (Monoid a, Eq a) => Eq (Modifier a) where+ (Modifier f) == (Modifier g) = (f mempty == g mempty)+ (AttrModifier f attr) == (AttrModifier g attr') = (f attr mempty == g attr' mempty)+ (NullModifier) == (NullModifier) = True+ _ == _ = False++isEmpty :: (Monoid a, Eq a) => a -> Bool+isEmpty x = x == mempty++isAttrModifier :: Modifier a -> Bool+isAttrModifier (AttrModifier _ _) = True+isAttrModifier _ = False++smushInlines :: [Inlines] -> Inlines+smushInlines xs = foldl combineInlines mempty xs++smushBlocks :: [Blocks] -> Blocks+smushBlocks xs = foldl combineBlocks mempty xs
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -50,6 +50,7 @@ , Row(..) , Cell(..) , archiveToDocx+ , archiveToDocxWithWarnings ) where import Codec.Archive.Zip import Text.XML.Light@@ -60,6 +61,7 @@ import qualified Data.ByteString.Lazy as B import qualified Text.Pandoc.UTF8 as UTF8 import Control.Monad.Reader+import Control.Monad.State import Control.Applicative ((<|>)) import qualified Data.Map as M import Text.Pandoc.Compat.Except@@ -81,16 +83,20 @@ } deriving Show +data ReaderState = ReaderState { stateWarnings :: [String] }+ deriving Show+ + data DocxError = DocxError | WrongElem deriving Show instance Error DocxError where noMsg = WrongElem -type D = ExceptT DocxError (Reader ReaderEnv)+type D = ExceptT DocxError (ReaderT ReaderEnv (State ReaderState)) -runD :: D a -> ReaderEnv -> Either DocxError a-runD dx re = runReader (runExceptT dx) re+runD :: D a -> ReaderEnv -> ReaderState -> (Either DocxError a, ReaderState)+runD dx re rs = runState (runReaderT (runExceptT dx) re) rs maybeToD :: Maybe a -> D a maybeToD (Just a) = return a@@ -257,7 +263,10 @@ type ChangeDate = String archiveToDocx :: Archive -> Either DocxError Docx-archiveToDocx archive = do+archiveToDocx archive = fst <$> archiveToDocxWithWarnings archive++archiveToDocxWithWarnings :: Archive -> Either DocxError (Docx, [String])+archiveToDocxWithWarnings archive = do let notes = archiveToNotes archive numbering = archiveToNumbering archive rels = archiveToRelationships archive@@ -265,10 +274,14 @@ (styles, parstyles) = archiveToStyles archive rEnv = ReaderEnv notes numbering rels media Nothing styles parstyles InDocument- doc <- runD (archiveToDocument archive) rEnv- return $ Docx doc+ rState = ReaderState { stateWarnings = [] }+ (eitherDoc, st) = runD (archiveToDocument archive) rEnv rState+ case eitherDoc of+ Right doc -> Right (Docx doc, stateWarnings st)+ Left e -> Left e + archiveToDocument :: Archive -> D Document archiveToDocument zf = do entry <- maybeToD $ findEntryByPath "word/document.xml" zf@@ -576,12 +589,14 @@ sty <- asks envParStyles let parstyle = elemToParagraphStyle ns element sty parparts <- mapD (elemToParPart ns) (elChildren element)- case pNumInfo parstyle of- Just (numId, lvl) -> do- num <- asks envNumbering- let levelInfo = lookupLevel numId lvl num- return $ ListItem parstyle numId lvl levelInfo parparts- Nothing -> return $ Paragraph parstyle parparts+ -- Word uses list enumeration for numbered headings, so we only+ -- want to infer a list from the styles if it is NOT a heading.+ case pHeading parstyle of+ Nothing | Just (numId, lvl) <- pNumInfo parstyle -> do+ num <- asks envNumbering+ let levelInfo = lookupLevel numId lvl num+ return $ ListItem parstyle numId lvl levelInfo parparts+ _ -> return $ Paragraph parstyle parparts elemToBodyPart ns element | isElem ns "w" "tbl" element = do let caption' = findChild (elemName ns "w" "tblPr") element@@ -702,37 +717,59 @@ getDim at = findElement (QName "extent" (Just wp_ns) (Just "wp")) drawingElem >>= findAttr (QName at Nothing Nothing) >>= safeRead -elemToRun :: NameSpaces -> Element -> D Run-elemToRun ns element- | isElem ns "w" "r" element- , Just drawingElem <- findChild (elemName ns "w" "drawing") element =++childElemToRun :: NameSpaces -> Element -> D Run+childElemToRun ns element+ | isElem ns "w" "drawing" element = let a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"- drawing = findElement (QName "blip" (Just a_ns) (Just "a")) drawingElem+ drawing = findElement (QName "blip" (Just a_ns) (Just "a")) element >>= findAttr (QName "embed" (lookup "r" ns) (Just "r")) in case drawing of Just s -> expandDrawingId s >>=- (\(fp, bs) -> return $ InlineDrawing fp bs $ elemToExtent drawingElem)+ (\(fp, bs) -> return $ InlineDrawing fp bs $ elemToExtent element) Nothing -> throwError WrongElem-elemToRun ns element- | isElem ns "w" "r" element- , Just ref <- findChild (elemName ns "w" "footnoteReference") element- , Just fnId <- findAttr (elemName ns "w" "id") ref = do+childElemToRun ns element+ | isElem ns "w" "footnoteReference" element+ , Just fnId <- findAttr (elemName ns "w" "id") element = do notes <- asks envNotes case lookupFootnote fnId notes of Just e -> do bps <- local (\r -> r {envLocation=InFootnote}) $ mapD (elemToBodyPart ns) (elChildren e) return $ Footnote bps Nothing -> return $ Footnote []-elemToRun ns element- | isElem ns "w" "r" element- , Just ref <- findChild (elemName ns "w" "endnoteReference") element- , Just enId <- findAttr (elemName ns "w" "id") ref = do+childElemToRun ns element+ | isElem ns "w" "endnoteReference" element+ , Just enId <- findAttr (elemName ns "w" "id") element = do notes <- asks envNotes case lookupEndnote enId notes of Just e -> do bps <- local (\r -> r {envLocation=InEndnote}) $ mapD (elemToBodyPart ns) (elChildren e) return $ Endnote bps Nothing -> return $ Endnote []+childElemToRun _ _ = throwError WrongElem++elemToRun :: NameSpaces -> Element -> D Run elemToRun ns element+ | isElem ns "w" "r" element+ , Just altCont <- findChild (elemName ns "mc" "AlternateContent") element =+ do let choices = findChildren (elemName ns "mc" "Choice") altCont+ choiceChildren = map head $ filter (not . null) $ map elChildren choices+ outputs <- mapD (childElemToRun ns) choiceChildren+ case outputs of+ r : _ -> return r+ [] -> throwError WrongElem+elemToRun ns element+ | isElem ns "w" "r" element+ , Just drawingElem <- findChild (elemName ns "w" "drawing") element =+ childElemToRun ns drawingElem+elemToRun ns element+ | isElem ns "w" "r" element+ , Just ref <- findChild (elemName ns "w" "footnoteReference") element =+ childElemToRun ns ref+elemToRun ns element+ | isElem ns "w" "r" element+ , Just ref <- findChild (elemName ns "w" "endnoteReference") element =+ childElemToRun ns ref+elemToRun ns element | isElem ns "w" "r" element = do runElems <- elemToRunElems ns element runStyle <- elemToRunStyleD ns element@@ -940,3 +977,4 @@ setFont :: Maybe Font -> ReaderEnv -> ReaderEnv setFont f s = s{envFont = f}+
− src/Text/Pandoc/Readers/Docx/Reducible.hs
@@ -1,181 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances,- PatternGuards #-}--module Text.Pandoc.Readers.Docx.Reducible ( concatReduce- , (<+>)- )- where---import Text.Pandoc.Builder-import Data.List-import Data.Sequence (ViewR(..), ViewL(..), viewl, viewr)-import qualified Data.Sequence as Seq (null)--data Modifier a = Modifier (a -> a)- | AttrModifier (Attr -> a -> a) Attr- | NullModifier--class (Eq a) => Modifiable a where- modifier :: a -> Modifier a- innards :: a -> a- getL :: a -> (a, a)- getR :: a -> (a, a)- spaceOut :: a -> (a, a, a)--spaceOutL :: (Monoid a, Modifiable a) => a -> (a, a)-spaceOutL ms = (l, stack fs (m' <> r))- where (l, m, r) = spaceOut ms- (fs, m') = unstack m--spaceOutR :: (Monoid a, Modifiable a) => a -> (a, a)-spaceOutR ms = (stack fs (l <> m'), r)- where (l, m, r) = spaceOut ms- (fs, m') = unstack m--instance (Monoid a, Show a) => Show (Modifier a) where- show (Modifier f) = show $ f mempty- show (AttrModifier f attr) = show $ f attr mempty- show (NullModifier) = "NullModifier"--instance (Monoid a, Eq a) => Eq (Modifier a) where- (Modifier f) == (Modifier g) = (f mempty == g mempty)- (AttrModifier f attr) == (AttrModifier g attr') = (f attr mempty == g attr' mempty)- (NullModifier) == (NullModifier) = True- _ == _ = False--instance Modifiable Inlines where- modifier ils = case viewl (unMany ils) of- (x :< xs) | Seq.null xs -> case x of- (Emph _) -> Modifier emph- (Strong _) -> Modifier strong- (SmallCaps _) -> Modifier smallcaps- (Strikeout _) -> Modifier strikeout- (Superscript _) -> Modifier superscript- (Subscript _) -> Modifier subscript- (Span attr _) -> AttrModifier spanWith attr- _ -> NullModifier- _ -> NullModifier-- innards ils = case viewl (unMany ils) of- (x :< xs) | Seq.null xs -> case x of- (Emph lst) -> fromList lst- (Strong lst) -> fromList lst- (SmallCaps lst) -> fromList lst- (Strikeout lst) -> fromList lst- (Superscript lst) -> fromList lst- (Subscript lst) -> fromList lst- (Span _ lst) -> fromList lst- _ -> ils- _ -> ils-- getL ils = case viewl $ unMany ils of- (s :< sq) -> (singleton s, Many sq)- _ -> (mempty, ils)-- getR ils = case viewr $ unMany ils of- (sq :> s) -> (Many sq, singleton s)- _ -> (ils, mempty)-- spaceOut ils =- let (fs, ils') = unstack ils- contents = unMany ils'- left = case viewl contents of- (Space :< _) -> space- _ -> mempty- right = case viewr contents of- (_ :> Space) -> space- _ -> mempty in- (left, (stack fs $ trimInlines .Many $ contents), right)--instance Modifiable Blocks where- modifier blks = case viewl (unMany blks) of- (x :< xs) | Seq.null xs -> case x of- (BlockQuote _) -> Modifier blockQuote- -- (Div attr _) -> AttrModifier divWith attr- _ -> NullModifier- _ -> NullModifier-- innards blks = case viewl (unMany blks) of- (x :< xs) | Seq.null xs -> case x of- (BlockQuote lst) -> fromList lst- -- (Div attr lst) -> fromList lst- _ -> blks- _ -> blks-- spaceOut blks = (mempty, blks, mempty)-- getL ils = case viewl $ unMany ils of- (s :< sq) -> (singleton s, Many sq)- _ -> (mempty, ils)-- getR ils = case viewr $ unMany ils of- (sq :> s) -> (Many sq, singleton s)- _ -> (ils, mempty)---unstack :: (Modifiable a) => a -> ([Modifier a], a)-unstack ms = case modifier ms of- NullModifier -> ([], ms)- _ -> (f : fs, ms') where- f = modifier ms- (fs, ms') = unstack $ innards ms--stack :: (Monoid a, Modifiable a) => [Modifier a] -> a -> a-stack [] ms = ms-stack (NullModifier : fs) ms = stack fs ms-stack ((Modifier f) : fs) ms =- if isEmpty ms- then stack fs ms- else f $ stack fs ms-stack ((AttrModifier f attr) : fs) ms = f attr $ stack fs ms--isEmpty :: (Monoid a, Eq a) => a -> Bool-isEmpty x = x == mempty---combine :: (Monoid a, Modifiable a, Eq a) => a -> a -> a-combine x y =- let (xs', x') = getR x- (y', ys') = getL y- in- xs' <> (combineSingleton x' y') <> ys'--isAttrModifier :: Modifier a -> Bool-isAttrModifier (AttrModifier _ _) = True-isAttrModifier _ = False--combineSingleton :: (Monoid a, Modifiable a, Eq a) => a -> a -> a-combineSingleton x y =- let (xfs, xs) = unstack x- (yfs, ys) = unstack y- shared = xfs `intersect` yfs- x_remaining = xfs \\ shared- y_remaining = yfs \\ shared- x_rem_attr = filter isAttrModifier x_remaining- y_rem_attr = filter isAttrModifier y_remaining- in- case null shared of- True | isEmpty xs && isEmpty ys ->- stack (x_rem_attr ++ y_rem_attr) mempty- | isEmpty xs ->- let (sp, y') = spaceOutL y in- (stack x_rem_attr mempty) <> sp <> y'- | isEmpty ys ->- let (x', sp) = spaceOutR x in- x' <> sp <> (stack y_rem_attr mempty)- | otherwise ->- let (x', xsp) = spaceOutR x- (ysp, y') = spaceOutL y- in- x' <> xsp <> ysp <> y'- False -> stack shared $- combine- (stack x_remaining xs)- (stack y_remaining ys)--(<+>) :: (Monoid a, Modifiable a, Eq a) => a -> a -> a-x <+> y = combine x y--concatReduce :: (Monoid a, Modifiable a) => [a] -> a-concatReduce xs = foldl combine mempty xs
src/Text/Pandoc/Readers/HTML.hs view
@@ -43,7 +43,7 @@ import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Builder (Blocks, Inlines, trimInlines, HasMeta(..))-import Text.Pandoc.Shared ( extractSpaces, renderTags'+import Text.Pandoc.Shared ( extractSpaces, renderTags', addMetaField , escapeURI, safeRead, mapLeft ) import Text.Pandoc.Options (ReaderOptions(readerParseRaw, readerTrace) , Extension (Ext_epub_html_exts,@@ -52,9 +52,9 @@ import Text.Pandoc.Walk import qualified Data.Map as M import Data.Maybe ( fromMaybe, isJust)-import Data.List ( intercalate, isInfixOf, isPrefixOf, isSuffixOf )+import Data.List ( intercalate, isInfixOf, isPrefixOf ) import Data.Char ( isDigit )-import Control.Monad ( liftM, guard, when, mzero, void, unless )+import Control.Monad ( guard, when, mzero, void, unless ) import Control.Arrow ((***)) import Control.Applicative ( (<|>) ) import Data.Monoid (First (..))@@ -63,12 +63,12 @@ import Text.TeXMath (readMathML, writeTeX) import Data.Default (Default (..), def) import Control.Monad.Reader (Reader,ask, asks, local, runReader)-import Network.URI (isURI)+import Network.URI (URI, parseURIReference, nonStrictRelativeTo) import Text.Pandoc.Error import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps) import Text.Pandoc.Compat.Monoid ((<>)) import Text.Parsec.Error-+import qualified Data.Set as Set -- | Convert HTML-formatted string to 'Pandoc' document. readHtml :: ReaderOptions -- ^ Reader options@@ -77,7 +77,7 @@ readHtml opts inp = mapLeft (ParseFailure . getError) . flip runReader def $ runParserT parseDoc- (HTMLState def{ stateOptions = opts } [] Nothing [] M.empty)+ (HTMLState def{ stateOptions = opts } [] Nothing Set.empty M.empty) "source" tags where tags = stripPrefixes . canonicalizeTags $ parseTagsOptions parseOptions{ optTagPosition = True } inp@@ -103,8 +103,8 @@ HTMLState { parserState :: ParserState, noteTable :: [(String, Blocks)],- baseHref :: Maybe String,- identifiers :: [String],+ baseHref :: Maybe URI,+ identifiers :: Set.Set String, headerMap :: M.Map Inlines String } @@ -137,19 +137,17 @@ then return mempty else do let content = fromAttrib "content" mt- updateState $ B.setMeta name (B.text content)+ updateState $ \s ->+ let ps = parserState s in+ s{ parserState = ps{+ stateMeta = addMetaField name (B.text content)+ (stateMeta ps) } } return mempty pBaseTag = do bt <- pSatisfy (~== TagOpen "base" [])- let baseH = fromAttrib "href" bt- if null baseH- then return mempty- else do- let baseH' = case reverse baseH of- '/':_ -> baseH- _ -> baseH ++ "/"- updateState $ \st -> st{ baseHref = Just baseH' }- return mempty+ updateState $ \st -> st{ baseHref =+ parseURIReference $ fromAttrib "href" bt }+ return mempty block :: TagParser Blocks block = do@@ -441,6 +439,7 @@ -- fail on empty table guard $ not $ null head' && null rows let isSinglePlain x = case B.toList x of+ [] -> True [Plain _] -> True _ -> False let isSimple = all isSinglePlain $ concat (head':rows)@@ -605,9 +604,9 @@ tag <- pSatisfy $ tagOpenLit "a" (const True) mbBaseHref <- baseHref <$> getState let url' = fromAttrib "href" tag- let url = case (isURI url', mbBaseHref) of- (False, Just h) -> h ++ url'- _ -> url'+ let url = case (parseURIReference url', mbBaseHref) of+ (Just rel, Just bs) -> show (rel `nonStrictRelativeTo` bs)+ _ -> url' let title = fromAttrib "title" tag let uid = fromAttrib "id" tag let cls = words $ fromAttrib "class" tag@@ -619,9 +618,9 @@ tag <- pSelfClosing (=="img") (isJust . lookup "src") mbBaseHref <- baseHref <$> getState let url' = fromAttrib "src" tag- let url = case (isURI url', mbBaseHref) of- (False, Just h) -> h ++ url'- _ -> url'+ let url = case (parseURIReference url', mbBaseHref) of+ (Just rel, Just bs) -> show (rel `nonStrictRelativeTo` bs)+ _ -> url' let title = fromAttrib "title" tag let alt = fromAttrib "alt" tag let uid = fromAttrib "id" tag@@ -925,15 +924,46 @@ => (Tag String -> Bool) -> ParserT String st m String htmlInBalanced f = try $ do- (TagOpen t _, tag) <- htmlTag f- guard $ not $ "/>" `isSuffixOf` tag -- not a self-closing tag- let stopper = htmlTag (~== TagClose t)- let anytag = snd <$> htmlTag (const True)- contents <- many $ notFollowedBy' stopper >>- (htmlInBalanced f <|> anytag <|> count 1 anyChar)- endtag <- liftM snd stopper- return $ tag ++ concat contents ++ endtag+ lookAhead (char '<')+ inp <- getInput+ let ts = canonicalizeTags $+ parseTagsOptions parseOptions{ optTagWarning = True,+ optTagPosition = True } inp+ case ts of+ (TagPosition sr sc : t@(TagOpen tn _) : rest) -> do+ guard $ f t+ guard $ not $ hasTagWarning (t : take 1 rest)+ case htmlInBalanced' tn (t:rest) of+ [] -> mzero+ xs -> case reverse xs of+ (TagClose _ : TagPosition er ec : _) -> do+ let ls = er - sr+ let cs = ec - sc+ lscontents <- concat <$> count ls anyLine+ cscontents <- count cs anyChar+ (_,closetag) <- htmlTag (~== TagClose tn)+ return (lscontents ++ cscontents ++ closetag)+ _ -> mzero+ _ -> mzero +htmlInBalanced' :: String+ -> [Tag String]+ -> [Tag String]+htmlInBalanced' tagname ts = fromMaybe [] $ go 0 ts+ where go :: Int -> [Tag String] -> Maybe [Tag String]+ go n (t@(TagOpen tn' _):rest) | tn' == tagname =+ (t :) <$> go (n + 1) rest+ go 1 (t@(TagClose tn'):_) | tn' == tagname =+ return [t]+ go n (t@(TagClose tn'):rest) | tn' == tagname =+ (t :) <$> go (n - 1) rest+ go n (t:ts') = (t :) <$> go n ts'+ go _ [] = mzero++hasTagWarning :: [Tag String] -> Bool+hasTagWarning (TagWarning _:_) = True+hasTagWarning _ = False+ -- | Matches a tag meeting a certain condition. htmlTag :: Monad m => (Tag String -> Bool)@@ -941,8 +971,6 @@ htmlTag f = try $ do lookAhead (char '<') inp <- getInput- let hasTagWarning (TagWarning _:_) = True- hasTagWarning _ = False let (next : rest) = canonicalizeTags $ parseTagsOptions parseOptions{ optTagWarning = True } inp guard $ f next
src/Text/Pandoc/Readers/LaTeX.hs view
@@ -166,10 +166,18 @@ mathInline p = math <$> (try p >>= applyMacros') mathChars :: LP String-mathChars = (concat <$>) $- many $- many1 (satisfy (\c -> c /= '$' && c /='\\'))- <|> (\c -> ['\\',c]) <$> try (char '\\' *> anyChar)+mathChars =+ concat <$> many (escapedChar+ <|> (snd <$> withRaw braced)+ <|> many1 (satisfy isOrdChar))+ where escapedChar = try $ do char '\\'+ c <- anyChar+ return ['\\',c]+ isOrdChar '$' = False+ isOrdChar '{' = False+ isOrdChar '}' = False+ isOrdChar '\\' = False+ isOrdChar _ = True quoted' :: (Inlines -> Inlines) -> LP String -> LP () -> LP Inlines quoted' f starter ender = do@@ -422,7 +430,8 @@ else if parseRaw then return $ rawInline "latex" rawcommand else return mempty- lookupListDefault mzero [name',name] inlineCommands+ (lookupListDefault mzero [name',name] inlineCommands <*+ optional (try (string "{}"))) <|> raw unlessParseRaw :: LP ()@@ -435,6 +444,7 @@ inlineEnvironments :: M.Map String (LP Inlines) inlineEnvironments = M.fromList [ ("displaymath", mathEnv id Nothing "displaymath")+ , ("math", math <$> verbEnv "math") , ("equation", mathEnv id Nothing "equation") , ("equation*", mathEnv id Nothing "equation*") , ("gather", mathEnv id (Just "gathered") "gather")
src/Text/Pandoc/Readers/Markdown.hs view
@@ -36,7 +36,7 @@ import qualified Data.Map as M import Data.Scientific (coefficient, base10Exponent) import Data.Ord ( comparing )-import Data.Char ( isSpace, isAlphaNum, toLower )+import Data.Char ( isSpace, isAlphaNum, toLower, isPunctuation ) import Data.Maybe import Text.Pandoc.Definition import Text.Pandoc.Emoji (emojis)@@ -61,7 +61,6 @@ import Control.Monad import System.FilePath (takeExtension, addExtension) import Text.HTML.TagSoup-import Text.HTML.TagSoup.Match (tagOpen) import qualified Data.Set as Set import Text.Printf (printf) import Debug.Trace (trace)@@ -1052,12 +1051,11 @@ strictHtmlBlock = htmlInBalanced (not . isInlineTag) rawVerbatimBlock :: MarkdownParser String-rawVerbatimBlock = try $ do- (TagOpen tag _, open) <- htmlTag (tagOpen (flip elem- ["pre", "style", "script"])- (const True))- contents <- manyTill anyChar (htmlTag (~== TagClose tag))- return $ open ++ contents ++ renderTags' [TagClose tag]+rawVerbatimBlock = htmlInBalanced isVerbTag+ where isVerbTag (TagOpen "pre" _) = True+ isVerbTag (TagOpen "style" _) = True+ isVerbTag (TagOpen "script" _) = True+ isVerbTag _ = False rawTeXBlock :: MarkdownParser (F Blocks) rawTeXBlock = do@@ -1356,16 +1354,18 @@ nonindentSpaces lookAhead nonspaceChar (heads,(aligns, seplengths)) <- (,) <$> pipeTableRow <*> pipeBreak+ let heads' = take (length aligns) <$> heads lines' <- many pipeTableRow+ let lines'' = map (take (length aligns) <$>) lines' let maxlength = maximum $- map (\x -> length . stringify $ runF x def) (heads : lines')+ map (\x -> length . stringify $ runF x def) (heads' : lines'') numColumns <- getOption readerColumns let widths = if maxlength > numColumns then map (\len -> fromIntegral (len + 1) / fromIntegral numColumns) seplengths else replicate (length aligns) 0.0- return $ (aligns, widths, heads, sequence lines')+ return $ (aligns, widths, heads', sequence lines'') sepPipe :: MarkdownParser () sepPipe = try $ do@@ -1374,26 +1374,28 @@ -- parse a row, also returning probable alignments for org-table cells pipeTableRow :: MarkdownParser (F [Blocks])-pipeTableRow = do+pipeTableRow = try $ do+ scanForPipe skipMany spaceChar openPipe <- (True <$ char '|') <|> return False- let cell = mconcat <$>- many (notFollowedBy (blankline <|> char '|') >> inline)- first <- cell- rest <- many $ sepPipe *> cell+ -- split into cells+ let chunk = void (code <|> rawHtmlInline <|> escapedChar <|> rawLaTeXInline')+ <|> void (noneOf "|\n\r")+ let cellContents = ((trim . snd) <$> withRaw (many chunk)) >>=+ parseFromString pipeTableCell+ cells <- cellContents `sepEndBy1` (char '|') -- surrounding pipes needed for a one-column table:- guard $ not (null rest && not openPipe)- optional (char '|')+ guard $ not (length cells == 1 && not openPipe) blankline- let cells = sequence (first:rest)- return $ do- cells' <- cells- return $ map- (\ils ->- case trimInlines ils of- ils' | B.isNull ils' -> mempty- | otherwise -> B.plain $ ils') cells'+ return $ sequence cells +pipeTableCell :: MarkdownParser (F Blocks)+pipeTableCell = do+ result <- many inline+ if null result+ then return mempty+ else return $ B.plain . mconcat <$> sequence result+ pipeTableHeaderPart :: Parser [Char] st (Alignment, Int) pipeTableHeaderPart = try $ do skipMany spaceChar@@ -1554,7 +1556,7 @@ math = (return . B.displayMath <$> (mathDisplay >>= applyMacros')) <|> (return . B.math <$> (mathInline >>= applyMacros')) <+?> ((getOption readerSmart >>= guard) *> (return <$> apostrophe)- <* notFollowedBy space)+ <* notFollowedBy (space <|> satisfy isPunctuation)) -- Parses material enclosed in *s, **s, _s, or __s. -- Designed to avoid backtracking.
src/Text/Pandoc/Readers/MediaWiki.hs view
@@ -52,6 +52,7 @@ import Data.Sequence (viewl, ViewL(..), (<|)) import qualified Data.Foldable as F import qualified Data.Map as M+import qualified Data.Set as Set import Data.Char (isDigit, isSpace) import Data.Maybe (fromMaybe) import Text.Printf (printf)@@ -69,7 +70,7 @@ , mwNextLinkNumber = 1 , mwCategoryLinks = [] , mwHeaderMap = M.empty- , mwIdentifierList = []+ , mwIdentifierList = Set.empty } (s ++ "\n") @@ -78,7 +79,7 @@ , mwNextLinkNumber :: Int , mwCategoryLinks :: [Inlines] , mwHeaderMap :: M.Map Inlines String- , mwIdentifierList :: [String]+ , mwIdentifierList :: Set.Set String } type MWParser = Parser [Char] MWState
src/Text/Pandoc/Readers/Odt/ContentReader.hs view
@@ -61,6 +61,7 @@ import Text.Pandoc.Readers.Odt.Generic.Fallible import Text.Pandoc.Readers.Odt.Generic.Utils +import qualified Data.Set as Set -------------------------------------------------------------------------------- -- State@@ -221,7 +222,7 @@ getHeaderAnchor :: OdtReaderSafe Inlines Anchor getHeaderAnchor = proc title -> do state <- getExtraState -< ()- let anchor = uniqueIdent (toList title) (usedAnchors state)+ let anchor = uniqueIdent (toList title) (Set.fromList $ usedAnchors state) modifyExtraState (putPrettyAnchor anchor anchor) -<< anchor
src/Text/Pandoc/Readers/Org.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-} {--Copyright (C) 2014-2015 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -21,7 +21,7 @@ {- | Module : Text.Pandoc.Readers.Org- Copyright : Copyright (C) 2014-2015 Albert Krewinkel+ Copyright : Copyright (C) 2014-2016 Albert Krewinkel License : GNU GPL, version 2 or above Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -53,6 +53,7 @@ import Data.Default import Data.List (intersperse, isPrefixOf, isSuffixOf) import qualified Data.Map as M+import qualified Data.Set as Set import Data.Maybe (fromMaybe, isJust) import Network.HTTP (urlEncode) @@ -144,7 +145,7 @@ , orgStateMeta' :: F Meta , orgStateNotes' :: OrgNoteTable , orgStateParserContext :: ParserContext- , orgStateIdentifiers :: [String]+ , orgStateIdentifiers :: Set.Set String , orgStateHeaderMap :: M.Map Inlines String } @@ -186,7 +187,7 @@ , orgStateMeta' = return nullMeta , orgStateNotes' = [] , orgStateParserContext = NullState- , orgStateIdentifiers = []+ , orgStateIdentifiers = Set.empty , orgStateHeaderMap = M.empty } @@ -628,7 +629,7 @@ maybeNam <- lookupBlockAttribute "name" guard $ isJust maybeCap || isJust maybeNam return ( fromMaybe mempty maybeCap- , maybe mempty withFigPrefix maybeNam )+ , withFigPrefix $ fromMaybe mempty maybeNam ) withFigPrefix cs = if "fig:" `isPrefixOf` cs then cs@@ -1238,37 +1239,37 @@ formatter <- M.lookup linkType <$> asksF orgStateLinkFormatters return $ maybe link ($ drop 1 rest) formatter --- TODO: might be a lot smarter/cleaner to use parsec and ADTs for this kind--- of parsing.+-- | Take a link and return a function which produces new inlines when given+-- description inlines. linkToInlinesF :: String -> Inlines -> F Inlines-linkToInlinesF s =- case s of- "" -> pure . B.link "" ""- ('#':_) -> pure . B.link s ""- _ | isImageFilename s -> const . pure $ B.image s "" ""- _ | isFileLink s -> pure . B.link (dropLinkType s) ""- _ | isUri s -> pure . B.link s ""- _ | isAbsoluteFilePath s -> pure . B.link ("file://" ++ s) ""- _ | isRelativeFilePath s -> pure . B.link s ""- _ -> internalLink s--isFileLink :: String -> Bool-isFileLink s = ("file:" `isPrefixOf` s) && not ("file://" `isPrefixOf` s)--dropLinkType :: String -> String-dropLinkType = tail . snd . break (== ':')--isRelativeFilePath :: String -> Bool-isRelativeFilePath s = (("./" `isPrefixOf` s) || ("../" `isPrefixOf` s)) &&- (':' `notElem` s)--isUri :: String -> Bool-isUri s = let (scheme, path) = break (== ':') s- in all (\c -> isAlphaNum c || c `elem` (".-" :: String)) scheme- && not (null path)+linkToInlinesF linkStr =+ case linkStr of+ "" -> pure . B.link mempty "" -- wiki link (empty by convention)+ ('#':_) -> pure . B.link linkStr "" -- document-local fraction+ _ -> case cleanLinkString linkStr of+ (Just cleanedLink) -> if isImageFilename cleanedLink+ then const . pure $ B.image cleanedLink "" ""+ else pure . B.link cleanedLink ""+ Nothing -> internalLink linkStr -- other internal link -isAbsoluteFilePath :: String -> Bool-isAbsoluteFilePath = ('/' ==) . head+-- | Cleanup and canonicalize a string describing a link. Return @Nothing@ if+-- the string does not appear to be a link.+cleanLinkString :: String -> Maybe String+cleanLinkString s =+ case s of+ '/':_ -> Just $ "file://" ++ s -- absolute path+ '.':'/':_ -> Just s -- relative path+ '.':'.':'/':_ -> Just s -- relative path+ -- Relative path or URL (file schema)+ 'f':'i':'l':'e':':':s' -> Just $ if ("//" `isPrefixOf` s') then s else s'+ _ | isUrl s -> Just s -- URL+ _ -> Nothing+ where+ isUrl :: String -> Bool+ isUrl cs =+ let (scheme, path) = break (== ':') cs+ in all (\c -> isAlphaNum c || c `elem` (".-"::String)) scheme+ && not (null path) isImageFilename :: String -> Bool isImageFilename filename =
src/Text/Pandoc/Readers/Textile.hs view
@@ -583,8 +583,19 @@ -- | Html / CSS attributes attributes :: Parser [Char] ParserState Attr-attributes = (foldl (flip ($)) ("",[],[])) `fmap` many attribute+attributes = (foldl (flip ($)) ("",[],[])) <$>+ try (do special <- option id specialAttribute+ attrs <- many attribute+ return (special : attrs)) +specialAttribute :: Parser [Char] ParserState (Attr -> Attr)+specialAttribute = do+ alignStr <- ("center" <$ char '=') <|>+ ("justify" <$ try (string "<>")) <|>+ ("right" <$ char '>') <|>+ ("left" <$ char '<')+ return $ addStyle ("text-align:" ++ alignStr)+ attribute :: Parser [Char] ParserState (Attr -> Attr) attribute = classIdAttr <|> styleAttr <|> langAttr @@ -602,7 +613,13 @@ styleAttr :: Parser [Char] ParserState (Attr -> Attr) styleAttr = do style <- try $ enclosed (char '{') (char '}') anyChar'- return $ \(id',classes,keyvals) -> (id',classes,("style",style):keyvals)+ return $ addStyle style++addStyle :: String -> Attr -> Attr+addStyle style (id',classes,keyvals) =+ (id',classes,keyvals')+ where keyvals' = ("style", style') : [(k,v) | (k,v) <- keyvals, k /= "style"]+ style' = style ++ ";" ++ concat [v | ("style",v) <- keyvals] langAttr :: Parser [Char] ParserState (Attr -> Attr) langAttr = do
@@ -706,14 +706,14 @@ -- | Generate a unique identifier from a list of inlines. -- Second argument is a list of already used identifiers.-uniqueIdent :: [Inline] -> [String] -> String+uniqueIdent :: [Inline] -> Set.Set String -> String uniqueIdent title' usedIdents = let baseIdent = case inlineListToIdentifier title' of "" -> "section" x -> x numIdent n = baseIdent ++ "-" ++ show n- in if baseIdent `elem` usedIdents- then case find (\x -> numIdent x `notElem` usedIdents) ([1..60000] :: [Int]) of+ in if baseIdent `Set.member` usedIdents+ then case find (\x -> not $ numIdent x `Set.member` usedIdents) ([1..60000] :: [Int]) of Just x -> numIdent x Nothing -> baseIdent -- if we have more than 60,000, allow repeats else baseIdent@@ -892,8 +892,10 @@ parseURIReference' :: String -> Maybe URI parseURIReference' s = case parseURIReference s of- Just u | length (uriScheme u) > 2 -> Just u- _ -> Nothing+ Just u+ | length (uriScheme u) > 2 -> Just u+ | null (uriScheme u) -> Just u -- protocol-relative+ _ -> Nothing -- | Fetch an image or other item from the local filesystem or the net. -- Returns raw content and maybe mime type.
src/Text/Pandoc/Writers/ConTeXt.hs view
@@ -279,7 +279,17 @@ -- | Convert list of inline elements to ConTeXt. inlineListToConTeXt :: [Inline] -- ^ Inlines to convert -> State WriterState Doc-inlineListToConTeXt lst = liftM hcat $ mapM inlineToConTeXt lst+inlineListToConTeXt lst = liftM hcat $ mapM inlineToConTeXt $ addStruts lst+ -- We add a \strut after a line break that precedes a space,+ -- or the space gets swallowed+ where addStruts (LineBreak : s : xs) | isSpacey s =+ LineBreak : RawInline (Format "context") "\\strut " : s :+ addStruts xs+ addStruts (x:xs) = x : addStruts xs+ addStruts [] = []+ isSpacey Space = True+ isSpacey (Str ('\160':_)) = True+ isSpacey _ = False -- | Convert inline element to ConTeXt inlineToConTeXt :: Inline -- ^ Inline to convert
src/Text/Pandoc/Writers/Custom.hs view
@@ -222,8 +222,8 @@ blockToCustom lua (Plain inlines) = callfunc lua "Plain" inlines -blockToCustom lua (Para [Image _ txt (src,tit)]) =- callfunc lua "CaptionedImage" src tit txt+blockToCustom lua (Para [Image attr txt (src,tit)]) =+ callfunc lua "CaptionedImage" src tit txt (attrToMap attr) blockToCustom lua (Para inlines) = callfunc lua "Para" inlines
src/Text/Pandoc/Writers/Docx.hs view
@@ -34,6 +34,7 @@ import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BL8 import qualified Data.Map as M+import qualified Data.Set as Set import qualified Text.Pandoc.UTF8 as UTF8 import Codec.Archive.Zip import Data.Time.Clock.POSIX@@ -95,7 +96,7 @@ stTextProperties :: [Element] , stParaProperties :: [Element] , stFootnotes :: [Element]- , stSectionIds :: [String]+ , stSectionIds :: Set.Set String , stExternalLinks :: M.Map String String , stImages :: M.Map FilePath (String, String, Maybe MimeType, Element, B.ByteString) , stListLevel :: Int@@ -117,7 +118,7 @@ stTextProperties = [] , stParaProperties = [] , stFootnotes = defaultFootnotes- , stSectionIds = []+ , stSectionIds = Set.empty , stExternalLinks = M.empty , stImages = M.empty , stListLevel = -1@@ -742,7 +743,7 @@ let bookmarkName = if null ident then uniqueIdent lst usedIdents else ident- modify $ \s -> s{ stSectionIds = bookmarkName : stSectionIds s }+ modify $ \s -> s{ stSectionIds = Set.insert bookmarkName $ stSectionIds s } id' <- getUniqueId let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id') ,("w:name",bookmarkName)] ()@@ -1102,7 +1103,7 @@ M.insert src i extlinks } return i return [ mknode "w:hyperlink" [("r:id",id')] contents ]-inlineToOpenXML opts (Image attr alt (src, tit)) = do+inlineToOpenXML opts (Image attr alt (src, _)) = do -- first, check to see if we've already done this image pageWidth <- gets stPrintWidth imgs <- gets stImages@@ -1153,7 +1154,7 @@ mknode "wp:inline" [] [ mknode "wp:extent" [("cx",show xemu),("cy",show yemu)] () , mknode "wp:effectExtent" [("b","0"),("l","0"),("r","0"),("t","0")] ()- , mknode "wp:docPr" [("descr",tit),("id","1"),("name","Picture")] ()+ , mknode "wp:docPr" [("descr",stringify alt),("id","1"),("name","Picture")] () , graphic ] let imgext = case mt >>= extensionFromMimeType of Just x -> '.':x
src/Text/Pandoc/Writers/DokuWiki.hs view
@@ -452,8 +452,11 @@ inlineToDokuWiki _ (Str str) = return $ escapeString str -inlineToDokuWiki _ (Math _ str) = return $ "$" ++ str ++ "$"+inlineToDokuWiki _ (Math mathType str) = return $ delim ++ str ++ delim -- note: str should NOT be escaped+ where delim = case mathType of+ DisplayMath -> "$$"+ InlineMath -> "$" inlineToDokuWiki _ (RawInline f str) | f == Format "dokuwiki" = return str
src/Text/Pandoc/Writers/EPUB.hs view
@@ -31,6 +31,7 @@ module Text.Pandoc.Writers.EPUB ( writeEPUB ) where import Data.IORef ( IORef, newIORef, readIORef, modifyIORef ) import qualified Data.Map as M+import qualified Data.Set as Set import Data.Maybe ( fromMaybe, catMaybes ) import Data.List ( isPrefixOf, isInfixOf, intercalate ) import System.Environment ( getEnv )@@ -916,13 +917,13 @@ -- Add identifiers to any headers without them. addIdentifiers :: [Block] -> [Block]-addIdentifiers bs = evalState (mapM go bs) []+addIdentifiers bs = evalState (mapM go bs) Set.empty where go (Header n (ident,classes,kvs) ils) = do ids <- get let ident' = if null ident then uniqueIdent ils ids else ident- put $ ident' : ids+ modify $ Set.insert ident' return $ Header n (ident',classes,kvs) ils go x = return x
src/Text/Pandoc/Writers/HTML.hs view
@@ -140,40 +140,38 @@ st <- get let notes = reverse (stNotes st) let thebody = blocks' >> footnoteSection opts notes- let math = if stMath st- then case writerHTMLMathMethod opts of- LaTeXMathML (Just url) ->- H.script ! A.src (toValue url)- ! A.type_ "text/javascript"- $ mempty- MathML (Just url) ->- H.script ! A.src (toValue url)- ! A.type_ "text/javascript"- $ mempty- MathJax url ->- H.script ! A.src (toValue url)- ! A.type_ "text/javascript"- $ case writerSlideVariant opts of- SlideousSlides ->- preEscapedString- "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);"- _ -> mempty- JsMath (Just url) ->- H.script ! A.src (toValue url)- ! A.type_ "text/javascript"- $ mempty- KaTeX js css ->- (H.script ! A.src (toValue js) $ mempty) <>- (H.link ! A.rel "stylesheet" ! A.href (toValue css)) <>- (H.script ! A.type_ "text/javascript" $ toHtml renderKaTeX)- _ -> case lookup "mathml-script" (writerVariables opts) of- Just s | not (writerHtml5 opts) ->- H.script ! A.type_ "text/javascript"- $ preEscapedString- ("/*<![CDATA[*/\n" ++ s ++ "/*]]>*/\n")- | otherwise -> mempty- Nothing -> mempty- else mempty+ let math = case writerHTMLMathMethod opts of+ LaTeXMathML (Just url) ->+ H.script ! A.src (toValue url)+ ! A.type_ "text/javascript"+ $ mempty+ MathML (Just url) ->+ H.script ! A.src (toValue url)+ ! A.type_ "text/javascript"+ $ mempty+ MathJax url ->+ H.script ! A.src (toValue url)+ ! A.type_ "text/javascript"+ $ case writerSlideVariant opts of+ SlideousSlides ->+ preEscapedString+ "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);"+ _ -> mempty+ JsMath (Just url) ->+ H.script ! A.src (toValue url)+ ! A.type_ "text/javascript"+ $ mempty+ KaTeX js css ->+ (H.script ! A.src (toValue js) $ mempty) <>+ (H.link ! A.rel "stylesheet" ! A.href (toValue css)) <>+ (H.script ! A.type_ "text/javascript" $ toHtml renderKaTeX)+ _ -> case lookup "mathml-script" (writerVariables opts) of+ Just s | not (writerHtml5 opts) ->+ H.script ! A.type_ "text/javascript"+ $ preEscapedString+ ("/*<![CDATA[*/\n" ++ s ++ "/*]]>*/\n")+ | otherwise -> mempty+ Nothing -> mempty let context = (if stHighlighting st then defField "highlighting-css" (styleToCss $ writerHighlightStyle opts)@@ -647,7 +645,7 @@ AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center"- AlignDefault -> "left"+ AlignDefault -> "" tableItemToHtml :: WriterOptions -> (Html -> Html)@@ -660,7 +658,10 @@ let attribs = if writerHtml5 opts then A.style (toValue $ "text-align: " ++ alignStr ++ ";") else A.align (toValue alignStr)- return $ (tag' ! attribs $ contents) >> nl opts+ let tag'' = if null alignStr+ then tag'+ else tag' ! attribs+ return $ (tag'' $ contents) >> nl opts toListItems :: WriterOptions -> [Html] -> [Html] toListItems opts items = map (toListItem opts) items ++ [nl opts]
src/Text/Pandoc/Writers/LaTeX.hs view
@@ -113,12 +113,7 @@ (fmap (render colwidth) . inlineListToLaTeX) meta let bookClasses = ["memoir","book","report","scrreprt","scrbook"]- let documentClass = case P.parse (do P.skipMany (P.satisfy (/='\\'))- P.string "\\documentclass"- P.skipMany (P.satisfy (/='{'))- P.char '{'- P.manyTill P.letter (P.char '}')) "template"- template of+ let documentClass = case P.parse pDocumentClass "template" template of Right r -> r Left _ -> "" case lookup "documentclass" (writerVariables options) `mplus`@@ -408,7 +403,7 @@ blockToLaTeX (Plain lst) = inlineListToLaTeX $ dropWhile isLineBreakOrSpace lst -- title beginning with fig: indicates that the image is a figure-blockToLaTeX (Para [Image attr txt (src,'f':'i':'g':':':tit)]) = do+blockToLaTeX (Para [Image attr@(ident, _, _) txt (src,'f':'i':'g':':':tit)]) = do inNote <- gets stInNote modify $ \st -> st{ stInMinipage = True, stNotes = [] } capt <- inlineListToLaTeX txt@@ -420,13 +415,14 @@ else brackets <$> inlineListToLaTeX (walk deNote txt) img <- inlineToLaTeX (Image attr txt (src,tit)) let footnotes = notesToLaTeX notes+ figure <- refLabel ident $ cr <>+ "\\begin{figure}[htbp]" $$ "\\centering" $$ img $$+ ("\\caption" <> captForLof <> braces capt) $$+ "\\end{figure}" <> cr return $ if inNote -- can't have figures in notes then "\\begin{center}" $$ img $+$ capt $$ "\\end{center}"- else "\\begin{figure}[htbp]" $$ "\\centering" $$ img $$- ("\\caption" <> captForLof <> braces capt) $$- "\\end{figure}" $$- footnotes+ else figure $$ footnotes -- . . . indicates pause in beamer slides blockToLaTeX (Para [Str ".",Space,Str ".",Space,Str "."]) = do beamer <- writerBeamer `fmap` gets stOptions@@ -576,26 +572,29 @@ blockToLaTeX (Table caption aligns widths heads rows) = do headers <- if all null heads then return empty- else ($$ "\\midrule\n") `fmap`- (tableRowToLaTeX True aligns widths) heads+ else do+ contents <- (tableRowToLaTeX True aligns widths) heads+ return ("\\toprule" $$ contents $$ "\\midrule") let endhead = if all null heads then empty else text "\\endhead"+ let endfirsthead = if all null heads+ then empty+ else text "\\endfirsthead" captionText <- inlineListToLaTeX caption let capt = if isEmpty captionText then empty- else text "\\caption" <> braces captionText- <> "\\tabularnewline\n\\toprule\n"- <> headers- <> "\\endfirsthead"+ else text "\\caption" <> braces captionText <> "\\tabularnewline"+ $$ headers+ $$ endfirsthead rows' <- mapM (tableRowToLaTeX False aligns widths) rows let colDescriptors = text $ concat $ map toColDescriptor aligns modify $ \s -> s{ stTable = True }- return $ "\\begin{longtable}[c]" <>+ return $ "\\begin{longtable}[]" <> braces ("@{}" <> colDescriptors <> "@{}") -- the @{} removes extra space at beginning and end $$ capt- $$ "\\toprule"+ $$ (if all null heads then "\\toprule" else empty) $$ headers $$ endhead $$ vcat rows'@@ -717,9 +716,8 @@ -> Int -> [Inline] -> State WriterState Doc-sectionHeader unnumbered ref level lst = do+sectionHeader unnumbered ident level lst = do txt <- inlineListToLaTeX lst- lab <- text `fmap` toLabel ref plain <- stringToLaTeX TextString $ foldl (++) "" $ map stringify lst let noNote (Note _) = Str "" noNote x = x@@ -742,16 +740,6 @@ book <- gets stBook opts <- gets stOptions let level' = if book || writerChapters opts then level - 1 else level- internalLinks <- gets stInternalLinks- let refLabel x = (if ref `elem` internalLinks- then text "\\hypertarget"- <> braces lab- <> braces x- else x)- let headerWith x y = refLabel $ text x <> y <>- if null ref- then empty- else text "\\label" <> braces lab let sectionType = case level' of 0 | writerBeamer opts -> "part" | otherwise -> "chapter"@@ -767,16 +755,31 @@ -- needed for \paragraph, \subparagraph in quote environment -- see http://tex.stackexchange.com/questions/169830/ else empty+ stuffing' <- refLabel ident $ text ('\\':sectionType) <> stuffing return $ if level' > 5 then txt- else prefix $$- headerWith ('\\':sectionType) stuffing+ else prefix $$ stuffing' $$ if unnumbered then "\\addcontentsline{toc}" <> braces (text sectionType) <> braces txtNoNotes else empty +-- | Append label to x and wrap in hypertarget+refLabel :: String -> Doc -> State WriterState Doc+refLabel ident x = do+ ref <- text `fmap` toLabel ident+ internalLinks <- gets stInternalLinks+ let hypertarget y = if ident `elem` internalLinks+ then text "\\hypertarget"+ <> braces ref+ <> braces y+ else y+ label = if null ident+ then empty+ else text "\\label" <> braces ref+ return $ hypertarget $ x <> label+ -- | Convert list of inline elements to LaTeX. inlineListToLaTeX :: [Inline] -- ^ Inlines to convert -> State WriterState Doc@@ -1260,3 +1263,24 @@ deNote :: Inline -> Inline deNote (Note _) = RawInline (Format "latex") "" deNote x = x++pDocumentOptions :: P.Parsec String () [String]+pDocumentOptions = do+ P.char '['+ opts <- P.sepBy+ (P.many $ P.spaces *> P.noneOf (" ,]" :: String) <* P.spaces)+ (P.char ',')+ P.char ']'+ return opts++pDocumentClass :: P.Parsec String () String+pDocumentClass =+ do P.skipMany (P.satisfy (/='\\'))+ P.string "\\documentclass"+ classOptions <- pDocumentOptions <|> return []+ if ("article" :: String) `elem` classOptions+ then return "article"+ else do P.skipMany (P.satisfy (/='{'))+ P.char '{'+ P.manyTill P.letter (P.char '}')+
src/Text/Pandoc/Writers/Markdown.hs view
@@ -53,6 +53,7 @@ import qualified Data.HashMap.Strict as H import qualified Data.Vector as V import qualified Data.Text as T+import qualified Data.Set as Set type Notes = [[Block]] type Ref = ([Inline], Target, Attr)@@ -61,11 +62,11 @@ , stRefs :: Refs , stRefShortcutable :: Bool , stInList :: Bool- , stIds :: [String]+ , stIds :: Set.Set String , stPlain :: Bool } instance Default WriterState where def = WriterState{ stNotes = [], stRefs = [], stRefShortcutable = True,- stInList = False, stIds = [], stPlain = False }+ stInList = False, stIds = Set.empty, stPlain = False } -- | Convert Pandoc to Markdown. writeMarkdown :: WriterOptions -> Pandoc -> String@@ -116,7 +117,7 @@ dat <> cr yamlMetadataBlock :: Value -> Doc-yamlMetadataBlock v = "---" $$ (jsonToYaml v) $$ "..."+yamlMetadataBlock v = "---" $$ (jsonToYaml v) $$ "---" jsonToYaml :: Value -> Doc jsonToYaml (Object hashmap) =@@ -364,7 +365,7 @@ -- so we know whether to print an explicit identifier ids <- gets stIds let autoId = uniqueIdent inlines ids- modify $ \st -> st{ stIds = autoId : ids }+ modify $ \st -> st{ stIds = Set.insert autoId ids } let attr' = case attr of ("",[],[]) -> empty (id',[],[]) | isEnabled Ext_auto_identifiers opts
src/Text/Pandoc/Writers/Org.hs view
@@ -102,6 +102,10 @@ , ('\x2026',"...") ] ++ backslashEscapes "^_" +isRawFormat :: Format -> Bool+isRawFormat f =+ f == Format "latex" || f == Format "tex" || f == Format "org"+ -- | Convert Pandoc block element to Org. blockToOrg :: Block -- ^ Block element -> State WriterState Doc@@ -129,7 +133,7 @@ blockToOrg (RawBlock "html" str) = return $ blankline $$ "#+BEGIN_HTML" $$ nest 2 (text str) $$ "#+END_HTML" $$ blankline-blockToOrg (RawBlock f str) | f `elem` ["org", "latex", "tex"] =+blockToOrg (RawBlock f str) | isRawFormat f = return $ text str blockToOrg (RawBlock _ _) = return empty blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline@@ -271,7 +275,8 @@ return $ if t == InlineMath then "$" <> text str <> "$" else "$$" <> text str <> "$$"-inlineToOrg (RawInline f str) | f == "tex" || f == "latex" = return $ text str+inlineToOrg (RawInline f str) | isRawFormat f =+ return $ text str inlineToOrg (RawInline _ _) = return empty inlineToOrg (LineBreak) = return (text "\\\\" <> cr) inlineToOrg Space = return space
+ src/Text/Pandoc/Writers/TEI.hs view
@@ -0,0 +1,320 @@+{-# LANGUAGE OverloadedStrings, PatternGuards #-}+{-+Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Text.Pandoc.Writers.Docbook+ Copyright : Copyright (C) 2006-2015 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to Docbook XML.+-}+module Text.Pandoc.Writers.TEI (writeTEI) where+import Text.Pandoc.Definition+import Text.Pandoc.XML+import Text.Pandoc.Shared+import Text.Pandoc.Writers.Shared+import Text.Pandoc.Options+import Text.Pandoc.Templates (renderTemplate')+import Data.List ( stripPrefix, isPrefixOf, isSuffixOf )+import Data.Char ( toLower )+import Text.Pandoc.Highlighting ( languages, languagesByExtension )+import Text.Pandoc.Pretty+import Text.Pandoc.ImageSize+import qualified Text.Pandoc.Builder as B++-- | Convert list of authors to a docbook <author> section+authorToTEI :: WriterOptions -> [Inline] -> B.Inlines+authorToTEI opts name' =+ let name = render Nothing $ inlinesToTEI opts name'+ colwidth = if writerWrapText opts == WrapAuto+ then Just $ writerColumns opts+ else Nothing+ in B.rawInline "tei" $ render colwidth $+ inTagsSimple "author" (text $ escapeStringForXML name)++-- | Convert Pandoc document to string in Docbook format.+writeTEI :: WriterOptions -> Pandoc -> String+writeTEI opts (Pandoc meta blocks) =+ let elements = hierarchicalize blocks+ colwidth = if writerWrapText opts == WrapAuto+ then Just $ writerColumns opts+ else Nothing+ render' = render colwidth+ opts' = if "/book>" `isSuffixOf`+ (trimr $ writerTemplate opts)+ then opts{ writerChapters = True }+ else opts+ startLvl = if writerChapters opts' then 0 else 1+ auths' = map (authorToTEI opts) $ docAuthors meta+ meta' = B.setMeta "author" auths' meta+ Just metadata = metaToJSON opts+ (Just . render colwidth . (vcat .+ (map (elementToTEI opts' startLvl)) . hierarchicalize))+ (Just . render colwidth . inlinesToTEI opts')+ meta'+ main = render' $ vcat (map (elementToTEI opts' startLvl) elements)+ context = defField "body" main+ $ defField "mathml" (case writerHTMLMathMethod opts of+ MathML _ -> True+ _ -> False)+ $ metadata+ in if writerStandalone opts+ then renderTemplate' (writerTemplate opts) context+ else main++-- | Convert an Element to TEI.+elementToTEI :: WriterOptions -> Int -> Element -> Doc+elementToTEI opts _ (Blk block) = blockToTEI opts block+elementToTEI opts lvl (Sec _ _num (id',_,_) title elements) =+ -- TEI doesn't allow sections with no content, so insert some if needed+ let elements' = if null elements+ then [Blk (Para [])]+ else elements+ divType = case lvl of+ n | n == 0 -> "chapter"+ | n >= 1 && n <= 5 -> "level" ++ show n+ | otherwise -> "section"+ in inTags True "div" [("type", divType) | not (null id')] $+-- ("id", writerIdentifierPrefix opts ++ id') | not (null id')] $+ inTagsSimple "head" (inlinesToTEI opts title) $$+ vcat (map (elementToTEI opts (lvl + 1)) elements')++-- | Convert a list of Pandoc blocks to TEI.+blocksToTEI :: WriterOptions -> [Block] -> Doc+blocksToTEI opts = vcat . map (blockToTEI opts)++-- | Auxiliary function to convert Plain block to Para.+plainToPara :: Block -> Block+plainToPara (Plain x) = Para x+plainToPara x = x++-- | Convert a list of pairs of terms and definitions into a TEI +-- list with labels and items.+deflistItemsToTEI :: WriterOptions -> [([Inline],[[Block]])] -> Doc+deflistItemsToTEI opts items =+ vcat $ map (\(term, defs) -> deflistItemToTEI opts term defs) items++-- | Convert a term and a list of blocks into a TEI varlistentry.+deflistItemToTEI :: WriterOptions -> [Inline] -> [[Block]] -> Doc+deflistItemToTEI opts term defs =+ let def' = concatMap (map plainToPara) defs+ in inTagsIndented "label" (inlinesToTEI opts term) $$+ inTagsIndented "item" (blocksToTEI opts def')++-- | Convert a list of lists of blocks to a list of TEI list items.+listItemsToTEI :: WriterOptions -> [[Block]] -> Doc+listItemsToTEI opts items = vcat $ map (listItemToTEI opts) items++-- | Convert a list of blocks into a TEI list item.+listItemToTEI :: WriterOptions -> [Block] -> Doc+listItemToTEI opts item =+ inTagsIndented "item" $ blocksToTEI opts $ map plainToPara item++imageToTEI :: WriterOptions -> Attr -> String -> Doc+imageToTEI _ attr src = selfClosingTag "graphic" $+ ("url", src) : idAndRole attr ++ dims+ where+ dims = go Width "width" ++ go Height "depth"+ go dir dstr = case (dimension dir attr) of+ Just a -> [(dstr, show a)]+ Nothing -> []++-- | Convert a Pandoc block element to TEI.+blockToTEI :: WriterOptions -> Block -> Doc+blockToTEI _ Null = empty+-- Add ids to paragraphs in divs with ids - this is needed for+-- pandoc-citeproc to get link anchors in bibliographies:+blockToTEI opts (Div (ident,_,_) [Para lst]) =+ let attribs = [("id", ident) | not (null ident)] in+ inTags False "p" attribs $ inlinesToTEI opts lst+blockToTEI opts (Div _ bs) = blocksToTEI opts $ map plainToPara bs+blockToTEI _ (Header _ _ _) = empty -- should not occur after hierarchicalize+-- For TEI simple, text must be within containing block element, so+-- we use plainToPara to ensure that Plain text ends up contained by+-- something.+blockToTEI opts (Plain lst) = blockToTEI opts $ Para lst+-- title beginning with fig: indicates that the image is a figure+--blockToTEI opts (Para [Image attr txt (src,'f':'i':'g':':':_)]) =+-- let alt = inlinesToTEI opts txt+-- capt = if null txt+-- then empty+-- else inTagsSimple "title" alt+-- in inTagsIndented "figure" $+-- capt $$+-- (inTagsIndented "mediaobject" $+-- (inTagsIndented "imageobject"+-- (imageToTEI opts attr src)) $$+-- inTagsSimple "textobject" (inTagsSimple "phrase" alt))+blockToTEI opts (Para lst) =+ inTags False "p" [] $ inlinesToTEI opts lst+blockToTEI opts (BlockQuote blocks) =+ inTagsIndented "quote" $ blocksToTEI opts blocks+blockToTEI _ (CodeBlock (_,classes,_) str) =+ text ("<ab type='codeblock " ++ lang ++ "'>") <> cr <>+ flush (text (escapeStringForXML str) <> cr <> text "</ab>")+ where lang = if null langs+ then ""+ else escapeStringForXML (head langs) + isLang l = map toLower l `elem` map (map toLower) languages+ langsFrom s = if isLang s+ then [s]+ else languagesByExtension . map toLower $ s+ langs = concatMap langsFrom classes+blockToTEI opts (BulletList lst) =+ let attribs = [("type", "unordered")]+ in inTags True "list" attribs $ listItemsToTEI opts lst+blockToTEI _ (OrderedList _ []) = empty+blockToTEI opts (OrderedList (start, numstyle, _) (first:rest)) =+ let attribs = case numstyle of+ DefaultStyle -> []+ Decimal -> [("type", "ordered:arabic")]+ Example -> [("type", "ordered:arabic")]+ UpperAlpha -> [("type", "ordered:upperalpha")]+ LowerAlpha -> [("type", "ordered:loweralpha")]+ UpperRoman -> [("type", "ordered:upperroman")]+ LowerRoman -> [("type", "ordered:lowerroman")]+ items = if start == 1+ then listItemsToTEI opts (first:rest)+ else (inTags True "item" [("n",show start)]+ (blocksToTEI opts $ map plainToPara first)) $$+ listItemsToTEI opts rest+ in inTags True "list" attribs items+blockToTEI opts (DefinitionList lst) =+ let attribs = [("type", "definition")]+ in inTags True "list" attribs $ deflistItemsToTEI opts lst+blockToTEI _ (RawBlock f str)+ | f == "tei" = text str -- raw TEI block (should such a thing exist).+-- | f == "html" = text str -- allow html for backwards compatibility+ | otherwise = empty+blockToTEI _ HorizontalRule =+ selfClosingTag "milestone" [("unit","undefined"), ("type","separator"),("rendition","line")]++-- | TEI Tables+-- TEI Simple's tables are composed of cells and rows; other +-- table info in the AST is here lossily discard.+blockToTEI opts (Table _ _ _ headers rows) =+ let+ headers' = tableHeadersToTEI opts headers+-- headers' = if all null headers+-- then return empty+-- else tableRowToTEI opts headers+ in+ inTags True "table" [] $ + vcat $ [headers'] <> map (tableRowToTEI opts) rows ++tableRowToTEI :: WriterOptions+ -> [[Block]]+ -> Doc+tableRowToTEI opts cols =+ inTagsIndented "row" $ vcat $ map (tableItemToTEI opts) cols++tableHeadersToTEI :: WriterOptions+ -> [[Block]]+ -> Doc+tableHeadersToTEI opts cols =+ inTags True "row" [("role","label")] $ vcat $ map (tableItemToTEI opts) cols++tableItemToTEI :: WriterOptions+ -> [Block]+ -> Doc+tableItemToTEI opts item =+ inTags False "cell" [] $ vcat $ map (blockToTEI opts) item++-- | Convert a list of inline elements to TEI.+inlinesToTEI :: WriterOptions -> [Inline] -> Doc+inlinesToTEI opts lst = hcat $ map (inlineToTEI opts) lst++-- | Convert an inline element to TEI.+inlineToTEI :: WriterOptions -> Inline -> Doc+inlineToTEI _ (Str str) = text $ escapeStringForXML str+inlineToTEI opts (Emph lst) =+ inTags False "hi" [("rendition","simple:italic")] $ inlinesToTEI opts lst+inlineToTEI opts (Strong lst) =+ inTags False "hi" [("rendition", "simple:bold")] $ inlinesToTEI opts lst+inlineToTEI opts (Strikeout lst) =+ inTags False "hi" [("rendition", "simple:strikethrough")] $+ inlinesToTEI opts lst+inlineToTEI opts (Superscript lst) =+ inTags False "hi" [("rendition", "simple:superscript")] $ inlinesToTEI opts lst+inlineToTEI opts (Subscript lst) =+ inTags False "hi" [("rendition", "simple:subscript")] $ inlinesToTEI opts lst+inlineToTEI opts (SmallCaps lst) =+ inTags False "hi" [("rendition", "simple:smallcaps")] $+ inlinesToTEI opts lst+inlineToTEI opts (Quoted _ lst) =+ inTagsSimple "quote" $ inlinesToTEI opts lst+inlineToTEI opts (Cite _ lst) =+ inlinesToTEI opts lst+inlineToTEI opts (Span _ ils) =+ inlinesToTEI opts ils+inlineToTEI _ (Code _ str) =+ inTags False "seg" [("type","code")] $ text (escapeStringForXML str)+-- Distinguish display from inline math by wrapping the former in a "figure."+inlineToTEI _ (Math t str) =+ case t of+ InlineMath -> inTags False "formula" [("notation","TeX")] $+ text (str)+ DisplayMath -> inTags True "figure" [("type","math")] $+ inTags False "formula" [("notation","TeX")] $ text (str)+ +inlineToTEI _ (RawInline f x) | f == "tei" = text x+ | otherwise = empty+inlineToTEI _ LineBreak = selfClosingTag "lb" []+inlineToTEI _ Space = space+-- because we use \n for LineBreak, we can't do soft breaks:+inlineToTEI _ SoftBreak = space+inlineToTEI opts (Link attr txt (src, _))+ | Just email <- stripPrefix "mailto:" src =+ let emailLink = text $+ escapeStringForXML $ email+ in case txt of+ [Str s] | escapeURI s == email -> emailLink+ _ -> inlinesToTEI opts txt <+>+ char '(' <> emailLink <> char ')'+ | otherwise =+ (if isPrefixOf "#" src+ then inTags False "ref" $ ("target", drop 1 src) : idAndRole attr+ else inTags False "ref" $ ("target", src) : idAndRole attr ) $+ inlinesToTEI opts txt+inlineToTEI opts (Image attr description (src, tit)) =+ let titleDoc = if null tit+ then empty+ else inTags False "figDesc" [] (text $ escapeStringForXML tit)+ imageDesc = if null description+ then empty+ else inTags False "head" [] (inlinesToTEI opts description)+ in inTagsIndented "figure" $ imageDesc $$+ imageToTEI opts attr src $$ titleDoc+inlineToTEI opts (Note contents) =+ inTagsIndented "note" $ blocksToTEI opts contents++idAndRole :: Attr -> [(String, String)]+idAndRole (id',cls,_) = ident ++ role+ where+ ident = if null id'+ then []+ else [("id", id')]+ role = if null cls+ then []+ else [("role", unwords cls)]+
src/Text/Pandoc/Writers/Texinfo.hs view
@@ -43,13 +43,14 @@ import Text.Pandoc.ImageSize import Network.URI ( isURI, unEscapeString ) import System.FilePath+import qualified Data.Set as Set data WriterState = WriterState { stStrikeout :: Bool -- document contains strikeout , stSuperscript :: Bool -- document contains superscript , stSubscript :: Bool -- document contains subscript , stEscapeComma :: Bool -- in a context where we need @comma- , stIdentifiers :: [String] -- header ids used already+ , stIdentifiers :: Set.Set String -- header ids used already , stOptions :: WriterOptions -- writer options } @@ -64,7 +65,7 @@ evalState (pandocToTexinfo options $ wrapTop document) $ WriterState { stStrikeout = False, stSuperscript = False, stEscapeComma = False, stSubscript = False,- stIdentifiers = [], stOptions = options}+ stIdentifiers = Set.empty, stOptions = options} -- | Add a "Top" node around the document, needed by Texinfo. wrapTop :: Pandoc -> Pandoc@@ -215,7 +216,7 @@ txt <- inlineListToTexinfo lst idsUsed <- gets stIdentifiers let id' = uniqueIdent lst idsUsed- modify $ \st -> st{ stIdentifiers = id' : idsUsed }+ modify $ \st -> st{ stIdentifiers = Set.insert id' idsUsed } return $ if (level > 0) && (level <= 4) then blankline <> text "@node " <> node $$ text (seccmd level) <> txt $$
stack.yaml view
@@ -7,10 +7,9 @@ network-uri: true packages: - '.'-extra-deps:-- 'cmark-0.5.0'-- 'pandoc-citeproc-0.9'-- 'pandoc-types-1.16.0.1'-# Use older aeson to avoid excessive memory use in compilation:-- 'aeson-0.8.0.2'-resolver: lts-4.0+extra-deps: []+# to compile against aeson 0.11.0.0:+# - 'aeson-0.11.0.0'+# - 'fail-4.9.0.0'+# - 'pandoc-types-1.16.1'+resolver: lts-5.8
tests/Tests/Old.hs view
@@ -162,7 +162,7 @@ [ test "reader" ["-r", "twiki", "-w", "native", "-s"] "twiki-reader.twiki" "twiki-reader.native" ] , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)- [ "opendocument" , "context" , "texinfo", "icml"+ [ "opendocument" , "context" , "texinfo", "icml", "tei" , "man" , "plain" , "rtf", "org", "asciidoc" ] , testGroup "writers-lang-and-dir"
tests/Tests/Readers/Docx.hs view
@@ -111,6 +111,10 @@ "docx/links.docx" "docx/links.native" , testCompare+ "normalizing adjacent hyperlinks"+ "docx/adjacent_links.docx"+ "docx/adjacent_links.native"+ , testCompare "inline image" "docx/image.docx" "docx/image_no_embed.native"@@ -165,9 +169,13 @@ "docx/already_auto_ident.docx" "docx/already_auto_ident.native" , testCompare- "numbered headers automatically made into list"+ "single numbered item not made into list" "docx/numbered_header.docx" "docx/numbered_header.native"+ , testCompare+ "enumerated headers not made into numbered list"+ "docx/enumerated_headings.docx"+ "docx/enumerated_headings.native" , testCompare "i18n blocks (headers and blockquotes)" "docx/i18n_blocks.docx"
tests/Tests/Readers/HTML.hs view
@@ -15,11 +15,14 @@ tests :: [Test] tests = [ testGroup "base tag" [ test html "simple" $- "<head><base href=\"http://www.w3schools.com/images\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?>+ "<head><base href=\"http://www.w3schools.com/images/foo\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?> plain (image "http://www.w3schools.com/images/stickman.gif" "" (text "Stickman")) , test html "slash at end of base" $ "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?> plain (image "http://www.w3schools.com/images/stickman.gif" "" (text "Stickman"))+ , test html "slash at beginning of href" $+ "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"/stickman.gif\" alt=\"Stickman\"></head>" =?>+ plain (image "http://www.w3schools.com/stickman.gif" "" (text "Stickman")) , test html "absolute URL" $ "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"http://example.com/stickman.gif\" alt=\"Stickman\"></head>" =?> plain (image "http://example.com/stickman.gif" "" (text "Stickman"))
tests/Tests/Readers/Org.hs view
@@ -190,6 +190,10 @@ "[[./sunset.jpg]]" =?> (para $ image "./sunset.jpg" "" "") + , "Image with explicit file: prefix" =:+ "[[file:sunrise.jpg]]" =?>+ (para $ image "sunrise.jpg" "" "")+ , "Explicit link" =: "[[http://zeitlens.com/][pseudo-random /nonsense/]]" =?> (para $ link "http://zeitlens.com/" ""@@ -635,11 +639,11 @@ ] =?> para (image "edward.jpg" "fig:goodguy" "A very courageous man.") - , "Unnamed figure" =:- unlines [ "#+caption: A great whistleblower."- , "[[snowden.png]]"+ , "Figure with no name" =:+ unlines [ "#+caption: I've been through the desert on this"+ , "[[horse.png]]" ] =?>- para (image "snowden.png" "" "A great whistleblower.")+ para (image "horse.png" "fig:" "I've been through the desert on this") , "Figure with `fig:` prefix in name" =: unlines [ "#+caption: Used as a metapher in evolutionary biology."
+ tests/Tests/Writers/TEI.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.TEI (tests) where++import Test.Framework+import Text.Pandoc.Builder+import Text.Pandoc+import Tests.Helpers+import Tests.Arbitrary()++{-+ "my test" =: X =?> Y++is shorthand for++ test html "my test" $ X =?> Y++which is in turn shorthand for++ test html "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+ => String -> (a, String) -> Test+(=:) = test (writeTEI def . toPandoc)++tests :: [Test]+tests = [ testGroup "block elements"+ ["para" =: para "Lorem ipsum cetera."+ =?> "<p>Lorem ipsum cetera.</p>"+ ]+ , testGroup "inlines"+ [+ "Emphasis" =: emph ("emphasized")+ =?> "<p><hi rendition=\"simple:italic\">emphasized</hi></p>"+ ,"SingleQuoted" =: singleQuoted (text "quoted material")+ =?> "<p><quote>quoted material</quote></p>"+ ,"DoubleQuoted" =: doubleQuoted (text "quoted material")+ =?> "<p><quote>quoted material</quote></p>"+ ,"NestedQuoted" =: doubleQuoted (singleQuoted (text "quoted material"))+ =?> "<p><quote><quote>quoted material</quote></quote></p>"+ ]+ ]
+ tests/docx/adjacent_links.docx view
binary file changed (absent → 8538 bytes)
+ tests/docx/adjacent_links.native view
@@ -0,0 +1,1 @@+[Para [Str "Le",Space,Str "plus",Space,Str "int\233ressant",Space,Str "\233tant",Space,Str "sans",Space,Str "doute",Space,Str "le",Space,Str "Marsan,",Space,Str "propos\233",Space,Str "par",Space,Str "Claude",Space,Str "Marsan",Space,Str "en",Space,Str "1976",Space,Str "qui",Space,Str "avait",Space,Str "m\234me",Space,Str "fait",Space,Str "l'objet",Space,Str "d'une",Space,Str "norme,",Space,Str "mais",Space,Str "qui",Space,Str "n'a",Space,Str "pas",Space,Str "du",Space,Str "tout",Space,Str "\233t\233",Space,Str "adopt\233",Space,Str "\224",Space,Str "cause",Space,Str "des",Space,Str "habitudes",Space,Str "trop",Space,Str "ancr\233es",Space,Str "et",Space,Str "qui",Space,Str "a",Space,Str "fini",Space,Str "par",Space,Str "tomber",Space,Str "dans",Space,Str "l'oubli,",Space,Str "gros",Space,Str "clin",Space,Str "d'\339il",Space,Str "\224",Space,Str "cela",Space,Str "d'ailleurs",Space,Str "dans",Space,Str "le",Space,Str "film",Space,Link ("",[],[]) [Emph [Str "\"Le",Space,Str "nom",Space,Str "des",Space,Str "gens\""]] ("http://www.allocine.fr/film/fichefilm_gen_cfilm=172167.html",""),Str ".",Space,Str "D\8217ailleurs",Space,Str "l\8217\233tat,",Space,Str "bien",Space,Str "conscient",Space,Str "que",Space,Str "tous",Space,Str "les",Space,Str "fran\231ais",Space,Str "\233crivent",Space,Str "sur",Space,Str "des",Space,Str "claviers",Space,Str "compl\232tement",Space,Str "inadapt\233s,",Space,Link ("",[],[]) [Emph [Str "tente",Space,Str "encore",Space,Str "une",Space,Str "fois",Space,Str "de",Space,Str "faire",Space,Str "une",Space,Str "norme",Space,Str "en",Space,Str "ce",Space,Str "moment",Space,Str "m\234me"]] ("http://www.appy-geek.com/Web/ArticleWeb.aspx?regionid=2&articleid=56103389&source=messenger",""),Str "."]]
+ tests/docx/enumerated_headings.docx view
binary file changed (absent → 12539 bytes)
+ tests/docx/enumerated_headings.native view
@@ -0,0 +1,4 @@+[Header 1 ("h1",[],[]) [Str "H1"]+,Header 2 ("h2",[],[]) [Str "H2"]+,Header 3 ("h3",[],[]) [Str "H3"]+,Para [Str "And",Space,Str "some",Space,Str "text"]]
tests/pipe-tables.native view
@@ -98,4 +98,18 @@ ,Para [Str "Pipe",Space,Str "table",Space,Str "with",Space,Str "no",Space,Str "body:"] ,Table [] [AlignDefault] [0.0] [[Plain [Str "Header"]]]- []]+ []+,Para [Str "Pipe",Space,Str "table",Space,Str "with",Space,Str "tricky",Space,Str "cell",Space,Str "contents",Space,Str "(see",Space,Str "#2765):"]+,Table [] [AlignLeft,AlignRight,AlignRight] [0.0,0.0,0.0]+ [[]+ ,[Plain [Str "IP_gene8-_1st"]]+ ,[Plain [Str "IP_gene8+_1st"]]]+ [[[Plain [Str "IP_gene8-_1st"]]+ ,[Plain [Str "1.0000000"]]+ ,[Plain [Str "0.4357325"]]]+ ,[[Plain [Str "IP_gene8+_1st"]]+ ,[Plain [Str "0.4357325"]]+ ,[Plain [Str "1.0000000"]]]+ ,[[Plain [Str "foo",Code ("",[],[]) "bar|baz"]]+ ,[Plain [Str "and|escaped"]]+ ,[Plain [Str "3.0000000"]]]]]
tests/pipe-tables.txt view
@@ -72,3 +72,11 @@ | Header | | ------ | +Pipe table with tricky cell contents (see #2765):++| | IP_gene8-_1st| IP_gene8+_1st|+|:--------------|-------------:|-------------:|+|IP_gene8-_1st | 1.0000000| 0.4357325|+|IP_gene8+_1st | 0.4357325| 1.0000000|+|foo`bar|baz` | and\|escaped | 3.0000000|+
tests/tables.html view
@@ -6,7 +6,7 @@ <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>-<th align="left">Default</th>+<th>Default</th> </tr> </thead> <tbody>@@ -14,19 +14,19 @@ <td align="right">12</td> <td align="left">12</td> <td align="center">12</td>-<td align="left">12</td>+<td>12</td> </tr> <tr class="even"> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td>-<td align="left">123</td>+<td>123</td> </tr> <tr class="odd"> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>-<td align="left">1</td>+<td>1</td> </tr> </tbody> </table>@@ -37,7 +37,7 @@ <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>-<th align="left">Default</th>+<th>Default</th> </tr> </thead> <tbody>@@ -45,19 +45,19 @@ <td align="right">12</td> <td align="left">12</td> <td align="center">12</td>-<td align="left">12</td>+<td>12</td> </tr> <tr class="even"> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td>-<td align="left">123</td>+<td>123</td> </tr> <tr class="odd"> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>-<td align="left">1</td>+<td>1</td> </tr> </tbody> </table>@@ -69,7 +69,7 @@ <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>-<th align="left">Default</th>+<th>Default</th> </tr> </thead> <tbody>@@ -77,19 +77,19 @@ <td align="right">12</td> <td align="left">12</td> <td align="center">12</td>-<td align="left">12</td>+<td>12</td> </tr> <tr class="even"> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td>-<td align="left">123</td>+<td>123</td> </tr> <tr class="odd"> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>-<td align="left">1</td>+<td>1</td> </tr> </tbody> </table>@@ -192,13 +192,13 @@ <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td>-<td align="left">Example of a row that spans multiple lines.</td>+<td>Example of a row that spans multiple lines.</td> </tr> <tr class="even"> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>-<td align="left">Here's another one. Note the blank line between rows.</td>+<td>Here's another one. Note the blank line between rows.</td> </tr> </tbody> </table>
tests/tables.latex view
@@ -1,6 +1,6 @@ Simple table with caption: -\begin{longtable}[c]{@{}rlcl@{}}+\begin{longtable}[]{@{}rlcl@{}} \caption{Demonstration of simple table syntax.}\tabularnewline \toprule Right & Left & Center & Default\tabularnewline@@ -18,7 +18,7 @@ Simple table without caption: -\begin{longtable}[c]{@{}rlcl@{}}+\begin{longtable}[]{@{}rlcl@{}} \toprule Right & Left & Center & Default\tabularnewline \midrule@@ -31,7 +31,7 @@ Simple table indented two spaces: -\begin{longtable}[c]{@{}rlcl@{}}+\begin{longtable}[]{@{}rlcl@{}} \caption{Demonstration of simple table syntax.}\tabularnewline \toprule Right & Left & Center & Default\tabularnewline@@ -49,7 +49,7 @@ Multiline table with caption: -\begin{longtable}[c]{@{}clrl@{}}+\begin{longtable}[]{@{}clrl@{}} \caption{Here's the caption. It may span multiple lines.}\tabularnewline \toprule \begin{minipage}[b]{0.13\columnwidth}\centering\strut@@ -98,7 +98,7 @@ Multiline table without caption: -\begin{longtable}[c]{@{}clrl@{}}+\begin{longtable}[]{@{}clrl@{}} \toprule \begin{minipage}[b]{0.13\columnwidth}\centering\strut Centered Header@@ -134,7 +134,7 @@ Table without column headers: -\begin{longtable}[c]{@{}rlcr@{}}+\begin{longtable}[]{@{}rlcr@{}} \toprule 12 & 12 & 12 & 12\tabularnewline 123 & 123 & 123 & 123\tabularnewline@@ -144,7 +144,7 @@ Multiline table without column headers: -\begin{longtable}[c]{@{}clrl@{}}+\begin{longtable}[]{@{}clrl@{}} \toprule \begin{minipage}[t]{0.13\columnwidth}\centering\strut First
tests/test-pandoc.hs view
@@ -24,6 +24,7 @@ import qualified Tests.Writers.AsciiDoc import qualified Tests.Writers.Docx import qualified Tests.Writers.RST+import qualified Tests.Writers.TEI import qualified Tests.Shared import qualified Tests.Walk import Text.Pandoc.Shared (inDirectory)@@ -44,6 +45,7 @@ , testGroup "AsciiDoc" Tests.Writers.AsciiDoc.tests , testGroup "Docx" Tests.Writers.Docx.tests , testGroup "RST" Tests.Writers.RST.tests+ , testGroup "TEI" Tests.Writers.TEI.tests ] , testGroup "Readers" [ testGroup "LaTeX" Tests.Readers.LaTeX.tests
tests/textile-reader.native view
@@ -132,8 +132,11 @@ ,Header 1 ("images",[],[]) [Str "Images"] ,Para [Str "Textile",Space,Str "inline",Space,Str "image",Space,Str "syntax,",Space,Str "like",LineBreak,Str "here",Space,Image ("",[],[]) [Str "this is the alt text"] ("this_is_an_image.png","this is the alt text"),LineBreak,Str "and",Space,Str "here",Space,Image ("",[],[]) [Str ""] ("this_is_an_image.png",""),Str "."] ,Header 1 ("attributes",[],[]) [Str "Attributes"]-,Header 2 ("ident",["bar","foo"],[("style","color:red"),("lang","en")]) [Str "HTML",Space,Str "and",Space,Str "CSS",Space,Str "attributes",Space,Str "are",Space,Str "parsed",Space,Str "in",Space,Str "headers."]-,Para [Str "as",Space,Str "well",Space,Str "as",Space,Strong [Span ("",["foo"],[]) [Str "inline",Space,Str "attributes"]],Space,Str "of",Space,Span ("",[],[("style","color:red")]) [Str "all",Space,Str "kind"]]+,Header 2 ("ident",["bar","foo"],[("style","color:red;"),("lang","en")]) [Str "HTML",Space,Str "and",Space,Str "CSS",Space,Str "attributes",Space,Str "are",Space,Str "parsed",Space,Str "in",Space,Str "headers."]+,Header 2 ("centered",[],[("style","text-align:center;")]) [Str "Centered"]+,Header 2 ("right",[],[("style","text-align:right;")]) [Str "Right"]+,Header 2 ("justified",[],[("lang","en"),("style","color:blue;text-align:justify;")]) [Str "Justified"]+,Para [Str "as",Space,Str "well",Space,Str "as",Space,Strong [Span ("",["foo"],[]) [Str "inline",Space,Str "attributes"]],Space,Str "of",Space,Span ("",[],[("style","color:red;")]) [Str "all",Space,Str "kind"]] ,Para [Str "and",Space,Str "paragraph",Space,Str "attributes,",Space,Str "and",Space,Str "table",Space,Str "attributes."] ,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0] []
tests/textile-reader.textile view
@@ -207,6 +207,12 @@ h2[en]{color:red}(foo bar #ident). HTML and CSS attributes are parsed in headers. +h2=. Centered++h2>. Right++h2<>{color:blue}[en]. Justified+ as well as *(foo)inline attributes* of %{color:red} all kind% p{color:green}. and paragraph attributes, and table attributes.
tests/writer.dokuwiki view
@@ -459,7 +459,7 @@ * $\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 some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ * Here’s one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn’t be math:
tests/writer.markdown view
@@ -4,7 +4,7 @@ - Anonymous date: 'July 17, 2006' title: Pandoc Test Suite-...+--- This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.