aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml186
-rw-r--r--CONTRIBUTING.md29
-rw-r--r--COPYRIGHT2
-rw-r--r--INSTALL2
-rw-r--r--README24
-rw-r--r--data/sample.lua2
m---------data/templates14
-rw-r--r--deb/stack.yaml6
-rw-r--r--osx/stack.yaml6
-rw-r--r--pandoc.cabal11
-rw-r--r--pandoc.hs2
-rw-r--r--src/Text/Pandoc.hs3
-rw-r--r--src/Text/Pandoc/Highlighting.hs3
-rw-r--r--src/Text/Pandoc/Options.hs1
-rw-r--r--src/Text/Pandoc/Parsing.hs12
-rw-r--r--src/Text/Pandoc/Readers/Docx.hs7
-rw-r--r--src/Text/Pandoc/Readers/Docx/Reducible.hs2
-rw-r--r--src/Text/Pandoc/Readers/HTML.hs64
-rw-r--r--src/Text/Pandoc/Readers/LaTeX.hs4
-rw-r--r--src/Text/Pandoc/Readers/Markdown.hs4
-rw-r--r--src/Text/Pandoc/Readers/MediaWiki.hs5
-rw-r--r--src/Text/Pandoc/Readers/Odt/ContentReader.hs3
-rw-r--r--src/Text/Pandoc/Readers/Org.hs63
-rw-r--r--src/Text/Pandoc/Readers/Textile.hs21
-rw-r--r--src/Text/Pandoc/Shared.hs6
-rw-r--r--src/Text/Pandoc/Writers/Custom.hs4
-rw-r--r--src/Text/Pandoc/Writers/Docx.hs7
-rw-r--r--src/Text/Pandoc/Writers/EPUB.hs5
-rw-r--r--src/Text/Pandoc/Writers/HTML.hs7
-rw-r--r--src/Text/Pandoc/Writers/LaTeX.hs28
-rw-r--r--src/Text/Pandoc/Writers/Markdown.hs7
-rw-r--r--src/Text/Pandoc/Writers/TEI.hs320
-rw-r--r--src/Text/Pandoc/Writers/Texinfo.hs7
-rw-r--r--stack.full.yaml6
-rw-r--r--stack.yaml13
-rw-r--r--tests/Tests/Old.hs2
-rw-r--r--tests/Tests/Readers/Docx.hs4
-rw-r--r--tests/Tests/Readers/Org.hs4
-rw-r--r--tests/Tests/Writers/TEI.hs43
-rw-r--r--tests/docx/adjacent_links.docxbin0 -> 8538 bytes
-rw-r--r--tests/docx/adjacent_links.native1
-rw-r--r--tests/tables.html28
-rw-r--r--tests/tables.tei171
-rw-r--r--tests/test-pandoc.hs2
-rw-r--r--tests/textile-reader.native7
-rw-r--r--tests/textile-reader.textile6
-rw-r--r--tests/writer.tei861
-rw-r--r--windows/stack.yaml4
48 files changed, 1784 insertions, 235 deletions
diff --git a/.travis.yml b/.travis.yml
index 2901288e9..9c031216f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,87 +1,125 @@
-# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
-language: c
+# Copy these contents into the root directory of your Github project in a file
+# named .travis.yml
+
+# Use new container infrastructure to enable caching
sudo: false
+# Choose a lightweight base image; we provide our own build tools.
+language: c
+
+# Caching so the next build will be fast too.
cache:
directories:
- - $HOME/.cabsnap
- - $HOME/.cabal/packages
-
-before_cache:
- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
+ - $HOME/.ghc
+ - $HOME/.cabal
+ - $HOME/.stack
+# The different configurations we want to test. We have BUILD=cabal which uses
+# cabal-install, and BUILD=stack which uses Stack. More documentation on each
+# of those below.
+#
+# We set the compiler values here to tell Travis to use a different
+# cache file per set of arguments.
+#
+# If you need to have different apt packages for each combination in the
+# matrix, you can use a line such as:
+# addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
matrix:
include:
- - env: CABALVER=1.16 GHCVER=7.4.2 GHCOPTS=-Werror
- compiler: ": #GHC 7.4.2"
- addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2], sources: [hvr-ghc]}}
- - env: CABALVER=1.16 GHCVER=7.6.3 GHCOPTS=-Werror
- compiler: ": #GHC 7.6.3"
- addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}}
- - env: CABALVER=1.18 GHCVER=7.8.4 GHCOPTS=-Werror
- compiler: ": #GHC 7.8.4"
- addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
- - env: CABALVER=1.22 GHCVER=7.10.2 GHCOPTS=-Werror
- compiler: ": #GHC 7.10.2"
- addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}}
+ # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See:
+ # https://github.com/hvr/multi-ghc-travis
+ - env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16
+ compiler: ": #GHC 7.4.2"
+ addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2], sources: [hvr-ghc]}}
+ - env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16
+ compiler: ": #GHC 7.6.3"
+ addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}}
+ - env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18
+ compiler: ": #GHC 7.8.4"
+ addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
+ - env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22
+ compiler: ": #GHC 7.10.3"
+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
-before_install:
- - unset CC
- - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
+ # Build with the newest GHC and cabal-install. This is an accepted failure,
+ # see below.
+ - env: BUILD=cabal GHCVER=head CABALVER=head
+ compiler: ": #GHC HEAD"
+ addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
-install:
- - cabal --version
- - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
- - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
- then
- zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
- $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
- fi
- - travis_retry cabal update -v
- - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
- - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
- - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
+ # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
+ # variable, such as using --stack-yaml to point to a different file.
+ - env: BUILD=stack ARGS="--resolver lts-5"
+ compiler: ": #stack 7.10.3"
+ addons: {apt: {packages: [ghc-7.10.3], sources: [hvr-ghc]}}
-# check whether current requested install-plan matches cached package-db snapshot
- - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
- then
- echo "cabal build-cache HIT";
- rm -rfv .ghc;
- cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
- cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
- else
- echo "cabal build-cache MISS";
- rm -rf $HOME/.cabsnap;
- mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
- cabal install --only-dependencies --enable-tests --enable-benchmarks;
- fi
-
-# snapshot package-db on cache miss
- - if [ ! -d $HOME/.cabsnap ];
- then
- echo "snapshotting package-db to build-cache";
- mkdir $HOME/.cabsnap;
- cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
- cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
- fi
+ # Nightly builds are allowed to fail
+ - env: BUILD=stack ARGS="--resolver nightly"
+ compiler: ": #stack nightly"
+ addons: {apt: {packages: [libgmp-dev]}}
-# Here starts the actual work to be performed for the package under test;
-# any command which exits with a non-zero exit code causes the build to fail.
-script:
- - if [ -f configure.ac ]; then autoreconf -i; fi
- - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging
- - cabal build --ghc-options=$GHCOPTS # this builds all libraries and executables (including tests/benchmarks)
- - cabal test
- - cabal check
-# Test that a source-distribution can be generated
-# (with cabal >= 1.18 'cabal sdist' would work too):
- - ./dist/setup/setup sdist
+ - env: BUILD=stack ARGS="--resolver lts-5"
+ compiler: ": #stack 7.10.3 osx"
+ os: osx
-# Check that the resulting source distribution can be built & installed.
-# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
-# `cabal install --force-reinstalls dist/*-*.tar.gz`
- - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
- (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
+ - env: BUILD=stack ARGS="--resolver nightly"
+ compiler: ": #stack nightly osx"
+ os: osx
-# EOF
+ allow_failures:
+ - env: BUILD=cabal GHCVER=head CABALVER=head
+ - env: BUILD=stack ARGS="--resolver nightly"
+
+before_install:
+# Using compiler above sets CC to an invalid value, so unset it
+- unset CC
+
+# We want to always allow newer versions of packages when building on GHC HEAD
+- CABALARGS=""
+- if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi
+
+# Download and unpack the stack executable
+- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:$PATH
+- mkdir -p ~/.local/bin
+- |
+ if [ `uname` = "Darwin" ]
+ then
+ curl --insecure -L https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
+ else
+ curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
+ fi
+
+install:
+- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
+- if [ -f configure.ac ]; then autoreconf -i; fi
+- |
+ case "$BUILD" in
+ stack)
+ stack --no-terminal --install-ghc $ARGS test --only-dependencies
+ ;;
+ cabal)
+ cabal --version
+ travis_retry cabal update
+ cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS
+ ;;
+ esac
+
+script:
+- |
+ case "$BUILD" in
+ stack)
+ stack --no-terminal $ARGS test --haddock --no-haddock-deps
+ ;;
+ cabal)
+ cabal configure --enable-tests --enable-benchmarks -v2 --ghc-options="-O0 -Werror"
+ cabal build
+ cabal check || [ "$CABALVER" == "1.16" ]
+ cabal test
+ cabal copy
+ # cabal sdist fails on cabal 1.16:
+ cabal sdist || [ "$CABALVER" == "1.16" ]
+ SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz && \
+ (cd dist && cabal install --force-reinstalls "$SRC_TGZ" || \
+ [ "$CABALVER" == "1.16" ])
+ ;;
+ esac
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index eff033057..f39acab10 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -145,21 +145,40 @@ Tests
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
@@ -266,3 +285,5 @@ The library is structured as follows:
[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
+
diff --git a/COPYRIGHT b/COPYRIGHT
index 19b532129..c94f4fd5b 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -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:
diff --git a/INSTALL b/INSTALL
index 3cb428db9..319c23d43 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,7 @@ https://github.com/jgm/pandoc/wiki/Installing-the-development-version-of-pandoc
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
diff --git a/README b/README
index 6d785721b..f5179dc89 100644
--- a/README
+++ b/README
@@ -22,7 +22,7 @@ markup], [Haddock markup], [OPML], [Emacs Org mode], [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],
+[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 @@ Markdown can be expected to be lossy.
[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 @@ General options
`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
@@ -471,7 +472,7 @@ General writer options
`-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.
@@ -579,7 +580,7 @@ General writer options
: 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`.
@@ -715,7 +716,7 @@ Options affecting specific writers
`-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*
@@ -1090,7 +1091,7 @@ Language variables
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,8 +3378,7 @@ variants are supported:
`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`.
diff --git a/data/sample.lua b/data/sample.lua
index 0cb492392..574f378cc 100644
--- a/data/sample.lua
+++ b/data/sample.lua
@@ -255,7 +255,7 @@ function html_align(align)
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>'
diff --git a/data/templates b/data/templates
-Subproject 8660958b2add3dba83f84d3f8845a029b672bbe
+Subproject 40175cfc59cfaaf1ec159cdf5ff580fc6d3b2f0
diff --git a/deb/stack.yaml b/deb/stack.yaml
index 3f84be738..9986ead40 100644
--- a/deb/stack.yaml
+++ b/deb/stack.yaml
@@ -15,8 +15,4 @@ packages:
- '..'
- 'https://hackage.haskell.org/package/pandoc-citeproc-0.9/pandoc-citeproc-0.9.tar.gz'
extra-deps:
-- 'cmark-0.5.0'
-- '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
+resolver: lts-5.2
diff --git a/osx/stack.yaml b/osx/stack.yaml
index d9decaba1..50a90f9d6 100644
--- a/osx/stack.yaml
+++ b/osx/stack.yaml
@@ -18,8 +18,4 @@ packages:
- '..'
- 'https://hackage.haskell.org/package/pandoc-citeproc-0.9/pandoc-citeproc-0.9.tar.gz'
extra-deps:
-- 'cmark-0.5.0'
-- '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
+resolver: lts-5.2
diff --git a/pandoc.cabal b/pandoc.cabal
index 4d2be8e6c..d82a7e629 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -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 @@ Description: Pandoc is a Haskell library for converting from one markup
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-Files:
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
@@ -259,7 +260,7 @@ Library
random >= 1 && < 1.2,
extensible-exceptions >= 0.1 && < 0.2,
pandoc-types >= 1.16 && < 1.17,
- aeson >= 0.7 && < 0.11,
+ aeson >= 0.7 && < 0.12,
tagsoup >= 0.13.1 && < 0.14,
base64-bytestring >= 0.1 && < 1.1,
zlib >= 0.5 && < 0.7,
@@ -362,6 +363,7 @@ Library
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,
@@ -414,7 +416,7 @@ Executable pandoc
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
@@ -504,6 +506,7 @@ Test-Suite test-pandoc
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
diff --git a/pandoc.hs b/pandoc.hs
index 01f8891d8..72a7592d8 100644
--- a/pandoc.hs
+++ b/pandoc.hs
@@ -1009,6 +1009,8 @@ defaultWriterName x =
".fb2" -> "fb2"
".opml" -> "opml"
".icml" -> "icml"
+ ".tei.xml" -> "tei"
+ ".tei" -> "tei"
['.',y] | y `elem` ['1'..'9'] -> "man"
_ -> "html"
diff --git a/src/Text/Pandoc.hs b/src/Text/Pandoc.hs
index 3f46648a2..4b2397eb9 100644
--- a/src/Text/Pandoc.hs
+++ b/src/Text/Pandoc.hs
@@ -115,6 +115,7 @@ module Text.Pandoc
, writeHaddock
, writeCommonMark
, writeCustom
+ , writeTEI
-- * Rendering templates and default templates
, module Text.Pandoc.Templates
-- * Miscellaneous
@@ -169,6 +170,7 @@ import Text.Pandoc.Writers.AsciiDoc
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)
@@ -304,6 +306,7 @@ writers = [
,("asciidoc" , PureStringWriter writeAsciiDoc)
,("haddock" , PureStringWriter writeHaddock)
,("commonmark" , PureStringWriter writeCommonMark)
+ ,("tei" , PureStringWriter writeTEI)
]
getDefaultExtensions :: String -> Set Extension
diff --git a/src/Text/Pandoc/Highlighting.hs b/src/Text/Pandoc/Highlighting.hs
index d7a14c129..ecfef1832 100644
--- a/src/Text/Pandoc/Highlighting.hs
+++ b/src/Text/Pandoc/Highlighting.hs
@@ -70,7 +70,8 @@ highlight formatter (_, classes, keyvals) rawCode =
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
diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs
index 7dd47cd59..333f499fb 100644
--- a/src/Text/Pandoc/Options.hs
+++ b/src/Text/Pandoc/Options.hs
@@ -202,7 +202,6 @@ githubMarkdownExtensions :: Set Extension
githubMarkdownExtensions = Set.fromList
[ Ext_pipe_tables
, Ext_raw_html
- , Ext_tex_math_single_backslash
, Ext_fenced_code_blocks
, Ext_auto_identifiers
, Ext_ascii_identifiers
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
index 16fe75ed5..325231846 100644
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -915,7 +915,7 @@ data ParserState = ParserState
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 @@ instance HasHeaderMap ParserState where
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 @@ defaultParserState =
stateMeta' = return nullMeta,
stateHeaderTable = [],
stateHeaders = M.empty,
- stateIdentifiers = [],
+ stateIdentifiers = Set.empty,
stateNextExample = 1,
stateExamples = M.empty,
stateHasChapters = False,
@@ -1092,8 +1092,8 @@ registerHeader (ident,classes,kvs) header' = do
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
diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
index 44f67ce75..1b3269136 100644
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -89,6 +89,7 @@ import Text.TeXMath (writeTeX)
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)
@@ -350,7 +351,7 @@ parPartToInlines (BookMark _ anchor) =
-- 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})
@@ -393,7 +394,7 @@ makeHeaderAnchor' (Header n (_, classes, kvs) ils)
| (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 +402,7 @@ makeHeaderAnchor' (Header n (_, classes, kvs) ils)
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
diff --git a/src/Text/Pandoc/Readers/Docx/Reducible.hs b/src/Text/Pandoc/Readers/Docx/Reducible.hs
index c93b40119..e6de2d474 100644
--- a/src/Text/Pandoc/Readers/Docx/Reducible.hs
+++ b/src/Text/Pandoc/Readers/Docx/Reducible.hs
@@ -53,6 +53,7 @@ instance Modifiable Inlines where
(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
@@ -65,6 +66,7 @@ instance Modifiable Inlines where
(Strikeout lst) -> fromList lst
(Superscript lst) -> fromList lst
(Subscript lst) -> fromList lst
+ (Link _ lst _) -> fromList lst
(Span _ lst) -> fromList lst
_ -> ils
_ -> ils
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
index a34e2fb5c..03b790d0b 100644
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -43,7 +43,7 @@ import Text.HTML.TagSoup.Match
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,
@@ -68,7 +68,7 @@ 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 :: ReaderOptions -- ^ Reader options
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
@@ -104,7 +104,7 @@ data HTMLState =
{ parserState :: ParserState,
noteTable :: [(String, Blocks)],
baseHref :: Maybe String,
- identifiers :: [String],
+ identifiers :: Set.Set String,
headerMap :: M.Map Inlines String
}
@@ -137,7 +137,11 @@ pHead = pInTags "head" $ pTitle <|> pMetaTag <|> pBaseTag <|> (mempty <$ pAnyTag
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" [])
@@ -441,6 +445,7 @@ pTable = try $ do
-- 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)
@@ -925,14 +930,45 @@ htmlInBalanced :: (Monad m)
=> (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 n [] = mzero
+
+hasTagWarning :: [Tag String] -> Bool
+hasTagWarning (TagWarning _:_) = True
+hasTagWarning _ = False
-- | Matches a tag meeting a certain condition.
htmlTag :: Monad m
@@ -941,8 +977,6 @@ htmlTag :: Monad m
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
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
index 4b30725aa..9a1708331 100644
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -422,7 +422,8 @@ inlineCommand = try $ do
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 +436,7 @@ isBlockCommand s = s `M.member` blockCommands
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")
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 77c3a1016..82d343243 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -36,7 +36,7 @@ import Data.List ( transpose, sortBy, findIndex, intersperse, intercalate )
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)
@@ -1554,7 +1554,7 @@ math :: MarkdownParser (F Inlines)
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.
diff --git a/src/Text/Pandoc/Readers/MediaWiki.hs b/src/Text/Pandoc/Readers/MediaWiki.hs
index d29ec50e7..950497992 100644
--- a/src/Text/Pandoc/Readers/MediaWiki.hs
+++ b/src/Text/Pandoc/Readers/MediaWiki.hs
@@ -52,6 +52,7 @@ import Text.HTML.TagSoup
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 @@ readMediaWiki opts s =
, mwNextLinkNumber = 1
, mwCategoryLinks = []
, mwHeaderMap = M.empty
- , mwIdentifierList = []
+ , mwIdentifierList = Set.empty
}
(s ++ "\n")
@@ -78,7 +79,7 @@ data MWState = MWState { mwOptions :: ReaderOptions
, mwNextLinkNumber :: Int
, mwCategoryLinks :: [Inlines]
, mwHeaderMap :: M.Map Inlines String
- , mwIdentifierList :: [String]
+ , mwIdentifierList :: Set.Set String
}
type MWParser = Parser [Char] MWState
diff --git a/src/Text/Pandoc/Readers/Odt/ContentReader.hs b/src/Text/Pandoc/Readers/Odt/ContentReader.hs
index 1f1c57646..8c475eefc 100644
--- a/src/Text/Pandoc/Readers/Odt/ContentReader.hs
+++ b/src/Text/Pandoc/Readers/Odt/ContentReader.hs
@@ -61,6 +61,7 @@ import Text.Pandoc.Readers.Odt.Generic.XMLConverter
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 @@ getPrettyAnchor = proc (baseIdent, uglyAnchor) -> do
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
diff --git a/src/Text/Pandoc/Readers/Org.hs b/src/Text/Pandoc/Readers/Org.hs
index c7906618c..3f29d06ef 100644
--- a/src/Text/Pandoc/Readers/Org.hs
+++ b/src/Text/Pandoc/Readers/Org.hs
@@ -53,6 +53,7 @@ import Data.Char (isAlphaNum, toLower)
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 @@ data OrgParserState = OrgParserState
, orgStateMeta' :: F Meta
, orgStateNotes' :: OrgNoteTable
, orgStateParserContext :: ParserContext
- , orgStateIdentifiers :: [String]
+ , orgStateIdentifiers :: Set.Set String
, orgStateHeaderMap :: M.Map Inlines String
}
@@ -186,7 +187,7 @@ defaultOrgParserState = OrgParserState
, orgStateMeta' = return nullMeta
, orgStateNotes' = []
, orgStateParserContext = NullState
- , orgStateIdentifiers = []
+ , orgStateIdentifiers = Set.empty
, orgStateHeaderMap = M.empty
}
@@ -1238,37 +1239,37 @@ applyCustomLinkFormat link = do
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 =
+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
+
+-- | 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
- "" -> 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)
-
-isAbsoluteFilePath :: String -> Bool
-isAbsoluteFilePath = ('/' ==) . head
+ '/':_ -> 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 =
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
index dd1d289a3..6f64540f8 100644
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -583,7 +583,18 @@ code2 = do
-- | 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 @@ classIdAttr = try $ do -- (class class #id)
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
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index aa07c81e1..b5efcf172 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -706,14 +706,14 @@ headerLtEq _ _ = False
-- | 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
diff --git a/src/Text/Pandoc/Writers/Custom.hs b/src/Text/Pandoc/Writers/Custom.hs
index 9671fc05b..d69eaaa64 100644
--- a/src/Text/Pandoc/Writers/Custom.hs
+++ b/src/Text/Pandoc/Writers/Custom.hs
@@ -222,8 +222,8 @@ blockToCustom _ Null = return ""
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
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
index 827d32620..150e19043 100644
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -34,6 +34,7 @@ import qualified Data.ByteString as B
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 @@ data WriterState = WriterState{
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 @@ defaultWriterState = WriterState{
stTextProperties = []
, stParaProperties = []
, stFootnotes = defaultFootnotes
- , stSectionIds = []
+ , stSectionIds = Set.empty
, stExternalLinks = M.empty
, stImages = M.empty
, stListLevel = -1
@@ -742,7 +743,7 @@ blockToOpenXML opts (Header lev (ident,_,_) lst) = do
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)] ()
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
index 64f94f41f..804dbb926 100644
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -31,6 +31,7 @@ Conversion of 'Pandoc' documents to EPUB.
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 @@ showChapter = printf "ch%03d.xhtml"
-- 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
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
index 6e199583e..c5b6a6db2 100644
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -645,7 +645,7 @@ alignmentToString alignment = case alignment of
AlignLeft -> "left"
AlignRight -> "right"
AlignCenter -> "center"
- AlignDefault -> "left"
+ AlignDefault -> ""
tableItemToHtml :: WriterOptions
-> (Html -> Html)
@@ -658,7 +658,10 @@ tableItemToHtml opts tag' align' item = do
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]
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
index e4e882b8c..4e4279ec5 100644
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -113,12 +113,7 @@ pandocToLaTeX options (Pandoc meta blocks) = do
(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`
@@ -1260,3 +1255,24 @@ commonFromBcp47 x = fromIso $ head x
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 '}')
+
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
index 7b56b3fe2..ce993093c 100644
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -53,6 +53,7 @@ import Data.Yaml (Value(Object,String,Array,Bool,Number))
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 @@ data WriterState = WriterState { stNotes :: Notes
, 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
@@ -364,7 +365,7 @@ blockToMarkdown opts (Header level attr inlines) = do
-- 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
diff --git a/src/Text/Pandoc/Writers/TEI.hs b/src/Text/Pandoc/Writers/TEI.hs
new file mode 100644
index 000000000..b9e683ab9
--- /dev/null
+++ b/src/Text/Pandoc/Writers/TEI.hs
@@ -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)]
+
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
index 1aefaa678..8420704dc 100644
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -43,13 +43,14 @@ import Text.Pandoc.Pretty
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 @@ writeTexinfo options document =
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 @@ blockToTexinfo (Header level _ lst) = do
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 $$
diff --git a/stack.full.yaml b/stack.full.yaml
index d79d25d0c..2d752d531 100644
--- a/stack.full.yaml
+++ b/stack.full.yaml
@@ -12,8 +12,4 @@ packages:
- '../pandoc-citeproc'
- '../pandoc-types'
- '../texmath'
-extra-deps:
-- 'cmark-0.5.0'
-# Use older aeson to avoid excessive memory use in compilation:
-- 'aeson-0.8.0.2'
-resolver: lts-4.0
+resolver: lts-5.2
diff --git a/stack.yaml b/stack.yaml
index 8dcc4c65f..21ff7bff7 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -7,10 +7,9 @@ flags:
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.2
diff --git a/tests/Tests/Old.hs b/tests/Tests/Old.hs
index c6b22af50..36bb3398e 100644
--- a/tests/Tests/Old.hs
+++ b/tests/Tests/Old.hs
@@ -162,7 +162,7 @@ tests = [ testGroup "markdown"
[ 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"
diff --git a/tests/Tests/Readers/Docx.hs b/tests/Tests/Readers/Docx.hs
index 086d3f964..9284d165a 100644
--- a/tests/Tests/Readers/Docx.hs
+++ b/tests/Tests/Readers/Docx.hs
@@ -111,6 +111,10 @@ tests = [ testGroup "inlines"
"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"
diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs
index bb3bffe22..8e255160f 100644
--- a/tests/Tests/Readers/Org.hs
+++ b/tests/Tests/Readers/Org.hs
@@ -190,6 +190,10 @@ tests =
"[[./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/" ""
diff --git a/tests/Tests/Writers/TEI.hs b/tests/Tests/Writers/TEI.hs
new file mode 100644
index 000000000..56764db9f
--- /dev/null
+++ b/tests/Tests/Writers/TEI.hs
@@ -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>"
+ ]
+ ]
diff --git a/tests/docx/adjacent_links.docx b/tests/docx/adjacent_links.docx
new file mode 100644
index 000000000..86b1c2a14
--- /dev/null
+++ b/tests/docx/adjacent_links.docx
Binary files differ
diff --git a/tests/docx/adjacent_links.native b/tests/docx/adjacent_links.native
new file mode 100644
index 000000000..cca861890
--- /dev/null
+++ b/tests/docx/adjacent_links.native
@@ -0,0 +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 "."]]
diff --git a/tests/tables.html b/tests/tables.html
index f5ddf3bcd..0a9ea413c 100644
--- a/tests/tables.html
+++ b/tests/tables.html
@@ -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>
diff --git a/tests/tables.tei b/tests/tables.tei
new file mode 100644
index 000000000..45b88b1cb
--- /dev/null
+++ b/tests/tables.tei
@@ -0,0 +1,171 @@
+<p>Simple table with caption:</p>
+<table>
+ <row role="label">
+ <cell><p>Right</p></cell>
+ <cell><p>Left</p></cell>
+ <cell><p>Center</p></cell>
+ <cell><p>Default</p></cell>
+ </row>
+ <row>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ </row>
+ <row>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ </row>
+ <row>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ </row>
+</table>
+<p>Simple table without caption:</p>
+<table>
+ <row role="label">
+ <cell><p>Right</p></cell>
+ <cell><p>Left</p></cell>
+ <cell><p>Center</p></cell>
+ <cell><p>Default</p></cell>
+ </row>
+ <row>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ </row>
+ <row>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ </row>
+ <row>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ </row>
+</table>
+<p>Simple table indented two spaces:</p>
+<table>
+ <row role="label">
+ <cell><p>Right</p></cell>
+ <cell><p>Left</p></cell>
+ <cell><p>Center</p></cell>
+ <cell><p>Default</p></cell>
+ </row>
+ <row>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ </row>
+ <row>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ </row>
+ <row>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ </row>
+</table>
+<p>Multiline table with caption:</p>
+<table>
+ <row role="label">
+ <cell><p>Centered Header</p></cell>
+ <cell><p>Left Aligned</p></cell>
+ <cell><p>Right Aligned</p></cell>
+ <cell><p>Default aligned</p></cell>
+ </row>
+ <row>
+ <cell><p>First</p></cell>
+ <cell><p>row</p></cell>
+ <cell><p>12.0</p></cell>
+ <cell><p>Example of a row that spans multiple lines.</p></cell>
+ </row>
+ <row>
+ <cell><p>Second</p></cell>
+ <cell><p>row</p></cell>
+ <cell><p>5.0</p></cell>
+ <cell><p>Here's another one. Note the blank line between rows.</p></cell>
+ </row>
+</table>
+<p>Multiline table without caption:</p>
+<table>
+ <row role="label">
+ <cell><p>Centered Header</p></cell>
+ <cell><p>Left Aligned</p></cell>
+ <cell><p>Right Aligned</p></cell>
+ <cell><p>Default aligned</p></cell>
+ </row>
+ <row>
+ <cell><p>First</p></cell>
+ <cell><p>row</p></cell>
+ <cell><p>12.0</p></cell>
+ <cell><p>Example of a row that spans multiple lines.</p></cell>
+ </row>
+ <row>
+ <cell><p>Second</p></cell>
+ <cell><p>row</p></cell>
+ <cell><p>5.0</p></cell>
+ <cell><p>Here's another one. Note the blank line between rows.</p></cell>
+ </row>
+</table>
+<p>Table without column headers:</p>
+<table>
+ <row role="label">
+ <cell></cell>
+ <cell></cell>
+ <cell></cell>
+ <cell></cell>
+ </row>
+ <row>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ <cell><p>12</p></cell>
+ </row>
+ <row>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ <cell><p>123</p></cell>
+ </row>
+ <row>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ <cell><p>1</p></cell>
+ </row>
+</table>
+<p>Multiline table without column headers:</p>
+<table>
+ <row role="label">
+ <cell></cell>
+ <cell></cell>
+ <cell></cell>
+ <cell></cell>
+ </row>
+ <row>
+ <cell><p>First</p></cell>
+ <cell><p>row</p></cell>
+ <cell><p>12.0</p></cell>
+ <cell><p>Example of a row that spans multiple lines.</p></cell>
+ </row>
+ <row>
+ <cell><p>Second</p></cell>
+ <cell><p>row</p></cell>
+ <cell><p>5.0</p></cell>
+ <cell><p>Here's another one. Note the blank line between rows.</p></cell>
+ </row>
+</table>
diff --git a/tests/test-pandoc.hs b/tests/test-pandoc.hs
index f7c2f0c1f..2488917cb 100644
--- a/tests/test-pandoc.hs
+++ b/tests/test-pandoc.hs
@@ -24,6 +24,7 @@ import qualified Tests.Writers.Plain
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 @@ tests = [ testGroup "Old" Tests.Old.tests
, 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
diff --git a/tests/textile-reader.native b/tests/textile-reader.native
index fe2c7be24..79a5f52da 100644
--- a/tests/textile-reader.native
+++ b/tests/textile-reader.native
@@ -132,8 +132,11 @@ Pandoc (Meta {unMeta = fromList []})
,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]
[]
diff --git a/tests/textile-reader.textile b/tests/textile-reader.textile
index d5d7378b0..a9c80ccbd 100644
--- a/tests/textile-reader.textile
+++ b/tests/textile-reader.textile
@@ -207,6 +207,12 @@ h1. Attributes
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.
diff --git a/tests/writer.tei b/tests/writer.tei
new file mode 100644
index 000000000..41f258775
--- /dev/null
+++ b/tests/writer.tei
@@ -0,0 +1,861 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TEI xmlns="http://www.tei-c.org/ns/1.0">
+<teiHeader>
+ <fileDesc>
+ <titleStmt>
+ <title>Pandoc Test Suite</title>
+ <author>John MacFarlane</author>
+ <author>Anonymous</author>
+ </titleStmt>
+ <publicationStmt>
+ <p></p>
+ </publicationStmt>
+ <sourceDesc>
+ <p>Produced by pandoc.</p>
+ </sourceDesc>
+ </fileDesc>
+</teiHeader>
+<text>
+<body>
+<p>This is a set of tests for pandoc. Most of them are adapted from John
+Gruber’s markdown test suite.</p>
+<milestone unit="undefined" type="separator" rendition="line" />
+<div type="level1">
+ <head>Headers</head>
+ <div type="level2">
+ <head>Level 2 with an <ref target="/url">embedded link</ref></head>
+ <div type="level3">
+ <head>Level 3 with <hi rendition="simple:italic">emphasis</hi></head>
+ <div type="level4">
+ <head>Level 4</head>
+ <div type="level5">
+ <head>Level 5</head>
+ <p></p>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div type="level1">
+ <head>Level 1</head>
+ <div type="level2">
+ <head>Level 2 with <hi rendition="simple:italic">emphasis</hi></head>
+ <div type="level3">
+ <head>Level 3</head>
+ <p>with no blank line</p>
+ </div>
+ </div>
+ <div type="level2">
+ <head>Level 2</head>
+ <p>with no blank line</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+ </div>
+</div>
+<div type="level1">
+ <head>Paragraphs</head>
+ <p>Here’s a regular paragraph.</p>
+ <p>In Markdown 1.0.0 and earlier. Version 8. This line turns into a list
+ item. Because a hard-wrapped line in the middle of a paragraph looked like a
+ list item.</p>
+ <p>Here’s one with a bullet. * criminey.</p>
+ <p>There should be a hard line break<lb />here.</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Block Quotes</head>
+ <p>E-mail style:</p>
+ <quote>
+ <p>This is a block quote. It is pretty short.</p>
+ </quote>
+ <quote>
+ <p>Code in a block quote:</p>
+ <ab type='codeblock '>
+sub status {
+ print &quot;working&quot;;
+}
+</ab>
+ <p>A list:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>item one</p>
+ </item>
+ <item>
+ <p>item two</p>
+ </item>
+ </list>
+ <p>Nested block quotes:</p>
+ <quote>
+ <p>nested</p>
+ </quote>
+ <quote>
+ <p>nested</p>
+ </quote>
+ </quote>
+ <p>This should not be a block quote: 2 &gt; 1.</p>
+ <p>And a following paragraph.</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Code Blocks</head>
+ <p>Code:</p>
+ <ab type='codeblock '>
+---- (should be four hyphens)
+
+sub status {
+ print &quot;working&quot;;
+}
+
+this code block is indented by one tab
+</ab>
+ <p>And:</p>
+ <ab type='codeblock '>
+ this code block is indented by two tabs
+
+These should not be escaped: \$ \\ \&gt; \[ \{
+</ab>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Lists</head>
+ <div type="level2">
+ <head>Unordered</head>
+ <p>Asterisks tight:</p>
+ <list type="unordered">
+ <item>
+ <p>asterisk 1</p>
+ </item>
+ <item>
+ <p>asterisk 2</p>
+ </item>
+ <item>
+ <p>asterisk 3</p>
+ </item>
+ </list>
+ <p>Asterisks loose:</p>
+ <list type="unordered">
+ <item>
+ <p>asterisk 1</p>
+ </item>
+ <item>
+ <p>asterisk 2</p>
+ </item>
+ <item>
+ <p>asterisk 3</p>
+ </item>
+ </list>
+ <p>Pluses tight:</p>
+ <list type="unordered">
+ <item>
+ <p>Plus 1</p>
+ </item>
+ <item>
+ <p>Plus 2</p>
+ </item>
+ <item>
+ <p>Plus 3</p>
+ </item>
+ </list>
+ <p>Pluses loose:</p>
+ <list type="unordered">
+ <item>
+ <p>Plus 1</p>
+ </item>
+ <item>
+ <p>Plus 2</p>
+ </item>
+ <item>
+ <p>Plus 3</p>
+ </item>
+ </list>
+ <p>Minuses tight:</p>
+ <list type="unordered">
+ <item>
+ <p>Minus 1</p>
+ </item>
+ <item>
+ <p>Minus 2</p>
+ </item>
+ <item>
+ <p>Minus 3</p>
+ </item>
+ </list>
+ <p>Minuses loose:</p>
+ <list type="unordered">
+ <item>
+ <p>Minus 1</p>
+ </item>
+ <item>
+ <p>Minus 2</p>
+ </item>
+ <item>
+ <p>Minus 3</p>
+ </item>
+ </list>
+ </div>
+ <div type="level2">
+ <head>Ordered</head>
+ <p>Tight:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>First</p>
+ </item>
+ <item>
+ <p>Second</p>
+ </item>
+ <item>
+ <p>Third</p>
+ </item>
+ </list>
+ <p>and:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>One</p>
+ </item>
+ <item>
+ <p>Two</p>
+ </item>
+ <item>
+ <p>Three</p>
+ </item>
+ </list>
+ <p>Loose using tabs:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>First</p>
+ </item>
+ <item>
+ <p>Second</p>
+ </item>
+ <item>
+ <p>Third</p>
+ </item>
+ </list>
+ <p>and using spaces:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>One</p>
+ </item>
+ <item>
+ <p>Two</p>
+ </item>
+ <item>
+ <p>Three</p>
+ </item>
+ </list>
+ <p>Multiple paragraphs:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>Item 1, graf one.</p>
+ <p>Item 1. graf two. The quick brown fox jumped over the lazy dog’s
+ back.</p>
+ </item>
+ <item>
+ <p>Item 2.</p>
+ </item>
+ <item>
+ <p>Item 3.</p>
+ </item>
+ </list>
+ </div>
+ <div type="level2">
+ <head>Nested</head>
+ <list type="unordered">
+ <item>
+ <p>Tab</p>
+ <list type="unordered">
+ <item>
+ <p>Tab</p>
+ <list type="unordered">
+ <item>
+ <p>Tab</p>
+ </item>
+ </list>
+ </item>
+ </list>
+ </item>
+ </list>
+ <p>Here’s another:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>First</p>
+ </item>
+ <item>
+ <p>Second:</p>
+ <list type="unordered">
+ <item>
+ <p>Fee</p>
+ </item>
+ <item>
+ <p>Fie</p>
+ </item>
+ <item>
+ <p>Foe</p>
+ </item>
+ </list>
+ </item>
+ <item>
+ <p>Third</p>
+ </item>
+ </list>
+ <p>Same thing but with paragraphs:</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>First</p>
+ </item>
+ <item>
+ <p>Second:</p>
+ <list type="unordered">
+ <item>
+ <p>Fee</p>
+ </item>
+ <item>
+ <p>Fie</p>
+ </item>
+ <item>
+ <p>Foe</p>
+ </item>
+ </list>
+ </item>
+ <item>
+ <p>Third</p>
+ </item>
+ </list>
+ </div>
+ <div type="level2">
+ <head>Tabs and spaces</head>
+ <list type="unordered">
+ <item>
+ <p>this is a list item indented with tabs</p>
+ </item>
+ <item>
+ <p>this is a list item indented with spaces</p>
+ <list type="unordered">
+ <item>
+ <p>this is an example list item indented with tabs</p>
+ </item>
+ <item>
+ <p>this is an example list item indented with spaces</p>
+ </item>
+ </list>
+ </item>
+ </list>
+ </div>
+ <div type="level2">
+ <head>Fancy list markers</head>
+ <list type="ordered:arabic">
+ <item n="2">
+ <p>begins with 2</p>
+ </item>
+ <item>
+ <p>and now 3</p>
+ <p>with a continuation</p>
+ <list type="ordered:lowerroman">
+ <item n="4">
+ <p>sublist with roman numerals, starting with 4</p>
+ </item>
+ <item>
+ <p>more items</p>
+ <list type="ordered:upperalpha">
+ <item>
+ <p>a subsublist</p>
+ </item>
+ <item>
+ <p>a subsublist</p>
+ </item>
+ </list>
+ </item>
+ </list>
+ </item>
+ </list>
+ <p>Nesting:</p>
+ <list type="ordered:upperalpha">
+ <item>
+ <p>Upper Alpha</p>
+ <list type="ordered:upperroman">
+ <item>
+ <p>Upper Roman.</p>
+ <list type="ordered:arabic">
+ <item n="6">
+ <p>Decimal start with 6</p>
+ <list type="ordered:loweralpha">
+ <item n="3">
+ <p>Lower alpha with paren</p>
+ </item>
+ </list>
+ </item>
+ </list>
+ </item>
+ </list>
+ </item>
+ </list>
+ <p>Autonumbering:</p>
+ <list>
+ <item>
+ <p>Autonumber.</p>
+ </item>
+ <item>
+ <p>More.</p>
+ <list>
+ <item>
+ <p>Nested.</p>
+ </item>
+ </list>
+ </item>
+ </list>
+ <p>Should not be a list item:</p>
+ <p>M.A. 2007</p>
+ <p>B. Williams</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+ </div>
+</div>
+<div type="level1">
+ <head>Definition Lists</head>
+ <p>Tight using spaces:</p>
+ <list type="definition">
+ <label>
+ apple
+ </label>
+ <item>
+ <p>red fruit</p>
+ </item>
+ <label>
+ orange
+ </label>
+ <item>
+ <p>orange fruit</p>
+ </item>
+ <label>
+ banana
+ </label>
+ <item>
+ <p>yellow fruit</p>
+ </item>
+ </list>
+ <p>Tight using tabs:</p>
+ <list type="definition">
+ <label>
+ apple
+ </label>
+ <item>
+ <p>red fruit</p>
+ </item>
+ <label>
+ orange
+ </label>
+ <item>
+ <p>orange fruit</p>
+ </item>
+ <label>
+ banana
+ </label>
+ <item>
+ <p>yellow fruit</p>
+ </item>
+ </list>
+ <p>Loose:</p>
+ <list type="definition">
+ <label>
+ apple
+ </label>
+ <item>
+ <p>red fruit</p>
+ </item>
+ <label>
+ orange
+ </label>
+ <item>
+ <p>orange fruit</p>
+ </item>
+ <label>
+ banana
+ </label>
+ <item>
+ <p>yellow fruit</p>
+ </item>
+ </list>
+ <p>Multiple blocks with italics:</p>
+ <list type="definition">
+ <label>
+ <hi rendition="simple:italic">apple</hi>
+ </label>
+ <item>
+ <p>red fruit</p>
+ <p>contains seeds, crisp, pleasant to taste</p>
+ </item>
+ <label>
+ <hi rendition="simple:italic">orange</hi>
+ </label>
+ <item>
+ <p>orange fruit</p>
+ <ab type='codeblock '>
+{ orange code block }
+</ab>
+ <quote>
+ <p>orange block quote</p>
+ </quote>
+ </item>
+ </list>
+ <p>Multiple definitions, tight:</p>
+ <list type="definition">
+ <label>
+ apple
+ </label>
+ <item>
+ <p>red fruit</p>
+ <p>computer</p>
+ </item>
+ <label>
+ orange
+ </label>
+ <item>
+ <p>orange fruit</p>
+ <p>bank</p>
+ </item>
+ </list>
+ <p>Multiple definitions, loose:</p>
+ <list type="definition">
+ <label>
+ apple
+ </label>
+ <item>
+ <p>red fruit</p>
+ <p>computer</p>
+ </item>
+ <label>
+ orange
+ </label>
+ <item>
+ <p>orange fruit</p>
+ <p>bank</p>
+ </item>
+ </list>
+ <p>Blank line after term, indented marker, alternate markers:</p>
+ <list type="definition">
+ <label>
+ apple
+ </label>
+ <item>
+ <p>red fruit</p>
+ <p>computer</p>
+ </item>
+ <label>
+ orange
+ </label>
+ <item>
+ <p>orange fruit</p>
+ <list type="ordered:arabic">
+ <item>
+ <p>sublist</p>
+ </item>
+ <item>
+ <p>sublist</p>
+ </item>
+ </list>
+ </item>
+ </list>
+</div>
+<div type="level1">
+ <head>HTML Blocks</head>
+ <p>Simple block on one line:</p>
+ <p>foo</p>
+ <p>And nested without indentation:</p>
+ <p>foo</p>
+ <p>bar</p>
+ <p>Interpreted markdown in a table:</p>
+ <p>This is <hi rendition="simple:italic">emphasized</hi></p>
+ <p>And this is <hi rendition="simple:bold">strong</hi></p>
+ <p>Here’s a simple block:</p>
+ <p>foo</p>
+ <p>This should be a code block, though:</p>
+ <ab type='codeblock '>
+&lt;div&gt;
+ foo
+&lt;/div&gt;
+</ab>
+ <p>As should this:</p>
+ <ab type='codeblock '>
+&lt;div&gt;foo&lt;/div&gt;
+</ab>
+ <p>Now, nested:</p>
+ <p>foo</p>
+ <p>This should just be an HTML comment:</p>
+ <p>Multiline:</p>
+ <p>Code block:</p>
+ <ab type='codeblock '>
+&lt;!-- Comment --&gt;
+</ab>
+ <p>Just plain comment, with trailing spaces on the line:</p>
+ <p>Code:</p>
+ <ab type='codeblock '>
+&lt;hr /&gt;
+</ab>
+ <p>Hr’s:</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Inline Markup</head>
+ <p>This is <hi rendition="simple:italic">emphasized</hi>, and so
+ <hi rendition="simple:italic">is this</hi>.</p>
+ <p>This is <hi rendition="simple:bold">strong</hi>, and so
+ <hi rendition="simple:bold">is this</hi>.</p>
+ <p>An <hi rendition="simple:italic"><ref target="/url">emphasized
+ link</ref></hi>.</p>
+ <p><hi rendition="simple:bold"><hi rendition="simple:italic">This is strong
+ and em.</hi></hi></p>
+ <p>So is
+ <hi rendition="simple:bold"><hi rendition="simple:italic">this</hi></hi>
+ word.</p>
+ <p><hi rendition="simple:bold"><hi rendition="simple:italic">This is strong
+ and em.</hi></hi></p>
+ <p>So is
+ <hi rendition="simple:bold"><hi rendition="simple:italic">this</hi></hi>
+ word.</p>
+ <p>This is code: <seg type="code">&gt;</seg>, <seg type="code">$</seg>,
+ <seg type="code">\</seg>, <seg type="code">\$</seg>,
+ <seg type="code">&lt;html&gt;</seg>.</p>
+ <p><hi rendition="simple:strikethrough">This is
+ <hi rendition="simple:italic">strikeout</hi>.</hi></p>
+ <p>Superscripts: a<hi rendition="simple:superscript">bc</hi>d
+ a<hi rendition="simple:superscript"><hi rendition="simple:italic">hello</hi></hi>
+ a<hi rendition="simple:superscript">hello there</hi>.</p>
+ <p>Subscripts: H<hi rendition="simple:subscript">2</hi>O,
+ H<hi rendition="simple:subscript">23</hi>O,
+ H<hi rendition="simple:subscript">many of them</hi>O.</p>
+ <p>These should not be superscripts or subscripts, because of the unescaped
+ spaces: a^b c^d, a~b c~d.</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Smart quotes, ellipses, dashes</head>
+ <p><quote>Hello,</quote> said the spider. <quote><quote>Shelob</quote> is my
+ name.</quote></p>
+ <p><quote>A</quote>, <quote>B</quote>, and <quote>C</quote> are letters.</p>
+ <p><quote>Oak,</quote> <quote>elm,</quote> and <quote>beech</quote> are
+ names of trees. So is <quote>pine.</quote></p>
+ <p><quote>He said, <quote>I want to go.</quote></quote> Were you alive in
+ the 70’s?</p>
+ <p>Here is some quoted <quote><seg type="code">code</seg></quote> and a
+ <quote><ref target="http://example.com/?foo=1&amp;bar=2">quoted
+ link</ref></quote>.</p>
+ <p>Some dashes: one—two — three—four — five.</p>
+ <p>Dashes between numbers: 5–7, 255–66, 1987–1999.</p>
+ <p>Ellipses…and…and….</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>LaTeX</head>
+ <list type="unordered">
+ <item>
+ <p></p>
+ </item>
+ <item>
+ <p><formula notation="TeX">2+2=4</formula></p>
+ </item>
+ <item>
+ <p><formula notation="TeX">x \in y</formula></p>
+ </item>
+ <item>
+ <p><formula notation="TeX">\alpha \wedge \omega</formula></p>
+ </item>
+ <item>
+ <p><formula notation="TeX">223</formula></p>
+ </item>
+ <item>
+ <p><formula notation="TeX">p</formula>-Tree</p>
+ </item>
+ <item>
+ <p>Here’s some display math: <figure type="math">
+ <formula notation="TeX">\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}</formula>
+ </figure></p>
+ </item>
+ <item>
+ <p>Here’s one that has a line break in it:
+ <formula notation="TeX">\alpha + \omega \times x^2</formula>.</p>
+ </item>
+ </list>
+ <p>These shouldn’t be math:</p>
+ <list type="unordered">
+ <item>
+ <p>To get the famous equation, write
+ <seg type="code">$e = mc^2$</seg>.</p>
+ </item>
+ <item>
+ <p>$22,000 is a <hi rendition="simple:italic">lot</hi> of money. So is
+ $34,000. (It worked if <quote>lot</quote> is emphasized.)</p>
+ </item>
+ <item>
+ <p>Shoes ($20) and socks ($5).</p>
+ </item>
+ <item>
+ <p>Escaped <seg type="code">$</seg>: $73
+ <hi rendition="simple:italic">this should be emphasized</hi> 23$.</p>
+ </item>
+ </list>
+ <p>Here’s a LaTeX table:</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Special Characters</head>
+ <p>Here is some unicode:</p>
+ <list type="unordered">
+ <item>
+ <p>I hat: Î</p>
+ </item>
+ <item>
+ <p>o umlaut: ö</p>
+ </item>
+ <item>
+ <p>section: §</p>
+ </item>
+ <item>
+ <p>set membership: ∈</p>
+ </item>
+ <item>
+ <p>copyright: ©</p>
+ </item>
+ </list>
+ <p>AT&amp;T has an ampersand in their name.</p>
+ <p>AT&amp;T is another way to write it.</p>
+ <p>This &amp; that.</p>
+ <p>4 &lt; 5.</p>
+ <p>6 &gt; 5.</p>
+ <p>Backslash: \</p>
+ <p>Backtick: `</p>
+ <p>Asterisk: *</p>
+ <p>Underscore: _</p>
+ <p>Left brace: {</p>
+ <p>Right brace: }</p>
+ <p>Left bracket: [</p>
+ <p>Right bracket: ]</p>
+ <p>Left paren: (</p>
+ <p>Right paren: )</p>
+ <p>Greater-than: &gt;</p>
+ <p>Hash: #</p>
+ <p>Period: .</p>
+ <p>Bang: !</p>
+ <p>Plus: +</p>
+ <p>Minus: -</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Links</head>
+ <div type="level2">
+ <head>Explicit</head>
+ <p>Just a <ref target="/url/">URL</ref>.</p>
+ <p><ref target="/url/">URL and title</ref>.</p>
+ <p><ref target="/url/">URL and title</ref>.</p>
+ <p><ref target="/url/">URL and title</ref>.</p>
+ <p><ref target="/url/">URL and title</ref></p>
+ <p><ref target="/url/">URL and title</ref></p>
+ <p><ref target="/url/with_underscore">with_underscore</ref></p>
+ <p>Email link (nobody@nowhere.net)</p>
+ <p><ref target="">Empty</ref>.</p>
+ </div>
+ <div type="level2">
+ <head>Reference</head>
+ <p>Foo <ref target="/url/">bar</ref>.</p>
+ <p>Foo <ref target="/url/">bar</ref>.</p>
+ <p>Foo <ref target="/url/">bar</ref>.</p>
+ <p>With <ref target="/url/">embedded [brackets]</ref>.</p>
+ <p><ref target="/url/">b</ref> by itself should be a link.</p>
+ <p>Indented <ref target="/url">once</ref>.</p>
+ <p>Indented <ref target="/url">twice</ref>.</p>
+ <p>Indented <ref target="/url">thrice</ref>.</p>
+ <p>This should [not][] be a link.</p>
+ <ab type='codeblock '>
+[not]: /url
+</ab>
+ <p>Foo <ref target="/url/">bar</ref>.</p>
+ <p>Foo <ref target="/url/">biz</ref>.</p>
+ </div>
+ <div type="level2">
+ <head>With ampersands</head>
+ <p>Here’s a <ref target="http://example.com/?foo=1&amp;bar=2">link with an
+ ampersand in the URL</ref>.</p>
+ <p>Here’s a link with an amersand in the link text:
+ <ref target="http://att.com/">AT&amp;T</ref>.</p>
+ <p>Here’s an <ref target="/script?foo=1&amp;bar=2">inline link</ref>.</p>
+ <p>Here’s an <ref target="/script?foo=1&amp;bar=2">inline link in pointy
+ braces</ref>.</p>
+ </div>
+ <div type="level2">
+ <head>Autolinks</head>
+ <p>With an ampersand:
+ <ref target="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</ref></p>
+ <list type="unordered">
+ <item>
+ <p>In a list?</p>
+ </item>
+ <item>
+ <p><ref target="http://example.com/">http://example.com/</ref></p>
+ </item>
+ <item>
+ <p>It should.</p>
+ </item>
+ </list>
+ <p>An e-mail address: nobody@nowhere.net</p>
+ <quote>
+ <p>Blockquoted:
+ <ref target="http://example.com/">http://example.com/</ref></p>
+ </quote>
+ <p>Auto-links should not occur here:
+ <seg type="code">&lt;http://example.com/&gt;</seg></p>
+ <ab type='codeblock '>
+or here: &lt;http://example.com/&gt;
+</ab>
+ <milestone unit="undefined" type="separator" rendition="line" />
+ </div>
+</div>
+<div type="level1">
+ <head>Images</head>
+ <p>From <quote>Voyage dans la Lune</quote> by Georges Melies (1902):</p>
+ <p><figure>
+ <head>lalune</head>
+ <graphic url="lalune.jpg" />
+ <figDesc>fig:Voyage dans la Lune</figDesc>
+ </figure></p>
+ <p>Here is a movie <figure>
+ <head>movie</head>
+ <graphic url="movie.jpg" />
+ </figure> icon.</p>
+ <milestone unit="undefined" type="separator" rendition="line" />
+</div>
+<div type="level1">
+ <head>Footnotes</head>
+ <p>Here is a footnote reference,<note>
+ <p>Here is the footnote. It can go anywhere after the footnote reference.
+ It need not be placed at the end of the document.</p>
+ </note> and another.<note>
+ <p>Here’s the long note. This one contains multiple blocks.</p>
+ <p>Subsequent blocks are indented to show that they belong to the footnote
+ (as with list items).</p>
+ <ab type='codeblock '>
+ { &lt;code&gt; }
+</ab>
+ <p>If you want, you can indent every line, but you can also be lazy and
+ just indent the first line of each block.</p>
+ </note> This should <hi rendition="simple:italic">not</hi> be a footnote
+ reference, because it contains a space.[^my note] Here is an inline
+ note.<note>
+ <p>This is <hi rendition="simple:italic">easier</hi> to type. Inline notes
+ may contain <ref target="http://google.com">links</ref> and
+ <seg type="code">]</seg> verbatim characters, as well as [bracketed
+ text].</p>
+ </note></p>
+ <quote>
+ <p>Notes can go in quotes.<note>
+ <p>In quote.</p>
+ </note></p>
+ </quote>
+ <list type="ordered:arabic">
+ <item>
+ <p>And in list items.<note>
+ <p>In list.</p>
+ </note></p>
+ </item>
+ </list>
+ <p>This paragraph should not be part of the note, as it is not indented.</p>
+</div>
+</body>
+</text>
+</TEI>
diff --git a/windows/stack.yaml b/windows/stack.yaml
index 91f1c1539..a01dbfc03 100644
--- a/windows/stack.yaml
+++ b/windows/stack.yaml
@@ -15,7 +15,5 @@ packages:
- '..'
- '../../pandoc-citeproc'
extra-deps:
-- 'cmark-0.5.0'
- 'hsb2hs-0.3.1'
-- 'pandoc-types-1.16.0.1'
-resolver: lts-3.20
+resolver: lts-5.2