packages feed

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 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+
@@ -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
src/Text/Pandoc/Shared.hs view
@@ -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.