aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.stylish-haskell.yaml8
-rw-r--r--.travis.yml53
-rw-r--r--AUTHORS.md13
-rw-r--r--CONTRIBUTING.md18
-rw-r--r--INSTALL.md29
-rw-r--r--MANUAL.txt277
-rw-r--r--Makefile40
-rw-r--r--README.md12
-rw-r--r--RELEASE-CHECKLIST3
-rw-r--r--RELEASE-CHECKLIST.md27
-rw-r--r--appveyor.yml80
-rw-r--r--cabal.project7
-rw-r--r--changelog712
-rw-r--r--data/pandoc.lua4
-rw-r--r--data/templates/default.epub32
-rw-r--r--data/templates/default.html52
-rw-r--r--data/templates/default.latex81
-rw-r--r--data/templates/default.opendocument4
-rw-r--r--data/templates/default.revealjs6
-rw-r--r--data/templates/default.rst8
-rw-r--r--data/templates/default.tei20
-rw-r--r--data/templates/default.texinfo22
-rw-r--r--data/translations/fr.yaml20
-rw-r--r--data/translations/ru.yaml18
-rw-r--r--default.nix2
-rw-r--r--doc/lua-filter-types-and-objects.md396
-rw-r--r--doc/lua-filters.md50
-rw-r--r--doc/using-the-pandoc-api.md4
-rw-r--r--linux/Dockerfile47
-rw-r--r--man/pandoc.1308
-rw-r--r--pandoc.cabal70
-rw-r--r--src/Text/Pandoc/App.hs79
-rw-r--r--src/Text/Pandoc/Class.hs6
-rw-r--r--src/Text/Pandoc/Emoji.hs7
-rw-r--r--src/Text/Pandoc/Extensions.hs7
-rw-r--r--src/Text/Pandoc/Highlighting.hs1
-rw-r--r--src/Text/Pandoc/ImageSize.hs55
-rw-r--r--src/Text/Pandoc/Lua.hs26
-rw-r--r--src/Text/Pandoc/Lua/Filter.hs144
-rw-r--r--src/Text/Pandoc/Lua/Init.hs15
-rw-r--r--src/Text/Pandoc/Lua/Module/MediaBag.hs2
-rw-r--r--src/Text/Pandoc/Lua/Module/Pandoc.hs35
-rw-r--r--src/Text/Pandoc/Lua/Module/Utils.hs34
-rw-r--r--src/Text/Pandoc/Lua/Packages.hs32
-rw-r--r--src/Text/Pandoc/Lua/StackInstances.hs254
-rw-r--r--src/Text/Pandoc/Lua/Util.hs186
-rw-r--r--src/Text/Pandoc/Options.hs2
-rw-r--r--src/Text/Pandoc/PDF.hs122
-rw-r--r--src/Text/Pandoc/Parsing.hs23
-rw-r--r--src/Text/Pandoc/Readers/CommonMark.hs64
-rw-r--r--src/Text/Pandoc/Readers/Creole.hs2
-rw-r--r--src/Text/Pandoc/Readers/DocBook.hs66
-rw-r--r--src/Text/Pandoc/Readers/Docx/Lists.hs5
-rw-r--r--src/Text/Pandoc/Readers/Docx/Parse.hs13
-rw-r--r--src/Text/Pandoc/Readers/EPUB.hs2
-rw-r--r--src/Text/Pandoc/Readers/HTML.hs53
-rw-r--r--src/Text/Pandoc/Readers/Haddock.hs14
-rw-r--r--src/Text/Pandoc/Readers/JATS.hs2
-rw-r--r--src/Text/Pandoc/Readers/LaTeX.hs1474
-rw-r--r--src/Text/Pandoc/Readers/LaTeX/Lang.hs173
-rw-r--r--src/Text/Pandoc/Readers/LaTeX/Parsing.hs668
-rw-r--r--src/Text/Pandoc/Readers/LaTeX/Types.hs6
-rw-r--r--src/Text/Pandoc/Readers/Markdown.hs192
-rw-r--r--src/Text/Pandoc/Readers/Muse.hs514
-rw-r--r--src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs4
-rw-r--r--src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs2
-rw-r--r--src/Text/Pandoc/Readers/Odt/Generic/Utils.hs8
-rw-r--r--src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs2
-rw-r--r--src/Text/Pandoc/Readers/Odt/StyleReader.hs4
-rw-r--r--src/Text/Pandoc/Readers/Org/Blocks.hs7
-rw-r--r--src/Text/Pandoc/Readers/Org/DocumentTree.hs139
-rw-r--r--src/Text/Pandoc/Readers/Org/ExportSettings.hs2
-rw-r--r--src/Text/Pandoc/Readers/Org/Inlines.hs10
-rw-r--r--src/Text/Pandoc/Readers/Org/Meta.hs14
-rw-r--r--src/Text/Pandoc/Readers/Org/ParserState.hs10
-rw-r--r--src/Text/Pandoc/Readers/Org/Parsing.hs15
-rw-r--r--src/Text/Pandoc/Readers/Org/Shared.hs4
-rw-r--r--src/Text/Pandoc/Readers/RST.hs68
-rw-r--r--src/Text/Pandoc/Readers/TWiki.hs111
-rw-r--r--src/Text/Pandoc/Readers/Textile.hs2
-rw-r--r--src/Text/Pandoc/Readers/TikiWiki.hs9
-rw-r--r--src/Text/Pandoc/Readers/Txt2Tags.hs8
-rw-r--r--src/Text/Pandoc/Readers/Vimwiki.hs18
-rw-r--r--src/Text/Pandoc/Shared.hs41
-rw-r--r--src/Text/Pandoc/Translations.hs39
-rw-r--r--src/Text/Pandoc/UUID.hs15
-rw-r--r--src/Text/Pandoc/Writers/AsciiDoc.hs25
-rw-r--r--src/Text/Pandoc/Writers/CommonMark.hs57
-rw-r--r--src/Text/Pandoc/Writers/ConTeXt.hs25
-rw-r--r--src/Text/Pandoc/Writers/Custom.hs155
-rw-r--r--src/Text/Pandoc/Writers/Docbook.hs7
-rw-r--r--src/Text/Pandoc/Writers/Docx.hs36
-rw-r--r--src/Text/Pandoc/Writers/EPUB.hs39
-rw-r--r--src/Text/Pandoc/Writers/FB2.hs12
-rw-r--r--src/Text/Pandoc/Writers/HTML.hs199
-rw-r--r--src/Text/Pandoc/Writers/Haddock.hs14
-rw-r--r--src/Text/Pandoc/Writers/ICML.hs5
-rw-r--r--src/Text/Pandoc/Writers/JATS.hs8
-rw-r--r--src/Text/Pandoc/Writers/LaTeX.hs203
-rw-r--r--src/Text/Pandoc/Writers/Man.hs33
-rw-r--r--src/Text/Pandoc/Writers/Markdown.hs55
-rw-r--r--src/Text/Pandoc/Writers/Math.hs2
-rw-r--r--src/Text/Pandoc/Writers/MediaWiki.hs1
-rw-r--r--src/Text/Pandoc/Writers/Ms.hs31
-rw-r--r--src/Text/Pandoc/Writers/Muse.hs245
-rw-r--r--src/Text/Pandoc/Writers/ODT.hs4
-rw-r--r--src/Text/Pandoc/Writers/OPML.hs3
-rw-r--r--src/Text/Pandoc/Writers/OpenDocument.hs156
-rw-r--r--src/Text/Pandoc/Writers/Org.hs4
-rw-r--r--src/Text/Pandoc/Writers/Powerpoint/Presentation.hs22
-rw-r--r--src/Text/Pandoc/Writers/RST.hs87
-rw-r--r--src/Text/Pandoc/Writers/RTF.hs6
-rw-r--r--src/Text/Pandoc/Writers/Shared.hs121
-rw-r--r--src/Text/Pandoc/Writers/TEI.hs15
-rw-r--r--src/Text/Pandoc/Writers/Texinfo.hs30
-rw-r--r--src/Text/Pandoc/Writers/Textile.hs14
-rw-r--r--stack.lts10.yaml31
-rw-r--r--stack.lts11.yaml27
-rw-r--r--stack.lts9.yaml27
-rw-r--r--stack.yaml28
-rw-r--r--test/Tests/Lua.hs19
-rw-r--r--test/Tests/Readers/HTML.hs25
-rw-r--r--test/Tests/Readers/Markdown.hs12
-rw-r--r--test/Tests/Readers/Muse.hs85
-rw-r--r--test/Tests/Readers/Org/Block/Header.hs38
-rw-r--r--test/Tests/Readers/Org/Block/List.hs11
-rw-r--r--test/Tests/Readers/Org/Directive.hs23
-rw-r--r--test/Tests/Readers/Org/Inline.hs9
-rw-r--r--test/Tests/Readers/RST.hs16
-rw-r--r--test/Tests/Writers/HTML.hs5
-rw-r--r--test/Tests/Writers/Muse.hs94
-rw-r--r--test/Tests/Writers/RST.hs8
-rw-r--r--test/command/1126.md29
-rw-r--r--test/command/1710.md7
-rw-r--r--test/command/2118.md2
-rw-r--r--test/command/3407.md4
-rw-r--r--test/command/3432.md2
-rw-r--r--test/command/3534.md22
-rw-r--r--test/command/3558.md4
-rw-r--r--test/command/3716.md2
-rw-r--r--test/command/3804.md2
-rw-r--r--test/command/3947.md2
-rw-r--r--test/command/4016.md4
-rw-r--r--test/command/4056.md2
-rw-r--r--test/command/4159.md2
-rw-r--r--test/command/4284.md40
-rw-r--r--test/command/4528.md156
-rw-r--r--test/command/4545.md20
-rw-r--r--test/command/4553.md15
-rw-r--r--test/command/4624.md30
-rw-r--r--test/command/4653.md8
-rw-r--r--test/command/4667.md20
-rw-r--r--test/command/4669.md29
-rw-r--r--test/command/4677.md8
-rw-r--r--test/command/4690.md28
-rw-r--r--test/command/4722.md34
-rw-r--r--test/command/4742.md25
-rw-r--r--test/command/4743.md25
-rw-r--r--test/command/4748.md16
-rw-r--r--test/command/4768.md7
-rw-r--r--test/command/4781.md22
-rw-r--r--test/command/4794.md18
-rw-r--r--test/command/4811.md48
-rw-r--r--test/command/4817.md10
-rw-r--r--test/command/4819.md50
-rw-r--r--test/command/4832.md21
-rw-r--r--test/command/4833.md20
-rw-r--r--test/command/4842.md6
-rw-r--r--test/command/4845.md6
-rw-r--r--test/command/4848.md59
-rw-r--r--test/command/4860.md9
-rw-r--r--test/command/4877.md13
-rw-r--r--test/command/4885.md8
-rw-r--r--test/command/4908.md16
-rw-r--r--test/command/4913.md34
-rw-r--r--test/command/4919.md14
-rw-r--r--test/command/4928.md48
-rw-r--r--test/command/adjacent_latex_blocks.md4
-rw-r--r--test/command/ascii.md45
-rw-r--r--test/command/bar.tex1
-rw-r--r--test/command/emoji.md27
-rw-r--r--test/command/empty-inline-code.txt6
-rw-r--r--test/command/gfm.md2
-rw-r--r--test/command/hspace.md6
-rw-r--r--test/command/macros.md8
-rw-r--r--test/command/refs.md47
-rw-r--r--test/command/write18.md2
-rw-r--r--test/command/yaml-metadata-blocks.md63
-rw-r--r--test/command/yaml-metadata.yaml4
-rw-r--r--test/docbook-xref.native2
-rw-r--r--test/fb2/meta.fb22
-rw-r--r--test/lhs-test.html10
-rw-r--r--test/lhs-test.html+lhs10
-rw-r--r--test/lua/test-pandoc-utils.lua15
-rw-r--r--test/markdown-reader-more.native17
-rw-r--r--test/pptx/lists.native2
-rw-r--r--test/pptx/lists.pptxbin26765 -> 26765 bytes
-rw-r--r--test/pptx/lists_templated.pptxbin394091 -> 394091 bytes
-rw-r--r--test/rst-reader.native2
-rw-r--r--test/tables-rstsubset.native8
-rw-r--r--test/tables.opendocument194
-rw-r--r--test/tables.rst60
-rw-r--r--test/testsuite.native10
-rw-r--r--test/textile-reader.native2
-rw-r--r--test/textile-reader.textile2
-rw-r--r--test/tikiwiki-reader.native58
-rw-r--r--test/txt2tags.t2t2
-rw-r--r--test/writer.context6
-rw-r--r--test/writer.docbook46
-rw-r--r--test/writer.docbook56
-rw-r--r--test/writer.fb22
-rw-r--r--test/writer.haddock14
-rw-r--r--test/writer.html42
-rw-r--r--test/writer.html54
-rw-r--r--test/writer.jats13
-rw-r--r--test/writer.muse77
-rw-r--r--test/writer.native10
-rw-r--r--test/writer.opendocument855
-rw-r--r--test/writer.org8
-rw-r--r--test/writer.rst82
-rw-r--r--test/writer.tei4
-rw-r--r--test/writer.texinfo24
-rw-r--r--test/writer.textile2
-rwxr-xr-xtools/changelog-helper.sh23
-rw-r--r--trypandoc/trypandoc.hs2
225 files changed, 8087 insertions, 3836 deletions
diff --git a/.stylish-haskell.yaml b/.stylish-haskell.yaml
index 496e72802..43c8442f8 100644
--- a/.stylish-haskell.yaml
+++ b/.stylish-haskell.yaml
@@ -41,7 +41,7 @@ steps:
# Default: global.
align: none
- # Folowing options affect only import list alignment.
+ # Following options affect only import list alignment.
#
# List align has following options:
#
@@ -75,7 +75,7 @@ steps:
# short enough to fit to single line. Otherwise it'll be multiline.
#
# - multiline: One line per import list entry.
- # Type with contructor list acts like single import.
+ # Type with constructor list acts like single import.
#
# > import qualified Data.Map as M
# > ( empty
@@ -91,7 +91,7 @@ steps:
# This option affects 'list_align' and 'long_list_align'.
list_padding: 4
- # Separate lists option affects formating of import list for type
+ # Separate lists option affects formatting of import list for type
# or class. The only difference is single space between type and list
# of constructors, selectors and class functions.
#
@@ -124,7 +124,7 @@ steps:
# Align affects alignment of closing pragma brackets.
#
- # - true: Brackets are aligned in same collumn.
+ # - true: Brackets are aligned in same column.
#
# - false: Brackets are not aligned together. There is only one space
# between actual import and closing bracket.
diff --git a/.travis.yml b/.travis.yml
index ee594e6de..7461426d1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -32,26 +32,26 @@ matrix:
# We grab the appropriate GHC and cabal-install versions from hvr's PPA. See:
# https://github.com/hvr/multi-ghc-travis
# don't build benchmarks for ghc 7.10.3, because build takes too long...
- - env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 OPTS="-O0 -Wall -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS=""
+ - env: BUILD=cabal GHCVER=7.10.3 CABALVER=2.0 OPTS="-O0 -Wall -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS="" TESTPATTERN="! /Round trip/"
compiler: ": #GHC 7.10.3"
- addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5], sources: [hvr-ghc]}}
+ addons: {apt: {packages: [cabal-install-2.0,ghc-7.10.3,happy-1.19.5], sources: [hvr-ghc]}}
# don't build benchmarks for ghc 8.0.2, because build takes too long...
- - env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast" CABALARGS=""
+ - env: BUILD=cabal GHCVER=8.0.2 CABALVER=2.0 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast" CABALARGS="" TESTPATTERN="! /Round trip/"
compiler: ": #GHC 8.0.2"
- addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5], sources: [hvr-ghc]}}
+ addons: {apt: {packages: [cabal-install-2.0,ghc-8.0.2,happy-1.19.5], sources: [hvr-ghc]}}
- - env: BUILD=cabal GHCVER=8.2.2 CABALVER=1.24 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks"
- compiler: ": #GHC 8.2.2"
- addons: {apt: {packages: [cabal-install-1.24,ghc-8.2.2,happy-1.19.5], sources: [hvr-ghc]}}
-
- - env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks"
+ - env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks" TESTPATTERN="! /Round trip/"
compiler: ": #GHC 8.2.2"
addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5], sources: [hvr-ghc]}}
- - env: BUILD=cabal GHCVER=8.4.1 CABALVER=2.0 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks"
- compiler: ": #GHC 8.4.1"
- addons: {apt: {packages: [cabal-install-2.0,ghc-8.4.1,happy-1.19.5], sources: [hvr-ghc]}}
+ - env: BUILD=cabal GHCVER=8.4.3 CABALVER=2.2 OPTS="-O0 -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks" TESTPATTERN="! /Round trip/"
+ compiler: ": #GHC 8.4.3"
+ addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3,happy-1.19.5], sources: [hvr-ghc]}}
+
+ # - env: BUILD=cabal GHCVER=8.6.1 CABALVER=2.4 OPTS="-O0 -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks --allow-newer=haddock-library:base" TESTPATTERN="! /Round trip/"
+ # compiler: ": #GHC 8.6.1"
+ # addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.1,happy-1.19.5], sources: [hvr-ghc]}}
# Build with the newest GHC and cabal-install. This is an accepted failure,
# see below.
@@ -61,18 +61,18 @@ matrix:
# 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="--stack-yaml stack.lts9.yaml" OPTS="-Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror"
+ # - env: BUILD=stack ARGS="--stack-yaml stack.lts9.yaml" OPTS="-O0 -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -Werror" FLAGS="fast embed_data_files"
# compiler: ": #stack 8.0.2"
# addons: {apt: {packages: [ghc-8.0.2], sources: [hvr-ghc]}}
- - env: BUILD=stack ARGS="--resolver lts-10" OPTS="-Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror"
- compiler: ": #stack 8.2.2"
- addons: {apt: {packages: [ghc-8.2.2], sources: [hvr-ghc]}}
+ - env: BUILD=stack ARGS="--resolver lts-12" OPTS="-O0 -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -Werror" TESTPATTERN="! /Round trip/"
+ compiler: ": #stack 8.4.3"
+ addons: {apt: {packages: [ghc-8.4.3], sources: [hvr-ghc]}}
# Nightly builds are allowed to fail
- - env: BUILD=stack ARGS="--resolver nightly" OPTS="-Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror"
+ - env: BUILD=stack ARGS="--resolver nightly" OPTS="-O0 -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -Werror" TESTPATTERN="."
compiler: ": #stack nightly"
- addons: {apt: {packages: [ghc-8.2.2], sources: [hvr-ghc]}}
+ addons: {apt: {packages: [ghc-8.4.3], sources: [hvr-ghc]}}
# - env: BUILD=stack ARGS="--resolver lts-8"
# compiler: ": #stack 8.0.2 osx"
@@ -84,14 +84,14 @@ matrix:
allow_failures:
- env: BUILD=cabal GHCVER=head CABALVER=head
- - env: BUILD=stack ARGS="--resolver nightly" OPTS="-Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror"
+ - env: BUILD=stack ARGS="--resolver nightly" OPTS="-O0 -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -Werror" TESTPATTERN="."
fast_finish: true
before_install:
# Using compiler above sets CC to an invalid value, so unset it
- unset CC
-- export PATH=/opt/happy/1.19.5/bin/:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:$HOME/.cabal/bin:$PATH
+- export PATH=/opt/happy/1.19.5/bin/:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:/opt/cabal/bin:$HOME/.local/bin:$HOME/.cabal/bin:$PATH
# Download and unpack the stack executable
- |
if [[ $BUILD == "stack" ]]; then
@@ -117,7 +117,14 @@ install:
cabal)
cabal --version
travis_retry cabal update
- cabal install --disable-optimization --only-dependencies --flags="$FLAGS" --enable-tests --force-reinstalls --reorder-goals --max-backjumps=-1 $CABALARGS
+ case "$GHCVER" in
+ 7.10.3)
+ cabal install -v1 --disable-optimization --flags="$FLAGS" --enable-tests --force-reinstalls --reorder-goals --max-backjumps=-1 $CABALARGS
+ ;;
+ *)
+ cabal install --disable-optimization --only-dependencies --flags="$FLAGS" --enable-tests --force-reinstalls --reorder-goals --max-backjumps=-1 $CABALARGS
+ ;;
+ esac
;;
esac
@@ -127,13 +134,13 @@ script:
stack)
ulimit -n 4096
stack config set system-ghc --global true
- stack --no-terminal $ARGS test --fast --flag 'aeson:fast' --flag pandoc:embed_data_files --haddock --no-haddock-deps --ghc-options="$OPTS" --test-arguments='--hide-successes'
+ stack --no-terminal $ARGS test --fast --flag 'aeson:fast' --flag pandoc:embed_data_files --haddock --no-haddock-deps --ghc-options="$OPTS" --test-arguments="--hide-successes --pattern \"$TESTPATTERN\""
;;
cabal)
cabal sdist --output-directory=sourcedist && \
cd sourcedist && \
cabal configure --disable-optimization --enable-tests -v2 --flags="$FLAGS" --ghc-options="$OPTS" $CABALARGS && \
cabal build -v2 -j2 && \
- cabal test
+ cabal test --test-options="--pattern=\"$TESTPATTERN\""
;;
esac
diff --git a/AUTHORS.md b/AUTHORS.md
index 1f6059e56..9c319d0bb 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -11,9 +11,11 @@
- Alexander Sulfrian
- Alexander V Vershilov
- Alfred Wechselberger
+- Anders Waldenborg
- Andreas Lööw
- Andrew Dunning
- Antoine Latter
+- Antonio Terceiro
- Arata Mizuki
- Arlo O'Keeffe
- Artyom Kazak
@@ -26,6 +28,7 @@
- Bjorn Buckwalter
- Bradley Kuhn
- Brent Yorgey
+- Brian Leung
- Bryan O'Sullivan
- Caleb McDaniel
- Calvin Beck
@@ -71,8 +74,11 @@
- Henrik Tramberend
- Henry de Valence
- Hubert Plociniczak
+- Igor Khorlo
- Ilya V. Portnov
+- Ivan Trubach
- Ivo Clarysse
+- J. B. Rainsberger
- J. Lewis Muir
- Jaime Marquínez Ferrándiz
- Jakob Voß
@@ -92,8 +98,10 @@
- John Muccigrosso
- John Luke Bentley
- Jonas Smedegaard
+- Jonas Scholl
- Jonathan Daugherty
- Jose Luis Duran
+- José de Mattos Neto
- Josef Svenningsson
- Julien Cretel
- Juliusz Gonera
@@ -133,6 +141,7 @@
- Nick Bart
- Nicolas Kaiser
- Nikolay Yakimov
+- Nils Carlson
- Nokome Bentley
- Oliver Matthews
- Ophir Lifshitz
@@ -148,6 +157,7 @@
- Puneeth Chaganti
- Ralf Stephan
- Raniere Silva
+- Raymond Ehlers
- Recai Oktaş
- Roland Hieber
- RyanGlScott
@@ -189,6 +199,8 @@
- d-dorazio
- iandol
- infinity0x
+- kaizshang91
+- lux-lth
- lwolfsonkin
- nkalvi
- oltolm
@@ -202,3 +214,4 @@
- takahashim
- tgkokk
- thsutton
+- wiefling
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 11a0c9c94..372caf0ae 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -144,13 +144,10 @@ Please follow these guidelines:
9. It is better not to introduce new dependencies. Dependencies on
external C libraries should especially be avoided.
-10. We aim for compatibility with ghc versions from 7.8.3 to the
+10. We aim for compatibility with ghc versions from 7.10.3 to the
latest release. All pull requests and commits are tested
automatically on <travis-ci.org>, using GHC versions in the
- `Tested-With` stanza of `pandoc.cabal`. We currently relax
- the "`-Wall` clean" requirement for GHC 7.10.x, because
- there are so many warnings relating to the addition of type
- classes to the Prelude.
+ `Tested-With` stanza of `pandoc.cabal`.
Tests
-----
@@ -192,7 +189,7 @@ Using the REPL
With a recent version of cabal, you can do `cabal repl` and get
a ghci REPL for working with pandoc. With [stack], use
-`cabal ghci`.
+`stack ghci`.
We recommend using the following `.ghci` file (which can be
placed in the source directory):
@@ -267,7 +264,7 @@ The library is structured as follows:
- `Text.Pandoc.Definition` (in `pandoc-types`) defines the types
used for representing a pandoc document.
- `Text.Pandoc.Builder` (in `pandoc-types`) provides functions for
- building pandoc documents programatically.
+ building pandoc documents programmatically.
- `Text.Pandoc.Generics` (in `pandoc-types`) provides functions allowing
you to promote functions that operate on parts of pandoc documents
to functions that operate on whole pandoc documents, walking the
@@ -306,6 +303,13 @@ The library is structured as follows:
- `Text.Pandoc.UUID` contains functions for generating UUIDs.
- `Text.Pandoc.XML` contains functions for formatting XML.
+Lua filters
+-----------
+
+If you've written a useful pandoc [lua filter](lua-filters.html),
+you may want to consider submitting a pull request to the
+[lua-filters repository](https://github.com/pandoc/lua-filters).
+
[open issues]: https://github.com/jgm/pandoc/issues
[closed issues]: https://github.com/jgm/pandoc/issues?q=is%3Aissue+is%3Aclosed
[latest released version]: https://github.com/jgm/pandoc/releases/latest
diff --git a/INSTALL.md b/INSTALL.md
index b299653d2..32e71cc3c 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -11,15 +11,15 @@
a zip file that contains pandoc's binaries and
documentation. Simply unzip this file and move the binaries
to a directory of your choice.
+
+ - Alternatively, you can install pandoc using
+ [chocolatey](https://chocolatey.org): `choco install pandoc`.
- For PDF output, you'll also need to install LaTeX.
We recommend [MiKTeX](http://miktex.org/).
## macOS
- - You can install pandoc using
- [homebrew](http://brew.sh): `brew install pandoc`.
-
- There is a package installer at pandoc's [download page].
If you later want to uninstall the package, you can do so
by downloading [this script][uninstaller]
@@ -30,6 +30,12 @@
unzip the file and move the binaries and man pages to
whatever directory you like.
+ - Alternatively, you can install pandoc using
+ [homebrew](http://brew.sh): `brew install pandoc`.
+ Note: If you are using macOS < 10.10, this method installs
+ pandoc from source, so it will take a long time and a lot of
+ disk space for the ghc compiler and dependent Haskell libraries.
+
- For PDF output, you'll also need LaTeX. Because a full [MacTeX]
installation takes more than a gigabyte of disk space, we recommend
installing [BasicTeX](http://www.tug.org/mactex/morepackages.html)
@@ -137,13 +143,21 @@ The easiest way to build pandoc from source is to use [stack]:
1. Install the [Haskell platform]. This will give you [GHC] and
the [cabal-install] build tool. Note that pandoc requires
- GHC >= 7.10.
+ GHC >= 7.10 and cabal >= 2.0.
2. Update your package database:
cabal update
-3. Use `cabal` to install pandoc and its dependencies:
+3. Check your cabal version with
+
+ cabal --version
+
+ If you have a version less than 2.0, install the latest with:
+
+ cabal install cabal-install
+
+4. Use `cabal` to install pandoc and its dependencies:
cabal install pandoc
@@ -156,7 +170,7 @@ The easiest way to build pandoc from source is to use [stack]:
cabal install
-4. Make sure the `$CABALDIR/bin` directory is in your path. You should
+5. Make sure the `$CABALDIR/bin` directory is in your path. You should
now be able to run `pandoc`:
pandoc --help
@@ -200,6 +214,7 @@ over the build and installation. Most users should use the
quick install, but this information may be of use to packagers.
For more details, see the [Cabal User's Guide]. These instructions
assume that the pandoc source directory is your working directory.
+You will need cabal version 2.0 or higher.
1. Install dependencies: in addition to the [Haskell platform],
you will need a number of additional libraries. You can install
@@ -331,5 +346,5 @@ To run just the markdown benchmarks:
[openSUSE]: https://software.opensuse.org/package/pandoc
[source tarball]: http://hackage.haskell.org/package/pandoc
[stack]: http://docs.haskellstack.org/en/stable/install_and_upgrade.html
-[cabal-install]: http://hackage.haskell.org/trac/hackage/wiki/CabalInstall
+[cabal-install]: http://hackage.haskell.org/package/cabal-install
[uninstaller]: https://raw.githubusercontent.com/jgm/pandoc/master/macos/uninstall-pandoc.pl
diff --git a/MANUAL.txt b/MANUAL.txt
index 595dab5ce..bf47184ce 100644
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -1,6 +1,6 @@
% Pandoc User's Guide
% John MacFarlane
-% May 10, 2018
+% September 27, 2018
Synopsis
========
@@ -155,9 +155,10 @@ the LaTeX engine requires [`fontspec`]. `xelatex` uses
`xelatex` will use [`mathspec`] instead of [`unicode-math`].
The [`upquote`] and [`microtype`] packages are used if
available, and [`csquotes`] will be used for [typography]
-if added to the template or included in any header file. The
-[`natbib`], [`biblatex`], [`bibtex`], and [`biber`] packages can
-optionally be used for [citation rendering].
+if `\usepackage{csquotes}` is present in the template or
+included via `/H/--include-in-header`. The [`natbib`],
+[`biblatex`], [`bibtex`], and [`biber`] packages can optionally
+be used for [citation rendering].
[`amsfonts`]: https://ctan.org/pkg/amsfonts
[`amsmath`]: https://ctan.org/pkg/amsmath
@@ -210,7 +211,7 @@ header when requesting a document from a URL:
Options
=======
-General options
+General options {.options}
---------------
`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*
@@ -225,9 +226,9 @@ General options
- `epub` ([EPUB])
- `fb2` ([FictionBook2] e-book)
- `gfm` ([GitHub-Flavored Markdown]),
- or `markdown_github`, which provides deprecated and less accurate
- support for Github-Flavored Markdown; please use `gfm` instead,
- unless you need to use extensions other than `smart`.
+ or the deprecated and less accurate `markdown_github`;
+ use [`markdown_github`](#markdown-variants) only
+ if you need extensions not supported in [`gfm`](#markdown-variants).
- `haddock` ([Haddock markup])
- `html` ([HTML])
- `jats` ([JATS] XML)
@@ -274,9 +275,9 @@ General options
- `epub2` (EPUB v2)
- `fb2` ([FictionBook2] e-book)
- `gfm` ([GitHub-Flavored Markdown]),
- or `markdown_github`, which provides deprecated and less accurate
- support for Github-Flavored Markdown; please use `gfm` instead,
- unless you use extensions that do not work with `gfm`.
+ or the deprecated and less accurate `markdown_github`;
+ use [`markdown_github`](#markdown-variants) only
+ if you need extensions not supported in [`gfm`](#markdown-variants).
- `haddock` ([Haddock markup])
- `html` or `html5` ([HTML], i.e. [HTML5]/XHTML [polyglot markup])
- `html4` ([XHTML] 1.0 Transitional)
@@ -458,7 +459,7 @@ General options
[PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint
[Vimwiki]: https://vimwiki.github.io
-Reader options
+Reader options {.options}
--------------
`--base-header-level=`*NUMBER*
@@ -493,7 +494,7 @@ Reader options
footnotes and links will not work across files. Reading binary
files (docx, odt, epub) implies `--file-scope`.
-`--filter=`*PROGRAM*
+`-F` *PROGRAM*, `--filter=`*PROGRAM*
: Specify an executable to be used as a filter transforming the
pandoc AST after the input is parsed and before the output is
@@ -577,6 +578,16 @@ Reader options
printed in some output formats) and metadata values will be escaped
when inserted into the template.
+`--metadata-file=`*FILE*
+
+: Read metadata from the supplied YAML (or JSON) file.
+ This option can be used with every input format, but string
+ scalars in the YAML file will always be parsed as Markdown.
+ Generally, the input will be handled the same as in
+ [YAML metadata blocks][Extension: `yaml_metadata_block`].
+ Metadata values specified inside the document, or by using `-M`,
+ overwrite values specified with this option.
+
`-p`, `--preserve-tabs`
: Preserve tabs instead of converting them to spaces (the default).
@@ -634,7 +645,7 @@ Reader options
[perl]: https://metacpan.org/pod/Pandoc::Filter
[JavaScript/node.js]: https://github.com/mvhenderson/pandoc-filter-node
-General writer options
+General writer options {.options}
----------------------
`-s`, `--standalone`
@@ -645,10 +656,10 @@ General writer options
output. For `native` output, this option causes metadata to
be included; otherwise, metadata is suppressed.
-`--template=`*FILE*
+`--template=`*FILE*|*URL*
-: Use *FILE* as a custom template for the generated document. Implies
- `--standalone`. See [Templates], below, for a description
+: Use the specified file as a custom template for the generated document.
+ Implies `--standalone`. See [Templates], below, for a description
of template syntax. If no extension is specified, an extension
corresponding to the writer will be added, so that `--template=special`
looks for `special.html` for HTML output. If the template is not
@@ -713,8 +724,9 @@ General writer options
: Include an automatically generated table of contents (or, in
the case of `latex`, `context`, `docx`, `odt`,
`opendocument`, `rst`, or `ms`, an instruction to create
- one) in the output document. This option has no effect on
- `man`, `docbook4`, `docbook5`, or `jats` output.
+ one) in the output document. This option has no effect
+ unless `-s/--standalone` is used, and it has no effect
+ on `man`, `docbook4`, `docbook5`, or `jats` output.
`--toc-depth=`*NUMBER*
@@ -803,14 +815,20 @@ General writer options
`--resource-path=.:test` will search the working directory
and the `test` subdirectory, in that order.
+ `--resource-path` only has an effect if (a) the output
+ format embeds images (for example, `docx`, `pdf`, or `html`
+ with `--self-contained`) or (b) it is used together with
+ `--extract-media`.
+
`--request-header=`*NAME*`:`*VAL*
: Set the request header *NAME* to the value *VAL* when making
HTTP requests (for example, when a URL is given on the
command line, or when resources used in a document must be
- downloaded).
+ downloaded). If you're behind a proxy, you also need to set
+ the environment variable `http_proxy` to `http://...`.
-Options affecting specific writers
+Options affecting specific writers {.options}
----------------------------------
`--self-contained`
@@ -842,8 +860,10 @@ Options affecting specific writers
: Use only ASCII characters in output. Currently supported for
XML and HTML formats (which use numerical entities instead of
- UTF-8 when this option is selected) and for groff ms and man
- (which use hexadecimal escapes).
+ UTF-8 when this option is selected), groff ms and man
+ (which use hexadecimal escapes), and to a limited degree
+ for LaTeX (which uses standard commands for accented
+ characters when possible).
`--reference-links`
@@ -898,7 +918,10 @@ Options affecting specific writers
`--listings`
-: Use the [`listings`] package for LaTeX code blocks
+: Use the [`listings`] package for LaTeX code blocks. The package
+ does not support multi-byte encoding for source code. To handle UTF-8
+ you would need to use a custom template. This issue is fully
+ documented here: [Encoding issue with the listings package].
`-i`, `--incremental`
@@ -1126,8 +1149,10 @@ Options affecting specific writers
[Dublin Core elements]: http://dublincore.org/documents/dces/
[ISO 8601 format]: http://www.w3.org/TR/NOTE-datetime
+[Encoding issue with the listings package]:
+ https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue
-Citation rendering
+Citation rendering {.options}
------------------
`--bibliography=`*FILE*
@@ -1167,7 +1192,7 @@ Citation rendering
with the `pandoc-citeproc` filter or with PDF output. It is intended for
use in producing a LaTeX file that can be processed with [`bibtex`] or [`biber`].
-Math rendering in HTML
+Math rendering in HTML {.options}
----------------------
The default is to render TeX math as far as possible using Unicode characters.
@@ -1208,14 +1233,9 @@ of the following options.
`--katex`[`=`*URL*]
: Use [KaTeX] to display embedded TeX math in HTML output.
- The *URL* is the base URL for the KaTeX library. If a *URL* is
- not provided, a link to the KaTeX CDN will be inserted.
-
-`--katex-stylesheet=`*URL*
-
-: The *URL* should point to the `katex.css` stylesheet. If this option is
- not specified, a link to the KaTeX CDN will be inserted. Note that this
- option does not imply `--katex`.
+ The *URL* is the base URL for the KaTeX library. That directory
+ should contain a `katex.min.js` and a `katex.min.css` file.
+ If a *URL* is not provided, a link to the KaTeX CDN will be inserted.
`--gladtex`
@@ -1233,7 +1253,7 @@ of the following options.
[KaTeX]: https://github.com/Khan/KaTeX
[GladTeX]: http://humenda.github.io/GladTeX/
-Options for wrapper scripts
+Options for wrapper scripts {.options}
---------------------------
`--dump-args`
@@ -1349,7 +1369,7 @@ depending on the output format, but include the following:
`toc-title`
: title of table of contents (works only with EPUB,
- opendocument, odt, docx, pptx)
+ opendocument, odt, docx, pptx, beamer, LaTeX)
`include-before`
: contents specified by `-B/--include-before-body` (may have
@@ -1523,12 +1543,14 @@ LaTeX variables are used when [creating a PDF].
: options to pass to the microtype package
`colorlinks`
-: add color to link text; automatically enabled if any of `linkcolor`, `citecolor`,
- `urlcolor`, or `toccolor` are set
+: add color to link text; automatically enabled if any of
+ `linkcolor`, `filecolor`, `citecolor`, `urlcolor`, or `toccolor` are set
-`linkcolor`, `citecolor`, `urlcolor`, `toccolor`
-: color for internal links, citation links, external links, and links in table of contents:
- uses options allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and `x11names` lists
+`linkcolor`, `filecolor`, `citecolor`, `urlcolor`, `toccolor`
+: color for internal links, external links, citation links, linked
+ URLs, and links in table of contents, respectively: uses options
+ allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and
+ `x11names` lists
`links-as-notes`
: causes links to be printed as footnotes
@@ -1646,17 +1668,17 @@ Variables for ConTeXt
from [ConTeXt ICC Profiles]. See also [ConTeXt PDFA] for more
details.
-[ConTeXt Paper Setup]: http://wiki.contextgarden.net/PaperSetup
-[ConTeXt Layout]: http://wiki.contextgarden.net/Layout
-[ConTeXt Font Switching]: http://wiki.contextgarden.net/Font_Switching
-[ConTeXt Color]: http://wiki.contextgarden.net/Color
-[ConTeXt Headers and Footers]: http://wiki.contextgarden.net/Headers_and_Footers
-[ConTeXt Indentation]: http://wiki.contextgarden.net/Indentation
-[ConTeXt ICC Profiles]: http://wiki.contextgarden.net/PDFX#ICC_profiles
-[ConTeXt PDFA]: http://wiki.contextgarden.net/PDF/A
-[`setupwhitespace`]: http://wiki.contextgarden.net/Command/setupwhitespace
-[`setupinterlinespace`]: http://wiki.contextgarden.net/Command/setupinterlinespace
-[`setuppagenumbering`]: http://wiki.contextgarden.net/Command/setuppagenumbering
+[ConTeXt Paper Setup]: https://wiki.contextgarden.net/PaperSetup
+[ConTeXt Layout]: https://wiki.contextgarden.net/Layout
+[ConTeXt Font Switching]: https://wiki.contextgarden.net/Font_Switching
+[ConTeXt Color]: https://wiki.contextgarden.net/Color
+[ConTeXt Headers and Footers]: https://wiki.contextgarden.net/Headers_and_Footers
+[ConTeXt Indentation]: https://wiki.contextgarden.net/Indentation
+[ConTeXt ICC Profiles]: https://wiki.contextgarden.net/PDFX#ICC_profiles
+[ConTeXt PDFA]: https://wiki.contextgarden.net/PDF/A
+[`setupwhitespace`]: https://wiki.contextgarden.net/Command/setupwhitespace
+[`setupinterlinespace`]: https://wiki.contextgarden.net/Command/setupinterlinespace
+[`setuppagenumbering`]: https://wiki.contextgarden.net/Command/setuppagenumbering
Variables for man pages
-----------------------
@@ -1723,8 +1745,7 @@ of the following:
- any object,
- the boolean `true` (to specify the boolean `true`
value using YAML metadata or the `--metadata` flag,
- use `y`, `Y`, `yes`, `Yes`, `YES`, `true`, `True`,
- `TRUE`, `on`, `On`, or `ON`; with the `--variable`
+ use `true`, `True`, or `TRUE`; with the `--variable`
flag, simply omit a value for the variable, e.g.
`--variable draft`).
@@ -1913,10 +1934,11 @@ This extension can be enabled/disabled for the following formats
(in addition to `markdown`):
input formats
-: `latex`, `org`, `textile`
+: `latex`, `org`, `textile`, `html` (environments, `\ref`, and
+ `\eqref` only)
output formats
-: `textile`
+: `textile`, `commonmark`
#### [Extension: `native_divs`] {#native_divs}
@@ -3051,13 +3073,17 @@ and pass it to pandoc as an argument, along with your Markdown files:
pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html
Just be sure that the YAML file begins with `---` and ends with `---` or
-`...`.)
+`...`.) Alternatively, you can use the `--metadata-file` option. Using
+that approach however, you cannot reference content (like footnotes)
+from the main markdown input document.
Metadata will be taken from the fields of the YAML object and added to any
existing document metadata. Metadata can contain lists and objects (nested
arbitrarily), but all string scalars will be interpreted as Markdown. Fields
with names ending in an underscore will be ignored by pandoc. (They may be
-given a role by external processors.)
+given a role by external processors.) Field names must not be
+interpretable as YAML numbers or boolean values (so, for
+example, `yes`, `True`, and `15` cannot be used as field names).
A document may contain multiple metadata blocks. The metadata fields will
be combined through a *left-biased union*: if two metadata blocks attempt
@@ -3079,7 +3105,7 @@ when the field contains blank lines or block-level formatting:
author:
- Author One
- Author Two
- tags: [nothing, nothingness]
+ keywords: [nothing, nothingness]
abstract: |
This is the abstract.
@@ -3290,8 +3316,13 @@ them and they won't be treated as math delimiters.
TeX math will be printed in all output formats. How it is rendered
depends on the output format:
-Markdown, LaTeX, Emacs Org mode, ConTeXt, ZimWiki
- ~ It will appear verbatim between `$` characters.
+LaTeX
+ ~ It will appear verbatim surrounded by `\(...\)` (for inline
+ math) or `\[...\]` (for display math).
+
+Markdown, Emacs Org mode, ConTeXt, ZimWiki
+ ~ It will appear verbatim surrounded by `$...$` (for inline
+ math) or `$$...$$` (for display math).
reStructuredText
~ It will be rendered using an [interpreted text role `:math:`].
@@ -3350,8 +3381,14 @@ Markdown allows it, but it has been made an extension so that it can
be disabled if desired.)
The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,
-DZSlides, EPUB, Markdown, Emacs Org mode, and Textile output, and suppressed
-in other formats.
+DZSlides, EPUB, Markdown, CommonMark, Emacs Org mode, and Textile
+output, and suppressed in other formats.
+
+In the CommonMark format, if `raw_html` is enabled, superscripts,
+subscripts, strikeouts and small capitals will be represented as HTML.
+Otherwise, plain-text fallbacks will be used. Note that even if
+`raw_html` is disabled, tables will be rendered with HTML syntax if
+they cannot use pipe syntax.
#### Extension: `markdown_in_html_blocks` ####
@@ -3964,11 +4001,12 @@ whether or not they appear in the document, by using a wildcard:
@*
...
-For LaTeX or PDF output, you can also use [`natbib`] or [`biblatex`]
-to render bibliography. In order to do so, specify bibliography files as
-outlined above, and add `--natbib` or `--biblatex` argument to `pandoc`
-invocation. Bear in mind that bibliography files have to be in respective
-format (either BibTeX or BibLaTeX).
+For LaTeX output, you can also use [`natbib`] or [`biblatex`] to
+render the bibliography. In order to do so, specify bibliography
+files as outlined above, and add `--natbib` or `--biblatex`
+argument to `pandoc` invocation. Bear in mind that bibliography
+files have to be in respective format (either BibTeX or
+BibLaTeX).
For more information, see the [pandoc-citeproc man page].
@@ -3976,7 +4014,7 @@ For more information, see the [pandoc-citeproc man page].
[Chicago Manual of Style]: http://chicagomanualofstyle.org
[Citation Style Language]: http://citationstyles.org
[Zotero Style Repository]: https://www.zotero.org/styles
-[finding and editing styles]: http://citationstyles.org/styles/
+[finding and editing styles]: https://citationstyles.org/authors/
[CSL locale files]: https://github.com/citation-style-language/locales
[pandoc-citeproc man page]: https://github.com/jgm/pandoc-citeproc/blob/master/man/pandoc-citeproc.1.md
@@ -4178,7 +4216,7 @@ individually disabled.
Also, `raw_tex` only affects `gfm` output, not input.
`gfm` (GitHub-Flavored Markdown)
-: `pipe_tables`, `raw_html`, `fenced_code_blocks`, `auto_identifiers`,
+: `pipe_tables`, `raw_html`, `fenced_code_blocks`, `gfm_auto_identifiers`,
`ascii_identifiers`, `backtick_code_blocks`, `autolink_bare_uris`,
`intraword_underscores`, `strikeout`, `hard_line_breaks`, `emoji`,
`shortcut_reference_links`, `angle_brackets_escapable`.
@@ -4438,28 +4476,32 @@ introducing the slide:
All of the other frame attributes described in Section 8.1 of
the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,
`allowframebreaks`, `b`, `c`, `t`, `environment`, `label`, `plain`,
-`shrink`.
+`shrink`, `standout`, `noframenumbering`.
-Background in reveal.js
------------------------
+Background in reveal.js and beamer
+----------------------------------
+
+Background images can be added to self-contained reveal.js slideshows and
+to beamer slideshows.
-Background images can be added to self-contained reveal.js slideshows.
+For the same image on every slide, use the configuration
+option `background-image` either in the YAML metadata block
+or as a command-line variable. (There are no other options in
+beamer and the rest of this section concerns reveal.js slideshows.)
-For the same image on every slide, use the reveal.js configuration
-option `parallaxBackgroundImage` either in the YAML metadata block
-or as a command-line variable. You can also set
-`parallaxBackgroundHorizontal` and `parallaxBackgroundVertical` the same
-way and must also set `parallaxBackgroundSize` to have your values
-take effect.
+For reveal.js, you can instead use the reveal.js-native option
+`parallaxBackgroundImage`. You can also set `parallaxBackgroundHorizontal`
+and `parallaxBackgroundVertical` the same way and must also set
+`parallaxBackgroundSize` to have your values take effect.
-To set an image for a particular slide, add
+To set an image for a particular reveal.js slide, add
`{data-background-image="/path/to/image"}`
to the first slide-level header on the slide (which may even be empty).
In reveal.js's overview mode, the parallaxBackgroundImage will show up
only on the first slide.
-Other background settings also work on individual slides, including
+Other reveal.js background settings also work on individual slides, including
`data-background-size`, `data-background-repeat`, `data-background-color`,
`data-transition`, and `data-transition-speed`.
@@ -4467,7 +4509,7 @@ See the [reveal.js
documentation](https://github.com/hakimel/reveal.js#slide-backgrounds)
for more details.
-For example:
+For example in reveal.js:
```
---
@@ -4590,11 +4632,52 @@ The following fields are recognized:
[MARC relators]: http://loc.gov/marc/relators/relaterm.html
[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem
+The `epub:type` attribute
+-------------------------
+
+For `epub3` output, you can mark up the header that corresponds to an EPUB
+chapter using the [`epub:type` attribute][epub-type]. For example, to set
+the attribute to the value `prologue`, use this markdown:
+
+ # My chapter {epub:type=prologue}
+
+Which will result in:
+
+ <body epub:type="frontmatter">
+ <section epub:type="prologue">
+ <h1>My chapter</h1>
+
+Pandoc will output `<body epub:type="bodymatter">`, unless
+you use one of the following values, in which case either
+`frontmatter` or `backmatter` will be output.
+
+`epub:type` of first section `epub:type` of body
+---------------------------- ------------------
+prologue frontmatter
+abstract frontmatter
+acknowledgments frontmatter
+copyright-page frontmatter
+dedication frontmatter
+foreword frontmatter
+halftitle, frontmatter
+introduction frontmatter
+preface frontmatter
+seriespage frontmatter
+titlepage frontmatter
+afterword backmatter
+appendix backmatter
+colophon backmatter
+conclusion backmatter
+epigraph backmatter
+
+[epub-type]: http://www.idpf.org/epub/31/spec/epub-contentdocs.html#sec-epub-type-attribute
+
Linked media
------------
-By default, pandoc will download linked media (including audio and
-video) and include it in the EPUB container, yielding a completely
+By default, pandoc will download media referenced from any `<img>`, `<audio>`,
+`<video>` or `<source>` element present in the generated EPUB,
+and include it in the EPUB container, yielding a completely
self-contained EPUB. If you want to link to external media resources
instead, use raw HTML in your source and add `data-external="1"` to the tag
with the `src` attribute. For example:
@@ -4610,9 +4693,9 @@ Syntax highlighting
Pandoc will automatically highlight syntax in [fenced code blocks] that
are marked with a language name. The Haskell library [skylighting] is
-used for highlighting, which works in HTML, Docx, Ms, and LaTeX/PDF output.
-To see a list of language names that pandoc will recognize, type
-`pandoc --list-highlight-languages`.
+used for highlighting. Currently highlighting is supported only for
+HTML, EPUB, Docx, Ms, and LaTeX/PDF output. To see a list of language names
+that pandoc will recognize, type `pandoc --list-highlight-languages`.
The color scheme can be selected using the `--highlight-style` option.
The default color scheme is `pygments`, which imitates the default color
@@ -4620,6 +4703,24 @@ scheme used by the Python library pygments (though pygments is not actually
used to do the highlighting). To see a list of highlight styles,
type `pandoc --list-highlight-styles`.
+If you are not satisfied with the predefined styles, you can
+use `--print-highlight-style` to generate a JSON `.theme` file which
+can be modified and used as the argument to `--highlight-style`. To
+get a JSON version of the `pygments` style, for example:
+
+ pandoc --print-highlight-style pygments > my.theme
+
+Then edit `my.theme` and use it like this:
+
+ pandoc --highlight-style my.theme
+
+If you are not satisfied with the built-in highlighting, or you
+want highlight a language that isn't supported, you can use the
+`--syntax-definition` option to load a [KDE-style XML syntax definition
+file](https://docs.kde.org/stable5/en/applications/katepart/highlight.html).
+Before writing your own, have a look at KDE's [repository of syntax
+definitions](https://github.com/KDE/syntax-highlighting/tree/master/data/syntax).
+
To disable highlighting, use the `--no-highlight` option.
[skylighting]: https://github.com/jgm/skylighting
diff --git a/Makefile b/Makefile
index 8076421ad..0dbc05a27 100644
--- a/Makefile
+++ b/Makefile
@@ -2,13 +2,23 @@ version?=$(shell grep '^[Vv]ersion:' pandoc.cabal | awk '{print $$2;}')
pandoc=$(shell find dist -name pandoc -type f -exec ls -t {} \; | head -1)
SOURCEFILES?=$(shell find pandoc.hs src test -name '*.hs')
BRANCH?=master
-RESOLVER=lts-10
-GHCOPTS=-fdiagnostics-color=always -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
+RESOLVER=lts-12
+GHCOPTS=-fdiagnostics-color=always -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wincomplete-uni-patterns -Werror=missing-home-modules -Widentities -Wcpp-undef -fhide-source-paths -j +RTS -A32M -RTS
+# Later:
+# -Wpartial-fields (currently used in Powerpoint writer)
+# -Wmissing-export-lists (currently some Odt modules violate this)
+# -Wredundant-constraints (problematic if we want to support older base)
WEBSITE=../../web/pandoc.org
quick:
stack install --resolver=$(RESOLVER) --ghc-options='$(GHCOPTS)' --install-ghc --flag 'pandoc:embed_data_files' --fast --test --test-arguments='-j4 --hide-successes $(TESTARGS)'
+quick-cabal:
+ cabal new-build . --ghc-options '$(GHCOPTS)' --flags '+embed_data_files' --enable-tests --only-dependencies
+ cabal new-build . --ghc-options '$(GHCOPTS)' --flags '+embed_data_files' --enable-tests --disable-optimization
+ cabal new-install --symlink-bindir=$$HOME/.local/bin
+ cabal new-run test-pandoc --ghc-options '$(GHCOPTS)' --flags '+embed_data_files' --disable-optimization -- --hide-successes $(TESTARGS)
+
full:
stack install --resolver=$(RESOLVER) --flag 'pandoc:embed_data_files' --flag 'pandoc:weigh-pandoc' --flag 'pandoc:trypandoc' --bench --no-run-benchmarks --test --test-arguments='-j4 --hide-successes' --ghc-options '-Wall -Werror -fno-warn-unused-do-bind -O0 -j4 $(GHCOPTS)'
@@ -57,25 +67,29 @@ macospkg: man/pandoc.1
winpkg: pandoc-$(version)-windows-i386.msi pandoc-$(version)-windows-i386.zip pandoc-$(version)-windows-x86_64.msi pandoc-$(version)-windows-x86_64.zip
pandoc-$(version)-windows-%.zip: pandoc-$(version)-windows-%.msi
- -rm -rf wintmp && \
- msiextract -C wintmp $< && \
- cd wintmp/"Program Files" && \
- mv Pandoc pandoc-$(version) && \
- zip -r $@ pandoc-$(version) && \
- mv $@ ../../ && \
- cd ../.. && \
- rm -rf wintmp
+ ORIGDIR=`pwd` && \
+ CONTAINER=$(basename $<) && \
+ TEMPDIR=`mktemp -d` && \
+ msiextract -C $$TEMPDIR/msi $< && \
+ pushd $$TEMPDIR && \
+ mkdir $$CONTAINER && \
+ find msi -type f -exec cp {} $$CONTAINER/ \; && \
+ zip -r $$ORIGDIR/$@ $$CONTAINER && \
+ popd & \
+ rm -rf $$TEMPDIR
pandoc-$(version)-windows-%.msi: pandoc-windows-%.msi
osslsigncode sign -pkcs12 ~/Private/ComodoCodeSigning.exp2019.p12 -in $< -i http://johnmacfarlane.net/ -t http://timestamp.comodoca.com/ -out $@ -askpass
rm $<
+.INTERMEDIATE: pandoc-windows-i386.msi pandoc-windows-x86_64.msi
+
pandoc-windows-i386.msi:
- JOBID=$(shell curl 'https://ci.appveyor.com/api/projects/jgm/pandoc' | jq -r '.build.jobs[0].jobId') && \
+ JOBID=$(shell curl 'https://ci.appveyor.com/api/projects/jgm/pandoc' | jq -r '.build.jobs[1].jobId') && \
wget "https://ci.appveyor.com/api/buildjobs/$$JOBID/artifacts/windows%2F$@" -O $@
pandoc-windows-x86_64.msi:
- JOBID=$(shell curl 'https://ci.appveyor.com/api/projects/jgm/pandoc' | jq -r '.build.jobs[1].jobId') && \
+ JOBID=$(shell curl 'https://ci.appveyor.com/api/projects/jgm/pandoc' | jq -r '.build.jobs[0].jobId') && \
wget "https://ci.appveyor.com/api/buildjobs/$$JOBID/artifacts/windows%2F$@" -O $@
man/pandoc.1: MANUAL.txt man/pandoc.1.template
@@ -109,7 +123,7 @@ pandoc-templates:
popd
trypandoc:
- ssh -t macfarlane 'cd src/pandoc && git pull && ~/.local/bin/stack install --flag pandoc:trypandoc --flag pandoc:embed_data_files && cd trypandoc && sudo make install'
+ ssh -t macfarlane 'cd src/pandoc && git pull && stack install --flag pandoc:trypandoc --flag pandoc:embed_data_files && cd trypandoc && sudo make install'
update-website:
make -C $(WEBSITE) update
diff --git a/README.md b/README.md
index dc64421f1..51e5c0a48 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,9 @@ library. It can convert *from*
e-book)
- `gfm` ([GitHub-Flavored
Markdown](https://help.github.com/articles/github-flavored-markdown/)),
- or `markdown_github`, which provides deprecated and less accurate
- support for Github-Flavored Markdown; please use `gfm` instead,
- unless you need to use extensions other than `smart`.
+ or the deprecated and less accurate `markdown_github`; use
+ [`markdown_github`](#markdown-variants) only if you need extensions
+ not supported in [`gfm`](#markdown-variants).
- `haddock` ([Haddock
markup](https://www.haskell.org/haddock/doc/html/ch03s08.html))
- `html` ([HTML](http://www.w3.org/html/))
@@ -92,9 +92,9 @@ It can convert *to*
e-book)
- `gfm` ([GitHub-Flavored
Markdown](https://help.github.com/articles/github-flavored-markdown/)),
- or `markdown_github`, which provides deprecated and less accurate
- support for Github-Flavored Markdown; please use `gfm` instead,
- unless you use extensions that do not work with `gfm`.
+ or the deprecated and less accurate `markdown_github`; use
+ [`markdown_github`](#markdown-variants) only if you need extensions
+ not supported in [`gfm`](#markdown-variants).
- `haddock` ([Haddock
markup](https://www.haskell.org/haddock/doc/html/ch03s08.html))
- `html` or `html5` ([HTML](http://www.w3.org/html/), i.e.
diff --git a/RELEASE-CHECKLIST b/RELEASE-CHECKLIST
index 1fbf396d7..178d514b8 100644
--- a/RELEASE-CHECKLIST
+++ b/RELEASE-CHECKLIST
@@ -1,8 +1,7 @@
[ ] make README.md and commit if needed
[ ] make man/pandoc.1 and commit if needed
[ ] Finalize changelog
- git log --pretty='format:%n%n* %s (%an)%n%b%n%h%n' \
- --reverse --name-only LASTRELEASE..HEAD > LOG
+ tools/changelog-helper.sh
[ ] make packages
[ ] make update-website
[ ] make trypandoc
diff --git a/RELEASE-CHECKLIST.md b/RELEASE-CHECKLIST.md
deleted file mode 100644
index 07fbcb8bb..000000000
--- a/RELEASE-CHECKLIST.md
+++ /dev/null
@@ -1,27 +0,0 @@
-- [ ] Test, on Linux, Windows, macOS (inc. website demos)
-
-- [ ] Finalize changelog:
- `git log --pretty='format:%n%n* %s (%an)%n%b%n%h%n' --reverse --name-only 1.17.0.3..HEAD > LOG`
-
-- [ ] `make man/pandoc.1` and commit if needed
-
-- [ ] Tag release in git
-
-- [ ] Tag templates
-
-- [ ] Generate Windows package (`make winpkg`)
-
-- [ ] Generate macOS package (`make macospkg`)
-
-- [ ] Generate Ubuntu/Debian deb package (`make debpkg`)
-
-- [ ] Add release on github (use `make changes_github` and upload files)
-
-- [ ] Upload to HackageDB
-
-- [ ] Update website (`make update`), including short description of changes (`make changes`)
-
-- [ ] on server, `cabal install --enable-tests -ftrypandoc`
- and then `cd trypandoc; sudo make install`
-
-- [ ] Announce on pandoc-announce, pandoc-discuss
diff --git a/appveyor.yml b/appveyor.yml
index f0d4975f9..e0c978887 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -3,18 +3,31 @@ clone_folder: "c:\\pandoc"
environment:
global:
WIXBIN: "c:\\Program Files (x86)\\WiX Toolset v3.11\\bin"
- STACK_YAML: "c:\\pandoc\\stack.yaml"
- STACK_BUILD_OPTS: "-j1 --no-terminal --test --local-bin-path=.\\windows"
+ CABAL_STORE: "C:\\cs"
+ CABAL_PACKAGE_DB: "%CABAL_STORE%\\ghc-%GHC_MINOR_VERSION%\\package.db"
+ # Override the temp directory to avoid sed escaping issues
+ # See https://github.com/haskell/cabal/issues/5386
+ TMP: "c:\\tmp"
# see #4201, https://github.com/haskell-tools/haskell-tools/issues/277
matrix:
- - STACK_VERSION: "windows-i386"
- STACK_ROOT: "c:\\sr32"
- STACK: "%STACK_ROOT%\\stack.exe"
- STACK_FLAGS: "--flag=hslua:lua_32bits"
- - STACK_VERSION: "windows-x86_64"
- STACK_ROOT: "c:\\sr64"
- STACK: "%STACK_ROOT%\\stack.exe"
- STACK_FLAGS: ""
+ - OSARCH: "windows-x86_64"
+ GHC_VERSION: "8.6.1.1"
+ GHC_MINOR_VERSION: "8.6.1"
+ GHC: "C:\\ProgramData\\chocolatey\\lib\\ghc\\tools\\ghc-%GHC_MINOR_VERSION%\\bin\\ghc.exe"
+ CABAL_VERSION: "2.4.0.0"
+ CABAL_OPTS: "-fembed_data_files -fbibutils"
+ GHC_OPTS: "-fhide-source-paths"
+ ARCH: "x64"
+ CHOCO_OPTS: ""
+ - OSARCH: "windows-i386"
+ GHC_VERSION: "8.6.1.1"
+ GHC_MINOR_VERSION: "8.6.1"
+ GHC: "C:\\ProgramData\\chocolatey\\lib\\ghc\\tools\\ghc-%GHC_MINOR_VERSION%\\bin\\ghc.exe"
+ CABAL_VERSION: "2.4.0.0"
+ CABAL_OPTS: "-flua_32bits -fembed_data_files -fbibutils"
+ GHC_OPTS: "-fhide-source-paths"
+ ARCH: "x86"
+ CHOCO_OPTS: "--x86"
skip_commits:
files:
@@ -30,50 +43,53 @@ matrix:
fast_finish: true
cache:
- - "%STACK_ROOT%"
- - "%WIXBIN%"
- # This is where stack install ghc by default, but we don't
- # cache it because it's too large:
- # - "c:\\Users\\appveyor\\AppData\\Local\\Programs\\stack"
+ - '%CABAL_STORE%'
# Note: to reset build cache, do the following in JavaScript
# console on appveyor:
# $.ajax({ url: 'https://ci.appveyor.com/api/projects/jgm/pandoc/buildcache', type: 'DELETE'})
-# We don't do a normal C build, but build in test_script via stack
+
+# We don't do a normal C build, but build in test_script
build: off
install:
- - '"%WIXBIN%"\candle -? || choco install wixtoolset'
- - |
- %STACK% --version || curl -ostack.zip -L --insecure http://www.stackage.org/stack/%STACK_VERSION% && 7z e stack.zip -o"%STACK_ROOT%" stack.exe
+ - choco install wixtoolset --version 3.11.1 %CHOCO_OPTS%
+ - choco install ghc --version %GHC_VERSION% --ignore-dependencies %CHOCO_OPTS%
+ - choco install cabal --version %CABAL_VERSION% --ignore-dependencies %CHOCO_OPTS%
# before_test:
test_script:
- # The ugly echo "" hack is to avoid complaints about 0 being an invalid file
- # descriptor
- - |
- %STACK% setup > nul
- %STACK% path
- echo "" | %STACK% clean
- echo "" | %STACK% install %STACK_BUILD_OPTS% pandoc pandoc-citeproc %STACK_FLAGS%
+ # Note: we manually create cabal store, because of a cabal bug:
+ # see https://github.com/haskell/cabal/issues/5516
+ - if not exist "%CABAL_PACKAGE_DB%" ( mkdir "%CABAL_PACKAGE_DB%" )
+ - cabal --store-dir="%CABAL_STORE%" --version
+ - cabal --store-dir="%CABAL_STORE%" new-update
+ - cabal --store-dir="%CABAL_STORE%" new-configure -w %GHC% --enable-tests %CABAL_OPTS% --ghc-options="%GHC_OPTS%" . pandoc-citeproc
+ - cabal --store-dir="%CABAL_STORE%" new-build . pandoc-citeproc
+ - cabal --store-dir="%CABAL_STORE%" new-test . pandoc-citeproc
+ - forfiles /P .\dist-newstyle /M pandoc*.exe /S /C "cmd /C copy @path C:\pandoc\windows"
after_test:
- # .\ in the stack commandline seems to be .\windows\ (where the stack-appveyor.yaml is)
+ # create msi and zip artifacts
- cd windows
- .\pandoc.exe -s --toc ..\MANUAL.txt -o MANUAL.html
- .\pandoc.exe -s ..\COPYING.md -o COPYING.rtf
- copy ..\COPYRIGHT COPYRIGHT.txt
- - 7z a "pandoc-%STACK_VERSION%.zip" pandoc.exe pandoc-citeproc.exe MANUAL.html COPYING.rtf
+ - 7z a "pandoc-%OSARCH%.zip" pandoc.exe pandoc-citeproc.exe MANUAL.html COPYING.rtf
- |
set VERSION=
for /f "tokens=1-2 delims= " %%a in ('.\pandoc.exe --version') do ( if not defined VERSION set "VERSION=%%b" )
echo %VERSION%
- "%WIXBIN%\\candle" -dVERSION=%VERSION% -dBINPATH=. *.wxs -out wixobj\
- "%WIXBIN%\\light" -sw1076 -ext WixUIExtension -ext WixUtilExtension -cultures:en-us -loc Pandoc-en-us.wxl -out "pandoc-%STACK_VERSION%.msi" wixobj\*.wixobj
+ "%WIXBIN%"\candle -arch %ARCH% -dVERSION=%VERSION% -dBINPATH=. *.wxs -out wixobj\
+ "%WIXBIN%"\light -sw1076 -ext WixUIExtension -ext WixUtilExtension -cultures:en-us -loc Pandoc-en-us.wxl -out "pandoc-%OSARCH%.msi" wixobj\*.wixobj
+
+# for debugging
+# on_finish:
+# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
artifacts:
- - path: 'windows\pandoc-%STACK_VERSION%.zip'
+ - path: 'windows\pandoc-%OSARCH%.zip'
name: exe
- - path: 'windows\pandoc-%STACK_VERSION%.msi'
+ - path: 'windows\pandoc-%OSARCH%.msi'
name: msi
diff --git a/cabal.project b/cabal.project
new file mode 100644
index 000000000..861dbe6a5
--- /dev/null
+++ b/cabal.project
@@ -0,0 +1,7 @@
+packages: pandoc.cabal
+
+source-repository-package
+ type: git
+ location: https://github.com/jgm/pandoc-citeproc
+
+allow-newer: haddock-library:base
diff --git a/changelog b/changelog
index 285e39e2d..e01a19158 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,644 @@
+pandoc (2.3.1)
+
+ * RST reader:
+
+ + Parse RST inlines containing newlines (#4912, Francesco Occhipinti).
+ This eliminates a regression introduced after pandoc 2.1.1, which
+ caused inline constructions containing newlines not to be recognized.
+ + Fix bug with internal link targets (#4919). They were gobbling up
+ indented content underneath.
+
+ * Markdown reader: distinguish autolinks in the AST. With this change,
+ autolinks are parsed as Links with the `uri` class. (The same is true
+ for bare links, if the `autolink_bare_uris` extension is enabled.)
+ Email autolinks are parsed as Links with the `email` class. This
+ allows the distinction to be represented in the AST.
+
+ * Org reader:
+
+ + Force inline code blocks to honor export options (Brian Leung).
+ + Parse empty argument array in inline src blocks (Brian Leung).
+
+ * Muse reader (Alexander Krotov):
+
+ + Added additional tests.
+ + Do not allow code markup to be followed by digit.
+ + Remove heading level limit.
+ + Simplify `<literal>` tag parsers
+ + Parse Text instead of String. Benchmark shows 7% improvement.
+ + Get rid of HTML parser dependency.
+ + Various code improvements.
+
+ * ConTeXt writer: change `\` to `/` in Windows image paths (#4918).
+ We do this in the LaTeX writer, and it avoids problems.
+ Note that `/` works as a LaTeX path separator on Windows.
+
+ * LaTeX writer:
+
+ + Add support for multiprenote and multipostnote arguments
+ with `--biblatex` (Brian Leung, #4930). The multiprenotes occur before
+ the first prefix of a multicite, and the multipostnotes follow the
+ last suffix.
+ + Fix a use of `last` that might take empty list. If you ran with
+ `--biblatex` and have an empty document (metadata but no blocks),
+ pandoc would previously raise an error because of the use of
+ `last` on an empty list.
+
+ * RTF writer: Fix build failure with ghc-8.6.1 caused by missing
+ MonadFail instance (Jonas Scholl).
+
+ * ODT Writer: Improve table header row style handling (Nils Carlson).
+ This changes the way styles for cells in the header row
+ and normal rows are handled in ODT tables.
+ Previously a new (but identical) style was generated for
+ every table, specifying the style of the cells within the table.
+ After this change there are two style definitions for table cells,
+ one for the cells in the header row, one for all other cells.
+ This doesn't change the actual styles, but makes post-processing
+ changes to the table styles much simpler as it is no longer
+ necessary to introduce new styles for header rows and there are
+ now only two styles where there was previously one per table.
+
+ * HTML writer:
+
+ + Don't add `uri` class to presumed autolinks. Formerly the `uri`
+ class was added to autolinks by the HTML writer, but it had to
+ guess what was an autolink and could not distinguish
+ `[http://example.com](http://example.com)` from
+ `<http://example.com>`. It also incorrectly recognized
+ `[pandoc](pandoc)` as an autolink. Now the HTML writer
+ simply passes through the `uri` attribute if it is present,
+ but does not add anything.
+ + Avoid adding extra section nestings for revealjs.
+ Previously revealjs title slides at level (slidelevel - 1)
+ were nested under an extra section element, even when
+ the section contained no additional (vertical) content.
+ That caused problems for some transition effects.
+ + Omit unknown attributes in EPUB2 output. For example,
+ `epub:type` attributes should not be passed through,
+ or the epub produced will not validate.
+
+ * JATS writer: remove 'role' attribute on 'bold' and 'sc' elements (#4937).
+ The JATS spec does not allow these.
+
+ * Textile writer: don't represent `uri` class explicitly
+ for autolinks (#4913).
+
+ * Lua filters (Albert Krewinkel):
+
+ + Cleanup filter execution code.
+ + Better error on test failure.
+
+ * HTML, Muse reader tests: reduce time taken by round-trip test.
+
+ * Added cabal.project.
+
+ * MANUAL: `epub:type` is only useful for epub3 (Maura Bieg).
+
+ * Use hslua v1.0.0 (Albert Krewinkel).
+
+ * Fix `translations/ru` to use modern Russian orthography
+ (Ivan Trubach).
+
+ * Build Windows binary using ghc 8.6.1 and cabal new-build. This
+ fixes issues with segfaults in the 32-bit Windows binaries (#4283).
+
+pandoc (2.3)
+
+ * Add `--metadata-file` option (Mauro Bieg, #1960), which allows
+ users to specify metadata in a YAML file, regardless of the
+ input format (#1960).
+
+ * Text.Pandoc.Writers.Shared: export `isDisplayMath` (API change).
+
+ * Text.Pandoc.Readers.Markdown: export `yamlToMeta` (API change,
+ Mauro Bieg).
+
+ * Text.Pandoc.Readers.LaTeX.Types:
+
+ + New type `ArgSpec` (API change).
+ + Second parameter of `Macro` constructor is now `[ArgSpec]` instead of
+ `Int` (API change).
+
+ * Markdown reader:
+
+ + Use `tex` instead of `latex` for raw tex-ish content. We can't
+ always tell if it's LaTeX, ConTeXt, or plain TeX. Better just to
+ use `tex` always. Note that if `context` or `latex` specifically
+ is desired, you can still force that in a markdown document by
+ using the raw attribute. Note that this change may affect some
+ filters, if they assume that raw tex parsed by the Markdown reader
+ will be RawBlock (Format `latex`). In most cases it should be
+ trivial to modify the filters to accept `tex` as well.
+ + Refactor and reorganize YAML code (Mauro Bieg).
+ + Make `example_lists` work for interrupted lists
+ without `startnum` (#4908).
+
+ * HTML reader:
+
+ + Parse `<script type="math/tex` tags as math (#4877).
+ These are used by MathJax in some configurations.
+ + Extract spaces inside links instead of trimming them
+ (Alexander Krotov, #4845).
+ + Added round-trip tests (Alexander Krotov).
+ + Make parsing sensitive to the `raw_tex` extension (#1126). This now
+ allows raw LaTeX environments, `\ref`, and `\eqref` to be parsed
+ (which is helpful for translation HTML documents using MathJaX).
+
+ * Org reader (Albert Krewinkel):
+
+ + Respect export option `p` for planning info. Inclusion of planning info
+ (`*DEADLINE*`, `*SCHEDULED*`, and `*CLOSED*`) can be controlled via the
+ `p` export option: setting the option to `t` will add all planning
+ information in a *Plain* block below the respective headline.
+ + Org reader internals: don't rely on RecordWildCards and ViewPatterns
+ ghc extensions.
+ + Strip planning info from output. Planning info is parsed, but not
+ included in the output (as is the default with Emacs Org-mode, #4867).
+
+ * LaTeX reader:
+
+ + Split some general-purpose definitions into a separate, unexported
+ module, Text.Pandoc.Readers.LaTeX.Parsing. This is to avoid
+ out-of-memory errors compiling the LaTeX reader.
+ + Handle parameter patterns for `\def` (#4768, #4771).
+ For example: `\def\foo#1[#2]{#1 and #2}`.
+ + Allow `%` characters in URLs. This affects `\href` and `\url` (#4832).
+ + Fixed parsing of `\texorpdfstring`. We were returning the wrong
+ argument as the content.
+ + Support `blockcquote`, `foreignblockquote`, `foreigncblockquote`,
+ `hyphenblockquote`, `hyphencblockquote`, `enquote*`, `foreignquote`,
+ `hyphenquote` from `csquotes` (#4848). Note that `foreignquote`
+ will be parsed as a regular Quoted inline (not using the quotes
+ appropriate to the foreign language).
+ + Support more text-mode accents (#4652). Add support for `\|`, `\b`, `\G`,
+ `\h`, `\d`, `\f`, `\r`, `\t`, `\U`, `\i`, `\j`, `\newtie`,
+ `\textcircled`. Also fall back to combining characters when composed
+ characters are not available.
+ + Resolve `\ref` for figure numbers.
+ + Support `mintinline` (#4365, Marc Schreiber).
+ + Fix siunitx unit commands so they are only recognized in
+ siunitx contexts (#4842). For example, `\l` outside of an
+ siunitx context should be l-slash, not l (for liter).
+ + Fix double `unnumbered` class (#4838). The `unnumbered` class
+ was being included twice for starred sections.
+
+ * RST reader: Don't skip link definitions after comments (#4860).
+
+ * Muse reader (Alexander Krotov):
+
+ + Close the `</quote>` in indented tag test.
+ There is already a separate test for unclosed `</quote>`.
+ + Autonumber sections in the correct order. Parsing now stops
+ at each section header to ensure the header is registered before
+ parsing of the next section starts.
+ + Move duplicate code into `headingStart` function.
+ + Allow newline after opening `*` or `**`.
+ + Don't allow digits after closing marker in lightweight markup
+ This change makes reader more compatible with Emacs Muse.
+ + Parse `<verse>` tag in one pass instead of using
+ `parseFromString`. This change makes it possible to have
+ verbatim `</verse>` tag inside verse.
+
+ * ODT reader: deal gracefully with missing `<office:font-face-decls/>`
+ (#4336). This allows pandoc to parse ODT document produced by KDE's
+ Calligra.
+
+ * Muse writer (Alexander Krotov):
+
+ + Output headers without asterisks if not on the top level.
+ + Never wrap definition list terms.
+ + Set `envInsideBlock = True` when rendering notes.
+ + Use `""` instead of `[]` for empty String.
+ + Check for whitespace in the beginning and end of Str's.
+ + Escape `-`, `;` and `>` in the beginning of strings.
+ + Escape list markers in the beginning of notes.
+ + Normalize inline list before testing if tags should be used.
+ + Use tags instead of lightweight markup for empty strings.
+ + Use lightweight markup when possible.
+ + Escape empty strings. This guarantees that `conditionalEscapeString`
+ never returns empty string.
+ + Wrap conditionalEscapeString result into `Muse` type.
+ This removes the need to pass `envInsideLinkDescription` to it.
+ + Separate `shouldEscapeString` function.
+ + Simplify inline list rendering.
+ + Replace newlines in strings with spaces.
+
+ * Docx writer:
+
+ + Add MetaString case for abstract, subtitle (#4900, Mauro Bieg).
+ + Properly handle display math in spans (#4826). This isn't a
+ complete solution, since other nestings of display math may still
+ cause problems, but it should work for what is by far the most
+ common case.
+
+ * HTML writer:
+
+ + Always output `<dt>` element, even if it is empty (#4883,
+ Alexander Krotov).
+ + Don't prefix `epub:` attributes with `data-`.
+
+ * Org writer: Don't escape literal `_`, `^` (#4882). Org doesn't
+ recognize these escapes.
+
+ * ODT writer: Fix percentage image scaling (#4881, Nils Carlson).
+ Image scaling was broken when a width was set to a percentage.
+
+ * EPUB writer: set `epub:type` on body element in each chapter,
+ depending on the `epub:type` of the first section (#4823). This
+ only affects epub3. See
+ http://www.idpf.org/epub/profiles/edu/structure/#h.l0bzsloklt10
+
+ * FB2 writer: put `coverpage` element between title and date rather than in
+ `document-info` element (#4854).
+
+ * Markdown writer: Escape `~` if strikeout extension enabled (#4840).
+
+ * Haddock writer: Use proper format for latex math in haddock (#4571, Joe
+ Hermaszewski). Inline math in `\(..\)`, display math in `\[..\]`,
+ tex is now used. Previously we'd "fake it with unicode" and fall
+ back to tex when that didn't work. But newer haddock versions
+ support latex math.
+
+ * TEI writer:
+
+ + Ensure that title element is always present, even if empty (#4839).
+ + Put author tags in the template, rather than adding them in
+ the writer (#4839).
+
+ * LaTeX writer/template: be sensitive to `filecolor` variable (#4822).
+ `linkcolor` only affects internal links, and `urlcolor` only
+ affects linked URLs. For external links, the option to use is
+ `filecolor`.
+
+ * ConTeXt writer: output raw `tex` blocks as well as `context` (#969).
+
+ * RST writer:
+
+ + Use `.. raw:: latex` for `tex` content.
+ + Use `.. container` for generic Divs, instead of raw HTML.
+ + Render Divs with admonition classes as admonitions (#4833).
+ Also omit Div with class `admonition-title`. These are generated
+ by the RST reader and should be omitted on round-trip.
+
+ * Text.Pandoc.PDF: fix message printed when rsvg-convert is not available
+ (#4855, Antonio Terceiro).
+
+ * HTML5 template: add the `title-block-header` identifier to the
+ `header` element, to make it easier to style precisely (#4767,
+ J. B. Rainsberger).
+
+ * OpenDocument template: Remove unnecessary indenting of TOC title (#4798,
+ José de Mattos Neto).
+
+ * latex template: Add support for $toc-title$ to LaTeX (and PDF)
+ (#4853, Wandmalfarbe).
+
+ * TEI template: improve `publicationStmt`. Add support for
+ `publisher`, `address`, `pubPlace`, and `date` variables.
+
+ * beamer template: Support "toc-title" (#4835, Cyril Roelandt).
+
+ * Text.Pandoc.Extensions: Fix haddock on `Ext_footnotes` (Chris Martin).
+
+ * Lua: cleanup Lua utils, remove unused functions (Albert Krewinkel).
+
+ * MANUAL.txt:
+
+ + Clarify that `--biblatex/--natbib` don't work directly for PDF
+ (#4904).
+ + Document `epub:type` attribute (Mauro Bieg, #4901)
+ + Clarify when `--resource-path` has an effect.
+ + More detail on customization in syntax highlighting section.
+ + Document encoding issue with `--listings` (#4871, Damien Clochard).
+ + Remove docs on removed `--katex-stylesheet` (Mauro Bieg, #4862).
+ + Use https for context wiki links (#4910).
+
+ * CONTRIBUTING.md:
+
+ + Link to lua-filters repository (#4874).
+ + Fix mistake in REPL instructions for stack. (#4849, Brian Leung).
+
+ * lua-filters.md: add links to filters, and to lua-filters repository
+ (#4874).
+
+ * INSTALL.md:
+
+ + Indicate that cabal >= 2.0 is needed.
+ + Added chocolatey installation method (#4844, Miodrag Milić).
+
+ * Travis: exclude round-trip tests, except for nightly test which can fail.
+
+ * Use latest texmath, pandoc-citeproc.
+
+ * Use a patched version of foundation until
+ https://github.com/haskell-foundation/foundation/pull/503
+ is fixed.
+
+ * Clean up appveyor build and Windows package creation.
+ We now use 64-bit stack and ghc 8.4.3, lts-12 for the 64-bit build. The
+ WiX-based msi is now 64-bit for 64-bit builds (fixing #4795).
+
+ * Remove obsolete RELEASE-CHECKLIST.md.
+
+ * Added additional compiler warnings in Makefile and CI builds.
+
+pandoc (2.2.3.2)
+
+ * Markdown reader: Properly handle boolean values in YAML metadata (#4819).
+ This fixes a regression in 2.2.3, which cause boolean values to
+ be parsed as MetaInlines instead of MetaBool.
+
+ We here record another undocumented (but desirable) change in 2.2.3:
+ numerical metadata fields are now parsed as MetaInlines rather than
+ MetaString.
+
+pandoc (2.2.3.1)
+
+ * Markdown reader: Fix parsing of embedded mappings in YAML metadata
+ (#4817). This fixes a regression in 2.2.3 which caused embedded
+ mappings (e.g. mappings in sequences) not to work in YAML metadata.
+
+pandoc (2.2.3)
+
+ * RST reader: improve parsing of inline interpreted text roles (#4811).
+
+ + Use a Span with class "title-reference" for the default
+ title-reference role.
+ + Use `B.text` to split up contents into `Space`s, `SoftBreak`s,
+ and `Str`s for `title-reference`.
+ + Use Code with class "interpreted-text" instead of Span and Str for
+ unknown roles. (The RST writer has also been modified to round-trip
+ this properly.)
+ + Disallow blank lines in interpreted text.
+ + Backslash-escape now works in interpreted text.
+ + Backticks followed by alphanumerics no longer end interpreted text.
+ + Remove support for nested inlines (Francesco Occhipinti).
+ RST does not allow nested emphasis, links, or other inline
+ constructs. This fixes several bugs (#4581, #4561, #4792).
+
+ * Org reader: fix parsers relying on `parseFromString` (#4784, Albert
+ Krewinkel). Emphasis was not parsed when it followed directly after
+ some block types (e.g., lists).
+
+ * Markdown reader: Allow unquoted numbers and booleans as YAML mapping
+ keys. Previously in 2.2.2 you could not do
+ ```
+ ---
+ 0: bar
+ ...
+ ```
+ but only
+ ```
+ ---
+ '0': bar
+ ...
+ ```
+ With this change, both forms work.
+
+ * DocBook reader: metadata handling improvements.
+ Now we properly parse title and subtitle elements that are direct
+ children of book and article (as well as children of bookinfo,
+ articleinfo, or info). We also now use the `subtitle` metadata
+ field for subtitles, rather than tacking the subtitle on to the
+ title.
+
+ * RST writer:
+
+ + Allow images to be directly nested within links (#4810, Francesco
+ Occhipinti).
+ + Use `titleblock` instead of `title` variable for title block (#4803,
+ Francesco Occhipinti). `titleblock` contains a properly formatted
+ title and subtitle (using top-level headers). `title` and
+ `subtitle` variables are still available and just contain the
+ title and subtitle text. Note that this change will require an
+ update to custom rst templates.
+ + Render Code with class "interpreted-text" as interpreted text role.
+
+ * MediaWiki writer: Avoid extra blank line in tables with empty cells
+ (#4794). Note that the old output is semantically identical, but the
+ new output looks better.
+
+ * Lua Utils module: add function `blocks_to_inlines` (#4799, Albert
+ Krewinkel). Exposes a function converting which flattenes a list of
+ blocks into a list of inlines. An example use case would be the
+ conversion of Note elements into other inlines.
+
+ * RST template: use `titleblock` instead of `title`. Users of
+ custom RST templates will want to update this.
+
+ * LaTeX template: Moved some beamer code in default.latex template.
+ This change allows beamer themes to change the template and font (as
+ Metropolis does) (#4450).
+
+ * Better error message on `-t pdf -o out.pdf` (#1155, Mauro Bieg).
+
+ * Added test case for #4669 to repository.
+
+ * INSTALL.md: Fix broken link for cabal-install (#4806, ChanHoHo).
+
+ * MANUAL.txt:
+
+ + Add beamer info for slide backgrounds (#4802, John Muccigrosso).
+ + Clarify when `csquotes` is used in LaTeX writer (#4514).
+ + Add `commonmark` to list of output formats where `raw_tex` has an
+ effect (see #4527).
+
+
+pandoc (2.2.2.1)
+
+ * Fix regression finding templates in user data directory (#4777).
+ Under version 2.2.1 and prior pandoc found latex templates in the
+ templates directory under the data directory, but this broke in 2.2.2.
+
+ * Fix for bug in parsing `\input` in `rawLaTeXBlock` and
+ `rawLaTeXInline` (#4781). (This primarily affects the markdown
+ reader, and other readers that accept raw tex.)
+ Starting in 2.2.2, everything after an `\input` (or `\include`)
+ in a markdown file would be parsed as raw LaTeX.
+
+ * MANUAL:
+
+ + Clarify `gfm` vs `markdown_github` (#4783, Mauro Bieg).
+ * Use `keywords` instead of `tags` in YAML metadata example (#4779).
+ Unlike `tags`, `keywords` is used in some of the writers
+ and default templates.
+
+ * Add missing `rollingLinks` option to revealjs template (#4778,
+ Igor Khorlo).
+
+pandoc (2.2.2)
+
+ * Use HsYAML instead of yaml for translations and YAML metadata (#4747).
+ yaml wraps a C library; HsYAML is pure Haskell. Advances #4535.
+
+ Note: HsYAML implements YAML 1.2, in which the valid true
+ values are `true`, `True`, `TRUE`. This means a change in
+ the semantics of YAML metadata that could affect users:
+ `y`, `yes`, and `on` no longer count as true values.
+
+ * Fix regression: make `--pdf-engine` work with full paths (#4681, Mauro
+ Bieg).
+
+ * CommonMark reader: Handle `ascii_identifiers` extension (#4742,
+ Anders Waldenborg). Non-ascii characters were not stripped from
+ identifiers even if the `ascii_identifiers` extension was
+ enabled (which is is by default for gfm).
+
+ * TikiWiki reader: Improve list parsing (#4722, Mauro Bieg).
+ Remove trailing Space from list items. Parse lists that have no space
+ after marker.
+
+ * LaTeX reader:
+
+ + Treat `lilypond` as a verbatim environment (#4725).
+ + Parse figure label into Image id (#4700, Mauro Bieg).
+ + Beamer: Allow "noframenumbering" option (#4696, Raymond Ehlers).
+ + Allow spaces around `\graphicspath` arguments (#4698).
+ + Handle includes without surrounding blanklines (#4553).
+ In addition, `\input` can now be used in an inline context,
+ e.g. to provide part of a paragraph, as it can in LaTeX.
+ + In `rawLaTeXBlock`, handle macros that resolve to a
+ `\begin` or `\end` (#4667).
+ + In `rawLaTeXBlock`, don't expand macros in macro definitions (#4653).
+ Note that this only affected LaTeX in markdown.
+ + Tighten up reading of beamer overlay specifications (#4669).
+ Ideally we'd turn these on only when reading beamer, but currently
+ beamer is not distinguished from latex as an input format.
+ This commit also activates parsing of overlay specifications
+ after commands in general (e.g. `\item`), since they can occur
+ in many contexts in beamer.
+ + Parse more siunitx unit commands (#4296, #4773).
+ + Be more forgiving in key/value option parsing (#4761).
+
+ * Markdown reader:
+
+ + Allow empty code spans, e.g. `` ` ` ``.
+ + Emojis are now wrapped in Spans with class `emoji` and
+ attribute `data-emoji` (Anders Waldenborg, #4743).
+ This allows the writer to handle them in a special way
+ (e.g. using a special font, or just rendering the
+ emoji name).
+
+ * Muse reader (Alexander Krotov, except where indicated):
+
+ + Get rid of non-exhaustive pattern match warning (Mauro Bieg).
+ + Add support for floating images.
+ + Add support for images with specified width.
+ + Parse image URLs without "guard" and "takeExtension".
+ + Split link and image parsing into separate functions.
+ + Parse links starting with "URL:" explicitly instead of trying to strip
+ "URL:" prefix after parsing.
+
+ * Texinfo writer: Use `@sup` and `@sub` instead of custom macros (#4728,
+ Alexander Krotov).
+
+ * Markdown writer: Preserve `implicit_figures` with attributes, even if
+ `implicit_attributes` is not set, by rendering in raw HTML (#4677).
+
+ * Markdown and commonmark/github writers now respect the `emoji`
+ extension. So, `-f markdown+emoji -t markdown+emoji` now leaves
+ `:smile:` as `:smile:` rather than converting it to a smile
+ character.
+
+ * Docx writer: Be sensitive to `toc` in YAML metadata (#4645).
+
+ * ODT/OpenDocument writer: Make internal links work (#4358).
+ This adds proper bookmarks to the headers with non-null IDs.
+
+ * EPUB writer: Properly escape pagetitle. Previously we weren't
+ escaping `&` and other XML characters in the pagetitle, so a title
+ containing a `&` would be invalid.
+
+ * AsciiDoc Writer: Eescape square brackets at start of line (#4545,
+ Mauro Bieg).
+
+ * RST writer:
+
+ + Don't treat 'example' as a syntax name (#4748).
+ This fixes conversions from org with example blocks.
+ + Support `--number-sections` via the `section-numbering`
+ directive in standalone output.
+
+ * reveal.js writer and template: reuse mathjax URL
+ provided by the argument to `--mathjax` or the normal pandoc default,
+ rather than a hard-coded one in the template (#4701).
+
+ * LaTeX writer:
+
+ + Properly handle footnotes in table captions (#4683).
+ Refactored code from figure captions to use in both places.
+ + In beamer output, fix single digit column percentage (#4690, Mauro
+ Bieg).
+
+ * FB2 writer (Alexander Krotov):
+
+ + Convert Plain to Para in annotation (#2424).
+ + Fix order of items in title-info (#2424).
+
+ * Custom writer: fix error message on script failure (Albert Krewinkel).
+ Error messages produced by Lua were not displayed by Pandoc.
+
+ * Text.Pandoc.Emoji now exports `emojiToInline`, which returns a Span
+ inline containing the emoji character and some attributes with metadata
+ (class `emoji`, attribute `data-emoji` with emoji name). (API change,
+ Anders Waldenborg, #4743).
+
+ * Text.Pandoc.PDF:
+
+ + Revert fix for #4484 (only compress images on last run, #4755).
+ This will mean some increase in the time it takes to
+ produce an image-heavy PDF with xelatex, but it will
+ make tables of contents correct, which is more important.
+ + Fix logic error in `runTeXProgram`. We were running the tex program
+ one more time than requested. This should speed up PDF production.
+
+ * Allow `--template` to take a URL as argument.
+
+ * Text.Pandoc.Highlighting: Add missing re-export of `breezeDark`
+ highlighting style (#4687, Adrian Sieber, API change).
+
+ * Clarify macOS install in INSTALL.md (#4661). Make the binary package
+ installer the recommended method, and note that on some older versions of
+ macOS, homebrew installs from source and takes a lot of disk space
+ (#4664, Ian).
+
+ * MANUAL:
+
+ + Clarify EPUB linked media (#4756, Mauro Bieg)
+ + Update manual for "true" YAML values. Now that we're using HsYAML and
+ YAML 1.2, the valid true values are `true`, `True`, `TRUE`. NOTE!
+ `y`, `yes`, `on` no longer count as true values.
+ + Document `-F` as alias for `--filter` (thanks to Gandalf Saxe).
+ + Update manual on how math is rendered in LaTeX.
+ + Add proxy description (#4131, Mauro Bieg).
+ + Clarify that `--toc` requires `--standalone` (#4703).
+ + Update citation styles link (#4699, wiefling).
+
+ * In API docs, clarify how `Ext_east_asian_line_breaks` extension works
+ (kaizshang91). Note that it will not take effect when readers/writers
+ are called as libraries (#4674).
+
+ * Improved translations/fr (#4766, lux-lth).
+
+ * Removed inadvertently added `.orig` files from repository (#4648).
+
+ * Remove `network-uri` flag and use 'Network.Socket'.
+ This removes a compiler warning. There is no need for the old
+ `network-uri` flag, since network 2.6 was released in 2014.
+
+ * Add stack.lts10.yaml, stack.lts11.yaml. use lts-12 in stack.yaml.
+
+ * Bump upper bounds for dependent packages.
+
+ * Exclude foundation 0.0.21 for ghc 7.10. Otherwise cabal gets
+ confused because of the way ghc 7.10 is excluded in foundation's
+ cabal file. This can be removed when haskell-foundation/foundation#500
+ is fixed.
+
+ * Require cabal-version >= 2.0. This is needed for haddock-library.
+
+
pandoc (2.2.1)
* Restored and undeprecated gladtex for HTML math (#4607).
@@ -432,7 +1073,7 @@ pandoc (2.1.3)
* JATS writer: Remove extraneous, significant whitespace (#4335,
Nokome Bentley).
- * html2pdf: inject base tag wih current working directory (#4413, Mauro
+ * html2pdf: inject base tag with current working directory (#4413, Mauro
Bieg). This helps ensure that linked resources are included.
* Add Semigroup instances for everything for which we defined a
@@ -580,7 +1221,7 @@ pandoc (2.1.2)
* Docx reader (Jesse Rosenthal, except where noted):
+ Handle nested sdt tags (#4415).
- + Don't look up dependant run styles if `+styles` is enabled.
+ + Don't look up dependent run styles if `+styles` is enabled.
+ Move pandoc inline styling inside custom-style span.
+ Read custom styles (#1843). This will read all paragraph and
character classes as divs and spans, respectively. Dependent styles
@@ -2283,7 +2924,7 @@ pandoc (2.0)
* Removed `hard_line_breaks` extension from `markdown_github` (#3594).
GitHub has two Markdown modes, one for long-form documents like READMEs
- and one for short things like issue coments. In issue comments, a line
+ and one for short things like issue comments. In issue comments, a line
break is treated as a hard line break. In README, wikis, etc., it is
treated as a space as in regular Markdown. Since pandoc is more likely to
be used to convert long-form documents from GitHub Markdown,
@@ -2416,6 +3057,11 @@ pandoc (2.0)
(since the two-space version of a line break doesn't work inside ATX
headers, and neither version works inside Setext headers).
+ + A space between the opening # and the header is now required for
+ pandoc and GitHub markdown (but not the other flavors). Disable
+ the `space_in_atx_header` extension (#3512) to restore the
+ original behavior.
+
* Org reader (Albert Krewinkel, unless noted):
@@ -2636,7 +3282,7 @@ pandoc (2.0)
top-level `Text.Pandoc` module.
+ Changed `StringWriter` -> `TextWriter`.
- + `getWriter` now retuns a pair of a reader and
+ + `getWriter` now returns a pair of a reader and
`Extensions`, instead of building the extensions into the
reader (#3659). The calling code must explicitly set
`readerExtensions` using the `Extensions` returned. The
@@ -3049,7 +3695,7 @@ pandoc (2.0)
of item disappear or are misplaced. Use `\texttt` instead.
+ Fix problem with escaping in `lstinline` (#1629). Previously the
LaTeX writer created invalid LaTeX when `--listings` was specified and
- a code span occured inside emphasis or another construction.
+ a code span occurred inside emphasis or another construction.
+ Fix error with line breaks after empty content (#2874). LaTeX
requires something before a line break, so we insert a `~` if no
printable content has yet been emitted.
@@ -3156,7 +3802,7 @@ pandoc (2.0)
+ Don't drop smartTag contents (#2242).
+ Handle local namespace declarations (#3365). Previously we didn't
- recognize math, for example, when the xmlns declaration occured on
+ recognize math, for example, when the xmlns declaration occurred on
the element and not the root.
+ More efficient trimSps (#1530). Replacing `trimLineBreaks`. This
does the work of `normalizeSpaces` as well, so we avoid the need for
@@ -3390,7 +4036,7 @@ pandoc (2.0)
+ Allow `]` inside group in option brackets (#3857).
+ lstinline with braces can be used (verb cannot be used with braces)
(Marc Schreiber, #3535).
- + Fix keyval funtion: pandoc did not parse options in braces correctly
+ + Fix keyval function: pandoc did not parse options in braces correctly
(Marc Schreiber, #3642).
+ When parsing raw LaTeX commands, include trailing space (#1773).
Otherwise things like `\noindent foo` break and turn into
@@ -3482,7 +4128,7 @@ pandoc (2.0)
parse, the parser was applied too often, consuming too much of the
input. This only affects `many1Till p end` where `p` matches on a
prefix of `end`.
- + Provide `parseFromString` (#3690). This is a verison of
+ + Provide `parseFromString` (#3690). This is a version of
`parseFromString` specialied to ParserState, which resets
`stateLastStrPos` at the end. This is almost always what we want.
This fixes a bug where `_hi_` wasn't treated as emphasis in the
@@ -3588,7 +4234,7 @@ pandoc (2.0)
+ Use `unicode-math` (Vaclav Haisman). Use `mathspec` with only
XeLaTeX on request.
+ Don't load `fontspec` before `unicode-math` (over there).
- The `unicode-math` package loads `fontspec` so explict loading of
+ The `unicode-math` package loads `fontspec` so explicit loading of
`fontspec` before `unicode-math` is not necessary.
+ Use `unicode-math` by default in default.latex template. mathspec will
be used in xelatex if the `mathspec` variable is set; otherwise
@@ -4241,7 +4887,7 @@ pandoc (1.18)
is now used in parsing RST and Markdown line blocks, DocBook
`linegroup`/`line` combinations, and Org-mode `VERSE` blocks.
Previously `Para` blocks with hard linebreaks were used. `LineBlock`s
- are handled specially in the following ouput formats: AsciiDoc
+ are handled specially in the following output formats: AsciiDoc
(as `[verse]` blocks), ConTeXt (`\startlines`/`\endlines`),
HTML (`div` with a style), Markdown (line blocks if `line_blocks`
is enabled), Org-mode (`VERSE` blocks), RST (line blocks). In
@@ -4388,7 +5034,7 @@ pandoc (1.18)
comma-separated list.
+ Give precedence to later meta lines. The last meta-line of any given
type is the significant line. Previously the value of the first line
- was kept, even if more lines of the same type were encounterd.
+ was kept, even if more lines of the same type were encountered.
+ Read LaTeX_header as header-includes. LaTeX-specific header commands
can be defined in `#+LaTeX_header` lines. They are parsed as
format-specific inlines to ensure that they will only show up in LaTeX
@@ -4436,7 +5082,7 @@ pandoc (1.18)
be able to figure out internal links to a header in a docx if the
anchor span was empty. We change that to read the inlines out of the
first anchor span in a header.
- + Let headers use exisiting id. Previously we always generated an id for
+ + Let headers use existing id. Previously we always generated an id for
headers (since they wouldn't bring one from Docx). Now we let it use an
existing one if possible. This should allow us to recurs through anchor
spans.
@@ -4543,7 +5189,7 @@ pandoc (1.18)
+ Don't emit HTML for tables unless `raw_html` extension is set (#3154).
Emit `[TABLE]` if no suitable table formats are enabled and raw HTML
is disabled.
- + Check for the `raw_html` extension before emiting a raw HTML block.
+ + Check for the `raw_html` extension before emitting a raw HTML block.
+ Abstract out note/ref function (Jesse Rosenthal).
+ Add ReaderT monad for environment variables (Jesse Rosenthal).
@@ -5023,7 +5669,7 @@ pandoc (1.17.1)
character. Empty rows where parsed as alignment rows and dropped from
the output.
+ Fix spacing after LaTeX-style symbols.
- The org-reader was droping space after unescaped LaTeX-style symbol
+ The org-reader was dropping space after unescaped LaTeX-style symbol
commands: `\ForAll \Auml` resulted in `∀Ä` but should give `∀ Ä`
instead. This seems to be because the LaTeX-reader treats the
command-terminating space as part of the command. Dropping the trailing
@@ -5117,7 +5763,7 @@ pandoc (1.17.1)
+ Clarified documentation of `implicit_header_references` (#2904).
+ Improved documentation of `--columns` option.
- * Added appveyor setup, with artefacts (Jan Schulz).
+ * Added appveyor setup, with artifacts (Jan Schulz).
* stack.yaml versions: Use proper flags used for texmath, pandoc-citeproc.
@@ -5356,7 +6002,7 @@ pandoc (1.16.0.1)
* Entity handling fixes: improved handling of entities like
`&lang;` that require a trailing semicolon. Allow uppercase
- `x` in numerical hexidecimal character references, working
+ `x` in numerical hexadecimal character references, working
around a tagsoup bug.
* `stack.yaml` - use lts-4.0, but with older aeson to avoid excessive
@@ -6852,7 +7498,7 @@ pandoc (1.14)
* `Text.Pandoc.Shared`:
+ Make safeRead safe (#1801, Matthew Pickering).
- + Addded `mapLeft`, `hush` (Matthew Pickering).
+ + Added `mapLeft`, `hush` (Matthew Pickering).
* `Text.Pandoc.Pretty`:
@@ -6920,7 +7566,7 @@ pandoc (1.14)
+ Use `text:p` instead of `text:h` for title.
Using `text:h` causes problems with numbering. Closes #2059.
- Thansk to @nkalvi for diagnosing this.
+ Thanks to @nkalvi for diagnosing this.
* reveal.js template:
@@ -7003,7 +7649,7 @@ pandoc (1.13.2.1)
pandoc (1.13.2)
- * TWiki Reader: add new new twiki reader (API change, Alexander Sulfrian).
+ * TWiki Reader: add new twiki reader (API change, Alexander Sulfrian).
* Markdown reader:
@@ -7026,7 +7672,7 @@ pandoc (1.13.2)
+ Parse RST class directives. The class directive accepts one or more
class names, and creates a Div value with those classes. If the
directive has an indented body, the body is parsed as the children of
- the Div. If not, the first block folowing the directive is made a
+ the Div. If not, the first block following the directive is made a
child of the Div. This differs from the behavior of rst2xml, which
does not create a Div element. Instead, the specified classes are
applied to each child of the directive. However, most Pandoc Block
@@ -7971,7 +8617,7 @@ pandoc (1.13)
different versions of the `directory` library.
+ Added `Text.Pandoc.Compat.Except` to allow building against
- different verions of `mtl`.
+ different versions of `mtl`.
* Code cleanup in some writers, using Reader monad to avoid
passing options parameter around (Matej Kollar).
@@ -8631,7 +9277,7 @@ pandoc (1.12.2)
+ Parse contents of curly quotes or matched `"` as quotes.
+ Support `\textnormal` as span with class `nodecor`.
This is needed for pandoc-citeproc.
- + Improved citation parsing. This fixes a run-time error that occured
+ + Improved citation parsing. This fixes a run-time error that occurred
with `\citet{}` (empty list of keys). It also ensures that empty keys
don't get produced.
@@ -8914,7 +9560,7 @@ pandoc (1.12)
to make that the current directory before running pandoc. (#942)
* Better error reporting in some readers, due to changes in `readWith`:
- the line in which the error occured is printed, with a caret pointing
+ the line in which the error occurred is printed, with a caret pointing
to the column.
* All slide formats now support incremental slide view for definition lists.
@@ -9608,7 +10254,7 @@ pandoc (1.11)
+ Include HTML TOC, even in epub2. The TOC is included in `<spine>`,
but `linear` is set to `no` unless the `--toc` option is specified.
Include `<guide>` element in OPF. This should allow the TOC to
- be useable in Kindles when converted with kindlegen. Closes #773.
+ be usable in Kindles when converted with kindlegen. Closes #773.
* `Text.Pandoc.Parsing`: Optimized `oneOfStringsCI`.
This dramatically reduces the speed penalty that comes from enabling the
@@ -9973,7 +10619,7 @@ pandoc (1.10)
[API changes]
* `Text.Pandoc.Definition`: Added `Attr` field to `Header`.
- Previously header identifers were autogenerated by the writers.
+ Previously header identifiers were autogenerated by the writers.
Now they are added in the readers (either automatically or explicitly).
* `Text.Pandoc.Builder`:
@@ -10210,7 +10856,7 @@ pandoc (1.10)
incorrectly implented RST-style autolinks for URLs and email
addresses. This has been fixed. Now an autolink is done this way:
`"$":http://myurl.com`.
- + Fixed footnotes bug in textile. This affected notes occuring
+ + Fixed footnotes bug in textile. This affected notes occurring
before punctuation, e.g. `foo[1].`. Closes #518.
* LaTeX reader:
@@ -11243,7 +11889,7 @@ pandoc (1.9)
Items are no longer installed as root.
Man pages are zipped and given proper permissions.
- * Modified windows installer generater to use cabal-dev.
+ * Modified windows installer generator to use cabal-dev.
* Setup: Making man pages now works with cabal-dev (at least on OSX). In
Setup.hs we now invoke 'runghc' in a way that points it to the correct
@@ -12286,7 +12932,7 @@ pandoc (1.5)
better browsers) as text/html.
+ Removed Text.Pandoc.LaTeXMathML. The module was no longer
necessary; it was replaced by two lines in pandoc.hs.
- + Replaced LaTeXMathML.js.commend and LaTeXMathML.js.packed with a
+ + Replaced LaTeXMathML.js.comment and LaTeXMathML.js.packed with a
single combined file, LaTeXMathML.js.
* Added --data-dir option.
@@ -12520,7 +13166,7 @@ pandoc (1.4)
* Replaced old headers with templates. Now users have much more
control over the way documents appear in --standalone mode,
and writer code is simplified. Resolves Issues #59, 147.
- Every effort has been made to retain backwards compatibilty.
+ Every effort has been made to retain backwards compatibility.
So, the --custom-header option should still work as before.
+ Added Text.Pandoc.Templates. This provides functions for
@@ -13488,7 +14134,7 @@ pandoc (0.46) unstable; urgency=low
+ Don't interpret contents of style tags as markdown.
(Resolves Issue #40.)
- - Added htmlStyle, analagous to htmlScript.
+ - Added htmlStyle, analogous to htmlScript.
- Use htmlStyle in htmlBlockElement and rawHtmlInline.
- Moved "script" from the list of tags that can be either block or
inline to the list of block tags.
@@ -14267,7 +14913,7 @@ pandoc (0.4) unstable; urgency=low
notes and add information to state. (Reference keys may be needed
at this stage.) Finally, parse everything else.
+ Replaced named constants like 'emphStart' with literals.
- + Removed an extra occurance of escapedChar in definition of inline.
+ + Removed an extra occurrence of escapedChar in definition of inline.
* RST reader:
@@ -14307,7 +14953,7 @@ pandoc (0.4) unstable; urgency=low
+ The Html header is now written programmatically, so it has been
removed from the 'headers' directory. The S5 header is still
needed, but the doctype and some of the meta declarations have
- been removed, since they are written programatically. This change
+ been removed, since they are written programmatically. This change
introduces a new dependency on the xhtml package.
+ Fixed two bugs in email obfuscation involving improper escaping
of '&' in the `<noscript>` section and in `--strict` mode. Resolves
@@ -14616,7 +15262,7 @@ pandoc (0.3) unstable; urgency=low
+ win-pkg target creates Windows binary package.
+ tarball target creates distribution source tarball.
+ website target generates pandoc's website automatically, including
- demos. New 'web' directory containts files needed for construction
+ demos. New 'web' directory contains files needed for construction
of the website (which will be created as the 'pandoc' subdirectory
of 'web').
+ Makefile checks to see if we're running Windows/Cygwin; if so,
diff --git a/data/pandoc.lua b/data/pandoc.lua
index 512b2919c..54370bd1b 100644
--- a/data/pandoc.lua
+++ b/data/pandoc.lua
@@ -124,7 +124,7 @@ Type.behavior = {
Type.behavior.__index = Type.behavior
--- Set a new behavior for the type, inheriting that of the parent type if none
---- is specified explicitely
+--- is specified explicitly
-- @param behavior the behavior object for this type.
-- @local
function Type:set_behavior (behavior)
@@ -487,7 +487,7 @@ M.Cite = M.Inline:create_constructor(
--- Creates a Code inline element
-- @function Code
--- @tparam string text brief image description
+-- @tparam string text code string
-- @tparam[opt] Attr attr additional attributes
-- @treturn Inline code element
M.Code = M.Inline:create_constructor(
diff --git a/data/templates/default.epub3 b/data/templates/default.epub3
index b22714963..6428e984c 100644
--- a/data/templates/default.epub3
+++ b/data/templates/default.epub3
@@ -26,7 +26,7 @@ $for(header-includes)$
$header-includes$
$endfor$
</head>
-<body$if(coverpage)$ id="cover"$endif$>
+<body$if(coverpage)$ id="cover"$endif$$if(body-type)$ epub:type="$body-type$"$endif$>
$if(titlepage)$
<section epub:type="titlepage">
$for(title)$
diff --git a/data/templates/default.html5 b/data/templates/default.html5
index 9c15107c0..c2bf0e093 100644
--- a/data/templates/default.html5
+++ b/data/templates/default.html5
@@ -46,7 +46,7 @@ $for(include-before)$
$include-before$
$endfor$
$if(title)$
-<header>
+<header id="title-block-header">
<h1 class="title">$title$</h1>
$if(subtitle)$
<p class="subtitle">$subtitle$</p>
diff --git a/data/templates/default.latex b/data/templates/default.latex
index 31093374f..e64b216eb 100644
--- a/data/templates/default.latex
+++ b/data/templates/default.latex
@@ -1,4 +1,4 @@
-\PassOptionsToPackage{unicode=true}{hyperref} % options for packages loaded elsewhere
+\PassOptionsToPackage{unicode=true$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref} % options for packages loaded elsewhere
\PassOptionsToPackage{hyphens}{url}
$if(colorlinks)$
\PassOptionsToPackage{dvipsnames,svgnames*,x11names*}{xcolor}
@@ -20,6 +20,41 @@ $endif$
$for(beameroption)$
\setbeameroption{$beameroption$}
$endfor$
+% Prevent slide breaks in the middle of a paragraph:
+\widowpenalties 1 10000
+\raggedbottom
+$if(section-titles)$
+\setbeamertemplate{part page}{
+\centering
+\begin{beamercolorbox}[sep=16pt,center]{part title}
+ \usebeamerfont{part title}\insertpart\par
+\end{beamercolorbox}
+}
+\setbeamertemplate{section page}{
+\centering
+\begin{beamercolorbox}[sep=12pt,center]{part title}
+ \usebeamerfont{section title}\insertsection\par
+\end{beamercolorbox}
+}
+\setbeamertemplate{subsection page}{
+\centering
+\begin{beamercolorbox}[sep=8pt,center]{part title}
+ \usebeamerfont{subsection title}\insertsubsection\par
+\end{beamercolorbox}
+}
+\AtBeginPart{
+ \frame{\partpage}
+}
+\AtBeginSection{
+ \ifbibliography
+ \else
+ \frame{\sectionpage}
+ \fi
+}
+\AtBeginSubsection{
+ \frame{\subsectionpage}
+}
+$endif$
$endif$
$if(beamerarticle)$
\usepackage{beamerarticle} % needs to be loaded first
@@ -148,6 +183,7 @@ $endif$
$if(colorlinks)$
colorlinks=true,
linkcolor=$if(linkcolor)$$linkcolor$$else$Maroon$endif$,
+ filecolor=$if(filecolor)$$filecolor$$else$Maroon$endif$,
citecolor=$if(citecolor)$$citecolor$$else$Blue$endif$,
urlcolor=$if(urlcolor)$$urlcolor$$else$Blue$endif$,
$else$
@@ -198,43 +234,6 @@ $if(graphics)$
% using explicit options in \includegraphics[width, height, ...]{}
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
$endif$
-$if(beamer)$
-% Prevent slide breaks in the middle of a paragraph:
-\widowpenalties 1 10000
-\raggedbottom
-$if(section-titles)$
-\setbeamertemplate{part page}{
-\centering
-\begin{beamercolorbox}[sep=16pt,center]{part title}
- \usebeamerfont{part title}\insertpart\par
-\end{beamercolorbox}
-}
-\setbeamertemplate{section page}{
-\centering
-\begin{beamercolorbox}[sep=12pt,center]{part title}
- \usebeamerfont{section title}\insertsection\par
-\end{beamercolorbox}
-}
-\setbeamertemplate{subsection page}{
-\centering
-\begin{beamercolorbox}[sep=8pt,center]{part title}
- \usebeamerfont{subsection title}\insertsubsection\par
-\end{beamercolorbox}
-}
-\AtBeginPart{
- \frame{\partpage}
-}
-\AtBeginSection{
- \ifbibliography
- \else
- \frame{\sectionpage}
- \fi
-}
-\AtBeginSubsection{
- \frame{\subsectionpage}
-}
-$endif$
-$endif$
$if(links-as-notes)$
% Make links footnotes instead of hotlinks:
\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}}
@@ -361,8 +360,14 @@ $include-before$
$endfor$
$if(toc)$
+$if(toc-title)$
+\renewcommand*\contentsname{$toc-title$}
+$endif$
$if(beamer)$
\begin{frame}
+$if(toc-title)$
+\frametitle{$toc-title$}
+$endif$
\tableofcontents[hideallsubsections]
\end{frame}
$else$
diff --git a/data/templates/default.opendocument b/data/templates/default.opendocument
index e0bc5c1d3..cc7d33002 100644
--- a/data/templates/default.opendocument
+++ b/data/templates/default.opendocument
@@ -26,9 +26,7 @@ $endfor$
$if(toc)$
<text:table-of-content>
<text:table-of-content-source text:outline-level="10">
- <text:index-title-template text:style-name="Contents_20_Heading">
- $toc-title$
- </text:index-title-template>
+ <text:index-title-template text:style-name="Contents_20_Heading">$toc-title$</text:index-title-template>
<text:table-of-content-entry-template text:outline-level="1"
text:style-name="Contents_20_1">
<text:index-entry-link-start text:style-name="Internet_20_link" />
diff --git a/data/templates/default.revealjs b/data/templates/default.revealjs
index 6f847e23a..2c6b8e2ff 100644
--- a/data/templates/default.revealjs
+++ b/data/templates/default.revealjs
@@ -170,6 +170,10 @@ $if(mouseWheel)$
// Enable slide navigation via mouse wheel
mouseWheel: $mouseWheel$,
$endif$
+$if(rollingLinks)$
+ // Apply a 3D roll to links on hover
+ rollingLinks: $rollingLinks$,
+$endif$
$if(hideAddressBar)$
// Hides the address bar on mobile devices
hideAddressBar: $hideAddressBar$,
@@ -237,7 +241,7 @@ $if(maxScale)$
$endif$
$if(mathjax)$
math: {
- mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',
+ mathjax: '$mathjaxurl$',
config: 'TeX-AMS_HTML-full',
tex2jax: {
inlineMath: [['\\(','\\)']],
diff --git a/data/templates/default.rst b/data/templates/default.rst
index e9c0dc203..9ba15f546 100644
--- a/data/templates/default.rst
+++ b/data/templates/default.rst
@@ -1,5 +1,5 @@
-$if(title)$
-$title$
+$if(titleblock)$
+$titleblock$
$endif$
$for(author)$
@@ -31,6 +31,10 @@ $if(toc)$
..
$endif$
+$if(number-sections)$
+.. section-numbering::
+
+$endif$
$for(header-includes)$
$header-includes$
diff --git a/data/templates/default.tei b/data/templates/default.tei
index 3778dccd5..757347886 100644
--- a/data/templates/default.tei
+++ b/data/templates/default.tei
@@ -3,18 +3,30 @@
<teiHeader>
<fileDesc>
<titleStmt>
-$if(title)$
<title>$title$</title>
-$endif$
$for(author)$
- $author$
+ <author>$author$</author>
$endfor$
</titleStmt>
<publicationStmt>
+$if(publicationStmt)$
<p>$if(publicationStmt)$$publicationStmt$$endif$</p>
- $if(license)$
+$endif$
+$if(license)$
<availability><licence>$license$</licence></availability>
$endif$
+$if(publisher)$
+ <publisher>$publisher$</publisher>
+$endif$
+$if(pubPlace)$
+ <pubPlace>$pubPlace$</pubPlace>
+$endif$
+$if(address)$
+ <address>$address$</address>
+$endif$
+$if(date)$
+ <date>$date$</date>
+$endif$
</publicationStmt>
<sourceDesc>
$if(sourceDesc)$
diff --git a/data/templates/default.texinfo b/data/templates/default.texinfo
index 458d4fdda..693827810 100644
--- a/data/templates/default.texinfo
+++ b/data/templates/default.texinfo
@@ -10,28 +10,6 @@ $if(strikeout)$
@end macro
$endif$
-$if(subscript)$
-@macro textsubscript{text}
-@iftex
-@textsubscript{\text\}
-@end iftex
-@ifnottex
-_@{\text\@}
-@end ifnottex
-@end macro
-
-$endif$
-$if(superscript)$
-@macro textsuperscript{text}
-@iftex
-@textsuperscript{\text\}
-@end iftex
-@ifnottex
-^@{\text\@}
-@end ifnottex
-@end macro
-
-$endif$
@ifnottex
@paragraphindent 0
@end ifnottex
diff --git a/data/translations/fr.yaml b/data/translations/fr.yaml
index 4b75da6f4..b0e6dc311 100644
--- a/data/translations/fr.yaml
+++ b/data/translations/fr.yaml
@@ -1,20 +1,20 @@
Abstract: Résumé
Appendix: Annexe
Bibliography: Bibliographie
-Cc: Copie à
-Chapter: Chaptire
+Cc: Cc
+Chapter: Chapitre
Contents: Table des matières
-Figure: Fig.
-Glossary:
+Figure: Figure
+Glossary: Glossaire
Index: Index
ListOfFigures: Table des figures
ListOfTables: Liste des tableaux
-Page: page
-Part: partie
+Page: Page
+Part: Partie
Preface: Préface
Proof: Démonstration
References: Références
-See: voir
-SeeAlso: voir aussi
-Table: Tab.
-To:
+See: Voir
+SeeAlso: Voir aussi
+Table: Tableau
+To: À
diff --git a/data/translations/ru.yaml b/data/translations/ru.yaml
index 6012c3e19..0bcbea62b 100644
--- a/data/translations/ru.yaml
+++ b/data/translations/ru.yaml
@@ -1,20 +1,20 @@
-Abstract: Аннотація
-Appendix: Приложеніе
+Abstract: Аннотация
+Appendix: Приложение
Author: Именной указатель
-Bibliography: Библіографія
+Bibliography: Литература
Cc: исх.
Chapter: Глава
-Contents: Оглавленіе
+Contents: Оглавление
Encl: вкл.
Figure: Рис.
-Index: Предмѣтный указатель
-ListOfFigures: Списокъ иллюстрацій
-ListOfTables: Списокъ таблицъ
+Index: Предметный указатель
+ListOfFigures: Список иллюстраций
+ListOfTables: Список таблиц
Page: с.
Part: Часть
-Preface: Предисловіе
+Preface: Предисловие
Proof: Доказательство
-References: Примѣчанія
+References: Список литературы
See: см.
SeeAlso: см. также
Table: Таблица
diff --git a/default.nix b/default.nix
index b34400204..3dc7d9b9e 100644
--- a/default.nix
+++ b/default.nix
@@ -2,7 +2,7 @@
#
# To build pandoc run:
# nix-build
-# To run a nix shell with everthing needed to build pandoc with cabal:
+# To run a nix shell with everything needed to build pandoc with cabal:
# nix-shell
# To build pandoc for use on Linux and macOS systems without Nix:
# nix-build -A patched
diff --git a/doc/lua-filter-types-and-objects.md b/doc/lua-filter-types-and-objects.md
new file mode 100644
index 000000000..f6d11a928
--- /dev/null
+++ b/doc/lua-filter-types-and-objects.md
@@ -0,0 +1,396 @@
+% Lua filter types and objects
+% Albert Krewinkel
+% Oct 6, 2018
+
+## Pandoc
+
+blocks
+: document content ([list] of [blocks])
+
+meta
+: document meta information ([Meta] object)
+
+
+## Meta
+
+Meta information on a document; string-indexed collection of [meta
+values](#metavalue). This is represented as a string-indexed table containing
+[meta values](#MetaValue).
+
+
+## MetaValue
+
+Document meta information items.
+
+### MetaBlocks
+
+blocks
+: a list of blocks usable as meta value ([list] of [blocks])
+
+
+## Block
+
+### BlockQuote
+
+A block quote element
+
+content:
+: block content ([list] of [blocks])
+
+tag, t
+: the literal `BlockQuote` (string)
+
+### BulletList
+
+A bullet list
+
+content
+: list of items ([list] of [blocks])
+
+tag, t
+: the literal `BlockQuote` (string)
+
+### CodeBlock
+
+Block of code.
+
+text
+: code string (string)
+
+attr
+: element attributes (Attr)
+
+identifier
+: alias for `attr.identifier` (string)
+
+classes
+: alias for `attr.classes` ([list] of strings)
+
+attributes
+: alias for `attr.attributes` ([attributes])
+
+tag, t
+: the literal `CodeBlock` (string)
+
+### DefinitionList
+
+Definition list, containing terms and their explanation.
+
+content
+: list of items
+
+tag, t
+: the literal `DefinitionList` (string)
+
+### Div
+
+Generic block container with attributes
+
+content
+: block content ([list] of [blocks])
+
+attr
+: element attributes (Attr)
+
+identifier
+: alias for `attr.identifier` (string)
+
+classes
+: alias for `attr.classes` ([list] of strings)
+
+attributes
+: alias for `attr.attributes` ([attributes])
+
+tag, t
+: the literal `Div` (string)
+
+### Header
+
+Creates a header element.
+
+level
+: header level (integer)
+
+content
+: inline content ([list] of [inlines])
+
+attr
+: element attributes (Attr)
+
+identifier
+: alias for `attr.identifier` (string)
+
+classes
+: alias for `attr.classes` ([list] of strings)
+
+attributes
+: alias for `attr.attributes` ([attributes])
+
+tag, t
+: the literal `Header` (string)
+
+
+### HorizontalRule
+
+A horizontal rule.
+
+tag, t
+: the literal `HorizontalRule` (string)
+
+### LineBlock
+
+A line block, i.e. a list of lines, each separated from the next
+by a newline.
+
+content
+: inline content
+
+tag, t
+: the literal `LineBlock` (string)
+
+### Null
+
+A null element; this element never produces any output in the
+target format.
+
+tag, t
+: the literal `Null` (string)
+
+### OrderedList
+
+An ordered list.
+
+Parameters:
+
+items
+: list items ([list] of [blocks])
+
+listAttributes
+: list parameters
+
+tag, t
+: the literal `OrderedList` (string)
+
+### Para
+
+A paragraph
+
+content
+: inline content
+
+tag, t
+: the literal `Para` (string)
+
+### Plain
+
+Plain text, not a paragraph
+
+content
+: inline content
+
+tag, t
+: the literal `Plain` (string)
+
+### RawBlock
+
+Raw content of a specified format.
+
+format
+: format of content (string)
+
+text
+: raw content (string)
+
+tag, t
+: the literal `RawBlock` (string)
+
+### Table
+
+A table.
+
+caption:
+: table caption
+
+aligns:
+: alignments
+
+widths:
+: column widths
+
+headers
+: header row
+
+rows:
+: table rows
+
+tag, t
+: the literal `Table` (string)
+
+## Inline
+
+### Cite
+Citation
+
+content
+: ([list] of [inlines])
+
+citations
+: citation entries ([list] of [citations])
+
+tag, t
+: the literal `Cite` (string)
+
+### Code
+Inline code
+
+text
+: code string (string)
+
+attr
+: attributes ([Attr])
+
+identifier
+: alias for `attr.identifier` (string)
+
+classes
+: alias for `attr.classes` ([list] of strings)
+
+attributes
+: alias for `attr.attributes` ([attributes])
+
+tag, t
+: the literal `Code` (string)
+
+### Emph
+Emphasized text
+
+content
+: inline content ([list] of [inlines])
+
+tag, t
+: the literal `Emph` (string)
+
+<!-- TODO -->
+
+### Image
+Image: alt text (list of inlines), target
+
+tag, t
+: the literal `Image` (string)
+
+### Link
+Hyperlink: alt text (list of inlines), target
+
+tag, t
+: the literal `Link` (string)
+
+### LineBreak
+Hard line break
+
+tag, t
+: the literal `LineBreak` (string)
+
+### Math
+TeX math (literal)
+
+tag, t
+: the literal `Math` (string)
+
+### Note
+Footnote or endnote
+
+tag, t
+: the literal `Note` (string)
+
+### Quoted
+Quoted text (list of inlines)
+
+tag, t
+: the literal `Quoted` (string)
+
+### RawInline
+Raw inline
+
+tag, t
+: the literal `RawInline` (string)
+
+### SmallCaps
+Small caps text (list of inlines)
+
+tag, t
+: the literal `SmallCaps` (string)
+
+### SoftBreak
+Soft line break
+
+tag, t
+: the literal `SoftBreak` (string)
+
+### Space
+Inter-word space
+
+tag, t
+: the literal `Space` (string)
+
+### Span
+Generic inline container with attributes
+
+attr
+: attributes ([Attr])
+
+identifier
+: alias for `attr.identifier` (string)
+
+classes
+: alias for `attr.classes` ([list] of strings)
+
+attributes
+: alias for `attr.attributes` ([attributes])
+
+tag, t
+: the literal `Span` (string)
+
+### Str
+Text (string)
+
+tag, t
+: the literal `Str` (string)
+
+### Strikeout
+Strikeout text (list of inlines)
+
+tag, t
+: the literal `Strikeout` (string)
+
+### Strong
+Strongly emphasized text (list of inlines)
+
+tag, t
+: the literal `Strong` (string)
+
+### Subscript
+Subscripted text (list of inlines)
+
+tag, t
+: the literal `Subscript` (string)
+
+### Superscript
+Superscripted text (list of inlines)
+
+tag, t
+: the literal `Superscript` (string)
+
+## Attributes
+
+List of key/value pairs. Values can be accessed by using keys as indices to the
+list table.
+
+
+[block]: #block
+[blocks]: #block
+[list]: #list
+[meta value]: #metavalue
+[inline]: #inline
+[inlines]: #inline
+[Attr]: #attr
+[attributes]: #attributes
diff --git a/doc/lua-filters.md b/doc/lua-filters.md
index 170aaa8f5..917b9cc16 100644
--- a/doc/lua-filters.md
+++ b/doc/lua-filters.md
@@ -10,11 +10,11 @@ title: Pandoc Lua Filters
Pandoc has long supported filters, which allow the pandoc
abstract syntax tree (AST) to be manipulated between the parsing
-and the writing phase. Traditional pandoc filters accept a JSON
-representation of the pandoc AST and produce an altered JSON
-representation of the AST. They may be written in any
-programming language, and invoked from pandoc using the
-`--filter` option.
+and the writing phase. [Traditional pandoc
+filters](filters.html) accept a JSON representation of the
+pandoc AST and produce an altered JSON representation of the
+AST. They may be written in any programming language, and
+invoked from pandoc using the `--filter` option.
Although traditional filters are very flexible, they have a
couple of disadvantages. First, there is some overhead in
@@ -114,7 +114,7 @@ The return of a filter function must one of the following:
- a pandoc object: this must be of the same type as the input
and will replace the original object.
- a list of pandoc objects: these will replace the original
- object; the list is merged with the neighbors of the orignal
+ object; the list is merged with the neighbors of the original
objects (spliced into the list the original object belongs
to); returning an empty list deletes the object.
@@ -240,6 +240,11 @@ colon syntax (`mystring:uc_upper()`).
# Examples
+The following filters are presented as examples.
+A repository of useful lua filters (which may also serve
+as good examples) is available at
+<https://github.com/pandoc/lua-filters>.
+
## Macro substitution.
The following filter converts the string `{{helloworld}}` into
@@ -948,7 +953,7 @@ Lua functions for pandoc scripts.
Parameters:
`text`:
- : brief image description
+ : code string
`attr`:
: additional attributes
@@ -1438,6 +1443,37 @@ Lua functions for pandoc scripts.
This module exposes internal pandoc functions and utility
functions.
+[`blocks_to_inlines (blocks[, sep])`]{#utils-blocks_to_inlines}
+
+: Squash a list of blocks into a list of inlines.
+
+ Parameters:
+
+ `blocks`:
+ : List of blocks to be flattened.
+
+ `sep`:
+ : List of inlines inserted as separator between two
+ consecutive blocks; defaults to `{ pandoc.Space(),
+ pandoc.Str'¶', pandoc.Space()}`.
+
+ Returns:
+
+ - ({[Inline][#Inline]}) List of inlines
+
+ Usage:
+
+ local blocks = {
+ pandoc.Para{ pandoc.Str 'Paragraph1' },
+ pandoc.Para{ pandoc.Emph 'Paragraph2' }
+ }
+ local inlines = pandoc.utils.blocks_to_inlines(blocks)
+ -- inlines = {
+ -- pandoc.Str 'Paragraph1',
+ -- pandoc.Space(), pandoc.Str'¶', pandoc.Space(),
+ -- pandoc.Emph{ pandoc.Str 'Paragraph2' }
+ -- }
+
[`hierarchicalize (blocks)`]{#utils-hierarchicalize}
: Convert list of blocks into an hierarchical list. An
diff --git a/doc/using-the-pandoc-api.md b/doc/using-the-pandoc-api.md
index 8527f6373..550b38c65 100644
--- a/doc/using-the-pandoc-api.md
+++ b/doc/using-the-pandoc-api.md
@@ -42,7 +42,7 @@ limitation is mostly a help rather than a hindrance, since many
of the formats pandoc supports have similar limitations.
The best way to explore the pandoc AST is to use `pandoc -t
-native`, which will display the AST correspoding to some
+native`, which will display the AST corresponding to some
Markdown input:
```
@@ -187,7 +187,7 @@ Some particularly important options to know about:
# Builder
Sometimes it's useful to construct a Pandoc document
-programatically. To make this easier we provide the
+programmatically. To make this easier we provide the
module [Text.Pandoc.Builder] `pandoc-types`.
Because concatenating lists is slow, we use special
diff --git a/linux/Dockerfile b/linux/Dockerfile
index 6c7679c56..97d4058cd 100644
--- a/linux/Dockerfile
+++ b/linux/Dockerfile
@@ -1,57 +1,24 @@
# USE ALPINE LINUX
FROM alpine
RUN apk update
-# INSTALL BASIC DEV TOOLS, GHC, GMP & ZLIB
-RUN echo "https://s3-us-west-2.amazonaws.com/alpine-ghc/8.0" >> /etc/apk/repositories
-ADD https://raw.githubusercontent.com/mitchty/alpine-ghc/master/mitch.tishmack%40gmail.com-55881c97.rsa.pub \
- /etc/apk/keys/mitch.tishmack@gmail.com-55881c97.rsa.pub
-RUN apk update
RUN apk add alpine-sdk git ca-certificates ghc gmp-dev zlib-dev bash dpkg fakeroot
# GRAB A RECENT BINARY OF STACK
-RUN curl -L https://github.com/commercialhaskell/stack/releases/download/v1.6.5/stack-1.6.5-linux-x86_64-static.tar.gz | tar xz --wildcards --strip-components=1 -C /usr/local/bin '*/stack'
-# COMPRESS WITH UPX
-ADD https://github.com/lalyos/docker-upx/releases/download/v3.91/upx /usr/local/bin/upx
+# Note that 1.6.5 is the last one with an official static binary...we need
+# a more recent version, so we use this unofficial one.
+RUN curl -L https://github.com/nh2/stack/releases/download/v1.6.5/stack-1.7.1-x86_64-unofficial-fully-static-musl > /usr/local/bin/stack
+#RUN curl -L https://github.com/commercialhaskell/stack/releases/download/v1.6.5/stack-1.6.5-linux-x86_64-static.tar.gz | tar xz --wildcards --strip-components=1 -C /usr/local/bin '*/stack'
+RUN chmod +x /usr/local/bin/stack
ENV PATH="/usr/local/bin:${PATH}"
-RUN chmod 755 /usr/local/bin/upx
RUN ulimit -n 4096
RUN stack config set system-ghc --global true
-RUN stack --resolver lts-9 setup --install-cabal 2.0.1.1
-#RUN mkdir -p /etc/stack
-#RUN echo "build: { split-objs: true }" > /etc/stack/config.yaml
+RUN stack setup --resolver lts-12
RUN mkdir -p /usr/src/
WORKDIR /usr/src/
RUN git clone https://github.com/jgm/pandoc
WORKDIR /usr/src/pandoc
-RUN stack install --stack-yaml stack.lts9.yaml \
- --only-dependencies \
- --flag 'pandoc:static' \
- --flag 'pandoc:embed_data_files' \
- --flag 'pandoc-citeproc:static' \
- --flag 'pandoc-citeproc:embed_data_files' \
- --flag 'hslua:-export-dynamic' \
- --ghc-options '-O2 -optc-Os -optl=-pthread -optl=-static -fPIC' \
- aeson
-RUN stack install --stack-yaml stack.lts9.yaml \
- --only-dependencies \
- --flag 'pandoc:static' \
- --flag 'pandoc:embed_data_files' \
- --flag 'pandoc-citeproc:static' \
- --flag 'pandoc-citeproc:embed_data_files' \
- --flag 'hslua:-export-dynamic' \
- --ghc-options '-O2 -optc-Os -optl=-pthread -optl=-static -fPIC' \
- http-client-tls
-RUN stack install --stack-yaml stack.lts9.yaml \
- --only-dependencies \
- --flag 'pandoc:static' \
- --flag 'pandoc:embed_data_files' \
- --flag 'pandoc-citeproc:static' \
- --flag 'pandoc-citeproc:embed_data_files' \
- --flag 'hslua:-export-dynamic' \
- --ghc-options '-O2 -optc-Os -optl=-pthread -optl=-static -fPIC' \
- pandoc pandoc-citeproc
CMD git pull && \
git checkout -b work $TREE && \
- stack install --stack-yaml stack.lts9.yaml \
+ stack install \
--flag 'pandoc:static' \
--flag 'pandoc:embed_data_files' \
--flag 'pandoc-citeproc:static' \
diff --git a/man/pandoc.1 b/man/pandoc.1
index 1379133f2..00cdfdc00 100644
--- a/man/pandoc.1
+++ b/man/pandoc.1
@@ -1,5 +1,5 @@
.\"t
-.TH PANDOC 1 "May 10, 2018" "pandoc 2.2.1"
+.TH PANDOC 1 "September 27, 2018" "pandoc 2.3.1"
.SH NAME
pandoc - general markup converter
.SH SYNOPSIS
@@ -187,8 +187,9 @@ requires \f[C]fontspec\f[].
If the \f[C]mathspec\f[] variable is set, \f[C]xelatex\f[] will use
\f[C]mathspec\f[] instead of \f[C]unicode\-math\f[].
The \f[C]upquote\f[] and \f[C]microtype\f[] packages are used if
-available, and \f[C]csquotes\f[] will be used for typography if added to
-the template or included in any header file.
+available, and \f[C]csquotes\f[] will be used for typography if
+\f[C]\\usepackage{csquotes}\f[] is present in the template or included
+via \f[C]/H/\-\-include\-in\-header\f[].
The \f[C]natbib\f[], \f[C]biblatex\f[], \f[C]bibtex\f[], and
\f[C]biber\f[] packages can optionally be used for citation rendering.
.SS Reading from the Web
@@ -231,10 +232,9 @@ Specify input format.
.IP \[bu] 2
\f[C]fb2\f[] (FictionBook2 e\-book)
.IP \[bu] 2
-\f[C]gfm\f[] (GitHub\-Flavored Markdown), or \f[C]markdown_github\f[],
-which provides deprecated and less accurate support for Github\-Flavored
-Markdown; please use \f[C]gfm\f[] instead, unless you need to use
-extensions other than \f[C]smart\f[].
+\f[C]gfm\f[] (GitHub\-Flavored Markdown), or the deprecated and less
+accurate \f[C]markdown_github\f[]; use \f[C]markdown_github\f[] only if
+you need extensions not supported in \f[C]gfm\f[].
.IP \[bu] 2
\f[C]haddock\f[] (Haddock markup)
.IP \[bu] 2
@@ -312,10 +312,9 @@ Specify output format.
.IP \[bu] 2
\f[C]fb2\f[] (FictionBook2 e\-book)
.IP \[bu] 2
-\f[C]gfm\f[] (GitHub\-Flavored Markdown), or \f[C]markdown_github\f[],
-which provides deprecated and less accurate support for Github\-Flavored
-Markdown; please use \f[C]gfm\f[] instead, unless you use extensions
-that do not work with \f[C]gfm\f[].
+\f[C]gfm\f[] (GitHub\-Flavored Markdown), or the deprecated and less
+accurate \f[C]markdown_github\f[]; use \f[C]markdown_github\f[] only if
+you need extensions not supported in \f[C]gfm\f[].
.IP \[bu] 2
\f[C]haddock\f[] (Haddock markup)
.IP \[bu] 2
@@ -556,7 +555,7 @@ Reading binary files (docx, odt, epub) implies \f[C]\-\-file\-scope\f[].
.RS
.RE
.TP
-.B \f[C]\-\-filter=\f[]\f[I]PROGRAM\f[]
+.B \f[C]\-F\f[] \f[I]PROGRAM\f[], \f[C]\-\-filter=\f[]\f[I]PROGRAM\f[]
Specify an executable to be used as a filter transforming the pandoc AST
after the input is parsed and before the output is written.
The executable should read JSON from stdin and write JSON to stdout.
@@ -659,6 +658,17 @@ escaped when inserted into the template.
.RS
.RE
.TP
+.B \f[C]\-\-metadata\-file=\f[]\f[I]FILE\f[]
+Read metadata from the supplied YAML (or JSON) file.
+This option can be used with every input format, but string scalars in
+the YAML file will always be parsed as Markdown.
+Generally, the input will be handled the same as in YAML metadata
+blocks.
+Metadata values specified inside the document, or by using \f[C]\-M\f[],
+overwrite values specified with this option.
+.RS
+.RE
+.TP
.B \f[C]\-p\f[], \f[C]\-\-preserve\-tabs\f[]
Preserve tabs instead of converting them to spaces (the default).
Note that this will only affect tabs in literal code spans and code
@@ -731,8 +741,8 @@ otherwise, metadata is suppressed.
.RS
.RE
.TP
-.B \f[C]\-\-template=\f[]\f[I]FILE\f[]
-Use \f[I]FILE\f[] as a custom template for the generated document.
+.B \f[C]\-\-template=\f[]\f[I]FILE\f[]|\f[I]URL\f[]
+Use the specified file as a custom template for the generated document.
Implies \f[C]\-\-standalone\f[].
See Templates, below, for a description of template syntax.
If no extension is specified, an extension corresponding to the writer
@@ -815,7 +825,8 @@ Include an automatically generated table of contents (or, in the case of
\f[C]latex\f[], \f[C]context\f[], \f[C]docx\f[], \f[C]odt\f[],
\f[C]opendocument\f[], \f[C]rst\f[], or \f[C]ms\f[], an instruction to
create one) in the output document.
-This option has no effect on \f[C]man\f[], \f[C]docbook4\f[],
+This option has no effect unless \f[C]\-s/\-\-standalone\f[] is used,
+and it has no effect on \f[C]man\f[], \f[C]docbook4\f[],
\f[C]docbook5\f[], or \f[C]jats\f[] output.
.RS
.RE
@@ -921,12 +932,19 @@ directory must be explicitly listed or it will not be searched.
For example: \f[C]\-\-resource\-path=.:test\f[] will search the working
directory and the \f[C]test\f[] subdirectory, in that order.
.RS
+.PP
+\f[C]\-\-resource\-path\f[] only has an effect if (a) the output format
+embeds images (for example, \f[C]docx\f[], \f[C]pdf\f[], or
+\f[C]html\f[] with \f[C]\-\-self\-contained\f[]) or (b) it is used
+together with \f[C]\-\-extract\-media\f[].
.RE
.TP
.B \f[C]\-\-request\-header=\f[]\f[I]NAME\f[]\f[C]:\f[]\f[I]VAL\f[]
Set the request header \f[I]NAME\f[] to the value \f[I]VAL\f[] when
making HTTP requests (for example, when a URL is given on the command
line, or when resources used in a document must be downloaded).
+If you\[aq]re behind a proxy, you also need to set the environment
+variable \f[C]http_proxy\f[] to \f[C]http://...\f[].
.RS
.RE
.SS Options affecting specific writers
@@ -1037,7 +1055,11 @@ Implies \f[C]\-\-number\-sections\f[].
.RE
.TP
.B \f[C]\-\-listings\f[]
-Use the \f[C]listings\f[] package for LaTeX code blocks
+Use the \f[C]listings\f[] package for LaTeX code blocks.
+The package does not support multi\-byte encoding for source code.
+To handle UTF\-8 you would need to use a custom template.
+This issue is fully documented here: Encoding issue with the listings
+package.
.RS
.RE
.TP
@@ -1402,19 +1424,13 @@ without native math support.
.B \f[C]\-\-katex\f[][\f[C]=\f[]\f[I]URL\f[]]
Use KaTeX to display embedded TeX math in HTML output.
The \f[I]URL\f[] is the base URL for the KaTeX library.
+That directory should contain a \f[C]katex.min.js\f[] and a
+\f[C]katex.min.css\f[] file.
If a \f[I]URL\f[] is not provided, a link to the KaTeX CDN will be
inserted.
.RS
.RE
.TP
-.B \f[C]\-\-katex\-stylesheet=\f[]\f[I]URL\f[]
-The \f[I]URL\f[] should point to the \f[C]katex.css\f[] stylesheet.
-If this option is not specified, a link to the KaTeX CDN will be
-inserted.
-Note that this option does not imply \f[C]\-\-katex\f[].
-.RS
-.RE
-.TP
.B \f[C]\-\-gladtex\f[]
Enclose TeX math in \f[C]<eq>\f[] tags in HTML output.
The resulting HTML can then be processed by GladTeX to produce images of
@@ -1594,7 +1610,7 @@ specified
.TP
.B \f[C]toc\-title\f[]
title of table of contents (works only with EPUB, opendocument, odt,
-docx, pptx)
+docx, pptx, beamer, LaTeX)
.RS
.RE
.TP
@@ -1825,15 +1841,16 @@ options to pass to the microtype package
.TP
.B \f[C]colorlinks\f[]
add color to link text; automatically enabled if any of
-\f[C]linkcolor\f[], \f[C]citecolor\f[], \f[C]urlcolor\f[], or
-\f[C]toccolor\f[] are set
+\f[C]linkcolor\f[], \f[C]filecolor\f[], \f[C]citecolor\f[],
+\f[C]urlcolor\f[], or \f[C]toccolor\f[] are set
.RS
.RE
.TP
-.B \f[C]linkcolor\f[], \f[C]citecolor\f[], \f[C]urlcolor\f[], \f[C]toccolor\f[]
-color for internal links, citation links, external links, and links in
-table of contents: uses options allowed by \f[C]xcolor\f[], including
-the \f[C]dvipsnames\f[], \f[C]svgnames\f[], and \f[C]x11names\f[] lists
+.B \f[C]linkcolor\f[], \f[C]filecolor\f[], \f[C]citecolor\f[], \f[C]urlcolor\f[], \f[C]toccolor\f[]
+color for internal links, external links, citation links, linked URLs,
+and links in table of contents, respectively: uses options allowed by
+\f[C]xcolor\f[], including the \f[C]dvipsnames\f[], \f[C]svgnames\f[],
+and \f[C]x11names\f[] lists
.RS
.RE
.TP
@@ -2109,11 +2126,9 @@ any number (including zero),
any object,
.IP \[bu] 2
the boolean \f[C]true\f[] (to specify the boolean \f[C]true\f[] value
-using YAML metadata or the \f[C]\-\-metadata\f[] flag, use \f[C]y\f[],
-\f[C]Y\f[], \f[C]yes\f[], \f[C]Yes\f[], \f[C]YES\f[], \f[C]true\f[],
-\f[C]True\f[], \f[C]TRUE\f[], \f[C]on\f[], \f[C]On\f[], or \f[C]ON\f[];
-with the \f[C]\-\-variable\f[] flag, simply omit a value for the
-variable, e.g.
+using YAML metadata or the \f[C]\-\-metadata\f[] flag, use
+\f[C]true\f[], \f[C]True\f[], or \f[C]TRUE\f[]; with the
+\f[C]\-\-variable\f[] flag, simply omit a value for the variable, e.g.
\f[C]\-\-variable\ draft\f[]).
.PP
\f[C]X\f[] and \f[C]Y\f[] are placeholders for any valid template text,
@@ -2360,12 +2375,13 @@ This extension can be enabled/disabled for the following formats (in
addition to \f[C]markdown\f[]):
.TP
.B input formats
-\f[C]latex\f[], \f[C]org\f[], \f[C]textile\f[]
+\f[C]latex\f[], \f[C]org\f[], \f[C]textile\f[], \f[C]html\f[]
+(environments, \f[C]\\ref\f[], and \f[C]\\eqref\f[] only)
.RS
.RE
.TP
.B output formats
-\f[C]textile\f[]
+\f[C]textile\f[], \f[C]commonmark\f[]
.RS
.RE
.SS Extension: \f[C]native_divs\f[]
@@ -3772,14 +3788,20 @@ pandoc\ chap1.md\ chap2.md\ chap3.md\ metadata.yaml\ \-s\ \-o\ book.html
.fi
.PP
Just be sure that the YAML file begins with \f[C]\-\-\-\f[] and ends
-with \f[C]\-\-\-\f[] or \f[C]\&...\f[].)
+with \f[C]\-\-\-\f[] or \f[C]\&...\f[].) Alternatively, you can use the
+\f[C]\-\-metadata\-file\f[] option.
+Using that approach however, you cannot reference content (like
+footnotes) from the main markdown input document.
.PP
Metadata will be taken from the fields of the YAML object and added to
any existing document metadata.
Metadata can contain lists and objects (nested arbitrarily), but all
string scalars will be interpreted as Markdown.
Fields with names ending in an underscore will be ignored by pandoc.
-(They may be given a role by external processors.)
+(They may be given a role by external processors.) Field names must not
+be interpretable as YAML numbers or boolean values (so, for example,
+\f[C]yes\f[], \f[C]True\f[], and \f[C]15\f[] cannot be used as field
+names).
.PP
A document may contain multiple metadata blocks.
The metadata fields will be combined through a \f[I]left\-biased
@@ -3806,7 +3828,7 @@ title:\ \ \[aq]This\ is\ the\ title:\ it\ contains\ a\ colon\[aq]
author:
\-\ Author\ One
\-\ Author\ Two
-tags:\ [nothing,\ nothingness]
+keywords:\ [nothing,\ nothingness]
abstract:\ |
\ \ This\ is\ the\ abstract.
@@ -4094,8 +4116,15 @@ delimiters.
TeX math will be printed in all output formats.
How it is rendered depends on the output format:
.TP
-.B Markdown, LaTeX, Emacs Org mode, ConTeXt, ZimWiki
-It will appear verbatim between \f[C]$\f[] characters.
+.B LaTeX
+It will appear verbatim surrounded by \f[C]\\(...\\)\f[] (for inline
+math) or \f[C]\\[...\\]\f[] (for display math).
+.RS
+.RE
+.TP
+.B Markdown, Emacs Org mode, ConTeXt, ZimWiki
+It will appear verbatim surrounded by \f[C]$...$\f[] (for inline math)
+or \f[C]$$...$$\f[] (for display math).
.RS
.RE
.TP
@@ -5017,8 +5046,8 @@ nocite:\ |
\f[]
.fi
.PP
-For LaTeX or PDF output, you can also use \f[C]natbib\f[] or
-\f[C]biblatex\f[] to render bibliography.
+For LaTeX output, you can also use \f[C]natbib\f[] or \f[C]biblatex\f[]
+to render the bibliography.
In order to do so, specify bibliography files as outlined above, and add
\f[C]\-\-natbib\f[] or \f[C]\-\-biblatex\f[] argument to \f[C]pandoc\f[]
invocation.
@@ -5230,7 +5259,7 @@ Also, \f[C]raw_tex\f[] only affects \f[C]gfm\f[] output, not input.
.TP
.B \f[C]gfm\f[] (GitHub\-Flavored Markdown)
\f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]fenced_code_blocks\f[],
-\f[C]auto_identifiers\f[], \f[C]ascii_identifiers\f[],
+\f[C]gfm_auto_identifiers\f[], \f[C]ascii_identifiers\f[],
\f[C]backtick_code_blocks\f[], \f[C]autolink_bare_uris\f[],
\f[C]intraword_underscores\f[], \f[C]strikeout\f[],
\f[C]hard_line_breaks\f[], \f[C]emoji\f[],
@@ -5551,33 +5580,40 @@ introducing the slide:
All of the other frame attributes described in Section 8.1 of the Beamer
User\[aq]s Guide may also be used: \f[C]allowdisplaybreaks\f[],
\f[C]allowframebreaks\f[], \f[C]b\f[], \f[C]c\f[], \f[C]t\f[],
-\f[C]environment\f[], \f[C]label\f[], \f[C]plain\f[], \f[C]shrink\f[].
-.SS Background in reveal.js
+\f[C]environment\f[], \f[C]label\f[], \f[C]plain\f[], \f[C]shrink\f[],
+\f[C]standout\f[], \f[C]noframenumbering\f[].
+.SS Background in reveal.js and beamer
.PP
-Background images can be added to self\-contained reveal.js slideshows.
+Background images can be added to self\-contained reveal.js slideshows
+and to beamer slideshows.
.PP
-For the same image on every slide, use the reveal.js configuration
-option \f[C]parallaxBackgroundImage\f[] either in the YAML metadata
-block or as a command\-line variable.
+For the same image on every slide, use the configuration option
+\f[C]background\-image\f[] either in the YAML metadata block or as a
+command\-line variable.
+(There are no other options in beamer and the rest of this section
+concerns reveal.js slideshows.)
+.PP
+For reveal.js, you can instead use the reveal.js\-native option
+\f[C]parallaxBackgroundImage\f[].
You can also set \f[C]parallaxBackgroundHorizontal\f[] and
\f[C]parallaxBackgroundVertical\f[] the same way and must also set
\f[C]parallaxBackgroundSize\f[] to have your values take effect.
.PP
-To set an image for a particular slide, add
+To set an image for a particular reveal.js slide, add
\f[C]{data\-background\-image="/path/to/image"}\f[] to the first
slide\-level header on the slide (which may even be empty).
.PP
In reveal.js\[aq]s overview mode, the parallaxBackgroundImage will show
up only on the first slide.
.PP
-Other background settings also work on individual slides, including
-\f[C]data\-background\-size\f[], \f[C]data\-background\-repeat\f[],
-\f[C]data\-background\-color\f[], \f[C]data\-transition\f[], and
-\f[C]data\-transition\-speed\f[].
+Other reveal.js background settings also work on individual slides,
+including \f[C]data\-background\-size\f[],
+\f[C]data\-background\-repeat\f[], \f[C]data\-background\-color\f[],
+\f[C]data\-transition\f[], and \f[C]data\-transition\-speed\f[].
.PP
See the reveal.js documentation for more details.
.PP
-For example:
+For example in reveal.js:
.IP
.nf
\f[C]
@@ -5748,11 +5784,129 @@ iBooks\-specific metadata, with the following fields:
\f[C]scroll\-axis\f[]:
\f[C]vertical\f[]|\f[C]horizontal\f[]|\f[C]default\f[]
.RE
+.SS The \f[C]epub:type\f[] attribute
+.PP
+For \f[C]epub3\f[] output, you can mark up the header that corresponds
+to an EPUB chapter using the \f[C]epub:type\f[] attribute.
+For example, to set the attribute to the value \f[C]prologue\f[], use
+this markdown:
+.IP
+.nf
+\f[C]
+#\ My\ chapter\ {epub:type=prologue}
+\f[]
+.fi
+.PP
+Which will result in:
+.IP
+.nf
+\f[C]
+<body\ epub:type="frontmatter">
+\ \ <section\ epub:type="prologue">
+\ \ \ \ <h1>My\ chapter</h1>
+\f[]
+.fi
+.PP
+Pandoc will output \f[C]<body\ epub:type="bodymatter">\f[], unless you
+use one of the following values, in which case either
+\f[C]frontmatter\f[] or \f[C]backmatter\f[] will be output.
+.PP
+.TS
+tab(@);
+l l.
+T{
+\f[C]epub:type\f[] of first section
+T}@T{
+\f[C]epub:type\f[] of body
+T}
+_
+T{
+prologue
+T}@T{
+frontmatter
+T}
+T{
+abstract
+T}@T{
+frontmatter
+T}
+T{
+acknowledgments
+T}@T{
+frontmatter
+T}
+T{
+copyright\-page
+T}@T{
+frontmatter
+T}
+T{
+dedication
+T}@T{
+frontmatter
+T}
+T{
+foreword
+T}@T{
+frontmatter
+T}
+T{
+halftitle,
+T}@T{
+frontmatter
+T}
+T{
+introduction
+T}@T{
+frontmatter
+T}
+T{
+preface
+T}@T{
+frontmatter
+T}
+T{
+seriespage
+T}@T{
+frontmatter
+T}
+T{
+titlepage
+T}@T{
+frontmatter
+T}
+T{
+afterword
+T}@T{
+backmatter
+T}
+T{
+appendix
+T}@T{
+backmatter
+T}
+T{
+colophon
+T}@T{
+backmatter
+T}
+T{
+conclusion
+T}@T{
+backmatter
+T}
+T{
+epigraph
+T}@T{
+backmatter
+T}
+.TE
.SS Linked media
.PP
-By default, pandoc will download linked media (including audio and
-video) and include it in the EPUB container, yielding a completely
-self\-contained EPUB.
+By default, pandoc will download media referenced from any
+\f[C]<img>\f[], \f[C]<audio>\f[], \f[C]<video>\f[] or \f[C]<source>\f[]
+element present in the generated EPUB, and include it in the EPUB
+container, yielding a completely self\-contained EPUB.
If you want to link to external media resources instead, use raw HTML in
your source and add \f[C]data\-external="1"\f[] to the tag with the
\f[C]src\f[] attribute.
@@ -5771,8 +5925,9 @@ For example:
.PP
Pandoc will automatically highlight syntax in fenced code blocks that
are marked with a language name.
-The Haskell library skylighting is used for highlighting, which works in
-HTML, Docx, Ms, and LaTeX/PDF output.
+The Haskell library skylighting is used for highlighting.
+Currently highlighting is supported only for HTML, EPUB, Docx, Ms, and
+LaTeX/PDF output.
To see a list of language names that pandoc will recognize, type
\f[C]pandoc\ \-\-list\-highlight\-languages\f[].
.PP
@@ -5784,6 +5939,33 @@ pygments is not actually used to do the highlighting).
To see a list of highlight styles, type
\f[C]pandoc\ \-\-list\-highlight\-styles\f[].
.PP
+If you are not satisfied with the predefined styles, you can use
+\f[C]\-\-print\-highlight\-style\f[] to generate a JSON
+\f[C]\&.theme\f[] file which can be modified and used as the argument to
+\f[C]\-\-highlight\-style\f[].
+To get a JSON version of the \f[C]pygments\f[] style, for example:
+.IP
+.nf
+\f[C]
+pandoc\ \-\-print\-highlight\-style\ pygments\ >\ my.theme
+\f[]
+.fi
+.PP
+Then edit \f[C]my.theme\f[] and use it like this:
+.IP
+.nf
+\f[C]
+pandoc\ \-\-highlight\-style\ my.theme
+\f[]
+.fi
+.PP
+If you are not satisfied with the built\-in highlighting, or you want
+highlight a language that isn\[aq]t supported, you can use the
+\f[C]\-\-syntax\-definition\f[] option to load a KDE\-style XML syntax
+definition file.
+Before writing your own, have a look at KDE\[aq]s repository of syntax
+definitions.
+.PP
To disable highlighting, use the \f[C]\-\-no\-highlight\f[] option.
.SH CUSTOM STYLES IN DOCX
.SS Input
diff --git a/pandoc.cabal b/pandoc.cabal
index 54bcf86d5..26c88d83c 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,6 +1,6 @@
name: pandoc
-version: 2.2.1
-cabal-version: >= 1.10
+version: 2.4
+cabal-version: 2.0
build-type: Custom
license: GPL-2
license-file: COPYING.md
@@ -11,7 +11,7 @@ bug-reports: https://github.com/jgm/pandoc/issues
stability: alpha
homepage: https://pandoc.org
category: Text
-tested-with: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1
+tested-with: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3
synopsis: Conversion between markup formats
description: Pandoc is a Haskell library for converting from one markup
format to another, and a command-line tool that uses
@@ -192,6 +192,8 @@ extra-source-files:
test/command/inkscape-cube.svg
test/command/sub-file-chapter-1.tex
test/command/sub-file-chapter-2.tex
+ test/command/bar.tex
+ test/command/yaml-metadata.yaml
test/command/3510-subdoc.org
test/command/3510-export.latex
test/command/3510-src.hs
@@ -334,15 +336,11 @@ flag trypandoc
Description: Build trypandoc cgi executable.
Default: False
-flag network-uri
- Description: Get Network.URI from the network-uri package
- Default: True
-
custom-setup
- setup-depends: base, Cabal
+ setup-depends: base, Cabal >= 2.0
library
- build-depends: base >= 4.7 && < 5,
+ build-depends: base >= 4.8 && < 5,
syb >= 0.1 && < 0.8,
containers >= 0.4.2.1 && < 0.6,
unordered-containers >= 0.2 && < 0.3,
@@ -358,40 +356,46 @@ library
safe >= 0.3 && < 0.4,
zip-archive >= 0.2.3.4 && < 0.4,
HTTP >= 4000.0.5 && < 4000.4,
- texmath >= 0.10 && < 0.12,
+ texmath >= 0.11 && < 0.12,
xml >= 1.3.12 && < 1.4,
split >= 0.2 && < 0.3,
random >= 1 && < 1.2,
- pandoc-types >= 1.17.4.2 && < 1.18,
- aeson >= 0.7 && < 1.4,
+ pandoc-types >= 1.17.5 && < 1.18,
+ aeson >= 0.7 && < 1.5,
aeson-pretty >= 0.8.5 && < 0.9,
tagsoup >= 0.14.6 && < 0.15,
base64-bytestring >= 0.1 && < 1.1,
zlib >= 0.5 && < 0.7,
- skylighting >= 0.5.1 && < 0.8,
+ skylighting >= 0.7.2 && < 0.8,
data-default >= 0.4 && < 0.8,
temporary >= 1.1 && < 1.4,
blaze-html >= 0.9 && < 0.10,
blaze-markup >= 0.8 && < 0.9,
- yaml >= 0.8.8.2 && < 0.9,
- scientific >= 0.2 && < 0.4,
vector >= 0.10 && < 0.13,
- hslua >= 0.9.5 && < 0.9.6,
- hslua-module-text >= 0.1.2 && < 0.2,
+ hslua >= 1.0.1 && < 1.1,
+ hslua-module-text >= 0.2 && < 0.3,
binary >= 0.5 && < 0.10,
SHA >= 1.6 && < 1.7,
- haddock-library >= 1.1 && < 1.6,
+ haddock-library >= 1.6 && < 1.7,
deepseq >= 1.3 && < 1.5,
- JuicyPixels >= 3.1.6.1 && < 3.3,
+ JuicyPixels >= 3.1.6.1 && < 3.4,
Glob >= 0.7 && < 0.10,
cmark-gfm >= 0.1.1 && < 0.2,
doctemplates >= 0.2.1 && < 0.3,
+ network-uri >= 2.6 && < 2.7,
+ network >= 2.6,
http-client >= 0.4.30 && < 0.6,
http-client-tls >= 0.2.4 && < 0.4,
http-types >= 0.8 && < 0.13,
- case-insensitive >= 1.2 && < 1.3
+ case-insensitive >= 1.2 && < 1.3,
+ unicode-transforms >= 0.3 && < 0.4,
+ HsYAML >= 0.1.1.1 && < 0.2
if impl(ghc < 8.0)
- build-depends: semigroups == 0.18.*
+ build-depends: semigroups == 0.18.*,
+ -- basement 0.0.8 and foundation 0.0.21, transitive
+ -- dependencies, drop support for ghc 7.10:
+ basement < 0.0.8,
+ foundation < 0.0.21
if impl(ghc < 8.4)
hs-source-dirs: prelude
other-modules: Prelude
@@ -400,10 +404,6 @@ library
cpp-options: -D_WINDOWS
else
build-depends: unix >= 2.4 && < 2.8
- if flag(network-uri)
- build-depends: network-uri >= 2.6 && < 2.7, network >= 2.6
- else
- build-depends: network >= 2 && < 2.6
if flag(embed_data_files)
cpp-options: -DEMBED_DATA_FILES
build-depends: file-embed >= 0.0 && < 0.1
@@ -510,6 +510,8 @@ library
Text.Pandoc.Readers.Docx.Util,
Text.Pandoc.Readers.Docx.StyleMap,
Text.Pandoc.Readers.Docx.Fields,
+ Text.Pandoc.Readers.LaTeX.Parsing,
+ Text.Pandoc.Readers.LaTeX.Lang,
Text.Pandoc.Readers.Odt.Base,
Text.Pandoc.Readers.Odt.Namespaces,
Text.Pandoc.Readers.Odt.StyleReader,
@@ -546,11 +548,11 @@ library
Text.Pandoc.Translations,
Text.Pandoc.Slides,
Paths_pandoc
-
+ autogen-modules: Paths_pandoc
buildable: True
executable pandoc
- build-depends: pandoc, base >= 4.7 && < 5
+ build-depends: pandoc, base >= 4.8 && < 5
if impl(ghc < 8.0)
build-depends: semigroups == 0.18.*
if impl(ghc < 8.4)
@@ -590,7 +592,7 @@ benchmark weigh-pandoc
main-is: weigh-pandoc.hs
hs-source-dirs: benchmark
build-depends: pandoc,
- base >= 4.2 && < 5,
+ base >= 4.8 && < 5,
text,
weigh >= 0.0 && < 0.1,
mtl >= 2.2 && < 2.3
@@ -608,20 +610,20 @@ test-suite test-pandoc
type: exitcode-stdio-1.0
main-is: test-pandoc.hs
hs-source-dirs: test
- build-depends: base >= 4.2 && < 5,
+ build-depends: base >= 4.8 && < 5,
pandoc,
- pandoc-types >= 1.17.4.2 && < 1.18,
+ pandoc-types >= 1.17.5 && < 1.18,
bytestring >= 0.9 && < 0.11,
base64-bytestring >= 0.1 && < 1.1,
text >= 0.11 && < 1.3,
time >= 1.5 && < 1.10,
directory >= 1 && < 1.4,
filepath >= 1.1 && < 1.5,
- hslua >= 0.9.5 && < 0.9.6,
+ hslua >= 1.0 && < 1.1,
process >= 1.2.3 && < 1.7,
temporary >= 1.1 && < 1.4,
Diff >= 0.2 && < 0.4,
- tasty >= 0.11 && < 1.1,
+ tasty >= 0.11 && < 1.2,
tasty-hunit >= 0.9 && < 0.11,
tasty-quickcheck >= 0.8 && < 0.11,
tasty-golden >= 2.3 && < 2.4,
@@ -696,9 +698,9 @@ benchmark benchmark-pandoc
hs-source-dirs: benchmark
build-depends: pandoc,
time, bytestring, containers,
- base >= 4.2 && < 5,
+ base >= 4.8 && < 5,
text >= 0.11 && < 1.3,
- criterion >= 1.0 && < 1.5
+ criterion >= 1.0 && < 1.6
if impl(ghc < 8.0)
build-depends: semigroups == 0.18.*
if impl(ghc < 8.4)
diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs
index a59fd9bbe..79d83c0d3 100644
--- a/src/Text/Pandoc/App.hs
+++ b/src/Text/Pandoc/App.hs
@@ -52,7 +52,7 @@ import Data.Aeson (defaultOptions)
import Data.Aeson.TH (deriveJSON)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as B
-import Data.Char (toLower, toUpper, isAscii, ord)
+import Data.Char (toLower, toUpper)
import Data.List (find, intercalate, isPrefixOf, isSuffixOf, sort)
import qualified Data.Map as M
import Data.Maybe (fromMaybe, isJust, isNothing)
@@ -62,8 +62,7 @@ import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TE
import qualified Data.Text.Encoding.Error as TE
-import Data.Yaml (decode)
-import qualified Data.Yaml as Yaml
+import qualified Data.YAML as YAML
import GHC.Generics
import Network.URI (URI (..), parseURI)
#ifdef EMBED_DATA_FILES
@@ -84,19 +83,18 @@ import System.Exit (exitSuccess)
import System.FilePath
import System.IO (nativeNewline, stdout)
import qualified System.IO as IO (Newline (..))
-import System.IO.Error (isDoesNotExistError)
import Text.Pandoc
import Text.Pandoc.BCP47 (Lang (..), parseBCP47)
import Text.Pandoc.Builder (setMeta, deleteMeta)
import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), applyFilters)
import Text.Pandoc.Highlighting (highlightingStyles)
import Text.Pandoc.PDF (makePDF)
+import Text.Pandoc.Readers.Markdown (yamlToMeta)
import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)
import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
headerShift, isURI, ordNub, safeRead, tabFilter, uriPathToPath)
import qualified Text.Pandoc.UTF8 as UTF8
import Text.Pandoc.Writers.Math (defaultKaTeXURL, defaultMathJaxURL)
-import Text.Pandoc.XML (toEntities)
import Text.Printf
#ifndef _WINDOWS
import System.Posix.IO (stdOutput)
@@ -144,6 +142,13 @@ engines = map ("html",) htmlEngines ++
pdfEngines :: [String]
pdfEngines = ordNub $ map snd engines
+pdfIsNoWriterErrorMsg :: String
+pdfIsNoWriterErrorMsg =
+ "To create a pdf using pandoc, use " ++
+ "-t latex|beamer|context|ms|html5" ++
+ "\nand specify an output file with " ++
+ ".pdf extension (-o filename.pdf)."
+
pdfWriterAndProg :: Maybe String -- ^ user-specified writer name
-> Maybe String -- ^ user-specified pdf-engine
-> IO (String, Maybe String) -- ^ IO (writerName, maybePdfEngineProg)
@@ -155,9 +160,9 @@ pdfWriterAndProg mWriter mEngine = do
where
go Nothing Nothing = Right ("latex", "pdflatex")
go (Just writer) Nothing = (writer,) <$> engineForWriter writer
- go Nothing (Just engine) = (,engine) <$> writerForEngine engine
+ go Nothing (Just engine) = (,engine) <$> writerForEngine (takeBaseName engine)
go (Just writer) (Just engine) =
- case find (== (baseWriterName writer, engine)) engines of
+ case find (== (baseWriterName writer, takeBaseName engine)) engines of
Just _ -> Right (writer, engine)
Nothing -> Left $ "pdf-engine " ++ engine ++
" is not compatible with output format " ++ writer
@@ -167,6 +172,7 @@ pdfWriterAndProg mWriter mEngine = do
[] -> Left $
"pdf-engine " ++ eng ++ " not known"
+ engineForWriter "pdf" = Left pdfIsNoWriterErrorMsg
engineForWriter w = case [e | (f,e) <- engines, f == baseWriterName w] of
eng : _ -> Right eng
[] -> Left $
@@ -235,11 +241,7 @@ convertWithOpts opts = do
else case getWriter (map toLower writerName) of
Left e -> E.throwIO $ PandocAppError $
if format == "pdf"
- then e ++
- "\nTo create a pdf using pandoc, use " ++
- "-t latex|beamer|context|ms|html5" ++
- "\nand specify an output file with " ++
- ".pdf extension (-o filename.pdf)."
+ then e ++ "\n" ++ pdfIsNoWriterErrorMsg
else e
Right (w, es) -> return (w :: Writer PandocIO, es)
@@ -381,11 +383,10 @@ convertWithOpts opts = do
"" -> tp <.> format
_ -> tp
Just . UTF8.toString <$>
- (readFileStrict tp' `catchError`
+ ((fst <$> fetchItem tp') `catchError`
(\e ->
case e of
- PandocIOError _ e' |
- isDoesNotExistError e' ->
+ PandocResourceNotFound _ ->
readDataFile ("templates" </> tp')
_ -> throwError e))
@@ -398,6 +399,10 @@ convertWithOpts opts = do
("application/xml", jatsCSL)
return $ ("csl", jatsEncoded) : optMetadata opts
else return $ optMetadata opts
+ metadataFromFile <-
+ case optMetadataFile opts of
+ Nothing -> return mempty
+ Just file -> readFileLazy file >>= yamlToMeta
case lookup "lang" (optMetadata opts) of
Just l -> case parseBCP47 l of
@@ -437,6 +442,7 @@ convertWithOpts opts = do
, writerTOCDepth = optTOCDepth opts
, writerReferenceDoc = optReferenceDoc opts
, writerSyntaxMap = syntaxMap
+ , writerPreferAscii = optAscii opts
}
let readerOpts = def{
@@ -490,6 +496,7 @@ convertWithOpts opts = do
( (if isJust (optExtractMedia opts)
then fillMediaBag
else return)
+ >=> return . addNonPresentMetadata metadataFromFile
>=> return . addMetadata metadata
>=> applyTransforms transforms
>=> applyFilters readerOpts filters' [format]
@@ -512,19 +519,10 @@ convertWithOpts opts = do
let htmlFormat = format `elem`
["html","html4","html5","s5","slidy",
"slideous","dzslides","revealjs"]
- escape
- | optAscii opts
- , htmlFormat || format == "docbook4" ||
- format == "docbook5" || format == "docbook" ||
- format == "jats" || format == "opml" ||
- format == "icml" = toEntities
- | optAscii opts
- , format == "ms" || format == "man" = groffEscape
- | otherwise = id
addNl = if standalone
then id
else (<> T.singleton '\n')
- output <- (addNl . escape) <$> f writerOptions doc
+ output <- addNl <$> f writerOptions doc
writerFn eol outputFile =<<
if optSelfContained opts && htmlFormat
-- TODO not maximally efficient; change type
@@ -532,12 +530,6 @@ convertWithOpts opts = do
then T.pack <$> makeSelfContained (T.unpack output)
else return output
-groffEscape :: Text -> Text
-groffEscape = T.concatMap toUchar
- where toUchar c
- | isAscii c = T.singleton c
- | otherwise = T.pack $ printf "\\[u%04X]" (ord c)
-
type Transform = Pandoc -> Pandoc
isTextFormat :: String -> Bool
@@ -555,6 +547,7 @@ data Opt = Opt
, optTemplate :: Maybe FilePath -- ^ Custom template
, optVariables :: [(String,String)] -- ^ Template variables to set
, optMetadata :: [(String, String)] -- ^ Metadata fields to set
+ , optMetadataFile :: Maybe FilePath -- ^ Name of YAML metadata file
, optOutputFile :: Maybe FilePath -- ^ Name of output file
, optInputFiles :: [FilePath] -- ^ Names of input files
, optNumberSections :: Bool -- ^ Number sections in LaTeX
@@ -598,7 +591,7 @@ data Opt = Opt
, optPdfEngineArgs :: [String] -- ^ Flags to pass to the engine
, optSlideLevel :: Maybe Int -- ^ Header level that creates slides
, optSetextHeaders :: Bool -- ^ Use atx headers for markdown level 1-2
- , optAscii :: Bool -- ^ Use ascii characters only in html
+ , optAscii :: Bool -- ^ Prefer ascii output
, optDefaultImageExtension :: String -- ^ Default image extension
, optExtractMedia :: Maybe FilePath -- ^ Path to extract embedded media
, optTrackChanges :: TrackChanges -- ^ Accept or reject MS Word track-changes.
@@ -627,6 +620,7 @@ defaultOpts = Opt
, optTemplate = Nothing
, optVariables = []
, optMetadata = []
+ , optMetadataFile = Nothing
, optOutputFile = Nothing
, optInputFiles = []
, optNumberSections = False
@@ -686,6 +680,9 @@ defaultOpts = Opt
, optStripComments = False
}
+addNonPresentMetadata :: Text.Pandoc.Meta -> Pandoc -> Pandoc
+addNonPresentMetadata newmeta (Pandoc meta bs) = Pandoc (meta <> newmeta) bs
+
addMetadata :: [(String, String)] -> Pandoc -> Pandoc
addMetadata kvs pdc = foldr addMeta (removeMetaKeys kvs pdc) kvs
@@ -702,10 +699,12 @@ removeMetaKeys :: [(String,String)] -> Pandoc -> Pandoc
removeMetaKeys kvs pdc = foldr (deleteMeta . fst) pdc kvs
readMetaValue :: String -> MetaValue
-readMetaValue s = case decode (UTF8.fromString s) of
- Just (Yaml.String t) -> MetaString $ T.unpack t
- Just (Yaml.Bool b) -> MetaBool b
- _ -> MetaString s
+readMetaValue s = case YAML.decodeStrict (UTF8.fromString s) of
+ Right [YAML.Scalar (YAML.SStr t)]
+ -> MetaString $ T.unpack t
+ Right [YAML.Scalar (YAML.SBool b)]
+ -> MetaBool b
+ _ -> MetaString s
-- Determine default reader based on source file extensions
defaultReaderName :: String -> [FilePath] -> String
@@ -960,6 +959,12 @@ options =
"KEY[:VALUE]")
""
+ , Option "" ["metadata-file"]
+ (ReqArg
+ (\arg opt -> return opt{ optMetadataFile = Just arg })
+ "FILE")
+ ""
+
, Option "V" ["variable"]
(ReqArg
(\arg opt -> do
@@ -1153,7 +1158,7 @@ options =
, Option "" ["ascii"]
(NoArg
(\opt -> return opt { optAscii = True }))
- "" -- "Use ascii characters only in HTML output"
+ "" -- "Prefer ASCII output"
, Option "" ["reference-links"]
(NoArg
diff --git a/src/Text/Pandoc/Class.hs b/src/Text/Pandoc/Class.hs
index 4ade2dc6d..e47546dfc 100644
--- a/src/Text/Pandoc/Class.hs
+++ b/src/Text/Pandoc/Class.hs
@@ -132,7 +132,7 @@ import Network.HTTP.Client.Internal (addProxy)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import System.Environment (getEnv)
import Network.HTTP.Types.Header ( hContentType )
-import Network (withSocketsDo)
+import Network.Socket (withSocketsDo)
import Data.ByteString.Lazy (toChunks)
import qualified Control.Exception as E
import qualified Data.Time.LocalTime as IO (getCurrentTimeZone)
@@ -882,10 +882,10 @@ adjustImagePath _ _ x = x
-- of things that would normally be obtained through IO.
data PureState = PureState { stStdGen :: StdGen
, stWord8Store :: [Word8] -- should be
- -- inifinite,
+ -- infinite,
-- i.e. [1..]
, stUniqStore :: [Int] -- should be
- -- inifinite and
+ -- infinite and
-- contain every
-- element at most
-- once, e.g. [1..]
diff --git a/src/Text/Pandoc/Emoji.hs b/src/Text/Pandoc/Emoji.hs
index 5cc965153..7d0af1a72 100644
--- a/src/Text/Pandoc/Emoji.hs
+++ b/src/Text/Pandoc/Emoji.hs
@@ -28,9 +28,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Emoji symbol lookup from canonical string identifier.
-}
-module Text.Pandoc.Emoji ( emojis ) where
+module Text.Pandoc.Emoji ( emojis, emojiToInline ) where
import Prelude
import qualified Data.Map as M
+import Text.Pandoc.Definition (Inline (Span, Str))
emojis :: M.Map String String
emojis = M.fromList
@@ -905,3 +906,7 @@ emojis = M.fromList
,("zero","0\65039\8419")
,("zzz","\128164")
]
+
+emojiToInline :: String -> Maybe Inline
+emojiToInline emojikey = makeSpan <$> M.lookup emojikey emojis
+ where makeSpan = Span ("", ["emoji"], [("data-emoji", emojikey)]) . (:[]) . Str
diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs
index 5ccb7dffb..b60c57497 100644
--- a/src/Text/Pandoc/Extensions.hs
+++ b/src/Text/Pandoc/Extensions.hs
@@ -101,7 +101,10 @@ data Extension =
-- and disallow laziness
| Ext_definition_lists -- ^ Definition lists as in pandoc, mmd, php
| Ext_east_asian_line_breaks -- ^ Newlines in paragraphs are ignored between
- -- East Asian wide characters
+ -- East Asian wide characters. Note: this extension
+ -- does not affect readers/writers directly; it causes
+ -- the eastAsianLineBreakFilter to be applied after
+ -- parsing, in Text.Pandoc.App.convertWithOpts.
| Ext_emoji -- ^ Support emoji like :smile:
| Ext_empty_paragraphs -- ^ Allow empty paragraphs
| Ext_epub_html_exts -- ^ Recognise the EPUB extended version of HTML
@@ -111,7 +114,7 @@ data Extension =
| Ext_fenced_code_attributes -- ^ Allow attributes on fenced code blocks
| Ext_fenced_code_blocks -- ^ Parse fenced code blocks
| Ext_fenced_divs -- ^ Allow fenced div syntax :::
- | Ext_footnotes -- ^ Pandoc/PHP/MMD style footnotes
+ | Ext_footnotes -- ^ Pandoc\/PHP\/MMD style footnotes
| Ext_four_space_rule -- ^ Require 4-space indent for list contents
| Ext_gfm_auto_identifiers -- ^ Automatic identifiers for headers, using
-- GitHub's method for generating identifiers
diff --git a/src/Text/Pandoc/Highlighting.hs b/src/Text/Pandoc/Highlighting.hs
index 70bb70302..672eca392 100644
--- a/src/Text/Pandoc/Highlighting.hs
+++ b/src/Text/Pandoc/Highlighting.hs
@@ -45,6 +45,7 @@ module Text.Pandoc.Highlighting ( highlightingStyles
, tango
, kate
, monochrome
+ , breezeDark
, haddock
, Style
, fromListingsLanguage
diff --git a/src/Text/Pandoc/ImageSize.hs b/src/Text/Pandoc/ImageSize.hs
index c5fe98a66..d57f66da5 100644
--- a/src/Text/Pandoc/ImageSize.hs
+++ b/src/Text/Pandoc/ImageSize.hs
@@ -319,20 +319,22 @@ pngSize img = do
(shift w1 24 + shift w2 16 + shift w3 8 + w4,
shift h1 24 + shift h2 16 + shift h3 8 + h4)
_ -> Nothing -- "PNG parse error"
- let (dpix, dpiy) = findpHYs rest''
+ (dpix, dpiy) <- findpHYs rest''
return ImageSize { pxX = x, pxY = y, dpiX = dpix, dpiY = dpiy }
-findpHYs :: ByteString -> (Integer, Integer)
+findpHYs :: ByteString -> Maybe (Integer, Integer)
findpHYs x
- | B.null x || "IDAT" `B.isPrefixOf` x = (72,72)
+ | B.null x || "IDAT" `B.isPrefixOf` x = return (72,72)
| "pHYs" `B.isPrefixOf` x =
- let [x1,x2,x3,x4,y1,y2,y3,y4,u] =
- map fromIntegral $ unpack $ B.take 9 $ B.drop 4 x
- factor = if u == 1 -- dots per meter
- then \z -> z * 254 `div` 10000
- else const 72
- in ( factor $ shift x1 24 + shift x2 16 + shift x3 8 + x4,
- factor $ shift y1 24 + shift y2 16 + shift y3 8 + y4 )
+ case map fromIntegral $ unpack $ B.take 9 $ B.drop 4 x of
+ [x1,x2,x3,x4,y1,y2,y3,y4,u] -> do
+ let factor = if u == 1 -- dots per meter
+ then \z -> z * 254 `div` 10000
+ else const 72
+ return
+ ( factor $ shift x1 24 + shift x2 16 + shift x3 8 + x4,
+ factor $ shift y1 24 + shift y2 16 + shift y3 8 + y4 )
+ _ -> mzero
| otherwise = findpHYs $ B.drop 1 x -- read another byte
gifSize :: ByteString -> Maybe ImageSize
@@ -408,20 +410,21 @@ jpegSize img =
jfifSize :: ByteString -> Either String ImageSize
jfifSize rest =
- let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral
- $ unpack $ B.take 5 $B.drop 9 rest
- factor = case dpiDensity of
- 1 -> id
- 2 -> \x -> x * 254 `div` 10
- _ -> const 72
- dpix = factor (shift dpix1 8 + dpix2)
- dpiy = factor (shift dpiy1 8 + dpiy2)
- in case findJfifSize rest of
- Left msg -> Left msg
- Right (w,h) ->Right ImageSize { pxX = w
+ case map fromIntegral $ unpack $ B.take 5 $ B.drop 9 rest of
+ [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] ->
+ let factor = case dpiDensity of
+ 1 -> id
+ 2 -> \x -> x * 254 `div` 10
+ _ -> const 72
+ dpix = factor (shift dpix1 8 + dpix2)
+ dpiy = factor (shift dpiy1 8 + dpiy2)
+ in case findJfifSize rest of
+ Left msg -> Left msg
+ Right (w,h) -> Right ImageSize { pxX = w
, pxY = h
, dpiX = dpix
, dpiY = dpiy }
+ _ -> Left "unable to determine JFIF size"
findJfifSize :: ByteString -> Either String (Integer,Integer)
findJfifSize bs =
@@ -541,10 +544,12 @@ exifHeader hdr = do
let resfactor = case lookup ResolutionUnit allentries of
Just (UnsignedShort 1) -> 100 / 254
_ -> 1
- let xres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor)
- $ lookup XResolution allentries
- let yres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor)
- $ lookup YResolution allentries
+ let xres = case lookup XResolution allentries of
+ Just (UnsignedRational x) -> floor (x * resfactor)
+ _ -> 72
+ let yres = case lookup YResolution allentries of
+ Just (UnsignedRational y) -> floor (y * resfactor)
+ _ -> 72
return ImageSize{
pxX = wdth
, pxY = hght
diff --git a/src/Text/Pandoc/Lua.hs b/src/Text/Pandoc/Lua.hs
index cd7117074..e160f7123 100644
--- a/src/Text/Pandoc/Lua.hs
+++ b/src/Text/Pandoc/Lua.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright © 2017–2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -16,6 +15,7 @@ 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
-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- |
Module : Text.Pandoc.Lua
Copyright : Copyright © 2017–2018 Albert Krewinkel
@@ -34,14 +34,14 @@ module Text.Pandoc.Lua
import Prelude
import Control.Monad ((>=>))
-import Foreign.Lua (FromLuaStack (peek), Lua, LuaException (..),
- Status (OK), ToLuaStack (push))
+import Foreign.Lua (Lua)
import Text.Pandoc.Class (PandocIO)
import Text.Pandoc.Definition (Pandoc)
import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
-import Text.Pandoc.Lua.Init (runPandocLua, registerScriptPath)
-import Text.Pandoc.Lua.Util (popValue)
+import Text.Pandoc.Lua.Init (LuaException (..), runPandocLua, registerScriptPath)
+import Text.Pandoc.Lua.Util (dofileWithTraceback)
import Text.Pandoc.Options (ReaderOptions)
+
import qualified Foreign.Lua as Lua
-- | Run the Lua filter in @filterPath@ for a transformation to target
@@ -59,26 +59,24 @@ runLuaFilter' ropts filterPath format pd = do
registerReaderOptions
registerScriptPath filterPath
top <- Lua.gettop
- stat <- Lua.dofile filterPath
- if stat /= OK
- then do
- luaErrMsg <- popValue
- Lua.throwLuaError luaErrMsg
+ stat <- dofileWithTraceback filterPath
+ if stat /= Lua.OK
+ then Lua.throwTopMessage
else do
newtop <- Lua.gettop
-- Use the returned filters, or the implicitly defined global filter if
-- nothing was returned.
luaFilters <- if newtop - top >= 1
- then peek (-1)
- else Lua.getglobal "_G" *> fmap (:[]) popValue
+ then Lua.peek Lua.stackTop
+ else Lua.pushglobaltable *> fmap (:[]) Lua.popValue
runAll luaFilters pd
where
registerFormat = do
- push format
+ Lua.push format
Lua.setglobal "FORMAT"
registerReaderOptions = do
- push ropts
+ Lua.push ropts
Lua.setglobal "PANDOC_READER_OPTIONS"
runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
diff --git a/src/Text/Pandoc/Lua/Filter.hs b/src/Text/Pandoc/Lua/Filter.hs
index 264066305..d17f9a969 100644
--- a/src/Text/Pandoc/Lua/Filter.hs
+++ b/src/Text/Pandoc/Lua/Filter.hs
@@ -1,6 +1,33 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-
+Copyright © 2012-2018 John MacFarlane <jgm@berkeley.edu>
+ 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+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
+-}
{-# LANGUAGE FlexibleContexts #-}
-
+{-# LANGUAGE NoImplicitPrelude #-}
+{- |
+Module : Text.Pandoc.Lua.Filter
+Copyright : © 2012–2018 John MacFarlane,
+ © 2017-2018 Albert Krewinkel
+License : GNU GPL, version 2 or above
+Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+Stability : alpha
+
+Types and functions for running Lua filters.
+-}
module Text.Pandoc.Lua.Filter ( LuaFilterFunction
, LuaFilter
, tryFilter
@@ -12,62 +39,58 @@ module Text.Pandoc.Lua.Filter ( LuaFilterFunction
, inlineElementNames
) where
import Prelude
-import Control.Monad (mplus, unless, when, (>=>))
+import Control.Monad (mplus, (>=>))
import Control.Monad.Catch (finally)
-import Text.Pandoc.Definition
+import Data.Data (Data, DataType, dataTypeConstrs, dataTypeName, dataTypeOf,
+ showConstr, toConstr, tyconUQname)
import Data.Foldable (foldrM)
import Data.Map (Map)
-import qualified Data.Map as Map
-import qualified Foreign.Lua as Lua
-import Foreign.Lua (FromLuaStack (peek), Lua, StackIndex,
- Status (OK), ToLuaStack (push))
+import Foreign.Lua (Lua, Peekable, Pushable)
+import Text.Pandoc.Definition
+import Text.Pandoc.Lua.StackInstances ()
import Text.Pandoc.Walk (walkM, Walkable)
-import Data.Data (Data, DataType, dataTypeConstrs, dataTypeName, dataTypeOf,
- showConstr, toConstr, tyconUQname)
-import Text.Pandoc.Lua.StackInstances()
-import Text.Pandoc.Lua.Util (typeCheck)
-type FunctionMap = Map String LuaFilterFunction
-
-newtype LuaFilterFunction = LuaFilterFunction { functionIndex :: Int }
-
-instance ToLuaStack LuaFilterFunction where
- push = pushFilterFunction
-
-instance FromLuaStack LuaFilterFunction where
- peek = registerFilterFunction
-
-newtype LuaFilter = LuaFilter FunctionMap
-
-instance FromLuaStack LuaFilter where
- peek idx =
- let constrs = metaFilterName : pandocFilterNames
- ++ blockElementNames
- ++ inlineElementNames
- fn c acc = do
- Lua.getfield idx c
- filterFn <- Lua.tryLua (peek (-1))
- Lua.pop 1
+import qualified Data.Map.Strict as Map
+import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.Lua.Util as LuaUtil
+
+-- | Filter function stored in the registry
+newtype LuaFilterFunction = LuaFilterFunction Lua.Reference
+
+-- | Collection of filter functions (at most one function per element
+-- constructor)
+newtype LuaFilter = LuaFilter (Map String LuaFilterFunction)
+
+instance Peekable LuaFilter where
+ peek idx = do
+ let constrs = metaFilterName
+ : pandocFilterNames
+ ++ blockElementNames
+ ++ inlineElementNames
+ let go constr acc = do
+ Lua.getfield idx constr
+ filterFn <- registerFilterFunction
return $ case filterFn of
- Left _ -> acc
- Right f -> (c, f) : acc
- in LuaFilter . Map.fromList <$> foldrM fn [] constrs
-
--- | Push the filter function to the top of the stack.
+ Nothing -> acc
+ Just fn -> Map.insert constr fn acc
+ LuaFilter <$> foldrM go Map.empty constrs
+
+-- | Register the function at the top of the stack as a filter function in the
+-- registry.
+registerFilterFunction :: Lua (Maybe LuaFilterFunction)
+registerFilterFunction = do
+ isFn <- Lua.isfunction Lua.stackTop
+ if isFn
+ then Just . LuaFilterFunction <$> Lua.ref Lua.registryindex
+ else Nothing <$ Lua.pop 1
+
+-- | Retrieve filter function from registry and push it to the top of the stack.
pushFilterFunction :: LuaFilterFunction -> Lua ()
-pushFilterFunction lf =
- -- The function is stored in a lua registry table, retrieve it from there.
- Lua.rawgeti Lua.registryindex (functionIndex lf)
-
-registerFilterFunction :: StackIndex -> Lua LuaFilterFunction
-registerFilterFunction idx = do
- isFn <- Lua.isfunction idx
- unless isFn . Lua.throwLuaError $ "Not a function at index " ++ show idx
- Lua.pushvalue idx
- refIdx <- Lua.ref Lua.registryindex
- return $ LuaFilterFunction refIdx
-
-elementOrList :: FromLuaStack a => a -> Lua [a]
+pushFilterFunction (LuaFilterFunction fnRef) =
+ Lua.getref Lua.registryindex fnRef
+
+
+elementOrList :: Peekable a => a -> Lua [a]
elementOrList x = do
let topOfStack = Lua.stackTop
elementUnchanged <- Lua.isnil topOfStack
@@ -77,12 +100,10 @@ elementOrList x = do
mbres <- Lua.peekEither topOfStack
case mbres of
Right res -> [res] <$ Lua.pop 1
- Left _ -> do
- typeCheck Lua.stackTop Lua.TypeTable
- Lua.toList topOfStack `finally` Lua.pop 1
+ Left _ -> Lua.peekList topOfStack `finally` Lua.pop 1
-- | Try running a filter for the given element
-tryFilter :: (Data a, FromLuaStack a, ToLuaStack a)
+tryFilter :: (Data a, Peekable a, Pushable a)
=> LuaFilter -> a -> Lua [a]
tryFilter (LuaFilter fnMap) x =
let filterFnName = showConstr (toConstr x)
@@ -96,14 +117,11 @@ tryFilter (LuaFilter fnMap) x =
-- called with given element as argument and is expected to return an element.
-- Alternatively, the function can return nothing or nil, in which case the
-- element is left unchanged.
-runFilterFunction :: ToLuaStack a => LuaFilterFunction -> a -> Lua ()
+runFilterFunction :: Pushable a => LuaFilterFunction -> a -> Lua ()
runFilterFunction lf x = do
pushFilterFunction lf
- push x
- z <- Lua.pcall 1 1 Nothing
- when (z /= OK) $ do
- let addPrefix = ("Error while running filter function: " ++)
- Lua.throwTopMessageAsError' addPrefix
+ Lua.push x
+ LuaUtil.callWithTraceback 1 1
walkMWithLuaFilter :: LuaFilter -> Pandoc -> Lua Pandoc
walkMWithLuaFilter f =
@@ -156,7 +174,7 @@ metaFilterName = "Meta"
pandocFilterNames :: [String]
pandocFilterNames = ["Pandoc", "Doc"]
-singleElement :: FromLuaStack a => a -> Lua a
+singleElement :: Peekable a => a -> Lua a
singleElement x = do
elementUnchanged <- Lua.isnil (-1)
if elementUnchanged
@@ -167,6 +185,6 @@ singleElement x = do
Right res -> res <$ Lua.pop 1
Left err -> do
Lua.pop 1
- Lua.throwLuaError $
+ Lua.throwException $
"Error while trying to get a filter's return " ++
"value from lua stack.\n" ++ err
diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs
index c8c7fdfbd..35611d481 100644
--- a/src/Text/Pandoc/Lua/Init.hs
+++ b/src/Text/Pandoc/Lua/Init.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -16,6 +15,7 @@ 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
-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- |
Module : Text.Pandoc.Lua
Copyright : Copyright © 2017-2018 Albert Krewinkel
@@ -40,7 +40,7 @@ import Control.Monad.Trans (MonadIO (..))
import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
import Data.IORef (newIORef, readIORef)
import Data.Version (Version (versionBranch))
-import Foreign.Lua (Lua, LuaException (..))
+import Foreign.Lua (Lua)
import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
import Paths_pandoc (version)
import Text.Pandoc.Class (PandocIO, getCommonState, getUserDataDir, getMediaBag,
@@ -54,17 +54,22 @@ import qualified Foreign.Lua as Lua
import qualified Foreign.Lua.Module.Text as Lua
import qualified Text.Pandoc.Definition as Pandoc
+-- | Lua error message
+newtype LuaException = LuaException String deriving (Show)
+
-- | Run the lua interpreter, using pandoc's default way of environment
--- initalization.
+-- initialization.
runPandocLua :: Lua a -> PandocIO (Either LuaException a)
runPandocLua luaOp = do
luaPkgParams <- luaPackageParams
enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
- res <- liftIO $ Lua.runLuaEither (initLuaState luaPkgParams *> luaOp)
+ res <- liftIO $ Lua.runEither (initLuaState luaPkgParams *> luaOp)
liftIO $ setForeignEncoding enc
newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
setMediaBag newMediaBag
- return res
+ return $ case res of
+ Left (Lua.Exception msg) -> Left (LuaException msg)
+ Right x -> Right x
-- | Generate parameters required to setup pandoc's lua environment.
luaPackageParams :: PandocIO LuaPackageParams
diff --git a/src/Text/Pandoc/Lua/Module/MediaBag.hs b/src/Text/Pandoc/Lua/Module/MediaBag.hs
index f48fe56c5..150c06cc8 100644
--- a/src/Text/Pandoc/Lua/Module/MediaBag.hs
+++ b/src/Text/Pandoc/Lua/Module/MediaBag.hs
@@ -87,7 +87,7 @@ mediaDirectoryFn mbRef = do
zipWithM_ addEntry [1..] dirContents
return 1
where
- addEntry :: Int -> (FilePath, MimeType, Int) -> Lua ()
+ addEntry :: Lua.Integer -> (FilePath, MimeType, Int) -> Lua ()
addEntry idx (fp, mimeType, contentLength) = do
Lua.newtable
Lua.push "path" *> Lua.push fp *> Lua.rawset (-3)
diff --git a/src/Text/Pandoc/Lua/Module/Pandoc.hs b/src/Text/Pandoc/Lua/Module/Pandoc.hs
index 8cb630d7b..769b04b9e 100644
--- a/src/Text/Pandoc/Lua/Module/Pandoc.hs
+++ b/src/Text/Pandoc/Lua/Module/Pandoc.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -17,6 +16,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- |
Module : Text.Pandoc.Lua.Module.Pandoc
Copyright : Copyright © 2017-2018 Albert Krewinkel
@@ -36,13 +36,12 @@ import Control.Monad (when)
import Data.Default (Default (..))
import Data.Maybe (fromMaybe)
import Data.Text (pack)
-import Foreign.Lua (ToLuaStack, FromLuaStack, Lua, NumResults, Optional, liftIO)
+import Foreign.Lua (Lua, NumResults, Optional, Peekable, Pushable)
import System.Exit (ExitCode (..))
import Text.Pandoc.Class (runIO)
import Text.Pandoc.Definition (Block, Inline)
import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter)
import Text.Pandoc.Lua.StackInstances ()
-import Text.Pandoc.Lua.Util (addFunction, addValue, loadScriptFromDataDir)
import Text.Pandoc.Walk (Walkable)
import Text.Pandoc.Options (ReaderOptions (readerExtensions))
import Text.Pandoc.Process (pipeProcess)
@@ -51,19 +50,20 @@ import Text.Pandoc.Readers (Reader (..), getReader)
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.Lua.Util as LuaUtil
-- | Push the "pandoc" on the lua stack. Requires the `list` module to be
-- loaded.
pushModule :: Maybe FilePath -> Lua NumResults
pushModule datadir = do
- loadScriptFromDataDir datadir "pandoc.lua"
- addFunction "read" readDoc
- addFunction "pipe" pipeFn
- addFunction "walk_block" walkBlock
- addFunction "walk_inline" walkInline
+ LuaUtil.loadScriptFromDataDir datadir "pandoc.lua"
+ LuaUtil.addFunction "read" readDoc
+ LuaUtil.addFunction "pipe" pipeFn
+ LuaUtil.addFunction "walk_block" walkBlock
+ LuaUtil.addFunction "walk_inline" walkInline
return 1
-walkElement :: (ToLuaStack a, Walkable [Inline] a, Walkable [Block] a)
+walkElement :: (Pushable a, Walkable [Inline] a, Walkable [Block] a)
=> a -> LuaFilter -> Lua a
walkElement x f = walkInlines f x >>= walkBlocks f
@@ -81,7 +81,8 @@ readDoc content formatSpecOrNil = do
Right (reader, es) ->
case reader of
TextReader r -> do
- res <- liftIO $ runIO $ r def{ readerExtensions = es } (pack content)
+ res <- Lua.liftIO . runIO $
+ r def{ readerExtensions = es } (pack content)
case res of
Right pd -> (1 :: NumResults) <$ Lua.push pd -- success, push Pandoc
Left s -> Lua.raiseError (show s) -- error while reading
@@ -93,7 +94,7 @@ pipeFn :: String
-> BL.ByteString
-> Lua NumResults
pipeFn command args input = do
- (ec, output) <- liftIO $ pipeProcess Nothing command args input
+ (ec, output) <- Lua.liftIO $ pipeProcess Nothing command args input
case ec of
ExitSuccess -> 1 <$ Lua.push output
ExitFailure n -> Lua.raiseError (PipeError command n output)
@@ -104,26 +105,26 @@ data PipeError = PipeError
, pipeErrorOutput :: BL.ByteString
}
-instance FromLuaStack PipeError where
+instance Peekable PipeError where
peek idx =
PipeError
<$> (Lua.getfield idx "command" *> Lua.peek (-1) <* Lua.pop 1)
<*> (Lua.getfield idx "error_code" *> Lua.peek (-1) <* Lua.pop 1)
<*> (Lua.getfield idx "output" *> Lua.peek (-1) <* Lua.pop 1)
-instance ToLuaStack PipeError where
+instance Pushable PipeError where
push pipeErr = do
Lua.newtable
- addValue "command" (pipeErrorCommand pipeErr)
- addValue "error_code" (pipeErrorCode pipeErr)
- addValue "output" (pipeErrorOutput pipeErr)
+ LuaUtil.addField "command" (pipeErrorCommand pipeErr)
+ LuaUtil.addField "error_code" (pipeErrorCode pipeErr)
+ LuaUtil.addField "output" (pipeErrorOutput pipeErr)
pushPipeErrorMetaTable
Lua.setmetatable (-2)
where
pushPipeErrorMetaTable :: Lua ()
pushPipeErrorMetaTable = do
v <- Lua.newmetatable "pandoc pipe error"
- when v $ addFunction "__tostring" pipeErrorMessage
+ when v $ LuaUtil.addFunction "__tostring" pipeErrorMessage
pipeErrorMessage :: PipeError -> Lua BL.ByteString
pipeErrorMessage (PipeError cmd errorCode output) = return $ mconcat
diff --git a/src/Text/Pandoc/Lua/Module/Utils.hs b/src/Text/Pandoc/Lua/Module/Utils.hs
index 7fa4616be..030d6af95 100644
--- a/src/Text/Pandoc/Lua/Module/Utils.hs
+++ b/src/Text/Pandoc/Lua/Module/Utils.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -16,6 +15,7 @@ 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
-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- |
Module : Text.Pandoc.Lua.Module.Utils
Copyright : Copyright © 2017-2018 Albert Krewinkel
@@ -33,15 +33,16 @@ module Text.Pandoc.Lua.Module.Utils
import Prelude
import Control.Applicative ((<|>))
import Data.Default (def)
-import Foreign.Lua (FromLuaStack, Lua, LuaInteger, NumResults)
+import Foreign.Lua (Peekable, Lua, NumResults)
import Text.Pandoc.Class (runIO, setUserDataDir)
import Text.Pandoc.Definition (Pandoc, Meta, MetaValue, Block, Inline)
import Text.Pandoc.Lua.StackInstances ()
-import Text.Pandoc.Lua.Util (addFunction, popValue)
+import Text.Pandoc.Lua.Util (addFunction)
import qualified Data.Digest.Pure.SHA as SHA
import qualified Data.ByteString.Lazy as BSL
import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.Builder as B
import qualified Text.Pandoc.Filter.JSON as JSONFilter
import qualified Text.Pandoc.Shared as Shared
@@ -49,6 +50,7 @@ import qualified Text.Pandoc.Shared as Shared
pushModule :: Maybe FilePath -> Lua NumResults
pushModule mbDatadir = do
Lua.newtable
+ addFunction "blocks_to_inlines" blocksToInlines
addFunction "hierarchicalize" hierarchicalize
addFunction "normalize_date" normalizeDate
addFunction "run_json_filter" (runJSONFilter mbDatadir)
@@ -57,6 +59,14 @@ pushModule mbDatadir = do
addFunction "to_roman_numeral" toRomanNumeral
return 1
+-- | Squashes a list of blocks into inlines.
+blocksToInlines :: [Block] -> Lua.Optional [Inline] -> Lua [Inline]
+blocksToInlines blks optSep = do
+ let sep = case Lua.fromOptional optSep of
+ Just x -> B.fromList x
+ Nothing -> Shared.defaultBlocksSeparator
+ return $ B.toList (Shared.blocksToInlinesWithSep sep blks)
+
-- | Convert list of Pandoc blocks into (hierarchical) list of Elements.
hierarchicalize :: [Block] -> Lua [Shared.Element]
hierarchicalize = return . Shared.hierarchicalize
@@ -79,7 +89,7 @@ runJSONFilter mbDatadir doc filterFile optArgs = do
Just x -> return x
Nothing -> do
Lua.getglobal "FORMAT"
- (:[]) <$> popValue
+ (:[]) <$> Lua.popValue
filterRes <- Lua.liftIO . runIO $ do
setUserDataDir mbDatadir
JSONFilter.apply def args filterFile doc
@@ -111,18 +121,18 @@ data AstElement
| MetaValueElement MetaValue
deriving (Show)
-instance FromLuaStack AstElement where
+instance Peekable AstElement where
peek idx = do
- res <- Lua.tryLua $ (PandocElement <$> Lua.peek idx)
- <|> (InlineElement <$> Lua.peek idx)
- <|> (BlockElement <$> Lua.peek idx)
- <|> (MetaElement <$> Lua.peek idx)
- <|> (MetaValueElement <$> Lua.peek idx)
+ res <- Lua.try $ (PandocElement <$> Lua.peek idx)
+ <|> (InlineElement <$> Lua.peek idx)
+ <|> (BlockElement <$> Lua.peek idx)
+ <|> (MetaElement <$> Lua.peek idx)
+ <|> (MetaValueElement <$> Lua.peek idx)
case res of
Right x -> return x
- Left _ -> Lua.throwLuaError
+ Left _ -> Lua.throwException
"Expected an AST element, but could not parse value as such."
-- | Convert a number < 4000 to uppercase roman numeral.
-toRomanNumeral :: LuaInteger -> Lua String
+toRomanNumeral :: Lua.Integer -> Lua String
toRomanNumeral = return . Shared.toRomanNumeral . fromIntegral
diff --git a/src/Text/Pandoc/Lua/Packages.hs b/src/Text/Pandoc/Lua/Packages.hs
index 59637826e..5cf11f5c5 100644
--- a/src/Text/Pandoc/Lua/Packages.hs
+++ b/src/Text/Pandoc/Lua/Packages.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -16,8 +15,9 @@ 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
-}
-{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE ScopedTypeVariables #-}
{- |
Module : Text.Pandoc.Lua.Packages
Copyright : Copyright © 2017-2018 Albert Krewinkel
@@ -35,12 +35,11 @@ module Text.Pandoc.Lua.Packages
import Prelude
import Control.Monad (forM_)
-import Data.ByteString.Char8 (unpack)
+import Data.ByteString (ByteString)
import Data.IORef (IORef)
import Foreign.Lua (Lua, NumResults, liftIO)
import Text.Pandoc.Class (CommonState, readDataFile, runIO, setUserDataDir)
import Text.Pandoc.MediaBag (MediaBag)
-import Text.Pandoc.Lua.Util (dostring')
import qualified Foreign.Lua as Lua
import Text.Pandoc.Lua.Module.Pandoc as Pandoc
@@ -57,14 +56,10 @@ data LuaPackageParams = LuaPackageParams
-- | Insert pandoc's package loader as the first loader, making it the default.
installPandocPackageSearcher :: LuaPackageParams -> Lua ()
installPandocPackageSearcher luaPkgParams = do
- luaVersion <- Lua.getglobal "_VERSION" *> Lua.peek (-1)
- if luaVersion == "Lua 5.1"
- then Lua.getglobal' "package.loaders"
- else Lua.getglobal' "package.searchers"
+ Lua.getglobal' "package.searchers"
shiftArray
Lua.pushHaskellFunction (pandocPackageSearcher luaPkgParams)
- Lua.wrapHaskellFunction
- Lua.rawseti (-2) 1
+ Lua.rawseti (Lua.nthFromTop 2) 1
Lua.pop 1 -- remove 'package.searchers' from stack
where
shiftArray = forM_ [4, 3, 2, 1] $ \i -> do
@@ -86,7 +81,6 @@ pandocPackageSearcher luaPkgParams pkgName =
where
pushWrappedHsFun f = do
Lua.pushHaskellFunction f
- Lua.wrapHaskellFunction
return 1
searchPureLuaLoader = do
let filename = pkgName ++ ".lua"
@@ -97,21 +91,19 @@ pandocPackageSearcher luaPkgParams pkgName =
Lua.push ("no file '" ++ filename ++ "' in pandoc's datadir")
return 1
-loadStringAsPackage :: String -> String -> Lua NumResults
+loadStringAsPackage :: String -> ByteString -> Lua NumResults
loadStringAsPackage pkgName script = do
- status <- dostring' script
+ status <- Lua.dostring script
if status == Lua.OK
then return (1 :: NumResults)
else do
- msg <- Lua.peek (-1) <* Lua.pop 1
- Lua.push ("Error while loading ``" ++ pkgName ++ "`.\n" ++ msg)
- Lua.lerror
- return (2 :: NumResults)
+ msg <- Lua.popValue
+ Lua.raiseError ("Error while loading `" <> pkgName <> "`.\n" <> msg)
--- | Get the string representation of the pandoc module
-dataDirScript :: Maybe FilePath -> FilePath -> IO (Maybe String)
+-- | Get the ByteString representation of the pandoc module.
+dataDirScript :: Maybe FilePath -> FilePath -> IO (Maybe ByteString)
dataDirScript datadir moduleFile = do
res <- runIO $ setUserDataDir datadir >> readDataFile moduleFile
return $ case res of
Left _ -> Nothing
- Right s -> Just (unpack s)
+ Right s -> Just s
diff --git a/src/Text/Pandoc/Lua/StackInstances.hs b/src/Text/Pandoc/Lua/StackInstances.hs
index 3298079c5..931b8c225 100644
--- a/src/Text/Pandoc/Lua/StackInstances.hs
+++ b/src/Text/Pandoc/Lua/StackInstances.hs
@@ -1,4 +1,8 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE LambdaCase #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
{-
Copyright © 2012-2018 John MacFarlane <jgm@berkeley.edu>
2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -17,10 +21,6 @@ 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
-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
{- |
Module : Text.Pandoc.Lua.StackInstances
Copyright : © 2012-2018 John MacFarlane
@@ -37,148 +37,125 @@ module Text.Pandoc.Lua.StackInstances () where
import Prelude
import Control.Applicative ((<|>))
import Control.Monad (when)
-import Control.Monad.Catch (finally)
import Data.Data (showConstr, toConstr)
-import Data.Foldable (forM_)
-import Foreign.Lua (FromLuaStack (peek), Lua, LuaInteger, LuaNumber, StackIndex,
- ToLuaStack (push), Type (..), throwLuaError, tryLua)
+import Foreign.Lua (Lua, Peekable, Pushable, StackIndex)
import Text.Pandoc.Definition
import Text.Pandoc.Extensions (Extensions)
-import Text.Pandoc.Lua.Util (getTable, getTag, pushViaConstructor, typeCheck)
+import Text.Pandoc.Lua.Util (defineHowTo, pushViaConstructor)
import Text.Pandoc.Options (ReaderOptions (..), TrackChanges)
-import Text.Pandoc.Shared (Element (Blk, Sec), safeRead)
+import Text.Pandoc.Shared (Element (Blk, Sec))
-import qualified Foreign.Lua as Lua
import qualified Data.Set as Set
+import qualified Foreign.Lua as Lua
import qualified Text.Pandoc.Lua.Util as LuaUtil
-defineHowTo :: String -> Lua a -> Lua a
-defineHowTo ctx op = op `Lua.modifyLuaError` (("Could not " ++ ctx ++ ": ") ++)
-
-instance ToLuaStack Pandoc where
+instance Pushable Pandoc where
push (Pandoc meta blocks) =
pushViaConstructor "Pandoc" blocks meta
-instance FromLuaStack Pandoc where
+instance Peekable Pandoc where
peek idx = defineHowTo "get Pandoc value" $ do
- typeCheck idx Lua.TypeTable
- blocks <- getTable idx "blocks"
- meta <- Lua.getfield idx "meta" *> (Lua.peek Lua.stackTop `finally` Lua.pop 1)
+ blocks <- LuaUtil.rawField idx "blocks"
+ meta <- LuaUtil.rawField idx "meta"
return $ Pandoc meta blocks
-instance ToLuaStack Meta where
+instance Pushable Meta where
push (Meta mmap) =
pushViaConstructor "Meta" mmap
-instance FromLuaStack Meta where
- peek idx = defineHowTo "get Meta value" $ do
- typeCheck idx Lua.TypeTable
- Meta <$> peek idx
+instance Peekable Meta where
+ peek idx = defineHowTo "get Meta value" $
+ Meta <$> Lua.peek idx
-instance ToLuaStack MetaValue where
+instance Pushable MetaValue where
push = pushMetaValue
-instance FromLuaStack MetaValue where
+instance Peekable MetaValue where
peek = peekMetaValue
-instance ToLuaStack Block where
+instance Pushable Block where
push = pushBlock
-instance FromLuaStack Block where
+instance Peekable Block where
peek = peekBlock
-- Inline
-instance ToLuaStack Inline where
+instance Pushable Inline where
push = pushInline
-instance FromLuaStack Inline where
+instance Peekable Inline where
peek = peekInline
-- Citation
-instance ToLuaStack Citation where
+instance Pushable Citation where
push (Citation cid prefix suffix mode noteNum hash) =
pushViaConstructor "Citation" cid mode prefix suffix noteNum hash
-instance FromLuaStack Citation where
+instance Peekable Citation where
peek idx = do
- id' <- getTable idx "id"
- prefix <- getTable idx "prefix"
- suffix <- getTable idx "suffix"
- mode <- getTable idx "mode"
- num <- getTable idx "note_num"
- hash <- getTable idx "hash"
+ id' <- LuaUtil.rawField idx "id"
+ prefix <- LuaUtil.rawField idx "prefix"
+ suffix <- LuaUtil.rawField idx "suffix"
+ mode <- LuaUtil.rawField idx "mode"
+ num <- LuaUtil.rawField idx "note_num"
+ hash <- LuaUtil.rawField idx "hash"
return $ Citation id' prefix suffix mode num hash
-instance ToLuaStack Alignment where
- push = push . show
-instance FromLuaStack Alignment where
- peek idx = safeRead' =<< peek idx
-
-instance ToLuaStack CitationMode where
- push = push . show
-instance FromLuaStack CitationMode where
- peek idx = safeRead' =<< peek idx
-
-instance ToLuaStack Format where
- push (Format f) = push f
-instance FromLuaStack Format where
- peek idx = Format <$> peek idx
-
-instance ToLuaStack ListNumberDelim where
- push = push . show
-instance FromLuaStack ListNumberDelim where
- peek idx = safeRead' =<< peek idx
-
-instance ToLuaStack ListNumberStyle where
- push = push . show
-instance FromLuaStack ListNumberStyle where
- peek idx = safeRead' =<< peek idx
-
-instance ToLuaStack MathType where
- push = push . show
-instance FromLuaStack MathType where
- peek idx = safeRead' =<< peek idx
-
-instance ToLuaStack QuoteType where
- push = push . show
-instance FromLuaStack QuoteType where
- peek idx = safeRead' =<< peek idx
-
-instance ToLuaStack Double where
- push = push . (realToFrac :: Double -> LuaNumber)
-instance FromLuaStack Double where
- peek = fmap (realToFrac :: LuaNumber -> Double) . peek
-
-instance ToLuaStack Int where
- push = push . (fromIntegral :: Int -> LuaInteger)
-instance FromLuaStack Int where
- peek = fmap (fromIntegral :: LuaInteger-> Int) . peek
-
-safeRead' :: Read a => String -> Lua a
-safeRead' s = case safeRead s of
- Nothing -> throwLuaError ("Could not read: " ++ s)
- Just x -> return x
+instance Pushable Alignment where
+ push = Lua.push . show
+instance Peekable Alignment where
+ peek = Lua.peekRead
+
+instance Pushable CitationMode where
+ push = Lua.push . show
+instance Peekable CitationMode where
+ peek = Lua.peekRead
+
+instance Pushable Format where
+ push (Format f) = Lua.push f
+instance Peekable Format where
+ peek idx = Format <$> Lua.peek idx
+
+instance Pushable ListNumberDelim where
+ push = Lua.push . show
+instance Peekable ListNumberDelim where
+ peek = Lua.peekRead
+
+instance Pushable ListNumberStyle where
+ push = Lua.push . show
+instance Peekable ListNumberStyle where
+ peek = Lua.peekRead
+
+instance Pushable MathType where
+ push = Lua.push . show
+instance Peekable MathType where
+ peek = Lua.peekRead
+
+instance Pushable QuoteType where
+ push = Lua.push . show
+instance Peekable QuoteType where
+ peek = Lua.peekRead
-- | Push an meta value element to the top of the lua stack.
pushMetaValue :: MetaValue -> Lua ()
pushMetaValue = \case
MetaBlocks blcks -> pushViaConstructor "MetaBlocks" blcks
- MetaBool bool -> push bool
+ MetaBool bool -> Lua.push bool
MetaInlines inlns -> pushViaConstructor "MetaInlines" inlns
MetaList metalist -> pushViaConstructor "MetaList" metalist
MetaMap metamap -> pushViaConstructor "MetaMap" metamap
- MetaString str -> push str
+ MetaString str -> Lua.push str
-- | Interpret the value at the given stack index as meta value.
peekMetaValue :: StackIndex -> Lua MetaValue
peekMetaValue idx = defineHowTo "get MetaValue" $ do
-- Get the contents of an AST element.
- let elementContent :: FromLuaStack a => Lua a
- elementContent = peek idx
+ let elementContent :: Peekable a => Lua a
+ elementContent = Lua.peek idx
luatype <- Lua.ltype idx
case luatype of
- TypeBoolean -> MetaBool <$> peek idx
- TypeString -> MetaString <$> peek idx
- TypeTable -> do
- tag <- tryLua $ getTag idx
+ Lua.TypeBoolean -> MetaBool <$> Lua.peek idx
+ Lua.TypeString -> MetaString <$> Lua.peek idx
+ Lua.TypeTable -> do
+ tag <- Lua.try $ LuaUtil.getTag idx
case tag of
Right "MetaBlocks" -> MetaBlocks <$> elementContent
Right "MetaBool" -> MetaBool <$> elementContent
@@ -186,16 +163,16 @@ peekMetaValue idx = defineHowTo "get MetaValue" $ do
Right "MetaInlines" -> MetaInlines <$> elementContent
Right "MetaList" -> MetaList <$> elementContent
Right "MetaString" -> MetaString <$> elementContent
- Right t -> throwLuaError ("Unknown meta tag: " ++ t)
+ Right t -> Lua.throwException ("Unknown meta tag: " <> t)
Left _ -> do
-- no meta value tag given, try to guess.
len <- Lua.rawlen idx
if len <= 0
- then MetaMap <$> peek idx
- else (MetaInlines <$> peek idx)
- <|> (MetaBlocks <$> peek idx)
- <|> (MetaList <$> peek idx)
- _ -> throwLuaError "could not get meta value"
+ then MetaMap <$> Lua.peek idx
+ else (MetaInlines <$> Lua.peek idx)
+ <|> (MetaBlocks <$> Lua.peek idx)
+ <|> (MetaList <$> Lua.peek idx)
+ _ -> Lua.throwException "could not get meta value"
-- | Push an block element to the top of the lua stack.
pushBlock :: Block -> Lua ()
@@ -219,8 +196,7 @@ pushBlock = \case
-- | Return the value at the given index as block if possible.
peekBlock :: StackIndex -> Lua Block
peekBlock idx = defineHowTo "get Block value" $ do
- typeCheck idx Lua.TypeTable
- tag <- getTag idx
+ tag <- LuaUtil.getTag idx
case tag of
"BlockQuote" -> BlockQuote <$> elementContent
"BulletList" -> BulletList <$> elementContent
@@ -239,11 +215,11 @@ peekBlock idx = defineHowTo "get Block value" $ do
"Table" -> (\(capt, aligns, widths, headers, body) ->
Table capt aligns widths headers body)
<$> elementContent
- _ -> throwLuaError ("Unknown block type: " ++ tag)
+ _ -> Lua.throwException ("Unknown block type: " <> tag)
where
-- Get the contents of an AST element.
- elementContent :: FromLuaStack a => Lua a
- elementContent = getTable idx "c"
+ elementContent :: Peekable a => Lua a
+ elementContent = LuaUtil.rawField idx "c"
-- | Push an inline element to the top of the lua stack.
pushInline :: Inline -> Lua ()
@@ -271,8 +247,7 @@ pushInline = \case
-- | Return the value at the given index as inline if possible.
peekInline :: StackIndex -> Lua Inline
peekInline idx = defineHowTo "get Inline value" $ do
- typeCheck idx Lua.TypeTable
- tag <- getTag idx
+ tag <- LuaUtil.getTag idx
case tag of
"Cite" -> uncurry Cite <$> elementContent
"Code" -> withAttr Code <$> elementContent
@@ -295,11 +270,11 @@ peekInline idx = defineHowTo "get Inline value" $ do
"Strong" -> Strong <$> elementContent
"Subscript" -> Subscript <$> elementContent
"Superscript"-> Superscript <$> elementContent
- _ -> throwLuaError ("Unknown inline type: " ++ tag)
+ _ -> Lua.throwException ("Unknown inline type: " <> tag)
where
-- Get the contents of an AST element.
- elementContent :: FromLuaStack a => Lua a
- elementContent = getTable idx "c"
+ elementContent :: Peekable a => Lua a
+ elementContent = LuaUtil.rawField idx "c"
withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
withAttr f (attributes, x) = f (fromLuaAttr attributes) x
@@ -307,25 +282,25 @@ withAttr f (attributes, x) = f (fromLuaAttr attributes) x
-- | Wrapper for Attr
newtype LuaAttr = LuaAttr { fromLuaAttr :: Attr }
-instance ToLuaStack LuaAttr where
+instance Pushable LuaAttr where
push (LuaAttr (id', classes, kv)) =
pushViaConstructor "Attr" id' classes kv
-instance FromLuaStack LuaAttr where
- peek idx = defineHowTo "get Attr value" (LuaAttr <$> peek idx)
+instance Peekable LuaAttr where
+ peek idx = defineHowTo "get Attr value" (LuaAttr <$> Lua.peek idx)
--
-- Hierarchical elements
--
-instance ToLuaStack Element where
- push (Blk blk) = push blk
+instance Pushable Element where
+ push (Blk blk) = Lua.push blk
push (Sec lvl num attr label contents) = do
Lua.newtable
- LuaUtil.addValue "level" lvl
- LuaUtil.addValue "numbering" num
- LuaUtil.addValue "attr" (LuaAttr attr)
- LuaUtil.addValue "label" label
- LuaUtil.addValue "contents" contents
+ LuaUtil.addField "level" lvl
+ LuaUtil.addField "numbering" num
+ LuaUtil.addField "attr" (LuaAttr attr)
+ LuaUtil.addField "label" label
+ LuaUtil.addField "contents" contents
pushSecMetaTable
Lua.setmetatable (-2)
where
@@ -333,7 +308,7 @@ instance ToLuaStack Element where
pushSecMetaTable = do
inexistant <- Lua.newmetatable "PandocElementSec"
when inexistant $ do
- LuaUtil.addValue "t" "Sec"
+ LuaUtil.addField "t" "Sec"
Lua.push "__index"
Lua.pushvalue (-2)
Lua.rawset (-3)
@@ -342,18 +317,13 @@ instance ToLuaStack Element where
--
-- Reader Options
--
-instance ToLuaStack Extensions where
- push exts = push (show exts)
-
-instance ToLuaStack TrackChanges where
- push = push . showConstr . toConstr
+instance Pushable Extensions where
+ push exts = Lua.push (show exts)
-instance ToLuaStack a => ToLuaStack (Set.Set a) where
- push set = do
- Lua.newtable
- forM_ set (`LuaUtil.addValue` True)
+instance Pushable TrackChanges where
+ push = Lua.push . showConstr . toConstr
-instance ToLuaStack ReaderOptions where
+instance Pushable ReaderOptions where
push ro = do
let ReaderOptions
(extensions :: Extensions)
@@ -367,12 +337,12 @@ instance ToLuaStack ReaderOptions where
(stripComments :: Bool)
= ro
Lua.newtable
- LuaUtil.addValue "extensions" extensions
- LuaUtil.addValue "standalone" standalone
- LuaUtil.addValue "columns" columns
- LuaUtil.addValue "tabStop" tabStop
- LuaUtil.addValue "indentedCodeClasses" indentedCodeClasses
- LuaUtil.addValue "abbreviations" abbreviations
- LuaUtil.addValue "defaultImageExtension" defaultImageExtension
- LuaUtil.addValue "trackChanges" trackChanges
- LuaUtil.addValue "stripComments" stripComments
+ LuaUtil.addField "extensions" extensions
+ LuaUtil.addField "standalone" standalone
+ LuaUtil.addField "columns" columns
+ LuaUtil.addField "tabStop" tabStop
+ LuaUtil.addField "indentedCodeClasses" indentedCodeClasses
+ LuaUtil.addField "abbreviations" abbreviations
+ LuaUtil.addField "defaultImageExtension" defaultImageExtension
+ LuaUtil.addField "trackChanges" trackChanges
+ LuaUtil.addField "stripComments" stripComments
diff --git a/src/Text/Pandoc/Lua/Util.hs b/src/Text/Pandoc/Lua/Util.hs
index ea9ec2554..77b27b88e 100644
--- a/src/Text/Pandoc/Lua/Util.hs
+++ b/src/Text/Pandoc/Lua/Util.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright © 2012-2018 John MacFarlane <jgm@berkeley.edu>
2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -18,6 +17,8 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- |
Module : Text.Pandoc.Lua.Util
Copyright : © 2012–2018 John MacFarlane,
@@ -31,101 +32,53 @@ Lua utility functions.
-}
module Text.Pandoc.Lua.Util
( getTag
- , getTable
- , addValue
+ , rawField
+ , addField
, addFunction
- , getRawInt
- , setRawInt
- , addRawInt
- , typeCheck
- , raiseError
- , popValue
- , PushViaCall
- , pushViaCall
+ , addValue
, pushViaConstructor
, loadScriptFromDataDir
- , dostring'
+ , defineHowTo
+ , throwTopMessageAsError'
+ , callWithTraceback
+ , dofileWithTraceback
) where
import Prelude
-import Control.Monad (when)
-import Control.Monad.Catch (finally)
-import Data.ByteString.Char8 (unpack)
-import Foreign.Lua (FromLuaStack (..), NumResults, Lua, NumArgs, StackIndex,
- ToLuaStack (..), ToHaskellFunction)
-import Foreign.Lua.Api (Status, call, pop, rawget, rawgeti, rawset, rawseti)
+import Control.Monad (unless, when)
+import Foreign.Lua ( Lua, NumArgs, NumResults, Peekable, Pushable, StackIndex
+ , Status, ToHaskellFunction )
import Text.Pandoc.Class (readDataFile, runIOorExplode, setUserDataDir)
import qualified Foreign.Lua as Lua
-
--- | Adjust the stack index, assuming that @n@ new elements have been pushed on
--- the stack.
-adjustIndexBy :: StackIndex -> StackIndex -> StackIndex
-adjustIndexBy idx n =
- if idx < 0
- then idx - n
- else idx
+import qualified Text.Pandoc.UTF8 as UTF8
-- | Get value behind key from table at given index.
-getTable :: (ToLuaStack a, FromLuaStack b) => StackIndex -> a -> Lua b
-getTable idx key = do
- push key
- rawget (idx `adjustIndexBy` 1)
- popValue
+rawField :: Peekable a => StackIndex -> String -> Lua a
+rawField idx key = do
+ absidx <- Lua.absindex idx
+ Lua.push key
+ Lua.rawget absidx
+ Lua.popValue
+
+-- | Add a value to the table at the top of the stack at a string-index.
+addField :: Pushable a => String -> a -> Lua ()
+addField = addValue
-- | Add a key-value pair to the table at the top of the stack.
-addValue :: (ToLuaStack a, ToLuaStack b) => a -> b -> Lua ()
+addValue :: (Pushable a, Pushable b) => a -> b -> Lua ()
addValue key value = do
- push key
- push value
- rawset (-3)
+ Lua.push key
+ Lua.push value
+ Lua.rawset (Lua.nthFromTop 3)
-- | Add a function to the table at the top of the stack, using the given name.
addFunction :: ToHaskellFunction a => String -> a -> Lua ()
addFunction name fn = do
Lua.push name
Lua.pushHaskellFunction fn
- Lua.wrapHaskellFunction
Lua.rawset (-3)
--- | Get value behind key from table at given index.
-getRawInt :: FromLuaStack a => StackIndex -> Int -> Lua a
-getRawInt idx key = do
- rawgeti idx key
- popValue
-
--- | Set numeric key/value in table at the given index
-setRawInt :: ToLuaStack a => StackIndex -> Int -> a -> Lua ()
-setRawInt idx key value = do
- push value
- rawseti (idx `adjustIndexBy` 1) key
-
--- | Set numeric key/value in table at the top of the stack.
-addRawInt :: ToLuaStack a => Int -> a -> Lua ()
-addRawInt = setRawInt (-1)
-
-typeCheck :: StackIndex -> Lua.Type -> Lua ()
-typeCheck idx expected = do
- actual <- Lua.ltype idx
- when (actual /= expected) $ do
- expName <- Lua.typename expected
- actName <- Lua.typename actual
- Lua.throwLuaError $ "expected " ++ expName ++ " but got " ++ actName ++ "."
-
-raiseError :: ToLuaStack a => a -> Lua NumResults
-raiseError e = do
- Lua.push e
- fromIntegral <$> Lua.lerror
-
--- | Get, then pop the value at the top of the stack.
-popValue :: FromLuaStack a => Lua a
-popValue = do
- resOrError <- Lua.peekEither (-1)
- pop 1
- case resOrError of
- Left err -> Lua.throwLuaError err
- Right x -> return x
-
-- | Helper class for pushing a single value to the stack via a lua function.
-- See @pushViaCall@.
class PushViaCall a where
@@ -136,11 +89,11 @@ instance PushViaCall (Lua ()) where
Lua.push fn
Lua.rawget Lua.registryindex
pushArgs
- call num 1
+ Lua.call num 1
-instance (ToLuaStack a, PushViaCall b) => PushViaCall (a -> b) where
+instance (Pushable a, PushViaCall b) => PushViaCall (a -> b) where
pushViaCall' fn pushArgs num x =
- pushViaCall' fn (pushArgs *> push x) (num + 1)
+ pushViaCall' fn (pushArgs *> Lua.push x) (num + 1)
-- | Push an value to the stack via a lua function. The lua function is called
-- with all arguments that are passed to this function and is expected to return
@@ -155,26 +108,11 @@ pushViaConstructor pandocFn = pushViaCall ("pandoc." ++ pandocFn)
-- | Load a file from pandoc's data directory.
loadScriptFromDataDir :: Maybe FilePath -> FilePath -> Lua ()
loadScriptFromDataDir datadir scriptFile = do
- script <- fmap unpack . Lua.liftIO . runIOorExplode $
+ script <- Lua.liftIO . runIOorExplode $
setUserDataDir datadir >> readDataFile scriptFile
- status <- dostring' script
- when (status /= Lua.OK) .
- Lua.throwTopMessageAsError' $ \msg ->
- "Couldn't load '" ++ scriptFile ++ "'.\n" ++ msg
-
--- | Load a string and immediately perform a full garbage collection. This is
--- important to keep the program from hanging: If the program contained a call
--- to @require@, the a new loader function was created which then become
--- garbage. If that function is collected at an inopportune times, i.e. when the
--- Lua API is called via a function that doesn't allow calling back into Haskell
--- (getraw, setraw, …), then the function's finalizer, and the full program,
--- will hang.
-dostring' :: String -> Lua Status
-dostring' script = do
- loadRes <- Lua.loadstring script
- if loadRes == Lua.OK
- then Lua.pcall 0 1 Nothing <* Lua.gc Lua.GCCOLLECT 0
- else return loadRes
+ status <- Lua.dostring script
+ when (status /= Lua.OK) $
+ throwTopMessageAsError' (("Couldn't load '" ++ scriptFile ++ "'.\n") ++)
-- | Get the tag of a value. This is an optimized and specialized version of
-- @Lua.getfield idx "tag"@. It only checks for the field on the table at index
@@ -182,8 +120,54 @@ dostring' script = do
-- metatable.
getTag :: StackIndex -> Lua String
getTag idx = do
- top <- Lua.gettop
- hasMT <- Lua.getmetatable idx
- push "tag"
- if hasMT then Lua.rawget (-2) else Lua.rawget (idx `adjustIndexBy` 1)
- peek Lua.stackTop `finally` Lua.settop top
+ -- push metatable or just the table
+ Lua.getmetatable idx >>= \hasMT -> unless hasMT (Lua.pushvalue idx)
+ Lua.push "tag"
+ Lua.rawget (Lua.nthFromTop 2)
+ Lua.tostring Lua.stackTop <* Lua.pop 2 >>= \case
+ Nothing -> Lua.throwException "untagged value"
+ Just x -> return (UTF8.toString x)
+
+-- | Modify the message at the top of the stack before throwing it as an
+-- Exception.
+throwTopMessageAsError' :: (String -> String) -> Lua a
+throwTopMessageAsError' modifier = do
+ msg <- Lua.tostring' Lua.stackTop
+ Lua.pop 2 -- remove error and error string pushed by tostring'
+ Lua.throwException (modifier (UTF8.toString msg))
+
+-- | Mark the context of a Lua computation for better error reporting.
+defineHowTo :: String -> Lua a -> Lua a
+defineHowTo ctx = Lua.withExceptionMessage (("Could not " <> ctx <> ": ") <>)
+
+-- | Like @'Lua.pcall'@, but uses a predefined error handler which adds a
+-- traceback on error.
+pcallWithTraceback :: NumArgs -> NumResults -> Lua Status
+pcallWithTraceback nargs nresults = do
+ let traceback' :: Lua NumResults
+ traceback' = do
+ l <- Lua.state
+ msg <- Lua.tostring' (Lua.nthFromBottom 1)
+ Lua.traceback l (Just (UTF8.toString msg)) 2
+ return 1
+ tracebackIdx <- Lua.absindex (Lua.nthFromTop (Lua.fromNumArgs nargs + 1))
+ Lua.pushHaskellFunction traceback'
+ Lua.insert tracebackIdx
+ result <- Lua.pcall nargs nresults (Just tracebackIdx)
+ Lua.remove tracebackIdx
+ return result
+
+-- | Like @'Lua.call'@, but adds a traceback to the error message (if any).
+callWithTraceback :: NumArgs -> NumResults -> Lua ()
+callWithTraceback nargs nresults = do
+ result <- pcallWithTraceback nargs nresults
+ when (result /= Lua.OK) Lua.throwTopMessage
+
+-- | Run the given string as a Lua program, while also adding a traceback to the
+-- error message if an error occurs.
+dofileWithTraceback :: FilePath -> Lua Status
+dofileWithTraceback fp = do
+ loadRes <- Lua.loadfile fp
+ case loadRes of
+ Lua.OK -> pcallWithTraceback 0 Lua.multret
+ _ -> return loadRes
diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs
index e5ca1764c..204060d70 100644
--- a/src/Text/Pandoc/Options.hs
+++ b/src/Text/Pandoc/Options.hs
@@ -194,6 +194,7 @@ data WriterOptions = WriterOptions
, writerReferenceDoc :: Maybe FilePath -- ^ Path to reference document if specified
, writerReferenceLocation :: ReferenceLocation -- ^ Location of footnotes and references for writing markdown
, writerSyntaxMap :: SyntaxMap
+ , writerPreferAscii :: Bool -- ^ Prefer ASCII representations of characters when possible
} deriving (Show, Data, Typeable, Generic)
instance Default WriterOptions where
@@ -228,6 +229,7 @@ instance Default WriterOptions where
, writerReferenceDoc = Nothing
, writerReferenceLocation = EndOfDocument
, writerSyntaxMap = defaultSyntaxMap
+ , writerPreferAscii = False
}
instance HasSyntaxExtensions WriterOptions where
diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs
index b171d65b0..3484699c0 100644
--- a/src/Text/Pandoc/PDF.hs
+++ b/src/Text/Pandoc/PDF.hs
@@ -79,13 +79,52 @@ changePathSeparators = intercalate "/" . splitDirectories
#endif
makePDF :: String -- ^ pdf creator (pdflatex, lualatex, xelatex,
- -- wkhtmltopdf, weasyprint, prince, context, pdfroff)
+ -- wkhtmltopdf, weasyprint, prince, context, pdfroff,
+ -- or path to executable)
-> [String] -- ^ arguments to pass to pdf creator
-> (WriterOptions -> Pandoc -> PandocIO Text) -- ^ writer
-> WriterOptions -- ^ options
-> Pandoc -- ^ document
-> PandocIO (Either ByteString ByteString)
-makePDF "wkhtmltopdf" pdfargs writer opts doc@(Pandoc meta _) = do
+makePDF program pdfargs writer opts doc = do
+ case takeBaseName program of
+ "wkhtmltopdf" -> makeWithWkhtmltopdf program pdfargs writer opts doc
+ prog | prog `elem` ["weasyprint", "prince"] -> do
+ source <- writer opts doc
+ verbosity <- getVerbosity
+ liftIO $ html2pdf verbosity program pdfargs source
+ "pdfroff" -> do
+ source <- writer opts doc
+ let args = ["-ms", "-mpdfmark", "-e", "-t", "-k", "-KUTF-8", "-i",
+ "--no-toc-relocation"] ++ pdfargs
+ verbosity <- getVerbosity
+ liftIO $ ms2pdf verbosity program args source
+ baseProg -> do
+ -- With context and latex, we create a temp directory within
+ -- the working directory, since pdflatex sometimes tries to
+ -- use tools like epstopdf.pl, which are restricted if run
+ -- on files outside the working directory.
+ let withTemp = withTempDirectory "."
+ commonState <- getCommonState
+ verbosity <- getVerbosity
+ liftIO $ withTemp "tex2pdf." $ \tmpdir -> do
+ source <- runIOorExplode $ do
+ putCommonState commonState
+ doc' <- handleImages tmpdir doc
+ writer opts doc'
+ case baseProg of
+ "context" -> context2pdf verbosity program tmpdir source
+ prog | prog `elem` ["pdflatex", "lualatex", "xelatex"]
+ -> tex2pdf verbosity program pdfargs tmpdir source
+ _ -> return $ Left $ UTF8.fromStringLazy $ "Unknown program " ++ program
+
+makeWithWkhtmltopdf :: String -- ^ wkhtmltopdf or path
+ -> [String] -- ^ arguments
+ -> (WriterOptions -> Pandoc -> PandocIO Text) -- ^ writer
+ -> WriterOptions -- ^ options
+ -> Pandoc -- ^ document
+ -> PandocIO (Either ByteString ByteString)
+makeWithWkhtmltopdf program pdfargs writer opts doc@(Pandoc meta _) = do
let mathArgs = case writerHTMLMathMethod opts of
-- with MathJax, wait til all math is rendered:
MathJax _ -> ["--run-script", "MathJax.Hub.Register.StartupHook('End Typeset', function() { window.status = 'mathjax_loaded' });",
@@ -111,39 +150,7 @@ makePDF "wkhtmltopdf" pdfargs writer opts doc@(Pandoc meta _) = do
]
source <- writer opts doc
verbosity <- getVerbosity
- liftIO $ html2pdf verbosity "wkhtmltopdf" args source
-makePDF "weasyprint" pdfargs writer opts doc = do
- source <- writer opts doc
- verbosity <- getVerbosity
- liftIO $ html2pdf verbosity "weasyprint" pdfargs source
-makePDF "prince" pdfargs writer opts doc = do
- source <- writer opts doc
- verbosity <- getVerbosity
- liftIO $ html2pdf verbosity "prince" pdfargs source
-makePDF "pdfroff" pdfargs writer opts doc = do
- source <- writer opts doc
- let args = ["-ms", "-mpdfmark", "-e", "-t", "-k", "-KUTF-8", "-i",
- "--no-toc-relocation"] ++ pdfargs
- verbosity <- getVerbosity
- liftIO $ ms2pdf verbosity args source
-makePDF program pdfargs writer opts doc = do
- -- With context and latex, we create a temp directory within
- -- the working directory, since pdflatex sometimes tries to
- -- use tools like epstopdf.pl, which are restricted if run
- -- on files outside the working directory.
- let withTemp = withTempDirectory "."
- commonState <- getCommonState
- verbosity <- getVerbosity
- liftIO $ withTemp "tex2pdf." $ \tmpdir -> do
- source <- runIOorExplode $ do
- putCommonState commonState
- doc' <- handleImages tmpdir doc
- writer opts doc'
- case takeBaseName program of
- "context" -> context2pdf verbosity tmpdir source
- prog | prog `elem` ["pdflatex", "lualatex", "xelatex"]
- -> tex2pdf' verbosity pdfargs tmpdir program source
- _ -> return $ Left $ UTF8.fromStringLazy $ "Unknown program " ++ program
+ liftIO $ html2pdf verbosity program args source
handleImages :: FilePath -- ^ temp dir to store images
-> Pandoc -- ^ document
@@ -181,7 +188,7 @@ convertImage tmpdir fname =
then return $ Right pdfOut
else return $ Left "conversion from SVG failed")
(\(e :: E.SomeException) -> return $ Left $
- "check that rsvg2pdf is in path.\n" ++
+ "check that rsvg-convert is in path.\n" ++
show e)
_ -> JP.readImage fname >>= \res ->
case res of
@@ -195,13 +202,13 @@ convertImage tmpdir fname =
mime = getMimeType fname
doNothing = return (Right fname)
-tex2pdf' :: Verbosity -- ^ Verbosity level
- -> [String] -- ^ Arguments to the latex-engine
- -> FilePath -- ^ temp directory for output
- -> String -- ^ tex program
- -> Text -- ^ tex source
- -> IO (Either ByteString ByteString)
-tex2pdf' verbosity args tmpDir program source = do
+tex2pdf :: Verbosity -- ^ Verbosity level
+ -> String -- ^ tex program
+ -> [String] -- ^ Arguments to the latex-engine
+ -> FilePath -- ^ temp directory for output
+ -> Text -- ^ tex source
+ -> IO (Either ByteString ByteString)
+tex2pdf verbosity program args tmpDir source = do
let numruns = if "\\tableofcontents" `T.isInfixOf` source
then 3 -- to get page numbers
else 2 -- 1 run won't give you PDF bookmarks
@@ -278,12 +285,7 @@ runTeXProgram verbosity program args runNumber numRuns tmpDir source = do
let file' = file
#endif
let programArgs = ["-halt-on-error", "-interaction", "nonstopmode",
- "-output-directory", tmpDir'] ++
- -- see #4484, only compress images on last run:
- if program == "xelatex" && runNumber < numRuns
- then ["-output-driver", "xdvipdfmx -z0"]
- else []
- ++ args ++ [file']
+ "-output-directory", tmpDir'] ++ args ++ [file']
env' <- getEnvironment
let sep = [searchPathSeparator]
let texinputs = maybe (tmpDir' ++ sep) ((tmpDir' ++ sep) ++)
@@ -307,7 +309,7 @@ runTeXProgram verbosity program args runNumber numRuns tmpDir source = do
putStrLn $ "[makePDF] Run #" ++ show runNumber
BL.hPutStr stdout out
putStr "\n"
- if runNumber <= numRuns
+ if runNumber < numRuns
then runTeXProgram verbosity program args (runNumber + 1) numRuns tmpDir source
else do
let pdfFile = replaceDirectory (replaceExtension file ".pdf") tmpDir
@@ -328,14 +330,15 @@ runTeXProgram verbosity program args runNumber numRuns tmpDir source = do
return (exit, log', pdf)
ms2pdf :: Verbosity
+ -> String
-> [String]
-> Text
-> IO (Either ByteString ByteString)
-ms2pdf verbosity args source = do
+ms2pdf verbosity program args source = do
env' <- getEnvironment
when (verbosity >= INFO) $ do
putStrLn "[makePDF] Command line:"
- putStrLn $ "pdfroff " ++ " " ++ unwords (map show args)
+ putStrLn $ program ++ " " ++ unwords (map show args)
putStr "\n"
putStrLn "[makePDF] Environment:"
mapM_ print env'
@@ -344,11 +347,11 @@ ms2pdf verbosity args source = do
putStr $ T.unpack source
putStr "\n"
(exit, out) <- E.catch
- (pipeProcess (Just env') "pdfroff" args
+ (pipeProcess (Just env') program args
(BL.fromStrict $ UTF8.fromText source))
(\(e :: IOError) -> if isDoesNotExistError e
then E.throwIO $
- PandocPDFProgramNotFoundError "pdfroff"
+ PandocPDFProgramNotFoundError program
else E.throwIO e)
when (verbosity >= INFO) $ do
BL.hPutStr stdout out
@@ -358,7 +361,7 @@ ms2pdf verbosity args source = do
ExitSuccess -> Right out
html2pdf :: Verbosity -- ^ Verbosity level
- -> String -- ^ Program (wkhtmltopdf, weasyprint or prince)
+ -> String -- ^ Program (wkhtmltopdf, weasyprint, prince, or path)
-> [String] -- ^ Args to program
-> Text -- ^ HTML5 source
-> IO (Either ByteString ByteString)
@@ -369,7 +372,7 @@ html2pdf verbosity program args source = do
file <- withTempFile "." "html2pdf.html" $ \fp _ -> return fp
pdfFile <- withTempFile "." "html2pdf.pdf" $ \fp _ -> return fp
BS.writeFile file $ UTF8.fromText source
- let pdfFileArgName = ["-o" | program == "prince"]
+ let pdfFileArgName = ["-o" | takeBaseName program == "prince"]
let programArgs = args ++ [file] ++ pdfFileArgName ++ [pdfFile]
env' <- getEnvironment
when (verbosity >= INFO) $ do
@@ -408,10 +411,11 @@ html2pdf verbosity program args source = do
(ExitSuccess, Just pdf) -> Right pdf
context2pdf :: Verbosity -- ^ Verbosity level
+ -> String -- ^ "context" or path to it
-> FilePath -- ^ temp directory for output
-> Text -- ^ ConTeXt source
-> IO (Either ByteString ByteString)
-context2pdf verbosity tmpDir source = inDirectory tmpDir $ do
+context2pdf verbosity program tmpDir source = inDirectory tmpDir $ do
let file = "input.tex"
BS.writeFile file $ UTF8.fromText source
#ifdef _WINDOWS
@@ -426,7 +430,7 @@ context2pdf verbosity tmpDir source = inDirectory tmpDir $ do
putStrLn "[makePDF] temp dir:"
putStrLn tmpDir'
putStrLn "[makePDF] Command line:"
- putStrLn $ "context" ++ " " ++ unwords (map show programArgs)
+ putStrLn $ program ++ " " ++ unwords (map show programArgs)
putStr "\n"
putStrLn "[makePDF] Environment:"
mapM_ print env'
@@ -435,7 +439,7 @@ context2pdf verbosity tmpDir source = inDirectory tmpDir $ do
BL.readFile file >>= BL.putStr
putStr "\n"
(exit, out) <- E.catch
- (pipeProcess (Just env') "context" programArgs BL.empty)
+ (pipeProcess (Just env') program programArgs BL.empty)
(\(e :: IOError) -> if isDoesNotExistError e
then E.throwIO $
PandocPDFProgramNotFoundError "context"
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
index 05f4f7d36..5d95d0e27 100644
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -514,22 +514,19 @@ charsInBalanced open close parser = try $ do
-- Auxiliary functions for romanNumeral:
-lowercaseRomanDigits :: [Char]
-lowercaseRomanDigits = ['i','v','x','l','c','d','m']
-
-uppercaseRomanDigits :: [Char]
-uppercaseRomanDigits = map toUpper lowercaseRomanDigits
-
-- | Parses a roman numeral (uppercase or lowercase), returns number.
romanNumeral :: Stream s m Char => Bool -- ^ Uppercase if true
-> ParserT s st m Int
romanNumeral upperCase = do
- let romanDigits = if upperCase
- then uppercaseRomanDigits
- else lowercaseRomanDigits
- lookAhead $ oneOf romanDigits
- let [one, five, ten, fifty, hundred, fivehundred, thousand] =
- map char romanDigits
+ let rchar uc = char $ if upperCase then uc else toLower uc
+ let one = rchar 'I'
+ let five = rchar 'V'
+ let ten = rchar 'X'
+ let fifty = rchar 'L'
+ let hundred = rchar 'C'
+ let fivehundred = rchar 'D'
+ let thousand = rchar 'M'
+ lookAhead $ choice [one, five, ten, fifty, hundred, fivehundred, thousand]
thousands <- ((1000 *) . length) <$> many thousand
ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900
fivehundreds <- option 0 $ 500 <$ fivehundred
@@ -1289,7 +1286,7 @@ type SubstTable = M.Map Key Inlines
-- unique identifier, and update the list of identifiers
-- in state. Issue a warning if an explicit identifier
-- is encountered that duplicates an earlier identifier
--- (explict or automatically generated).
+-- (explicit or automatically generated).
registerHeader :: (Stream s m a, HasReaderOptions st,
HasHeaderMap st, HasLogMessages st, HasIdentifierList st)
=> Attr -> Inlines -> ParserT s st m Attr
diff --git a/src/Text/Pandoc/Readers/CommonMark.hs b/src/Text/Pandoc/Readers/CommonMark.hs
index 79a4abbc2..9c4f7a8ac 100644
--- a/src/Text/Pandoc/Readers/CommonMark.hs
+++ b/src/Text/Pandoc/Readers/CommonMark.hs
@@ -39,10 +39,12 @@ import Control.Monad.State
import Data.Char (isAlphaNum, isLetter, isSpace, toLower)
import Data.List (groupBy)
import qualified Data.Map as Map
+import Data.Maybe (mapMaybe)
import Data.Text (Text, unpack)
+import Text.Pandoc.Asciify (toAsciiChar)
import Text.Pandoc.Class (PandocMonad)
import Text.Pandoc.Definition
-import Text.Pandoc.Emoji (emojis)
+import Text.Pandoc.Emoji (emojiToInline)
import Text.Pandoc.Options
import Text.Pandoc.Shared (stringify)
import Text.Pandoc.Walk (walkM)
@@ -51,7 +53,7 @@ import Text.Pandoc.Walk (walkM)
readCommonMark :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
readCommonMark opts s = return $
(if isEnabled Ext_gfm_auto_identifiers opts
- then addHeaderIdentifiers
+ then addHeaderIdentifiers opts
else id) $
nodeToPandoc opts $ commonmarkToNode opts' exts s
where opts' = [ optSmart | isEnabled Ext_smart opts ]
@@ -59,24 +61,27 @@ readCommonMark opts s = return $
[ extTable | isEnabled Ext_pipe_tables opts ] ++
[ extAutolink | isEnabled Ext_autolink_bare_uris opts ]
-convertEmojis :: String -> String
-convertEmojis (':':xs) =
+convertEmojis :: String -> [Inline]
+convertEmojis s@(':':xs) =
case break (==':') xs of
(ys,':':zs) ->
- case Map.lookup ys emojis of
- Just s -> s ++ convertEmojis zs
- Nothing -> ':' : ys ++ convertEmojis (':':zs)
- _ -> ':':xs
-convertEmojis (x:xs) = x : convertEmojis xs
-convertEmojis [] = []
-
-addHeaderIdentifiers :: Pandoc -> Pandoc
-addHeaderIdentifiers doc = evalState (walkM addHeaderId doc) mempty
-
-addHeaderId :: Block -> State (Map.Map String Int) Block
-addHeaderId (Header lev (_,classes,kvs) ils) = do
+ case emojiToInline ys of
+ Just em -> em : convertEmojis zs
+ Nothing -> Str (':' : ys) : convertEmojis (':':zs)
+ _ -> [Str s]
+convertEmojis s =
+ case break (==':') s of
+ ("","") -> []
+ (_,"") -> [Str s]
+ (xs,ys) -> Str xs:convertEmojis ys
+
+addHeaderIdentifiers :: ReaderOptions -> Pandoc -> Pandoc
+addHeaderIdentifiers opts doc = evalState (walkM (addHeaderId opts) doc) mempty
+
+addHeaderId :: ReaderOptions -> Block -> State (Map.Map String Int) Block
+addHeaderId opts (Header lev (_,classes,kvs) ils) = do
idmap <- get
- let ident = toIdent ils
+ let ident = toIdent opts ils
ident' <- case Map.lookup ident idmap of
Nothing -> do
put (Map.insert ident 1 idmap)
@@ -85,13 +90,16 @@ addHeaderId (Header lev (_,classes,kvs) ils) = do
put (Map.adjust (+ 1) ident idmap)
return (ident ++ "-" ++ show i)
return $ Header lev (ident',classes,kvs) ils
-addHeaderId x = return x
+addHeaderId _ x = return x
-toIdent :: [Inline] -> String
-toIdent = map (\c -> if isSpace c then '-' else c)
- . filter (\c -> isLetter c || isAlphaNum c || isSpace c ||
- c == '_' || c == '-')
- . map toLower . stringify
+toIdent :: ReaderOptions -> [Inline] -> String
+toIdent opts = map (\c -> if isSpace c then '-' else c)
+ . filterer
+ . map toLower . stringify
+ where filterer = if isEnabled Ext_ascii_identifiers opts
+ then mapMaybe toAsciiChar
+ else filter (\c -> isLetter c || isAlphaNum c || isSpace c ||
+ c == '_' || c == '-')
nodeToPandoc :: ReaderOptions -> Node -> Pandoc
nodeToPandoc opts (Node _ DOCUMENT nodes) =
@@ -200,17 +208,17 @@ addInlines :: ReaderOptions -> [Node] -> [Inline]
addInlines opts = foldr (addInline opts) []
addInline :: ReaderOptions -> Node -> [Inline] -> [Inline]
-addInline opts (Node _ (TEXT t) _) = (map toinl clumps ++)
+addInline opts (Node _ (TEXT t) _) = (foldr ((++) . toinl) [] clumps ++)
where raw = unpack t
clumps = groupBy samekind raw
samekind ' ' ' ' = True
samekind ' ' _ = False
samekind _ ' ' = False
samekind _ _ = True
- toinl (' ':_) = Space
- toinl xs = Str $ if isEnabled Ext_emoji opts
- then convertEmojis xs
- else xs
+ toinl (' ':_) = [Space]
+ toinl xs = if isEnabled Ext_emoji opts
+ then convertEmojis xs
+ else [Str xs]
addInline _ (Node _ LINEBREAK _) = (LineBreak :)
addInline opts (Node _ SOFTBREAK _)
| isEnabled Ext_hard_line_breaks opts = (LineBreak :)
diff --git a/src/Text/Pandoc/Readers/Creole.hs b/src/Text/Pandoc/Readers/Creole.hs
index 4fd38c0fd..a337bf937 100644
--- a/src/Text/Pandoc/Readers/Creole.hs
+++ b/src/Text/Pandoc/Readers/Creole.hs
@@ -2,7 +2,7 @@
{-
Copyright (C) 2017 Sascha Wilde <wilde@sha-bang.de>
- partly based on all the other readers, especialy the work by
+ partly based on all the other readers, especially the work by
John MacFarlane <jgm@berkeley.edu> and
Alexander Sulfrian <alexander.sulfrian@fu-berlin.de>
all bugs are solely created by me.
diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs
index 3d48c7ee8..b7bd71754 100644
--- a/src/Text/Pandoc/Readers/DocBook.hs
+++ b/src/Text/Pandoc/Readers/DocBook.hs
@@ -537,7 +537,6 @@ type DB m = StateT DBState m
data DBState = DBState{ dbSectionLevel :: Int
, dbQuoteType :: QuoteType
, dbMeta :: Meta
- , dbAcceptsMeta :: Bool
, dbBook :: Bool
, dbFigureTitle :: Inlines
, dbContent :: [Content]
@@ -547,7 +546,6 @@ instance Default DBState where
def = DBState{ dbSectionLevel = 0
, dbQuoteType = DoubleQuote
, dbMeta = mempty
- , dbAcceptsMeta = False
, dbBook = False
, dbFigureTitle = mempty
, dbContent = [] }
@@ -609,18 +607,26 @@ named s e = qName (elName e) == s
--
-acceptingMetadata :: PandocMonad m => DB m a -> DB m a
-acceptingMetadata p = do
- modify (\s -> s { dbAcceptsMeta = True } )
- res <- p
- modify (\s -> s { dbAcceptsMeta = False })
- return res
-
-checkInMeta :: (PandocMonad m, Monoid a) => DB m () -> DB m a
-checkInMeta p = do
- accepts <- dbAcceptsMeta <$> get
- when accepts p
- return mempty
+addMetadataFromElement :: PandocMonad m => Element -> DB m Blocks
+addMetadataFromElement e = do
+ case filterChild (named "title") e of
+ Nothing -> return ()
+ Just z -> do
+ getInlines z >>= addMeta "title"
+ addMetaField "subtitle" z
+ case filterChild (named "authorgroup") e of
+ Nothing -> return ()
+ Just z -> addMetaField "author" z
+ addMetaField "subtitle" e
+ addMetaField "author" e
+ addMetaField "date" e
+ addMetaField "release" e
+ return mempty
+ where addMetaField fieldname elt =
+ case filterChildren (named fieldname) elt of
+ [] -> return ()
+ [z] -> getInlines z >>= addMeta fieldname
+ zs -> mapM getInlines zs >>= addMeta fieldname
addMeta :: PandocMonad m => ToMetaValue a => String -> a -> DB m ()
addMeta field val = modify (setMeta field val)
@@ -718,11 +724,6 @@ parseBlock (Elem e) =
"attribution" -> return mempty
"titleabbrev" -> return mempty
"authorinitials" -> return mempty
- "title" -> checkInMeta getTitle
- "author" -> checkInMeta getAuthor
- "authorgroup" -> checkInMeta getAuthorGroup
- "releaseinfo" -> checkInMeta (getInlines e >>= addMeta "release")
- "date" -> checkInMeta getDate
"bibliography" -> sect 0
"bibliodiv" -> sect 1
"biblioentry" -> parseMixed para (elContent e)
@@ -788,8 +789,8 @@ parseBlock (Elem e) =
"figure" -> getFigure e
"mediaobject" -> para <$> getMediaobject e
"caption" -> return mempty
- "info" -> metaBlock
- "articleinfo" -> metaBlock
+ "info" -> addMetadataFromElement e
+ "articleinfo" -> addMetadataFromElement e
"sectioninfo" -> return mempty -- keywords & other metadata
"refsectioninfo" -> return mempty -- keywords & other metadata
"refsect1info" -> return mempty -- keywords & other metadata
@@ -803,10 +804,11 @@ parseBlock (Elem e) =
"chapterinfo" -> return mempty -- keywords & other metadata
"glossaryinfo" -> return mempty -- keywords & other metadata
"appendixinfo" -> return mempty -- keywords & other metadata
- "bookinfo" -> metaBlock
+ "bookinfo" -> addMetadataFromElement e
"article" -> modify (\st -> st{ dbBook = False }) >>
- getBlocks e
- "book" -> modify (\st -> st{ dbBook = True }) >> getBlocks e
+ addMetadataFromElement e >> getBlocks e
+ "book" -> modify (\st -> st{ dbBook = True }) >>
+ addMetadataFromElement e >> getBlocks e
"table" -> parseTable
"informaltable" -> parseTable
"informalexample" -> divWith ("", ["informalexample"], []) <$>
@@ -816,6 +818,8 @@ parseBlock (Elem e) =
"screen" -> codeBlockWithLang
"programlisting" -> codeBlockWithLang
"?xml" -> return mempty
+ "title" -> return mempty -- handled in parent element
+ "subtitle" -> return mempty -- handled in parent element
_ -> getBlocks e
where parseMixed container conts = do
let (ils,rest) = break isBlockElement conts
@@ -857,19 +861,6 @@ parseBlock (Elem e) =
terms' <- mapM getInlines terms
items' <- mapM getBlocks items
return (mconcat $ intersperse (str "; ") terms', items')
- getTitle = do
- tit <- getInlines e
- subtit <- case filterChild (named "subtitle") e of
- Just s -> (text ": " <>) <$>
- getInlines s
- Nothing -> return mempty
- addMeta "title" (tit <> subtit)
-
- getAuthor = (:[]) <$> getInlines e >>= addMeta "author"
- getAuthorGroup = do
- let terms = filterChildren (named "author") e
- mapM getInlines terms >>= addMeta "author"
- getDate = getInlines e >>= addMeta "date"
parseTable = do
let isCaption x = named "title" x || named "caption" x
caption <- case filterChild isCaption e of
@@ -935,7 +926,6 @@ parseBlock (Elem e) =
modify $ \st -> st{ dbSectionLevel = n - 1 }
return $ headerWith (ident,[],[]) n' headerText <> b
lineItems = mapM getInlines $ filterChildren (named "line") e
- metaBlock = acceptingMetadata (getBlocks e) >> return mempty
getInlines :: PandocMonad m => Element -> DB m Inlines
getInlines e' = (trimInlines . mconcat) <$>
diff --git a/src/Text/Pandoc/Readers/Docx/Lists.hs b/src/Text/Pandoc/Readers/Docx/Lists.hs
index 49ea71601..0be363f3d 100644
--- a/src/Text/Pandoc/Readers/Docx/Lists.hs
+++ b/src/Text/Pandoc/Readers/Docx/Lists.hs
@@ -183,14 +183,13 @@ blocksToDefinitions' defAcc acc
pair = if remainingAttr2 == ("", [], []) then (concatMap plainParaInlines blks1, [blks2]) else (concatMap plainParaInlines blks1, [[Div remainingAttr2 blks2]])
in
blocksToDefinitions' (pair : defAcc) acc blks
-blocksToDefinitions' defAcc acc
+blocksToDefinitions' ((defTerm, defItems):defs) acc
(Div (ident2, classes2, kvs2) blks2 : blks)
- | (not . null) defAcc && "Definition" `elem` classes2 =
+ | "Definition" `elem` classes2 =
let remainingAttr2 = (ident2, delete "Definition" classes2, kvs2)
defItems2 = case remainingAttr2 == ("", [], []) of
True -> blks2
False -> [Div remainingAttr2 blks2]
- ((defTerm, defItems):defs) = defAcc
defAcc' = case null defItems of
True -> (defTerm, [defItems2]) : defs
False -> (defTerm, init defItems ++ [last defItems ++ defItems2]) : defs
diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs
index 4c4c06073..b4e52de14 100644
--- a/src/Text/Pandoc/Readers/Docx/Parse.hs
+++ b/src/Text/Pandoc/Readers/Docx/Parse.hs
@@ -785,7 +785,7 @@ So we do this in a number of steps. If we encounter the fldchar begin
tag, we start open a fldchar state variable (see state above). We add
the instrtext to it as FieldInfo. Then we close that and start adding
the runs when we get to separate. Then when we get to end, we produce
-the Field type with approriate FieldInfo and Runs.
+the Field type with appropriate FieldInfo and Runs.
-}
elemToParPart ns element
| isElem ns "w" "r" element
@@ -1056,8 +1056,10 @@ elemToRunStyle ns element parentStyle
| Just rPr <- findChildByName ns "w" "rPr" element =
RunStyle
{
- isBold = checkOnOff ns rPr (elemName ns "w" "b")
- , isItalic = checkOnOff ns rPr (elemName ns "w" "i")
+ isBold = checkOnOff ns rPr (elemName ns "w" "b") `mplus`
+ checkOnOff ns rPr (elemName ns "w" "bCs")
+ , isItalic = checkOnOff ns rPr (elemName ns "w" "i") `mplus`
+ checkOnOff ns rPr (elemName ns "w" "iCs")
, isSmallCaps = checkOnOff ns rPr (elemName ns "w" "smallCaps")
, isStrike = checkOnOff ns rPr (elemName ns "w" "strike")
, rVertAlign =
@@ -1153,8 +1155,9 @@ getSymChar :: NameSpaces -> Element -> RunElem
getSymChar ns element
| Just s <- lowerFromPrivate <$> getCodepoint
, Just font <- getFont =
- let [(char, _)] = readLitChar ("\\x" ++ s) in
- TextRun . maybe "" (:[]) $ getUnicode font char
+ case readLitChar ("\\x" ++ s) of
+ [(char, _)] -> TextRun . maybe "" (:[]) $ getUnicode font char
+ _ -> TextRun ""
where
getCodepoint = findAttrByName ns "w" "char" element
getFont = stringToFont =<< findAttrByName ns "w" "font" element
diff --git a/src/Text/Pandoc/Readers/EPUB.hs b/src/Text/Pandoc/Readers/EPUB.hs
index c26447641..bfc3fc3ee 100644
--- a/src/Text/Pandoc/Readers/EPUB.hs
+++ b/src/Text/Pandoc/Readers/EPUB.hs
@@ -73,7 +73,7 @@ readEPUB opts bytes = case toArchiveOrFail bytes of
-- runEPUB :: Except PandocError a -> Either PandocError a
-- runEPUB = runExcept
--- Note that internal reference are aggresively normalised so that all ids
+-- Note that internal reference are aggressively normalised so that all ids
-- are of the form "filename#id"
--
archiveToEPUB :: (PandocMonad m) => ReaderOptions -> Archive -> m Pandoc
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
index 32a1ba5a6..b06e07a80 100644
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -68,11 +68,13 @@ import qualified Text.Pandoc.Builder as B
import Text.Pandoc.Class (PandocMonad (..))
import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps)
import Text.Pandoc.Definition
+import Text.Pandoc.Readers.LaTeX (rawLaTeXInline)
+import Text.Pandoc.Readers.LaTeX.Types (Macro)
import Text.Pandoc.Error
import Text.Pandoc.Logging
import Text.Pandoc.Options (
Extension (Ext_epub_html_exts, Ext_empty_paragraphs, Ext_native_divs,
- Ext_native_spans, Ext_raw_html, Ext_line_blocks),
+ Ext_native_spans, Ext_raw_html, Ext_line_blocks, Ext_raw_tex),
ReaderOptions (readerExtensions, readerStripComments),
extensionEnabled)
import Text.Pandoc.Parsing hiding ((<|>))
@@ -102,7 +104,8 @@ readHtml opts inp = do
(m:_) -> messageString m
result <- flip runReaderT def $
runParserT parseDoc
- (HTMLState def{ stateOptions = opts } [] Nothing Set.empty M.empty [])
+ (HTMLState def{ stateOptions = opts }
+ [] Nothing Set.empty M.empty [] M.empty)
"source" tags
case result of
Right doc -> return doc
@@ -124,7 +127,8 @@ data HTMLState =
baseHref :: Maybe URI,
identifiers :: Set.Set String,
headerMap :: M.Map Inlines String,
- logMessages :: [LogMessage]
+ logMessages :: [LogMessage],
+ macros :: M.Map Text Macro
}
data HTMLLocal = HTMLLocal { quoteContext :: QuoteContext
@@ -659,6 +663,7 @@ inline = choice
, pCode
, pSpan
, pMath False
+ , pScriptMath
, pRawHtmlInline
]
@@ -745,18 +750,18 @@ pLink = try $ do
let uid = fromMaybe (T.unpack $ fromAttrib "name" tag) $
maybeFromAttrib "id" tag
let cls = words $ T.unpack $ fromAttrib "class" tag
- lab <- trimInlines . mconcat <$> manyTill inline (pCloses "a")
+ lab <- mconcat <$> manyTill inline (pCloses "a")
-- check for href; if href, then a link, otherwise a span
case maybeFromAttrib "href" tag of
Nothing ->
- return $ B.spanWith (uid, cls, []) lab
+ return $ extractSpaces (B.spanWith (uid, cls, [])) lab
Just url' -> do
mbBaseHref <- baseHref <$> getState
let url = case (parseURIReference url', mbBaseHref) of
(Just rel, Just bs) ->
show (rel `nonStrictRelativeTo` bs)
_ -> url'
- return $ B.linkWith (uid, cls, []) (escapeURI url) title lab
+ return $ extractSpaces (B.linkWith (uid, cls, []) (escapeURI url) title) lab
pImage :: PandocMonad m => TagParser m Inlines
pImage = do
@@ -818,6 +823,17 @@ toStringAttr :: [(Text, Text)] -> [(String, String)]
toStringAttr = map go
where go (x,y) = (T.unpack x, T.unpack y)
+pScriptMath :: PandocMonad m => TagParser m Inlines
+pScriptMath = try $ do
+ TagOpen _ attr' <- pSatisfy $ tagOpen (=="script") (const True)
+ isdisplay <- case lookup "type" attr' of
+ Just x | "math/tex" `T.isPrefixOf` x
+ -> return $ "display" `T.isSuffixOf` x
+ _ -> mzero
+ contents <- T.unpack . innerText <$>
+ manyTill pAnyTag (pSatisfy (matchTagClose "script"))
+ return $ (if isdisplay then B.displayMath else B.math) contents
+
pMath :: PandocMonad m => Bool -> TagParser m Inlines
pMath inCase = try $ do
open@(TagOpen _ attr') <- pSatisfy $ tagOpen (=="math") (const True)
@@ -852,7 +868,7 @@ pInTags' tagtype tagtest parser = try $ do
pSatisfy (\t -> t ~== TagOpen tagtype [] && tagtest t)
mconcat <$> manyTill parser (pCloses tagtype <|> eof)
--- parses p, preceeded by an optional opening tag
+-- parses p, preceded by an optional opening tag
-- and followed by an optional closing tags
pOptInTag :: PandocMonad m => Text -> TagParser m a -> TagParser m a
pOptInTag tagtype p = try $ do
@@ -907,9 +923,25 @@ pTagContents =
<|> pStr
<|> pSpace
<|> smartPunctuation pTagContents
+ <|> pRawTeX
<|> pSymbol
<|> pBad
+pRawTeX :: PandocMonad m => InlinesParser m Inlines
+pRawTeX = do
+ lookAhead $ try $ do
+ char '\\'
+ choice $ map (try . string) ["begin", "eqref", "ref"]
+ guardEnabled Ext_raw_tex
+ inp <- getInput
+ st <- getState
+ res <- lift $ runParserT (withRaw rawLaTeXInline) st "chunk" (T.unpack inp)
+ case res of
+ Left _ -> mzero
+ Right (contents, raw) -> do
+ _ <- count (length raw) anyChar
+ return $ B.rawInline "tex" contents
+
pStr :: PandocMonad m => InlinesParser m Inlines
pStr = do
result <- many1 $ satisfy $ \c ->
@@ -923,6 +955,7 @@ isSpecial '\'' = True
isSpecial '.' = True
isSpecial '-' = True
isSpecial '$' = True
+isSpecial '\\' = True
isSpecial '\8216' = True
isSpecial '\8217' = True
isSpecial '\8220' = True
@@ -1249,6 +1282,10 @@ isSpace _ = False
-- Instances
+instance HasMacros HTMLState where
+ extractMacros = macros
+ updateMacros f st = st{ macros = f $ macros st }
+
instance HasIdentifierList HTMLState where
extractIdentifierList = identifiers
updateIdentifierList f s = s{ identifiers = f (identifiers s) }
@@ -1281,7 +1318,7 @@ instance HasLastStrPosition HTMLState where
setLastStrPos s st = st {parserState = setLastStrPos s (parserState st)}
getLastStrPos = getLastStrPos . parserState
--- For now we need a special verison here; the one in Shared has String type
+-- For now we need a special version here; the one in Shared has String type
renderTags' :: [Tag Text] -> Text
renderTags' = renderTagsOptions
renderOptions{ optMinimize = matchTags ["hr", "br", "img",
diff --git a/src/Text/Pandoc/Readers/Haddock.hs b/src/Text/Pandoc/Readers/Haddock.hs
index 967037e4e..072bab350 100644
--- a/src/Text/Pandoc/Readers/Haddock.hs
+++ b/src/Text/Pandoc/Readers/Haddock.hs
@@ -44,11 +44,7 @@ readHaddockEither :: ReaderOptions -- ^ Reader options
-> String -- ^ String to parse
-> Either PandocError Pandoc
readHaddockEither _opts =
-#if MIN_VERSION_haddock_library(1,2,0)
- Right . B.doc . docHToBlocks . _doc . parseParas
-#else
- Right . B.doc . docHToBlocks . parseParas
-#endif
+ Right . B.doc . docHToBlocks . _doc . parseParas Nothing
docHToBlocks :: DocH String Identifier -> Blocks
docHToBlocks d' =
@@ -68,10 +64,8 @@ docHToBlocks d' =
DocEmphasis _ -> inlineFallback
DocMonospaced _ -> inlineFallback
DocBold _ -> inlineFallback
-#if MIN_VERSION_haddock_library(1,4,0)
DocMathInline _ -> inlineFallback
DocMathDisplay _ -> inlineFallback
-#endif
DocHeader h -> B.header (headerLevel h)
(docHToInlines False $ headerTitle h)
DocUnorderedList items -> B.bulletList (map docHToBlocks items)
@@ -87,7 +81,6 @@ docHToBlocks d' =
DocProperty s -> B.codeBlockWith ("",["property","haskell"],[]) (trim s)
DocExamples es -> mconcat $ map (\e ->
makeExample ">>>" (exampleExpression e) (exampleResult e)) es
-#if MIN_VERSION_haddock_library(1,5,0)
DocTable H.Table{ tableHeaderRows = headerRows
, tableBodyRows = bodyRows
}
@@ -100,7 +93,6 @@ docHToBlocks d' =
colspecs = replicate (maximum (map length body))
(AlignDefault, 0.0)
in B.table mempty colspecs header body
-#endif
where inlineFallback = B.plain $ docHToInlines False d'
consolidatePlains = B.fromList . consolidatePlains' . B.toList
@@ -133,10 +125,8 @@ docHToInlines isCode d' =
DocMonospaced (DocString s) -> B.code s
DocMonospaced d -> docHToInlines True d
DocBold d -> B.strong (docHToInlines isCode d)
-#if MIN_VERSION_haddock_library(1,4,0)
DocMathInline s -> B.math s
DocMathDisplay s -> B.displayMath s
-#endif
DocHeader _ -> mempty
DocUnorderedList _ -> mempty
DocOrderedList _ -> mempty
@@ -149,9 +139,7 @@ docHToInlines isCode d' =
DocAName s -> B.spanWith (s,["anchor"],[]) mempty
DocProperty _ -> mempty
DocExamples _ -> mempty
-#if MIN_VERSION_haddock_library(1,5,0)
DocTable _ -> mempty
-#endif
-- | Create an 'Example', stripping superfluous characters as appropriate
makeExample :: String -> String -> [String] -> Blocks
diff --git a/src/Text/Pandoc/Readers/JATS.hs b/src/Text/Pandoc/Readers/JATS.hs
index 59af76d23..695c86b5d 100644
--- a/src/Text/Pandoc/Readers/JATS.hs
+++ b/src/Text/Pandoc/Readers/JATS.hs
@@ -191,7 +191,7 @@ parseBlock (Elem e) =
listType -> do
let start = fromMaybe 1 $
(strContent <$> (filterElement (named "list-item") e
- >>= filterElement (named "lable")))
+ >>= filterElement (named "label")))
>>= safeRead
orderedListWith (start, parseListStyleType listType, DefaultDelim)
<$> listitems
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
index 39dffde76..7c5619165 100644
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -47,8 +47,7 @@ import Prelude
import Control.Applicative (many, optional, (<|>))
import Control.Monad
import Control.Monad.Except (throwError)
-import Control.Monad.Trans (lift)
-import Data.Char (chr, isAlphaNum, isDigit, isLetter, ord, toLower, toUpper)
+import Data.Char (isDigit, isLetter, toLower, toUpper)
import Data.Default
import Data.List (intercalate, isPrefixOf)
import qualified Data.Map as M
@@ -63,7 +62,7 @@ import Text.Pandoc.Builder
import Text.Pandoc.Class (PandocMonad, PandocPure, getResourcePath, lookupEnv,
readFileFromDirs, report, setResourcePath,
setTranslations, translateTerm, trace)
-import Text.Pandoc.Error (PandocError (PandocMacroLoop, PandocParseError, PandocParsecError))
+import Text.Pandoc.Error (PandocError ( PandocParseError, PandocParsecError))
import Text.Pandoc.Highlighting (fromListingsLanguage, languagesByExtension)
import Text.Pandoc.ImageSize (numUnit, showFl)
import Text.Pandoc.Logging
@@ -71,12 +70,15 @@ import Text.Pandoc.Options
import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline,
optional, space, spaces, withRaw, (<|>))
import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),
- Tok (..), TokType (..))
+ ArgSpec (..), Tok (..), TokType (..))
+import Text.Pandoc.Readers.LaTeX.Parsing
+import Text.Pandoc.Readers.LaTeX.Lang (polyglossiaLangToBCP47,
+ babelLangToBCP47)
import Text.Pandoc.Shared
import qualified Text.Pandoc.Translations as Translations
import Text.Pandoc.Walk
-import Text.Parsec.Pos
import qualified Text.Pandoc.Builder as B
+import qualified Data.Text.Normalize as Normalize
-- for debugging:
-- import Text.Pandoc.Extensions (getDefaultExtensions)
@@ -137,482 +139,49 @@ resolveRefs _ x = x
-- Left e -> error (show e)
-- Right r -> return r
-newtype HeaderNum = HeaderNum [Int]
- deriving (Show)
-
-renderHeaderNum :: HeaderNum -> String
-renderHeaderNum (HeaderNum xs) =
- intercalate "." (map show xs)
-
-incrementHeaderNum :: Int -> HeaderNum -> HeaderNum
-incrementHeaderNum level (HeaderNum ns) = HeaderNum $
- case reverse (take level (ns ++ repeat 0)) of
- (x:xs) -> reverse (x+1 : xs)
- [] -> [] -- shouldn't happen
-
-data LaTeXState = LaTeXState{ sOptions :: ReaderOptions
- , sMeta :: Meta
- , sQuoteContext :: QuoteContext
- , sMacros :: M.Map Text Macro
- , sContainers :: [String]
- , sHeaders :: M.Map Inlines String
- , sLogMessages :: [LogMessage]
- , sIdentifiers :: Set.Set String
- , sVerbatimMode :: Bool
- , sCaption :: Maybe Inlines
- , sInListItem :: Bool
- , sInTableCell :: Bool
- , sLastHeaderNum :: HeaderNum
- , sLabels :: M.Map String [Inline]
- , sHasChapters :: Bool
- , sToggles :: M.Map String Bool
- }
- deriving Show
-
-defaultLaTeXState :: LaTeXState
-defaultLaTeXState = LaTeXState{ sOptions = def
- , sMeta = nullMeta
- , sQuoteContext = NoQuote
- , sMacros = M.empty
- , sContainers = []
- , sHeaders = M.empty
- , sLogMessages = []
- , sIdentifiers = Set.empty
- , sVerbatimMode = False
- , sCaption = Nothing
- , sInListItem = False
- , sInTableCell = False
- , sLastHeaderNum = HeaderNum []
- , sLabels = M.empty
- , sHasChapters = False
- , sToggles = M.empty
- }
-
-instance PandocMonad m => HasQuoteContext LaTeXState m where
- getQuoteContext = sQuoteContext <$> getState
- withQuoteContext context parser = do
- oldState <- getState
- let oldQuoteContext = sQuoteContext oldState
- setState oldState { sQuoteContext = context }
- result <- parser
- newState <- getState
- setState newState { sQuoteContext = oldQuoteContext }
- return result
-
-instance HasLogMessages LaTeXState where
- addLogMessage msg st = st{ sLogMessages = msg : sLogMessages st }
- getLogMessages st = reverse $ sLogMessages st
-
-instance HasIdentifierList LaTeXState where
- extractIdentifierList = sIdentifiers
- updateIdentifierList f st = st{ sIdentifiers = f $ sIdentifiers st }
-
-instance HasIncludeFiles LaTeXState where
- getIncludeFiles = sContainers
- addIncludeFile f s = s{ sContainers = f : sContainers s }
- dropLatestIncludeFile s = s { sContainers = drop 1 $ sContainers s }
-
-instance HasHeaderMap LaTeXState where
- extractHeaderMap = sHeaders
- updateHeaderMap f st = st{ sHeaders = f $ sHeaders st }
-
-instance HasMacros LaTeXState where
- extractMacros st = sMacros st
- updateMacros f st = st{ sMacros = f (sMacros st) }
-
-instance HasReaderOptions LaTeXState where
- extractReaderOptions = sOptions
-
-instance HasMeta LaTeXState where
- setMeta field val st =
- st{ sMeta = setMeta field val $ sMeta st }
- deleteMeta field st =
- st{ sMeta = deleteMeta field $ sMeta st }
-
-instance Default LaTeXState where
- def = defaultLaTeXState
-
-type LP m = ParserT [Tok] LaTeXState m
-
-withVerbatimMode :: PandocMonad m => LP m a -> LP m a
-withVerbatimMode parser = do
- updateState $ \st -> st{ sVerbatimMode = True }
- result <- parser
- updateState $ \st -> st{ sVerbatimMode = False }
- return result
-
-rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s)
- => LP m a -> LP m a -> ParserT String s m (a, String)
-rawLaTeXParser parser valParser = do
- inp <- getInput
- let toks = tokenize "source" $ T.pack inp
- pstate <- getState
- let lstate = def{ sOptions = extractReaderOptions pstate }
- let lstate' = lstate { sMacros = extractMacros pstate }
- let rawparser = (,) <$> withRaw valParser <*> getState
- res' <- lift $ runParserT (snd <$> withRaw parser) lstate "chunk" toks
- case res' of
- Left _ -> mzero
- Right toks' -> do
- res <- lift $ runParserT (do doMacros 0
- -- retokenize, applying macros
- ts <- many (satisfyTok (const True))
- setInput ts
- rawparser)
- lstate' "chunk" toks'
- case res of
- Left _ -> mzero
- Right ((val, raw), st) -> do
- updateState (updateMacros (sMacros st <>))
- _ <- takeP (T.length (untokenize toks'))
- return (val, T.unpack (untokenize raw))
-
-applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)
- => String -> ParserT String s m String
-applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|>
- do let retokenize = doMacros 0 *>
- (toksToString <$> many (satisfyTok (const True)))
- pstate <- getState
- let lstate = def{ sOptions = extractReaderOptions pstate
- , sMacros = extractMacros pstate }
- res <- runParserT retokenize lstate "math" (tokenize "math" (T.pack s))
- case res of
- Left e -> fail (show e)
- Right s' -> return s'
rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)
=> ParserT String s m String
rawLaTeXBlock = do
lookAhead (try (char '\\' >> letter))
- -- we don't want to apply newly defined latex macros to their own
- -- definitions:
- snd <$> rawLaTeXParser (environment <|> macroDef <|> blockCommand) blocks
+ snd <$> (rawLaTeXParser False macroDef blocks
+ <|> (rawLaTeXParser True
+ (do choice (map controlSeq
+ ["include", "input", "subfile", "usepackage"])
+ skipMany opt
+ braced
+ return mempty) blocks)
+ <|> rawLaTeXParser True
+ (environment <|> blockCommand)
+ (mconcat <$> (many (block <|> beginOrEndCommand))))
+
+-- See #4667 for motivation; sometimes people write macros
+-- that just evaluate to a begin or end command, which blockCommand
+-- won't accept.
+beginOrEndCommand :: PandocMonad m => LP m Blocks
+beginOrEndCommand = try $ do
+ Tok _ (CtrlSeq name) txt <- anyControlSeq
+ guard $ name == "begin" || name == "end"
+ (envname, rawargs) <- withRaw braced
+ if M.member (untokenize envname)
+ (inlineEnvironments :: M.Map Text (LP PandocPure Inlines))
+ then mzero
+ else return $ rawBlock "latex"
+ (T.unpack (txt <> untokenize rawargs))
rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)
=> ParserT String s m String
rawLaTeXInline = do
lookAhead (try (char '\\' >> letter))
- snd <$> rawLaTeXParser (inlineEnvironment <|> inlineCommand') inlines
+ snd <$> ( rawLaTeXParser True
+ (mempty <$ (controlSeq "input" >> skipMany opt >> braced))
+ inlines
+ <|> rawLaTeXParser True (inlineEnvironment <|> inlineCommand') inlines)
inlineCommand :: PandocMonad m => ParserT String ParserState m Inlines
inlineCommand = do
lookAhead (try (char '\\' >> letter))
- fst <$> rawLaTeXParser (inlineEnvironment <|> inlineCommand') inlines
-
-tokenize :: SourceName -> Text -> [Tok]
-tokenize sourcename = totoks (initialPos sourcename)
-
-totoks :: SourcePos -> Text -> [Tok]
-totoks pos t =
- case T.uncons t of
- Nothing -> []
- Just (c, rest)
- | c == '\n' ->
- Tok pos Newline "\n"
- : totoks (setSourceColumn (incSourceLine pos 1) 1) rest
- | isSpaceOrTab c ->
- let (sps, rest') = T.span isSpaceOrTab t
- in Tok pos Spaces sps
- : totoks (incSourceColumn pos (T.length sps))
- rest'
- | isAlphaNum c ->
- let (ws, rest') = T.span isAlphaNum t
- in Tok pos Word ws
- : totoks (incSourceColumn pos (T.length ws)) rest'
- | c == '%' ->
- let (cs, rest') = T.break (== '\n') rest
- in Tok pos Comment ("%" <> cs)
- : totoks (incSourceColumn pos (1 + T.length cs)) rest'
- | c == '\\' ->
- case T.uncons rest of
- Nothing -> [Tok pos (CtrlSeq " ") "\\"]
- Just (d, rest')
- | isLetterOrAt d ->
- -- \makeatletter is common in macro defs;
- -- ideally we should make tokenization sensitive
- -- to \makeatletter and \makeatother, but this is
- -- probably best for now
- let (ws, rest'') = T.span isLetterOrAt rest
- (ss, rest''') = T.span isSpaceOrTab rest''
- in Tok pos (CtrlSeq ws) ("\\" <> ws <> ss)
- : totoks (incSourceColumn pos
- (1 + T.length ws + T.length ss)) rest'''
- | isSpaceOrTab d || d == '\n' ->
- let (w1, r1) = T.span isSpaceOrTab rest
- (w2, (w3, r3)) = case T.uncons r1 of
- Just ('\n', r2)
- -> (T.pack "\n",
- T.span isSpaceOrTab r2)
- _ -> (mempty, (mempty, r1))
- ws = "\\" <> w1 <> w2 <> w3
- in case T.uncons r3 of
- Just ('\n', _) ->
- Tok pos (CtrlSeq " ") ("\\" <> w1)
- : totoks (incSourceColumn pos (T.length ws))
- r1
- _ ->
- Tok pos (CtrlSeq " ") ws
- : totoks (incSourceColumn pos (T.length ws))
- r3
- | otherwise ->
- Tok pos (CtrlSeq (T.singleton d)) (T.pack [c,d])
- : totoks (incSourceColumn pos 2) rest'
- | c == '#' ->
- let (t1, t2) = T.span (\d -> d >= '0' && d <= '9') rest
- in case safeRead (T.unpack t1) of
- Just i ->
- Tok pos (Arg i) ("#" <> t1)
- : totoks (incSourceColumn pos (1 + T.length t1)) t2
- Nothing ->
- Tok pos Symbol "#"
- : totoks (incSourceColumn pos 1) t2
- | c == '^' ->
- case T.uncons rest of
- Just ('^', rest') ->
- case T.uncons rest' of
- Just (d, rest'')
- | isLowerHex d ->
- case T.uncons rest'' of
- Just (e, rest''') | isLowerHex e ->
- Tok pos Esc2 (T.pack ['^','^',d,e])
- : totoks (incSourceColumn pos 4) rest'''
- _ ->
- Tok pos Esc1 (T.pack ['^','^',d])
- : totoks (incSourceColumn pos 3) rest''
- | d < '\128' ->
- Tok pos Esc1 (T.pack ['^','^',d])
- : totoks (incSourceColumn pos 3) rest''
- _ -> Tok pos Symbol "^" :
- Tok (incSourceColumn pos 1) Symbol "^" :
- totoks (incSourceColumn pos 2) rest'
- _ -> Tok pos Symbol "^"
- : totoks (incSourceColumn pos 1) rest
- | otherwise ->
- Tok pos Symbol (T.singleton c) : totoks (incSourceColumn pos 1) rest
-
-isSpaceOrTab :: Char -> Bool
-isSpaceOrTab ' ' = True
-isSpaceOrTab '\t' = True
-isSpaceOrTab _ = False
-
-isLetterOrAt :: Char -> Bool
-isLetterOrAt '@' = True
-isLetterOrAt c = isLetter c
-
-isLowerHex :: Char -> Bool
-isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f'
-
-untokenize :: [Tok] -> Text
-untokenize = mconcat . map untoken
-
-untoken :: Tok -> Text
-untoken (Tok _ _ t) = t
-
-satisfyTok :: PandocMonad m => (Tok -> Bool) -> LP m Tok
-satisfyTok f =
- try $ do
- res <- tokenPrim (T.unpack . untoken) updatePos matcher
- doMacros 0 -- apply macros on remaining input stream
- return res
- where matcher t | f t = Just t
- | otherwise = Nothing
- updatePos :: SourcePos -> Tok -> [Tok] -> SourcePos
- updatePos _spos _ (Tok pos _ _ : _) = pos
- updatePos spos _ [] = incSourceColumn spos 1
-
-doMacros :: PandocMonad m => Int -> LP m ()
-doMacros n = do
- verbatimMode <- sVerbatimMode <$> getState
- unless verbatimMode $ do
- inp <- getInput
- case inp of
- Tok spos (CtrlSeq "begin") _ : Tok _ Symbol "{" :
- Tok _ Word name : Tok _ Symbol "}" : ts
- -> handleMacros spos name ts
- Tok spos (CtrlSeq "end") _ : Tok _ Symbol "{" :
- Tok _ Word name : Tok _ Symbol "}" : ts
- -> handleMacros spos ("end" <> name) ts
- Tok _ (CtrlSeq "expandafter") _ : t : ts
- -> do setInput ts
- doMacros n
- getInput >>= setInput . combineTok t
- Tok spos (CtrlSeq name) _ : ts
- -> handleMacros spos name ts
- _ -> return ()
- where combineTok (Tok spos (CtrlSeq name) x) (Tok _ Word w : ts)
- | T.all isLetterOrAt w =
- Tok spos (CtrlSeq (name <> w)) (x1 <> w <> x2) : ts
- where (x1, x2) = T.break isSpaceOrTab x
- combineTok t ts = t:ts
- handleMacros spos name ts = do
- macros <- sMacros <$> getState
- case M.lookup name macros of
- Nothing -> return ()
- Just (Macro expansionPoint numargs optarg newtoks) -> do
- setInput ts
- let getarg = try $ spaces >> bracedOrToken
- args <- case optarg of
- Nothing -> count numargs getarg
- Just o ->
- (:) <$> option o bracketedToks
- <*> count (numargs - 1) getarg
- -- first boolean param is true if we're tokenizing
- -- an argument (in which case we don't want to
- -- expand #1 etc.)
- let addTok False (Tok _ (Arg i) _) acc | i > 0
- , i <= numargs =
- foldr (addTok True) acc (args !! (i - 1))
- -- add space if needed after control sequence
- -- see #4007
- addTok _ (Tok _ (CtrlSeq x) txt)
- acc@(Tok _ Word _ : _)
- | not (T.null txt) &&
- isLetter (T.last txt) =
- Tok spos (CtrlSeq x) (txt <> " ") : acc
- addTok _ t acc = setpos spos t : acc
- ts' <- getInput
- setInput $ foldr (addTok False) ts' newtoks
- case expansionPoint of
- ExpandWhenUsed ->
- if n > 20 -- detect macro expansion loops
- then throwError $ PandocMacroLoop (T.unpack name)
- else doMacros (n + 1)
- ExpandWhenDefined -> return ()
-
-
-setpos :: SourcePos -> Tok -> Tok
-setpos spos (Tok _ tt txt) = Tok spos tt txt
-
-anyControlSeq :: PandocMonad m => LP m Tok
-anyControlSeq = satisfyTok isCtrlSeq
- where isCtrlSeq (Tok _ (CtrlSeq _) _) = True
- isCtrlSeq _ = False
-
-anySymbol :: PandocMonad m => LP m Tok
-anySymbol = satisfyTok isSym
- where isSym (Tok _ Symbol _) = True
- isSym _ = False
-
-spaces :: PandocMonad m => LP m ()
-spaces = skipMany (satisfyTok (tokTypeIn [Comment, Spaces, Newline]))
-
-spaces1 :: PandocMonad m => LP m ()
-spaces1 = skipMany1 (satisfyTok (tokTypeIn [Comment, Spaces, Newline]))
-
-tokTypeIn :: [TokType] -> Tok -> Bool
-tokTypeIn toktypes (Tok _ tt _) = tt `elem` toktypes
-
-controlSeq :: PandocMonad m => Text -> LP m Tok
-controlSeq name = satisfyTok isNamed
- where isNamed (Tok _ (CtrlSeq n) _) = n == name
- isNamed _ = False
-
-symbol :: PandocMonad m => Char -> LP m Tok
-symbol c = satisfyTok isc
- where isc (Tok _ Symbol d) = case T.uncons d of
- Just (c',_) -> c == c'
- _ -> False
- isc _ = False
-
-symbolIn :: PandocMonad m => [Char] -> LP m Tok
-symbolIn cs = satisfyTok isInCs
- where isInCs (Tok _ Symbol d) = case T.uncons d of
- Just (c,_) -> c `elem` cs
- _ -> False
- isInCs _ = False
-
-sp :: PandocMonad m => LP m ()
-sp = whitespace <|> endline
-
-whitespace :: PandocMonad m => LP m ()
-whitespace = () <$ satisfyTok isSpaceTok
- where isSpaceTok (Tok _ Spaces _) = True
- isSpaceTok _ = False
-
-newlineTok :: PandocMonad m => LP m ()
-newlineTok = () <$ satisfyTok isNewlineTok
-
-isNewlineTok :: Tok -> Bool
-isNewlineTok (Tok _ Newline _) = True
-isNewlineTok _ = False
-
-comment :: PandocMonad m => LP m ()
-comment = () <$ satisfyTok isCommentTok
- where isCommentTok (Tok _ Comment _) = True
- isCommentTok _ = False
-
-anyTok :: PandocMonad m => LP m Tok
-anyTok = satisfyTok (const True)
-
-endline :: PandocMonad m => LP m ()
-endline = try $ do
- newlineTok
- lookAhead anyTok
- notFollowedBy blankline
-
-blankline :: PandocMonad m => LP m ()
-blankline = try $ skipMany whitespace *> newlineTok
-
-primEscape :: PandocMonad m => LP m Char
-primEscape = do
- Tok _ toktype t <- satisfyTok (tokTypeIn [Esc1, Esc2])
- case toktype of
- Esc1 -> case T.uncons (T.drop 2 t) of
- Just (c, _)
- | c >= '\64' && c <= '\127' -> return (chr (ord c - 64))
- | otherwise -> return (chr (ord c + 64))
- Nothing -> fail "Empty content of Esc1"
- Esc2 -> case safeRead ('0':'x':T.unpack (T.drop 2 t)) of
- Just x -> return (chr x)
- Nothing -> fail $ "Could not read: " ++ T.unpack t
- _ -> fail "Expected an Esc1 or Esc2 token" -- should not happen
-
-bgroup :: PandocMonad m => LP m Tok
-bgroup = try $ do
- skipMany sp
- symbol '{' <|> controlSeq "bgroup" <|> controlSeq "begingroup"
-
-egroup :: PandocMonad m => LP m Tok
-egroup = symbol '}' <|> controlSeq "egroup" <|> controlSeq "endgroup"
-
-grouped :: (PandocMonad m, Monoid a) => LP m a -> LP m a
-grouped parser = try $ do
- bgroup
- -- first we check for an inner 'grouped', because
- -- {{a,b}} should be parsed the same as {a,b}
- try (grouped parser <* egroup) <|> (mconcat <$> manyTill parser egroup)
-
-braced :: PandocMonad m => LP m [Tok]
-braced = bgroup *> braced' 1
- where braced' (n :: Int) =
- handleEgroup n <|> handleBgroup n <|> handleOther n
- handleEgroup n = do
- t <- egroup
- if n == 1
- then return []
- else (t:) <$> braced' (n - 1)
- handleBgroup n = do
- t <- bgroup
- (t:) <$> braced' (n + 1)
- handleOther n = do
- t <- anyTok
- (t:) <$> braced' n
-
-bracketed :: PandocMonad m => Monoid a => LP m a -> LP m a
-bracketed parser = try $ do
- symbol '['
- mconcat <$> manyTill parser (symbol ']')
-
-dimenarg :: PandocMonad m => LP m Text
-dimenarg = try $ do
- ch <- option False $ True <$ symbol '='
- Tok _ _ s <- satisfyTok isWordTok
- guard $ T.take 2 (T.reverse s) `elem`
- ["pt","pc","in","bp","cm","mm","dd","cc","sp"]
- let num = T.take (T.length s - 2) s
- guard $ T.length num > 0
- guard $ T.all isDigit num
- return $ T.pack ['=' | ch] <> s
+ fst <$> rawLaTeXParser True (inlineEnvironment <|> inlineCommand') inlines
-- inline elements:
@@ -625,13 +194,6 @@ regularSymbol = (str . T.unpack . untoken) <$> satisfyTok isRegularSymbol
isRegularSymbol _ = False
isSpecial c = c `Set.member` specialChars
-specialChars :: Set.Set Char
-specialChars = Set.fromList "#$%&~_^\\{}"
-
-isWordTok :: Tok -> Bool
-isWordTok (Tok _ Word _) = True
-isWordTok _ = False
-
inlineGroup :: PandocMonad m => LP m Inlines
inlineGroup = do
ils <- grouped inline
@@ -678,7 +240,7 @@ dosiunitx = do
skipopts
value <- tok
valueprefix <- option "" $ bracketed tok
- unit <- inlineCommand' <|> tok
+ unit <- grouped (mconcat <$> many1 siUnit) <|> siUnit <|> tok
let emptyOr160 "" = ""
emptyOr160 _ = "\160"
return . mconcat $ [valueprefix,
@@ -687,11 +249,187 @@ dosiunitx = do
emptyOr160 unit,
unit]
--- siunitx's \square command
-dosquare :: PandocMonad m => LP m Inlines
-dosquare = do
- unit <- inlineCommand' <|> tok
- return . mconcat $ [unit, "\178"]
+siUnit :: PandocMonad m => LP m Inlines
+siUnit = do
+ Tok _ (CtrlSeq name) _ <- anyControlSeq
+ if name == "square"
+ then do
+ unit <- grouped (mconcat <$> many1 siUnit) <|> siUnit <|> tok
+ return . mconcat $ [unit, "\178"]
+ else
+ case M.lookup name siUnitMap of
+ Just il -> return il
+ Nothing -> mzero
+
+siUnitMap :: M.Map Text Inlines
+siUnitMap = M.fromList
+ [ ("fg", str "fg")
+ , ("pg", str "pg")
+ , ("ng", str "ng")
+ , ("ug", str "μg")
+ , ("mg", str "mg")
+ , ("g", str "g")
+ , ("kg", str "kg")
+ , ("amu", str "u")
+ , ("pm", str "pm")
+ , ("nm", str "nm")
+ , ("um", str "μm")
+ , ("mm", str "mm")
+ , ("cm", str "cm")
+ , ("dm", str "dm")
+ , ("m", str "m")
+ , ("km", str "km")
+ , ("as", str "as")
+ , ("fs", str "fs")
+ , ("ps", str "ps")
+ , ("ns", str "ns")
+ , ("us", str "μs")
+ , ("ms", str "ms")
+ , ("s", str "s")
+ , ("fmol", str "fmol")
+ , ("pmol", str "pmol")
+ , ("nmol", str "nmol")
+ , ("umol", str "μmol")
+ , ("mmol", str "mmol")
+ , ("mol", str "mol")
+ , ("kmol", str "kmol")
+ , ("pA", str "pA")
+ , ("nA", str "nA")
+ , ("uA", str "μA")
+ , ("mA", str "mA")
+ , ("A", str "A")
+ , ("kA", str "kA")
+ , ("ul", str "μl")
+ , ("ml", str "ml")
+ , ("l", str "l")
+ , ("hl", str "hl")
+ , ("uL", str "μL")
+ , ("mL", str "mL")
+ , ("L", str "L")
+ , ("hL", str "hL")
+ , ("mHz", str "mHz")
+ , ("Hz", str "Hz")
+ , ("kHz", str "kHz")
+ , ("MHz", str "MHz")
+ , ("GHz", str "GHz")
+ , ("THz", str "THz")
+ , ("mN", str "mN")
+ , ("N", str "N")
+ , ("kN", str "kN")
+ , ("MN", str "MN")
+ , ("Pa", str "Pa")
+ , ("kPa", str "kPa")
+ , ("MPa", str "MPa")
+ , ("GPa", str "GPa")
+ , ("mohm", str "mΩ")
+ , ("kohm", str "kΩ")
+ , ("Mohm", str "MΩ")
+ , ("pV", str "pV")
+ , ("nV", str "nV")
+ , ("uV", str "μV")
+ , ("mV", str "mV")
+ , ("V", str "V")
+ , ("kV", str "kV")
+ , ("W", str "W")
+ , ("uW", str "μW")
+ , ("mW", str "mW")
+ , ("kW", str "kW")
+ , ("MW", str "MW")
+ , ("GW", str "GW")
+ , ("J", str "J")
+ , ("uJ", str "μJ")
+ , ("mJ", str "mJ")
+ , ("kJ", str "kJ")
+ , ("eV", str "eV")
+ , ("meV", str "meV")
+ , ("keV", str "keV")
+ , ("MeV", str "MeV")
+ , ("GeV", str "GeV")
+ , ("TeV", str "TeV")
+ , ("kWh", str "kWh")
+ , ("F", str "F")
+ , ("fF", str "fF")
+ , ("pF", str "pF")
+ , ("K", str "K")
+ , ("dB", str "dB")
+ , ("angstrom", str "Å")
+ , ("arcmin", str "′")
+ , ("arcminute", str "′")
+ , ("arcsecond", str "″")
+ , ("astronomicalunit", str "ua")
+ , ("atomicmassunit", str "u")
+ , ("atto", str "a")
+ , ("bar", str "bar")
+ , ("barn", str "b")
+ , ("becquerel", str "Bq")
+ , ("bel", str "B")
+ , ("candela", str "cd")
+ , ("celsius", str "°C")
+ , ("centi", str "c")
+ , ("coulomb", str "C")
+ , ("dalton", str "Da")
+ , ("day", str "d")
+ , ("deca", str "d")
+ , ("deci", str "d")
+ , ("decibel", str "db")
+ , ("degreeCelsius",str "°C")
+ , ("degree", str "°")
+ , ("deka", str "d")
+ , ("electronvolt", str "eV")
+ , ("exa", str "E")
+ , ("farad", str "F")
+ , ("femto", str "f")
+ , ("giga", str "G")
+ , ("gram", str "g")
+ , ("hectare", str "ha")
+ , ("hecto", str "h")
+ , ("henry", str "H")
+ , ("hertz", str "Hz")
+ , ("hour", str "h")
+ , ("joule", str "J")
+ , ("katal", str "kat")
+ , ("kelvin", str "K")
+ , ("kilo", str "k")
+ , ("kilogram", str "kg")
+ , ("knot", str "kn")
+ , ("liter", str "L")
+ , ("litre", str "l")
+ , ("lumen", str "lm")
+ , ("lux", str "lx")
+ , ("mega", str "M")
+ , ("meter", str "m")
+ , ("metre", str "m")
+ , ("milli", str "m")
+ , ("minute", str "min")
+ , ("mmHg", str "mmHg")
+ , ("mole", str "mol")
+ , ("nano", str "n")
+ , ("nauticalmile", str "M")
+ , ("neper", str "Np")
+ , ("newton", str "N")
+ , ("ohm", str "Ω")
+ , ("Pa", str "Pa")
+ , ("pascal", str "Pa")
+ , ("percent", str "%")
+ , ("per", str "/")
+ , ("peta", str "P")
+ , ("pico", str "p")
+ , ("radian", str "rad")
+ , ("second", str "s")
+ , ("siemens", str "S")
+ , ("sievert", str "Sv")
+ , ("steradian", str "sr")
+ , ("tera", str "T")
+ , ("tesla", str "T")
+ , ("tonne", str "t")
+ , ("volt", str "V")
+ , ("watt", str "W")
+ , ("weber", str "Wb")
+ , ("yocto", str "y")
+ , ("yotta", str "Y")
+ , ("zepto", str "z")
+ , ("zetta", str "Z")
+ ]
lit :: String -> LP m Inlines
lit = pure . str
@@ -742,13 +480,31 @@ quoted' f starter ender = do
cs -> cs)
else lit startchs
-enquote :: PandocMonad m => LP m Inlines
-enquote = do
+enquote :: PandocMonad m => Bool -> Maybe Text -> LP m Inlines
+enquote starred mblang = do
skipopts
+ let lang = (T.unpack <$> mblang) >>= babelLangToBCP47
+ let langspan = case lang of
+ Nothing -> id
+ Just l -> spanWith ("",[],[("lang", renderLang l)])
quoteContext <- sQuoteContext <$> getState
- if quoteContext == InDoubleQuote
- then singleQuoted <$> withQuoteContext InSingleQuote tok
- else doubleQuoted <$> withQuoteContext InDoubleQuote tok
+ if starred || quoteContext == InDoubleQuote
+ then singleQuoted . langspan <$> withQuoteContext InSingleQuote tok
+ else doubleQuoted . langspan <$> withQuoteContext InDoubleQuote tok
+
+blockquote :: PandocMonad m => Bool -> Maybe Text -> LP m Blocks
+blockquote citations mblang = do
+ citePar <- if citations
+ then do
+ cs <- cites NormalCitation False
+ return $ para (cite cs mempty)
+ else return mempty
+ let lang = (T.unpack <$> mblang) >>= babelLangToBCP47
+ let langdiv = case lang of
+ Nothing -> id
+ Just l -> divWith ("",[],[("lang", renderLang l)])
+ bs <- grouped block
+ return $ blockQuote . langdiv $ (bs <> citePar)
doAcronym :: PandocMonad m => String -> LP m Inlines
doAcronym form = do
@@ -791,6 +547,16 @@ dolstinline :: PandocMonad m => LP m Inlines
dolstinline = do
options <- option [] keyvals
let classes = maybeToList $ lookup "language" options >>= fromListingsLanguage
+ doinlinecode classes
+
+domintinline :: PandocMonad m => LP m Inlines
+domintinline = do
+ skipopts
+ cls <- toksToString <$> braced
+ doinlinecode [cls]
+
+doinlinecode :: PandocMonad m => [String] -> LP m Inlines
+doinlinecode classes = do
Tok _ Symbol t <- anySymbol
marker <- case T.uncons t of
Just (c, ts) | T.null ts -> return c
@@ -803,246 +569,41 @@ dolstinline = do
keyval :: PandocMonad m => LP m (String, String)
keyval = try $ do
Tok _ Word key <- satisfyTok isWordTok
- let isSpecSym (Tok _ Symbol t) = t /= "]" && t /= ","
- isSpecSym _ = False
optional sp
- val <- option [] $ do
+ val <- option mempty $ do
symbol '='
optional sp
- braced <|> many1 (satisfyTok isWordTok <|> satisfyTok isSpecSym
- <|> anyControlSeq)
- optional sp
+ (untokenize <$> braced) <|>
+ (mconcat <$> many1 (
+ (untokenize . snd <$> withRaw braced)
+ <|>
+ (untokenize <$> (many1
+ (satisfyTok
+ (\t -> case t of
+ Tok _ Symbol "]" -> False
+ Tok _ Symbol "," -> False
+ Tok _ Symbol "{" -> False
+ Tok _ Symbol "}" -> False
+ _ -> True))))))
optional (symbol ',')
optional sp
- return (T.unpack key, T.unpack . untokenize $ val)
+ return (T.unpack key, T.unpack $ T.strip val)
keyvals :: PandocMonad m => LP m [(String, String)]
keyvals = try $ symbol '[' >> manyTill keyval (symbol ']')
-accent :: PandocMonad m => Char -> (Char -> String) -> LP m Inlines
-accent c f = try $ do
+accent :: PandocMonad m => Char -> Maybe Char -> LP m Inlines
+accent combiningAccent fallBack = try $ do
ils <- tok
case toList ils of
- (Str (x:xs) : ys) -> return $ fromList (Str (f x ++ xs) : ys)
- [Space] -> return $ str [c]
- [] -> return $ str [c]
+ (Str (x:xs) : ys) -> return $ fromList $
+ -- try to normalize to the combined character:
+ Str (T.unpack
+ (Normalize.normalize Normalize.NFC
+ (T.pack [x, combiningAccent])) ++ xs) : ys
+ [Space] -> return $ str [fromMaybe combiningAccent fallBack]
+ [] -> return $ str [fromMaybe combiningAccent fallBack]
_ -> return ils
-
-grave :: Char -> String
-grave 'A' = "À"
-grave 'E' = "È"
-grave 'I' = "Ì"
-grave 'O' = "Ò"
-grave 'U' = "Ù"
-grave 'a' = "à"
-grave 'e' = "è"
-grave 'i' = "ì"
-grave 'o' = "ò"
-grave 'u' = "ù"
-grave c = [c]
-
-acute :: Char -> String
-acute 'A' = "Á"
-acute 'E' = "É"
-acute 'I' = "Í"
-acute 'O' = "Ó"
-acute 'U' = "Ú"
-acute 'Y' = "Ý"
-acute 'a' = "á"
-acute 'e' = "é"
-acute 'i' = "í"
-acute 'o' = "ó"
-acute 'u' = "ú"
-acute 'y' = "ý"
-acute 'C' = "Ć"
-acute 'c' = "ć"
-acute 'L' = "Ĺ"
-acute 'l' = "ĺ"
-acute 'N' = "Ń"
-acute 'n' = "ń"
-acute 'R' = "Ŕ"
-acute 'r' = "ŕ"
-acute 'S' = "Ś"
-acute 's' = "ś"
-acute 'Z' = "Ź"
-acute 'z' = "ź"
-acute c = [c]
-
-circ :: Char -> String
-circ 'A' = "Â"
-circ 'E' = "Ê"
-circ 'I' = "Î"
-circ 'O' = "Ô"
-circ 'U' = "Û"
-circ 'a' = "â"
-circ 'e' = "ê"
-circ 'i' = "î"
-circ 'o' = "ô"
-circ 'u' = "û"
-circ 'C' = "Ĉ"
-circ 'c' = "ĉ"
-circ 'G' = "Ĝ"
-circ 'g' = "ĝ"
-circ 'H' = "Ĥ"
-circ 'h' = "ĥ"
-circ 'J' = "Ĵ"
-circ 'j' = "ĵ"
-circ 'S' = "Ŝ"
-circ 's' = "ŝ"
-circ 'W' = "Ŵ"
-circ 'w' = "ŵ"
-circ 'Y' = "Ŷ"
-circ 'y' = "ŷ"
-circ c = [c]
-
-tilde :: Char -> String
-tilde 'A' = "Ã"
-tilde 'a' = "ã"
-tilde 'O' = "Õ"
-tilde 'o' = "õ"
-tilde 'I' = "Ĩ"
-tilde 'i' = "ĩ"
-tilde 'U' = "Ũ"
-tilde 'u' = "ũ"
-tilde 'N' = "Ñ"
-tilde 'n' = "ñ"
-tilde c = [c]
-
-umlaut :: Char -> String
-umlaut 'A' = "Ä"
-umlaut 'E' = "Ë"
-umlaut 'I' = "Ï"
-umlaut 'O' = "Ö"
-umlaut 'U' = "Ü"
-umlaut 'a' = "ä"
-umlaut 'e' = "ë"
-umlaut 'i' = "ï"
-umlaut 'o' = "ö"
-umlaut 'u' = "ü"
-umlaut c = [c]
-
-hungarumlaut :: Char -> String
-hungarumlaut 'A' = "A̋"
-hungarumlaut 'E' = "E̋"
-hungarumlaut 'I' = "I̋"
-hungarumlaut 'O' = "Ő"
-hungarumlaut 'U' = "Ű"
-hungarumlaut 'Y' = "ӳ"
-hungarumlaut 'a' = "a̋"
-hungarumlaut 'e' = "e̋"
-hungarumlaut 'i' = "i̋"
-hungarumlaut 'o' = "ő"
-hungarumlaut 'u' = "ű"
-hungarumlaut 'y' = "ӳ"
-hungarumlaut c = [c]
-
-dot :: Char -> String
-dot 'C' = "Ċ"
-dot 'c' = "ċ"
-dot 'E' = "Ė"
-dot 'e' = "ė"
-dot 'G' = "Ġ"
-dot 'g' = "ġ"
-dot 'I' = "İ"
-dot 'Z' = "Ż"
-dot 'z' = "ż"
-dot c = [c]
-
-macron :: Char -> String
-macron 'A' = "Ā"
-macron 'E' = "Ē"
-macron 'I' = "Ī"
-macron 'O' = "Ō"
-macron 'U' = "Ū"
-macron 'a' = "ā"
-macron 'e' = "ē"
-macron 'i' = "ī"
-macron 'o' = "ō"
-macron 'u' = "ū"
-macron c = [c]
-
-cedilla :: Char -> String
-cedilla 'c' = "ç"
-cedilla 'C' = "Ç"
-cedilla 's' = "ş"
-cedilla 'S' = "Ş"
-cedilla 't' = "ţ"
-cedilla 'T' = "Ţ"
-cedilla 'e' = "ȩ"
-cedilla 'E' = "Ȩ"
-cedilla 'h' = "ḩ"
-cedilla 'H' = "Ḩ"
-cedilla 'o' = "o̧"
-cedilla 'O' = "O̧"
-cedilla c = [c]
-
-hacek :: Char -> String
-hacek 'A' = "Ǎ"
-hacek 'a' = "ǎ"
-hacek 'C' = "Č"
-hacek 'c' = "č"
-hacek 'D' = "Ď"
-hacek 'd' = "ď"
-hacek 'E' = "Ě"
-hacek 'e' = "ě"
-hacek 'G' = "Ǧ"
-hacek 'g' = "ǧ"
-hacek 'H' = "Ȟ"
-hacek 'h' = "ȟ"
-hacek 'I' = "Ǐ"
-hacek 'i' = "ǐ"
-hacek 'j' = "ǰ"
-hacek 'K' = "Ǩ"
-hacek 'k' = "ǩ"
-hacek 'L' = "Ľ"
-hacek 'l' = "ľ"
-hacek 'N' = "Ň"
-hacek 'n' = "ň"
-hacek 'O' = "Ǒ"
-hacek 'o' = "ǒ"
-hacek 'R' = "Ř"
-hacek 'r' = "ř"
-hacek 'S' = "Š"
-hacek 's' = "š"
-hacek 'T' = "Ť"
-hacek 't' = "ť"
-hacek 'U' = "Ǔ"
-hacek 'u' = "ǔ"
-hacek 'Z' = "Ž"
-hacek 'z' = "ž"
-hacek c = [c]
-
-ogonek :: Char -> String
-ogonek 'a' = "ą"
-ogonek 'e' = "ę"
-ogonek 'o' = "ǫ"
-ogonek 'i' = "į"
-ogonek 'u' = "ų"
-ogonek 'A' = "Ą"
-ogonek 'E' = "Ę"
-ogonek 'I' = "Į"
-ogonek 'O' = "Ǫ"
-ogonek 'U' = "Ų"
-ogonek c = [c]
-
-breve :: Char -> String
-breve 'A' = "Ă"
-breve 'a' = "ă"
-breve 'E' = "Ĕ"
-breve 'e' = "ĕ"
-breve 'G' = "Ğ"
-breve 'g' = "ğ"
-breve 'I' = "Ĭ"
-breve 'i' = "ĭ"
-breve 'O' = "Ŏ"
-breve 'o' = "ŏ"
-breve 'U' = "Ŭ"
-breve 'u' = "ŭ"
-breve c = [c]
-
-toksToString :: [Tok] -> String
-toksToString = T.unpack . untokenize
-
mathDisplay :: String -> Inlines
mathDisplay = displayMath . trim
@@ -1119,7 +680,21 @@ citationLabel = do
cites :: PandocMonad m => CitationMode -> Bool -> LP m [Citation]
cites mode multi = try $ do
cits <- if multi
- then many1 simpleCiteArgs
+ then do
+ multiprenote <- optionMaybe $ toList <$> paropt
+ multipostnote <- optionMaybe $ toList <$> paropt
+ let (pre, suf) = case (multiprenote, multipostnote) of
+ (Just s , Nothing) -> (mempty, s)
+ (Nothing , Just t) -> (mempty, t)
+ (Just s , Just t ) -> (s, t)
+ _ -> (mempty, mempty)
+ tempCits <- many1 simpleCiteArgs
+ case tempCits of
+ (k:ks) -> case ks of
+ (_:_) -> return $ ((addMprenote pre k):init ks) ++
+ [addMpostnote suf (last ks)]
+ _ -> return [addMprenote pre (addMpostnote suf k)]
+ _ -> return [[]]
else count 1 simpleCiteArgs
let cs = concat cits
return $ case mode of
@@ -1127,6 +702,17 @@ cites mode multi = try $ do
(c:rest) -> c {citationMode = mode} : rest
[] -> []
_ -> map (\a -> a {citationMode = mode}) cs
+ where mprenote (k:ks) = (k:ks) ++ [Space]
+ mprenote _ = mempty
+ mpostnote (k:ks) = [Str ",", Space] ++ (k:ks)
+ mpostnote _ = mempty
+ addMprenote mpn (k:ks) =
+ let mpnfinal = case citationPrefix k of
+ (_:_) -> mprenote mpn
+ _ -> mpn
+ in addPrefix mpnfinal (k:ks)
+ addMprenote _ _ = []
+ addMpostnote = addSuffix . mpostnote
citation :: PandocMonad m => String -> CitationMode -> Bool -> LP m Inlines
citation name mode multi = do
@@ -1181,22 +767,12 @@ tok = try $ spaces >> grouped inline <|> inlineCommand' <|> singleChar'
Tok _ _ t <- singleChar
return (str (T.unpack t))
-singleChar :: PandocMonad m => LP m Tok
-singleChar = try $ do
- Tok pos toktype t <- satisfyTok (tokTypeIn [Word, Symbol])
- guard $ not $ toktype == Symbol &&
- T.any (`Set.member` specialChars) t
- if T.length t > 1
- then do
- let (t1, t2) = (T.take 1 t, T.drop 1 t)
- inp <- getInput
- setInput $ Tok (incSourceColumn pos 1) toktype t2 : inp
- return $ Tok pos toktype t1
- else return $ Tok pos toktype t
-
opt :: PandocMonad m => LP m Inlines
opt = bracketed inline <|> (str . T.unpack <$> rawopt)
+paropt :: PandocMonad m => LP m Inlines
+paropt = parenWrapped inline
+
rawopt :: PandocMonad m => LP m Text
rawopt = do
inner <- untokenize <$> bracketedToks
@@ -1204,30 +780,28 @@ rawopt = do
return $ "[" <> inner <> "]"
skipopts :: PandocMonad m => LP m ()
-skipopts = skipMany rawopt
+skipopts = skipMany (overlaySpecification <|> void rawopt)
-- opts in angle brackets are used in beamer
-rawangle :: PandocMonad m => LP m ()
-rawangle = try $ do
+overlaySpecification :: PandocMonad m => LP m ()
+overlaySpecification = try $ do
symbol '<'
- () <$ manyTill anyTok (symbol '>')
-
-skipangles :: PandocMonad m => LP m ()
-skipangles = skipMany rawangle
-
-ignore :: (Monoid a, PandocMonad m) => String -> ParserT s u m a
-ignore raw = do
- pos <- getPosition
- report $ SkippedContent raw pos
- return mempty
-
-withRaw :: PandocMonad m => LP m a -> LP m (a, [Tok])
-withRaw parser = do
- inp <- getInput
- result <- parser
- nxt <- option (Tok (initialPos "source") Word "") (lookAhead anyTok)
- let raw = takeWhile (/= nxt) inp
- return (result, raw)
+ ts <- manyTill overlayTok (symbol '>')
+ guard $ case ts of
+ -- see issue #3368
+ [Tok _ Word s] | T.all isLetter s -> s `elem`
+ ["beamer","presentation", "trans",
+ "handout","article", "second"]
+ _ -> True
+
+overlayTok :: PandocMonad m => LP m Tok
+overlayTok =
+ satisfyTok (\t ->
+ case t of
+ Tok _ Word _ -> True
+ Tok _ Spaces _ -> True
+ Tok _ Symbol c -> c `elem` ["-","+","@","|",":",","]
+ _ -> False)
inBrackets :: Inlines -> Inlines
inBrackets x = str "[" <> x <> str "]"
@@ -1275,6 +849,12 @@ inlineEnvironments = M.fromList [
, ("align*", mathEnvWith id (Just "aligned") "align*")
, ("alignat", mathEnvWith id (Just "aligned") "alignat")
, ("alignat*", mathEnvWith id (Just "aligned") "alignat*")
+ , ("dmath", mathEnvWith id Nothing "dmath")
+ , ("dmath*", mathEnvWith id Nothing "dmath*")
+ , ("dgroup", mathEnvWith id (Just "aligned") "dgroup")
+ , ("dgroup*", mathEnvWith id (Just "aligned") "dgroup*")
+ , ("darray", mathEnvWith id (Just "aligned") "darray")
+ , ("darray*", mathEnvWith id (Just "aligned") "darray*")
]
inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines)
@@ -1289,7 +869,7 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
, ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)
, ("texttt", ttfamily)
, ("sout", extractSpaces strikeout <$> tok)
- , ("alert", skipangles >> spanWith ("",["alert"],[]) <$> tok) -- beamer
+ , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer
, ("lq", return (str "‘"))
, ("rq", return (str "’"))
, ("textquoteleft", return (str "‘"))
@@ -1318,7 +898,7 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
, ("(", mathInline . toksToString <$> manyTill anyTok (controlSeq ")"))
, ("[", mathDisplay . toksToString <$> manyTill anyTok (controlSeq "]"))
, ("ensuremath", mathInline . toksToString <$> braced)
- , ("texorpdfstring", (\_ x -> x) <$> tok <*> tok)
+ , ("texorpdfstring", (\x _ -> x) <$> tok <*> tok)
, ("P", lit "¶")
, ("S", lit "§")
, ("$", lit "$")
@@ -1361,20 +941,32 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
, ("copyright", lit "©")
, ("textasciicircum", lit "^")
, ("textasciitilde", lit "~")
- , ("H", accent '\779' hungarumlaut)
- , ("`", accent '`' grave)
- , ("'", accent '\'' acute)
- , ("^", accent '^' circ)
- , ("~", accent '~' tilde)
- , ("\"", accent '\776' umlaut)
- , (".", accent '\775' dot)
- , ("=", accent '\772' macron)
- , ("c", accent '\807' cedilla)
- , ("v", accent 'ˇ' hacek)
- , ("u", accent '\774' breve)
- , ("k", accent '\808' ogonek)
- , ("textogonekcentered", accent '\808' ogonek)
- , ("i", lit "i")
+ , ("H", accent '\779' Nothing) -- hungarumlaut
+ , ("`", accent '\768' (Just '`')) -- grave
+ , ("'", accent '\769' (Just '\'')) -- acute
+ , ("^", accent '\770' (Just '^')) -- circ
+ , ("~", accent '\771' (Just '~')) -- tilde
+ , ("\"", accent '\776' Nothing) -- umlaut
+ , (".", accent '\775' Nothing) -- dot
+ , ("=", accent '\772' Nothing) -- macron
+ , ("|", accent '\781' Nothing) -- vertical line above
+ , ("b", accent '\817' Nothing) -- macron below
+ , ("c", accent '\807' Nothing) -- cedilla
+ , ("G", accent '\783' Nothing) -- doublegrave
+ , ("h", accent '\777' Nothing) -- hookabove
+ , ("d", accent '\803' Nothing) -- dotbelow
+ , ("f", accent '\785' Nothing) -- inverted breve
+ , ("r", accent '\778' Nothing) -- ringabove
+ , ("t", accent '\865' Nothing) -- double inverted breve
+ , ("U", accent '\782' Nothing) -- double vertical line above
+ , ("v", accent '\780' Nothing) -- hacek
+ , ("u", accent '\774' Nothing) -- breve
+ , ("k", accent '\808' Nothing) -- ogonek
+ , ("textogonekcentered", accent '\808' Nothing) -- ogonek
+ , ("i", lit "ı") -- dotless i
+ , ("j", lit "ȷ") -- dotless j
+ , ("newtie", accent '\785' Nothing) -- inverted breve
+ , ("textcircled", accent '\8413' Nothing) -- combining circle
, ("\\", linebreak <$ (do inTableCell <- sInTableCell <$> getState
guard $ not inTableCell
optional opt
@@ -1392,17 +984,25 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
, ("footnote", skipopts >> note <$> grouped block)
, ("verb", doverb)
, ("lstinline", dolstinline)
+ , ("mintinline", domintinline)
, ("Verb", doverb)
- , ("url", ((unescapeURL . T.unpack . untokenize) <$> braced) >>= \url ->
+ , ("url", ((unescapeURL . T.unpack . untokenize) <$> bracedUrl) >>= \url ->
pure (link url "" (str url)))
, ("href", (unescapeURL . toksToString <$>
- braced <* optional sp) >>= \url ->
+ bracedUrl <* optional sp) >>= \url ->
tok >>= \lab -> pure (link url "" lab))
, ("includegraphics", do options <- option [] keyvals
src <- unescapeURL . T.unpack .
removeDoubleQuotes . untokenize <$> braced
mkImage options src)
- , ("enquote", enquote)
+ , ("enquote*", enquote True Nothing)
+ , ("enquote", enquote False Nothing)
+ -- foreignquote is supposed to use native quote marks
+ , ("foreignquote*", braced >>= enquote True . Just . untokenize)
+ , ("foreignquote", braced >>= enquote False . Just . untokenize)
+ -- hypehnquote uses regular quotes
+ , ("hyphenquote*", braced >>= enquote True . Just . untokenize)
+ , ("hyphenquote", braced >>= enquote False . Just . untokenize)
, ("figurename", doTerm Translations.Figure)
, ("prefacename", doTerm Translations.Preface)
, ("refname", doTerm Translations.References)
@@ -1507,13 +1107,6 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
, ("acsp", doAcronymPlural "abbrv")
-- siuntix
, ("SI", dosiunitx)
- -- units of siuntix
- , ("celsius", lit "°C")
- , ("degreeCelsius", lit "°C")
- , ("gram", lit "g")
- , ("meter", lit "m")
- , ("milli", lit "m")
- , ("square", dosquare)
-- hyphenat
, ("bshyp", lit "\\\173")
, ("fshyp", lit "/\173")
@@ -1542,8 +1135,18 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
, ("Rn", romanNumeralLower)
-- babel
, ("foreignlanguage", foreignlanguage)
+ -- include
+ , ("input", include "input")
+ -- plain tex stuff that should just be passed through as raw tex
+ , ("ifdim", ifdim)
]
+ifdim :: PandocMonad m => LP m Inlines
+ifdim = do
+ contents <- manyTill anyTok (controlSeq "fi")
+ return $ rawInline "latex" $ T.unpack $
+ "\\ifdim" <> untokenize contents <> "\\fi"
+
makeUppercase :: Inlines -> Inlines
makeUppercase = fromList . walk (alterStr (map toUpper)) . toList
@@ -1693,7 +1296,6 @@ getRawCommand name txt = do
"def" ->
void $ manyTill anyTok braced
_ -> do
- skipangles
skipopts
option "" (try (optional sp *> dimenarg))
void $ many braced
@@ -1818,7 +1420,6 @@ end_ t = try (do
preamble :: PandocMonad m => LP m Blocks
preamble = mempty <$ many preambleBlock
where preambleBlock = spaces1
- <|> void include
<|> void macroDef
<|> void blockCommand
<|> void braced
@@ -1831,11 +1432,8 @@ paragraph = do
then return mempty
else return $ para x
-include :: PandocMonad m => LP m Blocks
-include = do
- (Tok _ (CtrlSeq name) _) <-
- controlSeq "include" <|> controlSeq "input" <|>
- controlSeq "subfile" <|> controlSeq "usepackage"
+include :: (PandocMonad m, Monoid a) => Text -> LP m a
+include name = do
skipMany opt
fs <- (map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .
untokenize) <$> braced
@@ -1912,31 +1510,28 @@ letmacro = do
optional $ symbol '='
spaces
contents <- bracedOrToken
- return (name, Macro ExpandWhenDefined 0 Nothing contents)
+ return (name, Macro ExpandWhenDefined [] Nothing contents)
defmacro :: PandocMonad m => LP m (Text, Macro)
defmacro = try $ do
controlSeq "def"
Tok _ (CtrlSeq name) _ <- anyControlSeq
- numargs <- option 0 $ argSeq 1
+ argspecs <- many (argspecArg <|> argspecPattern)
-- we use withVerbatimMode, because macros are to be expanded
-- at point of use, not point of definition
contents <- withVerbatimMode bracedOrToken
- return (name, Macro ExpandWhenUsed numargs Nothing contents)
+ return (name, Macro ExpandWhenUsed argspecs Nothing contents)
--- Note: we don't yet support fancy things like #1.#2
-argSeq :: PandocMonad m => Int -> LP m Int
-argSeq n = do
+argspecArg :: PandocMonad m => LP m ArgSpec
+argspecArg = do
Tok _ (Arg i) _ <- satisfyTok isArgTok
- guard $ i == n
- argSeq (n+1) <|> return n
+ return $ ArgNum i
-isArgTok :: Tok -> Bool
-isArgTok (Tok _ (Arg _) _) = True
-isArgTok _ = False
-
-bracedOrToken :: PandocMonad m => LP m [Tok]
-bracedOrToken = braced <|> ((:[]) <$> (anyControlSeq <|> singleChar))
+argspecPattern :: PandocMonad m => LP m ArgSpec
+argspecPattern =
+ Pattern <$> many1 (satisfyTok (\(Tok _ toktype' txt) ->
+ (toktype' == Symbol || toktype' == Word) &&
+ (txt /= "{" && txt /= "\\" && txt /= "}")))
newcommand :: PandocMonad m => LP m (Text, Macro)
newcommand = do
@@ -1950,6 +1545,7 @@ newcommand = do
(symbol '{' *> spaces *> anyControlSeq <* spaces <* symbol '}')
spaces
numargs <- option 0 $ try bracketedNum
+ let argspecs = map (\i -> ArgNum i) [1..numargs]
spaces
optarg <- option Nothing $ Just <$> try bracketedToks
spaces
@@ -1959,7 +1555,7 @@ newcommand = do
case M.lookup name macros of
Just _ -> report $ MacroAlreadyDefined (T.unpack txt) pos
Nothing -> return ()
- return (name, Macro ExpandWhenUsed numargs optarg contents)
+ return (name, Macro ExpandWhenUsed argspecs optarg contents)
newenvironment :: PandocMonad m => LP m (Text, Macro, Macro)
newenvironment = do
@@ -1972,6 +1568,7 @@ newenvironment = do
name <- untokenize <$> braced
spaces
numargs <- option 0 $ try bracketedNum
+ let argspecs = map (\i -> ArgNum i) [1..numargs]
spaces
optarg <- option Nothing $ Just <$> try bracketedToks
spaces
@@ -1983,13 +1580,8 @@ newenvironment = do
case M.lookup name macros of
Just _ -> report $ MacroAlreadyDefined (T.unpack name) pos
Nothing -> return ()
- return (name, Macro ExpandWhenUsed numargs optarg startcontents,
- Macro ExpandWhenUsed 0 Nothing endcontents)
-
-bracketedToks :: PandocMonad m => LP m [Tok]
-bracketedToks = do
- symbol '['
- mconcat <$> manyTill (braced <|> (:[]) <$> anyTok) (symbol ']')
+ return (name, Macro ExpandWhenUsed argspecs optarg startcontents,
+ Macro ExpandWhenUsed [] Nothing endcontents)
bracketedNum :: PandocMonad m => LP m Int
bracketedNum = do
@@ -2003,11 +1595,13 @@ setCaption = do
ils <- tok
mblabel <- option Nothing $
try $ spaces >> controlSeq "label" >> (Just <$> tok)
- let ils' = case mblabel of
- Just lab -> ils <> spanWith
- ("",[],[("label", stringify lab)]) mempty
- Nothing -> ils
- updateState $ \st -> st{ sCaption = Just ils' }
+ let capt = case mblabel of
+ Just lab -> let slab = stringify lab
+ ils' = ils <> spanWith
+ ("",[],[("label", slab)]) mempty
+ in (Just ils', Just slab)
+ Nothing -> (Just ils, Nothing)
+ updateState $ \st -> st{ sCaption = capt }
return mempty
looseItem :: PandocMonad m => LP m Blocks
@@ -2018,28 +1612,27 @@ looseItem = do
return mempty
resetCaption :: PandocMonad m => LP m ()
-resetCaption = updateState $ \st -> st{ sCaption = Nothing }
+resetCaption = updateState $ \st -> st{ sCaption = (Nothing, Nothing) }
-section :: PandocMonad m => Bool -> Attr -> Int -> LP m Blocks
-section starred (ident, classes, kvs) lvl = do
+section :: PandocMonad m => Attr -> Int -> LP m Blocks
+section (ident, classes, kvs) lvl = do
skipopts
contents <- grouped inline
lab <- option ident $
try (spaces >> controlSeq "label"
>> spaces >> toksToString <$> braced)
- let classes' = if starred then "unnumbered" : classes else classes
when (lvl == 0) $
updateState $ \st -> st{ sHasChapters = True }
- unless starred $ do
+ unless ("unnumbered" `elem` classes) $ do
hn <- sLastHeaderNum <$> getState
hasChapters <- sHasChapters <$> getState
let lvl' = lvl + if hasChapters then 1 else 0
- let num = incrementHeaderNum lvl' hn
- updateState $ \st -> st{ sLastHeaderNum = num }
- updateState $ \st -> st{ sLabels = M.insert lab
- [Str (renderHeaderNum num)]
- (sLabels st) }
- attr' <- registerHeader (lab, classes', kvs) contents
+ let num = incrementDottedNum lvl' hn
+ updateState $ \st -> st{ sLastHeaderNum = num
+ , sLabels = M.insert lab
+ [Str (renderDottedNum num)]
+ (sLabels st) }
+ attr' <- registerHeader (lab, classes, kvs) contents
return $ headerWith attr' lvl contents
blockCommand :: PandocMonad m => LP m Blocks
@@ -2100,23 +1693,23 @@ blockCommands = M.fromList
-- Koma-script metadata commands
, ("dedication", mempty <$ (skipopts *> tok >>= addMeta "dedication"))
-- sectioning
- , ("part", section False nullAttr (-1))
- , ("part*", section True nullAttr (-1))
- , ("chapter", section False nullAttr 0)
- , ("chapter*", section True ("",["unnumbered"],[]) 0)
- , ("section", section False nullAttr 1)
- , ("section*", section True ("",["unnumbered"],[]) 1)
- , ("subsection", section False nullAttr 2)
- , ("subsection*", section True ("",["unnumbered"],[]) 2)
- , ("subsubsection", section False nullAttr 3)
- , ("subsubsection*", section True ("",["unnumbered"],[]) 3)
- , ("paragraph", section False nullAttr 4)
- , ("paragraph*", section True ("",["unnumbered"],[]) 4)
- , ("subparagraph", section False nullAttr 5)
- , ("subparagraph*", section True ("",["unnumbered"],[]) 5)
+ , ("part", section nullAttr (-1))
+ , ("part*", section nullAttr (-1))
+ , ("chapter", section nullAttr 0)
+ , ("chapter*", section ("",["unnumbered"],[]) 0)
+ , ("section", section nullAttr 1)
+ , ("section*", section ("",["unnumbered"],[]) 1)
+ , ("subsection", section nullAttr 2)
+ , ("subsection*", section ("",["unnumbered"],[]) 2)
+ , ("subsubsection", section nullAttr 3)
+ , ("subsubsection*", section ("",["unnumbered"],[]) 3)
+ , ("paragraph", section nullAttr 4)
+ , ("paragraph*", section ("",["unnumbered"],[]) 4)
+ , ("subparagraph", section nullAttr 5)
+ , ("subparagraph*", section ("",["unnumbered"],[]) 5)
-- beamer slides
- , ("frametitle", section False nullAttr 3)
- , ("framesubtitle", section False nullAttr 4)
+ , ("frametitle", section nullAttr 3)
+ , ("framesubtitle", section nullAttr 4)
-- letters
, ("opening", (para . trimInlines) <$> (skipopts *> tok))
, ("closing", skipopts *> closing)
@@ -2152,6 +1745,18 @@ blockCommands = M.fromList
-- LaTeX colors
, ("textcolor", coloredBlock "color")
, ("colorbox", coloredBlock "background-color")
+ -- csquotes
+ , ("blockquote", blockquote False Nothing)
+ , ("blockcquote", blockquote True Nothing)
+ , ("foreignblockquote", braced >>= blockquote False . Just . untokenize)
+ , ("foreignblockcquote", braced >>= blockquote True . Just . untokenize)
+ , ("hyphenblockquote", braced >>= blockquote False . Just . untokenize)
+ , ("hyphenblockcquote", braced >>= blockquote True . Just . untokenize)
+ -- include
+ , ("include", include "include")
+ , ("input", include "input")
+ , ("subfile", include "subfile")
+ , ("usepackage", include "usepackage")
]
@@ -2192,6 +1797,7 @@ environments = M.fromList
, ("minted", minted)
, ("obeylines", obeylines)
, ("tikzpicture", rawVerbEnv "tikzpicture")
+ , ("lilypond", rawVerbEnv "lilypond")
-- etoolbox
, ("ifstrequal", ifstrequal)
, ("newtoggle", braced >>= newToggle)
@@ -2234,7 +1840,7 @@ rawVerbEnv :: PandocMonad m => Text -> LP m Blocks
rawVerbEnv name = do
pos <- getPosition
(_, raw) <- withRaw $ verbEnv name
- let raw' = "\\begin{tikzpicture}" ++ toksToString raw
+ let raw' = "\\begin{" ++ T.unpack name ++ "}" ++ toksToString raw
exts <- getOption readerExtensions
let parseRaw = extensionEnabled Ext_raw_tex exts
if parseRaw
@@ -2248,7 +1854,20 @@ verbEnv name = withVerbatimMode $ do
skipopts
optional blankline
res <- manyTill anyTok (end_ name)
- return $ stripTrailingNewlines $ toksToString res
+ return $ T.unpack
+ $ stripTrailingNewline
+ $ untokenize
+ $ res
+
+-- Strip single final newline and any spaces following it.
+-- Input is unchanged if it doesn't end with newline +
+-- optional spaces.
+stripTrailingNewline :: Text -> Text
+stripTrailingNewline t =
+ let (b, e) = T.breakOnEnd "\n" t
+ in if T.all (== ' ') e
+ then T.dropEnd 1 b
+ else t
fancyverbEnv :: PandocMonad m => Text -> LP m Blocks
fancyverbEnv name = do
@@ -2303,12 +1922,43 @@ figure = try $ do
addImageCaption :: PandocMonad m => Blocks -> LP m Blocks
addImageCaption = walkM go
- where go (Image attr alt (src,tit))
+ where go (Image attr@(_, cls, kvs) alt (src,tit))
| not ("fig:" `isPrefixOf` tit) = do
- mbcapt <- sCaption <$> getState
- return $ case mbcapt of
- Just ils -> Image attr (toList ils) (src, "fig:" ++ tit)
- Nothing -> Image attr alt (src,tit)
+ (mbcapt, mblab) <- sCaption <$> getState
+ let (alt', tit') = case mbcapt of
+ Just ils -> (toList ils, "fig:" ++ tit)
+ Nothing -> (alt, tit)
+ attr' = case mblab of
+ Just lab -> (lab, cls, kvs)
+ Nothing -> attr
+ case attr' of
+ ("", _, _) -> return ()
+ (ident, _, _) -> do
+ st <- getState
+ let chapnum =
+ case (sHasChapters st, sLastHeaderNum st) of
+ (True, DottedNum (n:_)) -> Just n
+ _ -> Nothing
+ let num = case sLastFigureNum st of
+ DottedNum [m,n] ->
+ case chapnum of
+ Just m' | m' == m -> DottedNum [m, n+1]
+ | otherwise -> DottedNum [m', 1]
+ Nothing -> DottedNum [1]
+ -- shouldn't happen
+ DottedNum [n] ->
+ case chapnum of
+ Just m -> DottedNum [m, 1]
+ Nothing -> DottedNum [n + 1]
+ _ ->
+ case chapnum of
+ Just n -> DottedNum [n, 1]
+ Nothing -> DottedNum [1]
+ setState $
+ st{ sLastFigureNum = num
+ , sLabels = M.insert ident
+ [Str (renderDottedNum num)] (sLabels st) }
+ return $ Image attr' alt' (src, tit')
go x = return x
coloredBlock :: PandocMonad m => String -> LP m Blocks
@@ -2321,7 +1971,8 @@ coloredBlock stylename = try $ do
graphicsPath :: PandocMonad m => LP m Blocks
graphicsPath = do
- ps <- map toksToString <$> (bgroup *> manyTill braced egroup)
+ ps <- map toksToString <$>
+ (bgroup *> spaces *> manyTill (braced <* spaces) egroup)
getResourcePath >>= setResourcePath . (++ ps)
return mempty
@@ -2579,7 +2230,7 @@ simpTable envname hasWidthParameter = try $ do
addTableCaption :: PandocMonad m => Blocks -> LP m Blocks
addTableCaption = walkM go
where go (Table c als ws hs rs) = do
- mbcapt <- sCaption <$> getState
+ (mbcapt, _) <- sCaption <$> getState
return $ case mbcapt of
Just ils -> Table (toList ils) als ws hs rs
Nothing -> Table c als ws hs rs
@@ -2590,7 +2241,6 @@ block :: PandocMonad m => LP m Blocks
block = do
res <- (mempty <$ spaces1)
<|> environment
- <|> include
<|> macroDef
<|> blockCommand
<|> paragraph
@@ -2613,137 +2263,3 @@ setDefaultLanguage = do
setTranslations l
updateState $ setMeta "lang" $ str (renderLang l)
return mempty
-
-polyglossiaLangToBCP47 :: M.Map String (String -> Lang)
-polyglossiaLangToBCP47 = M.fromList
- [ ("arabic", \o -> case filter (/=' ') o of
- "locale=algeria" -> Lang "ar" "" "DZ" []
- "locale=mashriq" -> Lang "ar" "" "SY" []
- "locale=libya" -> Lang "ar" "" "LY" []
- "locale=morocco" -> Lang "ar" "" "MA" []
- "locale=mauritania" -> Lang "ar" "" "MR" []
- "locale=tunisia" -> Lang "ar" "" "TN" []
- _ -> Lang "ar" "" "" [])
- , ("german", \o -> case filter (/=' ') o of
- "spelling=old" -> Lang "de" "" "DE" ["1901"]
- "variant=austrian,spelling=old"
- -> Lang "de" "" "AT" ["1901"]
- "variant=austrian" -> Lang "de" "" "AT" []
- "variant=swiss,spelling=old"
- -> Lang "de" "" "CH" ["1901"]
- "variant=swiss" -> Lang "de" "" "CH" []
- _ -> Lang "de" "" "" [])
- , ("lsorbian", \_ -> Lang "dsb" "" "" [])
- , ("greek", \o -> case filter (/=' ') o of
- "variant=poly" -> Lang "el" "" "polyton" []
- "variant=ancient" -> Lang "grc" "" "" []
- _ -> Lang "el" "" "" [])
- , ("english", \o -> case filter (/=' ') o of
- "variant=australian" -> Lang "en" "" "AU" []
- "variant=canadian" -> Lang "en" "" "CA" []
- "variant=british" -> Lang "en" "" "GB" []
- "variant=newzealand" -> Lang "en" "" "NZ" []
- "variant=american" -> Lang "en" "" "US" []
- _ -> Lang "en" "" "" [])
- , ("usorbian", \_ -> Lang "hsb" "" "" [])
- , ("latin", \o -> case filter (/=' ') o of
- "variant=classic" -> Lang "la" "" "" ["x-classic"]
- _ -> Lang "la" "" "" [])
- , ("slovenian", \_ -> Lang "sl" "" "" [])
- , ("serbianc", \_ -> Lang "sr" "cyrl" "" [])
- , ("pinyin", \_ -> Lang "zh" "Latn" "" ["pinyin"])
- , ("afrikaans", \_ -> Lang "af" "" "" [])
- , ("amharic", \_ -> Lang "am" "" "" [])
- , ("assamese", \_ -> Lang "as" "" "" [])
- , ("asturian", \_ -> Lang "ast" "" "" [])
- , ("bulgarian", \_ -> Lang "bg" "" "" [])
- , ("bengali", \_ -> Lang "bn" "" "" [])
- , ("tibetan", \_ -> Lang "bo" "" "" [])
- , ("breton", \_ -> Lang "br" "" "" [])
- , ("catalan", \_ -> Lang "ca" "" "" [])
- , ("welsh", \_ -> Lang "cy" "" "" [])
- , ("czech", \_ -> Lang "cs" "" "" [])
- , ("coptic", \_ -> Lang "cop" "" "" [])
- , ("danish", \_ -> Lang "da" "" "" [])
- , ("divehi", \_ -> Lang "dv" "" "" [])
- , ("esperanto", \_ -> Lang "eo" "" "" [])
- , ("spanish", \_ -> Lang "es" "" "" [])
- , ("estonian", \_ -> Lang "et" "" "" [])
- , ("basque", \_ -> Lang "eu" "" "" [])
- , ("farsi", \_ -> Lang "fa" "" "" [])
- , ("finnish", \_ -> Lang "fi" "" "" [])
- , ("french", \_ -> Lang "fr" "" "" [])
- , ("friulan", \_ -> Lang "fur" "" "" [])
- , ("irish", \_ -> Lang "ga" "" "" [])
- , ("scottish", \_ -> Lang "gd" "" "" [])
- , ("ethiopic", \_ -> Lang "gez" "" "" [])
- , ("galician", \_ -> Lang "gl" "" "" [])
- , ("hebrew", \_ -> Lang "he" "" "" [])
- , ("hindi", \_ -> Lang "hi" "" "" [])
- , ("croatian", \_ -> Lang "hr" "" "" [])
- , ("magyar", \_ -> Lang "hu" "" "" [])
- , ("armenian", \_ -> Lang "hy" "" "" [])
- , ("interlingua", \_ -> Lang "ia" "" "" [])
- , ("indonesian", \_ -> Lang "id" "" "" [])
- , ("icelandic", \_ -> Lang "is" "" "" [])
- , ("italian", \_ -> Lang "it" "" "" [])
- , ("japanese", \_ -> Lang "jp" "" "" [])
- , ("khmer", \_ -> Lang "km" "" "" [])
- , ("kurmanji", \_ -> Lang "kmr" "" "" [])
- , ("kannada", \_ -> Lang "kn" "" "" [])
- , ("korean", \_ -> Lang "ko" "" "" [])
- , ("lao", \_ -> Lang "lo" "" "" [])
- , ("lithuanian", \_ -> Lang "lt" "" "" [])
- , ("latvian", \_ -> Lang "lv" "" "" [])
- , ("malayalam", \_ -> Lang "ml" "" "" [])
- , ("mongolian", \_ -> Lang "mn" "" "" [])
- , ("marathi", \_ -> Lang "mr" "" "" [])
- , ("dutch", \_ -> Lang "nl" "" "" [])
- , ("nynorsk", \_ -> Lang "nn" "" "" [])
- , ("norsk", \_ -> Lang "no" "" "" [])
- , ("nko", \_ -> Lang "nqo" "" "" [])
- , ("occitan", \_ -> Lang "oc" "" "" [])
- , ("panjabi", \_ -> Lang "pa" "" "" [])
- , ("polish", \_ -> Lang "pl" "" "" [])
- , ("piedmontese", \_ -> Lang "pms" "" "" [])
- , ("portuguese", \_ -> Lang "pt" "" "" [])
- , ("romansh", \_ -> Lang "rm" "" "" [])
- , ("romanian", \_ -> Lang "ro" "" "" [])
- , ("russian", \_ -> Lang "ru" "" "" [])
- , ("sanskrit", \_ -> Lang "sa" "" "" [])
- , ("samin", \_ -> Lang "se" "" "" [])
- , ("slovak", \_ -> Lang "sk" "" "" [])
- , ("albanian", \_ -> Lang "sq" "" "" [])
- , ("serbian", \_ -> Lang "sr" "" "" [])
- , ("swedish", \_ -> Lang "sv" "" "" [])
- , ("syriac", \_ -> Lang "syr" "" "" [])
- , ("tamil", \_ -> Lang "ta" "" "" [])
- , ("telugu", \_ -> Lang "te" "" "" [])
- , ("thai", \_ -> Lang "th" "" "" [])
- , ("turkmen", \_ -> Lang "tk" "" "" [])
- , ("turkish", \_ -> Lang "tr" "" "" [])
- , ("ukrainian", \_ -> Lang "uk" "" "" [])
- , ("urdu", \_ -> Lang "ur" "" "" [])
- , ("vietnamese", \_ -> Lang "vi" "" "" [])
- ]
-
-babelLangToBCP47 :: String -> Maybe Lang
-babelLangToBCP47 s =
- case s of
- "austrian" -> Just $ Lang "de" "" "AT" ["1901"]
- "naustrian" -> Just $ Lang "de" "" "AT" []
- "swissgerman" -> Just $ Lang "de" "" "CH" ["1901"]
- "nswissgerman" -> Just $ Lang "de" "" "CH" []
- "german" -> Just $ Lang "de" "" "DE" ["1901"]
- "ngerman" -> Just $ Lang "de" "" "DE" []
- "lowersorbian" -> Just $ Lang "dsb" "" "" []
- "uppersorbian" -> Just $ Lang "hsb" "" "" []
- "polutonikogreek" -> Just $ Lang "el" "" "" ["polyton"]
- "slovene" -> Just $ Lang "sl" "" "" []
- "australian" -> Just $ Lang "en" "" "AU" []
- "canadian" -> Just $ Lang "en" "" "CA" []
- "british" -> Just $ Lang "en" "" "GB" []
- "newzealand" -> Just $ Lang "en" "" "NZ" []
- "american" -> Just $ Lang "en" "" "US" []
- "classiclatin" -> Just $ Lang "la" "" "" ["x-classic"]
- _ -> fmap ($ "") $ M.lookup s polyglossiaLangToBCP47
diff --git a/src/Text/Pandoc/Readers/LaTeX/Lang.hs b/src/Text/Pandoc/Readers/LaTeX/Lang.hs
new file mode 100644
index 000000000..9b57c98fd
--- /dev/null
+++ b/src/Text/Pandoc/Readers/LaTeX/Lang.hs
@@ -0,0 +1,173 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-
+Copyright (C) 2018 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.Readers.LaTeX.Lang
+ Copyright : Copyright (C) 2018 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+Functions for parsing polyglossia and babel language specifiers to
+BCP47 'Lang'.
+-}
+module Text.Pandoc.Readers.LaTeX.Lang
+ ( polyglossiaLangToBCP47
+ , babelLangToBCP47
+ )
+where
+import Prelude
+import qualified Data.Map as M
+import Text.Pandoc.BCP47 (Lang(..))
+
+polyglossiaLangToBCP47 :: M.Map String (String -> Lang)
+polyglossiaLangToBCP47 = M.fromList
+ [ ("arabic", \o -> case filter (/=' ') o of
+ "locale=algeria" -> Lang "ar" "" "DZ" []
+ "locale=mashriq" -> Lang "ar" "" "SY" []
+ "locale=libya" -> Lang "ar" "" "LY" []
+ "locale=morocco" -> Lang "ar" "" "MA" []
+ "locale=mauritania" -> Lang "ar" "" "MR" []
+ "locale=tunisia" -> Lang "ar" "" "TN" []
+ _ -> Lang "ar" "" "" [])
+ , ("german", \o -> case filter (/=' ') o of
+ "spelling=old" -> Lang "de" "" "DE" ["1901"]
+ "variant=austrian,spelling=old"
+ -> Lang "de" "" "AT" ["1901"]
+ "variant=austrian" -> Lang "de" "" "AT" []
+ "variant=swiss,spelling=old"
+ -> Lang "de" "" "CH" ["1901"]
+ "variant=swiss" -> Lang "de" "" "CH" []
+ _ -> Lang "de" "" "" [])
+ , ("lsorbian", \_ -> Lang "dsb" "" "" [])
+ , ("greek", \o -> case filter (/=' ') o of
+ "variant=poly" -> Lang "el" "" "polyton" []
+ "variant=ancient" -> Lang "grc" "" "" []
+ _ -> Lang "el" "" "" [])
+ , ("english", \o -> case filter (/=' ') o of
+ "variant=australian" -> Lang "en" "" "AU" []
+ "variant=canadian" -> Lang "en" "" "CA" []
+ "variant=british" -> Lang "en" "" "GB" []
+ "variant=newzealand" -> Lang "en" "" "NZ" []
+ "variant=american" -> Lang "en" "" "US" []
+ _ -> Lang "en" "" "" [])
+ , ("usorbian", \_ -> Lang "hsb" "" "" [])
+ , ("latin", \o -> case filter (/=' ') o of
+ "variant=classic" -> Lang "la" "" "" ["x-classic"]
+ _ -> Lang "la" "" "" [])
+ , ("slovenian", \_ -> Lang "sl" "" "" [])
+ , ("serbianc", \_ -> Lang "sr" "cyrl" "" [])
+ , ("pinyin", \_ -> Lang "zh" "Latn" "" ["pinyin"])
+ , ("afrikaans", \_ -> Lang "af" "" "" [])
+ , ("amharic", \_ -> Lang "am" "" "" [])
+ , ("assamese", \_ -> Lang "as" "" "" [])
+ , ("asturian", \_ -> Lang "ast" "" "" [])
+ , ("bulgarian", \_ -> Lang "bg" "" "" [])
+ , ("bengali", \_ -> Lang "bn" "" "" [])
+ , ("tibetan", \_ -> Lang "bo" "" "" [])
+ , ("breton", \_ -> Lang "br" "" "" [])
+ , ("catalan", \_ -> Lang "ca" "" "" [])
+ , ("welsh", \_ -> Lang "cy" "" "" [])
+ , ("czech", \_ -> Lang "cs" "" "" [])
+ , ("coptic", \_ -> Lang "cop" "" "" [])
+ , ("danish", \_ -> Lang "da" "" "" [])
+ , ("divehi", \_ -> Lang "dv" "" "" [])
+ , ("esperanto", \_ -> Lang "eo" "" "" [])
+ , ("spanish", \_ -> Lang "es" "" "" [])
+ , ("estonian", \_ -> Lang "et" "" "" [])
+ , ("basque", \_ -> Lang "eu" "" "" [])
+ , ("farsi", \_ -> Lang "fa" "" "" [])
+ , ("finnish", \_ -> Lang "fi" "" "" [])
+ , ("french", \_ -> Lang "fr" "" "" [])
+ , ("friulan", \_ -> Lang "fur" "" "" [])
+ , ("irish", \_ -> Lang "ga" "" "" [])
+ , ("scottish", \_ -> Lang "gd" "" "" [])
+ , ("ethiopic", \_ -> Lang "gez" "" "" [])
+ , ("galician", \_ -> Lang "gl" "" "" [])
+ , ("hebrew", \_ -> Lang "he" "" "" [])
+ , ("hindi", \_ -> Lang "hi" "" "" [])
+ , ("croatian", \_ -> Lang "hr" "" "" [])
+ , ("magyar", \_ -> Lang "hu" "" "" [])
+ , ("armenian", \_ -> Lang "hy" "" "" [])
+ , ("interlingua", \_ -> Lang "ia" "" "" [])
+ , ("indonesian", \_ -> Lang "id" "" "" [])
+ , ("icelandic", \_ -> Lang "is" "" "" [])
+ , ("italian", \_ -> Lang "it" "" "" [])
+ , ("japanese", \_ -> Lang "jp" "" "" [])
+ , ("khmer", \_ -> Lang "km" "" "" [])
+ , ("kurmanji", \_ -> Lang "kmr" "" "" [])
+ , ("kannada", \_ -> Lang "kn" "" "" [])
+ , ("korean", \_ -> Lang "ko" "" "" [])
+ , ("lao", \_ -> Lang "lo" "" "" [])
+ , ("lithuanian", \_ -> Lang "lt" "" "" [])
+ , ("latvian", \_ -> Lang "lv" "" "" [])
+ , ("malayalam", \_ -> Lang "ml" "" "" [])
+ , ("mongolian", \_ -> Lang "mn" "" "" [])
+ , ("marathi", \_ -> Lang "mr" "" "" [])
+ , ("dutch", \_ -> Lang "nl" "" "" [])
+ , ("nynorsk", \_ -> Lang "nn" "" "" [])
+ , ("norsk", \_ -> Lang "no" "" "" [])
+ , ("nko", \_ -> Lang "nqo" "" "" [])
+ , ("occitan", \_ -> Lang "oc" "" "" [])
+ , ("panjabi", \_ -> Lang "pa" "" "" [])
+ , ("polish", \_ -> Lang "pl" "" "" [])
+ , ("piedmontese", \_ -> Lang "pms" "" "" [])
+ , ("portuguese", \_ -> Lang "pt" "" "" [])
+ , ("romansh", \_ -> Lang "rm" "" "" [])
+ , ("romanian", \_ -> Lang "ro" "" "" [])
+ , ("russian", \_ -> Lang "ru" "" "" [])
+ , ("sanskrit", \_ -> Lang "sa" "" "" [])
+ , ("samin", \_ -> Lang "se" "" "" [])
+ , ("slovak", \_ -> Lang "sk" "" "" [])
+ , ("albanian", \_ -> Lang "sq" "" "" [])
+ , ("serbian", \_ -> Lang "sr" "" "" [])
+ , ("swedish", \_ -> Lang "sv" "" "" [])
+ , ("syriac", \_ -> Lang "syr" "" "" [])
+ , ("tamil", \_ -> Lang "ta" "" "" [])
+ , ("telugu", \_ -> Lang "te" "" "" [])
+ , ("thai", \_ -> Lang "th" "" "" [])
+ , ("turkmen", \_ -> Lang "tk" "" "" [])
+ , ("turkish", \_ -> Lang "tr" "" "" [])
+ , ("ukrainian", \_ -> Lang "uk" "" "" [])
+ , ("urdu", \_ -> Lang "ur" "" "" [])
+ , ("vietnamese", \_ -> Lang "vi" "" "" [])
+ ]
+
+babelLangToBCP47 :: String -> Maybe Lang
+babelLangToBCP47 s =
+ case s of
+ "austrian" -> Just $ Lang "de" "" "AT" ["1901"]
+ "naustrian" -> Just $ Lang "de" "" "AT" []
+ "swissgerman" -> Just $ Lang "de" "" "CH" ["1901"]
+ "nswissgerman" -> Just $ Lang "de" "" "CH" []
+ "german" -> Just $ Lang "de" "" "DE" ["1901"]
+ "ngerman" -> Just $ Lang "de" "" "DE" []
+ "lowersorbian" -> Just $ Lang "dsb" "" "" []
+ "uppersorbian" -> Just $ Lang "hsb" "" "" []
+ "polutonikogreek" -> Just $ Lang "el" "" "" ["polyton"]
+ "slovene" -> Just $ Lang "sl" "" "" []
+ "australian" -> Just $ Lang "en" "" "AU" []
+ "canadian" -> Just $ Lang "en" "" "CA" []
+ "british" -> Just $ Lang "en" "" "GB" []
+ "newzealand" -> Just $ Lang "en" "" "NZ" []
+ "american" -> Just $ Lang "en" "" "US" []
+ "classiclatin" -> Just $ Lang "la" "" "" ["x-classic"]
+ _ -> fmap ($ "") $ M.lookup s polyglossiaLangToBCP47
diff --git a/src/Text/Pandoc/Readers/LaTeX/Parsing.hs b/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
new file mode 100644
index 000000000..9256217fe
--- /dev/null
+++ b/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
@@ -0,0 +1,668 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-
+Copyright (C) 2006-2018 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.Readers.LaTeX.Parsing
+ Copyright : Copyright (C) 2006-2018 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+General parsing types and functions for LaTeX.
+-}
+module Text.Pandoc.Readers.LaTeX.Parsing
+ ( DottedNum(..)
+ , renderDottedNum
+ , incrementDottedNum
+ , LaTeXState(..)
+ , defaultLaTeXState
+ , LP
+ , withVerbatimMode
+ , rawLaTeXParser
+ , applyMacros
+ , tokenize
+ , untokenize
+ , untoken
+ , totoks
+ , toksToString
+ , satisfyTok
+ , doMacros
+ , setpos
+ , anyControlSeq
+ , anySymbol
+ , isNewlineTok
+ , isWordTok
+ , isArgTok
+ , spaces
+ , spaces1
+ , tokTypeIn
+ , controlSeq
+ , symbol
+ , symbolIn
+ , sp
+ , whitespace
+ , newlineTok
+ , comment
+ , anyTok
+ , singleChar
+ , specialChars
+ , endline
+ , blankline
+ , primEscape
+ , bgroup
+ , egroup
+ , grouped
+ , braced
+ , braced'
+ , bracedUrl
+ , bracedOrToken
+ , bracketed
+ , bracketedToks
+ , parenWrapped
+ , dimenarg
+ , ignore
+ , withRaw
+ ) where
+
+import Prelude
+import Control.Applicative (many, (<|>))
+import Control.Monad
+import Control.Monad.Except (throwError)
+import Control.Monad.Trans (lift)
+import Data.Char (chr, isAlphaNum, isDigit, isLetter, ord)
+import Data.Default
+import Data.List (intercalate)
+import qualified Data.Map as M
+import qualified Data.Set as Set
+import Data.Text (Text)
+import qualified Data.Text as T
+import Text.Pandoc.Builder
+import Text.Pandoc.Class (PandocMonad, report)
+import Text.Pandoc.Error (PandocError (PandocMacroLoop))
+import Text.Pandoc.Logging
+import Text.Pandoc.Options
+import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline,
+ optional, space, spaces, withRaw, (<|>))
+import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),
+ ArgSpec (..), Tok (..), TokType (..))
+import Text.Pandoc.Shared
+import Text.Parsec.Pos
+
+newtype DottedNum = DottedNum [Int]
+ deriving (Show)
+
+renderDottedNum :: DottedNum -> String
+renderDottedNum (DottedNum xs) =
+ intercalate "." (map show xs)
+
+incrementDottedNum :: Int -> DottedNum -> DottedNum
+incrementDottedNum level (DottedNum ns) = DottedNum $
+ case reverse (take level (ns ++ repeat 0)) of
+ (x:xs) -> reverse (x+1 : xs)
+ [] -> [] -- shouldn't happen
+
+data LaTeXState = LaTeXState{ sOptions :: ReaderOptions
+ , sMeta :: Meta
+ , sQuoteContext :: QuoteContext
+ , sMacros :: M.Map Text Macro
+ , sContainers :: [String]
+ , sHeaders :: M.Map Inlines String
+ , sLogMessages :: [LogMessage]
+ , sIdentifiers :: Set.Set String
+ , sVerbatimMode :: Bool
+ , sCaption :: (Maybe Inlines, Maybe String)
+ , sInListItem :: Bool
+ , sInTableCell :: Bool
+ , sLastHeaderNum :: DottedNum
+ , sLastFigureNum :: DottedNum
+ , sLabels :: M.Map String [Inline]
+ , sHasChapters :: Bool
+ , sToggles :: M.Map String Bool
+ }
+ deriving Show
+
+defaultLaTeXState :: LaTeXState
+defaultLaTeXState = LaTeXState{ sOptions = def
+ , sMeta = nullMeta
+ , sQuoteContext = NoQuote
+ , sMacros = M.empty
+ , sContainers = []
+ , sHeaders = M.empty
+ , sLogMessages = []
+ , sIdentifiers = Set.empty
+ , sVerbatimMode = False
+ , sCaption = (Nothing, Nothing)
+ , sInListItem = False
+ , sInTableCell = False
+ , sLastHeaderNum = DottedNum []
+ , sLastFigureNum = DottedNum []
+ , sLabels = M.empty
+ , sHasChapters = False
+ , sToggles = M.empty
+ }
+
+instance PandocMonad m => HasQuoteContext LaTeXState m where
+ getQuoteContext = sQuoteContext <$> getState
+ withQuoteContext context parser = do
+ oldState <- getState
+ let oldQuoteContext = sQuoteContext oldState
+ setState oldState { sQuoteContext = context }
+ result <- parser
+ newState <- getState
+ setState newState { sQuoteContext = oldQuoteContext }
+ return result
+
+instance HasLogMessages LaTeXState where
+ addLogMessage msg st = st{ sLogMessages = msg : sLogMessages st }
+ getLogMessages st = reverse $ sLogMessages st
+
+instance HasIdentifierList LaTeXState where
+ extractIdentifierList = sIdentifiers
+ updateIdentifierList f st = st{ sIdentifiers = f $ sIdentifiers st }
+
+instance HasIncludeFiles LaTeXState where
+ getIncludeFiles = sContainers
+ addIncludeFile f s = s{ sContainers = f : sContainers s }
+ dropLatestIncludeFile s = s { sContainers = drop 1 $ sContainers s }
+
+instance HasHeaderMap LaTeXState where
+ extractHeaderMap = sHeaders
+ updateHeaderMap f st = st{ sHeaders = f $ sHeaders st }
+
+instance HasMacros LaTeXState where
+ extractMacros st = sMacros st
+ updateMacros f st = st{ sMacros = f (sMacros st) }
+
+instance HasReaderOptions LaTeXState where
+ extractReaderOptions = sOptions
+
+instance HasMeta LaTeXState where
+ setMeta field val st =
+ st{ sMeta = setMeta field val $ sMeta st }
+ deleteMeta field st =
+ st{ sMeta = deleteMeta field $ sMeta st }
+
+instance Default LaTeXState where
+ def = defaultLaTeXState
+
+type LP m = ParserT [Tok] LaTeXState m
+
+withVerbatimMode :: PandocMonad m => LP m a -> LP m a
+withVerbatimMode parser = do
+ updateState $ \st -> st{ sVerbatimMode = True }
+ result <- parser
+ updateState $ \st -> st{ sVerbatimMode = False }
+ return result
+
+rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s)
+ => Bool -> LP m a -> LP m a -> ParserT String s m (a, String)
+rawLaTeXParser retokenize parser valParser = do
+ inp <- getInput
+ let toks = tokenize "source" $ T.pack inp
+ pstate <- getState
+ let lstate = def{ sOptions = extractReaderOptions pstate }
+ let lstate' = lstate { sMacros = extractMacros pstate }
+ let rawparser = (,) <$> withRaw valParser <*> getState
+ res' <- lift $ runParserT (snd <$> withRaw parser) lstate "chunk" toks
+ case res' of
+ Left _ -> mzero
+ Right toks' -> do
+ res <- lift $ runParserT (do when retokenize $ do
+ -- retokenize, applying macros
+ doMacros 0
+ ts <- many (satisfyTok (const True))
+ setInput ts
+ rawparser)
+ lstate' "chunk" toks'
+ case res of
+ Left _ -> mzero
+ Right ((val, raw), st) -> do
+ updateState (updateMacros (sMacros st <>))
+ _ <- takeP (T.length (untokenize toks'))
+ return (val, T.unpack (untokenize raw))
+
+applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)
+ => String -> ParserT String s m String
+applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|>
+ do let retokenize = doMacros 0 *>
+ (toksToString <$> many (satisfyTok (const True)))
+ pstate <- getState
+ let lstate = def{ sOptions = extractReaderOptions pstate
+ , sMacros = extractMacros pstate }
+ res <- runParserT retokenize lstate "math" (tokenize "math" (T.pack s))
+ case res of
+ Left e -> fail (show e)
+ Right s' -> return s'
+tokenize :: SourceName -> Text -> [Tok]
+tokenize sourcename = totoks (initialPos sourcename)
+
+totoks :: SourcePos -> Text -> [Tok]
+totoks pos t =
+ case T.uncons t of
+ Nothing -> []
+ Just (c, rest)
+ | c == '\n' ->
+ Tok pos Newline "\n"
+ : totoks (setSourceColumn (incSourceLine pos 1) 1) rest
+ | isSpaceOrTab c ->
+ let (sps, rest') = T.span isSpaceOrTab t
+ in Tok pos Spaces sps
+ : totoks (incSourceColumn pos (T.length sps))
+ rest'
+ | isAlphaNum c ->
+ let (ws, rest') = T.span isAlphaNum t
+ in Tok pos Word ws
+ : totoks (incSourceColumn pos (T.length ws)) rest'
+ | c == '%' ->
+ let (cs, rest') = T.break (== '\n') rest
+ in Tok pos Comment ("%" <> cs)
+ : totoks (incSourceColumn pos (1 + T.length cs)) rest'
+ | c == '\\' ->
+ case T.uncons rest of
+ Nothing -> [Tok pos (CtrlSeq " ") "\\"]
+ Just (d, rest')
+ | isLetterOrAt d ->
+ -- \makeatletter is common in macro defs;
+ -- ideally we should make tokenization sensitive
+ -- to \makeatletter and \makeatother, but this is
+ -- probably best for now
+ let (ws, rest'') = T.span isLetterOrAt rest
+ (ss, rest''') = T.span isSpaceOrTab rest''
+ in Tok pos (CtrlSeq ws) ("\\" <> ws <> ss)
+ : totoks (incSourceColumn pos
+ (1 + T.length ws + T.length ss)) rest'''
+ | isSpaceOrTab d || d == '\n' ->
+ let (w1, r1) = T.span isSpaceOrTab rest
+ (w2, (w3, r3)) = case T.uncons r1 of
+ Just ('\n', r2)
+ -> (T.pack "\n",
+ T.span isSpaceOrTab r2)
+ _ -> (mempty, (mempty, r1))
+ ws = "\\" <> w1 <> w2 <> w3
+ in case T.uncons r3 of
+ Just ('\n', _) ->
+ Tok pos (CtrlSeq " ") ("\\" <> w1)
+ : totoks (incSourceColumn pos (T.length ws))
+ r1
+ _ ->
+ Tok pos (CtrlSeq " ") ws
+ : totoks (incSourceColumn pos (T.length ws))
+ r3
+ | otherwise ->
+ Tok pos (CtrlSeq (T.singleton d)) (T.pack [c,d])
+ : totoks (incSourceColumn pos 2) rest'
+ | c == '#' ->
+ let (t1, t2) = T.span (\d -> d >= '0' && d <= '9') rest
+ in case safeRead (T.unpack t1) of
+ Just i ->
+ Tok pos (Arg i) ("#" <> t1)
+ : totoks (incSourceColumn pos (1 + T.length t1)) t2
+ Nothing ->
+ Tok pos Symbol "#"
+ : totoks (incSourceColumn pos 1) t2
+ | c == '^' ->
+ case T.uncons rest of
+ Just ('^', rest') ->
+ case T.uncons rest' of
+ Just (d, rest'')
+ | isLowerHex d ->
+ case T.uncons rest'' of
+ Just (e, rest''') | isLowerHex e ->
+ Tok pos Esc2 (T.pack ['^','^',d,e])
+ : totoks (incSourceColumn pos 4) rest'''
+ _ ->
+ Tok pos Esc1 (T.pack ['^','^',d])
+ : totoks (incSourceColumn pos 3) rest''
+ | d < '\128' ->
+ Tok pos Esc1 (T.pack ['^','^',d])
+ : totoks (incSourceColumn pos 3) rest''
+ _ -> Tok pos Symbol "^" :
+ Tok (incSourceColumn pos 1) Symbol "^" :
+ totoks (incSourceColumn pos 2) rest'
+ _ -> Tok pos Symbol "^"
+ : totoks (incSourceColumn pos 1) rest
+ | otherwise ->
+ Tok pos Symbol (T.singleton c) : totoks (incSourceColumn pos 1) rest
+
+isSpaceOrTab :: Char -> Bool
+isSpaceOrTab ' ' = True
+isSpaceOrTab '\t' = True
+isSpaceOrTab _ = False
+
+isLetterOrAt :: Char -> Bool
+isLetterOrAt '@' = True
+isLetterOrAt c = isLetter c
+
+isLowerHex :: Char -> Bool
+isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f'
+
+untokenize :: [Tok] -> Text
+untokenize = mconcat . map untoken
+
+untoken :: Tok -> Text
+untoken (Tok _ _ t) = t
+
+toksToString :: [Tok] -> String
+toksToString = T.unpack . untokenize
+
+satisfyTok :: PandocMonad m => (Tok -> Bool) -> LP m Tok
+satisfyTok f =
+ try $ do
+ res <- tokenPrim (T.unpack . untoken) updatePos matcher
+ doMacros 0 -- apply macros on remaining input stream
+ return res
+ where matcher t | f t = Just t
+ | otherwise = Nothing
+ updatePos :: SourcePos -> Tok -> [Tok] -> SourcePos
+ updatePos _spos _ (Tok pos _ _ : _) = pos
+ updatePos spos _ [] = incSourceColumn spos 1
+
+doMacros :: PandocMonad m => Int -> LP m ()
+doMacros n = do
+ verbatimMode <- sVerbatimMode <$> getState
+ unless verbatimMode $ do
+ inp <- getInput
+ case inp of
+ Tok spos (CtrlSeq "begin") _ : Tok _ Symbol "{" :
+ Tok _ Word name : Tok _ Symbol "}" : ts
+ -> handleMacros spos name ts
+ Tok spos (CtrlSeq "end") _ : Tok _ Symbol "{" :
+ Tok _ Word name : Tok _ Symbol "}" : ts
+ -> handleMacros spos ("end" <> name) ts
+ Tok _ (CtrlSeq "expandafter") _ : t : ts
+ -> do setInput ts
+ doMacros n
+ getInput >>= setInput . combineTok t
+ Tok spos (CtrlSeq name) _ : ts
+ -> handleMacros spos name ts
+ _ -> return ()
+ where combineTok (Tok spos (CtrlSeq name) x) (Tok _ Word w : ts)
+ | T.all isLetterOrAt w =
+ Tok spos (CtrlSeq (name <> w)) (x1 <> w <> x2) : ts
+ where (x1, x2) = T.break isSpaceOrTab x
+ combineTok t ts = t:ts
+ handleMacros spos name ts = do
+ macros <- sMacros <$> getState
+ case M.lookup name macros of
+ Nothing -> return ()
+ Just (Macro expansionPoint argspecs optarg newtoks) -> do
+ setInput ts
+ let matchTok (Tok _ toktype txt) =
+ satisfyTok (\(Tok _ toktype' txt') ->
+ toktype == toktype' &&
+ txt == txt')
+ let matchPattern toks = try $ mapM_ matchTok toks
+ let getargs argmap [] = return argmap
+ getargs argmap (Pattern toks : rest) = try $ do
+ matchPattern toks
+ getargs argmap rest
+ getargs argmap (ArgNum i : Pattern toks : rest) =
+ try $ do
+ x <- mconcat <$> manyTill
+ (braced <|> ((:[]) <$> anyTok))
+ (matchPattern toks)
+ getargs (M.insert i x argmap) rest
+ getargs argmap (ArgNum i : rest) = do
+ x <- try $ spaces >> bracedOrToken
+ getargs (M.insert i x argmap) rest
+ args <- case optarg of
+ Nothing -> getargs M.empty argspecs
+ Just o -> do
+ x <- option o bracketedToks
+ getargs (M.singleton 1 x) argspecs
+ -- first boolean param is true if we're tokenizing
+ -- an argument (in which case we don't want to
+ -- expand #1 etc.)
+ let addTok False (Tok _ (Arg i) _) acc =
+ case M.lookup i args of
+ Nothing -> mzero
+ Just xs -> foldr (addTok True) acc xs
+ -- see #4007
+ addTok _ (Tok _ (CtrlSeq x) txt)
+ acc@(Tok _ Word _ : _)
+ | not (T.null txt) &&
+ isLetter (T.last txt) =
+ Tok spos (CtrlSeq x) (txt <> " ") : acc
+ addTok _ t acc = setpos spos t : acc
+ ts' <- getInput
+ setInput $ foldr (addTok False) ts' newtoks
+ case expansionPoint of
+ ExpandWhenUsed ->
+ if n > 20 -- detect macro expansion loops
+ then throwError $ PandocMacroLoop (T.unpack name)
+ else doMacros (n + 1)
+ ExpandWhenDefined -> return ()
+
+
+setpos :: SourcePos -> Tok -> Tok
+setpos spos (Tok _ tt txt) = Tok spos tt txt
+
+anyControlSeq :: PandocMonad m => LP m Tok
+anyControlSeq = satisfyTok isCtrlSeq
+
+isCtrlSeq :: Tok -> Bool
+isCtrlSeq (Tok _ (CtrlSeq _) _) = True
+isCtrlSeq _ = False
+
+anySymbol :: PandocMonad m => LP m Tok
+anySymbol = satisfyTok isSymbolTok
+
+isSymbolTok :: Tok -> Bool
+isSymbolTok (Tok _ Symbol _) = True
+isSymbolTok _ = False
+
+isWordTok :: Tok -> Bool
+isWordTok (Tok _ Word _) = True
+isWordTok _ = False
+
+isArgTok :: Tok -> Bool
+isArgTok (Tok _ (Arg _) _) = True
+isArgTok _ = False
+
+spaces :: PandocMonad m => LP m ()
+spaces = skipMany (satisfyTok (tokTypeIn [Comment, Spaces, Newline]))
+
+spaces1 :: PandocMonad m => LP m ()
+spaces1 = skipMany1 (satisfyTok (tokTypeIn [Comment, Spaces, Newline]))
+
+tokTypeIn :: [TokType] -> Tok -> Bool
+tokTypeIn toktypes (Tok _ tt _) = tt `elem` toktypes
+
+controlSeq :: PandocMonad m => Text -> LP m Tok
+controlSeq name = satisfyTok isNamed
+ where isNamed (Tok _ (CtrlSeq n) _) = n == name
+ isNamed _ = False
+
+symbol :: PandocMonad m => Char -> LP m Tok
+symbol c = satisfyTok isc
+ where isc (Tok _ Symbol d) = case T.uncons d of
+ Just (c',_) -> c == c'
+ _ -> False
+ isc _ = False
+
+symbolIn :: PandocMonad m => [Char] -> LP m Tok
+symbolIn cs = satisfyTok isInCs
+ where isInCs (Tok _ Symbol d) = case T.uncons d of
+ Just (c,_) -> c `elem` cs
+ _ -> False
+ isInCs _ = False
+
+sp :: PandocMonad m => LP m ()
+sp = whitespace <|> endline
+
+whitespace :: PandocMonad m => LP m ()
+whitespace = () <$ satisfyTok isSpaceTok
+
+isSpaceTok :: Tok -> Bool
+isSpaceTok (Tok _ Spaces _) = True
+isSpaceTok _ = False
+
+newlineTok :: PandocMonad m => LP m ()
+newlineTok = () <$ satisfyTok isNewlineTok
+
+isNewlineTok :: Tok -> Bool
+isNewlineTok (Tok _ Newline _) = True
+isNewlineTok _ = False
+
+comment :: PandocMonad m => LP m ()
+comment = () <$ satisfyTok isCommentTok
+
+isCommentTok :: Tok -> Bool
+isCommentTok (Tok _ Comment _) = True
+isCommentTok _ = False
+
+anyTok :: PandocMonad m => LP m Tok
+anyTok = satisfyTok (const True)
+
+singleChar :: PandocMonad m => LP m Tok
+singleChar = try $ do
+ Tok pos toktype t <- satisfyTok (tokTypeIn [Word, Symbol])
+ guard $ not $ toktype == Symbol &&
+ T.any (`Set.member` specialChars) t
+ if T.length t > 1
+ then do
+ let (t1, t2) = (T.take 1 t, T.drop 1 t)
+ inp <- getInput
+ setInput $ Tok (incSourceColumn pos 1) toktype t2 : inp
+ return $ Tok pos toktype t1
+ else return $ Tok pos toktype t
+
+specialChars :: Set.Set Char
+specialChars = Set.fromList "#$%&~_^\\{}"
+
+endline :: PandocMonad m => LP m ()
+endline = try $ do
+ newlineTok
+ lookAhead anyTok
+ notFollowedBy blankline
+
+blankline :: PandocMonad m => LP m ()
+blankline = try $ skipMany whitespace *> newlineTok
+
+primEscape :: PandocMonad m => LP m Char
+primEscape = do
+ Tok _ toktype t <- satisfyTok (tokTypeIn [Esc1, Esc2])
+ case toktype of
+ Esc1 -> case T.uncons (T.drop 2 t) of
+ Just (c, _)
+ | c >= '\64' && c <= '\127' -> return (chr (ord c - 64))
+ | otherwise -> return (chr (ord c + 64))
+ Nothing -> fail "Empty content of Esc1"
+ Esc2 -> case safeRead ('0':'x':T.unpack (T.drop 2 t)) of
+ Just x -> return (chr x)
+ Nothing -> fail $ "Could not read: " ++ T.unpack t
+ _ -> fail "Expected an Esc1 or Esc2 token" -- should not happen
+
+bgroup :: PandocMonad m => LP m Tok
+bgroup = try $ do
+ skipMany sp
+ symbol '{' <|> controlSeq "bgroup" <|> controlSeq "begingroup"
+
+egroup :: PandocMonad m => LP m Tok
+egroup = symbol '}' <|> controlSeq "egroup" <|> controlSeq "endgroup"
+
+grouped :: (PandocMonad m, Monoid a) => LP m a -> LP m a
+grouped parser = try $ do
+ bgroup
+ -- first we check for an inner 'grouped', because
+ -- {{a,b}} should be parsed the same as {a,b}
+ try (grouped parser <* egroup) <|> (mconcat <$> manyTill parser egroup)
+
+braced' :: PandocMonad m => LP m Tok -> Int -> LP m [Tok]
+braced' getTok n =
+ handleEgroup <|> handleBgroup <|> handleOther
+ where handleEgroup = do
+ t <- egroup
+ if n == 1
+ then return []
+ else (t:) <$> braced' getTok (n - 1)
+ handleBgroup = do
+ t <- bgroup
+ (t:) <$> braced' getTok (n + 1)
+ handleOther = do
+ t <- getTok
+ (t:) <$> braced' getTok n
+
+braced :: PandocMonad m => LP m [Tok]
+braced = bgroup *> braced' anyTok 1
+
+-- URLs require special handling, because they can contain %
+-- characters. So we retonenize comments as we go...
+bracedUrl :: PandocMonad m => LP m [Tok]
+bracedUrl = bgroup *> braced' (retokenizeComment >> anyTok) 1
+
+-- For handling URLs, which allow literal % characters...
+retokenizeComment :: PandocMonad m => LP m ()
+retokenizeComment = (do
+ Tok pos Comment txt <- satisfyTok isCommentTok
+ let updPos (Tok pos' toktype' txt') =
+ Tok (incSourceColumn (incSourceLine pos' (sourceLine pos - 1))
+ (sourceColumn pos)) toktype' txt'
+ let newtoks = map updPos $ tokenize (sourceName pos) $ T.tail txt
+ getInput >>= setInput . ((Tok pos Symbol "%" : newtoks) ++))
+ <|> return ()
+
+bracedOrToken :: PandocMonad m => LP m [Tok]
+bracedOrToken = braced <|> ((:[]) <$> (anyControlSeq <|> singleChar))
+
+bracketed :: PandocMonad m => Monoid a => LP m a -> LP m a
+bracketed parser = try $ do
+ symbol '['
+ mconcat <$> manyTill parser (symbol ']')
+
+bracketedToks :: PandocMonad m => LP m [Tok]
+bracketedToks = do
+ symbol '['
+ mconcat <$> manyTill (braced <|> (:[]) <$> anyTok) (symbol ']')
+
+parenWrapped :: PandocMonad m => Monoid a => LP m a -> LP m a
+parenWrapped parser = try $ do
+ symbol '('
+ mconcat <$> manyTill parser (symbol ')')
+
+dimenarg :: PandocMonad m => LP m Text
+dimenarg = try $ do
+ ch <- option False $ True <$ symbol '='
+ Tok _ _ s <- satisfyTok isWordTok
+ guard $ T.take 2 (T.reverse s) `elem`
+ ["pt","pc","in","bp","cm","mm","dd","cc","sp"]
+ let num = T.take (T.length s - 2) s
+ guard $ T.length num > 0
+ guard $ T.all isDigit num
+ return $ T.pack ['=' | ch] <> s
+
+ignore :: (Monoid a, PandocMonad m) => String -> ParserT s u m a
+ignore raw = do
+ pos <- getPosition
+ report $ SkippedContent raw pos
+ return mempty
+
+withRaw :: PandocMonad m => LP m a -> LP m (a, [Tok])
+withRaw parser = do
+ inp <- getInput
+ result <- parser
+ nxt <- option (Tok (initialPos "source") Word "") (lookAhead anyTok)
+ let raw = takeWhile (/= nxt) inp
+ return (result, raw)
diff --git a/src/Text/Pandoc/Readers/LaTeX/Types.hs b/src/Text/Pandoc/Readers/LaTeX/Types.hs
index fa832114b..e3a302d49 100644
--- a/src/Text/Pandoc/Readers/LaTeX/Types.hs
+++ b/src/Text/Pandoc/Readers/LaTeX/Types.hs
@@ -31,6 +31,7 @@ Types for LaTeX tokens and macros.
module Text.Pandoc.Readers.LaTeX.Types ( Tok(..)
, TokType(..)
, Macro(..)
+ , ArgSpec(..)
, ExpansionPoint(..)
, SourcePos
)
@@ -49,5 +50,8 @@ data Tok = Tok SourcePos TokType Text
data ExpansionPoint = ExpandWhenDefined | ExpandWhenUsed
deriving (Eq, Ord, Show)
-data Macro = Macro ExpansionPoint Int (Maybe [Tok]) [Tok]
+data Macro = Macro ExpansionPoint [ArgSpec] (Maybe [Tok]) [Tok]
+ deriving Show
+
+data ArgSpec = ArgNum Int | Pattern [Tok]
deriving Show
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 156b2b622..d1ea7a1a5 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -1,6 +1,7 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RelaxedPolyRec #-}
{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
{-
Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
@@ -31,31 +32,28 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Conversion of markdown-formatted plain text to 'Pandoc' document.
-}
-module Text.Pandoc.Readers.Markdown ( readMarkdown ) where
+module Text.Pandoc.Readers.Markdown ( readMarkdown, yamlToMeta ) where
import Prelude
import Control.Monad
import Control.Monad.Except (throwError)
+import qualified Data.ByteString.Lazy as BS
import Data.Char (isAlphaNum, isPunctuation, isSpace, toLower)
-import qualified Data.HashMap.Strict as H
import Data.List (intercalate, sortBy, transpose, elemIndex)
import qualified Data.Map as M
import Data.Maybe
import Data.Ord (comparing)
-import Data.Scientific (base10Exponent, coefficient)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as T
-import qualified Data.Vector as V
-import Data.Yaml (ParseException (..), YamlException (..), YamlMark (..))
-import qualified Data.Yaml as Yaml
+import qualified Data.YAML as YAML
import System.FilePath (addExtension, takeExtension)
import Text.HTML.TagSoup
import Text.Pandoc.Builder (Blocks, Inlines)
import qualified Text.Pandoc.Builder as B
import Text.Pandoc.Class (PandocMonad (..), report)
import Text.Pandoc.Definition
-import Text.Pandoc.Emoji (emojis)
+import Text.Pandoc.Emoji (emojiToInline)
import Text.Pandoc.Error
import Text.Pandoc.Logging
import Text.Pandoc.Options
@@ -234,11 +232,9 @@ pandocTitleBlock = try $ do
$ nullMeta
updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }
-
yamlMetaBlock :: PandocMonad m => MarkdownParser m (F Blocks)
yamlMetaBlock = try $ do
guardEnabled Ext_yaml_metadata_block
- pos <- getPosition
string "---"
blankline
notFollowedBy blankline -- if --- is followed by a blank it's an HRULE
@@ -246,52 +242,44 @@ yamlMetaBlock = try $ do
-- by including --- and ..., we allow yaml blocks with just comments:
let rawYaml = unlines ("---" : (rawYamlLines ++ ["..."]))
optional blanklines
- case Yaml.decodeEither' $ UTF8.fromString rawYaml of
- Right (Yaml.Object hashmap) -> do
- let alist = H.toList hashmap
- mapM_ (\(k, v) ->
- if ignorable k
- then return ()
- else do
- v' <- yamlToMeta v
- let k' = T.unpack k
- updateState $ \st -> st{ stateMeta' =
- do m <- stateMeta' st
- -- if there's already a value, leave it unchanged
- case lookupMeta k' m of
- Just _ -> return m
- Nothing -> do
- v'' <- v'
- return $ B.setMeta (T.unpack k) v'' m}
- ) alist
- Right Yaml.Null -> return ()
+ newMetaF <- yamlBsToMeta $ UTF8.fromStringLazy rawYaml
+ -- Since `<>` is left-biased, existing values are not touched:
+ updateState $ \st -> st{ stateMeta' = (stateMeta' st) <> newMetaF }
+ return mempty
+
+-- | Read a YAML string and convert it to pandoc metadata.
+-- String scalars in the YAML are parsed as Markdown.
+yamlToMeta :: PandocMonad m => BS.ByteString -> m Meta
+yamlToMeta bstr = do
+ let parser = do
+ meta <- yamlBsToMeta bstr
+ return $ runF meta defaultParserState
+ parsed <- readWithM parser def ""
+ case parsed of
+ Right result -> return result
+ Left e -> throwError e
+
+yamlBsToMeta :: PandocMonad m => BS.ByteString -> MarkdownParser m (F Meta)
+yamlBsToMeta bstr = do
+ pos <- getPosition
+ case YAML.decodeNode' YAML.failsafeSchemaResolver False False bstr of
+ Right ((YAML.Doc (YAML.Mapping _ o)):_) -> (fmap Meta) <$> yamlMap o
+ Right [] -> return . return $ mempty
+ Right [YAML.Doc (YAML.Scalar YAML.SNull)] -> return . return $ mempty
Right _ -> do
- logMessage $
- CouldNotParseYamlMetadata "not an object"
- pos
- return ()
+ logMessage $
+ CouldNotParseYamlMetadata "not an object"
+ pos
+ return . return $ mempty
Left err' -> do
- case err' of
- InvalidYaml (Just YamlParseException{
- yamlProblem = problem
- , yamlContext = _ctxt
- , yamlProblemMark = Yaml.YamlMark {
- yamlLine = yline
- , yamlColumn = ycol
- }}) ->
- logMessage $ CouldNotParseYamlMetadata
- problem (setSourceLine
- (setSourceColumn pos
- (sourceColumn pos + ycol))
- (sourceLine pos + 1 + yline))
- _ -> logMessage $ CouldNotParseYamlMetadata
- (show err') pos
- return ()
- return mempty
+ logMessage $ CouldNotParseYamlMetadata
+ err' pos
+ return . return $ mempty
--- ignore fields ending with _
-ignorable :: Text -> Bool
-ignorable t = (T.pack "_") `T.isSuffixOf` t
+nodeToKey :: Monad m => YAML.Node -> m Text
+nodeToKey (YAML.Scalar (YAML.SStr t)) = return t
+nodeToKey (YAML.Scalar (YAML.SUnknown _ t)) = return t
+nodeToKey _ = fail "Non-string key in YAML mapping"
toMetaValue :: PandocMonad m
=> Text -> MarkdownParser m (F MetaValue)
@@ -312,34 +300,51 @@ toMetaValue x =
-- not end in a newline, but a "block" set off with
-- `|` or `>` will.
-yamlToMeta :: PandocMonad m
- => Yaml.Value -> MarkdownParser m (F MetaValue)
-yamlToMeta (Yaml.String t) = toMetaValue t
-yamlToMeta (Yaml.Number n)
- -- avoid decimal points for numbers that don't need them:
- | base10Exponent n >= 0 = return $ return $ MetaString $ show
- $ coefficient n * (10 ^ base10Exponent n)
- | otherwise = return $ return $ MetaString $ show n
-yamlToMeta (Yaml.Bool b) = return $ return $ MetaBool b
-yamlToMeta (Yaml.Array xs) = do
- xs' <- mapM yamlToMeta (V.toList xs)
+checkBoolean :: Text -> Maybe Bool
+checkBoolean t =
+ if t == T.pack "true" || t == T.pack "True" || t == T.pack "TRUE"
+ then Just True
+ else if t == T.pack "false" || t == T.pack "False" || t == T.pack "FALSE"
+ then Just False
+ else Nothing
+
+yamlToMetaValue :: PandocMonad m
+ => YAML.Node -> MarkdownParser m (F MetaValue)
+yamlToMetaValue (YAML.Scalar x) =
+ case x of
+ YAML.SStr t -> toMetaValue t
+ YAML.SBool b -> return $ return $ MetaBool b
+ YAML.SFloat d -> return $ return $ MetaString (show d)
+ YAML.SInt i -> return $ return $ MetaString (show i)
+ YAML.SUnknown _ t ->
+ case checkBoolean t of
+ Just b -> return $ return $ MetaBool b
+ Nothing -> toMetaValue t
+ YAML.SNull -> return $ return $ MetaString ""
+yamlToMetaValue (YAML.Sequence _ xs) = do
+ xs' <- mapM yamlToMetaValue xs
return $ do
xs'' <- sequence xs'
return $ B.toMetaValue xs''
-yamlToMeta (Yaml.Object o) = do
- let alist = H.toList o
- foldM (\m (k,v) ->
- if ignorable k
- then return m
- else do
- v' <- yamlToMeta v
- return $ do
- MetaMap m' <- m
- v'' <- v'
- return (MetaMap $ M.insert (T.unpack k) v'' m'))
- (return $ MetaMap M.empty)
- alist
-yamlToMeta _ = return $ return $ MetaString ""
+yamlToMetaValue (YAML.Mapping _ o) = fmap B.toMetaValue <$> yamlMap o
+yamlToMetaValue _ = return $ return $ MetaString ""
+
+yamlMap :: PandocMonad m
+ => M.Map YAML.Node YAML.Node
+ -> MarkdownParser m (F (M.Map String MetaValue))
+yamlMap o = do
+ kvs <- forM (M.toList o) $ \(key, v) -> do
+ k <- nodeToKey key
+ return (k, v)
+ let kvs' = filter (not . ignorable . fst) kvs
+ (fmap M.fromList . sequence) <$> mapM toMeta kvs'
+ where
+ ignorable t = (T.pack "_") `T.isSuffixOf` t
+ toMeta (k, v) = do
+ fv <- yamlToMetaValue v
+ return $ do
+ v' <- fv
+ return (T.unpack k, v')
stopLine :: PandocMonad m => MarkdownParser m ()
stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
@@ -966,7 +971,9 @@ orderedList = try $ do
<|> return (style == Example)
items <- fmap sequence $ many1 $ listItem fourSpaceRule
(orderedListStart (Just (style, delim)))
- start' <- (start <$ guardEnabled Ext_startnum) <|> return 1
+ start' <- if style == Example
+ then return start
+ else (start <$ guardEnabled Ext_startnum) <|> return 1
return $ B.orderedListWith (start', style, delim) <$> fmap compactify items
bulletList :: PandocMonad m => MarkdownParser m (F Blocks)
@@ -1142,10 +1149,9 @@ rawTeXBlock :: PandocMonad m => MarkdownParser m (F Blocks)
rawTeXBlock = do
guardEnabled Ext_raw_tex
lookAhead $ try $ char '\\' >> letter
- result <- (B.rawBlock "context" . trim . concat <$>
- many1 ((++) <$> (rawConTeXtEnvironment <|> conTeXtCommand)
- <*> spnl'))
- <|> (B.rawBlock "latex" . trim . concat <$>
+ result <- (B.rawBlock "tex" . trim . concat <$>
+ many1 ((++) <$> rawConTeXtEnvironment <*> spnl'))
+ <|> (B.rawBlock "tex" . trim . concat <$>
many1 ((++) <$> rawLaTeXBlock <*> spnl'))
return $ case B.toList result of
[RawBlock _ cs]
@@ -1153,9 +1159,6 @@ rawTeXBlock = do
-- don't create a raw block for suppressed macro defs
_ -> return result
-conTeXtCommand :: PandocMonad m => MarkdownParser m String
-conTeXtCommand = oneOfStrings ["\\placeformula"]
-
rawHtmlBlocks :: PandocMonad m => MarkdownParser m (F Blocks)
rawHtmlBlocks = do
(TagOpen tagtype _, raw) <- htmlTag isBlockTag
@@ -1591,7 +1594,7 @@ code = try $ do
starts <- many1 (char '`')
skipSpaces
result <- (trim . concat) <$>
- many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|>
+ manyTill (many1 (noneOf "`\n") <|> many1 (char '`') <|>
(char '\n' >> notFollowedBy' blankline >> return " "))
(try (skipSpaces >> count (length starts) (char '`') >>
notFollowedBy (char '`')))
@@ -1877,23 +1880,24 @@ bareURL :: PandocMonad m => MarkdownParser m (F Inlines)
bareURL = try $ do
guardEnabled Ext_autolink_bare_uris
getState >>= guard . stateAllowLinks
- (orig, src) <- uri <|> emailAddress
+ (cls, (orig, src)) <- (("uri",) <$> uri) <|> (("email",) <$> emailAddress)
notFollowedBy $ try $ spaces >> htmlTag (~== TagClose "a")
- return $ return $ B.link src "" (B.str orig)
+ return $ return $ B.linkWith ("",[cls],[]) src "" (B.str orig)
autoLink :: PandocMonad m => MarkdownParser m (F Inlines)
autoLink = try $ do
getState >>= guard . stateAllowLinks
char '<'
- (orig, src) <- uri <|> emailAddress
+ (cls, (orig, src)) <- (("uri",) <$> uri) <|> (("email",) <$> emailAddress)
-- in rare cases, something may remain after the uri parser
-- is finished, because the uri parser tries to avoid parsing
-- final punctuation. for example: in `<http://hi---there>`,
-- the URI parser will stop before the dashes.
extra <- fromEntities <$> manyTill nonspaceChar (char '>')
- attr <- option nullAttr $ try $
+ attr <- option ("", [cls], []) $ try $
guardEnabled Ext_link_attributes >> attributes
- return $ return $ B.linkWith attr (src ++ escapeURI extra) "" (B.str $ orig ++ extra)
+ return $ return $ B.linkWith attr (src ++ escapeURI extra) ""
+ (B.str $ orig ++ extra)
image :: PandocMonad m => MarkdownParser m (F Inlines)
image = try $ do
@@ -2037,9 +2041,9 @@ emoji = try $ do
char ':'
emojikey <- many1 (oneOf emojiChars)
char ':'
- case M.lookup emojikey emojis of
- Just s -> return (return (B.str s))
- Nothing -> mzero
+ case emojiToInline emojikey of
+ Just i -> return (return $ B.singleton i)
+ Nothing -> mzero
-- Citations
diff --git a/src/Text/Pandoc/Readers/Muse.hs b/src/Text/Pandoc/Readers/Muse.hs
index fe6b3698c..134598c07 100644
--- a/src/Text/Pandoc/Readers/Muse.hs
+++ b/src/Text/Pandoc/Readers/Muse.hs
@@ -35,34 +35,32 @@ TODO:
- Page breaks (five "*")
- Org tables
- table.el tables
-- Images with attributes (floating and width)
- <cite> tag
-}
module Text.Pandoc.Readers.Muse (readMuse) where
import Prelude
import Control.Monad
+import Control.Monad.Reader
import Control.Monad.Except (throwError)
import Data.Bifunctor
-import Data.Char (isLetter)
+import Data.Char (isAlphaNum)
import Data.Default
-import Data.List (stripPrefix, intercalate)
+import Data.List (intercalate)
import Data.List.Split (splitOn)
import qualified Data.Map as M
import qualified Data.Set as Set
-import Data.Maybe (fromMaybe, isNothing)
+import Data.Maybe (fromMaybe, isNothing, maybeToList)
import Data.Text (Text, unpack)
-import System.FilePath (takeExtension)
-import Text.HTML.TagSoup
import Text.Pandoc.Builder (Blocks, Inlines)
import qualified Text.Pandoc.Builder as B
import Text.Pandoc.Class (PandocMonad (..))
import Text.Pandoc.Definition
+import Text.Pandoc.Error (PandocError (PandocParsecError))
import Text.Pandoc.Logging
import Text.Pandoc.Options
-import Text.Pandoc.Parsing hiding (F)
-import Text.Pandoc.Readers.HTML (htmlTag)
-import Text.Pandoc.Shared (crFilter, underlineSpan)
+import Text.Pandoc.Parsing hiding (F, enclosed)
+import Text.Pandoc.Shared (crFilter, underlineSpan, mapLeft)
-- | Read Muse from an input string and return a Pandoc document.
readMuse :: PandocMonad m
@@ -70,7 +68,8 @@ readMuse :: PandocMonad m
-> Text
-> m Pandoc
readMuse opts s = do
- res <- readWithM parseMuse def{ museOptions = opts } (unpack (crFilter s))
+ let input = crFilter s
+ res <- mapLeft (PandocParsecError $ unpack input) `liftM` runReaderT (runParserT parseMuse def{ museOptions = opts } "source" input) def
case res of
Left e -> throwError e
Right d -> return d
@@ -84,7 +83,6 @@ data MuseState = MuseState { museMeta :: F Meta -- ^ Document metadata
, museLastStrPos :: Maybe SourcePos -- ^ Position after last str parsed
, museLogMessages :: [LogMessage]
, museNotes :: M.Map String (SourcePos, F Blocks)
- , museInLink :: Bool -- ^ True when parsing a link description to avoid nested links
, museInPara :: Bool -- ^ True when looking for a paragraph terminator
}
@@ -96,11 +94,17 @@ instance Default MuseState where
, museLastStrPos = Nothing
, museLogMessages = []
, museNotes = M.empty
- , museInLink = False
, museInPara = False
}
-type MuseParser = ParserT String MuseState
+data MuseEnv =
+ MuseEnv { museInLink :: Bool -- ^ True when parsing a link description to avoid nested links
+ }
+
+instance Default MuseEnv where
+ def = MuseEnv { museInLink = False }
+
+type MuseParser m = ParserT Text MuseState (ReaderT MuseEnv m)
instance HasReaderOptions MuseState where
extractReaderOptions = museOptions
@@ -125,11 +129,9 @@ instance HasLogMessages MuseState where
parseMuse :: PandocMonad m => MuseParser m Pandoc
parseMuse = do
many directive
- blocks <- parseBlocks
+ blocks <- (:) <$> parseBlocks <*> many parseSection
st <- getState
- let doc = runF (do Pandoc _ bs <- B.doc <$> blocks
- meta <- museMeta st
- return $ Pandoc meta bs) st
+ let doc = runF (Pandoc <$> museMeta st <*> fmap B.toList (mconcat blocks)) st
reportLogMessages
return doc
@@ -144,9 +146,8 @@ commonPrefix (x:xs) (y:ys)
-- | Trim up to one newline from the beginning of the string.
lchop :: String -> String
-lchop s = case s of
- '\n':ss -> ss
- _ -> s
+lchop ('\n':xs) = xs
+lchop s = s
-- | Trim up to one newline from the end of the string.
rchop :: String -> String
@@ -165,12 +166,19 @@ atStart p = do
guard $ museLastStrPos st /= Just pos
p
+firstColumn :: PandocMonad m => MuseParser m ()
+firstColumn = getPosition >>= \pos -> guard (sourceColumn pos == 1)
+
-- * Parsers
-- | Parse end-of-line, which can be either a newline or end-of-file.
eol :: Stream s m Char => ParserT s st m ()
eol = void newline <|> eof
+getIndent :: PandocMonad m
+ => MuseParser m Int
+getIndent = subtract 1 . sourceColumn <$ many spaceChar <*> getPosition
+
someUntil :: (Stream s m t)
=> ParserT s u m a
-> ParserT s u m b
@@ -179,28 +187,21 @@ someUntil p end = first <$> ((:) <$> p) <*> manyUntil p end
-- ** HTML parsers
--- | Parse HTML tag, returning its attributes and literal contents.
-htmlElement :: PandocMonad m
- => String -- ^ Tag name
- -> MuseParser m (Attr, String)
-htmlElement tag = try $ do
- (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
- content <- manyTill anyChar endtag
- return (htmlAttrToPandoc attr, content)
+openTag :: PandocMonad m => String -> MuseParser m [(String, String)]
+openTag tag = try $
+ char '<' *> string tag *> manyTill attr (char '>')
where
- endtag = void $ htmlTag (~== TagClose tag)
+ attr = try $ (,)
+ <$ many1 spaceChar
+ <*> many1 (noneOf "=\n")
+ <* string "=\""
+ <*> manyTill (noneOf "\"") (char '"')
-htmlBlock :: PandocMonad m
- => String -- ^ Tag name
- -> MuseParser m (Attr, String)
-htmlBlock tag = try $ do
- many spaceChar
- res <- htmlElement tag
- manyTill spaceChar eol
- return res
+closeTag :: PandocMonad m => String -> MuseParser m ()
+closeTag tag = try $ string "</" *> string tag *> void (char '>')
-- | Convert HTML attributes to Pandoc 'Attr'
-htmlAttrToPandoc :: [Attribute String] -> Attr
+htmlAttrToPandoc :: [(String, String)] -> Attr
htmlAttrToPandoc attrs = (ident, classes, keyvals)
where
ident = fromMaybe "" $ lookup "id" attrs
@@ -211,15 +212,12 @@ parseHtmlContent :: PandocMonad m
=> String -- ^ Tag name
-> MuseParser m (Attr, F Blocks)
parseHtmlContent tag = try $ do
- many spaceChar
- pos <- getPosition
- (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
+ indent <- getIndent
+ attr <- openTag tag
manyTill spaceChar eol
- content <- parseBlocksTill $ try $ count (sourceColumn pos - 1) spaceChar >> endtag
+ content <- parseBlocksTill $ try $ count indent spaceChar *> closeTag tag
manyTill spaceChar eol -- closing tag must be followed by optional whitespace and newline
return (htmlAttrToPandoc attr, content)
- where
- endtag = void $ htmlTag (~== TagClose tag)
-- ** Directive parsers
@@ -228,21 +226,19 @@ parseDirectiveKey :: PandocMonad m => MuseParser m String
parseDirectiveKey = char '#' *> many (letter <|> char '-')
parseEmacsDirective :: PandocMonad m => MuseParser m (String, F Inlines)
-parseEmacsDirective = do
- key <- parseDirectiveKey
- spaceChar
- value <- trimInlinesF . mconcat <$> manyTill (choice inlineList) eol
- return (key, value)
+parseEmacsDirective = (,)
+ <$> parseDirectiveKey
+ <* spaceChar
+ <*> (trimInlinesF . mconcat <$> manyTill inline' eol)
parseAmuseDirective :: PandocMonad m => MuseParser m (String, F Inlines)
-parseAmuseDirective = do
- key <- parseDirectiveKey
- many1 spaceChar
- value <- trimInlinesF . mconcat <$> many1Till inline endOfDirective
- many blankline
- return (key, value)
+parseAmuseDirective = (,)
+ <$> parseDirectiveKey
+ <* many1 spaceChar
+ <*> (trimInlinesF . mconcat <$> many1Till inline endOfDirective)
+ <* many blankline
where
- endOfDirective = lookAhead $ eof <|> try (newline >> (void blankline <|> void parseDirectiveKey))
+ endOfDirective = lookAhead $ eof <|> try (newline *> (void blankline <|> void parseDirectiveKey))
directive :: PandocMonad m => MuseParser m ()
directive = do
@@ -254,17 +250,20 @@ directive = do
-- ** Block parsers
+-- | Parse section contents until EOF or next header
parseBlocks :: PandocMonad m
=> MuseParser m (F Blocks)
parseBlocks =
try (parseEnd <|>
+ nextSection <|>
blockStart <|>
listStart <|>
paraStart)
where
+ nextSection = mempty <$ lookAhead headingStart
parseEnd = mempty <$ eof
- blockStart = ((B.<>) <$> (emacsHeading <|> blockElements <|> emacsNoteBlock)
- <*> parseBlocks) <|> (uncurry (B.<>) <$> amuseHeadingUntil parseBlocks)
+ blockStart = (B.<>) <$> (blockElements <|> emacsNoteBlock)
+ <*> parseBlocks
listStart = do
updateState (\st -> st { museInPara = False })
uncurry (B.<>) <$> (anyListUntil parseBlocks <|> amuseNoteBlockUntil parseBlocks)
@@ -273,6 +272,13 @@ parseBlocks =
uncurry (B.<>) . first (p indent) <$> paraUntil parseBlocks
where p indent = if indent >= 2 && indent < 6 then fmap B.blockQuote else id
+-- | Parse section that starts with a header
+parseSection :: PandocMonad m
+ => MuseParser m (F Blocks)
+parseSection =
+ ((B.<>) <$> emacsHeading <*> parseBlocks) <|>
+ (uncurry (B.<>) <$> amuseHeadingUntil parseBlocks)
+
parseBlocksTill :: PandocMonad m
=> MuseParser m a
-> MuseParser m (F Blocks)
@@ -347,31 +353,32 @@ blockElements = do
-- | Parse a line comment, starting with @;@ in the first column.
comment :: PandocMonad m => MuseParser m (F Blocks)
-comment = try $ do
- getPosition >>= \pos -> guard (sourceColumn pos == 1)
- char ';'
- optional (spaceChar >> many (noneOf "\n"))
- eol
- return mempty
+comment = try $ mempty
+ <$ firstColumn
+ <* char ';'
+ <* optional (spaceChar *> many (noneOf "\n"))
+ <* eol
-- | Parse a horizontal rule, consisting of 4 or more @\'-\'@ characters.
separator :: PandocMonad m => MuseParser m (F Blocks)
-separator = try $ do
- string "----"
- many $ char '-'
- many spaceChar
- eol
- return $ return B.horizontalRule
+separator = try $ pure B.horizontalRule
+ <$ string "----"
+ <* many (char '-')
+ <* many spaceChar
+ <* eol
+
+headingStart :: PandocMonad m => MuseParser m (String, Int)
+headingStart = try $ (,)
+ <$> option "" (try (parseAnchor <* manyTill spaceChar eol))
+ <* firstColumn
+ <*> fmap length (many1 $ char '*')
+ <* spaceChar
-- | Parse a single-line heading.
emacsHeading :: PandocMonad m => MuseParser m (F Blocks)
emacsHeading = try $ do
guardDisabled Ext_amuse
- anchorId <- option "" $ try (parseAnchor <* manyTill spaceChar eol)
- getPosition >>= \pos -> guard (sourceColumn pos == 1)
- level <- fmap length $ many1 $ char '*'
- guard $ level <= 5
- spaceChar
+ (anchorId, level) <- headingStart
content <- trimInlinesF . mconcat <$> manyTill inline eol
attr <- registerHeader (anchorId, [], []) (runF content def)
return $ B.headerWith attr level <$> content
@@ -383,11 +390,7 @@ amuseHeadingUntil :: PandocMonad m
-> MuseParser m (F Blocks, a)
amuseHeadingUntil end = try $ do
guardEnabled Ext_amuse
- anchorId <- option "" $ try (parseAnchor <* manyTill spaceChar eol)
- getPosition >>= \pos -> guard (sourceColumn pos == 1)
- level <- fmap length $ many1 $ char '*'
- guard $ level <= 5
- spaceChar
+ (anchorId, level) <- headingStart
(content, e) <- paraContentsUntil end
attr <- registerHeader (anchorId, [], []) (runF content def)
return (B.headerWith attr level <$> content, e)
@@ -395,33 +398,28 @@ amuseHeadingUntil end = try $ do
-- | Parse an example between @{{{@ and @}}}@.
-- It is an Amusewiki extension influenced by Creole wiki, as described in @Text::Amuse@ documentation.
example :: PandocMonad m => MuseParser m (F Blocks)
-example = try $ do
- string "{{{"
- optional blankline
- contents <- manyTill anyChar $ try (optional blankline >> string "}}}")
- return $ return $ B.codeBlock contents
+example = try $ pure . B.codeBlock
+ <$ string "{{{"
+ <* optional blankline
+ <*> manyTill anyChar (try (optional blankline *> string "}}}"))
-- | Parse an @\<example>@ tag.
exampleTag :: PandocMonad m => MuseParser m (F Blocks)
-exampleTag = try $ do
- (attr, contents) <- htmlBlock "example"
- return $ return $ B.codeBlockWith attr $ rchop $ intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop contents
+exampleTag = try $ fmap pure $ B.codeBlockWith
+ <$ many spaceChar
+ <*> (htmlAttrToPandoc <$> openTag "example")
+ <*> (rchop . intercalate "\n" . dropSpacePrefix . splitOn "\n" . lchop <$> manyTill anyChar (closeTag "example"))
+ <* manyTill spaceChar eol
-- | Parse a @\<literal>@ tag as a raw block.
-- For 'RawInline' @\<literal>@ parser, see 'inlineLiteralTag'.
literalTag :: PandocMonad m => MuseParser m (F Blocks)
-literalTag = try $ do
- many spaceChar
- (TagOpen _ attr, _) <- htmlTag (~== TagOpen "literal" [])
- manyTill spaceChar eol
- content <- manyTill anyChar endtag
- manyTill spaceChar eol
- return $ return $ rawBlock (htmlAttrToPandoc attr, content)
- where
- endtag = void $ htmlTag (~== TagClose "literal")
- -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
- format (_, _, kvs) = fromMaybe "html" $ lookup "style" kvs
- rawBlock (attrs, content) = B.rawBlock (format attrs) $ rchop $ intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop content
+literalTag = try $ fmap pure $ B.rawBlock
+ <$ many spaceChar
+ <*> (fromMaybe "html" . lookup "style" <$> openTag "literal") -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
+ <* manyTill spaceChar eol
+ <*> (rchop . intercalate "\n" . dropSpacePrefix . splitOn "\n" . lchop <$> manyTill anyChar (closeTag "literal"))
+ <* manyTill spaceChar eol
-- | Parse @\<center>@ tag.
-- Currently it is ignored as Pandoc cannot represent centered blocks.
@@ -459,25 +457,27 @@ playTag = do
fmap (B.divWith ("", ["play"], [])) . snd <$> parseHtmlContent "play"
verseLine :: PandocMonad m => MuseParser m (F Inlines)
-verseLine = do
- indent <- (B.str <$> many1 (char ' ' >> pure '\160')) <|> pure mempty
- rest <- manyTill (choice inlineList) newline
- return $ trimInlinesF $ mconcat (pure indent : rest)
-
-verseLines :: PandocMonad m => MuseParser m (F Blocks)
-verseLines = do
- lns <- many verseLine
- return $ B.lineBlock <$> sequence lns
+verseLine = (<>)
+ <$> fmap pure (option mempty (B.str <$> many1 ('\160' <$ char ' ')))
+ <*> fmap (trimInlinesF . mconcat) (manyTill inline' eol)
-- | Parse @\<verse>@ tag.
verseTag :: PandocMonad m => MuseParser m (F Blocks)
-verseTag = do
- (_, content) <- htmlBlock "verse"
- parseFromString verseLines (intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop content)
+verseTag = try $ do
+ indent <- getIndent
+ openTag "verse"
+ manyTill spaceChar eol
+ content <- sequence <$> manyTill (count indent spaceChar *> verseLine) (try $ count indent spaceChar *> closeTag "verse")
+ manyTill spaceChar eol
+ return $ B.lineBlock <$> content
-- | Parse @\<comment>@ tag.
commentTag :: PandocMonad m => MuseParser m (F Blocks)
-commentTag = htmlBlock "comment" >> return mempty
+commentTag = try $ mempty
+ <$ many spaceChar
+ <* openTag "comment"
+ <* manyTill anyChar (closeTag "comment")
+ <* manyTill spaceChar eol
-- | Parse paragraph contents.
paraContentsUntil :: PandocMonad m
@@ -485,7 +485,7 @@ paraContentsUntil :: PandocMonad m
-> MuseParser m (F Inlines, a)
paraContentsUntil end = do
updateState (\st -> st { museInPara = True })
- (l, e) <- someUntil inline $ try (manyTill spaceChar eol >> end)
+ (l, e) <- someUntil inline $ try (manyTill spaceChar eol *> end)
updateState (\st -> st { museInPara = False })
return (trimInlinesF $ mconcat l, e)
@@ -499,9 +499,10 @@ paraUntil end = do
first (fmap B.para) <$> paraContentsUntil end
noteMarker :: PandocMonad m => MuseParser m String
-noteMarker = try $ do
- char '['
- (:) <$> oneOf "123456789" <*> manyTill digit (char ']')
+noteMarker = try $ (:)
+ <$ char '['
+ <*> oneOf "123456789"
+ <*> manyTill digit (char ']')
-- Amusewiki version of note
-- Parsing is similar to list item, except that note marker is used instead of list marker
@@ -541,27 +542,15 @@ emacsNoteBlock = try $ do
-- Verse markup
--
-lineVerseLine :: PandocMonad m => MuseParser m (F Inlines)
-lineVerseLine = try $ do
- string "> "
- indent <- many (char ' ' >> pure '\160')
- let indentEl = if null indent then mempty else B.str indent
- rest <- manyTill (choice inlineList) eol
- return $ trimInlinesF $ mconcat (pure indentEl : rest)
-
-blanklineVerseLine :: PandocMonad m => MuseParser m (F Inlines)
-blanklineVerseLine = try $ do
- char '>'
- blankline
- pure mempty
-
-- | Parse a line block indicated by @\'>\'@ characters.
lineBlock :: PandocMonad m => MuseParser m (F Blocks)
lineBlock = try $ do
- many spaceChar
- col <- sourceColumn <$> getPosition
- lns <- (blanklineVerseLine <|> lineVerseLine) `sepBy1'` try (indentWith (col - 1))
+ indent <- getIndent
+ lns <- (blankVerseLine <|> nonblankVerseLine) `sepBy1'` try (indentWith indent)
return $ B.lineBlock <$> sequence lns
+ where
+ blankVerseLine = try $ mempty <$ char '>' <* blankline
+ nonblankVerseLine = try (string "> ") *> verseLine
-- *** List parsers
@@ -573,7 +562,7 @@ bulletListItemsUntil indent end = try $ do
char '-'
void spaceChar <|> lookAhead eol
updateState (\st -> st { museInPara = False })
- (x, (xs, e)) <- listItemContentsUntil (indent + 2) (try (optional blankline >> indentWith indent >> bulletListItemsUntil indent end)) (([],) <$> end)
+ (x, (xs, e)) <- listItemContentsUntil (indent + 2) (try (optional blankline *> indentWith indent *> bulletListItemsUntil indent end)) (([],) <$> end)
return (x:xs, e)
-- | Parse a bullet list.
@@ -581,19 +570,9 @@ bulletListUntil :: PandocMonad m
=> MuseParser m a
-> MuseParser m (F Blocks, a)
bulletListUntil end = try $ do
- many spaceChar
- pos <- getPosition
- let indent = sourceColumn pos - 1
+ indent <- getIndent
guard $ indent /= 0
- (items, e) <- bulletListItemsUntil indent end
- return (B.bulletList <$> sequence items, e)
-
--- | Parses an ordered list marker and returns list attributes.
-anyMuseOrderedListMarker :: PandocMonad m => MuseParser m ListAttributes
-anyMuseOrderedListMarker = do
- (style, start) <- decimal <|> lowerRoman <|> upperRoman <|> lowerAlpha <|> upperAlpha
- char '.'
- return (start, style, Period)
+ first (fmap B.bulletList . sequence) <$> bulletListItemsUntil indent end
museOrderedListMarker :: PandocMonad m
=> ListNumberStyle
@@ -620,7 +599,7 @@ orderedListItemsUntil indent style end =
pos <- getPosition
void spaceChar <|> lookAhead eol
updateState (\st -> st { museInPara = False })
- (x, (xs, e)) <- listItemContentsUntil (sourceColumn pos) (try (optional blankline >> indentWith indent >> museOrderedListMarker style >> continuation)) (([],) <$> end)
+ (x, (xs, e)) <- listItemContentsUntil (sourceColumn pos) (try (optional blankline *> indentWith indent *> museOrderedListMarker style *> continuation)) (([],) <$> end)
return (x:xs, e)
-- | Parse an ordered list.
@@ -628,14 +607,12 @@ orderedListUntil :: PandocMonad m
=> MuseParser m a
-> MuseParser m (F Blocks, a)
orderedListUntil end = try $ do
- many spaceChar
- pos <- getPosition
- let indent = sourceColumn pos - 1
+ indent <- getIndent
guard $ indent /= 0
- p@(_, style, _) <- anyMuseOrderedListMarker
- guard $ style `elem` [Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman]
- (items, e) <- orderedListItemsUntil indent style end
- return (B.orderedListWith p <$> sequence items, e)
+ (style, start) <- decimal <|> lowerRoman <|> upperRoman <|> lowerAlpha <|> upperAlpha
+ char '.'
+ first (fmap (B.orderedListWith (start, style, Period)) . sequence)
+ <$> orderedListItemsUntil indent style end
descriptionsUntil :: PandocMonad m
=> Int
@@ -644,7 +621,7 @@ descriptionsUntil :: PandocMonad m
descriptionsUntil indent end = do
void spaceChar <|> lookAhead eol
updateState (\st -> st { museInPara = False })
- (x, (xs, e)) <- listItemContentsUntil indent (try (optional blankline >> indentWith indent >> manyTill spaceChar (string "::") >> descriptionsUntil indent end)) (([],) <$> end)
+ (x, (xs, e)) <- listItemContentsUntil indent (try (optional blankline *> indentWith indent *> manyTill spaceChar (string "::") *> descriptionsUntil indent end)) (([],) <$> end)
return (x:xs, e)
definitionListItemsUntil :: PandocMonad m
@@ -656,8 +633,8 @@ definitionListItemsUntil indent end =
where
continuation = try $ do
pos <- getPosition
- term <- trimInlinesF . mconcat <$> manyTill (choice inlineList) (try $ string "::")
- (x, (xs, e)) <- descriptionsUntil (sourceColumn pos) (try (optional blankline >> indentWith indent >> continuation) <|> (([],) <$> end))
+ term <- trimInlinesF . mconcat <$> manyTill inline' (try $ string "::")
+ (x, (xs, e)) <- descriptionsUntil (sourceColumn pos) (try (optional blankline *> indentWith indent *> continuation) <|> (([],) <$> end))
let xx = (,) <$> term <*> sequence x
return (xx:xs, e)
@@ -666,9 +643,7 @@ definitionListUntil :: PandocMonad m
=> MuseParser m a -- ^ Terminator parser
-> MuseParser m (F Blocks, a)
definitionListUntil end = try $ do
- many spaceChar
- pos <- getPosition
- let indent = sourceColumn pos - 1
+ indent <- getIndent
guardDisabled Ext_amuse <|> guard (indent /= 0) -- Initial space is required by Amusewiki, but not Emacs Muse
first (fmap B.definitionList . sequence) <$> definitionListItemsUntil indent end
@@ -713,7 +688,7 @@ museAppendElement element tbl =
tableCell :: PandocMonad m => MuseParser m (F Blocks)
tableCell = try $ fmap B.plain . trimInlinesF . mconcat <$> manyTill inline (lookAhead cellEnd)
- where cellEnd = try $ void (many1 spaceChar >> char '|') <|> eol
+ where cellEnd = try $ void (many1 spaceChar *> char '|') <|> eol
tableElements :: PandocMonad m => MuseParser m (F [MuseTableElement])
tableElements = sequence <$> (tableParseElement `sepEndBy1` eol)
@@ -735,11 +710,10 @@ tableParseElement = tableParseHeader
tableParseRow :: PandocMonad m
=> Int -- ^ Number of separator characters
-> MuseParser m (F [Blocks])
-tableParseRow n = try $ do
- fields <- tableCell `sepBy2` fieldSep
- return $ sequence fields
- where p `sepBy2` sep = (:) <$> p <*> many1 (sep >> p)
- fieldSep = many1 spaceChar >> count n (char '|') >> (void (many1 spaceChar) <|> void (lookAhead newline))
+tableParseRow n = try $
+ sequence <$> (tableCell `sepBy2` fieldSep)
+ where p `sepBy2` sep = (:) <$> p <*> many1 (sep *> p)
+ fieldSep = many1 spaceChar *> count n (char '|') *> (void (many1 spaceChar) <|> void (lookAhead newline))
-- | Parse a table header row.
tableParseHeader :: PandocMonad m => MuseParser m (F MuseTableElement)
@@ -755,53 +729,51 @@ tableParseFooter = fmap MuseFooterRow <$> tableParseRow 3
-- | Parse table caption.
tableParseCaption :: PandocMonad m => MuseParser m (F MuseTableElement)
-tableParseCaption = try $ do
- many spaceChar
- string "|+"
- fmap MuseCaption <$> (trimInlinesF . mconcat <$> many1Till inline (string "+|"))
+tableParseCaption = try $ fmap MuseCaption . trimInlinesF . mconcat
+ <$ many spaceChar
+ <* string "|+"
+ <*> many1Till inline (try $ string "+|")
-- ** Inline parsers
-inlineList :: PandocMonad m => [MuseParser m (F Inlines)]
-inlineList = [ whitespace
- , br
- , anchor
- , footnote
- , strong
- , strongTag
- , emph
- , emphTag
- , underlined
- , superscriptTag
- , subscriptTag
- , strikeoutTag
- , verbatimTag
- , classTag
- , nbsp
- , link
- , code
- , codeTag
- , mathTag
- , inlineLiteralTag
- , str
- , symbol
- ]
+inline' :: PandocMonad m => MuseParser m (F Inlines)
+inline' = whitespace
+ <|> br
+ <|> anchor
+ <|> footnote
+ <|> strong
+ <|> strongTag
+ <|> emph
+ <|> emphTag
+ <|> underlined
+ <|> superscriptTag
+ <|> subscriptTag
+ <|> strikeoutTag
+ <|> verbatimTag
+ <|> classTag
+ <|> nbsp
+ <|> linkOrImage
+ <|> code
+ <|> codeTag
+ <|> mathTag
+ <|> inlineLiteralTag
+ <|> str
+ <|> symbol
+ <?> "inline"
inline :: PandocMonad m => MuseParser m (F Inlines)
-inline = endline <|> choice inlineList <?> "inline"
+inline = endline <|> inline'
-- | Parse a soft break.
endline :: PandocMonad m => MuseParser m (F Inlines)
-endline = try $ do
- newline
- notFollowedBy blankline
- return $ return B.softbreak
+endline = try $ pure B.softbreak <$ newline <* notFollowedBy blankline
parseAnchor :: PandocMonad m => MuseParser m String
-parseAnchor = try $ do
- getPosition >>= \pos -> guard (sourceColumn pos == 1)
- char '#'
- (:) <$> letter <*> many (letter <|> digit <|> char '-')
+parseAnchor = try $ (:)
+ <$ firstColumn
+ <* char '#'
+ <*> letter
+ <*> many (letter <|> digit <|> char '-')
anchor :: PandocMonad m => MuseParser m (F Inlines)
anchor = try $ do
@@ -812,7 +784,7 @@ anchor = try $ do
-- | Parse a footnote reference.
footnote :: PandocMonad m => MuseParser m (F Inlines)
footnote = try $ do
- inLink <- museInLink <$> getState
+ inLink <- asks museInLink
guard $ not inLink
ref <- noteMarker
return $ do
@@ -825,33 +797,38 @@ footnote = try $ do
return $ B.note contents'
whitespace :: PandocMonad m => MuseParser m (F Inlines)
-whitespace = try $ do
- skipMany1 spaceChar
- return $ return B.space
+whitespace = try $ pure B.space <$ skipMany1 spaceChar
-- | Parse @\<br>@ tag.
br :: PandocMonad m => MuseParser m (F Inlines)
-br = try $ do
- string "<br>"
- return $ return B.linebreak
+br = try $ pure B.linebreak <$ string "<br>"
emphasisBetween :: (PandocMonad m, Show a) => MuseParser m a -> MuseParser m (F Inlines)
emphasisBetween c = try $ enclosedInlines c c
+-- | Parses material enclosed between start and end parsers.
+enclosed :: (Show end, Stream s m Char) => ParserT s st m t -- ^ start parser
+ -> ParserT s st m end -- ^ end parser
+ -> ParserT s st m a -- ^ content parser (to be used repeatedly)
+ -> ParserT s st m [a]
+enclosed start end parser = try $
+ start *> notFollowedBy spaceChar *> many1Till parser end
+
enclosedInlines :: (PandocMonad m, Show a, Show b)
=> MuseParser m a
-> MuseParser m b
-> MuseParser m (F Inlines)
-enclosedInlines start end = try $
- trimInlinesF . mconcat <$> (enclosed (atStart start) end inline <* notFollowedBy (satisfy isLetter))
+enclosedInlines start end = try $ trimInlinesF . mconcat
+ <$> enclosed (atStart start) end inline
+ <* notFollowedBy (satisfy isAlphaNum)
-- | Parse an inline tag, such as @\<em>@ and @\<strong>@.
inlineTag :: PandocMonad m
=> String -- ^ Tag name
-> MuseParser m (F Inlines)
-inlineTag tag = try $ do
- htmlTag (~== TagOpen tag [])
- mconcat <$> manyTill inline (void $ htmlTag (~== TagClose tag))
+inlineTag tag = try $ mconcat
+ <$ openTag tag
+ <*> manyTill inline (closeTag tag)
-- | Parse strong inline markup, indicated by @**@.
strong :: PandocMonad m => MuseParser m (F Inlines)
@@ -864,9 +841,9 @@ emph = fmap B.emph <$> emphasisBetween (char '*')
-- | Parse underline inline markup, indicated by @_@.
-- Supported only in Emacs Muse mode, not Text::Amuse.
underlined :: PandocMonad m => MuseParser m (F Inlines)
-underlined = do
- guardDisabled Ext_amuse -- Supported only by Emacs Muse
- fmap underlineSpan <$> emphasisBetween (char '_')
+underlined = fmap underlineSpan
+ <$ guardDisabled Ext_amuse -- Supported only by Emacs Muse
+ <*> emphasisBetween (char '_')
-- | Parse @\<strong>@ tag.
strongTag :: PandocMonad m => MuseParser m (F Inlines)
@@ -890,21 +867,20 @@ strikeoutTag = fmap B.strikeout <$> inlineTag "del"
-- | Parse @\<verbatim>@ tag.
verbatimTag :: PandocMonad m => MuseParser m (F Inlines)
-verbatimTag = return . B.text . snd <$> htmlElement "verbatim"
+verbatimTag = return . B.text
+ <$ openTag "verbatim"
+ <*> manyTill anyChar (closeTag "verbatim")
-- | Parse @\<class>@ tag.
classTag :: PandocMonad m => MuseParser m (F Inlines)
classTag = do
- (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "class" [])
- res <- manyTill inline (void $ htmlTag (~== TagClose "class"))
- let classes = maybe [] words $ lookup "name" attrs
+ classes <- maybe [] words . lookup "name" <$> openTag "class"
+ res <- manyTill inline $ closeTag "class"
return $ B.spanWith ("", classes, []) <$> mconcat res
-- | Parse "~~" as nonbreaking space.
nbsp :: PandocMonad m => MuseParser m (F Inlines)
-nbsp = try $ do
- string "~~"
- return $ return $ B.str "\160"
+nbsp = try $ pure (B.str "\160") <$ string "~~"
-- | Parse code markup, indicated by @\'=\'@ characters.
code :: PandocMonad m => MuseParser m (F Inlines)
@@ -914,26 +890,27 @@ code = try $ do
guard $ not $ null contents
guard $ head contents `notElem` " \t\n"
guard $ last contents `notElem` " \t\n"
- notFollowedBy $ satisfy isLetter
+ notFollowedBy $ satisfy isAlphaNum
return $ return $ B.code contents
-- | Parse @\<code>@ tag.
codeTag :: PandocMonad m => MuseParser m (F Inlines)
-codeTag = return . uncurry B.codeWith <$> htmlElement "code"
+codeTag = fmap pure $ B.codeWith
+ <$> (htmlAttrToPandoc <$> openTag "code")
+ <*> manyTill anyChar (closeTag "code")
-- | Parse @\<math>@ tag.
-- @\<math>@ tag is an Emacs Muse extension enabled by @(require 'muse-latex2png)@
mathTag :: PandocMonad m => MuseParser m (F Inlines)
-mathTag = return . B.math . snd <$> htmlElement "math"
+mathTag = return . B.math
+ <$ openTag "math"
+ <*> manyTill anyChar (closeTag "math")
-- | Parse inline @\<literal>@ tag as a raw inline.
inlineLiteralTag :: PandocMonad m => MuseParser m (F Inlines)
-inlineLiteralTag =
- (return . rawInline) <$> htmlElement "literal"
- where
- -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
- format (_, _, kvs) = fromMaybe "html" $ lookup "style" kvs
- rawInline (attrs, content) = B.rawInline (format attrs) content
+inlineLiteralTag = try $ fmap pure $ B.rawInline
+ <$> (fromMaybe "html" . lookup "style" <$> openTag "literal") -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
+ <*> manyTill anyChar (closeTag "literal")
str :: PandocMonad m => MuseParser m (F Inlines)
str = return . B.str <$> many1 alphaNum <* updateLastStrPos
@@ -942,29 +919,58 @@ symbol :: PandocMonad m => MuseParser m (F Inlines)
symbol = return . B.str <$> count 1 nonspaceChar
-- | Parse a link or image.
-link :: PandocMonad m => MuseParser m (F Inlines)
-link = try $ do
- st <- getState
- guard $ not $ museInLink st
- setState $ st{ museInLink = True }
- (url, content) <- linkText
- updateState (\state -> state { museInLink = False })
- return $ case stripPrefix "URL:" url of
- Nothing -> if isImageUrl url
- then B.image url "" <$> fromMaybe (return mempty) content
- else B.link url "" <$> fromMaybe (return $ B.str url) content
- Just url' -> B.link url' "" <$> fromMaybe (return $ B.str url') content
- where -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el
- imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]
- isImageUrl = (`elem` imageExtensions) . takeExtension
+linkOrImage :: PandocMonad m => MuseParser m (F Inlines)
+linkOrImage = try $ do
+ inLink <- asks museInLink
+ guard $ not inLink
+ local (\s -> s { museInLink = True }) (explicitLink <|> image <|> link)
linkContent :: PandocMonad m => MuseParser m (F Inlines)
-linkContent = char '[' >> trimInlinesF . mconcat <$> manyTill inline (string "]")
+linkContent = trimInlinesF . mconcat
+ <$ char '['
+ <*> manyTill inline (char ']')
+
+-- | Parse a link starting with @URL:@
+explicitLink :: PandocMonad m => MuseParser m (F Inlines)
+explicitLink = try $ do
+ string "[[URL:"
+ url <- manyTill anyChar $ char ']'
+ content <- option (pure $ B.str url) linkContent
+ char ']'
+ return $ B.link url "" <$> content
-linkText :: PandocMonad m => MuseParser m (String, Maybe (F Inlines))
-linkText = do
+image :: PandocMonad m => MuseParser m (F Inlines)
+image = try $ do
+ string "[["
+ (url, (ext, width, align)) <- manyUntil (noneOf "]") (imageExtensionAndOptions <* char ']')
+ content <- option mempty linkContent
+ char ']'
+ let widthAttr = case align of
+ Just 'f' -> [("width", fromMaybe "100" width ++ "%"), ("height", "75%")]
+ _ -> maybeToList (("width",) . (++ "%") <$> width)
+ let alignClass = case align of
+ Just 'r' -> ["align-right"]
+ Just 'l' -> ["align-left"]
+ Just 'f' -> []
+ _ -> []
+ return $ B.imageWith ("", alignClass, widthAttr) (url ++ ext) mempty <$> content
+ where -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el
+ imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]
+ imageExtension = choice (try . string <$> imageExtensions)
+ imageExtensionAndOptions = do
+ ext <- imageExtension
+ (width, align) <- option (Nothing, Nothing) imageAttrs
+ return (ext, width, align)
+ imageAttrs = (,)
+ <$ many1 spaceChar
+ <*> optionMaybe (many1 digit)
+ <* many spaceChar
+ <*> optionMaybe (oneOf "rlf")
+
+link :: PandocMonad m => MuseParser m (F Inlines)
+link = try $ do
string "[["
url <- manyTill anyChar $ char ']'
content <- optionMaybe linkContent
char ']'
- return (url, content)
+ return $ B.link url "" <$> fromMaybe (return $ B.str url) content
diff --git a/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs b/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs
index d3db3a9e2..9e8221248 100644
--- a/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs
+++ b/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs
@@ -100,7 +100,7 @@ liftA fun a = a >>^ fun
-- | Duplicate a value to subsequently feed it into different arrows.
-- Can almost always be replaced with '(&&&)', 'keepingTheValue',
-- or even '(|||)'.
--- Aequivalent to
+-- Equivalent to
-- > returnA &&& returnA
duplicate :: (Arrow a) => a b (b,b)
duplicate = arr $ join (,)
@@ -114,7 +114,7 @@ infixr 2 >>%
-- | Duplicate a value and apply an arrow to the second instance.
--- Aequivalent to
+-- Equivalent to
-- > \a -> duplicate >>> second a
-- or
-- > \a -> returnA &&& a
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs b/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs
index 6d96897aa..e76bbf5cf 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs
@@ -50,7 +50,7 @@ class (Eq nsID, Ord nsID) => NameSpaceID nsID where
getNamespaceID :: NameSpaceIRI
-> NameSpaceIRIs nsID
-> Maybe (NameSpaceIRIs nsID, nsID)
- -- | Given a namespace id, lookup its IRI. May be overriden for performance.
+ -- | Given a namespace id, lookup its IRI. May be overridden for performance.
getIRI :: nsID
-> NameSpaceIRIs nsID
-> Maybe NameSpaceIRI
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs b/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs
index 616d9290b..45c6cd58c 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs
@@ -61,7 +61,7 @@ import qualified Data.Foldable as F (Foldable, foldr)
import Data.Maybe
--- | Aequivalent to
+-- | Equivalent to
-- > foldr (.) id
-- where '(.)' are 'id' are the ones from "Control.Category"
-- and 'foldr' is the one from "Data.Foldable".
@@ -72,7 +72,7 @@ import Data.Maybe
composition :: (Category cat, F.Foldable f) => f (cat a a) -> cat a a
composition = F.foldr (<<<) Cat.id
--- | Aequivalent to
+-- | Equivalent to
-- > foldr (flip (.)) id
-- where '(.)' are 'id' are the ones from "Control.Category"
-- and 'foldr' is the one from "Data.Foldable".
@@ -133,9 +133,7 @@ class Lookupable a where
-- can be used directly in almost any case.
readLookupables :: (Lookupable a) => String -> [(a,String)]
readLookupables s = [ (a,rest) | (word,rest) <- lex s,
- let result = lookup word lookupTable,
- isJust result,
- let Just a = result
+ a <- maybeToList (lookup word lookupTable)
]
-- | Very similar to a simple 'lookup' in the 'lookupTable', but with a lexer.
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs b/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs
index 81392e16b..2327ea908 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs
@@ -261,7 +261,7 @@ convertingExtraState v a = withSubStateF setVAsExtraState modifyWithA
-- The resulting converter even behaves like an identity converter on the
-- value level.
--
--- Aequivalent to
+-- Equivalent to
--
-- > \v x a -> convertingExtraState v (returnV x >>> a)
--
diff --git a/src/Text/Pandoc/Readers/Odt/StyleReader.hs b/src/Text/Pandoc/Readers/Odt/StyleReader.hs
index e0444559b..6a1682829 100644
--- a/src/Text/Pandoc/Readers/Odt/StyleReader.hs
+++ b/src/Text/Pandoc/Readers/Odt/StyleReader.hs
@@ -138,7 +138,7 @@ fontPitchReader = executeIn NsOffice "font-face-decls" (
lookupDefaultingAttr NsStyle "font-pitch"
))
>>?^ ( M.fromList . foldl accumLegalPitches [] )
- )
+ ) `ifFailedDo` (returnV (Right M.empty))
where accumLegalPitches ls (Nothing,_) = ls
accumLegalPitches ls (Just n,p) = (n,p):ls
@@ -342,7 +342,7 @@ instance Read XslUnit where
readsPrec _ _ = []
-- | Rough conversion of measures into millimetres.
--- Pixels and em's are actually implementation dependant/relative measures,
+-- Pixels and em's are actually implementation dependent/relative measures,
-- so I could not really easily calculate anything exact here even if I wanted.
-- But I do not care about exactness right now, as I only use measures
-- to determine if a paragraph is "indented" or not.
diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs
index 888cd9307..1c52c3477 100644
--- a/src/Text/Pandoc/Readers/Org/Blocks.hs
+++ b/src/Text/Pandoc/Readers/Org/Blocks.hs
@@ -40,7 +40,7 @@ import Text.Pandoc.Readers.Org.Meta (metaExport, metaKey, metaLine)
import Text.Pandoc.Readers.Org.ParserState
import Text.Pandoc.Readers.Org.Parsing
import Text.Pandoc.Readers.Org.Shared (cleanLinkString, isImageFilename,
- originalLang, translateLang)
+ originalLang, translateLang, exportsCode)
import Text.Pandoc.Builder (Blocks, Inlines)
import Text.Pandoc.Class (PandocMonad)
@@ -314,9 +314,6 @@ codeBlock blockAttrs blockType = do
labelledBlock :: F Inlines -> F Blocks
labelledBlock = fmap (B.plain . B.spanWith ("", ["label"], []))
- exportsCode :: [(String, String)] -> Bool
- exportsCode = maybe True (`elem` ["code", "both"]) . lookup "exports"
-
exportsResults :: [(String, String)] -> Bool
exportsResults = maybe False (`elem` ["results", "both"]) . lookup "exports"
@@ -743,7 +740,7 @@ latexEnd envName = try $
--
--- Footnote defintions
+-- Footnote definitions
--
noteBlock :: PandocMonad m => OrgParser m (F Blocks)
noteBlock = try $ do
diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs
index c9465581a..7d55892fe 100644
--- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs
+++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
{-
Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -17,8 +16,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- |
Module : Text.Pandoc.Readers.Org.DocumentTree
Copyright : Copyright (C) 2014-2018 Albert Krewinkel
@@ -45,7 +43,7 @@ import Text.Pandoc.Readers.Org.BlockStarts
import Text.Pandoc.Readers.Org.ParserState
import Text.Pandoc.Readers.Org.Parsing
-import qualified Data.Map as Map
+import qualified Data.Set as Set
import qualified Text.Pandoc.Builder as B
--
@@ -60,7 +58,7 @@ documentTree :: PandocMonad m
documentTree blocks inline = do
initialBlocks <- blocks
headlines <- sequence <$> manyTill (headline blocks inline 1) eof
- title <- fmap (getTitle . unMeta) . orgStateMeta <$> getState
+ title <- fmap docTitle . orgStateMeta <$> getState
return $ do
headlines' <- headlines
initialBlocks' <- initialBlocks
@@ -70,19 +68,11 @@ documentTree blocks inline = do
, headlineTodoMarker = Nothing
, headlineText = B.fromList title'
, headlineTags = mempty
+ , headlinePlanning = emptyPlanning
, headlineProperties = mempty
, headlineContents = initialBlocks'
, headlineChildren = headlines'
}
- where
- getTitle :: Map.Map String MetaValue -> [Inline]
- getTitle metamap =
- case Map.lookup "title" metamap of
- Just (MetaInlines inlns) -> inlns
- _ -> []
-
-newtype Tag = Tag { fromTag :: String }
- deriving (Show, Eq)
-- | Create a tag containing the given string.
toTag :: String -> Tag
@@ -117,6 +107,7 @@ data Headline = Headline
, headlineTodoMarker :: Maybe TodoMarker
, headlineText :: Inlines
, headlineTags :: [Tag]
+ , headlinePlanning :: PlanningInfo -- ^ subtree planning information
, headlineProperties :: Properties
, headlineContents :: Blocks
, headlineChildren :: [Headline]
@@ -136,6 +127,7 @@ headline blocks inline lvl = try $ do
title <- trimInlinesF . mconcat <$> manyTill inline endOfTitle
tags <- option [] headerTags
newline
+ planning <- option emptyPlanning planningInfo
properties <- option mempty propertiesDrawer
contents <- blocks
children <- many (headline blocks inline (level + 1))
@@ -148,6 +140,7 @@ headline blocks inline lvl = try $ do
, headlineTodoMarker = todoKw
, headlineText = title'
, headlineTags = tags
+ , headlinePlanning = planning
, headlineProperties = properties
, headlineContents = contents'
, headlineChildren = children'
@@ -158,22 +151,27 @@ headline blocks inline lvl = try $ do
headerTags :: Monad m => OrgParser m [Tag]
headerTags = try $
- let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':'
+ let tag = orgTagWord <* char ':'
in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)
-- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks
headlineToBlocks :: Monad m => Headline -> OrgParser m Blocks
-headlineToBlocks hdln@Headline {..} = do
- maxHeadlineLevels <- getExportSetting exportHeadlineLevels
+headlineToBlocks hdln = do
+ maxLevel <- getExportSetting exportHeadlineLevels
+ let tags = headlineTags hdln
+ let text = headlineText hdln
+ let level = headlineLevel hdln
+ shouldNotExport <- hasDoNotExportTag tags
case () of
- _ | any isNoExportTag headlineTags -> return mempty
- _ | any isArchiveTag headlineTags -> archivedHeadlineToBlocks hdln
- _ | isCommentTitle headlineText -> return mempty
- _ | headlineLevel >= maxHeadlineLevels -> headlineToHeaderWithList hdln
- _ | otherwise -> headlineToHeaderWithContents hdln
+ _ | shouldNotExport -> return mempty
+ _ | any isArchiveTag tags -> archivedHeadlineToBlocks hdln
+ _ | isCommentTitle text -> return mempty
+ _ | maxLevel <= level -> headlineToHeaderWithList hdln
+ _ | otherwise -> headlineToHeaderWithContents hdln
-isNoExportTag :: Tag -> Bool
-isNoExportTag = (== toTag "noexport")
+hasDoNotExportTag :: Monad m => [Tag] -> OrgParser m Bool
+hasDoNotExportTag tags = containsExcludedTag . orgStateExcludedTags <$> getState
+ where containsExcludedTag s = any (`Set.member` s) tags
isArchiveTag :: Tag -> Bool
isArchiveTag = (== toTag "ARCHIVE")
@@ -182,8 +180,9 @@ isArchiveTag = (== toTag "ARCHIVE")
-- FIXME: This accesses builder internals not intended for use in situations
-- like these. Replace once keyword parsing is supported.
isCommentTitle :: Inlines -> Bool
-isCommentTitle (B.toList -> (Str "COMMENT":_)) = True
-isCommentTitle _ = False
+isCommentTitle inlns = case B.toList inlns of
+ (Str "COMMENT":_) -> True
+ _ -> False
archivedHeadlineToBlocks :: Monad m => Headline -> OrgParser m Blocks
archivedHeadlineToBlocks hdln = do
@@ -194,17 +193,23 @@ archivedHeadlineToBlocks hdln = do
ArchivedTreesHeadlineOnly -> headlineToHeader hdln
headlineToHeaderWithList :: Monad m => Headline -> OrgParser m Blocks
-headlineToHeaderWithList hdln@Headline {..} = do
+headlineToHeaderWithList hdln = do
maxHeadlineLevels <- getExportSetting exportHeadlineLevels
header <- headlineToHeader hdln
- listElements <- mapM headlineToBlocks headlineChildren
+ listElements <- mapM headlineToBlocks (headlineChildren hdln)
+ planningBlock <- planningToBlock (headlinePlanning hdln)
let listBlock = if null listElements
then mempty
else B.orderedList listElements
- let headerText = if maxHeadlineLevels == headlineLevel
+ let headerText = if maxHeadlineLevels == headlineLevel hdln
then header
else flattenHeader header
- return $ headerText <> headlineContents <> listBlock
+ return . mconcat $
+ [ headerText
+ , headlineContents hdln
+ , planningBlock
+ , listBlock
+ ]
where
flattenHeader :: Blocks -> Blocks
flattenHeader blks =
@@ -213,27 +218,28 @@ headlineToHeaderWithList hdln@Headline {..} = do
_ -> mempty
headlineToHeaderWithContents :: Monad m => Headline -> OrgParser m Blocks
-headlineToHeaderWithContents hdln@Headline {..} = do
+headlineToHeaderWithContents hdln = do
header <- headlineToHeader hdln
- childrenBlocks <- mconcat <$> mapM headlineToBlocks headlineChildren
- return $ header <> headlineContents <> childrenBlocks
+ planningBlock <- planningToBlock (headlinePlanning hdln)
+ childrenBlocks <- mconcat <$> mapM headlineToBlocks (headlineChildren hdln)
+ return $ header <> planningBlock <> headlineContents hdln <> childrenBlocks
headlineToHeader :: Monad m => Headline -> OrgParser m Blocks
-headlineToHeader Headline {..} = do
+headlineToHeader hdln = do
exportTodoKeyword <- getExportSetting exportWithTodoKeywords
exportTags <- getExportSetting exportWithTags
let todoText = if exportTodoKeyword
- then case headlineTodoMarker of
+ then case headlineTodoMarker hdln of
Just kw -> todoKeywordToInlines kw <> B.space
Nothing -> mempty
else mempty
- let text = todoText <> headlineText <>
+ let text = todoText <> headlineText hdln <>
if exportTags
- then tagsToInlines headlineTags
+ then tagsToInlines (headlineTags hdln)
else mempty
- let propAttr = propertiesToAttr headlineProperties
- attr <- registerHeader propAttr headlineText
- return $ B.headerWith attr headlineLevel text
+ let propAttr = propertiesToAttr (headlineProperties hdln)
+ attr <- registerHeader propAttr (headlineText hdln)
+ return $ B.headerWith attr (headlineLevel hdln) text
todoKeyword :: Monad m => OrgParser m TodoMarker
todoKeyword = try $ do
@@ -277,9 +283,60 @@ tagsToInlines tags =
tagSpan :: Tag -> Inlines -> Inlines
tagSpan t = B.spanWith ("", ["tag"], [("tag-name", fromTag t)])
+-- | Render planning info as a block iff the respective export setting is
+-- enabled.
+planningToBlock :: Monad m => PlanningInfo -> OrgParser m Blocks
+planningToBlock planning = do
+ includePlanning <- getExportSetting exportWithPlanning
+ return $
+ if includePlanning
+ then B.plain . mconcat . intersperse B.space . filter (/= mempty) $
+ [ datumInlines planningClosed "CLOSED"
+ , datumInlines planningDeadline "DEADLINE"
+ , datumInlines planningScheduled "SCHEDULED"
+ ]
+ else mempty
+ where
+ datumInlines field name =
+ case field planning of
+ Nothing -> mempty
+ Just time -> B.strong (B.str name <> B.str ":")
+ <> B.space
+ <> B.emph (B.str time)
+
+-- | An Org timestamp, including repetition marks. TODO: improve
+type Timestamp = String
+
+timestamp :: Monad m => OrgParser m Timestamp
+timestamp = try $ do
+ openChar <- oneOf "<["
+ let isActive = openChar == '<'
+ let closeChar = if isActive then '>' else ']'
+ content <- many1Till anyChar (char closeChar)
+ return (openChar : content ++ [closeChar])
+
+-- | Planning information for a subtree/headline.
+data PlanningInfo = PlanningInfo
+ { planningClosed :: Maybe Timestamp
+ , planningDeadline :: Maybe Timestamp
+ , planningScheduled :: Maybe Timestamp
+ }
+emptyPlanning :: PlanningInfo
+emptyPlanning = PlanningInfo Nothing Nothing Nothing
-
+-- | Read a single planning-related and timestamped line.
+planningInfo :: Monad m => OrgParser m PlanningInfo
+planningInfo = try $ do
+ updaters <- many1 planningDatum <* skipSpaces <* newline
+ return $ foldr ($) emptyPlanning updaters
+ where
+ planningDatum = skipSpaces *> choice
+ [ updateWith (\s p -> p { planningScheduled = Just s}) "SCHEDULED"
+ , updateWith (\d p -> p { planningDeadline = Just d}) "DEADLINE"
+ , updateWith (\c p -> p { planningClosed = Just c}) "CLOSED"
+ ]
+ updateWith fn cs = fn <$> (string cs *> char ':' *> skipSpaces *> timestamp)
-- | Read a :PROPERTIES: drawer and return the key/value pairs contained
-- within.
diff --git a/src/Text/Pandoc/Readers/Org/ExportSettings.hs b/src/Text/Pandoc/Readers/Org/ExportSettings.hs
index d02eb37c5..f79ee0d64 100644
--- a/src/Text/Pandoc/Readers/Org/ExportSettings.hs
+++ b/src/Text/Pandoc/Readers/Org/ExportSettings.hs
@@ -69,7 +69,7 @@ exportSetting = choice
, integerSetting "H" (\val es -> es { exportHeadlineLevels = val })
, ignoredSetting "inline"
, ignoredSetting "num"
- , ignoredSetting "p"
+ , booleanSetting "p" (\val es -> es { exportWithPlanning = val })
, ignoredSetting "pri"
, ignoredSetting "prop"
, ignoredSetting "stat"
diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs
index 7d1568b80..a5335ca57 100644
--- a/src/Text/Pandoc/Readers/Org/Inlines.hs
+++ b/src/Text/Pandoc/Readers/Org/Inlines.hs
@@ -39,7 +39,7 @@ import Text.Pandoc.Readers.Org.BlockStarts (endOfBlock, noteMarker)
import Text.Pandoc.Readers.Org.ParserState
import Text.Pandoc.Readers.Org.Parsing
import Text.Pandoc.Readers.Org.Shared (cleanLinkString, isImageFilename,
- originalLang, translateLang)
+ originalLang, translateLang, exportsCode)
import Text.Pandoc.Builder (Inlines)
import qualified Text.Pandoc.Builder as B
@@ -510,7 +510,7 @@ anchor = try $ do
<* string ">>"
<* skipSpaces
--- | Replace every char but [a-zA-Z0-9_.-:] with a hypen '-'. This mirrors
+-- | Replace every char but [a-zA-Z0-9_.-:] with a hyphen '-'. This mirrors
-- the org function @org-export-solidify-link-text@.
solidify :: String -> String
@@ -525,11 +525,13 @@ inlineCodeBlock :: PandocMonad m => OrgParser m (F Inlines)
inlineCodeBlock = try $ do
string "src_"
lang <- many1 orgArgWordChar
- opts <- option [] $ enclosedByPair '[' ']' inlineBlockOption
+ opts <- option [] $ try (enclosedByPair '[' ']' inlineBlockOption)
+ <|> (mempty <$ string "[]")
inlineCode <- enclosedByPair '{' '}' (noneOf "\n\r")
let attrClasses = [translateLang lang]
let attrKeyVal = originalLang lang <> opts
- returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode
+ let codeInlineBlck = B.codeWith ("", attrClasses, attrKeyVal) inlineCode
+ returnF $ (if exportsCode opts then codeInlineBlck else mempty)
where
inlineBlockOption :: PandocMonad m => OrgParser m (String, String)
inlineBlockOption = try $ do
diff --git a/src/Text/Pandoc/Readers/Org/Meta.hs b/src/Text/Pandoc/Readers/Org/Meta.hs
index 965e33d94..cad1d7123 100644
--- a/src/Text/Pandoc/Readers/Org/Meta.hs
+++ b/src/Text/Pandoc/Readers/Org/Meta.hs
@@ -52,6 +52,7 @@ import Data.Char (toLower)
import Data.List (intersperse)
import Data.Maybe (fromMaybe)
import qualified Data.Map as M
+import qualified Data.Set as Set
import Network.HTTP (urlEncode)
-- | Returns the current meta, respecting export options.
@@ -158,6 +159,7 @@ optionLine = try $ do
"seq_todo" -> todoSequence >>= updateState . registerTodoSequence
"typ_todo" -> todoSequence >>= updateState . registerTodoSequence
"macro" -> macroDefinition >>= updateState . registerMacro
+ "exclude_tags" -> excludedTagList >>= updateState . setExcludedTags
"pandoc-emphasis-pre" -> emphChars >>= updateState . setEmphasisPreChar
"pandoc-emphasis-post" -> emphChars >>= updateState . setEmphasisPostChar
_ -> mzero
@@ -190,6 +192,18 @@ parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend
rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r")
tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:""))
+excludedTagList :: Monad m => OrgParser m [Tag]
+excludedTagList = do
+ skipSpaces
+ map Tag <$> many (orgTagWord <* skipSpaces) <* newline
+
+setExcludedTags :: [Tag] -> OrgParserState -> OrgParserState
+setExcludedTags tagList st =
+ let finalSet = if orgStateExcludedTagsChanged st
+ then foldr Set.insert (orgStateExcludedTags st) tagList
+ else Set.fromList tagList
+ in st { orgStateExcludedTags = finalSet, orgStateExcludedTagsChanged = True}
+
setEmphasisPreChar :: Maybe [Char] -> OrgParserState -> OrgParserState
setEmphasisPreChar csMb st =
let preChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb
diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs
index 4cb5bb626..59478256f 100644
--- a/src/Text/Pandoc/Readers/Org/ParserState.hs
+++ b/src/Text/Pandoc/Readers/Org/ParserState.hs
@@ -33,6 +33,7 @@ module Text.Pandoc.Readers.Org.ParserState
, defaultOrgParserState
, OrgParserLocal (..)
, OrgNoteRecord
+ , Tag(..)
, HasReaderOptions (..)
, HasQuoteContext (..)
, HasMacros (..)
@@ -88,6 +89,9 @@ type OrgNoteTable = [OrgNoteRecord]
type OrgLinkFormatters = M.Map String (String -> String)
-- | Macro expander function
type MacroExpander = [String] -> String
+-- | Tag
+newtype Tag = Tag { fromTag :: String }
+ deriving (Show, Eq, Ord)
-- | The states in which a todo item can be
data TodoState = Todo | Done
@@ -113,6 +117,8 @@ data OrgParserState = OrgParserState
-- specified here.
, orgStateEmphasisPostChars :: [Char] -- ^ Chars allowed at after emphasis
, orgStateEmphasisNewlines :: Maybe Int
+ , orgStateExcludedTags :: Set.Set Tag
+ , orgStateExcludedTagsChanged :: Bool
, orgStateExportSettings :: ExportSettings
, orgStateHeaderMap :: M.Map Inlines String
, orgStateIdentifiers :: Set.Set String
@@ -183,6 +189,8 @@ defaultOrgParserState = OrgParserState
, orgStateEmphasisCharStack = []
, orgStateEmphasisNewlines = Nothing
, orgStateExportSettings = def
+ , orgStateExcludedTags = Set.singleton $ Tag "noexport"
+ , orgStateExcludedTagsChanged = False
, orgStateHeaderMap = M.empty
, orgStateIdentifiers = Set.empty
, orgStateIncludeFiles = []
@@ -260,6 +268,7 @@ data ExportSettings = ExportSettings
, exportWithAuthor :: Bool -- ^ Include author in final meta-data
, exportWithCreator :: Bool -- ^ Include creator in final meta-data
, exportWithEmail :: Bool -- ^ Include email in final meta-data
+ , exportWithPlanning :: Bool -- ^ Keep planning info after headlines
, exportWithTags :: Bool -- ^ Keep tags as part of headlines
, exportWithTodoKeywords :: Bool -- ^ Keep TODO keywords in headers
}
@@ -280,6 +289,7 @@ defaultExportSettings = ExportSettings
, exportWithAuthor = True
, exportWithCreator = True
, exportWithEmail = True
+ , exportWithPlanning = False
, exportWithTags = True
, exportWithTodoKeywords = True
}
diff --git a/src/Text/Pandoc/Readers/Org/Parsing.hs b/src/Text/Pandoc/Readers/Org/Parsing.hs
index e014de65e..52a346e36 100644
--- a/src/Text/Pandoc/Readers/Org/Parsing.hs
+++ b/src/Text/Pandoc/Readers/Org/Parsing.hs
@@ -46,6 +46,8 @@ module Text.Pandoc.Readers.Org.Parsing
, orgArgKey
, orgArgWord
, orgArgWordChar
+ , orgTagWord
+ , orgTagWordChar
-- * Re-exports from Text.Pandoc.Parser
, ParserContext (..)
, many1Till
@@ -137,14 +139,13 @@ anyLine =
<* updateLastPreCharPos
<* updateLastForbiddenCharPos
--- The version Text.Pandoc.Parsing cannot be used, as we need additional parts
--- of the state saved and restored.
+-- | Like @'Text.Pandoc.Parsing'@, but resets the position of the last character
+-- allowed before emphasised text.
parseFromString :: Monad m => OrgParser m a -> String -> OrgParser m a
parseFromString parser str' = do
- oldLastPreCharPos <- orgStateLastPreCharPos <$> getState
updateState $ \s -> s{ orgStateLastPreCharPos = Nothing }
result <- P.parseFromString parser str'
- updateState $ \s -> s{ orgStateLastPreCharPos = oldLastPreCharPos }
+ updateState $ \s -> s { orgStateLastPreCharPos = Nothing }
return result
-- | Skip one or more tab or space characters.
@@ -221,3 +222,9 @@ orgArgWord = many1 orgArgWordChar
-- | Chars treated as part of a word in plists.
orgArgWordChar :: Monad m => OrgParser m Char
orgArgWordChar = alphaNum <|> oneOf "-_"
+
+orgTagWord :: Monad m => OrgParser m String
+orgTagWord = many1 orgTagWordChar
+
+orgTagWordChar :: Monad m => OrgParser m Char
+orgTagWordChar = alphaNum <|> oneOf "@%#_"
diff --git a/src/Text/Pandoc/Readers/Org/Shared.hs b/src/Text/Pandoc/Readers/Org/Shared.hs
index 17fe34738..71d1dd517 100644
--- a/src/Text/Pandoc/Readers/Org/Shared.hs
+++ b/src/Text/Pandoc/Readers/Org/Shared.hs
@@ -32,6 +32,7 @@ module Text.Pandoc.Readers.Org.Shared
, isImageFilename
, originalLang
, translateLang
+ , exportsCode
) where
import Prelude
@@ -96,3 +97,6 @@ translateLang cs =
"sh" -> "bash"
"sqlite" -> "sql"
_ -> cs
+
+exportsCode :: [(String, String)] -> Bool
+exportsCode = maybe True (`elem` ["code", "both"]) . lookup "exports"
diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs
index 71a38cf82..28fa7b83e 100644
--- a/src/Text/Pandoc/Readers/RST.hs
+++ b/src/Text/Pandoc/Readers/RST.hs
@@ -37,7 +37,7 @@ import Control.Arrow (second)
import Control.Monad (forM_, guard, liftM, mplus, mzero, when)
import Control.Monad.Except (throwError)
import Control.Monad.Identity (Identity (..))
-import Data.Char (isHexDigit, isSpace, toLower, toUpper)
+import Data.Char (isHexDigit, isSpace, toLower, toUpper, isAlphaNum)
import Data.List (deleteFirstsBy, elemIndex, intercalate, isInfixOf, isSuffixOf,
nub, sort, transpose, union)
import qualified Data.Map as M
@@ -172,6 +172,7 @@ parseRST = do
docMinusKeys <- concat <$>
manyTill (referenceKey <|> anchorDef <|>
noteBlock <|> citationBlock <|>
+ (snd <$> withRaw comment) <|>
headerBlock <|> lineClump) eof
setInput docMinusKeys
setPosition startPos
@@ -1089,7 +1090,7 @@ referenceKey = do
targetURI :: Monad m => ParserT [Char] st m [Char]
targetURI = do
skipSpaces
- optional newline
+ optional $ try $ newline >> notFollowedBy blankline
contents <- trim <$>
many1 (satisfy (/='\n')
<|> try (newline >> many1 spaceChar >> noneOf " \t\n"))
@@ -1313,19 +1314,24 @@ table = gridTable False <|> simpleTable False <|>
inline :: PandocMonad m => RSTParser m Inlines
inline = choice [ note -- can start with whitespace, so try before ws
- , whitespace
, link
- , str
- , endline
, strong
, emph
, code
, subst
, interpretedRole
- , smart
- , hyphens
- , escapedChar
- , symbol ] <?> "inline"
+ , inlineContent ] <?> "inline"
+
+-- strings, spaces and other characters that can appear either by
+-- themselves or within inline markup
+inlineContent :: PandocMonad m => RSTParser m Inlines
+inlineContent = choice [ whitespace
+ , str
+ , endline
+ , smart
+ , hyphens
+ , escapedChar
+ , symbol ] <?> "inline content"
parseInlineFromString :: PandocMonad m => String -> RSTParser m Inlines
parseInlineFromString = parseFromString' (trimInlines . mconcat <$> many inline)
@@ -1368,11 +1374,11 @@ atStart p = do
emph :: PandocMonad m => RSTParser m Inlines
emph = B.emph . trimInlines . mconcat <$>
- enclosed (atStart $ char '*') (char '*') inline
+ enclosed (atStart $ char '*') (char '*') inlineContent
strong :: PandocMonad m => RSTParser m Inlines
strong = B.strong . trimInlines . mconcat <$>
- enclosed (atStart $ string "**") (try $ string "**") inline
+ enclosed (atStart $ string "**") (try $ string "**") inlineContent
-- Note, this doesn't precisely implement the complex rule in
-- http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#inline-markup-recognition-rules
@@ -1380,7 +1386,6 @@ strong = B.strong . trimInlines . mconcat <$>
--
-- TODO:
-- - Classes are silently discarded in addNewRole
--- - Lacks sensible implementation for title-reference (which is the default)
-- - Allows direct use of the :raw: role, rST only allows inherited use.
interpretedRole :: PandocMonad m => RSTParser m Inlines
interpretedRole = try $ do
@@ -1390,12 +1395,12 @@ interpretedRole = try $ do
renderRole :: PandocMonad m
=> String -> Maybe String -> String -> Attr -> RSTParser m Inlines
renderRole contents fmt role attr = case role of
- "sup" -> return $ B.superscript $ B.str contents
- "superscript" -> return $ B.superscript $ B.str contents
- "sub" -> return $ B.subscript $ B.str contents
- "subscript" -> return $ B.subscript $ B.str contents
- "emphasis" -> return $ B.emph $ B.str contents
- "strong" -> return $ B.strong $ B.str contents
+ "sup" -> return $ B.superscript $ treatAsText contents
+ "superscript" -> return $ B.superscript $ treatAsText contents
+ "sub" -> return $ B.subscript $ treatAsText contents
+ "subscript" -> return $ B.subscript $ treatAsText contents
+ "emphasis" -> return $ B.emph $ treatAsText contents
+ "strong" -> return $ B.strong $ treatAsText contents
"rfc-reference" -> return $ rfcLink contents
"RFC" -> return $ rfcLink contents
"pep-reference" -> return $ pepLink contents
@@ -1406,7 +1411,7 @@ renderRole contents fmt role attr = case role of
"title" -> titleRef contents
"t" -> titleRef contents
"code" -> return $ B.codeWith (addClass "sourceCode" attr) contents
- "span" -> return $ B.spanWith attr $ B.str contents
+ "span" -> return $ B.spanWith attr $ treatAsText contents
"raw" -> return $ B.rawInline (fromMaybe "" fmt) contents
custom -> do
customRoles <- stateRstCustomRoles <$> getState
@@ -1414,14 +1419,20 @@ renderRole contents fmt role attr = case role of
Just (newRole, newFmt, newAttr) ->
renderRole contents newFmt newRole newAttr
Nothing -> -- undefined role
- return $ B.spanWith ("",[],[("role",role)]) (B.str contents)
+ return $ B.codeWith ("",["interpreted-text"],[("role",role)])
+ contents
where
- titleRef ref = return $ B.str ref -- FIXME: Not a sensible behaviour
+ titleRef ref = return $ B.spanWith ("",["title-ref"],[]) $ treatAsText ref
rfcLink rfcNo = B.link rfcUrl ("RFC " ++ rfcNo) $ B.str ("RFC " ++ rfcNo)
where rfcUrl = "http://www.faqs.org/rfcs/rfc" ++ rfcNo ++ ".html"
pepLink pepNo = B.link pepUrl ("PEP " ++ pepNo) $ B.str ("PEP " ++ pepNo)
where padNo = replicate (4 - length pepNo) '0' ++ pepNo
pepUrl = "http://www.python.org/dev/peps/pep-" ++ padNo ++ "/"
+ treatAsText = B.text . handleEscapes
+ handleEscapes [] = []
+ handleEscapes ('\\':' ':cs) = handleEscapes cs
+ handleEscapes ('\\':c:cs) = c : handleEscapes cs
+ handleEscapes (c:cs) = c : handleEscapes cs
addClass :: String -> Attr -> Attr
addClass c (ident, classes, keyValues) = (ident, classes `union` [c], keyValues)
@@ -1445,7 +1456,18 @@ roleAfter = try $ do
return (role,contents)
unmarkedInterpretedText :: PandocMonad m => RSTParser m [Char]
-unmarkedInterpretedText = enclosed (atStart $ char '`') (char '`') anyChar
+unmarkedInterpretedText = try $ do
+ atStart (char '`')
+ contents <- mconcat <$> (many1
+ ( many1 (noneOf "`\\\n")
+ <|> (char '\\' >> ((\c -> ['\\',c]) <$> noneOf "\n"))
+ <|> (string "\n" <* notFollowedBy blankline)
+ <|> try (string "`" <*
+ notFollowedBy (() <$ roleMarker) <*
+ lookAhead (satisfy isAlphaNum))
+ ))
+ char '`'
+ return contents
whitespace :: PandocMonad m => RSTParser m Inlines
whitespace = B.space <$ skipMany1 spaceChar <?> "whitespace"
@@ -1480,7 +1502,7 @@ explicitLink = try $ do
char '`'
notFollowedBy (char '`') -- `` marks start of inline code
label' <- trimInlines . mconcat <$>
- manyTill (notFollowedBy (char '`') >> inline) (char '<')
+ manyTill (notFollowedBy (char '`') >> inlineContent) (char '<')
src <- trim <$> manyTill (noneOf ">\n") (char '>')
skipSpaces
string "`_"
diff --git a/src/Text/Pandoc/Readers/TWiki.hs b/src/Text/Pandoc/Readers/TWiki.hs
index 1f230ae7e..c3cfedcfb 100644
--- a/src/Text/Pandoc/Readers/TWiki.hs
+++ b/src/Text/Pandoc/Readers/TWiki.hs
@@ -74,9 +74,6 @@ type TWParser = ParserT [Char] ParserState
tryMsg :: String -> TWParser m a -> TWParser m a
tryMsg msg p = try p <?> msg
-skip :: TWParser m a -> TWParser m ()
-skip parser = parser >> return ()
-
nested :: PandocMonad m => TWParser m a -> TWParser m a
nested p = do
nestlevel <- stateMaxNestingLevel <$> getState
@@ -92,7 +89,7 @@ htmlElement tag = tryMsg tag $ do
content <- manyTill anyChar (endtag <|> endofinput)
return (htmlAttrToPandoc attr, trim content)
where
- endtag = skip $ htmlTag (~== TagClose tag)
+ endtag = void $ htmlTag (~== TagClose tag)
endofinput = lookAhead $ try $ skipMany blankline >> skipSpaces >> eof
trim = dropWhile (=='\n') . reverse . dropWhile (=='\n') . reverse
@@ -114,18 +111,15 @@ parseHtmlContentWithAttrs tag parser = do
endOfContent = try $ skipMany blankline >> skipSpaces >> eof
parseHtmlContent :: PandocMonad m => String -> TWParser m a -> TWParser m [a]
-parseHtmlContent tag p = parseHtmlContentWithAttrs tag p >>= return . snd
+parseHtmlContent tag p = snd <$> parseHtmlContentWithAttrs tag p
--
-- main parser
--
parseTWiki :: PandocMonad m => TWParser m Pandoc
-parseTWiki = do
- bs <- mconcat <$> many block
- spaces
- eof
- return $ B.doc bs
+parseTWiki =
+ B.doc . mconcat <$> many block <* spaces <* eof
--
@@ -158,7 +152,7 @@ separator = tryMsg "separator" $ string "---" >> newline >> return B.horizontalR
header :: PandocMonad m => TWParser m B.Blocks
header = tryMsg "header" $ do
string "---"
- level <- many1 (char '+') >>= return . length
+ level <- length <$> many1 (char '+')
guard $ level <= 6
classes <- option [] $ string "!!" >> return ["unnumbered"]
skipSpaces
@@ -167,11 +161,10 @@ header = tryMsg "header" $ do
return $ B.headerWith attr level content
verbatim :: PandocMonad m => TWParser m B.Blocks
-verbatim = (htmlElement "verbatim" <|> htmlElement "pre")
- >>= return . (uncurry B.codeBlockWith)
+verbatim = uncurry B.codeBlockWith <$> (htmlElement "verbatim" <|> htmlElement "pre")
literal :: PandocMonad m => TWParser m B.Blocks
-literal = htmlElement "literal" >>= return . rawBlock
+literal = rawBlock <$> htmlElement "literal"
where
format (_, _, kvs) = fromMaybe "html" $ lookup "format" kvs
rawBlock (attrs, content) = B.rawBlock (format attrs) content
@@ -183,7 +176,7 @@ list prefix = choice [ bulletList prefix
definitionList :: PandocMonad m => String -> TWParser m B.Blocks
definitionList prefix = tryMsg "definitionList" $ do
- indent <- lookAhead $ string prefix *> (many1 $ string " ") <* string "$ "
+ indent <- lookAhead $ string prefix *> many1 (string " ") <* string "$ "
elements <- many $ parseDefinitionListItem (prefix ++ concat indent)
return $ B.definitionList elements
where
@@ -193,7 +186,7 @@ definitionList prefix = tryMsg "definitionList" $ do
string (indent ++ "$ ") >> skipSpaces
term <- many1Till inline $ string ": "
line <- listItemLine indent $ string "$ "
- return $ (mconcat term, [line])
+ return (mconcat term, [line])
bulletList :: PandocMonad m => String -> TWParser m B.Blocks
bulletList prefix = tryMsg "bulletList" $
@@ -227,25 +220,24 @@ parseListItem prefix marker = string prefix >> marker >> listItemLine prefix mar
listItemLine :: (PandocMonad m, Show a)
=> String -> TWParser m a -> TWParser m B.Blocks
-listItemLine prefix marker = lineContent >>= parseContent >>= return . mconcat
+listItemLine prefix marker = mconcat <$> (lineContent >>= parseContent)
where
lineContent = do
content <- anyLine
continuation <- optionMaybe listContinuation
- return $ filterSpaces content ++ "\n" ++ (maybe "" (" " ++) continuation)
+ return $ filterSpaces content ++ "\n" ++ maybe "" (" " ++) continuation
filterSpaces = reverse . dropWhile (== ' ') . reverse
listContinuation = notFollowedBy (string prefix >> marker) >>
string " " >> lineContent
parseContent = parseFromString' $ many1 $ nestedList <|> parseInline
- parseInline = many1Till inline (lastNewline <|> newlineBeforeNestedList) >>=
- return . B.plain . mconcat
+ parseInline = (B.plain . mconcat) <$> many1Till inline (lastNewline <|> newlineBeforeNestedList)
nestedList = list prefix
lastNewline = try $ char '\n' <* eof
newlineBeforeNestedList = try $ char '\n' <* lookAhead nestedList
table :: PandocMonad m => TWParser m B.Blocks
table = try $ do
- tableHead <- optionMaybe $ many1Till tableParseHeader newline >>= return . unzip
+ tableHead <- optionMaybe (unzip <$> many1Till tableParseHeader newline)
rows <- many1 tableParseRow
return $ buildTable mempty rows $ fromMaybe (align rows, columns rows) tableHead
where
@@ -258,11 +250,11 @@ table = try $ do
tableParseHeader :: PandocMonad m => TWParser m ((Alignment, Double), B.Blocks)
tableParseHeader = try $ do
char '|'
- leftSpaces <- many spaceChar >>= return . length
+ leftSpaces <- length <$> many spaceChar
char '*'
content <- tableColumnContent (char '*' >> skipSpaces >> char '|')
char '*'
- rightSpaces <- many spaceChar >>= return . length
+ rightSpaces <- length <$> many spaceChar
optional tableEndOfRow
return (tableAlign leftSpaces rightSpaces, content)
where
@@ -283,13 +275,13 @@ tableEndOfRow :: PandocMonad m => TWParser m Char
tableEndOfRow = lookAhead (try $ char '|' >> char '\n') >> char '|'
tableColumnContent :: PandocMonad m => TWParser m a -> TWParser m B.Blocks
-tableColumnContent end = manyTill content (lookAhead $ try end) >>= return . B.plain . mconcat
+tableColumnContent end = (B.plain . mconcat) <$> manyTill content (lookAhead $ try end)
where
content = continuation <|> inline
continuation = try $ char '\\' >> newline >> return mempty
blockQuote :: PandocMonad m => TWParser m B.Blocks
-blockQuote = parseHtmlContent "blockquote" block >>= return . B.blockQuote . mconcat
+blockQuote = (B.blockQuote . mconcat) <$> parseHtmlContent "blockquote" block
noautolink :: PandocMonad m => TWParser m B.Blocks
noautolink = do
@@ -300,15 +292,15 @@ noautolink = do
setState $ st{ stateAllowLinks = True }
return $ mconcat blocks
where
- parseContent = parseFromString' $ many $ block
+ parseContent = parseFromString' $ many block
para :: PandocMonad m => TWParser m B.Blocks
-para = many1Till inline endOfParaElement >>= return . result . mconcat
+para = (result . mconcat) <$> many1Till inline endOfParaElement
where
endOfParaElement = lookAhead $ endOfInput <|> endOfPara <|> newBlockElement
endOfInput = try $ skipMany blankline >> skipSpaces >> eof
endOfPara = try $ blankline >> skipMany1 blankline
- newBlockElement = try $ blankline >> skip blockElements
+ newBlockElement = try $ blankline >> void blockElements
result content = if F.all (==Space) content
then mempty
else B.para $ B.trimInlines content
@@ -340,7 +332,7 @@ inline = choice [ whitespace
] <?> "inline"
whitespace :: PandocMonad m => TWParser m B.Inlines
-whitespace = (lb <|> regsp) >>= return
+whitespace = lb <|> regsp
where lb = try $ skipMany spaceChar >> linebreak >> return B.space
regsp = try $ skipMany1 spaceChar >> return B.space
@@ -362,13 +354,13 @@ enclosed :: (Monoid b, PandocMonad m, Show a)
=> TWParser m a -> (TWParser m a -> TWParser m b) -> TWParser m b
enclosed sep p = between sep (try $ sep <* endMarker) p
where
- endMarker = lookAhead $ skip endSpace <|> skip (oneOf ".,!?:)|") <|> eof
+ endMarker = lookAhead $ void endSpace <|> void (oneOf ".,!?:)|") <|> eof
endSpace = (spaceChar <|> newline) >> return B.space
macro :: PandocMonad m => TWParser m B.Inlines
macro = macroWithParameters <|> withoutParameters
where
- withoutParameters = enclosed (char '%') (\_ -> macroName) >>= return . emptySpan
+ withoutParameters = emptySpan <$> enclosed (char '%') (const macroName)
emptySpan name = buildSpan name [] mempty
macroWithParameters :: PandocMonad m => TWParser m B.Inlines
@@ -393,13 +385,13 @@ macroName = do
return (first:rest)
attributes :: PandocMonad m => TWParser m (String, [(String, String)])
-attributes = char '{' *> spnl *> many (attribute <* spnl) <* char '}' >>=
- return . foldr (either mkContent mkKvs) ([], [])
+attributes = foldr (either mkContent mkKvs) ([], [])
+ <$> (char '{' *> spnl *> many (attribute <* spnl) <* char '}')
where
spnl = skipMany (spaceChar <|> newline)
mkContent c ([], kvs) = (c, kvs)
mkContent c (rest, kvs) = (c ++ " " ++ rest, kvs)
- mkKvs kv (cont, rest) = (cont, (kv : rest))
+ mkKvs kv (cont, rest) = (cont, kv : rest)
attribute :: PandocMonad m => TWParser m (Either String (String, String))
attribute = withKey <|> withoutKey
@@ -407,52 +399,50 @@ attribute = withKey <|> withoutKey
withKey = try $ do
key <- macroName
char '='
- parseValue False >>= return . (curry Right key)
- withoutKey = try $ parseValue True >>= return . Left
- parseValue allowSpaces = (withQuotes <|> withoutQuotes allowSpaces) >>= return . fromEntities
+ curry Right key <$> parseValue False
+ withoutKey = try $ Left <$> parseValue True
+ parseValue allowSpaces = fromEntities <$> (withQuotes <|> withoutQuotes allowSpaces)
withQuotes = between (char '"') (char '"') (\_ -> count 1 $ noneOf ['"'])
withoutQuotes allowSpaces
- | allowSpaces == True = many1 $ noneOf "}"
- | otherwise = many1 $ noneOf " }"
+ | allowSpaces = many1 $ noneOf "}"
+ | otherwise = many1 $ noneOf " }"
nestedInlines :: (Show a, PandocMonad m)
=> TWParser m a -> TWParser m B.Inlines
nestedInlines end = innerSpace <|> nestedInline
where
- innerSpace = try $ whitespace <* (notFollowedBy end)
+ innerSpace = try $ whitespace <* notFollowedBy end
nestedInline = notFollowedBy whitespace >> nested inline
strong :: PandocMonad m => TWParser m B.Inlines
-strong = try $ enclosed (char '*') nestedInlines >>= return . B.strong
+strong = try $ B.strong <$> enclosed (char '*') nestedInlines
strongHtml :: PandocMonad m => TWParser m B.Inlines
-strongHtml = (parseHtmlContent "strong" inline <|> parseHtmlContent "b" inline)
- >>= return . B.strong . mconcat
+strongHtml = B.strong . mconcat <$> (parseHtmlContent "strong" inline <|> parseHtmlContent "b" inline)
strongAndEmph :: PandocMonad m => TWParser m B.Inlines
-strongAndEmph = try $ enclosed (string "__") nestedInlines >>= return . B.emph . B.strong
+strongAndEmph = try $ B.emph . B.strong <$> enclosed (string "__") nestedInlines
emph :: PandocMonad m => TWParser m B.Inlines
-emph = try $ enclosed (char '_') nestedInlines >>= return . B.emph
+emph = try $ B.emph <$> enclosed (char '_') nestedInlines
emphHtml :: PandocMonad m => TWParser m B.Inlines
-emphHtml = (parseHtmlContent "em" inline <|> parseHtmlContent "i" inline)
- >>= return . B.emph . mconcat
+emphHtml = B.emph . mconcat <$> (parseHtmlContent "em" inline <|> parseHtmlContent "i" inline)
nestedString :: (Show a, PandocMonad m)
=> TWParser m a -> TWParser m String
-nestedString end = innerSpace <|> (count 1 nonspaceChar)
+nestedString end = innerSpace <|> count 1 nonspaceChar
where
innerSpace = try $ many1 spaceChar <* notFollowedBy end
boldCode :: PandocMonad m => TWParser m B.Inlines
-boldCode = try $ enclosed (string "==") nestedString >>= return . B.strong . B.code . fromEntities
+boldCode = try $ (B.strong . B.code . fromEntities) <$> enclosed (string "==") nestedString
htmlComment :: PandocMonad m => TWParser m B.Inlines
htmlComment = htmlTag isCommentTag >> return mempty
code :: PandocMonad m => TWParser m B.Inlines
-code = try $ enclosed (char '=') nestedString >>= return . B.code . fromEntities
+code = try $ (B.code . fromEntities) <$> enclosed (char '=') nestedString
codeHtml :: PandocMonad m => TWParser m B.Inlines
codeHtml = do
@@ -464,7 +454,7 @@ autoLink = try $ do
state <- getState
guard $ stateAllowLinks state
(text, url) <- parseLink
- guard $ checkLink (head $ reverse url)
+ guard $ checkLink (last url)
return $ makeLink (text, url)
where
parseLink = notFollowedBy nop >> (uri <|> emailAddress)
@@ -474,17 +464,17 @@ autoLink = try $ do
| otherwise = isAlphaNum c
str :: PandocMonad m => TWParser m B.Inlines
-str = (many1 alphaNum <|> count 1 characterReference) >>= return . B.str
+str = B.str <$> (many1 alphaNum <|> count 1 characterReference)
nop :: PandocMonad m => TWParser m B.Inlines
-nop = try $ (skip exclamation <|> skip nopTag) >> followContent
+nop = try $ (void exclamation <|> void nopTag) >> followContent
where
exclamation = char '!'
nopTag = stringAnyCase "<nop>"
- followContent = many1 nonspaceChar >>= return . B.str . fromEntities
+ followContent = B.str . fromEntities <$> many1 nonspaceChar
symbol :: PandocMonad m => TWParser m B.Inlines
-symbol = count 1 nonspaceChar >>= return . B.str
+symbol = B.str <$> count 1 nonspaceChar
smart :: PandocMonad m => TWParser m B.Inlines
smart = do
@@ -498,17 +488,16 @@ smart = do
singleQuoted :: PandocMonad m => TWParser m B.Inlines
singleQuoted = try $ do
singleQuoteStart
- withQuoteContext InSingleQuote $
- many1Till inline singleQuoteEnd >>=
- (return . B.singleQuoted . B.trimInlines . mconcat)
+ withQuoteContext InSingleQuote
+ (B.singleQuoted . B.trimInlines . mconcat <$> many1Till inline singleQuoteEnd)
doubleQuoted :: PandocMonad m => TWParser m B.Inlines
doubleQuoted = try $ do
doubleQuoteStart
contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
- (withQuoteContext InDoubleQuote $ doubleQuoteEnd >>
+ withQuoteContext InDoubleQuote (doubleQuoteEnd >>
return (B.doubleQuoted $ B.trimInlines contents))
- <|> (return $ (B.str "\8220") B.<> contents)
+ <|> return (B.str "\8220" B.<> contents)
link :: PandocMonad m => TWParser m B.Inlines
link = try $ do
@@ -527,5 +516,5 @@ linkText = do
char ']'
return (url, "", content)
where
- linkContent = (char '[') >> many1Till anyChar (char ']') >>= parseLinkContent
+ linkContent = char '[' >> many1Till anyChar (char ']') >>= parseLinkContent
parseLinkContent = parseFromString' $ many1 inline
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
index bc3bcaf26..4b65be347 100644
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -540,7 +540,7 @@ wordChunk = try $ do
str :: PandocMonad m => ParserT [Char] ParserState m Inlines
str = do
baseStr <- hyphenedWords
- -- RedCloth compliance : if parsed word is uppercase and immediatly
+ -- RedCloth compliance : if parsed word is uppercase and immediately
-- followed by parens, parens content is unconditionally word acronym
fullStr <- option baseStr $ try $ do
guard $ all isUpper baseStr
diff --git a/src/Text/Pandoc/Readers/TikiWiki.hs b/src/Text/Pandoc/Readers/TikiWiki.hs
index 5c7507248..8458b05e5 100644
--- a/src/Text/Pandoc/Readers/TikiWiki.hs
+++ b/src/Text/Pandoc/Readers/TikiWiki.hs
@@ -22,6 +22,7 @@ import Prelude
import Control.Monad
import Control.Monad.Except (throwError)
import qualified Data.Foldable as F
+import Data.List (dropWhileEnd)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
@@ -166,7 +167,7 @@ table = try $ do
-- return $ B.simpleTable (headers rows) $ trace ("rows: " ++ (show rows)) rows
return $B.simpleTable (headers rows) rows
where
- -- The headers are as many empty srings as the number of columns
+ -- The headers are as many empty strings as the number of columns
-- in the first row
headers rows = map (B.plain . B.str) $replicate (length $ head rows) ""
@@ -319,7 +320,7 @@ listItem = choice [
bulletItem :: PandocMonad m => TikiWikiParser m (ListNesting, B.Blocks)
bulletItem = try $ do
prefix <- many1 $ char '*'
- many1 $ char ' '
+ many $ char ' '
content <- listItemLine (length prefix)
return (LN Bullet (length prefix), B.plain content)
@@ -331,7 +332,7 @@ bulletItem = try $ do
numberedItem :: PandocMonad m => TikiWikiParser m (ListNesting, B.Blocks)
numberedItem = try $ do
prefix <- many1 $ char '#'
- many1 $ char ' '
+ many $ char ' '
content <- listItemLine (length prefix)
return (LN Numbered (length prefix), B.plain content)
@@ -346,7 +347,7 @@ listItemLine nest = lineContent >>= parseContent
listContinuation = string (replicate nest '+') >> lineContent
parseContent x = do
parsed <- parseFromString (many1 inline) x
- return $ mconcat parsed
+ return $ mconcat $ dropWhileEnd (== B.space) parsed
-- Turn the CODE macro attributes into Pandoc code block attributes.
mungeAttrs :: [(String, String)] -> (String, [String], [(String, String)])
diff --git a/src/Text/Pandoc/Readers/Txt2Tags.hs b/src/Text/Pandoc/Readers/Txt2Tags.hs
index bed49fd46..26dc934a9 100644
--- a/src/Text/Pandoc/Readers/Txt2Tags.hs
+++ b/src/Text/Pandoc/Readers/Txt2Tags.hs
@@ -198,7 +198,7 @@ para = try $ do
commentBlock :: T2T Blocks
commentBlock = try (blockMarkupArea anyLine (const mempty) "%%%") <|> comment
--- Seperator and Strong line treated the same
+-- Separator and Strong line treated the same
hrule :: T2T Blocks
hrule = try $ do
spaces
@@ -575,8 +575,10 @@ symbol = B.str . (:[]) <$> oneOf specialChars
getTarget :: T2T String
getTarget = do
mv <- lookupMeta "target" . stateMeta <$> getState
- let MetaString target = fromMaybe (MetaString "html") mv
- return target
+ return $ case mv of
+ Just (MetaString target) -> target
+ Just (MetaInlines [Str target]) -> target
+ _ -> "html"
atStart :: T2T ()
atStart = (sourceColumn <$> getPosition) >>= guard . (== 1)
diff --git a/src/Text/Pandoc/Readers/Vimwiki.hs b/src/Text/Pandoc/Readers/Vimwiki.hs
index 824a912c3..15f0d991f 100644
--- a/src/Text/Pandoc/Readers/Vimwiki.hs
+++ b/src/Text/Pandoc/Readers/Vimwiki.hs
@@ -429,9 +429,7 @@ tableRow = try $ do
s <- lookAhead $ manyTill anyChar (try (char '|' >> many spaceChar
>> newline))
guard $ not $ "||" `isInfixOf` ("|" ++ s ++ "|")
- tr <- many tableCell
- many spaceChar >> char '\n'
- return tr
+ many tableCell <* many spaceChar <* char '\n'
tableCell :: PandocMonad m => VwParser m Blocks
tableCell = try $
@@ -451,13 +449,13 @@ ph s = try $ do
noHtmlPh :: PandocMonad m => VwParser m ()
noHtmlPh = try $
- () <$ (many spaceChar >> string "%nohtml" >> many spaceChar
- >> lookAhead newline)
+ () <$ many spaceChar <* string "%nohtml" <* many spaceChar
+ <* lookAhead newline
templatePh :: PandocMonad m => VwParser m ()
templatePh = try $
- () <$ (many spaceChar >> string "%template" >>many (noneOf "\n")
- >> lookAhead newline)
+ () <$ many spaceChar <* string "%template" <* many (noneOf "\n")
+ <* lookAhead newline
-- inline parser
@@ -617,10 +615,8 @@ procImgurl :: String -> String
procImgurl s = if take 6 s == "local:" then "file" ++ drop 5 s else s
inlineMath :: PandocMonad m => VwParser m Inlines
-inlineMath = try $ do
- char '$'
- contents <- many1Till (noneOf "\n") (char '$')
- return $ B.math contents
+inlineMath = try $
+ B.math <$ char '$' <*> many1Till (noneOf "\n") (char '$')
tag :: PandocMonad m => VwParser m Inlines
tag = try $ do
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index 26b01bc90..9f48080b8 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -79,6 +79,7 @@ module Text.Pandoc.Shared (
makeMeta,
eastAsianLineBreakFilter,
underlineSpan,
+ splitSentences,
-- * TagSoup HTML handling
renderTags',
-- * File handling
@@ -94,6 +95,8 @@ module Text.Pandoc.Shared (
-- * for squashing blocks
blocksToInlines,
blocksToInlines',
+ blocksToInlinesWithSep,
+ defaultBlocksSeparator,
-- * Safe read
safeRead,
-- * Temp directory
@@ -580,6 +583,31 @@ eastAsianLineBreakFilter = bottomUp go
underlineSpan :: Inlines -> Inlines
underlineSpan = B.spanWith ("", ["underline"], [])
+-- | Returns the first sentence in a list of inlines, and the rest.
+breakSentence :: [Inline] -> ([Inline], [Inline])
+breakSentence [] = ([],[])
+breakSentence xs =
+ let isSentenceEndInline (Str ys@(_:_)) | last ys == '.' = True
+ isSentenceEndInline (Str ys@(_:_)) | last ys == '?' = True
+ isSentenceEndInline LineBreak = True
+ isSentenceEndInline _ = False
+ (as, bs) = break isSentenceEndInline xs
+ in case bs of
+ [] -> (as, [])
+ [c] -> (as ++ [c], [])
+ (c:Space:cs) -> (as ++ [c], cs)
+ (c:SoftBreak:cs) -> (as ++ [c], cs)
+ (Str ".":Str (')':ys):cs) -> (as ++ [Str ".", Str (')':ys)], cs)
+ (x@(Str ('.':')':_)):cs) -> (as ++ [x], cs)
+ (LineBreak:x@(Str ('.':_)):cs) -> (as ++[LineBreak], x:cs)
+ (c:cs) -> (as ++ [c] ++ ds, es)
+ where (ds, es) = breakSentence cs
+
+-- | Split a list of inlines into sentences.
+splitSentences :: [Inline] -> [[Inline]]
+splitSentences xs =
+ let (sent, rest) = breakSentence xs
+ in if null rest then [sent] else sent : splitSentences rest
--
-- TagSoup HTML handling
@@ -712,7 +740,7 @@ schemes = Set.fromList
, "ws", "wss", "wtai", "wyciwyg", "xcon", "xcon-userid", "xfire"
, "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"
, "z39.50s"
- -- Inofficial schemes
+ -- Unofficial schemes
, "doi", "isbn", "javascript", "pmid"
]
@@ -757,12 +785,19 @@ blocksToInlinesWithSep sep =
mconcat . intersperse sep . map blockToInlines
blocksToInlines' :: [Block] -> Inlines
-blocksToInlines' = blocksToInlinesWithSep parSep
- where parSep = B.space <> B.str "¶" <> B.space
+blocksToInlines' = blocksToInlinesWithSep defaultBlocksSeparator
blocksToInlines :: [Block] -> [Inline]
blocksToInlines = B.toList . blocksToInlines'
+-- | Inline elements used to separate blocks when squashing blocks into
+-- inlines.
+defaultBlocksSeparator :: Inlines
+defaultBlocksSeparator =
+ -- This is used in the pandoc.utils.blocks_to_inlines function. Docs
+ -- there should be updated if this is changed.
+ B.space <> B.str "¶" <> B.space
+
--
-- Safe read
diff --git a/src/Text/Pandoc/Translations.hs b/src/Text/Pandoc/Translations.hs
index 4a216af92..13dcb3b61 100644
--- a/src/Text/Pandoc/Translations.hs
+++ b/src/Text/Pandoc/Translations.hs
@@ -48,11 +48,12 @@ module Text.Pandoc.Translations (
)
where
import Prelude
-import Data.Aeson.Types (typeMismatch)
+import Data.Aeson.Types (Value(..), FromJSON(..))
+import qualified Data.Aeson.Types as Aeson
import qualified Data.HashMap.Strict as HM
import qualified Data.Map as M
import Data.Text as T
-import Data.Yaml as Yaml
+import qualified Data.YAML as YAML
import GHC.Generics (Generic)
import Text.Pandoc.Shared (safeRead)
import qualified Text.Pandoc.UTF8 as UTF8
@@ -90,7 +91,15 @@ instance FromJSON Term where
Just t' -> pure t'
Nothing -> fail $ "Invalid Term name " ++
show t
- parseJSON invalid = typeMismatch "Term" invalid
+ parseJSON invalid = Aeson.typeMismatch "Term" invalid
+
+instance YAML.FromYAML Term where
+ parseYAML (YAML.Scalar (YAML.SStr t)) =
+ case safeRead (T.unpack t) of
+ Just t' -> pure t'
+ Nothing -> fail $ "Invalid Term name " ++
+ show t
+ parseYAML invalid = YAML.typeMismatch "Term" invalid
instance FromJSON Translations where
parseJSON (Object hm) = do
@@ -102,14 +111,28 @@ instance FromJSON Translations where
Just t ->
case v of
(String s) -> return (t, T.unpack $ T.strip s)
- inv -> typeMismatch "String" inv
- parseJSON invalid = typeMismatch "Translations" invalid
+ inv -> Aeson.typeMismatch "String" inv
+ parseJSON invalid = Aeson.typeMismatch "Translations" invalid
+
+instance YAML.FromYAML Translations where
+ parseYAML = YAML.withMap "Translations" $
+ \tr -> Translations .M.fromList <$> mapM addItem (M.toList tr)
+ where addItem (n@(YAML.Scalar (YAML.SStr k)), v) =
+ case safeRead (T.unpack k) of
+ Nothing -> YAML.typeMismatch "Term" n
+ Just t ->
+ case v of
+ (YAML.Scalar (YAML.SStr s)) ->
+ return (t, T.unpack (T.strip s))
+ n' -> YAML.typeMismatch "String" n'
+ addItem (n, _) = YAML.typeMismatch "String" n
lookupTerm :: Term -> Translations -> Maybe String
lookupTerm t (Translations tm) = M.lookup t tm
readTranslations :: String -> Either String Translations
readTranslations s =
- case Yaml.decodeEither' $ UTF8.fromString s of
- Left err' -> Left $ prettyPrintParseException err'
- Right t -> Right t
+ case YAML.decodeStrict $ UTF8.fromString s of
+ Left err' -> Left err'
+ Right (t:_) -> Right t
+ Right [] -> Left "empty YAML document"
diff --git a/src/Text/Pandoc/UUID.hs b/src/Text/Pandoc/UUID.hs
index c1bae7038..60ff269da 100644
--- a/src/Text/Pandoc/UUID.hs
+++ b/src/Text/Pandoc/UUID.hs
@@ -67,13 +67,14 @@ instance Show UUID where
getUUID :: RandomGen g => g -> UUID
getUUID gen =
- let [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] = take 16 $ randoms gen :: [Word8]
- -- set variant
- i' = i `setBit` 7 `clearBit` 6
- -- set version (0100 for random)
- g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4
- in
- UUID a b c d e f g' h i' j k l m n o p
+ case take 16 (randoms gen :: [Word8]) of
+ [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] ->
+ -- set variant
+ let i' = i `setBit` 7 `clearBit` 6
+ -- set version (0100 for random)
+ g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4
+ in UUID a b c d e f g' h i' j k l m n o p
+ _ -> error "not enough random numbers for UUID" -- should not happen
getRandomUUID :: IO UUID
getRandomUUID = getUUID <$> getStdGen
diff --git a/src/Text/Pandoc/Writers/AsciiDoc.hs b/src/Text/Pandoc/Writers/AsciiDoc.hs
index 036185282..ffe5b7473 100644
--- a/src/Text/Pandoc/Writers/AsciiDoc.hs
+++ b/src/Text/Pandoc/Writers/AsciiDoc.hs
@@ -44,7 +44,7 @@ import Data.Aeson (Result (..), Value (String), fromJSON, toJSON)
import Data.Char (isPunctuation, isSpace)
import Data.List (intercalate, intersperse, stripPrefix)
import qualified Data.Map as M
-import Data.Maybe (fromMaybe, isJust)
+import Data.Maybe (fromMaybe, isJust, listToMaybe)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as T
@@ -126,11 +126,16 @@ olMarker = do (start, style', delim) <- anyOrderedListMarker
else spaceChar
-- | True if string begins with an ordered list marker
-beginsWithOrderedListMarker :: String -> Bool
-beginsWithOrderedListMarker str =
- case runParser olMarker defaultParserState "para start" (take 10 str) of
- Left _ -> False
- Right _ -> True
+-- or would be interpreted as an AsciiDoc option command
+needsEscaping :: String -> Bool
+needsEscaping s = beginsWithOrderedListMarker s || isBracketed s
+ where
+ beginsWithOrderedListMarker str =
+ case runParser olMarker defaultParserState "para start" (take 10 str) of
+ Left _ -> False
+ Right _ -> True
+ isBracketed ('[':cs) = listToMaybe (reverse cs) == Just ']'
+ isBracketed _ = False
-- | Convert Pandoc block element to asciidoc.
blockToAsciiDoc :: PandocMonad m
@@ -146,8 +151,8 @@ blockToAsciiDoc opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) =
blockToAsciiDoc opts (Para inlines) = do
contents <- inlineListToAsciiDoc opts inlines
-- escape if para starts with ordered list marker
- let esc = if beginsWithOrderedListMarker (render Nothing contents)
- then text "\\"
+ let esc = if needsEscaping (render Nothing contents)
+ then text "{empty}"
else empty
return $ esc <> contents <> blankline
blockToAsciiDoc opts (LineBlock lns) = do
@@ -280,7 +285,7 @@ blockToAsciiDoc opts (DefinitionList items) = do
contents <- mapM (definitionListItemToAsciiDoc opts) items
return $ cat contents <> blankline
blockToAsciiDoc opts (Div (ident,_,_) bs) = do
- let identifier = if null ident then empty else ("[[" <> text ident <> "]]")
+ let identifier = if null ident then empty else "[[" <> text ident <> "]]"
contents <- blockListToAsciiDoc opts bs
return $ identifier $$ contents
@@ -487,6 +492,6 @@ inlineToAsciiDoc opts (Note [Plain inlines]) = do
-- asciidoc can't handle blank lines in notes
inlineToAsciiDoc _ (Note _) = return "[multiblock footnote omitted]"
inlineToAsciiDoc opts (Span (ident,_,_) ils) = do
- let identifier = if null ident then empty else ("[[" <> text ident <> "]]")
+ let identifier = if null ident then empty else "[[" <> text ident <> "]]"
contents <- inlineListToAsciiDoc opts ils
return $ identifier <> contents
diff --git a/src/Text/Pandoc/Writers/CommonMark.hs b/src/Text/Pandoc/Writers/CommonMark.hs
index 98c1101fa..84ea37f38 100644
--- a/src/Text/Pandoc/Writers/CommonMark.hs
+++ b/src/Text/Pandoc/Writers/CommonMark.hs
@@ -45,7 +45,7 @@ import Network.HTTP (urlEncode)
import Text.Pandoc.Class (PandocMonad)
import Text.Pandoc.Definition
import Text.Pandoc.Options
-import Text.Pandoc.Shared (isTightList, linesToPara, substitute)
+import Text.Pandoc.Shared (isTightList, linesToPara, substitute, capitalize)
import Text.Pandoc.Templates (renderTemplate')
import Text.Pandoc.Walk (query, walk, walkM)
import Text.Pandoc.Writers.HTML (writeHtml5String, tagWithAttributes)
@@ -253,18 +253,34 @@ inlineToNodes opts (Strong xs) = (node STRONG (inlinesToNodes opts xs) :)
inlineToNodes opts (Strikeout xs) =
if isEnabled Ext_strikeout opts
then (node (CUSTOM_INLINE "~~" "~~") (inlinesToNodes opts xs) :)
- else ((node (HTML_INLINE (T.pack "<s>")) [] : inlinesToNodes opts xs ++
- [node (HTML_INLINE (T.pack "</s>")) []]) ++ )
+ else if isEnabled Ext_raw_html opts
+ then ((node (HTML_INLINE (T.pack "<s>")) [] : inlinesToNodes opts xs ++
+ [node (HTML_INLINE (T.pack "</s>")) []]) ++ )
+ else (inlinesToNodes opts xs ++)
inlineToNodes opts (Superscript xs) =
- ((node (HTML_INLINE (T.pack "<sup>")) [] : inlinesToNodes opts xs ++
- [node (HTML_INLINE (T.pack "</sup>")) []]) ++ )
+ if isEnabled Ext_raw_html opts
+ then ((node (HTML_INLINE (T.pack "<sup>")) [] : inlinesToNodes opts xs ++
+ [node (HTML_INLINE (T.pack "</sup>")) []]) ++ )
+ else case traverse toSuperscriptInline xs of
+ Nothing ->
+ ((node (TEXT (T.pack "^(")) [] : inlinesToNodes opts xs ++
+ [node (TEXT (T.pack ")")) []]) ++ )
+ Just xs' -> (inlinesToNodes opts xs' ++)
inlineToNodes opts (Subscript xs) =
- ((node (HTML_INLINE (T.pack "<sub>")) [] : inlinesToNodes opts xs ++
- [node (HTML_INLINE (T.pack "</sub>")) []]) ++ )
+ if isEnabled Ext_raw_html opts
+ then ((node (HTML_INLINE (T.pack "<sub>")) [] : inlinesToNodes opts xs ++
+ [node (HTML_INLINE (T.pack "</sub>")) []]) ++ )
+ else case traverse toSubscriptInline xs of
+ Nothing ->
+ ((node (TEXT (T.pack "_(")) [] : inlinesToNodes opts xs ++
+ [node (TEXT (T.pack ")")) []]) ++ )
+ Just xs' -> (inlinesToNodes opts xs' ++)
inlineToNodes opts (SmallCaps xs) =
- ((node (HTML_INLINE (T.pack "<span class=\"smallcaps\">")) []
- : inlinesToNodes opts xs ++
- [node (HTML_INLINE (T.pack "</span>")) []]) ++ )
+ if isEnabled Ext_raw_html opts
+ then ((node (HTML_INLINE (T.pack "<span class=\"smallcaps\">")) []
+ : inlinesToNodes opts xs ++
+ [node (HTML_INLINE (T.pack "</span>")) []]) ++ )
+ else (inlinesToNodes opts (capitalize xs) ++)
inlineToNodes opts (Link _ ils (url,tit)) =
(node (LINK (T.pack url) (T.pack tit)) (inlinesToNodes opts ils) :)
-- title beginning with fig: indicates implicit figure
@@ -304,6 +320,11 @@ inlineToNodes opts (Math mt str) =
(node (HTML_INLINE (T.pack ("\\(" ++ str ++ "\\)"))) [] :)
DisplayMath ->
(node (HTML_INLINE (T.pack ("\\[" ++ str ++ "\\]"))) [] :)
+inlineToNodes opts (Span ("",["emoji"],kvs) [Str s]) = do
+ case lookup "data-emoji" kvs of
+ Just emojiname | isEnabled Ext_emoji opts ->
+ (node (TEXT (":" <> T.pack emojiname <> ":")) [] :)
+ _ -> (node (TEXT (T.pack s)) [] :)
inlineToNodes opts (Span attr ils) =
let nodes = inlinesToNodes opts ils
op = tagWithAttributes opts True False "span" attr
@@ -314,3 +335,19 @@ inlineToNodes opts (Span attr ils) =
inlineToNodes opts (Cite _ ils) = (inlinesToNodes opts ils ++)
inlineToNodes _ (Note _) = id -- should not occur
-- we remove Note elements in preprocessing
+
+toSubscriptInline :: Inline -> Maybe Inline
+toSubscriptInline Space = Just Space
+toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils
+toSubscriptInline (Str s) = Str <$> traverse toSubscript s
+toSubscriptInline LineBreak = Just LineBreak
+toSubscriptInline SoftBreak = Just SoftBreak
+toSubscriptInline _ = Nothing
+
+toSuperscriptInline :: Inline -> Maybe Inline
+toSuperscriptInline Space = Just Space
+toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils
+toSuperscriptInline (Str s) = Str <$> traverse toSuperscript s
+toSuperscriptInline LineBreak = Just LineBreak
+toSuperscriptInline SoftBreak = Just SoftBreak
+toSuperscriptInline _ = Nothing
diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs
index 10e996bdb..1f9760442 100644
--- a/src/Text/Pandoc/Writers/ConTeXt.hs
+++ b/src/Text/Pandoc/Writers/ConTeXt.hs
@@ -190,10 +190,9 @@ blockToConTeXt (BlockQuote lst) = do
blockToConTeXt (CodeBlock _ str) =
return $ flush ("\\starttyping" <> cr <> text str <> cr <> "\\stoptyping") $$ blankline
-- blankline because \stoptyping can't have anything after it, inc. '}'
-blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline
-blockToConTeXt b@(RawBlock _ _ ) = do
- report $ BlockNotRendered b
- return empty
+blockToConTeXt b@(RawBlock f str)
+ | f == Format "context" || f == Format "tex" = return $ text str <> blankline
+ | otherwise = empty <$ report (BlockNotRendered b)
blockToConTeXt (Div (ident,_,kvs) bs) = do
let align dir txt = "\\startalignment[" <> dir <> "]" $$ txt $$ "\\stopalignment"
mblang <- fromBCP47 (lookup "lang" kvs)
@@ -330,8 +329,7 @@ alignToConTeXt align = case align of
AlignDefault -> empty
listItemToConTeXt :: PandocMonad m => [Block] -> WM m Doc
-listItemToConTeXt list = blockListToConTeXt list >>=
- return . ("\\item" $$) . nest 2
+listItemToConTeXt list = (("\\item" $$) . nest 2) <$> blockListToConTeXt list
defListItemToConTeXt :: PandocMonad m => ([Inline], [[Block]]) -> WM m Doc
defListItemToConTeXt (term, defs) = do
@@ -401,11 +399,9 @@ inlineToConTeXt (Math InlineMath str) =
return $ char '$' <> text str <> char '$'
inlineToConTeXt (Math DisplayMath str) =
return $ text "\\startformula " <> text str <> text " \\stopformula" <> space
-inlineToConTeXt (RawInline "context" str) = return $ text str
-inlineToConTeXt (RawInline "tex" str) = return $ text str
-inlineToConTeXt il@(RawInline _ _) = do
- report $ InlineNotRendered il
- return empty
+inlineToConTeXt il@(RawInline f str)
+ | f == Format "tex" || f == Format "context" = return $ text str
+ | otherwise = empty <$ report (InlineNotRendered il)
inlineToConTeXt LineBreak = return $ text "\\crlf" <> cr
inlineToConTeXt SoftBreak = do
wrapText <- gets (writerWrapText . stOptions)
@@ -457,7 +453,12 @@ inlineToConTeXt (Image attr@(_,cls,_) _ (src, _)) = do
clas = if null cls
then empty
else brackets $ text $ toLabel $ head cls
- src' = if isURI src
+ -- Use / for path separators on Windows; see #4918
+ fixPathSeparators = map $ \c -> case c of
+ '\\' -> '/'
+ _ -> c
+ src' = fixPathSeparators $
+ if isURI src
then src
else unEscapeString src
return $ braces $ "\\externalfigure" <> brackets (text src') <> dims <> clas
diff --git a/src/Text/Pandoc/Writers/Custom.hs b/src/Text/Pandoc/Writers/Custom.hs
index 53b321c7c..37fec9f0f 100644
--- a/src/Text/Pandoc/Writers/Custom.hs
+++ b/src/Text/Pandoc/Writers/Custom.hs
@@ -1,6 +1,6 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
{- Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
This program is free software; you can redistribute it and/or modify
@@ -35,25 +35,26 @@ import Prelude
import Control.Arrow ((***))
import Control.Exception
import Control.Monad (when)
-import Control.Monad.Trans (MonadIO (liftIO))
import Data.Char (toLower)
import Data.List (intersperse)
import qualified Data.Map as M
import Data.Text (Text, pack)
import Data.Typeable
-import Foreign.Lua (Lua, ToLuaStack (..), callFunc)
-import Foreign.Lua.Api
+import Foreign.Lua (Lua, Pushable)
import Text.Pandoc.Class (PandocIO)
import Text.Pandoc.Definition
import Text.Pandoc.Error
-import Text.Pandoc.Lua.Init (runPandocLua, registerScriptPath)
+import Text.Pandoc.Lua.Init (LuaException (LuaException), runPandocLua,
+ registerScriptPath)
import Text.Pandoc.Lua.StackInstances ()
-import Text.Pandoc.Lua.Util (addValue, dostring')
+import Text.Pandoc.Lua.Util (addField, dofileWithTraceback)
import Text.Pandoc.Options
import Text.Pandoc.Templates
import qualified Text.Pandoc.UTF8 as UTF8
import Text.Pandoc.Writers.Shared
+import qualified Foreign.Lua as Lua
+
attrToMap :: Attr -> M.Map String String
attrToMap (id',classes,keyvals) = M.fromList
$ ("id", id')
@@ -62,41 +63,43 @@ attrToMap (id',classes,keyvals) = M.fromList
newtype Stringify a = Stringify a
-instance ToLuaStack (Stringify Format) where
- push (Stringify (Format f)) = push (map toLower f)
+instance Pushable (Stringify Format) where
+ push (Stringify (Format f)) = Lua.push (map toLower f)
-instance ToLuaStack (Stringify [Inline]) where
- push (Stringify ils) = push =<< inlineListToCustom ils
+instance Pushable (Stringify [Inline]) where
+ push (Stringify ils) = Lua.push =<< inlineListToCustom ils
-instance ToLuaStack (Stringify [Block]) where
- push (Stringify blks) = push =<< blockListToCustom blks
+instance Pushable (Stringify [Block]) where
+ push (Stringify blks) = Lua.push =<< blockListToCustom blks
-instance ToLuaStack (Stringify MetaValue) where
- push (Stringify (MetaMap m)) = push (fmap Stringify m)
- push (Stringify (MetaList xs)) = push (map Stringify xs)
- push (Stringify (MetaBool x)) = push x
- push (Stringify (MetaString s)) = push s
- push (Stringify (MetaInlines ils)) = push (Stringify ils)
- push (Stringify (MetaBlocks bs)) = push (Stringify bs)
+instance Pushable (Stringify MetaValue) where
+ push (Stringify (MetaMap m)) = Lua.push (fmap Stringify m)
+ push (Stringify (MetaList xs)) = Lua.push (map Stringify xs)
+ push (Stringify (MetaBool x)) = Lua.push x
+ push (Stringify (MetaString s)) = Lua.push s
+ push (Stringify (MetaInlines ils)) = Lua.push (Stringify ils)
+ push (Stringify (MetaBlocks bs)) = Lua.push (Stringify bs)
-instance ToLuaStack (Stringify Citation) where
+instance Pushable (Stringify Citation) where
push (Stringify cit) = do
- createtable 6 0
- addValue "citationId" $ citationId cit
- addValue "citationPrefix" . Stringify $ citationPrefix cit
- addValue "citationSuffix" . Stringify $ citationSuffix cit
- addValue "citationMode" $ show (citationMode cit)
- addValue "citationNoteNum" $ citationNoteNum cit
- addValue "citationHash" $ citationHash cit
+ Lua.createtable 6 0
+ addField "citationId" $ citationId cit
+ addField "citationPrefix" . Stringify $ citationPrefix cit
+ addField "citationSuffix" . Stringify $ citationSuffix cit
+ addField "citationMode" $ show (citationMode cit)
+ addField "citationNoteNum" $ citationNoteNum cit
+ addField "citationHash" $ citationHash cit
-- | Key-value pair, pushed as a table with @a@ as the only key and @v@ as the
-- associated value.
newtype KeyValue a b = KeyValue (a, b)
-instance (ToLuaStack a, ToLuaStack b) => ToLuaStack (KeyValue a b) where
+instance (Pushable a, Pushable b) => Pushable (KeyValue a b) where
push (KeyValue (k, v)) = do
- newtable
- addValue k v
+ Lua.newtable
+ Lua.push k
+ Lua.push v
+ Lua.rawset (Lua.nthFromTop 3)
data PandocLuaException = PandocLuaException String
deriving (Show, Typeable)
@@ -106,14 +109,13 @@ instance Exception PandocLuaException
-- | Convert Pandoc to custom markup.
writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
writeCustom luaFile opts doc@(Pandoc meta _) = do
- luaScript <- liftIO $ UTF8.readFile luaFile
res <- runPandocLua $ do
registerScriptPath luaFile
- stat <- dostring' luaScript
+ stat <- dofileWithTraceback luaFile
-- check for error in lua script (later we'll change the return type
-- to handle this more gracefully):
- when (stat /= OK) $
- tostring 1 >>= throw . PandocLuaException . UTF8.toString
+ when (stat /= Lua.OK) $
+ Lua.tostring' (-1) >>= throw . PandocLuaException . UTF8.toString
-- TODO - call hierarchicalize, so we have that info
rendered <- docToCustom opts doc
context <- metaToJSON opts
@@ -122,7 +124,7 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
meta
return (rendered, context)
let (body, context) = case res of
- Left e -> throw (PandocLuaException (show e))
+ Left (LuaException msg) -> throw (PandocLuaException msg)
Right x -> x
case writerTemplate opts of
Nothing -> return $ pack body
@@ -134,7 +136,7 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
docToCustom :: WriterOptions -> Pandoc -> Lua String
docToCustom opts (Pandoc (Meta metamap) blocks) = do
body <- blockListToCustom blocks
- callFunc "Doc" body (fmap Stringify metamap) (writerVariables opts)
+ Lua.callFunc "Doc" body (fmap Stringify metamap) (writerVariables opts)
-- | Convert Pandoc block element to Custom.
blockToCustom :: Block -- ^ Block element
@@ -142,52 +144,55 @@ blockToCustom :: Block -- ^ Block element
blockToCustom Null = return ""
-blockToCustom (Plain inlines) = callFunc "Plain" (Stringify inlines)
+blockToCustom (Plain inlines) = Lua.callFunc "Plain" (Stringify inlines)
blockToCustom (Para [Image attr txt (src,tit)]) =
- callFunc "CaptionedImage" src tit (Stringify txt) (attrToMap attr)
+ Lua.callFunc "CaptionedImage" src tit (Stringify txt) (attrToMap attr)
-blockToCustom (Para inlines) = callFunc "Para" (Stringify inlines)
+blockToCustom (Para inlines) = Lua.callFunc "Para" (Stringify inlines)
-blockToCustom (LineBlock linesList) = callFunc "LineBlock" (map Stringify linesList)
+blockToCustom (LineBlock linesList) =
+ Lua.callFunc "LineBlock" (map Stringify linesList)
blockToCustom (RawBlock format str) =
- callFunc "RawBlock" (Stringify format) str
+ Lua.callFunc "RawBlock" (Stringify format) str
-blockToCustom HorizontalRule = callFunc "HorizontalRule"
+blockToCustom HorizontalRule = Lua.callFunc "HorizontalRule"
blockToCustom (Header level attr inlines) =
- callFunc "Header" level (Stringify inlines) (attrToMap attr)
+ Lua.callFunc "Header" level (Stringify inlines) (attrToMap attr)
blockToCustom (CodeBlock attr str) =
- callFunc "CodeBlock" str (attrToMap attr)
+ Lua.callFunc "CodeBlock" str (attrToMap attr)
-blockToCustom (BlockQuote blocks) = callFunc "BlockQuote" (Stringify blocks)
+blockToCustom (BlockQuote blocks) =
+ Lua.callFunc "BlockQuote" (Stringify blocks)
blockToCustom (Table capt aligns widths headers rows) =
let aligns' = map show aligns
capt' = Stringify capt
headers' = map Stringify headers
rows' = map (map Stringify) rows
- in callFunc "Table" capt' aligns' widths headers' rows'
+ in Lua.callFunc "Table" capt' aligns' widths headers' rows'
-blockToCustom (BulletList items) = callFunc "BulletList" (map Stringify items)
+blockToCustom (BulletList items) =
+ Lua.callFunc "BulletList" (map Stringify items)
blockToCustom (OrderedList (num,sty,delim) items) =
- callFunc "OrderedList" (map Stringify items) num (show sty) (show delim)
+ Lua.callFunc "OrderedList" (map Stringify items) num (show sty) (show delim)
blockToCustom (DefinitionList items) =
- callFunc "DefinitionList"
- (map (KeyValue . (Stringify *** map Stringify)) items)
+ Lua.callFunc "DefinitionList"
+ (map (KeyValue . (Stringify *** map Stringify)) items)
blockToCustom (Div attr items) =
- callFunc "Div" (Stringify items) (attrToMap attr)
+ Lua.callFunc "Div" (Stringify items) (attrToMap attr)
-- | Convert list of Pandoc block elements to Custom.
blockListToCustom :: [Block] -- ^ List of block elements
-> Lua String
blockListToCustom xs = do
- blocksep <- callFunc "Blocksep"
+ blocksep <- Lua.callFunc "Blocksep"
bs <- mapM blockToCustom xs
return $ mconcat $ intersperse blocksep bs
@@ -200,51 +205,51 @@ inlineListToCustom lst = do
-- | Convert Pandoc inline element to Custom.
inlineToCustom :: Inline -> Lua String
-inlineToCustom (Str str) = callFunc "Str" str
+inlineToCustom (Str str) = Lua.callFunc "Str" str
-inlineToCustom Space = callFunc "Space"
+inlineToCustom Space = Lua.callFunc "Space"
-inlineToCustom SoftBreak = callFunc "SoftBreak"
+inlineToCustom SoftBreak = Lua.callFunc "SoftBreak"
-inlineToCustom (Emph lst) = callFunc "Emph" (Stringify lst)
+inlineToCustom (Emph lst) = Lua.callFunc "Emph" (Stringify lst)
-inlineToCustom (Strong lst) = callFunc "Strong" (Stringify lst)
+inlineToCustom (Strong lst) = Lua.callFunc "Strong" (Stringify lst)
-inlineToCustom (Strikeout lst) = callFunc "Strikeout" (Stringify lst)
+inlineToCustom (Strikeout lst) = Lua.callFunc "Strikeout" (Stringify lst)
-inlineToCustom (Superscript lst) = callFunc "Superscript" (Stringify lst)
+inlineToCustom (Superscript lst) = Lua.callFunc "Superscript" (Stringify lst)
-inlineToCustom (Subscript lst) = callFunc "Subscript" (Stringify lst)
+inlineToCustom (Subscript lst) = Lua.callFunc "Subscript" (Stringify lst)
-inlineToCustom (SmallCaps lst) = callFunc "SmallCaps" (Stringify lst)
+inlineToCustom (SmallCaps lst) = Lua.callFunc "SmallCaps" (Stringify lst)
-inlineToCustom (Quoted SingleQuote lst) = callFunc "SingleQuoted" (Stringify lst)
+inlineToCustom (Quoted SingleQuote lst) = Lua.callFunc "SingleQuoted" (Stringify lst)
-inlineToCustom (Quoted DoubleQuote lst) = callFunc "DoubleQuoted" (Stringify lst)
+inlineToCustom (Quoted DoubleQuote lst) = Lua.callFunc "DoubleQuoted" (Stringify lst)
-inlineToCustom (Cite cs lst) = callFunc "Cite" (Stringify lst) (map Stringify cs)
+inlineToCustom (Cite cs lst) = Lua.callFunc "Cite" (Stringify lst) (map Stringify cs)
inlineToCustom (Code attr str) =
- callFunc "Code" str (attrToMap attr)
+ Lua.callFunc "Code" str (attrToMap attr)
inlineToCustom (Math DisplayMath str) =
- callFunc "DisplayMath" str
+ Lua.callFunc "DisplayMath" str
inlineToCustom (Math InlineMath str) =
- callFunc "InlineMath" str
+ Lua.callFunc "InlineMath" str
inlineToCustom (RawInline format str) =
- callFunc "RawInline" (Stringify format) str
+ Lua.callFunc "RawInline" (Stringify format) str
-inlineToCustom LineBreak = callFunc "LineBreak"
+inlineToCustom LineBreak = Lua.callFunc "LineBreak"
inlineToCustom (Link attr txt (src,tit)) =
- callFunc "Link" (Stringify txt) src tit (attrToMap attr)
+ Lua.callFunc "Link" (Stringify txt) src tit (attrToMap attr)
inlineToCustom (Image attr alt (src,tit)) =
- callFunc "Image" (Stringify alt) src tit (attrToMap attr)
+ Lua.callFunc "Image" (Stringify alt) src tit (attrToMap attr)
-inlineToCustom (Note contents) = callFunc "Note" (Stringify contents)
+inlineToCustom (Note contents) = Lua.callFunc "Note" (Stringify contents)
inlineToCustom (Span attr items) =
- callFunc "Span" (Stringify items) (attrToMap attr)
+ Lua.callFunc "Span" (Stringify items) (attrToMap attr)
diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs
index f6e814095..3306e4f31 100644
--- a/src/Text/Pandoc/Writers/Docbook.hs
+++ b/src/Text/Pandoc/Writers/Docbook.hs
@@ -126,9 +126,10 @@ writeDocbook opts (Pandoc meta blocks) = do
defField "mathml" (case writerHTMLMathMethod opts of
MathML -> True
_ -> False) metadata
- case writerTemplate opts of
- Nothing -> return main
- Just tpl -> renderTemplate' tpl context
+ (if writerPreferAscii opts then toEntities else id) <$>
+ case writerTemplate opts of
+ Nothing -> return main
+ Just tpl -> renderTemplate' tpl context
-- | Convert an Element to Docbook.
elementToDocbook :: PandocMonad m => WriterOptions -> Int -> Element -> DB m Doc
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
index 1666c0562..524d20fd1 100644
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -66,7 +66,7 @@ import Text.Pandoc.Readers.Docx.StyleMap
import Text.Pandoc.Shared hiding (Element)
import Text.Pandoc.Walk
import Text.Pandoc.Writers.Math
-import Text.Pandoc.Writers.Shared (fixDisplayMath, metaValueToInlines)
+import Text.Pandoc.Writers.Shared
import Text.Printf (printf)
import Text.TeXMath
import Text.XML.Light as XML
@@ -230,7 +230,7 @@ writeDocx opts doc@(Pandoc meta _) = do
let mbAttrMarLeft = (elAttribs <$> mbpgmar) >>= lookupAttrBy ((=="left") . qName)
let mbAttrMarRight = (elAttribs <$> mbpgmar) >>= lookupAttrBy ((=="right") . qName)
- -- Get the avaible area (converting the size and the margins to int and
+ -- Get the available area (converting the size and the margins to int and
-- doing the difference
let pgContentWidth = (-) <$> (read <$> mbAttrSzWidth ::Maybe Integer)
<*> (
@@ -266,8 +266,9 @@ writeDocx opts doc@(Pandoc meta _) = do
-- parse styledoc for heading styles
let styleMaps = getStyleMaps styledoc
- let tocTitle = fromMaybe (stTocTitle defaultWriterState) $
- metaValueToInlines <$> lookupMeta "toc-title" meta
+ let tocTitle = case lookupMetaInlines "toc-title" meta of
+ [] -> stTocTitle defaultWriterState
+ ls -> ls
let initialSt = defaultWriterState {
stStyleMaps = styleMaps
@@ -727,7 +728,7 @@ getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists
makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]
-makeTOC opts | writerTableOfContents opts = do
+makeTOC opts = do
let depth = "1-"++show (writerTOCDepth opts)
let tocCmd = "TOC \\o \""++depth++"\" \\h \\z \\u"
tocTitle <- gets stTocTitle
@@ -751,8 +752,6 @@ makeTOC opts | writerTableOfContents opts = do
) -- w:p
])
])] -- w:sdt
-makeTOC _ = return []
-
-- | Convert Pandoc document to two lists of
-- OpenXML elements (the main document and footnotes).
@@ -761,15 +760,9 @@ writeOpenXML opts (Pandoc meta blocks) = do
let tit = docTitle meta
let auths = docAuthors meta
let dat = docDate meta
- let abstract' = case lookupMeta "abstract" meta of
- Just (MetaBlocks bs) -> bs
- Just (MetaInlines ils) -> [Plain ils]
- _ -> []
- let subtitle' = case lookupMeta "subtitle" meta of
- Just (MetaBlocks [Plain xs]) -> xs
- Just (MetaBlocks [Para xs]) -> xs
- Just (MetaInlines xs) -> xs
- _ -> []
+ let abstract' = lookupMetaBlocks "abstract" meta
+ let subtitle' = lookupMetaInlines "subtitle" meta
+ let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta
title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]
subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]
authors <- withParaProp (pCustomStyle "Author") $ blocksToOpenXML opts $
@@ -801,7 +794,9 @@ writeOpenXML opts (Pandoc meta blocks) = do
] ++ annotation
]
comments' <- mapM toComment comments
- toc <- makeTOC opts
+ toc <- if includeTOC
+ then makeTOC opts
+ else return []
let meta' = title ++ subtitle ++ authors ++ date ++ abstract ++ toc
return (meta' ++ doc', notes', comments')
@@ -908,9 +903,10 @@ blockToOpenXML' opts (Para lst)
| null lst && not (isEnabled Ext_empty_paragraphs opts) = return []
| otherwise = do
isFirstPara <- gets stFirstPara
- paraProps <- getParaProps $ case lst of
- [Math DisplayMath _] -> True
- _ -> False
+ let displayMathPara = case lst of
+ [x] -> isDisplayMath x
+ _ -> False
+ paraProps <- getParaProps displayMathPara
bodyTextStyle <- pStyleM "Body Text"
let paraProps' = case paraProps of
[] | isFirstPara -> [mknode "w:pPr" []
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
index f1ff8b482..6099f0223 100644
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -74,6 +74,7 @@ import Text.Printf (printf)
import Text.XML.Light (Attr (..), Element (..), Node (..), QName (..),
add_attrs, lookupAttr, node, onlyElems, parseXML,
ppElement, showElement, strContent, unode, unqual)
+import Text.Pandoc.XML (escapeStringForXML)
-- A Chapter includes a list of blocks and maybe a section
-- number offset. Note, some chapters are unnumbered. The section
@@ -446,7 +447,8 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
cpContent <- lift $ writeHtml
opts'{ writerVariables =
("coverpage","true"):
- ("pagetitle",plainTitle):
+ ("pagetitle",
+ escapeStringForXML plainTitle):
cssvars True ++ vars }
(Pandoc meta [RawBlock (Format "html") $ "<div id=\"cover-image\">\n<img src=\"../media/" ++ coverImage ++ "\" alt=\"cover image\" />\n</div>"])
imgContent <- lift $ P.readFileLazy img
@@ -459,7 +461,8 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
-- title page
tpContent <- lift $ writeHtml opts'{
writerVariables = ("titlepage","true"):
- ("pagetitle",plainTitle):
+ ("body-type", "frontmatter"):
+ ("pagetitle", escapeStringForXML plainTitle):
cssvars True ++ vars }
(Pandoc meta [])
tpEntry <- mkEntry "text/title_page.xhtml" tpContent
@@ -563,13 +566,28 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
let chapToEntry num (Chapter mbnum bs) =
mkEntry ("text/" ++ showChapter num) =<<
writeHtml opts'{ writerNumberOffset = fromMaybe [] mbnum
- , writerVariables = cssvars True ++ vars }
- (case bs of
- (Header _ _ xs : _) ->
+ , writerVariables = ("body-type", bodyType) :
+ cssvars True ++ vars } pdoc
+ where (pdoc, bodyType) =
+ case bs of
+ (Header _ (_,_,kvs) xs : _) ->
-- remove notes or we get doubled footnotes
- Pandoc (setMeta "title" (walk removeNote $ fromList xs)
- nullMeta) bs
- _ -> Pandoc nullMeta bs)
+ (Pandoc (setMeta "title"
+ (walk removeNote $ fromList xs) nullMeta) bs,
+ case lookup "epub:type" kvs of
+ Nothing -> "bodymatter"
+ Just x
+ | x `elem` frontMatterTypes -> "frontmatter"
+ | x `elem` backMatterTypes -> "backmatter"
+ | otherwise -> "bodymatter")
+ _ -> (Pandoc nullMeta bs, "bodymatter")
+ frontMatterTypes = ["prologue", "abstract", "acknowledgments",
+ "copyright-page", "dedication",
+ "foreword", "halftitle",
+ "introduction", "preface",
+ "seriespage", "titlepage"]
+ backMatterTypes = ["afterword", "appendix", "colophon",
+ "conclusion", "epigraph"]
chapterEntries <- zipWithM chapToEntry [1..] chapters
@@ -754,7 +772,8 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
(writeHtmlStringForEPUB version
opts{ writerTemplate = Nothing
, writerVariables =
- ("pagetitle",plainTitle):
+ ("pagetitle",
+ escapeStringForXML plainTitle):
writerVariables opts}
(Pandoc nullMeta
[Plain $ walk clean tit])) of
@@ -782,7 +801,7 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
[ unode "a" ! [("href", "text/cover.xhtml")
,("epub:type", "cover")] $
"Cover"] |
- epubCoverImage metadata /= Nothing
+ isJust (epubCoverImage metadata)
] ++
[ unode "li"
[ unode "a" ! [("href", "#toc")
diff --git a/src/Text/Pandoc/Writers/FB2.hs b/src/Text/Pandoc/Writers/FB2.hs
index a46011a8f..a139de5cd 100644
--- a/src/Text/Pandoc/Writers/FB2.hs
+++ b/src/Text/Pandoc/Writers/FB2.hs
@@ -119,7 +119,7 @@ description meta' = do
let as = authors meta'
dd <- docdate meta'
annotation <- case lookupMeta "abstract" meta' of
- Just (MetaBlocks bs) -> (list . el "annotation") <$> cMapM blockToXml bs
+ Just (MetaBlocks bs) -> (list . el "annotation") <$> cMapM blockToXml (map unPlain bs)
_ -> pure mempty
let lang = case lookupMeta "lang" meta' of
Just (MetaInlines [Str s]) -> [el "lang" $ iso639 s]
@@ -135,8 +135,9 @@ description meta' = do
Just (MetaString s) -> coverimage s
_ -> return []
return $ el "description"
- [ el "title-info" (genre : (bt ++ annotation ++ as ++ dd ++ lang))
- , el "document-info" (el "program-used" "pandoc" : coverpage)
+ [ el "title-info" (genre :
+ (as ++ bt ++ annotation ++ dd ++ coverpage ++ lang))
+ , el "document-info" [el "program-used" "pandoc"]
]
booktitle :: PandocMonad m => Meta -> FBM m [Content]
@@ -398,6 +399,11 @@ plainToPara (Para inlines : rest) =
Para inlines : HorizontalRule : plainToPara rest -- HorizontalRule will be converted to <empty-line />
plainToPara (p:rest) = p : plainToPara rest
+-- Replace plain text with paragraphs
+unPlain :: Block -> Block
+unPlain (Plain inlines) = Para inlines
+unPlain x = x
+
-- Simulate increased indentation level. Will not really work
-- for multi-line paragraphs.
indentPrefix :: String -> Block -> Block
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
index a09ad2fda..46f754226 100644
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -50,13 +50,13 @@ import Prelude
import Control.Monad.State.Strict
import Data.Char (ord, toLower)
import Data.List (intercalate, intersperse, isPrefixOf, partition)
-import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing)
+import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, mapMaybe)
import qualified Data.Set as Set
import Data.String (fromString)
import Data.Text (Text)
import qualified Data.Text.Lazy as TL
import Network.HTTP (urlEncode)
-import Network.URI (URI (..), parseURIReference, unEscapeString)
+import Network.URI (URI (..), parseURIReference)
import Numeric (showHex)
import Text.Blaze.Internal (customLeaf, customParent, MarkupM(Empty))
#if MIN_VERSION_blaze_markup(0,6,3)
@@ -75,7 +75,7 @@ import Text.Pandoc.Templates
import Text.Pandoc.Walk
import Text.Pandoc.Writers.Math
import Text.Pandoc.Writers.Shared
-import Text.Pandoc.XML (escapeStringForXML, fromEntities)
+import Text.Pandoc.XML (escapeStringForXML, fromEntities, toEntities)
#if MIN_VERSION_blaze_markup(0,6,3)
#else
import Text.Blaze.Internal (preEscapedString, preEscapedText)
@@ -206,7 +206,8 @@ writeHtmlString' :: PandocMonad m
=> WriterState -> WriterOptions -> Pandoc -> m Text
writeHtmlString' st opts d = do
(body, context) <- evalStateT (pandocToHtml opts d) st
- case writerTemplate opts of
+ (if writerPreferAscii opts then toEntities else id) <$>
+ case writerTemplate opts of
Nothing -> return $ renderHtml' body
Just tpl -> do
-- warn if empty lang
@@ -221,16 +222,19 @@ writeHtmlString' st opts d = do
lookup "sourcefile" (writerVariables opts)
report $ NoTitleElement fallback
return $ resetField "pagetitle" fallback context
- renderTemplate' tpl $
- defField "body" (renderHtml' body) context'
+ renderTemplate' tpl
+ (defField "body" (renderHtml' body) context')
writeHtml' :: PandocMonad m => WriterState -> WriterOptions -> Pandoc -> m Html
writeHtml' st opts d =
case writerTemplate opts of
Just _ -> preEscapedText <$> writeHtmlString' st opts d
- Nothing -> do
- (body, _) <- evalStateT (pandocToHtml opts d) st
- return body
+ Nothing
+ | writerPreferAscii opts
+ -> preEscapedText <$> writeHtmlString' st opts d
+ | otherwise -> do
+ (body, _) <- evalStateT (pandocToHtml opts d) st
+ return body
-- result is (title, authors, date, toc, body, new variables)
pandocToHtml :: PandocMonad m
@@ -259,7 +263,7 @@ pandocToHtml opts (Pandoc meta blocks) = do
st <- get
notes <- footnoteSection opts (reverse (stNotes st))
let thebody = blocks' >> notes
- let math = case writerHTMLMathMethod opts of
+ let math = case writerHTMLMathMethod opts of
MathJax url
| slideVariant /= RevealJsSlides ->
-- mathjax is handled via a special plugin in revealjs
@@ -273,10 +277,10 @@ pandocToHtml opts (Pandoc meta blocks) = do
KaTeX url -> do
H.script !
A.src (toValue $ url ++ "katex.min.js") $ mempty
- H.script !
- A.src (toValue $ url ++ "contrib/auto-render.min.js") $ mempty
+ nl opts
H.script
- "document.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body);\n});"
+ "document.addEventListener(\"DOMContentLoaded\", function () {\n var mathElements = document.getElementsByClassName(\"math\");\n for (var i = 0; i < mathElements.length; i++) {\n var texText = mathElements[i].firstChild;\n if (mathElements[i].tagName == \"SPAN\") { katex.render(texText.data, mathElements[i], { displayMode: mathElements[i].classList.contains(\"display\"), throwOnError: false } );\n }}});"
+ nl opts
H.link ! A.rel "stylesheet" !
A.href (toValue $ url ++ "katex.min.css")
@@ -296,10 +300,11 @@ pandocToHtml opts (Pandoc meta blocks) = do
(if stMath st
then defField "math" (renderHtml' math)
else id) $
- defField "mathjax"
- (case writerHTMLMathMethod opts of
- MathJax _ -> True
- _ -> False) $
+ (case writerHTMLMathMethod opts of
+ MathJax u -> defField "mathjax" True .
+ defField "mathjaxurl"
+ (takeWhile (/='?') u)
+ _ -> defField "mathjax" False) $
defField "quotes" (stQuotes st) $
-- for backwards compatibility we populate toc
-- with the contents of the toc, rather than a
@@ -460,7 +465,7 @@ elementToHtml slideLevel opts (Sec level num (id',classes,keyvals) title' elemen
t <- addAttrs opts attr $
secttag header'
return $
- (if slideVariant == RevealJsSlides
+ (if slideVariant == RevealJsSlides && not (null innerContents)
then H5.section
else id) $ mconcat $ t : innerContents
else if writerSectionDivs opts || slide
@@ -576,12 +581,23 @@ toAttrs :: PandocMonad m
=> [(String, String)] -> StateT WriterState m [Attribute]
toAttrs kvs = do
html5 <- gets stHtml5
- return $ map (\(x,y) ->
- customAttribute
- (fromString (if not html5 || x `Set.member` html5Attributes
- || "data-" `isPrefixOf` x
- then x
- else "data-" ++ x)) (toValue y)) kvs
+ mbEpubVersion <- gets stEPUBVersion
+ return $ mapMaybe (\(x,y) ->
+ if html5
+ then
+ if x `Set.member` html5Attributes
+ || ':' `elem` x -- e.g. epub: namespace
+ || "data-" `isPrefixOf` x
+ then Just $ customAttribute (fromString x) (toValue y)
+ else Just $ customAttribute (fromString ("data-" ++ x))
+ (toValue y)
+ else
+ if mbEpubVersion == Just EPUB2 &&
+ not (x `Set.member` html4Attributes ||
+ "xml:" `isPrefixOf` x)
+ then Nothing
+ else Just $ customAttribute (fromString x) (toValue y))
+ kvs
attrsToHtml :: PandocMonad m
=> WriterOptions -> Attr -> StateT WriterState m [Attribute]
@@ -828,9 +844,7 @@ blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do
return $ foldl (!) l attribs
blockToHtml opts (DefinitionList lst) = do
contents <- mapM (\(term, defs) ->
- do term' <- if null term
- then return mempty
- else liftM H.dt $ inlineListToHtml opts term
+ do term' <- liftM H.dt $ inlineListToHtml opts term
defs' <- mapM (liftM (\x -> H.dd (x >> nl opts)) .
blockListToHtml opts) defs
return $ mconcat $ nl opts : term' : nl opts :
@@ -1051,8 +1065,8 @@ inlineToHtml opts inline = do
DisplayMath -> "\\[" ++ str ++ "\\]"
KaTeX _ -> return $ H.span ! A.class_ mathClass $ toHtml $
case t of
- InlineMath -> "\\(" ++ str ++ "\\)"
- DisplayMath -> "\\[" ++ str ++ "\\]"
+ InlineMath -> str
+ DisplayMath -> str
PlainMath -> do
x <- lift (texMathToInlines t str) >>= inlineListToHtml opts
let m = H.span ! A.class_ mathClass $ x
@@ -1084,10 +1098,7 @@ inlineToHtml opts inline = do
in '#' : prefix ++ xs
_ -> s
let link = H.a ! A.href (toValue s') $ linkText
- let attr = if txt == [Str (unEscapeString s)]
- then (ident, "uri" : classes, kvs)
- else (ident, classes, kvs)
- link' <- addAttrs opts attr link
+ link' <- addAttrs opts (ident, classes, kvs) link
return $ if null tit
then link'
else link' ! A.title (toValue tit)
@@ -1422,3 +1433,125 @@ html5Attributes = Set.fromList
, "workertype"
, "wrap"
]
+
+html4Attributes :: Set.Set String
+html4Attributes = Set.fromList
+ [ "abbr"
+ , "accept"
+ , "accept-charset"
+ , "accesskey"
+ , "action"
+ , "align"
+ , "alink"
+ , "alt"
+ , "archive"
+ , "axis"
+ , "background"
+ , "bgcolor"
+ , "border"
+ , "cellpadding"
+ , "cellspacing"
+ , "char"
+ , "charoff"
+ , "charset"
+ , "checked"
+ , "cite"
+ , "class"
+ , "classid"
+ , "clear"
+ , "code"
+ , "codebase"
+ , "codetype"
+ , "color"
+ , "cols"
+ , "colspan"
+ , "compact"
+ , "content"
+ , "coords"
+ , "data"
+ , "datetime"
+ , "declare"
+ , "defer"
+ , "dir"
+ , "disabled"
+ , "enctype"
+ , "face"
+ , "for"
+ , "frame"
+ , "frameborder"
+ , "headers"
+ , "height"
+ , "href"
+ , "hreflang"
+ , "hspace"
+ , "http-equiv"
+ , "id"
+ , "ismap"
+ , "label"
+ , "lang"
+ , "language"
+ , "link"
+ , "longdesc"
+ , "marginheight"
+ , "marginwidth"
+ , "maxlength"
+ , "media"
+ , "method"
+ , "multiple"
+ , "name"
+ , "nohref"
+ , "noresize"
+ , "noshade"
+ , "nowrap"
+ , "object"
+ , "onblur"
+ , "onchange"
+ , "onclick"
+ , "ondblclick"
+ , "onfocus"
+ , "onkeydown"
+ , "onkeypress"
+ , "onkeyup"
+ , "onload"
+ , "onmousedown"
+ , "onmousemove"
+ , "onmouseout"
+ , "onmouseover"
+ , "onmouseup"
+ , "onreset"
+ , "onselect"
+ , "onsubmit"
+ , "onunload"
+ , "profile"
+ , "prompt"
+ , "readonly"
+ , "rel"
+ , "rev"
+ , "rows"
+ , "rowspan"
+ , "rules"
+ , "scheme"
+ , "scope"
+ , "scrolling"
+ , "selected"
+ , "shape"
+ , "size"
+ , "span"
+ , "src"
+ , "standby"
+ , "start"
+ , "style"
+ , "summary"
+ , "tabindex"
+ , "target"
+ , "text"
+ , "title"
+ , "usemap"
+ , "valign"
+ , "value"
+ , "valuetype"
+ , "version"
+ , "vlink"
+ , "vspace"
+ , "width"
+ ]
diff --git a/src/Text/Pandoc/Writers/Haddock.hs b/src/Text/Pandoc/Writers/Haddock.hs
index 75b8c78dc..80e092b6a 100644
--- a/src/Text/Pandoc/Writers/Haddock.hs
+++ b/src/Text/Pandoc/Writers/Haddock.hs
@@ -45,7 +45,6 @@ import Text.Pandoc.Options
import Text.Pandoc.Pretty
import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate')
-import Text.Pandoc.Writers.Math (texMathToInlines)
import Text.Pandoc.Writers.Shared
type Notes = [[Block]]
@@ -208,13 +207,13 @@ blockListToHaddock :: PandocMonad m
-> [Block] -- ^ List of block elements
-> StateT WriterState m Doc
blockListToHaddock opts blocks =
- mapM (blockToHaddock opts) blocks >>= return . cat
+ cat <$> mapM (blockToHaddock opts) blocks
-- | Convert list of Pandoc inline elements to haddock.
inlineListToHaddock :: PandocMonad m
=> WriterOptions -> [Inline] -> StateT WriterState m Doc
inlineListToHaddock opts lst =
- mapM (inlineToHaddock opts) lst >>= return . cat
+ cat <$> mapM (inlineToHaddock opts) lst
-- | Convert Pandoc inline element to haddock.
inlineToHaddock :: PandocMonad m
@@ -250,11 +249,10 @@ inlineToHaddock _ (Code _ str) =
return $ "@" <> text (escapeString str) <> "@"
inlineToHaddock _ (Str str) =
return $ text $ escapeString str
-inlineToHaddock opts (Math mt str) = do
- let adjust x = case mt of
- DisplayMath -> cr <> x <> cr
- InlineMath -> x
- adjust <$> (lift (texMathToInlines mt str) >>= inlineListToHaddock opts)
+inlineToHaddock _ (Math mt str) =
+ return $ case mt of
+ DisplayMath -> cr <> "\\[" <> text str <> "\\]" <> cr
+ InlineMath -> "\\(" <> text str <> "\\)"
inlineToHaddock _ il@(RawInline f str)
| f == "haddock" = return $ text str
| otherwise = do
diff --git a/src/Text/Pandoc/Writers/ICML.hs b/src/Text/Pandoc/Writers/ICML.hs
index 266d58007..ef1e2af0a 100644
--- a/src/Text/Pandoc/Writers/ICML.hs
+++ b/src/Text/Pandoc/Writers/ICML.hs
@@ -149,11 +149,12 @@ writeICML opts (Pandoc meta blocks) = do
$ defField "charStyles" (render' $ charStylesToDoc st)
$ defField "parStyles" (render' $ parStylesToDoc st)
$ defField "hyperlinks" (render' $ hyperlinksToDoc $ links st) metadata
- case writerTemplate opts of
+ (if writerPreferAscii opts then toEntities else id) <$>
+ case writerTemplate opts of
Nothing -> return main
Just tpl -> renderTemplate' tpl context
--- | Auxilary functions for parStylesToDoc and charStylesToDoc.
+-- | Auxiliary functions for parStylesToDoc and charStylesToDoc.
contains :: String -> (String, (String, String)) -> [(String, String)]
contains s rule =
[snd rule | (fst rule) `isInfixOf` s]
diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs
index fb3236bd9..4e78a4cce 100644
--- a/src/Text/Pandoc/Writers/JATS.hs
+++ b/src/Text/Pandoc/Writers/JATS.hs
@@ -102,7 +102,8 @@ docToJATS opts (Pandoc meta blocks) = do
$ defField "mathml" (case writerHTMLMathMethod opts of
MathML -> True
_ -> False) metadata
- case writerTemplate opts of
+ (if writerPreferAscii opts then toEntities else id) <$>
+ case writerTemplate opts of
Nothing -> return main
Just tpl -> renderTemplate' tpl context
@@ -344,7 +345,7 @@ inlineToJATS _ (Str str) = return $ text $ escapeStringForXML str
inlineToJATS opts (Emph lst) =
inTagsSimple "italic" <$> inlinesToJATS opts lst
inlineToJATS opts (Strong lst) =
- inTags False "bold" [("role", "strong")] <$> inlinesToJATS opts lst
+ inTagsSimple "bold" <$> inlinesToJATS opts lst
inlineToJATS opts (Strikeout lst) =
inTagsSimple "strike" <$> inlinesToJATS opts lst
inlineToJATS opts (Superscript lst) =
@@ -352,8 +353,7 @@ inlineToJATS opts (Superscript lst) =
inlineToJATS opts (Subscript lst) =
inTagsSimple "sub" <$> inlinesToJATS opts lst
inlineToJATS opts (SmallCaps lst) =
- inTags False "sc" [("role", "smallcaps")] <$>
- inlinesToJATS opts lst
+ inTagsSimple "sc" <$> inlinesToJATS opts lst
inlineToJATS opts (Quoted SingleQuote lst) = do
contents <- inlinesToJATS opts lst
return $ char '‘' <> contents <> char '’'
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
index 2904bec06..c1b5d0fa4 100644
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -42,8 +42,9 @@ import Data.Aeson (FromJSON, object, (.=))
import Data.Char (isAlphaNum, isAscii, isDigit, isLetter, isPunctuation, ord,
toLower)
import Data.List (foldl', intercalate, intersperse, isInfixOf, nubBy,
- stripPrefix, (\\))
+ stripPrefix, (\\), uncons)
import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)
+import qualified Data.Map as M
import Data.Text (Text)
import qualified Data.Text as T
import Network.URI (unEscapeString)
@@ -63,6 +64,7 @@ import Text.Pandoc.Walk
import Text.Pandoc.Writers.Shared
import qualified Text.Parsec as P
import Text.Printf (printf)
+import qualified Data.Text.Normalize as Normalize
data WriterState =
WriterState { stInNote :: Bool -- true if we're in a note
@@ -176,9 +178,9 @@ pandocToLaTeX options (Pandoc meta blocks) = do
modify $ \s -> s{stCsquotes = True}
let (blocks'', lastHeader) = if writerCiteMethod options == Citeproc then
(blocks', [])
- else case last blocks' of
- Header 1 _ il -> (init blocks', il)
- _ -> (blocks', [])
+ else case reverse blocks' of
+ Header 1 _ il : _ -> (init blocks', il)
+ _ -> (blocks', [])
beamer <- gets stBeamer
blocks''' <- if beamer
then toSlides blocks''
@@ -248,7 +250,8 @@ pandocToLaTeX options (Pandoc meta blocks) = do
defField "biblatex" True
_ -> id) $
defField "colorlinks" (any hasStringValue
- ["citecolor", "urlcolor", "linkcolor", "toccolor"]) $
+ ["citecolor", "urlcolor", "linkcolor", "toccolor",
+ "filecolor"]) $
(if null dirs
then id
else defField "dir" ("ltr" :: String)) $
@@ -317,46 +320,110 @@ data StringContext = TextString
-- escape things as needed for LaTeX
stringToLaTeX :: PandocMonad m => StringContext -> String -> LW m String
-stringToLaTeX _ [] = return ""
-stringToLaTeX ctx (x:xs) = do
+stringToLaTeX context zs = do
opts <- gets stOptions
- rest <- stringToLaTeX ctx xs
- let ligatures = isEnabled Ext_smart opts && ctx == TextString
- let isUrl = ctx == URLString
- return $
+ go opts context $
+ if writerPreferAscii opts
+ then T.unpack $ Normalize.normalize Normalize.NFD $ T.pack zs
+ else zs
+ where
+ go _ _ [] = return ""
+ go opts ctx (x:xs) = do
+ let ligatures = isEnabled Ext_smart opts && ctx == TextString
+ let isUrl = ctx == URLString
+ let mbAccentCmd =
+ if writerPreferAscii opts && ctx == TextString
+ then uncons xs >>= \(c,_) -> M.lookup c accents
+ else Nothing
+ let emits s =
+ case mbAccentCmd of
+ Just cmd -> ((cmd ++ "{" ++ s ++ "}") ++)
+ <$> go opts ctx (drop 1 xs) -- drop combining accent
+ Nothing -> (s++) <$> go opts ctx xs
+ let emitc c =
+ case mbAccentCmd of
+ Just cmd -> ((cmd ++ "{" ++ [c] ++ "}") ++)
+ <$> go opts ctx (drop 1 xs) -- drop combining accent
+ Nothing -> (c:) <$> go opts ctx xs
case x of
- '{' -> "\\{" ++ rest
- '}' -> "\\}" ++ rest
- '`' | ctx == CodeString -> "\\textasciigrave{}" ++ rest
- '$' | not isUrl -> "\\$" ++ rest
- '%' -> "\\%" ++ rest
- '&' -> "\\&" ++ rest
- '_' | not isUrl -> "\\_" ++ rest
- '#' -> "\\#" ++ rest
- '-' | not isUrl -> case xs of
- -- prevent adjacent hyphens from forming ligatures
- ('-':_) -> "-\\/" ++ rest
- _ -> '-' : rest
- '~' | not isUrl -> "\\textasciitilde{}" ++ rest
- '^' -> "\\^{}" ++ rest
- '\\'| isUrl -> '/' : rest -- NB. / works as path sep even on Windows
- | otherwise -> "\\textbackslash{}" ++ rest
- '|' | not isUrl -> "\\textbar{}" ++ rest
- '<' -> "\\textless{}" ++ rest
- '>' -> "\\textgreater{}" ++ rest
- '[' -> "{[}" ++ rest -- to avoid interpretation as
- ']' -> "{]}" ++ rest -- optional arguments
- '\'' | ctx == CodeString -> "\\textquotesingle{}" ++ rest
- '\160' -> "~" ++ rest
- '\x202F' -> "\\," ++ rest
- '\x2026' -> "\\ldots{}" ++ rest
- '\x2018' | ligatures -> "`" ++ rest
- '\x2019' | ligatures -> "'" ++ rest
- '\x201C' | ligatures -> "``" ++ rest
- '\x201D' | ligatures -> "''" ++ rest
- '\x2014' | ligatures -> "---" ++ rest
- '\x2013' | ligatures -> "--" ++ rest
- _ -> x : rest
+ '{' -> emits "\\{"
+ '}' -> emits "\\}"
+ '`' | ctx == CodeString -> emits "\\textasciigrave{}"
+ '$' | not isUrl -> emits "\\$"
+ '%' -> emits "\\%"
+ '&' -> emits "\\&"
+ '_' | not isUrl -> emits "\\_"
+ '#' -> emits "\\#"
+ '-' | not isUrl -> case xs of
+ -- prevent adjacent hyphens from forming ligatures
+ ('-':_) -> emits "-\\/"
+ _ -> emitc '-'
+ '~' | not isUrl -> emits "\\textasciitilde{}"
+ '^' -> emits "\\^{}"
+ '\\'| isUrl -> emitc '/' -- NB. / works as path sep even on Windows
+ | otherwise -> emits "\\textbackslash{}"
+ '|' | not isUrl -> emits "\\textbar{}"
+ '<' -> emits "\\textless{}"
+ '>' -> emits "\\textgreater{}"
+ '[' -> emits "{[}" -- to avoid interpretation as
+ ']' -> emits "{]}" -- optional arguments
+ '\'' | ctx == CodeString -> emits "\\textquotesingle{}"
+ '\160' -> emits "~"
+ '\x202F' -> emits "\\,"
+ '\x2026' -> emits "\\ldots{}"
+ '\x2018' | ligatures -> emits "`"
+ '\x2019' | ligatures -> emits "'"
+ '\x201C' | ligatures -> emits "``"
+ '\x201D' | ligatures -> emits "''"
+ '\x2014' | ligatures -> emits "---"
+ '\x2013' | ligatures -> emits "--"
+ _ | writerPreferAscii opts
+ -> case x of
+ 'ı' -> emits "\\i "
+ 'ȷ' -> emits "\\j "
+ 'å' -> emits "\\aa "
+ 'Å' -> emits "\\AA "
+ 'ß' -> emits "\\ss "
+ 'ø' -> emits "\\o "
+ 'Ø' -> emits "\\O "
+ 'Ł' -> emits "\\L "
+ 'ł' -> emits "\\l "
+ 'æ' -> emits "\\ae "
+ 'Æ' -> emits "\\AE "
+ 'œ' -> emits "\\oe "
+ 'Œ' -> emits "\\OE "
+ '£' -> emits "\\pounds "
+ '€' -> emits "\\euro "
+ '©' -> emits "\\copyright "
+ _ -> emitc x
+ | otherwise -> emitc x
+
+accents :: M.Map Char String
+accents = M.fromList
+ [ ('\779' , "\\H")
+ , ('\768' , "\\`")
+ , ('\769' , "\\'")
+ , ('\770' , "\\^")
+ , ('\771' , "\\~")
+ , ('\776' , "\\\"")
+ , ('\775' , "\\.")
+ , ('\772' , "\\=")
+ , ('\781' , "\\|")
+ , ('\817' , "\\b")
+ , ('\807' , "\\c")
+ , ('\783' , "\\G")
+ , ('\777' , "\\h")
+ , ('\803' , "\\d")
+ , ('\785' , "\\f")
+ , ('\778' , "\\r")
+ , ('\865' , "\\t")
+ , ('\782' , "\\U")
+ , ('\780' , "\\v")
+ , ('\774' , "\\u")
+ , ('\808' , "\\k")
+ , ('\785' , "\\newtie")
+ , ('\8413', "\\textcircled")
+ ]
toLabel :: PandocMonad m => String -> LW m String
toLabel z = go `fmap` stringToLaTeX URLString z
@@ -402,7 +469,8 @@ elementToBeamer slideLevel (Sec lvl _num (ident,classes,kvs) tit elts)
not (null $ query hasCodeBlock elts ++ query hasCode elts)
let frameoptions = ["allowdisplaybreaks", "allowframebreaks", "fragile",
"b", "c", "t", "environment",
- "label", "plain", "shrink", "standout"]
+ "label", "plain", "shrink", "standout",
+ "noframenumbering"]
let optionslist = ["fragile" | fragile && isNothing (lookup "fragile" kvs)] ++
[k | k <- classes, k `elem` frameoptions] ++
[k ++ "=" ++ v | (k,v) <- kvs, k `elem` frameoptions]
@@ -487,7 +555,7 @@ blockToLaTeX (Div (identifier,classes,kvs) bs)
then \contents ->
let fromPct xs =
case reverse xs of
- '%':ds -> '0':'.': reverse ds
+ '%':ds -> showFl (read (reverse ds) / 100 :: Double)
_ -> xs
w = maybe "0.48" fromPct (lookup "width" kvs)
in inCmd "begin" "column" <>
@@ -517,25 +585,15 @@ blockToLaTeX (Plain lst) =
inlineListToLaTeX $ dropWhile isLineBreakOrSpace lst
-- title beginning with fig: indicates that the image is a figure
blockToLaTeX (Para [Image attr@(ident, _, _) txt (src,'f':'i':'g':':':tit)]) = do
- inNote <- gets stInNote
- inMinipage <- gets stInMinipage
- modify $ \st -> st{ stInMinipage = True, stNotes = [] }
- capt <- inlineListToLaTeX txt
- notes <- gets stNotes
- modify $ \st -> st{ stInMinipage = False, stNotes = [] }
-
- -- We can't have footnotes in the list of figures, so remove them:
- captForLof <- if null notes
- then return empty
- else brackets <$> inlineListToLaTeX (walk deNote txt)
- img <- inlineToLaTeX (Image attr txt (src,tit))
- let footnotes = notesToLaTeX notes
+ (capt, captForLof, footnotes) <- getCaption txt
lab <- labelFor ident
let caption = "\\caption" <> captForLof <> braces capt <> lab
+ img <- inlineToLaTeX (Image attr txt (src,tit))
innards <- hypertarget True ident $
"\\centering" $$ img $$ caption <> cr
let figure = cr <> "\\begin{figure}" $$ innards $$ "\\end{figure}"
- return $ if inNote || inMinipage
+ st <- get
+ return $ if stInNote st || stInMinipage st
-- can't have figures in notes or minipage (here, table cell)
-- http://www.tex.ac.uk/FAQ-ouparmd.html
then "\\begin{center}" $$ img $+$ capt $$ "\\end{center}"
@@ -714,11 +772,11 @@ blockToLaTeX (Header level (id',classes,_) lst) = do
modify $ \s -> s{stInHeading = False}
return hdr
blockToLaTeX (Table caption aligns widths heads rows) = do
+ (captionText, captForLof, footnotes) <- getCaption caption
let toHeaders hs = do contents <- tableRowToLaTeX True aligns widths hs
return ("\\toprule" $$ contents $$ "\\midrule")
let removeNote (Note _) = Span ("", [], []) []
removeNote x = x
- captionText <- inlineListToLaTeX caption
firsthead <- if isEmpty captionText || all null heads
then return empty
else ($$ text "\\endfirsthead") <$> toHeaders heads
@@ -730,8 +788,8 @@ blockToLaTeX (Table caption aligns widths heads rows) = do
else walk removeNote heads)
let capt = if isEmpty captionText
then empty
- else text "\\caption" <>
- braces captionText <> "\\tabularnewline"
+ else "\\caption" <> captForLof <> braces captionText
+ <> "\\tabularnewline"
rows' <- mapM (tableRowToLaTeX False aligns widths) rows
let colDescriptors = text $ concatMap toColDescriptor aligns
modify $ \s -> s{ stTable = True }
@@ -745,6 +803,21 @@ blockToLaTeX (Table caption aligns widths heads rows) = do
$$ vcat rows'
$$ "\\bottomrule"
$$ "\\end{longtable}"
+ $$ footnotes
+
+getCaption :: PandocMonad m => [Inline] -> LW m (Doc, Doc, Doc)
+getCaption txt = do
+ inMinipage <- gets stInMinipage
+ modify $ \st -> st{ stInMinipage = True, stNotes = [] }
+ capt <- inlineListToLaTeX txt
+ notes <- gets stNotes
+ modify $ \st -> st{ stInMinipage = inMinipage, stNotes = [] }
+ -- We can't have footnotes in the list of figures/tables, so remove them:
+ captForLof <- if null notes
+ then return empty
+ else brackets <$> inlineListToLaTeX (walk deNote txt)
+ let footnotes = notesToLaTeX notes
+ return (capt, captForLof, footnotes)
toColDescriptor :: Alignment -> String
toColDescriptor align =
@@ -863,9 +936,11 @@ defListItemToLaTeX (term, defs) = do
else term'
def' <- liftM vsep $ mapM blockListToLaTeX defs
return $ case defs of
- ((Header{} : _) : _) ->
+ ((Header{} : _) : _) ->
+ "\\item" <> brackets term'' <> " ~ " $$ def'
+ ((CodeBlock{} : _) : _) -> -- see #4662
"\\item" <> brackets term'' <> " ~ " $$ def'
- _ ->
+ _ ->
"\\item" <> brackets term'' $$ def'
-- | Craft the section header, inserting the secton reference, if supplied.
diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs
index 912231a88..81fa38bd7 100644
--- a/src/Text/Pandoc/Writers/Man.hs
+++ b/src/Text/Pandoc/Writers/Man.hs
@@ -107,7 +107,8 @@ pandocToMan opts (Pandoc meta blocks) = do
$ defField "has-tables" hasTables
$ defField "hyphenate" True
$ defField "pandoc-version" pandocVersion metadata
- case writerTemplate opts of
+ (if writerPreferAscii opts then groffEscape else id) <$>
+ case writerTemplate opts of
Nothing -> return main
Just tpl -> renderTemplate' tpl context
@@ -152,32 +153,6 @@ escapeCode = intercalate "\n" . map escapeLine . lines where
-- line. groff/troff treats the line-ending period differently.
-- See http://code.google.com/p/pandoc/issues/detail?id=148.
--- | Returns the first sentence in a list of inlines, and the rest.
-breakSentence :: [Inline] -> ([Inline], [Inline])
-breakSentence [] = ([],[])
-breakSentence xs =
- let isSentenceEndInline (Str ys@(_:_)) | last ys == '.' = True
- isSentenceEndInline (Str ys@(_:_)) | last ys == '?' = True
- isSentenceEndInline LineBreak = True
- isSentenceEndInline _ = False
- (as, bs) = break isSentenceEndInline xs
- in case bs of
- [] -> (as, [])
- [c] -> (as ++ [c], [])
- (c:Space:cs) -> (as ++ [c], cs)
- (c:SoftBreak:cs) -> (as ++ [c], cs)
- (Str ".":Str (')':ys):cs) -> (as ++ [Str ".", Str (')':ys)], cs)
- (x@(Str ('.':')':_)):cs) -> (as ++ [x], cs)
- (LineBreak:x@(Str ('.':_)):cs) -> (as ++[LineBreak], x:cs)
- (c:cs) -> (as ++ [c] ++ ds, es)
- where (ds, es) = breakSentence cs
-
--- | Split a list of inlines into sentences.
-splitSentences :: [Inline] -> [[Inline]]
-splitSentences xs =
- let (sent, rest) = breakSentence xs
- in if null rest then [sent] else sent : splitSentences rest
-
-- | Convert Pandoc block element to man.
blockToMan :: PandocMonad m
=> WriterOptions -- ^ Options
@@ -325,11 +300,11 @@ blockListToMan :: PandocMonad m
-> [Block] -- ^ List of block elements
-> StateT WriterState m Doc
blockListToMan opts blocks =
- mapM (blockToMan opts) blocks >>= (return . vcat)
+ vcat <$> mapM (blockToMan opts) blocks
-- | Convert list of Pandoc inline elements to man.
inlineListToMan :: PandocMonad m => WriterOptions -> [Inline] -> StateT WriterState m Doc
-inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat)
+inlineListToMan opts lst = hcat <$> mapM (inlineToMan opts) lst
-- | Convert Pandoc inline element to man.
inlineToMan :: PandocMonad m => WriterOptions -> Inline -> StateT WriterState m Doc
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
index 075858e5e..9a4acb59d 100644
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -38,7 +38,7 @@ module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where
import Prelude
import Control.Monad.Reader
import Control.Monad.State.Strict
-import Data.Char (chr, isPunctuation, isSpace, ord, isAlphaNum)
+import Data.Char (isPunctuation, isSpace, isAlphaNum)
import Data.Default
import qualified Data.HashMap.Strict as H
import Data.List (find, group, intersperse, sortBy, stripPrefix, transpose)
@@ -50,7 +50,7 @@ import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Vector as V
-import Data.Yaml (Value (Array, Bool, Number, Object, String))
+import Data.Aeson (Value (Array, Bool, Number, Object, String))
import Network.HTTP (urlEncode)
import Text.HTML.TagSoup (Tag (..), isTagText, parseTags)
import Text.Pandoc.Class (PandocMonad, report)
@@ -298,7 +298,8 @@ escapeString opts (c:cs) =
'\\':c:escapeString opts cs
'|' | isEnabled Ext_pipe_tables opts -> '\\':'|':escapeString opts cs
'^' | isEnabled Ext_superscript opts -> '\\':'^':escapeString opts cs
- '~' | isEnabled Ext_subscript opts -> '\\':'~':escapeString opts cs
+ '~' | isEnabled Ext_subscript opts ||
+ isEnabled Ext_strikeout opts -> '\\':'~':escapeString opts cs
'$' | isEnabled Ext_tex_math_dollars opts -> '\\':'$':escapeString opts cs
'\'' | isEnabled Ext_smart opts -> '\\':'\'':escapeString opts cs
'"' | isEnabled Ext_smart opts -> '\\':'"':escapeString opts cs
@@ -452,8 +453,14 @@ blockToMarkdown' opts (Plain inlines) = do
| otherwise -> contents
return $ contents' <> cr
-- title beginning with fig: indicates figure
-blockToMarkdown' opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) =
- blockToMarkdown opts (Para [Image attr alt (src,tit)])
+blockToMarkdown' opts (Para [Image attr alt (src,'f':'i':'g':':':tit)])
+ | isEnabled Ext_raw_html opts &&
+ not (isEnabled Ext_link_attributes opts) &&
+ attr /= nullAttr = -- use raw HTML
+ (text . T.unpack . T.strip) <$>
+ writeHtml5String opts{ writerTemplate = Nothing }
+ (Pandoc nullMeta [Para [Image attr alt (src,"fig:" ++ tit)]])
+ | otherwise = blockToMarkdown opts (Para [Image attr alt (src,tit)])
blockToMarkdown' opts (Para inlines) =
(<> blankline) `fmap` blockToMarkdown opts (Plain inlines)
blockToMarkdown' opts (LineBlock lns) =
@@ -619,7 +626,7 @@ blockToMarkdown' opts t@(Table caption aligns widths headers rows) = do
(all null headers) aligns' widths' headers rows
| isEnabled Ext_raw_html opts -> fmap (id,) $
(text . T.unpack) <$>
- (writeHtml5String def $ Pandoc nullMeta [t])
+ (writeHtml5String opts{ writerTemplate = Nothing } $ Pandoc nullMeta [t])
| hasSimpleCells &&
isEnabled Ext_pipe_tables opts -> do
rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers
@@ -976,6 +983,11 @@ isRight (Left _) = False
-- | Convert Pandoc inline element to markdown.
inlineToMarkdown :: PandocMonad m => WriterOptions -> Inline -> MD m Doc
+inlineToMarkdown opts (Span ("",["emoji"],kvs) [Str s]) = do
+ case lookup "data-emoji" kvs of
+ Just emojiname | isEnabled Ext_emoji opts ->
+ return $ ":" <> text emojiname <> ":"
+ _ -> inlineToMarkdown opts (Str s)
inlineToMarkdown opts (Span attrs ils) = do
plain <- asks envPlain
contents <- inlineListToMarkdown opts ils
@@ -1172,7 +1184,7 @@ inlineToMarkdown opts lnk@(Link attr txt (src, tit))
not (isEnabled Ext_link_attributes opts) &&
attr /= nullAttr = -- use raw HTML
(text . T.unpack . T.strip) <$>
- writeHtml5String def (Pandoc nullMeta [Plain [lnk]])
+ writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain [lnk]])
| otherwise = do
plain <- asks envPlain
linktext <- inlineListToMarkdown opts txt
@@ -1212,7 +1224,7 @@ inlineToMarkdown opts img@(Image attr alternate (source, tit))
not (isEnabled Ext_link_attributes opts) &&
attr /= nullAttr = -- use raw HTML
(text . T.unpack . T.strip) <$>
- writeHtml5String def (Pandoc nullMeta [Plain [img]])
+ writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain [img]])
| otherwise = do
plain <- asks envPlain
let txt = if null alternate || alternate == [Str source]
@@ -1237,33 +1249,6 @@ makeMathPlainer = walk go
go (Emph xs) = Span nullAttr xs
go x = x
-toSuperscript :: Char -> Maybe Char
-toSuperscript '1' = Just '\x00B9'
-toSuperscript '2' = Just '\x00B2'
-toSuperscript '3' = Just '\x00B3'
-toSuperscript '+' = Just '\x207A'
-toSuperscript '-' = Just '\x207B'
-toSuperscript '=' = Just '\x207C'
-toSuperscript '(' = Just '\x207D'
-toSuperscript ')' = Just '\x207E'
-toSuperscript c
- | c >= '0' && c <= '9' =
- Just $ chr (0x2070 + (ord c - 48))
- | isSpace c = Just c
- | otherwise = Nothing
-
-toSubscript :: Char -> Maybe Char
-toSubscript '+' = Just '\x208A'
-toSubscript '-' = Just '\x208B'
-toSubscript '=' = Just '\x208C'
-toSubscript '(' = Just '\x208D'
-toSubscript ')' = Just '\x208E'
-toSubscript c
- | c >= '0' && c <= '9' =
- Just $ chr (0x2080 + (ord c - 48))
- | isSpace c = Just c
- | otherwise = Nothing
-
lineBreakToSpace :: Inline -> Inline
lineBreakToSpace LineBreak = Space
lineBreakToSpace SoftBreak = Space
diff --git a/src/Text/Pandoc/Writers/Math.hs b/src/Text/Pandoc/Writers/Math.hs
index 99d17d594..61decf2df 100644
--- a/src/Text/Pandoc/Writers/Math.hs
+++ b/src/Text/Pandoc/Writers/Math.hs
@@ -55,4 +55,4 @@ defaultMathJaxURL :: String
defaultMathJaxURL = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/"
defaultKaTeXURL :: String
-defaultKaTeXURL = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.8.3/"
+defaultKaTeXURL = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/"
diff --git a/src/Text/Pandoc/Writers/MediaWiki.hs b/src/Text/Pandoc/Writers/MediaWiki.hs
index df50028a0..666853a3c 100644
--- a/src/Text/Pandoc/Writers/MediaWiki.hs
+++ b/src/Text/Pandoc/Writers/MediaWiki.hs
@@ -313,6 +313,7 @@ tableCellToMediaWiki headless rownum (alignment, width, bs) = do
let sep = case bs of
[Plain _] -> " "
[Para _] -> " "
+ [] -> ""
_ -> "\n"
return $ marker ++ attr ++ sep ++ trimr contents
diff --git a/src/Text/Pandoc/Writers/Ms.hs b/src/Text/Pandoc/Writers/Ms.hs
index 16a66c85b..9a35a9693 100644
--- a/src/Text/Pandoc/Writers/Ms.hs
+++ b/src/Text/Pandoc/Writers/Ms.hs
@@ -127,7 +127,8 @@ pandocToMs opts (Pandoc meta blocks) = do
$ defField "title-meta" titleMeta
$ defField "author-meta" (intercalate "; " authorsMeta)
$ defField "highlighting-macros" highlightingMacros metadata
- case writerTemplate opts of
+ (if writerPreferAscii opts then groffEscape else id) <$>
+ case writerTemplate opts of
Nothing -> return main
Just tpl -> renderTemplate' tpl context
@@ -188,32 +189,6 @@ escapeCode = intercalate "\n" . map escapeLine . lines
-- line. groff/troff treats the line-ending period differently.
-- See http://code.google.com/p/pandoc/issues/detail?id=148.
--- | Returns the first sentence in a list of inlines, and the rest.
-breakSentence :: [Inline] -> ([Inline], [Inline])
-breakSentence [] = ([],[])
-breakSentence xs =
- let isSentenceEndInline (Str ys@(_:_)) | last ys == '.' = True
- isSentenceEndInline (Str ys@(_:_)) | last ys == '?' = True
- isSentenceEndInline LineBreak = True
- isSentenceEndInline _ = False
- (as, bs) = break isSentenceEndInline xs
- in case bs of
- [] -> (as, [])
- [c] -> (as ++ [c], [])
- (c:Space:cs) -> (as ++ [c], cs)
- (c:SoftBreak:cs) -> (as ++ [c], cs)
- (Str ".":Str (')':ys):cs) -> (as ++ [Str ".", Str (')':ys)], cs)
- (x@(Str ('.':')':_)):cs) -> (as ++ [x], cs)
- (LineBreak:x@(Str ('.':_)):cs) -> (as ++[LineBreak], x:cs)
- (c:cs) -> (as ++ [c] ++ ds, es)
- where (ds, es) = breakSentence cs
-
--- | Split a list of inlines into sentences.
-splitSentences :: [Inline] -> [[Inline]]
-splitSentences xs =
- let (sent, rest) = breakSentence xs
- in if null rest then [sent] else sent : splitSentences rest
-
blockToMs :: PandocMonad m
=> WriterOptions -- ^ Options
-> Block -- ^ Block element
@@ -434,7 +409,7 @@ blockListToMs :: PandocMonad m
-> [Block] -- ^ List of block elements
-> MS m Doc
blockListToMs opts blocks =
- mapM (blockToMs opts) blocks >>= (return . vcat)
+ vcat <$> mapM (blockToMs opts) blocks
-- | Convert list of Pandoc inline elements to ms.
inlineListToMs :: PandocMonad m => WriterOptions -> [Inline] -> MS m Doc
diff --git a/src/Text/Pandoc/Writers/Muse.hs b/src/Text/Pandoc/Writers/Muse.hs
index 3681fcc0d..18aebc364 100644
--- a/src/Text/Pandoc/Writers/Muse.hs
+++ b/src/Text/Pandoc/Writers/Muse.hs
@@ -46,7 +46,7 @@ module Text.Pandoc.Writers.Muse (writeMuse) where
import Prelude
import Control.Monad.Reader
import Control.Monad.State.Strict
-import Data.Char (isSpace, isDigit, isAsciiUpper, isAsciiLower)
+import Data.Char (isSpace, isAlphaNum, isDigit, isAsciiUpper, isAsciiLower)
import Data.Default
import Data.Text (Text)
import Data.List (intersperse, transpose, isInfixOf)
@@ -70,20 +70,24 @@ data WriterEnv =
WriterEnv { envOptions :: WriterOptions
, envTopLevel :: Bool
, envInsideBlock :: Bool
- , envInlineStart :: Bool
+ , envInlineStart :: Bool -- ^ True if there is only whitespace since last newline
, envInsideLinkDescription :: Bool -- ^ Escape ] if True
- , envAfterSpace :: Bool
+ , envAfterSpace :: Bool -- ^ There is whitespace (not just newline) before
, envOneLine :: Bool -- ^ True if newlines are not allowed
+ , envInsideAsterisks :: Bool -- ^ True if outer element is emphasis with asterisks
+ , envNearAsterisks :: Bool -- ^ Rendering inline near asterisks
}
data WriterState =
WriterState { stNotes :: Notes
, stIds :: Set.Set String
+ , stUseTags :: Bool -- ^ Use tags for emphasis, for example because previous character is a letter
}
instance Default WriterState
where def = WriterState { stNotes = []
, stIds = Set.empty
+ , stUseTags = False
}
evalMuse :: PandocMonad m => Muse m a -> WriterEnv -> WriterState -> m a
@@ -103,6 +107,8 @@ writeMuse opts document =
, envInsideLinkDescription = False
, envAfterSpace = False
, envOneLine = False
+ , envInsideAsterisks = False
+ , envNearAsterisks = False
}
-- | Return Muse representation of document.
@@ -212,6 +218,7 @@ blockToMuse (BulletList items) = do
=> [Block]
-> Muse m Doc
bulletListItemToMuse item = do
+ modify $ \st -> st { stUseTags = False }
contents <- blockListToMuse item
return $ hang 2 "- " contents
blockToMuse (DefinitionList items) = do
@@ -223,16 +230,18 @@ blockToMuse (DefinitionList items) = do
=> ([Inline], [[Block]])
-> Muse m Doc
definitionListItemToMuse (label, defs) = do
+ modify $ \st -> st { stUseTags = False }
label' <- local (\env -> env { envOneLine = True, envAfterSpace = True }) $ inlineListToMuse' label
contents <- vcat <$> mapM descriptionToMuse defs
let ind = offset label'
- return $ hang ind label' contents
+ return $ hang ind (nowrap label') contents
descriptionToMuse :: PandocMonad m
=> [Block]
-> Muse m Doc
descriptionToMuse desc = hang 4 " :: " <$> blockListToMuse desc
blockToMuse (Header level (ident,_,_) inlines) = do
opts <- asks envOptions
+ topLevel <- asks envTopLevel
contents <- local (\env -> env { envOneLine = True }) $ inlineListToMuse' inlines
ids <- gets stIds
let autoId = uniqueIdent inlines ids
@@ -241,8 +250,8 @@ blockToMuse (Header level (ident,_,_) inlines) = do
let attr' = if null ident || (isEnabled Ext_auto_identifiers opts && ident == autoId)
then empty
else "#" <> text ident <> cr
- let header' = text $ replicate level '*'
- return $ blankline <> attr' $$ nowrap (header' <> space <> contents) <> blankline
+ let header' = if topLevel then (text $ replicate level '*') <> space else mempty
+ return $ blankline <> attr' $$ nowrap (header' <> contents) <> blankline
-- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors
blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline
blockToMuse (Table caption _ _ headers rows) = do
@@ -284,7 +293,11 @@ noteToMuse :: PandocMonad m
-> [Block]
-> Muse m Doc
noteToMuse num note =
- hang (length marker) (text marker) <$> blockListToMuse note
+ hang (length marker) (text marker) <$>
+ (local (\env -> env { envInsideBlock = True
+ , envInlineStart = True
+ , envAfterSpace = True
+ }) $ blockListToMuse note)
where
marker = "[" ++ show num ++ "] "
@@ -295,6 +308,12 @@ escapeString s =
substitute "</verbatim>" "<</verbatim><verbatim>/verbatim>" s ++
"</verbatim>"
+-- | Replace newlines with spaces
+replaceNewlines :: String -> String
+replaceNewlines ('\n':xs) = ' ':replaceNewlines xs
+replaceNewlines (x:xs) = x:replaceNewlines xs
+replaceNewlines [] = []
+
startsWithMarker :: (Char -> Bool) -> String -> Bool
startsWithMarker f (' ':xs) = startsWithMarker f xs
startsWithMarker f (x:xs) =
@@ -321,16 +340,28 @@ containsFootnotes = p
s (_:xs) = p xs
s [] = False
-conditionalEscapeString :: Bool -> String -> String
-conditionalEscapeString isInsideLinkDescription s =
- if any (`elem` ("#*<=|" :: String)) s ||
- "::" `isInfixOf` s ||
- "~~" `isInfixOf` s ||
- "[[" `isInfixOf` s ||
- ("]" `isInfixOf` s && isInsideLinkDescription) ||
- containsFootnotes s
- then escapeString s
- else s
+-- | Return True if string should be escaped with <verbatim> tags
+shouldEscapeString :: PandocMonad m
+ => String
+ -> Muse m Bool
+shouldEscapeString s = do
+ insideLink <- asks envInsideLinkDescription
+ return $ null s ||
+ any (`elem` ("#*<=|" :: String)) s ||
+ "::" `isInfixOf` s ||
+ "~~" `isInfixOf` s ||
+ "[[" `isInfixOf` s ||
+ ("]" `isInfixOf` s && insideLink) ||
+ containsFootnotes s
+
+conditionalEscapeString :: PandocMonad m
+ => String
+ -> Muse m String
+conditionalEscapeString s = do
+ shouldEscape <- shouldEscapeString s
+ return $ if shouldEscape
+ then escapeString s
+ else s
-- Expand Math and Cite before normalizing inline list
preprocessInlineList :: PandocMonad m
@@ -389,6 +420,19 @@ fixNotes (Space : n@Note{} : rest) = Str " " : n : fixNotes rest
fixNotes (SoftBreak : n@Note{} : rest) = Str " " : n : fixNotes rest
fixNotes (x:xs) = x : fixNotes xs
+startsWithSpace :: [Inline] -> Bool
+startsWithSpace (Space:_) = True
+startsWithSpace (SoftBreak:_) = True
+startsWithSpace (Str s:_) = stringStartsWithSpace s
+startsWithSpace _ = False
+
+endsWithSpace :: [Inline] -> Bool
+endsWithSpace [Space] = True
+endsWithSpace [SoftBreak] = True
+endsWithSpace [Str s] = stringStartsWithSpace $ reverse s
+endsWithSpace (_:xs) = endsWithSpace xs
+endsWithSpace [] = False
+
urlEscapeBrackets :: String -> String
urlEscapeBrackets (']':xs) = '%':'5':'D':urlEscapeBrackets xs
urlEscapeBrackets (x:xs) = x:urlEscapeBrackets xs
@@ -397,22 +441,33 @@ urlEscapeBrackets [] = []
isHorizontalRule :: String -> Bool
isHorizontalRule s = length s >= 4 && all (== '-') s
-startsWithSpace :: String -> Bool
-startsWithSpace (x:_) = isSpace x
-startsWithSpace [] = False
+stringStartsWithSpace :: String -> Bool
+stringStartsWithSpace (x:_) = isSpace x
+stringStartsWithSpace "" = False
fixOrEscape :: Bool -> Inline -> Bool
fixOrEscape sp (Str "-") = sp
-fixOrEscape sp (Str ";") = not sp
-fixOrEscape _ (Str ">") = True
+fixOrEscape sp (Str s@('-':x:_)) = (sp && isSpace x) || isHorizontalRule s
+fixOrEscape sp (Str (";")) = not sp
+fixOrEscape sp (Str (';':x:_)) = not sp && isSpace x
+fixOrEscape _ (Str (">")) = True
+fixOrEscape _ (Str ('>':x:_)) = isSpace x
fixOrEscape sp (Str s) = (sp && (startsWithMarker isDigit s ||
startsWithMarker isAsciiLower s ||
startsWithMarker isAsciiUpper s))
- || isHorizontalRule s || startsWithSpace s
+ || stringStartsWithSpace s
fixOrEscape _ Space = True
fixOrEscape _ SoftBreak = True
fixOrEscape _ _ = False
+inlineListStartsWithAlnum :: PandocMonad m
+ => [Inline]
+ -> Muse m Bool
+inlineListStartsWithAlnum (Str s:_) = do
+ esc <- shouldEscapeString s
+ return $ esc || isAlphaNum (head s)
+inlineListStartsWithAlnum _ = return False
+
-- | Convert list of Pandoc inline elements to Muse
renderInlineList :: PandocMonad m
=> [Inline]
@@ -424,86 +479,159 @@ renderInlineList (x:xs) = do
start <- asks envInlineStart
afterSpace <- asks envAfterSpace
topLevel <- asks envTopLevel
- r <- inlineToMuse x
+ insideAsterisks <- asks envInsideAsterisks
+ nearAsterisks <- asks envNearAsterisks
+ useTags <- gets stUseTags
+ alnumNext <- inlineListStartsWithAlnum xs
+ let newUseTags = useTags || alnumNext
+ modify $ \st -> st { stUseTags = newUseTags }
+
+ r <- local (\env -> env { envInlineStart = False
+ , envInsideAsterisks = False
+ , envNearAsterisks = nearAsterisks || (null xs && insideAsterisks)
+ }) $ inlineToMuse x
opts <- asks envOptions
let isNewline = (x == SoftBreak && writerWrapText opts == WrapPreserve) || x == LineBreak
lst' <- local (\env -> env { envInlineStart = isNewline
, envAfterSpace = x == Space || (not topLevel && isNewline)
+ , envNearAsterisks = False
}) $ renderInlineList xs
if start && fixOrEscape afterSpace x
then pure (text "<verbatim></verbatim>" <> r <> lst')
else pure (r <> lst')
-- | Normalize and convert list of Pandoc inline elements to Muse.
-inlineListToMuse'' :: PandocMonad m
- => Bool
- -> [Inline]
- -> Muse m Doc
-inlineListToMuse'' start lst = do
- lst' <- (normalizeInlineList . fixNotes) <$> preprocessInlineList (map (removeKeyValues . replaceSmallCaps) lst)
- topLevel <- asks envTopLevel
- afterSpace <- asks envAfterSpace
- local (\env -> env { envInlineStart = start
- , envAfterSpace = afterSpace || (start && not topLevel)
- }) $ renderInlineList lst'
+inlineListToMuse :: PandocMonad m
+ => [Inline]
+ -> Muse m Doc
+inlineListToMuse lst = do
+ lst' <- normalizeInlineList . fixNotes <$> preprocessInlineList (map (removeKeyValues . replaceSmallCaps) lst)
+ insideAsterisks <- asks envInsideAsterisks
+ modify $ \st -> st { stUseTags = False } -- Previous character is likely a '>' or some other markup
+ local (\env -> env { envNearAsterisks = insideAsterisks }) $ renderInlineList lst'
inlineListToMuse' :: PandocMonad m => [Inline] -> Muse m Doc
-inlineListToMuse' = inlineListToMuse'' True
-
-inlineListToMuse :: PandocMonad m => [Inline] -> Muse m Doc
-inlineListToMuse = inlineListToMuse'' False
+inlineListToMuse' lst = do
+ topLevel <- asks envTopLevel
+ afterSpace <- asks envAfterSpace
+ local (\env -> env { envInlineStart = True
+ , envAfterSpace = afterSpace || not topLevel
+ }) $ inlineListToMuse lst
-- | Convert Pandoc inline element to Muse.
inlineToMuse :: PandocMonad m
=> Inline
-> Muse m Doc
inlineToMuse (Str str) = do
- insideLink <- asks envInsideLinkDescription
- return $ text $ conditionalEscapeString insideLink str
+ escapedStr <- conditionalEscapeString $ replaceNewlines str
+ let useTags = isAlphaNum $ last escapedStr -- escapedStr is never empty because empty strings are escaped
+ modify $ \st -> st { stUseTags = useTags }
+ return $ text escapedStr
+inlineToMuse (Emph [Strong lst]) = do
+ useTags <- gets stUseTags
+ let lst' = normalizeInlineList lst
+ if useTags
+ then do contents <- local (\env -> env { envInsideAsterisks = True }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = False }
+ return $ "<em>**" <> contents <> "**</em>"
+ else if null lst' || startsWithSpace lst' || endsWithSpace lst'
+ then do
+ contents <- local (\env -> env { envInsideAsterisks = False }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = True }
+ return $ "*<strong>" <> contents <> "</strong>*"
+ else do
+ contents <- local (\env -> env { envInsideAsterisks = True }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = True }
+ return $ "***" <> contents <> "***"
inlineToMuse (Emph lst) = do
- contents <- inlineListToMuse lst
- return $ "<em>" <> contents <> "</em>"
+ useTags <- gets stUseTags
+ let lst' = normalizeInlineList lst
+ if useTags || null lst' || startsWithSpace lst' || endsWithSpace lst'
+ then do contents <- inlineListToMuse lst'
+ return $ "<em>" <> contents <> "</em>"
+ else do contents <- local (\env -> env { envInsideAsterisks = True }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = True }
+ return $ "*" <> contents <> "*"
+inlineToMuse (Strong [Emph lst]) = do
+ useTags <- gets stUseTags
+ let lst' = normalizeInlineList lst
+ if useTags
+ then do contents <- local (\env -> env { envInsideAsterisks = True }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = False }
+ return $ "<strong>*" <> contents <> "*</strong>"
+ else if null lst' || startsWithSpace lst' || endsWithSpace lst'
+ then do
+ contents <- local (\env -> env { envInsideAsterisks = False }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = True }
+ return $ "**<em>" <> contents <> "</em>**"
+ else do
+ contents <- local (\env -> env { envInsideAsterisks = True }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = True }
+ return $ "***" <> contents <> "***"
inlineToMuse (Strong lst) = do
- contents <- inlineListToMuse lst
- return $ "<strong>" <> contents <> "</strong>"
+ useTags <- gets stUseTags
+ let lst' = normalizeInlineList lst
+ if useTags || null lst' || startsWithSpace lst' || endsWithSpace lst'
+ then do contents <- inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = False }
+ return $ "<strong>" <> contents <> "</strong>"
+ else do contents <- local (\env -> env { envInsideAsterisks = True }) $ inlineListToMuse lst'
+ modify $ \st -> st { stUseTags = True }
+ return $ "**" <> contents <> "**"
inlineToMuse (Strikeout lst) = do
contents <- inlineListToMuse lst
+ modify $ \st -> st { stUseTags = False }
return $ "<del>" <> contents <> "</del>"
inlineToMuse (Superscript lst) = do
contents <- inlineListToMuse lst
+ modify $ \st -> st { stUseTags = False }
return $ "<sup>" <> contents <> "</sup>"
inlineToMuse (Subscript lst) = do
contents <- inlineListToMuse lst
+ modify $ \st -> st { stUseTags = False }
return $ "<sub>" <> contents <> "</sub>"
inlineToMuse SmallCaps {} =
fail "SmallCaps should be expanded before normalization"
inlineToMuse (Quoted SingleQuote lst) = do
contents <- inlineListToMuse lst
+ modify $ \st -> st { stUseTags = False }
return $ "‘" <> contents <> "’"
inlineToMuse (Quoted DoubleQuote lst) = do
contents <- inlineListToMuse lst
+ modify $ \st -> st { stUseTags = False }
return $ "“" <> contents <> "”"
inlineToMuse Cite {} =
fail "Citations should be expanded before normalization"
-inlineToMuse (Code _ str) = return $
- "<code>" <> text (substitute "</code>" "<</code><code>/code>" str) <> "</code>"
+inlineToMuse (Code _ str) = do
+ useTags <- gets stUseTags
+ modify $ \st -> st { stUseTags = False }
+ return $ if useTags || null str || '=' `elem` str || isSpace (head str) || isSpace (last str)
+ then "<code>" <> text (substitute "</code>" "<</code><code>/code>" str) <> "</code>"
+ else "=" <> text str <> "="
inlineToMuse Math{} =
fail "Math should be expanded before normalization"
-inlineToMuse (RawInline (Format f) str) =
+inlineToMuse (RawInline (Format f) str) = do
+ modify $ \st -> st { stUseTags = False }
return $ "<literal style=\"" <> text f <> "\">" <> text str <> "</literal>"
inlineToMuse LineBreak = do
oneline <- asks envOneLine
+ modify $ \st -> st { stUseTags = False }
return $ if oneline then "<br>" else "<br>" <> cr
-inlineToMuse Space = return space
+inlineToMuse Space = do
+ modify $ \st -> st { stUseTags = False }
+ return space
inlineToMuse SoftBreak = do
oneline <- asks envOneLine
wrapText <- asks $ writerWrapText . envOptions
+ modify $ \st -> st { stUseTags = False }
return $ if not oneline && wrapText == WrapPreserve then cr else space
inlineToMuse (Link _ txt (src, _)) =
case txt of
- [Str x] | escapeURI x == src ->
+ [Str x] | escapeURI x == src -> do
+ modify $ \st -> st { stUseTags = False }
return $ "[[" <> text (escapeLink x) <> "]]"
_ -> do contents <- local (\env -> env { envInsideLinkDescription = True }) $ inlineListToMuse txt
+ modify $ \st -> st { stUseTags = False }
return $ "[[" <> text (escapeLink src) <> "][" <> contents <> "]]"
where escapeLink lnk = if isImageUrl lnk then "URL:" ++ urlEscapeBrackets lnk else urlEscapeBrackets lnk
-- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el
@@ -514,11 +642,12 @@ inlineToMuse (Image attr alt (source,'f':'i':'g':':':title)) =
inlineToMuse (Image attr@(_, classes, _) inlines (source, title)) = do
opts <- asks envOptions
alt <- local (\env -> env { envInsideLinkDescription = True }) $ inlineListToMuse inlines
- let title' = if null title
- then if null inlines
- then ""
- else "[" <> alt <> "]"
- else "[" <> text (conditionalEscapeString True title) <> "]"
+ title' <- if null title
+ then if null inlines
+ then return ""
+ else return $ "[" <> alt <> "]"
+ else do s <- local (\env -> env { envInsideLinkDescription = True }) $ conditionalEscapeString title
+ return $ "[" <> text s <> "]"
let width = case dimension Width attr of
Just (Percent x) | isEnabled Ext_amuse opts -> " " ++ show (round x :: Integer)
_ -> ""
@@ -528,11 +657,14 @@ inlineToMuse (Image attr@(_, classes, _) inlines (source, title)) = do
let rightalign = if "align-right" `elem` classes
then " r"
else ""
+ modify $ \st -> st { stUseTags = False }
return $ "[[" <> text (urlEscapeBrackets source ++ width ++ leftalign ++ rightalign) <> "]" <> title' <> "]"
inlineToMuse (Note contents) = do
-- add to notes in state
notes <- gets stNotes
- modify $ \st -> st { stNotes = contents:notes }
+ modify $ \st -> st { stNotes = contents:notes
+ , stUseTags = False
+ }
let ref = show $ length notes + 1
return $ "[" <> text ref <> "]"
inlineToMuse (Span (anchor,names,_) inlines) = do
@@ -540,6 +672,7 @@ inlineToMuse (Span (anchor,names,_) inlines) = do
let anchorDoc = if null anchor
then mempty
else text ('#':anchor) <> space
+ modify $ \st -> st { stUseTags = False }
return $ anchorDoc <> (if null inlines && not (null anchor)
then mempty
else (if null names
diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs
index 7aecb3da5..1c9481630 100644
--- a/src/Text/Pandoc/Writers/ODT.hs
+++ b/src/Text/Pandoc/Writers/ODT.hs
@@ -189,8 +189,8 @@ transformPicMath opts (Image attr@(id', cls, _) lab (src,t)) = catchError
let dims =
case (getDim Width, getDim Height) of
(Just w, Just h) -> [("width", show w), ("height", show h)]
- (Just w@(Percent p), Nothing) -> [("width", show w), ("height", show (p / ratio) ++ "%")]
- (Nothing, Just h@(Percent p)) -> [("width", show (p * ratio) ++ "%"), ("height", show h)]
+ (Just w@(Percent _), Nothing) -> [("rel-width", show w),("rel-height", "scale"),("width", show ptX ++ "pt"),("height", show ptY ++ "pt")]
+ (Nothing, Just h@(Percent _)) -> [("rel-width", "scale"),("rel-height", show h),("width", show ptX ++ "pt"),("height", show ptY ++ "pt")]
(Just w@(Inch i), Nothing) -> [("width", show w), ("height", show (i / ratio) ++ "in")]
(Nothing, Just h@(Inch i)) -> [("width", show (i * ratio) ++ "in"), ("height", show h)]
_ -> [("width", show ptX ++ "pt"), ("height", show ptY ++ "pt")]
diff --git a/src/Text/Pandoc/Writers/OPML.hs b/src/Text/Pandoc/Writers/OPML.hs
index 6c48046a2..716c5cbad 100644
--- a/src/Text/Pandoc/Writers/OPML.hs
+++ b/src/Text/Pandoc/Writers/OPML.hs
@@ -62,7 +62,8 @@ writeOPML opts (Pandoc meta blocks) = do
meta'
main <- (render colwidth . vcat) <$> mapM (elementToOPML opts) elements
let context = defField "body" main metadata
- case writerTemplate opts of
+ (if writerPreferAscii opts then toEntities else id) <$>
+ case writerTemplate opts of
Nothing -> return main
Just tpl -> renderTemplate' tpl context
diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs
index 514327e9a..d9f0a8e44 100644
--- a/src/Text/Pandoc/Writers/OpenDocument.hs
+++ b/src/Text/Pandoc/Writers/OpenDocument.hs
@@ -39,17 +39,20 @@ import Control.Monad.State.Strict hiding (when)
import Data.Char (chr)
import Data.List (sortBy)
import qualified Data.Map as Map
+import Data.Maybe (fromMaybe)
import Data.Ord (comparing)
import qualified Data.Set as Set
import Data.Text (Text)
import Text.Pandoc.BCP47 (Lang (..), parseBCP47)
-import Text.Pandoc.Class (PandocMonad, report)
+import Text.Pandoc.Class (PandocMonad, report, translateTerm,
+ setTranslations, toLang)
import Text.Pandoc.Definition
import Text.Pandoc.Logging
import Text.Pandoc.Options
import Text.Pandoc.Pretty
import Text.Pandoc.Shared (linesToPara)
import Text.Pandoc.Templates (renderTemplate')
+import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))
import Text.Pandoc.Writers.Math
import Text.Pandoc.Writers.Shared
import Text.Pandoc.XML
@@ -67,32 +70,36 @@ plainToPara x = x
type OD m = StateT WriterState m
data WriterState =
- WriterState { stNotes :: [Doc]
- , stTableStyles :: [Doc]
- , stParaStyles :: [Doc]
- , stListStyles :: [(Int, [Doc])]
- , stTextStyles :: Map.Map (Set.Set TextStyle) (String, Doc)
- , stTextStyleAttr :: Set.Set TextStyle
- , stIndentPara :: Int
- , stInDefinition :: Bool
- , stTight :: Bool
- , stFirstPara :: Bool
- , stImageId :: Int
+ WriterState { stNotes :: [Doc]
+ , stTableStyles :: [Doc]
+ , stParaStyles :: [Doc]
+ , stListStyles :: [(Int, [Doc])]
+ , stTextStyles :: Map.Map (Set.Set TextStyle) (String, Doc)
+ , stTextStyleAttr :: Set.Set TextStyle
+ , stIndentPara :: Int
+ , stInDefinition :: Bool
+ , stTight :: Bool
+ , stFirstPara :: Bool
+ , stImageId :: Int
+ , stTableCaptionId :: Int
+ , stImageCaptionId :: Int
}
defaultWriterState :: WriterState
defaultWriterState =
- WriterState { stNotes = []
- , stTableStyles = []
- , stParaStyles = []
- , stListStyles = []
- , stTextStyles = Map.empty
- , stTextStyleAttr = Set.empty
- , stIndentPara = 0
- , stInDefinition = False
- , stTight = False
- , stFirstPara = False
- , stImageId = 1
+ WriterState { stNotes = []
+ , stTableStyles = []
+ , stParaStyles = []
+ , stListStyles = []
+ , stTextStyles = Map.empty
+ , stTextStyleAttr = Set.empty
+ , stIndentPara = 0
+ , stInDefinition = False
+ , stTight = False
+ , stFirstPara = False
+ , stImageId = 1
+ , stTableCaptionId = 1
+ , stImageCaptionId = 1
}
when :: Bool -> Doc -> Doc
@@ -193,10 +200,15 @@ formulaStyle mt = inTags False "style:style"
,("style:horizontal-rel", "paragraph-content")
,("style:wrap", "none")]
-inHeaderTags :: PandocMonad m => Int -> Doc -> OD m Doc
-inHeaderTags i d =
+inHeaderTags :: PandocMonad m => Int -> String -> Doc -> OD m Doc
+inHeaderTags i ident d =
return $ inTags False "text:h" [ ("text:style-name", "Heading_20_" ++ show i)
- , ("text:outline-level", show i)] d
+ , ("text:outline-level", show i)]
+ $ if null ident
+ then d
+ else selfClosingTag "text:bookmark-start" [ ("text:name", ident) ]
+ <> d <>
+ selfClosingTag "text:bookmark-end" [ ("text:name", ident) ]
inQuotes :: QuoteType -> Doc -> Doc
inQuotes SingleQuote s = char '\8216' <> s <> char '\8217'
@@ -218,6 +230,11 @@ handleSpaces s
-- | Convert Pandoc document to string in OpenDocument format.
writeOpenDocument :: PandocMonad m => WriterOptions -> Pandoc -> m Text
writeOpenDocument opts (Pandoc meta blocks) = do
+ let defLang = Lang "en" "US" "" []
+ lang <- case lookupMetaString "lang" meta of
+ "" -> pure defLang
+ s -> fromMaybe defLang <$> toLang (Just s)
+ setTranslations lang
let colwidth = if writerWrapText opts == WrapAuto
then Just $ writerColumns opts
else Nothing
@@ -349,8 +366,9 @@ blockToOpenDocument o bs
| LineBlock b <- bs = blockToOpenDocument o $ linesToPara b
| Div attr xs <- bs = withLangFromAttr attr
(blocksToOpenDocument o xs)
- | Header i _ b <- bs = setFirstPara >>
- (inHeaderTags i =<< inlinesToOpenDocument o b)
+ | Header i (ident,_,_) b
+ <- bs = setFirstPara >> (inHeaderTags i ident
+ =<< inlinesToOpenDocument o b)
| BlockQuote b <- bs = setFirstPara >> mkBlockQuote b
| DefinitionList b <- bs = setFirstPara >> defList b
| BulletList b <- bs = setFirstPara >> bulletListToOpenDocument o b
@@ -394,11 +412,11 @@ blockToOpenDocument o bs
mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles
captionDoc <- if null c
then return empty
- else withParagraphStyle o "Table" [Para c]
+ else inlinesToOpenDocument o c >>= numberedTableCaption
th <- if all null h
then return empty
- else colHeadsToOpenDocument o name (map fst paraHStyles) h
- tr <- mapM (tableRowToOpenDocument o name (map fst paraStyles)) r
+ else colHeadsToOpenDocument o (map fst paraHStyles) h
+ tr <- mapM (tableRowToOpenDocument o (map fst paraStyles)) r
return $ inTags True "table:table" [ ("table:name" , name)
, ("table:style-name", name)
] (vcat columns $$ th $$ vcat tr) $$ captionDoc
@@ -406,28 +424,54 @@ blockToOpenDocument o bs
withParagraphStyle o "Figure" [Para [Image attr caption (source,title)]]
| otherwise = do
imageDoc <- withParagraphStyle o "FigureWithCaption" [Para [Image attr caption (source,title)]]
- captionDoc <- withParagraphStyle o "FigureCaption" [Para caption]
+ captionDoc <- inlinesToOpenDocument o caption >>= numberedFigureCaption
return $ imageDoc $$ captionDoc
+
+numberedTableCaption :: PandocMonad m => Doc -> OD m Doc
+numberedTableCaption caption = do
+ id' <- gets stTableCaptionId
+ modify (\st -> st{ stTableCaptionId = id' + 1 })
+ capterm <- translateTerm Term.Table
+ return $ numberedCaption "Table" capterm "Table" id' caption
+
+numberedFigureCaption :: PandocMonad m => Doc -> OD m Doc
+numberedFigureCaption caption = do
+ id' <- gets stImageCaptionId
+ modify (\st -> st{ stImageCaptionId = id' + 1 })
+ capterm <- translateTerm Term.Figure
+ return $ numberedCaption "FigureCaption" capterm "Illustration" id' caption
+
+numberedCaption :: String -> String -> String -> Int -> Doc -> Doc
+numberedCaption style term name num caption =
+ let t = text term
+ r = num - 1
+ s = inTags False "text:sequence" [ ("text:ref-name", "ref" ++ name ++ show r),
+ ("text:name", name),
+ ("text:formula", "ooow:" ++ name ++ "+1"),
+ ("style:num-format", "1") ] $ text $ show num
+ c = text ": "
+ in inParagraphTagsWithStyle style $ hcat [ t, text " ", s, c, caption ]
+
colHeadsToOpenDocument :: PandocMonad m
- => WriterOptions -> String -> [String] -> [[Block]]
+ => WriterOptions -> [String] -> [[Block]]
-> OD m Doc
-colHeadsToOpenDocument o tn ns hs =
+colHeadsToOpenDocument o ns hs =
inTagsIndented "table:table-header-rows" . inTagsIndented "table:table-row" . vcat <$>
- mapM (tableItemToOpenDocument o tn) (zip ns hs)
+ mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns hs)
tableRowToOpenDocument :: PandocMonad m
- => WriterOptions -> String -> [String] -> [[Block]]
+ => WriterOptions -> [String] -> [[Block]]
-> OD m Doc
-tableRowToOpenDocument o tn ns cs =
+tableRowToOpenDocument o ns cs =
inTagsIndented "table:table-row" . vcat <$>
- mapM (tableItemToOpenDocument o tn) (zip ns cs)
+ mapM (tableItemToOpenDocument o "TableRowCell") (zip ns cs)
tableItemToOpenDocument :: PandocMonad m
=> WriterOptions -> String -> (String,[Block])
-> OD m Doc
-tableItemToOpenDocument o tn (n,i) =
- let a = [ ("table:style-name" , tn ++ ".A1" )
+tableItemToOpenDocument o s (n,i) =
+ let a = [ ("table:style-name" , s )
, ("office:value-type", "string" )
]
in inTags True "table:table-cell" a <$>
@@ -500,7 +544,9 @@ inlineToOpenDocument o ils
modify (\st -> st{ stImageId = id' + 1 })
let getDims [] = []
getDims (("width", w) :xs) = ("svg:width", w) : getDims xs
+ getDims (("rel-width", w):xs) = ("style:rel-width", w) : getDims xs
getDims (("height", h):xs) = ("svg:height", h) : getDims xs
+ getDims (("rel-height", w):xs) = ("style:rel-height", w) : getDims xs
getDims (_:xs) = getDims xs
return $ inTags False "draw:frame"
(("draw:name", "img" ++ show id') : getDims kvs) $
@@ -555,10 +601,18 @@ orderedListLevelStyle (s,n, d) (l,ls) =
listLevelStyle :: Int -> Doc
listLevelStyle i =
- let indent = show (0.4 * fromIntegral (i - 1) :: Double) in
- selfClosingTag "style:list-level-properties"
- [ ("text:space-before" , indent ++ "in")
- , ("text:min-label-width", "0.4in")]
+ let indent = show (0.5 * fromIntegral i :: Double) in
+ inTags True "style:list-level-properties"
+ [ ("text:list-level-position-and-space-mode",
+ "label-alignment")
+ , ("fo:text-align", "right")
+ ] $
+ selfClosingTag "style:list-level-label-alignment"
+ [ ("text:label-followed-by", "listtab")
+ , ("text:list-tab-stop-position", indent ++ "in")
+ , ("fo:text-indent", "-0.1in")
+ , ("fo:margin-left", indent ++ "in")
+ ]
tableStyle :: Int -> [(Char,Double)] -> Doc
tableStyle num wcs =
@@ -576,13 +630,21 @@ tableStyle num wcs =
, ("style:family", "table-column" )] $
selfClosingTag "style:table-column-properties"
[("style:rel-column-width", printf "%d*" (floor $ w * 65535 :: Integer))]
- cellStyle = inTags True "style:style"
- [ ("style:name" , tableId ++ ".A1")
+ headerRowCellStyle = inTags True "style:style"
+ [ ("style:name" , "TableHeaderRowCell")
+ , ("style:family", "table-cell" )] $
+ selfClosingTag "style:table-cell-properties"
+ [ ("fo:border", "none")]
+ rowCellStyle = inTags True "style:style"
+ [ ("style:name" , "TableRowCell")
, ("style:family", "table-cell" )] $
selfClosingTag "style:table-cell-properties"
[ ("fo:border", "none")]
+ cellStyles = if num == 0
+ then headerRowCellStyle $$ rowCellStyle
+ else empty
columnStyles = map colStyle wcs
- in table $$ vcat columnStyles $$ cellStyle
+ in cellStyles $$ table $$ vcat columnStyles
paraStyle :: PandocMonad m => [(String,String)] -> OD m Int
paraStyle attrs = do
diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs
index a71775e13..12a54fd71 100644
--- a/src/Text/Pandoc/Writers/Org.hs
+++ b/src/Text/Pandoc/Writers/Org.hs
@@ -109,7 +109,7 @@ escapeString = escapeStringUsing $
, ('\x2013',"--")
, ('\x2019',"'")
, ('\x2026',"...")
- ] ++ backslashEscapes "^_"
+ ]
isRawFormat :: Format -> Bool
isRawFormat f =
@@ -266,7 +266,7 @@ orderedListItemToOrg marker items = do
contents <- blockListToOrg items
return $ hang (length marker + 1) (text marker <> space) (contents <> cr)
--- | Convert defintion list item (label, list of blocks) to Org.
+-- | Convert definition list item (label, list of blocks) to Org.
definitionListItemToOrg :: PandocMonad m
=> ([Inline], [[Block]]) -> Org m Doc
definitionListItemToOrg (label, defs) = do
diff --git a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
index e14476b16..c97d8d770 100644
--- a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
@@ -72,7 +72,7 @@ import Text.Pandoc.Logging
import Text.Pandoc.Walk
import Data.Time (UTCTime)
import qualified Text.Pandoc.Shared as Shared -- so we don't overlap "Element"
-import Text.Pandoc.Writers.Shared (metaValueToInlines)
+import Text.Pandoc.Writers.Shared (lookupMetaInlines)
import qualified Data.Map as M
import qualified Data.Set as S
import Data.Maybe (maybeToList, fromMaybe)
@@ -731,9 +731,9 @@ makeEndNotesSlideBlocks = do
anchorSet <- M.keysSet <$> gets stAnchorMap
if M.null noteIds
then return []
- else let title = case lookupMeta "notes-title" meta of
- Just val -> metaValueToInlines val
- Nothing -> [Str "Notes"]
+ else let title = case lookupMetaInlines "notes-title" meta of
+ [] -> [Str "Notes"]
+ ls -> ls
ident = Shared.uniqueIdent title anchorSet
hdr = Header slideLevel (ident, [], []) title
blks = concatMap (\(n, bs) -> makeNoteEntry n bs) $
@@ -744,13 +744,7 @@ getMetaSlide :: Pres (Maybe Slide)
getMetaSlide = do
meta <- asks envMetadata
title <- inlinesToParElems $ docTitle meta
- subtitle <- inlinesToParElems $
- case lookupMeta "subtitle" meta of
- Just (MetaString s) -> [Str s]
- Just (MetaInlines ils) -> ils
- Just (MetaBlocks [Plain ils]) -> ils
- Just (MetaBlocks [Para ils]) -> ils
- _ -> []
+ subtitle <- inlinesToParElems $ lookupMetaInlines "subtitle" meta
authors <- mapM inlinesToParElems $ docAuthors meta
date <- inlinesToParElems $ docDate meta
if null title && null subtitle && null authors && null date
@@ -785,9 +779,9 @@ makeTOCSlide blks = local (\env -> env{envCurSlideId = tocSlideId}) $ do
contents <- BulletList <$> mapM elementToListItem (Shared.hierarchicalize blks)
meta <- asks envMetadata
slideLevel <- asks envSlideLevel
- let tocTitle = case lookupMeta "toc-title" meta of
- Just val -> metaValueToInlines val
- Nothing -> [Str "Table of Contents"]
+ let tocTitle = case lookupMetaInlines "toc-title" meta of
+ [] -> [Str "Table of Contents"]
+ ls -> ls
hdr = Header slideLevel nullAttr tocTitle
blocksToSlide [hdr, contents]
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
index f82597c55..d64529c21 100644
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -35,7 +35,7 @@ module Text.Pandoc.Writers.RST ( writeRST, flatten ) where
import Prelude
import Control.Monad.State.Strict
import Data.Char (isSpace, toLower)
-import Data.List (isPrefixOf, stripPrefix)
+import Data.List (isPrefixOf, stripPrefix, transpose)
import Data.Maybe (fromMaybe)
import Data.Text (Text, stripEnd)
import qualified Text.Pandoc.Builder as B
@@ -82,14 +82,12 @@ pandocToRST (Pandoc meta blocks) = do
else Nothing
let render' :: Doc -> Text
render' = render colwidth
- let subtit = case lookupMeta "subtitle" meta of
- Just (MetaBlocks [Plain xs]) -> xs
- _ -> []
+ let subtit = lookupMetaInlines "subtitle" meta
title <- titleToRST (docTitle meta) subtit
metadata <- metaToJSON opts
(fmap render' . blockListToRST)
(fmap (stripEnd . render') . inlineListToRST)
- $ B.deleteMeta "title" $ B.deleteMeta "subtitle" meta
+ meta
body <- blockListToRST' True $ case writerTemplate opts of
Just _ -> normalizeHeadings 1 blocks
Nothing -> blocks
@@ -103,8 +101,9 @@ pandocToRST (Pandoc meta blocks) = do
let context = defField "body" main
$ defField "toc" (writerTableOfContents opts)
$ defField "toc-depth" (show $ writerTOCDepth opts)
+ $ defField "number-sections" (writerNumberSections opts)
$ defField "math" hasMath
- $ defField "title" (render Nothing title :: String)
+ $ defField "titleblock" (render Nothing title :: String)
$ defField "math" hasMath
$ defField "rawtex" rawTeX metadata
case writerTemplate opts of
@@ -209,11 +208,26 @@ blockToRST :: PandocMonad m
=> Block -- ^ Block element
-> RST m Doc
blockToRST Null = return empty
-blockToRST (Div attr bs) = do
+blockToRST (Div ("",["admonition-title"],[]) _) = return empty
+ -- this is generated by the rst reader and can safely be
+ -- omitted when we're generating rst
+blockToRST (Div (ident,classes,_kvs) bs) = do
contents <- blockListToRST bs
- let startTag = ".. raw:: html" $+$ nest 3 (tagWithAttrs "div" attr)
- let endTag = ".. raw:: html" $+$ nest 3 "</div>"
- return $ blankline <> startTag $+$ contents $+$ endTag $$ blankline
+ let admonitions = ["attention","caution","danger","error","hint",
+ "important","note","tip","warning","admonition"]
+ let admonition = case classes of
+ (cl:_)
+ | cl `elem` admonitions
+ -> ".. " <> text cl <> "::"
+ cls -> ".. container::" <> space <>
+ text (unwords (filter (/= "container") cls))
+ return $ blankline $$
+ admonition $$
+ (if null ident
+ then blankline
+ else " :name: " <> text ident $$ blankline) $$
+ nest 3 contents $$
+ blankline
blockToRST (Plain inlines) = inlineListToRST inlines
-- title beginning with fig: indicates that the image is a figure
blockToRST (Para [Image attr txt (src,'f':'i':'g':':':tit)]) = do
@@ -236,6 +250,7 @@ blockToRST (LineBlock lns) =
linesToLineBlock lns
blockToRST (RawBlock f@(Format f') str)
| f == "rst" = return $ text str
+ | f == "tex" = blockToRST (RawBlock (Format "latex") str)
| otherwise = return $ blankline <> ".. raw:: " <>
text (map toLower f') $+$
nest 3 (text str) $$ blankline
@@ -272,7 +287,8 @@ blockToRST (CodeBlock (_,classes,kvs) str) = do
then return $ prefixed "> " (text str) $$ blankline
else return $
(case [c | c <- classes,
- c `notElem` ["sourceCode","literate","numberLines"]] of
+ c `notElem` ["sourceCode","literate","numberLines",
+ "number-lines","example"]] of
[] -> "::"
(lang:_) -> (".. code:: " <> text lang) $$ numberlines)
$+$ nest 3 (text str) $$ blankline
@@ -288,9 +304,12 @@ blockToRST (Table caption aligns widths headers rows) = do
modify $ \st -> st{ stOptions = oldOpts }
return result
opts <- gets stOptions
- tbl <- gridTable opts blocksToDoc (all null headers)
- (map (const AlignDefault) aligns) widths
- headers rows
+ let isSimple = all (== 0) widths
+ tbl <- if isSimple
+ then simpleTable opts blocksToDoc headers rows
+ else gridTable opts blocksToDoc (all null headers)
+ (map (const AlignDefault) aligns) widths
+ headers rows
return $ if null caption
then tbl $$ blankline
else (".. table:: " <> caption') $$ blankline $$ nest 3 tbl $$
@@ -331,7 +350,7 @@ orderedListItemToRST marker items = do
let marker' = marker ++ " "
return $ hang (length marker') (text marker') $ contents <> cr
--- | Convert defintion list item (label, list of blocks) to RST.
+-- | Convert definition list item (label, list of blocks) to RST.
definitionListItemToRST :: PandocMonad m => ([Inline], [[Block]]) -> RST m Doc
definitionListItemToRST (label, defs) = do
label' <- inlineListToRST label
@@ -470,6 +489,8 @@ flatten outer
-- them and they will be readable and parsable
(Quoted _ _, _) -> keep f i
(_, Quoted _ _) -> keep f i
+ -- inlineToRST handles this case properly so it's safe to keep
+ (Link _ _ _, Image _ _ _) -> keep f i
-- parent inlines would prevent links from being correctly
-- parsed, in this case we prioritise the content over the
-- style
@@ -569,15 +590,18 @@ inlineToRST (Quoted DoubleQuote lst) = do
else return $ "“" <> contents <> "”"
inlineToRST (Cite _ lst) =
writeInlines lst
+inlineToRST (Code (_,["interpreted-text"],[("role",role)]) str) = do
+ return $ ":" <> text role <> ":`" <> text str <> "`"
inlineToRST (Code _ str) = do
opts <- gets stOptions
-- we trim the string because the delimiters must adjoin a
-- non-space character; see #3496
-- we use :literal: when the code contains backticks, since
-- :literal: allows backslash-escapes; see #3974
- return $ if '`' `elem` str
- then ":literal:`" <> text (escapeString opts (trim str)) <> "`"
- else "``" <> text (trim str) <> "``"
+ return $
+ if '`' `elem` str
+ then ":literal:`" <> text (escapeString opts (trim str)) <> "`"
+ else "``" <> text (trim str) <> "``"
inlineToRST (Str str) = do
opts <- gets stOptions
return $ text $
@@ -672,3 +696,30 @@ imageDimsToRST attr = do
Just dim -> cols dim
Nothing -> empty
return $ cr <> name $$ showDim Width $$ showDim Height
+
+simpleTable :: PandocMonad m
+ => WriterOptions
+ -> (WriterOptions -> [Block] -> m Doc)
+ -> [[Block]]
+ -> [[[Block]]]
+ -> m Doc
+simpleTable opts blocksToDoc headers rows = do
+ -- can't have empty cells in first column:
+ let fixEmpties (d:ds) = if isEmpty d
+ then text "\\ " : ds
+ else d : ds
+ fixEmpties [] = []
+ headerDocs <- if all null headers
+ then return []
+ else fixEmpties <$> mapM (blocksToDoc opts) headers
+ rowDocs <- mapM (fmap fixEmpties . mapM (blocksToDoc opts)) rows
+ let numChars [] = 0
+ numChars xs = maximum . map offset $ xs
+ let colWidths = map numChars $ transpose (headerDocs : rowDocs)
+ let toRow = hsep . zipWith lblock colWidths
+ let hline = hsep (map (\n -> text (replicate n '=')) colWidths)
+ let hdr = if all null headers
+ then mempty
+ else hline $$ toRow headerDocs
+ let bdy = vcat $ map toRow rowDocs
+ return $ hdr $$ hline $$ bdy $$ hline
diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs
index 3045c1c10..ed8dc9ae4 100644
--- a/src/Text/Pandoc/Writers/RTF.hs
+++ b/src/Text/Pandoc/Writers/RTF.hs
@@ -341,8 +341,10 @@ listItemToRTF :: PandocMonad m
listItemToRTF alignment indent marker [] = return $
rtfCompact (indent + listIncrement) (negate listIncrement) alignment
(marker ++ "\\tx" ++ show listIncrement ++ "\\tab ")
-listItemToRTF alignment indent marker list = do
- (first:rest) <- mapM (blockToRTF (indent + listIncrement) alignment) list
+listItemToRTF alignment indent marker (listFirst:listRest) = do
+ let f = blockToRTF (indent + listIncrement) alignment
+ first <- f listFirst
+ rest <- mapM f listRest
let listMarker = "\\fi" ++ show (negate listIncrement) ++ " " ++ marker ++
"\\tx" ++ show listIncrement ++ "\\tab"
let insertListMarker ('\\':'f':'i':'-':d:xs) | isDigit d =
diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs
index 2edce7deb..ed2c46d7b 100644
--- a/src/Text/Pandoc/Writers/Shared.hs
+++ b/src/Text/Pandoc/Writers/Shared.hs
@@ -38,17 +38,27 @@ module Text.Pandoc.Writers.Shared (
, resetField
, defField
, tagWithAttrs
+ , isDisplayMath
, fixDisplayMath
, unsmartify
+ , hasSimpleCells
, gridTable
- , metaValueToInlines
+ , lookupMetaBool
+ , lookupMetaBlocks
+ , lookupMetaInlines
+ , lookupMetaString
, stripLeadingTrailingSpace
+ , groffEscape
+ , toSubscript
+ , toSuperscript
)
where
import Prelude
import Control.Monad (zipWithM)
+import Data.Monoid (Any (..))
import Data.Aeson (FromJSON (..), Result (..), ToJSON (..), Value (Object),
encode, fromJSON)
+import Data.Char (chr, ord, isAscii, isSpace)
import qualified Data.HashMap.Strict as H
import Data.List (groupBy, intersperse, transpose)
import qualified Data.Map as M
@@ -59,9 +69,11 @@ import qualified Text.Pandoc.Builder as Builder
import Text.Pandoc.Definition
import Text.Pandoc.Options
import Text.Pandoc.Pretty
-import Text.Pandoc.Walk (query)
+import Text.Pandoc.Shared (stringify)
import Text.Pandoc.UTF8 (toStringLazy)
import Text.Pandoc.XML (escapeStringForXML)
+import Text.Pandoc.Walk (query)
+import Text.Printf (printf)
-- | Create JSON value for template from a 'Meta' and an association list
-- of variables, specified at the command line or in the writer.
@@ -187,8 +199,9 @@ tagWithAttrs tag (ident,classes,kvs) = hsep
] <> ">"
isDisplayMath :: Inline -> Bool
-isDisplayMath (Math DisplayMath _) = True
-isDisplayMath _ = False
+isDisplayMath (Math DisplayMath _) = True
+isDisplayMath (Span _ [Math DisplayMath _]) = True
+isDisplayMath _ = False
stripLeadingTrailingSpace :: [Inline] -> [Inline]
stripLeadingTrailingSpace = go . reverse . go . reverse
@@ -233,6 +246,21 @@ unsmartify opts ('\8216':xs) = '\'' : unsmartify opts xs
unsmartify opts (x:xs) = x : unsmartify opts xs
unsmartify _ [] = []
+-- | True if block is a table that can be represented with
+-- one line per row.
+hasSimpleCells :: Block -> Bool
+hasSimpleCells (Table _caption _aligns _widths headers rows) =
+ all isSimpleCell (concat (headers:rows))
+ where
+ isLineBreak LineBreak = Any True
+ isLineBreak _ = Any False
+ hasLineBreak = getAny . query isLineBreak
+ isSimpleCell [Plain ils] = not (hasLineBreak ils)
+ isSimpleCell [Para ils ] = not (hasLineBreak ils)
+ isSimpleCell [] = True
+ isSimpleCell _ = False
+hasSimpleCells _ = False
+
gridTable :: Monad m
=> WriterOptions
-> (WriterOptions -> [Block] -> m Doc)
@@ -332,9 +360,82 @@ gridTable opts blocksToDoc headless aligns widths headers rows = do
body $$
border '-' (repeat AlignDefault) widthsInChars
-metaValueToInlines :: MetaValue -> [Inline]
-metaValueToInlines (MetaString s) = [Str s]
-metaValueToInlines (MetaInlines ils) = ils
-metaValueToInlines (MetaBlocks bs) = query return bs
-metaValueToInlines (MetaBool b) = [Str $ show b]
-metaValueToInlines _ = []
+
+
+-- | Retrieve the metadata value for a given @key@
+-- and convert to Bool.
+lookupMetaBool :: String -> Meta -> Bool
+lookupMetaBool key meta =
+ case lookupMeta key meta of
+ Just (MetaBlocks _) -> True
+ Just (MetaInlines _) -> True
+ Just (MetaString (_:_)) -> True
+ Just (MetaBool True) -> True
+ _ -> False
+
+-- | Retrieve the metadata value for a given @key@
+-- and extract blocks.
+lookupMetaBlocks :: String -> Meta -> [Block]
+lookupMetaBlocks key meta =
+ case lookupMeta key meta of
+ Just (MetaBlocks bs) -> bs
+ Just (MetaInlines ils) -> [Plain ils]
+ Just (MetaString s) -> [Plain [Str s]]
+ _ -> []
+
+-- | Retrieve the metadata value for a given @key@
+-- and extract inlines.
+lookupMetaInlines :: String -> Meta -> [Inline]
+lookupMetaInlines key meta =
+ case lookupMeta key meta of
+ Just (MetaString s) -> [Str s]
+ Just (MetaInlines ils) -> ils
+ Just (MetaBlocks [Plain ils]) -> ils
+ Just (MetaBlocks [Para ils]) -> ils
+ _ -> []
+
+-- | Retrieve the metadata value for a given @key@
+-- and convert to String.
+lookupMetaString :: String -> Meta -> String
+lookupMetaString key meta =
+ case lookupMeta key meta of
+ Just (MetaString s) -> s
+ Just (MetaInlines ils) -> stringify ils
+ Just (MetaBlocks bs) -> stringify bs
+ Just (MetaBool b) -> show b
+ _ -> ""
+
+-- | Escape non-ASCII characters using groff \u[..] sequences.
+groffEscape :: T.Text -> T.Text
+groffEscape = T.concatMap toUchar
+ where toUchar c
+ | isAscii c = T.singleton c
+ | otherwise = T.pack $ printf "\\[u%04X]" (ord c)
+
+
+toSuperscript :: Char -> Maybe Char
+toSuperscript '1' = Just '\x00B9'
+toSuperscript '2' = Just '\x00B2'
+toSuperscript '3' = Just '\x00B3'
+toSuperscript '+' = Just '\x207A'
+toSuperscript '-' = Just '\x207B'
+toSuperscript '=' = Just '\x207C'
+toSuperscript '(' = Just '\x207D'
+toSuperscript ')' = Just '\x207E'
+toSuperscript c
+ | c >= '0' && c <= '9' =
+ Just $ chr (0x2070 + (ord c - 48))
+ | isSpace c = Just c
+ | otherwise = Nothing
+
+toSubscript :: Char -> Maybe Char
+toSubscript '+' = Just '\x208A'
+toSubscript '-' = Just '\x208B'
+toSubscript '=' = Just '\x208C'
+toSubscript '(' = Just '\x208D'
+toSubscript ')' = Just '\x208E'
+toSubscript c
+ | c >= '0' && c <= '9' =
+ Just $ chr (0x2080 + (ord c - 48))
+ | isSpace c = Just c
+ | otherwise = Nothing
diff --git a/src/Text/Pandoc/Writers/TEI.hs b/src/Text/Pandoc/Writers/TEI.hs
index e461f5715..9169c8515 100644
--- a/src/Text/Pandoc/Writers/TEI.hs
+++ b/src/Text/Pandoc/Writers/TEI.hs
@@ -35,7 +35,6 @@ import Prelude
import Data.Char (toLower)
import Data.List (isPrefixOf, stripPrefix)
import Data.Text (Text)
-import qualified Text.Pandoc.Builder as B
import Text.Pandoc.Class (PandocMonad, report)
import Text.Pandoc.Definition
import Text.Pandoc.Highlighting (languages, languagesByExtension)
@@ -48,16 +47,6 @@ import Text.Pandoc.Templates (renderTemplate')
import Text.Pandoc.Writers.Shared
import Text.Pandoc.XML
--- | Convert list of authors to a docbook <author> section
-authorToTEI :: PandocMonad m => WriterOptions -> [Inline] -> m B.Inlines
-authorToTEI opts name' = do
- name <- render Nothing <$> inlinesToTEI opts name'
- let colwidth = if writerWrapText opts == WrapAuto
- then Just $ writerColumns opts
- else Nothing
- return $ B.rawInline "tei" $ render colwidth $
- inTagsSimple "author" (text $ escapeStringForXML name)
-
-- | Convert Pandoc document to string in Docbook format.
writeTEI :: PandocMonad m => WriterOptions -> Pandoc -> m Text
writeTEI opts (Pandoc meta blocks) = do
@@ -72,13 +61,11 @@ writeTEI opts (Pandoc meta blocks) = do
TopLevelChapter -> 0
TopLevelSection -> 1
TopLevelDefault -> 1
- auths' <- mapM (authorToTEI opts) $ docAuthors meta
- let meta' = B.setMeta "author" auths' meta
metadata <- metaToJSON opts
(fmap (render' . vcat) .
mapM (elementToTEI opts startLvl) . hierarchicalize)
(fmap render' . inlinesToTEI opts)
- meta'
+ meta
main <- (render' . vcat) <$> mapM (elementToTEI opts startLvl) elements
let context = defField "body" main
$
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
index 305b41206..21d1f4eca 100644
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -56,8 +56,6 @@ import Text.Printf (printf)
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 :: Set.Set String -- header ids used already
, stOptions :: WriterOptions -- writer options
@@ -74,8 +72,7 @@ type TI m = StateT WriterState m
writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text
writeTexinfo options document =
evalStateT (pandocToTexinfo options $ wrapTop document)
- WriterState { stStrikeout = False, stSuperscript = False,
- stEscapeComma = False, stSubscript = False,
+ WriterState { stStrikeout = False, stEscapeComma = False,
stIdentifiers = Set.empty, stOptions = options}
-- | Add a "Top" node around the document, needed by Texinfo.
@@ -102,8 +99,6 @@ pandocToTexinfo options (Pandoc meta blocks) = do
let context = defField "body" body
$ defField "toc" (writerTableOfContents options)
$ defField "titlepage" titlePage
- $ defField "subscript" (stSubscript st)
- $ defField "superscript" (stSuperscript st)
$
defField "strikeout" (stStrikeout st) metadata
case writerTemplate options of
@@ -351,12 +346,9 @@ collectNodes :: Int -> [Block] -> [Block]
collectNodes _ [] = []
collectNodes level (x:xs) =
case x of
- (Header hl _ _) ->
- if hl < level
- then []
- else if hl == level
- then x : collectNodes level xs
- else collectNodes level xs
+ (Header hl _ _) | hl < level -> []
+ | hl == level -> x : collectNodes level xs
+ | otherwise -> collectNodes level xs
_ ->
collectNodes level xs
@@ -394,7 +386,7 @@ defListItemToTexinfo (term, defs) = do
inlineListToTexinfo :: PandocMonad m
=> [Inline] -- ^ Inlines to convert
-> TI m Doc
-inlineListToTexinfo lst = mapM inlineToTexinfo lst >>= return . hcat
+inlineListToTexinfo lst = hcat <$> mapM inlineToTexinfo lst
-- | Convert list of inline elements to Texinfo acceptable for a node name.
inlineListForNode :: PandocMonad m
@@ -416,10 +408,10 @@ inlineToTexinfo (Span _ lst) =
inlineListToTexinfo lst
inlineToTexinfo (Emph lst) =
- inlineListToTexinfo lst >>= return . inCmd "emph"
+ inCmd "emph" <$> inlineListToTexinfo lst
inlineToTexinfo (Strong lst) =
- inlineListToTexinfo lst >>= return . inCmd "strong"
+ inCmd "strong" <$> inlineListToTexinfo lst
inlineToTexinfo (Strikeout lst) = do
modify $ \st -> st{ stStrikeout = True }
@@ -427,17 +419,15 @@ inlineToTexinfo (Strikeout lst) = do
return $ text "@textstrikeout{" <> contents <> text "}"
inlineToTexinfo (Superscript lst) = do
- modify $ \st -> st{ stSuperscript = True }
contents <- inlineListToTexinfo lst
- return $ text "@textsuperscript{" <> contents <> char '}'
+ return $ text "@sup{" <> contents <> char '}'
inlineToTexinfo (Subscript lst) = do
- modify $ \st -> st{ stSubscript = True }
contents <- inlineListToTexinfo lst
- return $ text "@textsubscript{" <> contents <> char '}'
+ return $ text "@sub{" <> contents <> char '}'
inlineToTexinfo (SmallCaps lst) =
- inlineListToTexinfo lst >>= return . inCmd "sc"
+ inCmd "sc" <$> inlineListToTexinfo lst
inlineToTexinfo (Code _ str) =
return $ text $ "@code{" ++ stringToTexinfo str ++ "}"
diff --git a/src/Text/Pandoc/Writers/Textile.hs b/src/Text/Pandoc/Writers/Textile.hs
index 0ed79d2df..c7d96454a 100644
--- a/src/Text/Pandoc/Writers/Textile.hs
+++ b/src/Text/Pandoc/Writers/Textile.hs
@@ -73,7 +73,7 @@ pandocToTextile opts (Pandoc meta blocks) = do
(inlineListToTextile opts) meta
body <- blockListToTextile opts blocks
notes <- gets $ unlines . reverse . stNotes
- let main = pack $ body ++ if null notes then "" else ("\n\n" ++ notes)
+ let main = pack $ body ++ if null notes then "" else "\n\n" ++ notes
let context = defField "body" main metadata
case writerTemplate opts of
Nothing -> return main
@@ -154,7 +154,7 @@ blockToTextile _ HorizontalRule = return "<hr />\n"
blockToTextile opts (Header level (ident,classes,keyvals) inlines) = do
contents <- inlineListToTextile opts inlines
- let identAttr = if null ident then "" else ('#':ident)
+ let identAttr = if null ident then "" else '#':ident
let attribs = if null identAttr && null classes
then ""
else "(" ++ unwords classes ++ identAttr ++ ")"
@@ -382,13 +382,13 @@ blockListToTextile :: PandocMonad m
-> [Block] -- ^ List of block elements
-> TW m String
blockListToTextile opts blocks =
- mapM (blockToTextile opts) blocks >>= return . vcat
+ vcat <$> mapM (blockToTextile opts) blocks
-- | Convert list of Pandoc inline elements to Textile.
inlineListToTextile :: PandocMonad m
=> WriterOptions -> [Inline] -> TW m String
inlineListToTextile opts lst =
- mapM (inlineToTextile opts) lst >>= return . concat
+ concat <$> mapM (inlineToTextile opts) lst
-- | Convert Pandoc inline element to Textile.
inlineToTextile :: PandocMonad m => WriterOptions -> Inline -> TW m String
@@ -463,15 +463,15 @@ inlineToTextile _ SoftBreak = return " "
inlineToTextile _ Space = return " "
inlineToTextile opts (Link (_, cls, _) txt (src, _)) = do
- let classes = if null cls
- then ""
- else "(" ++ unwords cls ++ ")"
label <- case txt of
[Code _ s]
| s == src -> return "$"
[Str s]
| s == src -> return "$"
_ -> inlineListToTextile opts txt
+ let classes = if null cls || cls == ["uri"] && label == "$"
+ then ""
+ else "(" ++ unwords cls ++ ")"
return $ "\"" ++ classes ++ label ++ "\":" ++ src
inlineToTextile opts (Image attr@(_, cls, _) alt (source, tit)) = do
diff --git a/stack.lts10.yaml b/stack.lts10.yaml
new file mode 100644
index 000000000..76fc3b921
--- /dev/null
+++ b/stack.lts10.yaml
@@ -0,0 +1,31 @@
+flags:
+ pandoc:
+ trypandoc: false
+ embed_data_files: true
+ pandoc-citeproc:
+ bibutils: true
+ embed_data_files: true
+ unicode_collation: false
+ test_citeproc: false
+ debug: false
+packages:
+- '.'
+extra-deps:
+- pandoc-citeproc-0.14.4
+- skylighting-0.7.2
+- skylighting-core-0.7.2
+- ansi-terminal-0.8.0.2
+- tasty-1.0.1.1
+- test-framework-0.8.2.0
+- pandoc-types-1.17.5.1
+- cmark-gfm-0.1.3
+- texmath-0.11.1
+- haddock-library-1.6.0
+- HsYAML-0.1.1.1
+- text-1.2.3.0
+- hs-bibutils-6.6.0.0
+- hslua-1.0.1
+- hslua-module-text-0.2.0
+ghc-options:
+ "$locals": -fhide-source-paths -XNoImplicitPrelude
+resolver: lts-10.10
diff --git a/stack.lts11.yaml b/stack.lts11.yaml
new file mode 100644
index 000000000..afacb655f
--- /dev/null
+++ b/stack.lts11.yaml
@@ -0,0 +1,27 @@
+flags:
+ pandoc:
+ trypandoc: false
+ embed_data_files: true
+ pandoc-citeproc:
+ bibutils: true
+ embed_data_files: true
+ unicode_collation: false
+ test_citeproc: false
+ debug: false
+packages:
+- '.'
+extra-deps:
+- pandoc-citeproc-0.14.4
+- skylighting-0.7.2
+- skylighting-core-0.7.2
+- pandoc-types-1.17.5.1
+- texmath-0.11.1
+- haddock-library-1.6.0
+- HsYAML-0.1.1.1
+- hs-bibutils-6.6.0.0
+- yaml-0.9.0
+- hslua-1.0.1
+- hslua-module-text-0.2.0
+ghc-options:
+ "$locals": -fhide-source-paths -XNoImplicitPrelude
+resolver: lts-11.17
diff --git a/stack.lts9.yaml b/stack.lts9.yaml
index c4cc3caf7..b12cd57dc 100644
--- a/stack.lts9.yaml
+++ b/stack.lts9.yaml
@@ -2,7 +2,6 @@ flags:
pandoc:
trypandoc: false
embed_data_files: true
- network-uri: true
pandoc-citeproc:
bibutils: true
embed_data_files: true
@@ -12,20 +11,28 @@ flags:
packages:
- '.'
extra-deps:
-- hslua-0.9.5.1
-- hslua-module-text-0.1.2.1
-- skylighting-0.7.0.2
-- skylighting-core-0.7.0.2
+- pandoc-citeproc-0.14.4
+- hslua-1.0.1
+- hslua-module-text-0.2.0
- ansi-terminal-0.8.0.2
- cmark-gfm-0.1.3
- QuickCheck-2.11.3
- tasty-1.0.1.1
- tasty-quickcheck-0.9.1
- doctemplates-0.2.2.1
-- hs-bibutils-6.2.0.1
-- pandoc-citeproc-0.14.3.1
+- hs-bibutils-6.6.0.0
- tagsoup-0.14.6
-- pandoc-types-1.17.4.2
-- haddock-library-1.5.0.1
-- texmath-0.11
+- pandoc-types-1.17.5.1
+- haddock-library-1.6.0
+- texmath-0.11.1
+- HsYAML-0.1.1.1
+- text-1.2.3.0
+- Cabal-2.4.0.0
+- dlist-0.8.0.4
+- parsec-3.1.13.0
+- skylighting-core-0.7.3
+- skylighting-0.7.3
+- yaml-0.9.0
+- hslua-1.0.0
+- hslua-module-text-0.2.0
resolver: lts-9.14
diff --git a/stack.yaml b/stack.yaml
index 5f96a78d9..986cae642 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -2,7 +2,6 @@ flags:
pandoc:
trypandoc: false
embed_data_files: true
- network-uri: true
pandoc-citeproc:
bibutils: true
embed_data_files: true
@@ -11,17 +10,22 @@ flags:
debug: false
packages:
- '.'
+# See https://github.com/haskell-foundation/foundation/pull/503
+# We can go back to released foundation when this is fixed.
+- location:
+ git: https://github.com/jgm/foundation
+ commit: '4294e39'
+ subdirs:
+ - foundation
+ extra-dep: true
extra-deps:
-- pandoc-citeproc-0.14.3.1
-- skylighting-0.7.0.2
-- skylighting-core-0.7.0.2
-- ansi-terminal-0.8.0.2
-- tasty-1.0.1.1
-- test-framework-0.8.2.0
-- pandoc-types-1.17.4.2
-- cmark-gfm-0.1.3
-- hslua-module-text-0.1.2.1
-- texmath-0.11
+- pandoc-citeproc-0.14.4
+- haddock-library-1.6.0
+- HsYAML-0.1.1.1
+- texmath-0.11.1
+- yaml-0.9.0
+- hslua-1.0.1
+- hslua-module-text-0.2.0
ghc-options:
"$locals": -fhide-source-paths -XNoImplicitPrelude
-resolver: lts-10.10
+resolver: lts-12.6
diff --git a/test/Tests/Lua.hs b/test/Tests/Lua.hs
index 28a691715..3fe9c1121 100644
--- a/test/Tests/Lua.hs
+++ b/test/Tests/Lua.hs
@@ -7,7 +7,7 @@ import Control.Monad (when)
import Data.Version (Version (versionBranch))
import System.FilePath ((</>))
import Test.Tasty (TestTree, localOption)
-import Test.Tasty.HUnit (Assertion, assertEqual, testCase)
+import Test.Tasty.HUnit (Assertion, assertEqual, assertFailure, testCase)
import Test.Tasty.QuickCheck (QuickCheckTests (..), ioProperty, testProperty)
import Text.Pandoc.Arbitrary ()
import Text.Pandoc.Builder (bulletList, divWith, doc, doubleQuoted, emph,
@@ -109,7 +109,8 @@ tests = map (localOption (QuickCheckTests 20))
assertFilterConversion "pandoc.utils doesn't work as expected."
"test-pandoc-utils.lua"
(doc $ para "doesn't matter")
- (doc $ mconcat [ plain (str "hierarchicalize: OK")
+ (doc $ mconcat [ plain (str "blocks_to_inlines: OK")
+ , plain (str "hierarchicalize: OK")
, plain (str "normalize_date: OK")
, plain (str "pipe: OK")
, plain (str "failing pipe: OK")
@@ -129,7 +130,7 @@ tests = map (localOption (QuickCheckTests 20))
, testCase "Pandoc version is set" . runPandocLua' $ do
Lua.getglobal' "table.concat"
Lua.getglobal "PANDOC_VERSION"
- Lua.push ("." :: String) -- seperator
+ Lua.push ("." :: String) -- separator
Lua.call 2 1
Lua.liftIO . assertEqual "pandoc version is wrong" pandocVersion
=<< Lua.peek Lua.stackTop
@@ -163,11 +164,11 @@ tests = map (localOption (QuickCheckTests 20))
, testCase "informative error messages" . runPandocLua' $ do
Lua.pushboolean True
- err <- Lua.peekEither Lua.stackTop :: Lua.Lua (Either String Pandoc)
- case err of
+ err <- Lua.peekEither Lua.stackTop
+ case (err :: Either String Pandoc) of
Left msg -> do
let expectedMsg = "Could not get Pandoc value: "
- ++ "expected table but got boolean."
+ <> "table expected, got boolean"
Lua.liftIO $ assertEqual "unexpected error message" expectedMsg msg
Right _ -> error "Getting a Pandoc element from a bool should fail."
]
@@ -178,13 +179,13 @@ assertFilterConversion msg filterPath docIn docExpected = do
setUserDataDir (Just "../data")
runLuaFilter def ("lua" </> filterPath) [] docIn
case docEither of
- Left _ -> fail "lua filter failed"
+ Left exception -> assertFailure (show exception)
Right docRes -> assertEqual msg docExpected docRes
-roundtripEqual :: (Eq a, Lua.FromLuaStack a, Lua.ToLuaStack a) => a -> IO Bool
+roundtripEqual :: (Eq a, Lua.Peekable a, Lua.Pushable a) => a -> IO Bool
roundtripEqual x = (x ==) <$> roundtripped
where
- roundtripped :: (Lua.FromLuaStack a, Lua.ToLuaStack a) => IO a
+ roundtripped :: (Lua.Peekable a, Lua.Pushable a) => IO a
roundtripped = runPandocLua' $ do
oldSize <- Lua.gettop
Lua.push x
diff --git a/test/Tests/Readers/HTML.hs b/test/Tests/Readers/HTML.hs
index f61f1f497..eedb99029 100644
--- a/test/Tests/Readers/HTML.hs
+++ b/test/Tests/Readers/HTML.hs
@@ -4,11 +4,14 @@ module Tests.Readers.HTML (tests) where
import Prelude
import Data.Text (Text)
+import qualified Data.Text as T
import Test.Tasty
+import Test.Tasty.QuickCheck
import Tests.Helpers
import Text.Pandoc
import Text.Pandoc.Arbitrary ()
import Text.Pandoc.Builder
+import Text.Pandoc.Walk (walk)
html :: Text -> Pandoc
html = purely $ readHtml def
@@ -16,6 +19,27 @@ html = purely $ readHtml def
htmlNativeDivs :: Text -> Pandoc
htmlNativeDivs = purely $ readHtml def { readerExtensions = enableExtension Ext_native_divs $ readerExtensions def }
+makeRoundTrip :: Block -> Block
+makeRoundTrip CodeBlock{} = Para [Str "code block was here"]
+makeRoundTrip LineBlock{} = Para [Str "line block was here"]
+makeRoundTrip RawBlock{} = Para [Str "raw block was here"]
+makeRoundTrip x = x
+
+removeRawInlines :: Inline -> Inline
+removeRawInlines RawInline{} = Str "raw inline was here"
+removeRawInlines x = x
+
+roundTrip :: Blocks -> Bool
+roundTrip b = d'' == d'''
+ where d = walk removeRawInlines $
+ walk makeRoundTrip $ Pandoc nullMeta $ toList b
+ d' = rewrite d
+ d'' = rewrite d'
+ d''' = rewrite d''
+ rewrite = html . T.pack . (++ "\n") . T.unpack .
+ purely (writeHtml5String def
+ { writerWrapText = WrapPreserve })
+
tests :: [TestTree]
tests = [ testGroup "base tag"
[ test html "simple" $
@@ -53,4 +77,5 @@ tests = [ testGroup "base tag"
, test htmlNativeDivs "<main> followed by text" $ "<main>main content</main>non-main content" =?>
doc (divWith ("", [], [("role", "main")]) (plain (text "main content")) <> plain (text "non-main content"))
]
+ , testProperty "Round trip" (withMaxSuccess 25 roundTrip)
]
diff --git a/test/Tests/Readers/Markdown.hs b/test/Tests/Readers/Markdown.hs
index e44c7fc19..be89e708e 100644
--- a/test/Tests/Readers/Markdown.hs
+++ b/test/Tests/Readers/Markdown.hs
@@ -39,7 +39,7 @@ testBareLink (inp, ils) =
(unpack inp) (inp, doc $ para ils)
autolink :: String -> Inlines
-autolink = autolinkWith nullAttr
+autolink = autolinkWith ("",["uri"],[])
autolinkWith :: Attr -> String -> Inlines
autolinkWith attr s = linkWith attr s "" (str s)
@@ -72,10 +72,12 @@ bareLinkTests =
, ("http://en.wikipedia.org/wiki/Sprite_(computer_graphics)",
autolink "http://en.wikipedia.org/wiki/Sprite_(computer_graphics)")
, ("http://en.wikipedia.org/wiki/Sprite_[computer_graphics]",
- link "http://en.wikipedia.org/wiki/Sprite_%5Bcomputer_graphics%5D" ""
+ linkWith ("",["uri"],[])
+ "http://en.wikipedia.org/wiki/Sprite_%5Bcomputer_graphics%5D" ""
(str "http://en.wikipedia.org/wiki/Sprite_[computer_graphics]"))
, ("http://en.wikipedia.org/wiki/Sprite_{computer_graphics}",
- link "http://en.wikipedia.org/wiki/Sprite_%7Bcomputer_graphics%7D" ""
+ linkWith ("",["uri"],[])
+ "http://en.wikipedia.org/wiki/Sprite_%7Bcomputer_graphics%7D" ""
(str "http://en.wikipedia.org/wiki/Sprite_{computer_graphics}"))
, ("http://example.com/Notification_Center-GitHub-20101108-140050.jpg",
autolink "http://example.com/Notification_Center-GitHub-20101108-140050.jpg")
@@ -199,7 +201,9 @@ tests = [ testGroup "inline code"
]
, testGroup "emoji"
[ test markdownGH "emoji symbols" $
- ":smile: and :+1:" =?> para (text "😄 and 👍")
+ ":smile: and :+1:" =?> para (spanWith ("", ["emoji"], [("data-emoji", "smile")]) "😄" <>
+ space <> str "and" <> space <>
+ spanWith ("", ["emoji"], [("data-emoji", "+1")]) "👍")
]
, "unbalanced brackets" =:
"[[[[[[[[[[[[hi" =?> para (text "[[[[[[[[[[[[hi")
diff --git a/test/Tests/Readers/Muse.hs b/test/Tests/Readers/Muse.hs
index ecdd5fdb0..958a74915 100644
--- a/test/Tests/Readers/Muse.hs
+++ b/test/Tests/Readers/Muse.hs
@@ -39,9 +39,9 @@ makeRoundTrip x = x
-- Demand that any AST produced by Muse reader and written by Muse writer can be read back exactly the same way.
-- Currently we remove tables and compare first rewrite to the second.
-roundTrip :: Block -> Bool
+roundTrip :: Blocks -> Bool
roundTrip b = d' == d''
- where d = walk makeRoundTrip $ Pandoc nullMeta [b]
+ where d = walk makeRoundTrip $ Pandoc nullMeta $ toList b
d' = rewrite d
d'' = rewrite d'
rewrite = amuse . T.pack . (++ "\n") . T.unpack .
@@ -62,6 +62,14 @@ tests =
"*Foo bar*" =?>
para (emph . spcSep $ ["Foo", "bar"])
+ -- Emacs Muse allows this
+ , "Newline in the beginning of emphasis" =:
+ "*\nFoo bar*" =?>
+ para (emph ("Foo" <> space <> "bar"))
+ , "Newline in the end of emphasis" =:
+ "*Foo bar\n*" =?>
+ para (emph ("Foo" <> space <> "bar"))
+
, "Comma after closing *" =:
"Foo *bar*, baz" =?>
para ("Foo " <> emph "bar" <> ", baz")
@@ -74,6 +82,10 @@ tests =
"Foo x*bar* baz" =?>
para "Foo x*bar* baz"
+ , "Digit after closing *" =:
+ "Foo *bar*0 baz" =?>
+ para "Foo *bar*0 baz"
+
, "Emphasis tag" =:
"<em>Foo bar</em>" =?>
para (emph . spcSep $ ["Foo", "bar"])
@@ -138,6 +150,10 @@ tests =
"Foo =bar=, baz" =?>
para (text "Foo " <> code "bar" <> text ", baz")
+ , "Not code if followed by digit" =:
+ "Foo =bar=0 baz" =?>
+ para (text "Foo =bar=0 baz")
+
, "One character code" =: "=c=" =?> para (code "c")
, "Three = characters is not a code" =: "===" =?> para "==="
@@ -194,9 +210,27 @@ tests =
, "Image" =:
"[[image.jpg]]" =?>
para (image "image.jpg" "" mempty)
+ , "Closing bracket is not allowed in image filename" =:
+ "[[foo]bar.jpg]]" =?>
+ para (text "[[foo]bar.jpg]]")
, "Image with description" =:
"[[image.jpg][Image]]" =?>
para (image "image.jpg" "" (text "Image"))
+ , "Image with space in filename" =:
+ "[[image name.jpg]]" =?>
+ para (image "image name.jpg" "" mempty)
+ , "Image with width" =:
+ "[[image.jpg 60]]" =?>
+ para (imageWith ("", [], [("width", "60%")]) "image.jpg" mempty mempty)
+ , "At least one space is required between image filename and width" =:
+ "[[image.jpg60]]" =?>
+ para (link "image.jpg60" mempty (str "image.jpg60"))
+ , "Left-aligned image with width" =:
+ "[[image.png 60 l][Image]]" =?>
+ para (imageWith ("", ["align-left"], [("width", "60%")]) "image.png" "" (str "Image"))
+ , "Right-aligned image with width" =:
+ "[[image.png 60 r][Image]]" =?>
+ para (imageWith ("", ["align-right"], [("width", "60%")]) "image.png" "" (str "Image"))
, "Image link" =:
"[[URL:image.jpg]]" =?>
para (link "image.jpg" "" (str "image.jpg"))
@@ -225,8 +259,8 @@ tests =
]
]
- , testGroup "Blocks" $
- [ testProperty "Round trip" roundTrip
+ , testGroup "Blocks"
+ [ testProperty "Round trip" (withMaxSuccess 25 roundTrip)
, "Block elements end paragraphs" =:
T.unlines [ "First paragraph"
, "----"
@@ -385,6 +419,12 @@ tests =
, "</verse>"
] =?>
lineBlock [ "" ]
+ , "Verse tag with verbatim close tag inside" =:
+ T.unlines [ "<verse>"
+ , "<verbatim></verse></verbatim>"
+ , "</verse>"
+ ] =?>
+ lineBlock [ "</verse>" ]
, testGroup "Example"
[ "Braces on separate lines" =:
T.unlines [ "{{{"
@@ -589,6 +629,18 @@ tests =
T.unlines [ "* Foo"
, "bar"
] =?> header 1 "Foo\nbar"
+ , test (purely $ readMuse def { readerExtensions = extensionsFromList [Ext_amuse, Ext_auto_identifiers]})
+ "Auto identifiers"
+ (T.unlines [ "* foo"
+ , "** Foo"
+ , "* bar"
+ , "** foo"
+ , "* foo"
+ ] =?> headerWith ("foo",[],[]) 1 "foo" <>
+ headerWith ("foo-1",[],[]) 2 "Foo" <>
+ headerWith ("bar",[],[]) 1 "bar" <>
+ headerWith ("foo-2",[],[]) 2 "foo" <>
+ headerWith ("foo-3",[],[]) 1 "foo")
]
, testGroup "Directives"
[ "Title" =:
@@ -710,6 +762,13 @@ tests =
, " > Baz"
] =?>
para ("Foo" <> note (para "Bar" <> lineBlock ["Baz"]))
+ , "Footnote ending in self-terminating element and followed by paragraph" =:
+ T.unlines [ "Foo[1]"
+ , ""
+ , "[1] > bar"
+ , "baz"
+ ] =?>
+ para (str "Foo" <> note (lineBlock ["bar"])) <> para (str "baz")
, test emacsMuse "Emacs multiparagraph footnotes"
(T.unlines
[ "First footnote reference[1] and second footnote reference[2]."
@@ -798,6 +857,14 @@ tests =
[plain "Foo", plain "bar", plain "baz"]
[[plain "First", plain "row", plain "here"],
[plain "Second", plain "row", plain "there"]]
+ , "Table caption with +" =:
+ T.unlines
+ [ "Foo | bar"
+ , "|+ Table + caption +|"
+ ] =?>
+ table (text "Table + caption") (replicate 2 (AlignDefault, 0.0))
+ []
+ [[plain "Foo", plain "bar"]]
, "Caption without table" =:
"|+ Foo bar baz +|" =?>
table (text "Foo bar baz") [] [] []
@@ -972,7 +1039,7 @@ tests =
, para "c"
]
]
- , "List continuation afeter nested list" =:
+ , "List continuation after nested list" =:
T.unlines
[ " - - foo"
, ""
@@ -1118,6 +1185,11 @@ tests =
] =?>
bulletList [ lineBlock [ "foo" ] ] <> bulletList [ para "bar" ]
]
+ , "List ending in self-terminating element and followed by paragraph" =:
+ T.unlines [ " - > Foo"
+ , "bar"
+ ] =?>
+ bulletList [lineBlock ["Foo"]] <> para (str "bar")
-- Test that definition list requires a leading space.
-- Emacs Muse does not require a space, we follow Amusewiki here.
, "Not a definition list" =:
@@ -1335,7 +1407,8 @@ tests =
, " <verse>"
, " </quote>"
, " </verse>"
+ , "</quote>"
] =?>
- para "<quote>" <> bulletList [ para "Foo" <> para "</quote>" <> para "bar" <> lineBlock [ "</quote>" ] ]
+ blockQuote (bulletList [ para "Foo" <> para "</quote>" <> para "bar" <> lineBlock [ "</quote>" ] ])
]
]
diff --git a/test/Tests/Readers/Org/Block/Header.hs b/test/Tests/Readers/Org/Block/Header.hs
index 3b0d7dda9..913c830d6 100644
--- a/test/Tests/Readers/Org/Block/Header.hs
+++ b/test/Tests/Readers/Org/Block/Header.hs
@@ -181,4 +181,42 @@ tests =
, " :END:"
] =?>
headerWith ("not-numbered", ["unnumbered"], []) 1 "Not numbered"
+
+ , testGroup "planning information"
+ [ "Planning info is not included in output" =:
+ T.unlines [ "* important"
+ , T.unwords
+ [ "CLOSED: [2018-09-05 Wed 13:58]"
+ , "DEADLINE: <2018-09-17 Mon>"
+ , "SCHEDULED: <2018-09-10 Mon>"
+ ]
+ ] =?>
+ headerWith ("important", [], []) 1 "important"
+
+ , "Properties after planning info are recognized" =:
+ T.unlines [ "* important "
+ , " " <> T.unwords
+ [ "CLOSED: [2018-09-05 Wed 13:58]"
+ , "DEADLINE: <2018-09-17 Mon>"
+ , "SCHEDULED: <2018-09-10 Mon>"
+ ]
+ , " :PROPERTIES:"
+ , " :custom_id: look"
+ , " :END:"
+ ] =?>
+ headerWith ("look", [], []) 1 "important"
+
+ , "Planning info followed by test" =:
+ T.unlines [ "* important "
+ , " " <> T.unwords
+ [ "CLOSED: [2018-09-05 Wed 13:58]"
+ , "DEADLINE: <2018-09-17 Mon>"
+ , "SCHEDULED: <2018-09-10 Mon>"
+ ]
+ , " :PROPERTIES:"
+ , " :custom_id: look"
+ , " :END:"
+ ] =?>
+ headerWith ("look", [], []) 1 "important"
+ ]
]
diff --git a/test/Tests/Readers/Org/Block/List.hs b/test/Tests/Readers/Org/Block/List.hs
index f273b684d..bdab01404 100644
--- a/test/Tests/Readers/Org/Block/List.hs
+++ b/test/Tests/Readers/Org/Block/List.hs
@@ -243,4 +243,15 @@ tests =
mconcat [ para "CLOSED: [2015-10-19 Mon 15:03]"
, bulletList [ plain "Note taken on [2015-10-19 Mon 13:24]" ]
]
+
+ , "Markup after header and list" =:
+ T.unlines [ "* headline"
+ , "- list"
+ , ""
+ , "~variable name~"
+ ] =?>
+ mconcat [ headerWith ("headline", [], []) 1 "headline"
+ , bulletList [ plain "list" ]
+ , para (code "variable name")
+ ]
]
diff --git a/test/Tests/Readers/Org/Directive.hs b/test/Tests/Readers/Org/Directive.hs
index bb9c52e69..87abb714d 100644
--- a/test/Tests/Readers/Org/Directive.hs
+++ b/test/Tests/Readers/Org/Directive.hs
@@ -150,6 +150,29 @@ tests =
, "* Headline :hello:world:"
] =?>
headerWith ("headline", [], mempty) 1 "Headline"
+
+ , testGroup "planning information"
+ [ "include planning info after headlines" =:
+ T.unlines [ "#+OPTIONS: p:t"
+ , "* important"
+ , " DEADLINE: <2018-10-01 Mon> SCHEDULED: <2018-09-15 Sat>"
+ ] =?>
+ mconcat [ headerWith ("important", mempty, mempty) 1 "important"
+ , plain $ strong "DEADLINE:"
+ <> space
+ <> emph (str "<2018-10-01 Mon>")
+ <> space
+ <> strong "SCHEDULED:"
+ <> space
+ <> emph (str "<2018-09-15 Sat>")
+ ]
+
+ , "empty planning info is not included" =:
+ T.unlines [ "#+OPTIONS: p:t"
+ , "* Wichtig"
+ ] =?>
+ headerWith ("wichtig", mempty, mempty) 1 "Wichtig"
+ ]
]
, testGroup "Include"
diff --git a/test/Tests/Readers/Org/Inline.hs b/test/Tests/Readers/Org/Inline.hs
index 07fe2d2e9..9cfcda79f 100644
--- a/test/Tests/Readers/Org/Inline.hs
+++ b/test/Tests/Readers/Org/Inline.hs
@@ -96,7 +96,7 @@ tests =
"[fn::Schreib mir eine E-Mail]" =?>
para (note $ para "Schreib mir eine E-Mail")
- , "Markup-chars not occuring on word break are symbols" =:
+ , "Markup-chars not occurring on word break are symbols" =:
T.unlines [ "this+that+ +so+on"
, "seven*eight* nine*"
, "+not+funny+"
@@ -280,6 +280,13 @@ tests =
)
"echo 'Hello, World'")
+ , "Inline code block with a blank argument array" =:
+ "src_sh[]{echo 'Hello, World'}" =?>
+ para (codeWith ( ""
+ , [ "bash" ]
+ , [ ("org-language", "sh") ])
+ "echo 'Hello, World'")
+
, "Inline code block with toggle" =:
"src_sh[:toggle]{echo $HOME}" =?>
para (codeWith ( ""
diff --git a/test/Tests/Readers/RST.hs b/test/Tests/Readers/RST.hs
index 906ed4ff9..963e7530d 100644
--- a/test/Tests/Readers/RST.hs
+++ b/test/Tests/Readers/RST.hs
@@ -177,7 +177,7 @@ tests = [ "line block with blank line" =:
=: ".. role:: haskell(code)\n.. role:: lhs(haskell)\n\n:lhs:`text`"
=?> para (codeWith ("", ["lhs", "haskell", "sourceCode"], []) "text")
, "unknown role" =: ":unknown:`text`" =?>
- para (spanWith ("",[],[("role","unknown")]) (str "text"))
+ para (codeWith ("",["interpreted-text"],[("role","unknown")]) "text")
]
, testGroup "footnotes"
[ "remove space before note" =: T.unlines
@@ -188,4 +188,18 @@ tests = [ "line block with blank line" =:
] =?>
para ("foo" <> note (para "bar"))
]
+ , testGroup "inlines"
+ [ "links can contain an URI without being parsed twice (#4581)" =:
+ "`http://loc <http://loc>`__" =?>
+ para (link "http://loc" "" "http://loc")
+ , "inline markup cannot be nested" =:
+ "**a*b*c**" =?>
+ para (strong "a*b*c")
+ , "bare URI parsing disabled inside emphasis (#4561)" =:
+ "*http://location*" =?>
+ para (emph (text "http://location"))
+ , "include newlines" =:
+ "**before\nafter**" =?>
+ para (strong (text "before\nafter"))
+ ]
]
diff --git a/test/Tests/Writers/HTML.hs b/test/Tests/Writers/HTML.hs
index e771255b3..dfacda608 100644
--- a/test/Tests/Writers/HTML.hs
+++ b/test/Tests/Writers/HTML.hs
@@ -43,4 +43,9 @@ tests = [ testGroup "inline code"
image "/url" "title" ("my " <> emph "image")
=?> "<img src=\"/url\" title=\"title\" alt=\"my image\" />"
]
+ , testGroup "blocks"
+ [ "definition list with empty <dt>" =:
+ definitionList [(mempty, [para $ text "foo bar"])]
+ =?> "<dl><dt></dt><dd><p>foo bar</p></dd></dl>"
+ ]
]
diff --git a/test/Tests/Writers/Muse.hs b/test/Tests/Writers/Muse.hs
index 50c0e78eb..f7287d57d 100644
--- a/test/Tests/Writers/Muse.hs
+++ b/test/Tests/Writers/Muse.hs
@@ -275,7 +275,7 @@ tests = [ testGroup "block elements"
unlines [ "#bar"
, "** Foo"
]
- , "empty heading" =: header 4 (mempty) =?> "**** <verbatim></verbatim>"
+ , "empty heading" =: header 4 mempty =?> "**** <verbatim></verbatim>"
]
, "horizontal rule" =: horizontalRule =?> "----"
, "escape horizontal rule" =: para (text "----") =?> "<verbatim></verbatim>----"
@@ -283,6 +283,7 @@ tests = [ testGroup "block elements"
, "don't escape horizontal inside paragraph" =: para (text "foo ---- bar") =?> "foo ---- bar"
, "escape nonbreaking space" =: para (text "~~") =?> "<verbatim>~~</verbatim>"
, "escape > in the beginning of line" =: para (text "> foo bar") =?> "<verbatim></verbatim>> foo bar"
+ , "escape string with > and space in the beginning of line" =: para (str "> foo bar") =?> "<verbatim></verbatim>> foo bar"
, testGroup "tables"
[ "table without header" =:
let rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
@@ -341,36 +342,95 @@ tests = [ testGroup "block elements"
, "do not escape colon" =: str ":" =?> ":"
, "escape - to avoid accidental unordered lists" =: text " - foo" =?> "<verbatim></verbatim> - foo"
, "escape - inside a list to avoid accidental nested unordered lists" =:
- bulletList [ (para $ text "foo") <>
- (para $ text "- bar")
+ bulletList [ para (text "foo") <>
+ para (text "- bar")
] =?>
unlines [ " - foo"
, ""
, " <verbatim></verbatim>- bar"
]
+ , "escape strings starting with - inside a list" =:
+ bulletList [ para (str "foo") <>
+ para (str "- bar")
+ ] =?>
+ unlines [ " - foo"
+ , ""
+ , " <verbatim></verbatim>- bar"
+ ]
+ , "escape - inside a note" =:
+ note (para (text "- foo")) =?>
+ unlines [ "[1]"
+ , ""
+ , "[1] <verbatim></verbatim>- foo"
+ ]
+ , "escape - after softbreak in note" =:
+ note (para (str "foo" <> softbreak <> str "- bar")) =?>
+ unlines [ "[1]"
+ , ""
+ , "[1] foo"
+ , " <verbatim></verbatim>- bar"
+ ]
, "escape ; to avoid accidental comments" =: text "; foo" =?> "<verbatim></verbatim>; foo"
+ , "escape strings starting with ; and space" =: str "; foo" =?> "<verbatim></verbatim>; foo"
, "escape ; after softbreak" =: text "foo" <> softbreak <> text "; bar" =?> "foo\n<verbatim></verbatim>; bar"
, "escape ; after linebreak" =: text "foo" <> linebreak <> text "; bar" =?> "foo<br>\n<verbatim></verbatim>; bar"
, "do not escape ; inside paragraph" =: text "foo ; bar" =?> "foo ; bar"
+ , "escape newlines" =: str "foo\nbar" =?> "foo bar"
]
, testGroup "emphasis"
- [ "emph" =: emph (text "foo") =?> "<em>foo</em>"
- , "strong" =: strong (text "foo") =?> "<strong>foo</strong>"
+ [ "emphasis" =: emph (text "foo") =?> "*foo*"
+ , "emphasis inside word" =: text "foo" <> emph (text "bar") <> text "baz" =?> "foo<em>bar</em>baz"
+ , "emphasis before comma" =: emph (text "foo") <> text ", bar" =?> "*foo*, bar"
+ , "emphasis before period" =: emph (text "foobar") <> text "." =?> "*foobar*."
+ , "empty emphasis" =: emph mempty =?> "<em></em>"
+ , "empty strong" =: strong mempty =?> "<strong></strong>"
+ , "empty strong emphasis" =: strong (emph mempty) =?> "**<em></em>**"
+ , "empty emphasized strong" =: emph (strong mempty) =?> "*<strong></strong>*"
+ , "emphasized empty string" =: emph (str "") =?> "<em></em>"
+ , "strong empty string" =: strong (str "") =?> "<strong></strong>"
+ , "strong emphasized empty string" =: strong (emph (str "")) =?> "**<em></em>**"
+ , "emphasized strong empty string" =: emph (strong (str "")) =?> "*<strong></strong>*"
+ , "emphasized string with space" =: emph (str " ") =?> "<em> </em>"
+ , "emphasized string ending with space" =: emph (str "foo ") =?> "<em>foo </em>"
+ , "emphasized string with tab" =: emph (str "\t") =?> "<em>\t</em>"
+ , "emphasized space between empty strings" =: emph (str "" <> space <> str "") =?> "<em> </em>"
+ , "strong" =: strong (text "foo") =?> "**foo**"
+ , "strong inside word" =: text "foo" <> strong (text "bar") <> text "baz" =?> "foo<strong>bar</strong>baz"
+ , "strong emphasis" =: strong (emph (text "foo")) =?> "***foo***"
+ , "strong after emphasis" =: emph (text "foo") <> strong (text "bar") =?> "*foo*<strong>bar</strong>"
+ , "strong emphasis after emphasis" =: emph (text "foo") <> strong (emph (text "bar")) =?> "*foo*<strong>*bar*</strong>"
+ , "strong in the end of emphasis" =: emph (text "foo" <> strong (text "bar")) =?> "*foo<strong>bar</strong>*"
, "strikeout" =: strikeout (text "foo") =?> "<del>foo</del>"
+ , "space at the beginning of emphasis" =: emph (text " foo") =?> "<em> foo</em>"
+ , "space at the end of emphasis" =: emph (text "foo ") =?> "<em>foo </em>"
+ , "space at the beginning of strong" =: strong (text " foo") =?> "<strong> foo</strong>"
+ , "space at the end of strong" =: strong (text "foo ") =?> "<strong>foo </strong>"
+ , "space at the beginning of strong emphasis" =: strong (emph (text " foo")) =?> "**<em> foo</em>**"
+ , "space at the end of strong emphasis" =: strong (emph (text "foo ")) =?> "**<em>foo </em>**"
+ , "space at the beginning of emphasiszed strong" =: emph (strong (text " foo")) =?> "*<strong> foo</strong>*"
+ , "space at the end of emphasized strong" =: emph (strong (text "foo ")) =?> "*<strong>foo </strong>*"
]
, "superscript" =: superscript (text "foo") =?> "<sup>foo</sup>"
, "subscript" =: subscript (text "foo") =?> "<sub>foo</sub>"
- , "smallcaps" =: smallcaps (text "foo") =?> "<em>foo</em>"
- , "smallcaps near emphasis" =: emph (str "foo") <> smallcaps (str "bar") =?> "<em>foobar</em>"
+ , "smallcaps" =: smallcaps (text "foo") =?> "*foo*"
+ , "smallcaps near emphasis" =: emph (str "foo") <> smallcaps (str "bar") =?> "*foobar*"
, "single quoted" =: singleQuoted (text "foo") =?> "‘foo’"
, "double quoted" =: doubleQuoted (text "foo") =?> "“foo”"
-- Cite is trivial
, testGroup "code"
- [ "simple" =: code "foo" =?> "<code>foo</code>"
+ [ "simple" =: code "foo" =?> "=foo="
+ , "empty" =: code "" =?> "<code></code>"
+ , "space" =: code " " =?> "<code> </code>"
+ , "space at the beginning" =: code " foo" =?> "<code> foo</code>"
+ , "space at the end" =: code "foo " =?> "<code>foo </code>"
+ , "use tags for =" =: code "foo = bar" =?> "<code>foo = bar</code>"
, "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><code>foo = bar<</code><code>/code> baz</code>"
- , "normalization with attributes" =: codeWith ("",["haskell"],[]) "foo" <> code "bar" =?> "<code>foobar</code>"
- , "normalization" =: code "</co" <> code "de>" =?> "<code><</code><code>/code></code>"
- , "normalization with empty string" =: code "</co" <> str "" <> code "de>" =?> "<code><</code><code>/code></code>"
+ , "normalization with attributes" =: codeWith ("",["haskell"],[]) "foo" <> code "bar" =?> "=foobar="
+ , "code tag" =: code "<code>foo</code>" =?> "=<code>foo</code>="
+ , "normalization" =: code "</co" <> code "de>" <> code "=" =?> "<code><</code><code>/code>=</code>"
+ , "normalization with empty string" =: code "</co" <> str "" <> code "de>" <> code "=" =?> "<code><</code><code>/code>=</code>"
+ , "emphasized code" =: emph (code "foo") =?> "*=foo=*"
+ , "strong code" =: strong (code "foo") =?> "**=foo=**"
]
, testGroup "spaces"
[ "space" =: text "a" <> space <> text "b" =?> "a b"
@@ -385,7 +445,7 @@ tests = [ testGroup "block elements"
, testGroup "math"
[ "inline math" =: math "2^3" =?> "2<sup>3</sup>"
, "display math" =: displayMath "2^3" =?> "2<sup>3</sup>"
- , "multiple letters in inline math" =: math "abc" =?> "<em>abc</em>"
+ , "multiple letters in inline math" =: math "abc" =?> "*abc*"
, "expand math before normalization" =: math "[" <> str "2]" =?> "<verbatim>[2]</verbatim>"
, "multiple math expressions inside one inline list" =: math "5_4" <> text ", " <> displayMath "3^2" =?> "5<sub>4</sub>, 3<sup>2</sup>"
]
@@ -441,11 +501,11 @@ tests = [ testGroup "block elements"
=?> "<class name=\"foobar\">Some text</class>"
, "span without class" =: spanWith ("",[],[]) (text "Some text")
=?> "<class>Some text</class>"
- , "span with anchor" =: spanWith ("anchor", [], []) (mempty) <> (text "Foo bar")
+ , "span with anchor" =: spanWith ("anchor", [], []) mempty <> text "Foo bar"
=?> "#anchor Foo bar"
- , "empty span with anchor" =: spanWith ("anchor", [], []) (mempty)
+ , "empty span with anchor" =: spanWith ("anchor", [], []) mempty
=?> "#anchor"
- , "empty span without class and anchor" =: spanWith ("", [], []) (mempty)
+ , "empty span without class and anchor" =: spanWith ("", [], []) mempty
=?> "<class></class>"
, "span with class and anchor" =: spanWith ("anchor", ["foo"], []) (text "bar")
=?> "#anchor <class name=\"foo\">bar</class>"
@@ -461,7 +521,7 @@ tests = [ testGroup "block elements"
"<em>foo</em>bar"
, "emph quoted" =:
para (doubleQuoted (emph (text "foo"))) =?>
- "“<em>foo</em>”"
+ "“*foo*”"
, "strong word before" =:
para (text "foo" <> strong (text "bar")) =?>
"foo<strong>bar</strong>"
@@ -470,7 +530,7 @@ tests = [ testGroup "block elements"
"<strong>foo</strong>bar"
, "strong quoted" =:
para (singleQuoted (strong (text "foo"))) =?>
- "‘<strong>foo</strong>’"
+ "‘**foo**’"
]
]
]
diff --git a/test/Tests/Writers/RST.hs b/test/Tests/Writers/RST.hs
index a1a4510e0..0d5b7c38a 100644
--- a/test/Tests/Writers/RST.hs
+++ b/test/Tests/Writers/RST.hs
@@ -16,6 +16,11 @@ infix 4 =:
=> String -> (a, String) -> TestTree
(=:) = test (purely (writeRST def . toPandoc))
+testTemplate :: (ToString a, ToString c, ToPandoc a) =>
+ String -> String -> (a, c) -> TestTree
+testTemplate t =
+ test (purely (writeRST def{ writerTemplate = Just t }) . toPandoc)
+
tests :: [TestTree]
tests = [ testGroup "rubrics"
[ "in list item" =:
@@ -156,4 +161,7 @@ tests = [ testGroup "rubrics"
, "Header 2"
, "--------"]
]
+ , testTemplate "$subtitle$\n" "subtitle" $
+ (setMeta "subtitle" ("subtitle" :: Inlines) $ doc $ plain "") =?>
+ ("subtitle" :: String)
]
diff --git a/test/command/1126.md b/test/command/1126.md
new file mode 100644
index 000000000..014a8ae2d
--- /dev/null
+++ b/test/command/1126.md
@@ -0,0 +1,29 @@
+```
+% pandoc -f html -t latex
+\begin{eqnarray}
+A&=&B,\\
+C&=&D
+\end{eqnarray}
+^D
+\textbackslash{}begin\{eqnarray\}
+A\&=\&B,\textbackslash{}\textbackslash{} C\&=\&D
+\textbackslash{}end\{eqnarray\}
+```
+
+```
+% pandoc -f html+raw_tex -t latex
+<p>See \eqref{myeq}.</p>
+\begin{eqnarray}
+A&=&B,\\
+C&amp;=&amp;D
+\\label{myeq}
+\end{eqnarray}
+^D
+See \eqref{myeq}.
+
+\begin{eqnarray}
+A&=&B,\\
+C&=&D
+\\label{myeq}
+\end{eqnarray}
+```
diff --git a/test/command/1710.md b/test/command/1710.md
index d20dfe191..4d9c64b30 100644
--- a/test/command/1710.md
+++ b/test/command/1710.md
@@ -58,7 +58,7 @@ ok
\protect\hypertarget{slide-one}{}
\begin{columns}[T]
-\begin{column}{0.40\textwidth}
+\begin{column}{0.4\textwidth}
\begin{itemize}
\tightlist
\item
@@ -68,7 +68,7 @@ ok
\end{itemize}
\end{column}
-\begin{column}{0.40\textwidth}
+\begin{column}{0.4\textwidth}
\begin{itemize}
\tightlist
\item
@@ -78,11 +78,10 @@ ok
\end{itemize}
\end{column}
-\begin{column}{0.10\textwidth}
+\begin{column}{0.1\textwidth}
ok
\end{column}
\end{columns}
\end{frame}
```
-
diff --git a/test/command/2118.md b/test/command/2118.md
index 27b3723d3..9730dd383 100644
--- a/test/command/2118.md
+++ b/test/command/2118.md
@@ -7,5 +7,5 @@
\label{fig:setminus}
\end{figure}
^D
-[Para [Image ("",[],[("width","80%")]) [Str "Set",Space,Str "subtraction",Span ("",[],[("label","fig:setminus")]) []] ("setminus.png","fig:")]]
+[Para [Image ("fig:setminus",[],[("width","80%")]) [Str "Set",Space,Str "subtraction",Span ("",[],[("label","fig:setminus")]) []] ("setminus.png","fig:")]]
```
diff --git a/test/command/3407.md b/test/command/3407.md
index 3160d1263..aec253ff5 100644
--- a/test/command/3407.md
+++ b/test/command/3407.md
@@ -1,6 +1,6 @@
```
% pandoc -f native -t rst
-[Para [Span ("",[],[("role","foo")]) [Str "text"]]]
+[Para [Code ("",["interpreted-text"],[("role","foo")]) "text"]]
^D
:foo:`text`
```
@@ -9,5 +9,5 @@
% pandoc -f rst -t native
:foo:`text`
^D
-[Para [Span ("",[],[("role","foo")]) [Str "text"]]]
+[Para [Code ("",["interpreted-text"],[("role","foo")]) "text"]]
```
diff --git a/test/command/3432.md b/test/command/3432.md
index 7264d22c3..381f8af87 100644
--- a/test/command/3432.md
+++ b/test/command/3432.md
@@ -195,7 +195,7 @@ List-table without header-rows.
</table>
```
-List-table with empty cells. You need a space after '-', otherwise the row will disapear. Parser for Bulletlists causes this ristriction.
+List-table with empty cells. You need a space after '-', otherwise the row will disappear. Parser for Bulletlists causes this restriction.
```
% pandoc -f rst
diff --git a/test/command/3534.md b/test/command/3534.md
index 89224551b..cd0915d88 100644
--- a/test/command/3534.md
+++ b/test/command/3534.md
@@ -21,3 +21,25 @@ I want to explain the interface of \lstinline[language=Java]{public class MyClas
[Para [Str "I",Space,Str "want",Space,Str "to",Space,Str "explain",Space,Str "the",Space,Str "interface",Space,Str "of",Space,Code ("",["java"],[]) "public class MyClass",Str "."]]
```
+```
+% pandoc -f latex -t html
+I want to explain the interface of \mintinline{java}{public class MyClass}.
+^D
+<p>I want to explain the interface of <code class="sourceCode java"><span class="kw">public</span> <span class="kw">class</span> MyClass</code>.</p>
+
+```
+
+```
+% pandoc -f latex -t html
+I want to explain the interface of \mintinline{java}|public class MyClass|.
+^D
+<p>I want to explain the interface of <code class="sourceCode java"><span class="kw">public</span> <span class="kw">class</span> MyClass</code>.</p>
+
+```
+
+```
+% pandoc -f latex -t native
+I want to explain the interface of \mintinline[linenos]{java}{public class MyClass}.
+^D
+[Para [Str "I",Space,Str "want",Space,Str "to",Space,Str "explain",Space,Str "the",Space,Str "interface",Space,Str "of",Space,Code ("",["java"],[]) "public class MyClass",Str "."]]
+```
diff --git a/test/command/3558.md b/test/command/3558.md
index 795858b78..956b09e57 100644
--- a/test/command/3558.md
+++ b/test/command/3558.md
@@ -6,7 +6,7 @@ hello
\endmulti
^D
-[RawBlock (Format "latex") "\\multi"
+[RawBlock (Format "tex") "\\multi"
,Para [Str "hello"]
-,RawBlock (Format "latex") "\\endmulti"]
+,RawBlock (Format "tex") "\\endmulti"]
```
diff --git a/test/command/3716.md b/test/command/3716.md
index 7e00819da..81e4a9568 100644
--- a/test/command/3716.md
+++ b/test/command/3716.md
@@ -2,5 +2,5 @@
% pandoc
<http://example.com>{.foo}
^D
-<p><a href="http://example.com" class="uri foo">http://example.com</a></p>
+<p><a href="http://example.com" class="foo">http://example.com</a></p>
```
diff --git a/test/command/3804.md b/test/command/3804.md
index c13c2ef42..520d408df 100644
--- a/test/command/3804.md
+++ b/test/command/3804.md
@@ -2,5 +2,5 @@
% pandoc -t native
\titleformat{\chapter}[display]{\normalfont\large\bfseries}{第\thechapter{}章}{20pt}{\Huge}
^D
-[RawBlock (Format "latex") "\\titleformat{\\chapter}[display]{\\normalfont\\large\\bfseries}{\31532\\thechapter{}\31456}{20pt}{\\Huge}"]
+[RawBlock (Format "tex") "\\titleformat{\\chapter}[display]{\\normalfont\\large\\bfseries}{\31532\\thechapter{}\31456}{20pt}{\\Huge}"]
```
diff --git a/test/command/3947.md b/test/command/3947.md
index 7ce0be171..b1d695fbd 100644
--- a/test/command/3947.md
+++ b/test/command/3947.md
@@ -6,6 +6,6 @@
Another Code block
^D
-[RawBlock (Format "latex") "\\newpage"
+[RawBlock (Format "tex") "\\newpage"
,CodeBlock ("",[],[]) "Code block\n\nAnother Code block"]
```
diff --git a/test/command/4016.md b/test/command/4016.md
index 3918251c6..5e4e35e0d 100644
--- a/test/command/4016.md
+++ b/test/command/4016.md
@@ -17,7 +17,7 @@ pandoc -t beamer
\protect\hypertarget{level-2-blocks}{}
\begin{columns}[T]
-\begin{column}{0.40\textwidth}
+\begin{column}{0.4\textwidth}
\begin{block}{Block one}
\begin{itemize}
@@ -29,7 +29,7 @@ pandoc -t beamer
\end{block}
\end{column}
-\begin{column}{0.60\textwidth}
+\begin{column}{0.6\textwidth}
\begin{block}{Block two}
\begin{itemize}
diff --git a/test/command/4056.md b/test/command/4056.md
index eed4f6d6a..e972931dd 100644
--- a/test/command/4056.md
+++ b/test/command/4056.md
@@ -5,7 +5,7 @@
\end{shaded}
}
^D
-[RawBlock (Format "latex") "\\parbox[t]{0.4\\textwidth}{\n\\begin{shaded}\n\\end{shaded}\n}"]
+[RawBlock (Format "tex") "\\parbox[t]{0.4\\textwidth}{\n\\begin{shaded}\n\\end{shaded}\n}"]
```
```
diff --git a/test/command/4159.md b/test/command/4159.md
index 4881edcc5..d61959950 100644
--- a/test/command/4159.md
+++ b/test/command/4159.md
@@ -3,6 +3,6 @@
\newcommand{\gen}{a\ Gen\ b}
abc
^D
-[RawBlock (Format "latex") "\\newcommand{\\gen}{a\\ Gen\\ b}"
+[RawBlock (Format "tex") "\\newcommand{\\gen}{a\\ Gen\\ b}"
,Para [Str "abc"]]
```
diff --git a/test/command/4284.md b/test/command/4284.md
new file mode 100644
index 000000000..eddd1b03a
--- /dev/null
+++ b/test/command/4284.md
@@ -0,0 +1,40 @@
+```
+% pandoc -f org -t native
+#+EXCLUDE_TAGS:apple cat bye dog %
+
+* This should not appear :apple:
+* NOEXPORT should appear if not specified in EXCLUDE_TAGS :noexport:
+* This should not appear :cat:hi:laptop:
+** Children of headers with excluded tags should not appear :xylophone:
+* This should not appear :%:
+^D
+[Header 1 ("noexport-should-appear-if-not-specified-in-excludetags",[],[]) [Str "NOEXPORT",Space,Str "should",Space,Str "appear",Space,Str "if",Space,Str "not",Space,Str "specified",Space,Str "in",Space,Str "EXCLUDE",Subscript [Str "TAGS"],Space,Span ("",["tag"],[("tag-name","noexport")]) [SmallCaps [Str "noexport"]]]]
+```
+
+```
+% pandoc -f org -t native
+#+EXCLUDE_TAGS:elephant
+* This should not appear :elephant:
+* This should appear :fawn:
+^D
+[Header 1 ("this-should-appear",[],[]) [Str "This",Space,Str "should",Space,Str "appear",Space,Span ("",["tag"],[("tag-name","fawn")]) [SmallCaps [Str "fawn"]]]]
+```
+
+```
+% pandoc -f org -t native
+#+EXCLUDE_TAGS: giraffe
+#+EXCLUDE_TAGS: hippo
+* This should not appear :giraffe:
+* This should not appear :hippo:
+* This should appear :noexport:
+^D
+[Header 1 ("this-should-appear",[],[]) [Str "This",Space,Str "should",Space,Str "appear",Space,Span ("",["tag"],[("tag-name","noexport")]) [SmallCaps [Str "noexport"]]]]
+```
+
+```
+% pandoc -f org -t native
+#+EXCLUDE_TAGS:
+* NOEXPORT should appear if not specified in EXCLUDE_TAGS :noexport:
+^D
+[Header 1 ("noexport-should-appear-if-not-specified-in-excludetags",[],[]) [Str "NOEXPORT",Space,Str "should",Space,Str "appear",Space,Str "if",Space,Str "not",Space,Str "specified",Space,Str "in",Space,Str "EXCLUDE",Subscript [Str "TAGS"],Space,Span ("",["tag"],[("tag-name","noexport")]) [SmallCaps [Str "noexport"]]]]
+```
diff --git a/test/command/4528.md b/test/command/4528.md
new file mode 100644
index 000000000..a60f6decf
--- /dev/null
+++ b/test/command/4528.md
@@ -0,0 +1,156 @@
+# Rendering small caps, superscripts and subscripts with and without `raw_html`
+
+## Small caps
+
+```
+% pandoc --wrap=none -f latex -t commonmark-raw_html
+This has \textsc{small caps} in it.
+^D
+This has SMALL CAPS in it.
+```
+
+```
+% pandoc --wrap=none -f latex -t commonmark+raw_html
+This has \textsc{small caps} in it.
+^D
+This has <span class="smallcaps">small caps</span> in it.
+```
+```
+
+```
+% pandoc --wrap=none -f latex -t markdown_strict+raw_html
+This has \textsc{small caps} in it.
+^D
+This has <span class="smallcaps">small caps</span> in it.
+```
+
+## Strikeout
+
+```
+% pandoc --wrap=none -f html -t commonmark-raw_html-strikeout
+This has <s>strikeout</s> in it.
+^D
+This has strikeout in it.
+
+```
+% pandoc --wrap=none -f html -t commonmark+raw_html-strikeout
+This has <s>strikeout</s> in it.
+^D
+This has <s>strikeout</s> in it.
+```
+
+```
+% pandoc --wrap=none -f html -t commonmark-raw_html+strikeout
+This has <s>strikeout</s> in it.
+^D
+This has ~~strikeout~~ in it.
+```
+
+```
+% pandoc --wrap=none -f html -t commonmark+raw_html+strikeout
+This has <s>strikeout</s> in it.
+^D
+This has ~~strikeout~~ in it.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict-raw_html-strikeout
+This has <s>strikeout</s> in it.
+^D
+This has strikeout in it.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict+raw_html-strikeout
+This has <s>strikeout</s> in it.
+^D
+This has <s>strikeout</s> in it.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict-raw_html+strikeout
+This has <s>strikeout</s> in it.
+^D
+This has ~~strikeout~~ in it.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict+raw_html+strikeout
+This has <s>strikeout</s> in it.
+^D
+This has ~~strikeout~~ in it.
+```
+
+## Superscript
+
+```
+% pandoc --wrap=none -f html -t commonmark-raw_html
+This has <sup>superscript</sup> in it and <sup>2 3</sup> again. With emphasis: <sup><em>2</em> 3</sup>. With letters: <sup>foo</sup>. With a span: <sup><span class=foo>2</span></sup>.
+^D
+This has ^(superscript) in it and ² ³ again. With emphasis: ^(*2* 3). With letters: ^(foo). With a span: ².
+```
+
+```
+% pandoc --wrap=none -f html -t commonmark+raw_html
+This has <sup>superscript</sup> in it and <sup>2</sup> again.
+^D
+This has <sup>superscript</sup> in it and <sup>2</sup> again.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict-raw_html-superscript
+This has <sup>superscript</sup> in it and <sup>2</sup> again.
+^D
+This has ^(superscript) in it and ² again.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict+raw_html-superscript
+This has <sup>superscript</sup> in it and <sup>2</sup> again.
+^D
+This has <sup>superscript</sup> in it and <sup>2</sup> again.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict+raw_html+superscript
+This has <sup>superscript</sup> in it and <sup>2</sup> again.
+^D
+This has ^superscript^ in it and ^2^ again.
+```
+
+## Subscript
+
+```
+% pandoc --wrap=none -f html -t commonmark-raw_html
+This has <sub>subscript</sub> in it and <sub>2 3</sub> again. With emphasis: <sub><em>2</em> 3</sub>. With letters: <sub>foo</sub>. With a span: <sub><span class=foo>2</span></sub>.
+^D
+This has \_(subscript) in it and ₂ ₃ again. With emphasis: \_(*2* 3). With letters: \_(foo). With a span: ₂.
+```
+
+```
+% pandoc --wrap=none -f html -t commonmark+raw_html
+This has <sub>subscript</sub> in it and <sub>2</sub> again.
+^D
+This has <sub>subscript</sub> in it and <sub>2</sub> again.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict-raw_html-subscript
+This has <sub>subscript</sub> in it and <sub>2</sub> again.
+^D
+This has _(subscript) in it and ₂ again.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict+raw_html-subscript
+This has <sub>subscript</sub> in it and <sub>2</sub> again.
+^D
+This has <sub>subscript</sub> in it and <sub>2</sub> again.
+```
+
+```
+% pandoc --wrap=none -f html -t markdown_strict+raw_html+subscript
+This has <sub>subscript</sub> in it and <sub>2</sub> again.
+^D
+This has ~subscript~ in it and ~2~ again.
+```
diff --git a/test/command/4545.md b/test/command/4545.md
new file mode 100644
index 000000000..e5fc6e244
--- /dev/null
+++ b/test/command/4545.md
@@ -0,0 +1,20 @@
+```
+% pandoc -t asciidoc
+Test 1
+
+[my text]
+
+Test 2
+^D
+Test 1
+
+{empty}[my text]
+
+Test 2
+```
+```
+% pandoc -t asciidoc
+4\. foo
+^D
+{empty}4. foo
+```
diff --git a/test/command/4553.md b/test/command/4553.md
new file mode 100644
index 000000000..e5122d4d9
--- /dev/null
+++ b/test/command/4553.md
@@ -0,0 +1,15 @@
+```
+pandoc -f latex -t native
+foo \include{command/bar}
+^D
+[Para [Str "foo"]
+,Para [Emph [Str "hi",Space,Str "there"]]]
+```
+
+```
+pandoc -f latex -t native
+foo \input{command/bar}
+^D
+[Para [Str "foo",Space,Emph [Str "hi",Space,Str "there"]]]
+```
+
diff --git a/test/command/4624.md b/test/command/4624.md
new file mode 100644
index 000000000..f9aa45596
--- /dev/null
+++ b/test/command/4624.md
@@ -0,0 +1,30 @@
+```
+% pandoc -f latex -t native
+\begin{Verbatim}[key1=value1]
+code1
+
+\end{Verbatim}
+
+
+\begin{lstlisting}[key2=value2]
+code2
+
+\end{lstlisting}
+
+\begin{verbatim}
+code3
+\end{verbatim}
+
+\begin{verbatim}
+code4
+ \end{verbatim}
+
+\begin{verbatim}
+code5\end{verbatim}
+^D
+[CodeBlock ("",[],[("key1","value1")]) "code1\n"
+,CodeBlock ("",[],[("key2","value2")]) "code2\n "
+,CodeBlock ("",[],[]) "code3"
+,CodeBlock ("",[],[]) "code4"
+,CodeBlock ("",[],[]) "code5"]
+```
diff --git a/test/command/4653.md b/test/command/4653.md
new file mode 100644
index 000000000..24a706e89
--- /dev/null
+++ b/test/command/4653.md
@@ -0,0 +1,8 @@
+```
+% pandoc -t latex
+\let\tex\TeX
+\renewcommand{\TeX}{\tex\xspace}
+^D
+\let\tex\TeX
+\renewcommand{\TeX}{\tex\xspace}
+```
diff --git a/test/command/4667.md b/test/command/4667.md
new file mode 100644
index 000000000..1fff3708d
--- /dev/null
+++ b/test/command/4667.md
@@ -0,0 +1,20 @@
+```
+pandoc -t latex
+---
+header-includes:
+- \newcommand{\blandscape}{\begin{landscape}}
+- \newcommand{\elandscape}{\end{landscape}}
+...
+
+\blandscape
+
+testing
+
+\elandscape
+^D
+\begin{landscape}
+
+testing
+
+\end{landscape}
+```
diff --git a/test/command/4669.md b/test/command/4669.md
new file mode 100644
index 000000000..b9db45b17
--- /dev/null
+++ b/test/command/4669.md
@@ -0,0 +1,29 @@
+```
+% pandoc -f latex -t native
+{\tt <-}
+
+\begin{verbatim}
+ while (n > 0) {
+\end{verbatim}
+^D
+[Para [Span ("",[],[]) [Str "<-"]]
+,CodeBlock ("",[],[]) " while (n > 0) {"]
+```
+
+```
+% pandoc -f latex -t native
+\begin{itemize}
+\item<1> one
+\item<2-3,5> two
+\item<2| @alert> three
+\item<handout> four
+\item<beamer:2> five
+\end{itemize}
+^D
+[BulletList
+ [[Para [Str "one"]]
+ ,[Para [Str "two"]]
+ ,[Para [Str "three"]]
+ ,[Para [Str "four"]]
+ ,[Para [Str "five"]]]]
+```
diff --git a/test/command/4677.md b/test/command/4677.md
new file mode 100644
index 000000000..0343cf42a
--- /dev/null
+++ b/test/command/4677.md
@@ -0,0 +1,8 @@
+```
+% pandoc --to "markdown-bracketed_spans-fenced_divs-link_attributes-simple_tables-multiline_tables-grid_tables-pipe_tables-fenced_code_attributes-markdown_in_html_blocks-table_captions-smart"
+![Caption](img.png){#img:1}
+^D
+<figure>
+<img src="img.png" alt="Caption" id="img:1" /><figcaption>Caption</figcaption>
+</figure>
+```
diff --git a/test/command/4690.md b/test/command/4690.md
new file mode 100644
index 000000000..deccfba13
--- /dev/null
+++ b/test/command/4690.md
@@ -0,0 +1,28 @@
+```
+% pandoc -t beamer
+# title
+
+:::: {.columns}
+::: {.column width="8%"}
+content
+:::
+::: {.column width="84%"}
+content2
+:::
+::::
+^D
+\begin{frame}{title}
+\protect\hypertarget{title}{}
+
+\begin{columns}[T]
+\begin{column}{0.08\textwidth}
+content
+\end{column}
+
+\begin{column}{0.84\textwidth}
+content2
+\end{column}
+\end{columns}
+
+\end{frame}
+```
diff --git a/test/command/4722.md b/test/command/4722.md
new file mode 100644
index 000000000..6c8c14716
--- /dev/null
+++ b/test/command/4722.md
@@ -0,0 +1,34 @@
+```
+% pandoc -f tikiwiki -t native
+*Level 1
+*Level 1
+**Level 2
+***Level 3
+*Level 1
+^D
+[BulletList
+ [[Plain [Str "Level",Space,Str "1"]]
+ ,[Plain [Str "Level",Space,Str "1"]
+ ,BulletList
+ [[Plain [Str "Level",Space,Str "2"]
+ ,BulletList
+ [[Plain [Str "Level",Space,Str "3"]]]]]]
+ ,[Plain [Str "Level",Space,Str "1"]]]]
+```
+```
+% pandoc -f tikiwiki -t native
+#Level 1
+#Level 1
+##Level 2
+###Level 3
+#Level 1
+^D
+[OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Plain [Str "Level",Space,Str "1"]]
+ ,[Plain [Str "Level",Space,Str "1"]
+ ,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Plain [Str "Level",Space,Str "2"]
+ ,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Plain [Str "Level",Space,Str "3"]]]]]]
+ ,[Plain [Str "Level",Space,Str "1"]]]]
+```
diff --git a/test/command/4742.md b/test/command/4742.md
new file mode 100644
index 000000000..72751d727
--- /dev/null
+++ b/test/command/4742.md
@@ -0,0 +1,25 @@
+Check that the commonmark reader handles the `ascii_identifiers`
+extension properly.
+
+```
+% pandoc -f commonmark+gfm_auto_identifiers+ascii_identifiers -t native
+# non ascii ⚠️ räksmörgås
+^D
+[Header 1 ("non-ascii--raksmorgas",[],[]) [Str "non",Space,Str "ascii",Space,Str "\9888\65039",Space,Str "r\228ksm\246rg\229s"]]
+```
+
+```
+% pandoc -f commonmark+gfm_auto_identifiers-ascii_identifiers -t native
+# non ascii ⚠️ räksmörgås
+^D
+[Header 1 ("non-ascii-\65039-r\228ksm\246rg\229s",[],[]) [Str "non",Space,Str "ascii",Space,Str "\9888\65039",Space,Str "r\228ksm\246rg\229s"]]
+```
+
+`gfm` should have `ascii_identifiers` enabled by default.
+
+```
+% pandoc -f gfm -t native
+# non ascii ⚠️ räksmörgås
+^D
+[Header 1 ("non-ascii--raksmorgas",[],[]) [Str "non",Space,Str "ascii",Space,Str "\9888\65039",Space,Str "r\228ksm\246rg\229s"]]
+```
diff --git a/test/command/4743.md b/test/command/4743.md
new file mode 100644
index 000000000..49b4b6d59
--- /dev/null
+++ b/test/command/4743.md
@@ -0,0 +1,25 @@
+Test that emojis are wrapped in Span
+
+```
+% pandoc -f commonmark+emoji -t native
+My:thumbsup:emoji:heart:
+^D
+[Para [Str "My",Span ("",["emoji"],[("data-emoji","thumbsup")]) [Str "\128077"],Str "emoji",Span ("",["emoji"],[("data-emoji","heart")]) [Str "\10084\65039"]]]
+```
+
+```
+% pandoc -f markdown+emoji -t native
+My:thumbsup:emoji:heart:
+^D
+[Para [Str "My",Span ("",["emoji"],[("data-emoji","thumbsup")]) [Str "\128077"],Str "emoji",Span ("",["emoji"],[("data-emoji","heart")]) [Str "\10084\65039"]]]
+```
+
+```
+% pandoc -f commonmark+emoji -t html
+:zero: header
+=============
+My:thumbsup:emoji:heart:x :hearts: xyz
+^D
+<h1><span class="emoji" data-emoji="zero">0️⃣</span> header</h1>
+<p>My<span class="emoji" data-emoji="thumbsup">👍</span>emoji<span class="emoji" data-emoji="heart">❤️</span>x <span class="emoji" data-emoji="hearts">♥️</span> xyz</p>
+```
diff --git a/test/command/4748.md b/test/command/4748.md
new file mode 100644
index 000000000..1de0fa9ed
--- /dev/null
+++ b/test/command/4748.md
@@ -0,0 +1,16 @@
+```
+% pandoc -f org -t rst
+Before example block.
+#+begin_example
+This is in an example block.
+#+end_example
+After example block.
+^D
+Before example block.
+
+::
+
+ This is in an example block.
+
+After example block.
+```
diff --git a/test/command/4768.md b/test/command/4768.md
new file mode 100644
index 000000000..60d407d8b
--- /dev/null
+++ b/test/command/4768.md
@@ -0,0 +1,7 @@
+```
+% pandoc -f latex -t plain
+\def\foo#1!#2!#3{#1 or #2 and #3}
+\foo aa!bbb bbb!{ccc}
+^D
+aa or bbb bbb and ccc
+```
diff --git a/test/command/4781.md b/test/command/4781.md
new file mode 100644
index 000000000..8a75e09a0
--- /dev/null
+++ b/test/command/4781.md
@@ -0,0 +1,22 @@
+```
+% pandoc -t native
+Markdown parsed *here*
+
+\include{command/bar}
+
+*But not here*
+^D
+[Para [Str "Markdown",Space,Str "parsed",Space,Emph [Str "here"]]
+,RawBlock (Format "tex") "\\include{command/bar}"
+,Para [Emph [Str "But",Space,Str "not",Space,Str "here"]]]
+```
+
+```
+% pandoc -t native
+*here* \input{command/bar}
+
+*But not here*
+^D
+[Para [Emph [Str "here"],Space,RawInline (Format "tex") "\\input{command/bar}"]
+,Para [Emph [Str "But",Space,Str "not",Space,Str "here"]]]
+```
diff --git a/test/command/4794.md b/test/command/4794.md
new file mode 100644
index 000000000..8356d2157
--- /dev/null
+++ b/test/command/4794.md
@@ -0,0 +1,18 @@
+```
+% pandoc -f markdown -t mediawiki
+| Column1 | Column2 | Column3 |
+| ------- | ------- | ------- |
+| text | | text |
+^D
+{|
+! Column1
+! Column2
+! Column3
+|-
+| text
+|
+| text
+|}
+
+
+```
diff --git a/test/command/4811.md b/test/command/4811.md
new file mode 100644
index 000000000..9c8bea7ce
--- /dev/null
+++ b/test/command/4811.md
@@ -0,0 +1,48 @@
+No blank lines in inline interpreted roles:
+
+```
+% pandoc -f rst -t native
+`no
+
+blank`:myrole:
+^D
+[Para [Str "`no"]
+,Para [Str "blank`:myrole:"]]
+```
+
+Backslash escape behaves properly in interpreted roles:
+
+```
+% pandoc -f rst -t native
+`hi\ there`:sup:
+
+`hi\ there`:code:
+^D
+[Para [Superscript [Str "hithere"]]
+,Para [Code ("",["sourceCode"],[]) "hi\\ there"]]
+```
+
+Backtick followed by alphanumeric doesn't end the span:
+```
+% pandoc -f rst -t native
+`hi`there`:myrole:
+^D
+[Para [Code ("",["interpreted-text"],[("role","myrole")]) "hi`there"]]
+```
+
+Newline is okay, as long as not blank:
+```
+% pandoc -f rst -t native
+`hi
+there`:myrole:
+^D
+[Para [Code ("",["interpreted-text"],[("role","myrole")]) "hi\nthere"]]
+```
+
+Use span for title-reference:
+```
+% pandoc -f rst -t native
+`default`
+^D
+[Para [Span ("",["title-ref"],[]) [Str "default"]]]
+```
diff --git a/test/command/4817.md b/test/command/4817.md
new file mode 100644
index 000000000..7718e3b3a
--- /dev/null
+++ b/test/command/4817.md
@@ -0,0 +1,10 @@
+```
+% pandoc -t native -s
+---
+foo:
+- bar: bam
+...
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaList [MetaMap (fromList [("bar",MetaInlines [Str "bam"])])])]})
+[]
+```
diff --git a/test/command/4819.md b/test/command/4819.md
new file mode 100644
index 000000000..548583387
--- /dev/null
+++ b/test/command/4819.md
@@ -0,0 +1,50 @@
+```
+% pandoc -f markdown -t native -s
+---
+foo: 42
+...
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaInlines [Str "42"])]})
+[]
+```
+
+```
+% pandoc -f markdown -t native -s
+---
+foo: true
+...
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaBool True)]})
+[]
+```
+
+```
+% pandoc -f markdown -t native -s
+---
+foo: True
+...
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaBool True)]})
+[]
+```
+
+```
+% pandoc -f markdown -t native -s
+---
+foo: FALSE
+...
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaBool False)]})
+[]
+```
+
+```
+% pandoc -f markdown -t native -s
+---
+foo: no
+...
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaInlines [Str "no"])]})
+[]
+```
+
diff --git a/test/command/4832.md b/test/command/4832.md
new file mode 100644
index 000000000..9ba40804c
--- /dev/null
+++ b/test/command/4832.md
@@ -0,0 +1,21 @@
+```
+% pandoc -f latex -t native
+\url{http://example.com/foo%20bar.htm}
+^D
+[Para [Link ("",[],[]) [Str "http://example.com/foo%20bar.htm"] ("http://example.com/foo%20bar.htm","")]]
+```
+
+```
+% pandoc -f latex -t native
+\url{http://example.com/foo{bar}.htm}
+^D
+[Para [Link ("",[],[]) [Str "http://example.com/foo{bar}.htm"] ("http://example.com/foo{bar}.htm","")]]
+```
+
+```
+% pandoc -f latex -t native
+\href{http://example.com/foo%20bar}{Foobar}
+^D
+[Para [Link ("",[],[]) [Str "Foobar"] ("http://example.com/foo%20bar","")]]
+```
+
diff --git a/test/command/4833.md b/test/command/4833.md
new file mode 100644
index 000000000..ed6de606b
--- /dev/null
+++ b/test/command/4833.md
@@ -0,0 +1,20 @@
+```
+pandoc -f native -t rst
+[Div ("",["warning"],[])
+ [Div ("",["admonition-title"],[])
+ [Para [Str "Warning"]]
+ ,Para [Str "Hi"]]]
+^D
+.. warning::
+
+ Hi
+```
+```
+pandoc -f native -t rst
+[Div ("",["unknown"],[])
+ [Para [Str "Hi"]]]
+^D
+.. container:: unknown
+
+ Hi
+```
diff --git a/test/command/4842.md b/test/command/4842.md
new file mode 100644
index 000000000..a311739b7
--- /dev/null
+++ b/test/command/4842.md
@@ -0,0 +1,6 @@
+```
+pandoc -f latex -t native
+\l
+^D
+[Para [Str "\322"]]
+```
diff --git a/test/command/4845.md b/test/command/4845.md
new file mode 100644
index 000000000..093161ac7
--- /dev/null
+++ b/test/command/4845.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f html -t native
+x<a href="/foo"> leading trailing space </a>x
+^D
+[Plain [Str "x",Space,Link ("",[],[]) [Str "leading",Space,Str "trailing",Space,Str "space"] ("/foo",""),Space,Str "x"]]
+```
diff --git a/test/command/4848.md b/test/command/4848.md
new file mode 100644
index 000000000..2cd2bab34
--- /dev/null
+++ b/test/command/4848.md
@@ -0,0 +1,59 @@
+```
+% pandoc -f latex -t native
+\enquote*{hi}
+^D
+[Para [Quoted SingleQuote [Str "hi"]]]
+```
+
+```
+% pandoc -f latex -t native
+\foreignquote{italian}{hi}
+^D
+[Para [Quoted DoubleQuote [Span ("",[],[("lang","it")]) [Str "hi"]]]]
+```
+
+```
+% pandoc -f latex -t native
+\hyphenquote*{italian}{hi}
+^D
+[Para [Quoted SingleQuote [Span ("",[],[("lang","it")]) [Str "hi"]]]]
+```
+
+```
+% pandoc -f latex -t native
+Lorem ipsum
+\blockquote{dolor sit amet}
+consectetuer.
+^D
+[Para [Str "Lorem",Space,Str "ipsum"]
+,BlockQuote
+ [Para [Str "dolor",Space,Str "sit",Space,Str "amet"]]
+,Para [Str "consectetuer."]]
+```
+
+```
+% pandoc -f latex -t native
+Lorem ipsum
+\blockcquote[198]{Knu86}{dolor sit amet}
+consectetuer.
+^D
+[Para [Str "Lorem",Space,Str "ipsum"]
+,BlockQuote
+ [Para [Str "dolor",Space,Str "sit",Space,Str "amet"]
+ ,Para [Cite [Citation {citationId = "Knu86", citationPrefix = [], citationSuffix = [Str "198"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] []]]
+,Para [Str "consectetuer."]]
+```
+
+```
+% pandoc -f latex -t native
+Lorem ipsum
+\foreignblockquote{italian}{dolor sit amet}
+consectetuer.
+^D
+[Para [Str "Lorem",Space,Str "ipsum"]
+,BlockQuote
+ [Div ("",[],[("lang","it")])
+ [Para [Str "dolor",Space,Str "sit",Space,Str "amet"]]]
+,Para [Str "consectetuer."]]
+```
+
diff --git a/test/command/4860.md b/test/command/4860.md
new file mode 100644
index 000000000..9198f68d7
--- /dev/null
+++ b/test/command/4860.md
@@ -0,0 +1,9 @@
+```
+% pandoc -f rst -t native
+This is broken_.
+
+.. ***** REFERENCES FOLLOW *****
+.. _broken: http://google.com
+^D
+[Para [Str "This",Space,Str "is",Space,Link ("",[],[]) [Str "broken"] ("http://google.com",""),Str "."]]
+```
diff --git a/test/command/4877.md b/test/command/4877.md
new file mode 100644
index 000000000..070687345
--- /dev/null
+++ b/test/command/4877.md
@@ -0,0 +1,13 @@
+```
+% pandoc -f html -t native
+My <script type="math/tex">\mathcal{D}</script>
+^D
+[Plain [Str "My",Space,Math InlineMath "\\mathcal{D}"]]
+```
+
+```
+% pandoc -f html -t native
+<script type="math/tex; mode=display">\mathcal{D}</script>
+^D
+[Plain [Math DisplayMath "\\mathcal{D}"]]
+```
diff --git a/test/command/4885.md b/test/command/4885.md
new file mode 100644
index 000000000..8611097c2
--- /dev/null
+++ b/test/command/4885.md
@@ -0,0 +1,8 @@
+```
+% pandoc -f org -t markdown
+This won't show the command.
+src_maxima[:exports none :results raw]{tex('integrate(sin((e^x)/pi),x,0,inf));} $$\int_{0}^{\infty }{\sin \left({{e^{x}}\over{\pi}}\right)\;dx}$$
+^D
+This won\'t show the command.
+$$\int_{0}^{\infty }{\sin \left({{e^{x}}\over{\pi}}\right)\;dx}$$
+```
diff --git a/test/command/4908.md b/test/command/4908.md
new file mode 100644
index 000000000..2ff1a4603
--- /dev/null
+++ b/test/command/4908.md
@@ -0,0 +1,16 @@
+```
+% pandoc -f markdown_mmd+fancy_lists+example_lists -t native -t plain
+(@) Example one
+(@) Example two
+
+some text
+
+(@) Example three
+^D
+(1) Example one
+(2) Example two
+
+some text
+
+(3) Example three
+```
diff --git a/test/command/4913.md b/test/command/4913.md
new file mode 100644
index 000000000..6492b80ce
--- /dev/null
+++ b/test/command/4913.md
@@ -0,0 +1,34 @@
+```
+% pandoc -f markdown -t html
+[https://pandoc.org](https://pandoc.org)
+^D
+<p><a href="https://pandoc.org">https://pandoc.org</a></p>
+```
+
+```
+% pandoc -f markdown -t markdown
+[https://pandoc.org](https://pandoc.org)
+^D
+<https://pandoc.org>
+```
+
+```
+% pandoc -f markdown -t html
+<https://pandoc.org>
+^D
+<p><a href="https://pandoc.org" class="uri">https://pandoc.org</a></p>
+```
+
+```
+% pandoc -f markdown -t html
+<https://pandoc.org>{.foo}
+^D
+<p><a href="https://pandoc.org" class="foo">https://pandoc.org</a></p>
+```
+
+```
+% pandoc -f markdown -t html
+<me@example.com>
+^D
+<p><a href="mailto:me@example.com" class="email">me@example.com</a></p>
+```
diff --git a/test/command/4919.md b/test/command/4919.md
new file mode 100644
index 000000000..029d1beff
--- /dev/null
+++ b/test/command/4919.md
@@ -0,0 +1,14 @@
+```
+% pandoc -f rst -t native
+.. _`tgtmath`:
+
+ .. math::
+ :name:
+
+ V = \frac{K}{r^2}
+^D
+[Div ("tgtmath",[],[])
+ [BlockQuote
+ [Para [Math DisplayMath "V = \\frac{K}{r^2}"]]]]
+```
+
diff --git a/test/command/4928.md b/test/command/4928.md
new file mode 100644
index 000000000..d1e2b6db7
--- /dev/null
+++ b/test/command/4928.md
@@ -0,0 +1,48 @@
+```
+% pandoc -f latex -t native
+\cites(Multiprenote)(multipostnote)[23][42]{Knu86}[65]{Nie72}
+^D
+[Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "Multiprenote",Space,Str "23"], citationSuffix = [Str "42"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [Str "65",Str ",",Space,Str "multipostnote"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\cites(Multiprenote)(multipostnote)[23][42]{Knu86}[65]{Nie72}"]]]
+```
+
+```
+% pandoc -f latex -t native
+\cites(Multiprenote)()[23][42]{Knu86}[65]{Nie72}
+^D
+[Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "Multiprenote",Space,Str "23"], citationSuffix = [Str "42"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [Str "65"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\cites(Multiprenote)()[23][42]{Knu86}[65]{Nie72}"]]]
+```
+
+```
+% pandoc -f latex -t native
+\cites()(multipostnote)[23][42]{Knu86}[65]{Nie72}
+^D
+[Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "23"], citationSuffix = [Str "42"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [Str "65",Str ",",Space,Str "multipostnote"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\cites()(multipostnote)[23][42]{Knu86}[65]{Nie72}"]]]
+```
+
+```
+% pandoc -f latex -t native
+\cites()()[23][42]{Knu86}[65]{Nie72}
+^D
+[Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "23"], citationSuffix = [Str "42"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [Str "65"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\cites()()[23][42]{Knu86}[65]{Nie72}"]]]
+```
+
+```
+% pandoc -f latex -t native
+\cites(multipostnote)[23][42]{Knu86}[65]{Nie72}
+^D
+[Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "23"], citationSuffix = [Str "42"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [Str "65",Str ",",Space,Str "multipostnote"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\cites(multipostnote)[23][42]{Knu86}[65]{Nie72}"]]]
+```
+
+```
+% pandoc -f latex -t native
+\cites(Multiprenote)(multipostnote){Knu86}
+^D
+[Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "Multiprenote"], citationSuffix = [Str ",",Space,Str "multipostnote"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\cites(Multiprenote)(multipostnote){Knu86}"]]]
+```
+
+```
+% pandoc -f latex -t native
+\footcites(Multiprenote)(multipostnote)[23][42]{Knu86}[65]{Nie72}
+^D
+[Para [Note [Para [Cite [Citation {citationId = "Knu86", citationPrefix = [Str "Multiprenote",Space,Str "23"], citationSuffix = [Str "42"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [Str "65",Str ",",Space,Str "multipostnote"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [RawInline (Format "latex") "\\footcites(Multiprenote)(multipostnote)[23][42]{Knu86}[65]{Nie72}"],Str "."]]]]
+```
diff --git a/test/command/adjacent_latex_blocks.md b/test/command/adjacent_latex_blocks.md
index 3e72f1d4f..e7dc6d895 100644
--- a/test/command/adjacent_latex_blocks.md
+++ b/test/command/adjacent_latex_blocks.md
@@ -4,6 +4,6 @@
\listoftables
^D
-[RawBlock (Format "latex") "\\listoffigures"
-,RawBlock (Format "latex") "\\listoftables"]
+[RawBlock (Format "tex") "\\listoffigures"
+,RawBlock (Format "tex") "\\listoftables"]
```
diff --git a/test/command/ascii.md b/test/command/ascii.md
new file mode 100644
index 000000000..523baa46c
--- /dev/null
+++ b/test/command/ascii.md
@@ -0,0 +1,45 @@
+```
+pandoc -t html --ascii
+äéıå
+^D
+<p>&#228;&#233;&#305;&#229;</p>
+```
+
+```
+pandoc -t latex --ascii
+äéıå
+^D
+\"{a}\'{e}\i \r{a}
+```
+
+```
+pandoc -t man --ascii
+äéıå
+^D
+.PP
+\[u00E4]\[u00E9]\[u0131]\[u00E5]
+```
+
+```
+pandoc -t ms --ascii
+äéıå
+^D
+.LP
+\[u00E4]\[u00E9]\[u0131]\[u00E5]
+```
+
+```
+pandoc -t docbook --ascii
+äéıå
+^D
+<para>
+ &#228;&#233;&#305;&#229;
+</para>
+```
+
+```
+pandoc -t jats --ascii
+äéıå
+^D
+<p>&#228;&#233;&#305;&#229;</p>
+```
diff --git a/test/command/bar.tex b/test/command/bar.tex
new file mode 100644
index 000000000..e2113ab93
--- /dev/null
+++ b/test/command/bar.tex
@@ -0,0 +1 @@
+\emph{hi there}
diff --git a/test/command/emoji.md b/test/command/emoji.md
new file mode 100644
index 000000000..b5c573b3f
--- /dev/null
+++ b/test/command/emoji.md
@@ -0,0 +1,27 @@
+```
+% pandoc -t markdown+emoji -f markdown+emoji
+:smile:
+^D
+:smile:
+```
+
+```
+% pandoc -t markdown-emoji -f markdown+emoji
+:smile:
+^D
+😄
+```
+
+```
+% pandoc -t gfm -f markdown+emoji
+:smile:
+^D
+:smile:
+```
+
+```
+% pandoc -t gfm-emoji -f markdown+emoji
+:smile:
+^D
+😄
+```
diff --git a/test/command/empty-inline-code.txt b/test/command/empty-inline-code.txt
new file mode 100644
index 000000000..b57072a44
--- /dev/null
+++ b/test/command/empty-inline-code.txt
@@ -0,0 +1,6 @@
+```
+% pandoc -t native
+` `
+^D
+[Code ("",[],[]) ""]
+```
diff --git a/test/command/gfm.md b/test/command/gfm.md
index 670f3cd6e..7a7098989 100644
--- a/test/command/gfm.md
+++ b/test/command/gfm.md
@@ -38,7 +38,7 @@ gfm tests:
% pandoc -f gfm -t native
My:thumbsup:emoji:heart:
^D
-[Para [Str "My\128077emoji\10084\65039"]]
+[Para [Str "My",Span ("",["emoji"],[("data-emoji","thumbsup")]) [Str "\128077"],Str "emoji",Span ("",["emoji"],[("data-emoji","heart")]) [Str "\10084\65039"]]]
```
```
diff --git a/test/command/hspace.md b/test/command/hspace.md
index ec1669ca5..a8b97b8bc 100644
--- a/test/command/hspace.md
+++ b/test/command/hspace.md
@@ -8,7 +8,7 @@ Here they need to be inline:
\caption{lalune \hspace{2em} \vspace{1em} bloo}
\end{figure}
^D
-[RawBlock (Format "latex") "\\begin{figure}\n\\includegraphics{lalune.jpg}\n\\caption{lalune \\hspace{2em} \\vspace{1em} bloo}\n\\end{figure}"]
+[RawBlock (Format "tex") "\\begin{figure}\n\\includegraphics{lalune.jpg}\n\\caption{lalune \\hspace{2em} \\vspace{1em} bloo}\n\\end{figure}"]
```
Here block:
@@ -32,7 +32,7 @@ F & T &\\
F & F &\\
\end{tabular}
^D
-[RawBlock (Format "latex") "\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\wedge Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}\n\\hspace{1em}\n\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\vee Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}"]
+[RawBlock (Format "tex") "\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\wedge Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}\n\\hspace{1em}\n\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\vee Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}"]
```
```
@@ -51,6 +51,6 @@ hi
there
^D
[Para [Str "hi"]
-,RawBlock (Format "latex") "\\hspace{1em}"
+,RawBlock (Format "tex") "\\hspace{1em}"
,Para [Str "there"]]
```
diff --git a/test/command/macros.md b/test/command/macros.md
index 9de87e7a0..d091c2191 100644
--- a/test/command/macros.md
+++ b/test/command/macros.md
@@ -24,18 +24,18 @@ expanded at point of use:
% pandoc -f latex -t latex
\let\a\b
\newcommand{\b}{\emph{ouk}}
-\a
+\a a
^D
-\b
+a̱
```
```
% pandoc -f latex -t latex
\newcommand{\a}{\b}
\newcommand{\b}{\emph{ouk}}
-\a
+\a a
^D
-\emph{ouk}
+\emph{ouk}a
```
```
diff --git a/test/command/refs.md b/test/command/refs.md
index 66959e5c3..8b58ea6d7 100644
--- a/test/command/refs.md
+++ b/test/command/refs.md
@@ -42,12 +42,55 @@ Accuracy~\eqref{eq:Accuracy} is the proportion, measuring true results among all
Figure \ref{fig:Logo} illustrated the SVG logo
^D
-[Para [Image ("",[],[]) [Str "Logo",Span ("",[],[("label","fig:Logo")]) []] ("command/SVG_logo.svg","fig:")]
-,Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:Logo")]) [Str "[fig:Logo]"] ("#fig:Logo",""),Space,Str "illustrated",Space,Str "the",Space,Str "SVG",Space,Str "logo"]]
+[Para [Image ("fig:Logo",[],[]) [Str "Logo",Span ("",[],[("label","fig:Logo")]) []] ("command/SVG_logo.svg","fig:")]
+,Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:Logo")]) [Str "1"] ("#fig:Logo",""),Space,Str "illustrated",Space,Str "the",Space,Str "SVG",Space,Str "logo"]]
```
```
% pandoc -f latex -t native
+\chapter{One}
+\begin{figure}
+ \includegraphics{command/SVG_logo.svg}
+ \caption{Logo}
+ \label{fig:Logo}
+\end{figure}
+
+\begin{figure}
+ \includegraphics{command/SVG_logo2.svg}
+ \caption{Logo2}
+ \label{fig:Logo2}
+\end{figure}
+
+\chapter{Two}
+
+\section{Subone}
+
+\begin{figure}
+ \includegraphics{command/SVG_logo3.svg}
+ \caption{Logo3}
+ \label{fig:Logo3}
+\end{figure}
+
+Figure \ref{fig:Logo} illustrated the SVG logo
+
+Figure \ref{fig:Logo2} illustrated the SVG logo
+
+Figure \ref{fig:Logo3} illustrated the SVG logo
+^D
+[Header 1 ("one",[],[]) [Str "One"]
+,Para [Image ("fig:Logo",[],[]) [Str "Logo",Span ("",[],[("label","fig:Logo")]) []] ("command/SVG_logo.svg","fig:")]
+,Para [Image ("fig:Logo2",[],[]) [Str "Logo2",Span ("",[],[("label","fig:Logo2")]) []] ("command/SVG_logo2.svg","fig:")]
+,Header 1 ("two",[],[]) [Str "Two"]
+,Header 2 ("subone",[],[]) [Str "Subone"]
+,Para [Image ("fig:Logo3",[],[]) [Str "Logo3",Span ("",[],[("label","fig:Logo3")]) []] ("command/SVG_logo3.svg","fig:")]
+,Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:Logo")]) [Str "1.1"] ("#fig:Logo",""),Space,Str "illustrated",Space,Str "the",Space,Str "SVG",Space,Str "logo"]
+,Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:Logo2")]) [Str "1.2"] ("#fig:Logo2",""),Space,Str "illustrated",Space,Str "the",Space,Str "SVG",Space,Str "logo"]
+,Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:Logo3")]) [Str "2.1"] ("#fig:Logo3",""),Space,Str "illustrated",Space,Str "the",Space,Str "SVG",Space,Str "logo"]]
+```
+
+
+```
+% pandoc -f latex -t native
\label{section} Section \ref{section}
^D
[Para [Span ("section",[],[("label","section")]) [Str "[section]"],Space,Str "Section",Space,Link ("",[],[("reference-type","ref"),("reference","section")]) [Str "[section]"] ("#section","")]]
diff --git a/test/command/write18.md b/test/command/write18.md
index 344dfc8cf..5000c298b 100644
--- a/test/command/write18.md
+++ b/test/command/write18.md
@@ -3,7 +3,7 @@ Handle \write18{..} as raw tex:
% pandoc -t native
\write18{git --version}
^D
-[RawBlock (Format "latex") "\\write18{git --version}"]
+[RawBlock (Format "tex") "\\write18{git --version}"]
```
```
diff --git a/test/command/yaml-metadata-blocks.md b/test/command/yaml-metadata-blocks.md
new file mode 100644
index 000000000..5b73cff72
--- /dev/null
+++ b/test/command/yaml-metadata-blocks.md
@@ -0,0 +1,63 @@
+```
+% pandoc -s -t native
+---
+foobar_: this should be ignored
+foo:
+ bar_: as should this
+---
+^D
+Pandoc (Meta {unMeta = fromList [("foo",MetaMap (fromList []))]})
+[]
+```
+```
+% pandoc -s -t native
+---
+# For precedence, see multiple-metadata-blocks.md and vars-and-metadata.md
+# For Bools, see also 4819.md
+# For Multiline strings, see yaml-with-chomp.md
+int: 7
+float: 1.5
+scientific: 3.7e-5
+bool: true
+more: False
+nothing: null
+emtpy: []
+nested:
+ int: 8
+ float: 2.5
+ bool: true
+ more: False
+ nothing: null
+ emtpy: []
+ scientific: 3.7e-5
+---
+^D
+Pandoc (Meta {unMeta = fromList [("bool",MetaBool True),("emtpy",MetaList []),("float",MetaInlines [Str "1.5"]),("int",MetaInlines [Str "7"]),("more",MetaBool False),("nested",MetaMap (fromList [("bool",MetaBool True),("emtpy",MetaList []),("float",MetaInlines [Str "2.5"]),("int",MetaInlines [Str "8"]),("more",MetaBool False),("nothing",MetaInlines [Str "null"]),("scientific",MetaInlines [Str "3.7e-5"])])),("nothing",MetaInlines [Str "null"]),("scientific",MetaInlines [Str "3.7e-5"])]})
+[]
+```
+```
+% pandoc -s -t native
+---
+array:
+ - foo: bar
+ - bool: True
+---
+^D
+Pandoc (Meta {unMeta = fromList [("array",MetaList [MetaMap (fromList [("foo",MetaInlines [Str "bar"])]),MetaMap (fromList [("bool",MetaBool True)])])]})
+[]
+```
+```
+% pandoc -s -t native --metadata-file command/yaml-metadata.yaml
+---
+title: document
+---
+^D
+Pandoc (Meta {unMeta = fromList [("other",MetaInlines [Emph [Str "markdown"],Space,Str "value"]),("title",MetaInlines [Str "document"])]})
+[]
+```
+```
+% pandoc -s -t native --metadata-file command/yaml-metadata.yaml -M title=cmdline
+^D
+Pandoc (Meta {unMeta = fromList [("other",MetaInlines [Emph [Str "markdown"],Space,Str "value"]),("title",MetaString "cmdline")]})
+[]
+```
diff --git a/test/command/yaml-metadata.yaml b/test/command/yaml-metadata.yaml
new file mode 100644
index 000000000..9cd0043d3
--- /dev/null
+++ b/test/command/yaml-metadata.yaml
@@ -0,0 +1,4 @@
+---
+title: file
+other: _markdown_ value
+---
diff --git a/test/docbook-xref.native b/test/docbook-xref.native
index 23bc497b2..54a63768e 100644
--- a/test/docbook-xref.native
+++ b/test/docbook-xref.native
@@ -1,4 +1,4 @@
-Pandoc (Meta {unMeta = fromList []})
+Pandoc (Meta {unMeta = fromList [("title",MetaInlines [Str "An",Space,Str "Example",Space,Str "Book"])]})
[Header 1 ("ch01",[],[]) [Str "XRef",Space,Str "Samples"]
,Para [Str "This",Space,Str "paragraph",Space,Str "demonstrates",Space,Str "several",Space,Str "features",Space,Str "of",SoftBreak,Str "XRef."]
,BulletList
diff --git a/test/fb2/meta.fb2 b/test/fb2/meta.fb2
index 04bd5f3c5..1db48c068 100644
--- a/test/fb2/meta.fb2
+++ b/test/fb2/meta.fb2
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
-<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre><book-title>Book title</book-title><annotation><p>This is the abstract.</p>It consists of two paragraphs.</annotation></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p>Book title</p></title></body></FictionBook>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre><book-title>Book title</book-title><annotation><p>This is the abstract.</p><p>It consists of two paragraphs.</p></annotation></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p>Book title</p></title></body></FictionBook>
diff --git a/test/lhs-test.html b/test/lhs-test.html
index c9777ea7b..5fce225df 100644
--- a/test/lhs-test.html
+++ b/test/lhs-test.html
@@ -14,7 +14,7 @@
<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
-a.sourceLine:empty { height: 1.2em; position: absolute; }
+a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
@@ -27,13 +27,11 @@ code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
- { position: relative; }
-pre.numberSource a.sourceLine:empty
- { position: absolute; }
+ { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(data-line-number);
- position: absolute; left: -5em; text-align: right; vertical-align: baseline;
- border: none; pointer-events: all;
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
+ border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
diff --git a/test/lhs-test.html+lhs b/test/lhs-test.html+lhs
index 4a121e0d1..78bc1d426 100644
--- a/test/lhs-test.html+lhs
+++ b/test/lhs-test.html+lhs
@@ -14,7 +14,7 @@
<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
-a.sourceLine:empty { height: 1.2em; position: absolute; }
+a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
@@ -27,13 +27,11 @@ code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
- { position: relative; }
-pre.numberSource a.sourceLine:empty
- { position: absolute; }
+ { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(data-line-number);
- position: absolute; left: -5em; text-align: right; vertical-align: baseline;
- border: none; pointer-events: all;
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
+ border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
diff --git a/test/lua/test-pandoc-utils.lua b/test/lua/test-pandoc-utils.lua
index 21f937edb..4421603ec 100644
--- a/test/lua/test-pandoc-utils.lua
+++ b/test/lua/test-pandoc-utils.lua
@@ -1,5 +1,19 @@
utils = require 'pandoc.utils'
+-- Squash blocks to inlines
+------------------------------------------------------------------------
+function test_blocks_to_inlines ()
+ local blocks = {
+ pandoc.Para{ pandoc.Str 'Paragraph1' },
+ pandoc.Para{ pandoc.Emph 'Paragraph2' }
+ }
+ local inlines = utils.blocks_to_inlines(blocks, {pandoc.LineBreak()})
+ return #inlines == 3
+ and inlines[1].text == "Paragraph1"
+ and inlines[2].t == 'LineBreak'
+ and inlines[3].content[1].text == "Paragraph2"
+end
+
-- hierarchicalize
------------------------------------------------------------------------
function test_hierarchicalize ()
@@ -110,6 +124,7 @@ end
function Para (el)
return {
+ pandoc.Plain{pandoc.Str("blocks_to_inlines: " .. run(test_blocks_to_inlines))},
pandoc.Plain{pandoc.Str("hierarchicalize: " .. run(test_hierarchicalize))},
pandoc.Plain{pandoc.Str("normalize_date: " .. run(test_normalize_date))},
pandoc.Plain{pandoc.Str("pipe: " .. run(test_pipe))},
diff --git a/test/markdown-reader-more.native b/test/markdown-reader-more.native
index 17e91bb89..9c128ab94 100644
--- a/test/markdown-reader-more.native
+++ b/test/markdown-reader-more.native
@@ -3,10 +3,11 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Author",S
,Header 2 ("blank-line-before-url-in-link-reference",[],[]) [Str "Blank",Space,Str "line",Space,Str "before",Space,Str "URL",Space,Str "in",Space,Str "link",Space,Str "reference"]
,Para [Link ("",[],[]) [Str "foo"] ("/url",""),Space,Str "and",Space,Link ("",[],[]) [Str "bar"] ("/url","title")]
,Header 2 ("raw-context-environments",[],[]) [Str "Raw",Space,Str "ConTeXt",Space,Str "environments"]
-,RawBlock (Format "context") "\\placeformula \\startformula\n L_{1} = L_{2}\n \\stopformula"
-,RawBlock (Format "context") "\\start[a2]\n\\start[a2]\n\\stop[a2]\n\\stop[a2]"
+,RawBlock (Format "tex") "\\placeformula \\startformula"
+,Para [Str "L_{1}",Space,Str "=",Space,Str "L_{2}",SoftBreak,RawInline (Format "tex") "\\stopformula"]
+,RawBlock (Format "tex") "\\start[a2]\n\\start[a2]\n\\stop[a2]\n\\stop[a2]"
,Header 2 ("raw-latex-environments",[],[]) [Str "Raw",Space,Str "LaTeX",Space,Str "environments"]
-,RawBlock (Format "latex") "\\begin{center}\n\\begin{tikzpicture}[baseline={([yshift=+-.5ex]current bounding box.center)}, level distance=24pt]\n\\Tree [.{S} [.NP John\\index{i} ] [.VP [.V likes ] [.NP himself\\index{i,*j} ]]]\n\\end{tikzpicture}\n\\end{center}"
+,RawBlock (Format "tex") "\\begin{center}\n\\begin{tikzpicture}[baseline={([yshift=+-.5ex]current bounding box.center)}, level distance=24pt]\n\\Tree [.{S} [.NP John\\index{i} ] [.VP [.V likes ] [.NP himself\\index{i,*j} ]]]\n\\end{tikzpicture}\n\\end{center}"
,Header 2 ("urls-with-spaces-and-punctuation",[],[]) [Str "URLs",Space,Str "with",Space,Str "spaces",Space,Str "and",Space,Str "punctuation"]
,Para [Link ("",[],[]) [Str "foo"] ("/bar%20and%20baz",""),SoftBreak,Link ("",[],[]) [Str "foo"] ("/bar%20and%20baz",""),SoftBreak,Link ("",[],[]) [Str "foo"] ("/bar%20and%20baz",""),SoftBreak,Link ("",[],[]) [Str "foo"] ("bar%20baz","title")]
,Para [Link ("",[],[]) [Str "baz"] ("/foo%20foo",""),Space,Link ("",[],[]) [Str "bam"] ("/foo%20fee",""),Space,Link ("",[],[]) [Str "bork"] ("/foo/zee%20zob","title")]
@@ -44,9 +45,9 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Author",S
,Para [Str "`hi"]
,Para [Str "there`"]
,Header 2 ("multilingual-urls",[],[]) [Str "Multilingual",Space,Str "URLs"]
-,Para [Link ("",[],[]) [Str "http://\27979.com?\27979=\27979"] ("http://\27979.com?\27979=\27979","")]
+,Para [Link ("",["uri"],[]) [Str "http://\27979.com?\27979=\27979"] ("http://\27979.com?\27979=\27979","")]
,Para [Link ("",[],[]) [Str "foo"] ("/bar/\27979?x=\27979","title")]
-,Para [Link ("",[],[]) [Str "\27979@foo.\27979.baz"] ("mailto:\27979@foo.\27979.baz","")]
+,Para [Link ("",["email"],[]) [Str "\27979@foo.\27979.baz"] ("mailto:\27979@foo.\27979.baz","")]
,Header 2 ("numbered-examples",[],[]) [Str "Numbered",Space,Str "examples"]
,OrderedList (1,Example,TwoParens)
[[Plain [Str "First",Space,Str "example."]]
@@ -55,7 +56,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Author",S
,OrderedList (3,Example,TwoParens)
[[Plain [Str "Third",Space,Str "example."]]]
,Header 2 ("macros",[],[]) [Str "Macros"]
-,RawBlock (Format "latex") "\\newcommand{\\tuple}[1]{\\langle #1 \\rangle}"
+,RawBlock (Format "tex") "\\newcommand{\\tuple}[1]{\\langle #1 \\rangle}"
,Para [Math InlineMath "\\langle x,y \\rangle"]
,Header 2 ("case-insensitive-references",[],[]) [Str "Case-insensitive",Space,Str "references"]
,Para [Link ("",[],[]) [Str "Fum"] ("/fum","")]
@@ -175,8 +176,8 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Author",S
,[]]]
,Header 2 ("entities-in-links-and-titles",[],[]) [Str "Entities",Space,Str "in",Space,Str "links",Space,Str "and",Space,Str "titles"]
,Para [Link ("",[],[]) [Str "link"] ("/\252rl","\246\246!")]
-,Para [Link ("",[],[]) [Str "http://g\246\246gle.com"] ("http://g\246\246gle.com","")]
-,Para [Link ("",[],[]) [Str "me@ex\228mple.com"] ("mailto:me@ex\228mple.com","")]
+,Para [Link ("",["uri"],[]) [Str "http://g\246\246gle.com"] ("http://g\246\246gle.com","")]
+,Para [Link ("",["email"],[]) [Str "me@ex\228mple.com"] ("mailto:me@ex\228mple.com","")]
,Para [Link ("",[],[]) [Str "foobar"] ("/\252rl","\246\246!")]
,Header 2 ("parentheses-in-urls",[],[]) [Str "Parentheses",Space,Str "in",Space,Str "URLs"]
,Para [Link ("",[],[]) [Str "link"] ("/hi(there)","")]
diff --git a/test/pptx/lists.native b/test/pptx/lists.native
index e08580cd5..61249c7fe 100644
--- a/test/pptx/lists.native
+++ b/test/pptx/lists.native
@@ -1,7 +1,7 @@
[Header 1 ("lists",[],[]) [Str "Lists"]
,BulletList
[[Para [Str "Bulleted",Space,Str "bulleted",Space,Str "lists."]]
- ,[Para [Str "And",Space,Str "go",Space,Str "to",Space,Str "aribtrary",Space,Str "depth."]
+ ,[Para [Str "And",Space,Str "go",Space,Str "to",Space,Str "arbitrary",Space,Str "depth."]
,BulletList
[[Para [Str "Like",Space,Str "this"]
,BulletList
diff --git a/test/pptx/lists.pptx b/test/pptx/lists.pptx
index acb0841ce..c28e840f1 100644
--- a/test/pptx/lists.pptx
+++ b/test/pptx/lists.pptx
Binary files differ
diff --git a/test/pptx/lists_templated.pptx b/test/pptx/lists_templated.pptx
index a25feaff1..74505454e 100644
--- a/test/pptx/lists_templated.pptx
+++ b/test/pptx/lists_templated.pptx
Binary files differ
diff --git a/test/rst-reader.native b/test/rst-reader.native
index b0e51bd3f..89dde7396 100644
--- a/test/rst-reader.native
+++ b/test/rst-reader.native
@@ -326,7 +326,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Spa
,Para [Math DisplayMath "\\alpha = beta",Math DisplayMath "E = mc^2"]
,Para [Str "Some",Space,Superscript [Str "of"],Space,Str "these",Space,Superscript [Str "words"],Space,Str "are",Space,Str "in",Space,Superscript [Str "superscript"],Str "."]
,Para [Str "Reset",Space,Str "default-role",Space,Str "to",Space,Str "the",Space,Str "default",Space,Str "default."]
-,Para [Str "And",Space,Str "now",Space,Str "some-invalid-string-3231231",Space,Str "is",Space,Str "nonsense."]
+,Para [Str "And",Space,Str "now",Space,Span ("",["title-ref"],[]) [Str "some-invalid-string-3231231"],Space,Str "is",Space,Str "nonsense."]
,Para [Str "And",Space,Str "now",Space,Str "with",Space,RawInline (Format "html") "<b>inline</b> <span id=\"test\">HTML</span>",Str "."]
,Para [Str "And",Space,Str "some",Space,Str "inline",Space,Str "haskell",Space,Code ("",["haskell","sourceCode"],[]) "fmap id [1,2..10]",Str "."]
,Para [Str "Indirect",Space,Str "python",Space,Str "role",Space,Code ("",["py","python","indirect","sourceCode"],[]) "[x*x for x in [1,2,3,4,5]]",Str "."]
diff --git a/test/tables-rstsubset.native b/test/tables-rstsubset.native
index 5ea520d7c..a4f801b1c 100644
--- a/test/tables-rstsubset.native
+++ b/test/tables-rstsubset.native
@@ -1,5 +1,5 @@
[Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1,8.75e-2,0.1125,0.125]
+,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
[[Plain [Str "Right"]]
,[Plain [Str "Left"]]
,[Plain [Str "Center"]]
@@ -17,7 +17,7 @@
,[Plain [Str "1"]]
,[Plain [Str "1"]]]]
,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1,8.75e-2,0.1125,0.125]
+,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
[[Plain [Str "Right"]]
,[Plain [Str "Left"]]
,[Plain [Str "Center"]]
@@ -35,7 +35,7 @@
,[Plain [Str "1"]]
,[Plain [Str "1"]]]]
,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1,8.75e-2,0.1125,0.125]
+,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
[[Plain [Str "Right"]]
,[Plain [Str "Left"]]
,[Plain [Str "Center"]]
@@ -81,7 +81,7 @@
,[Plain [Str "5.0"]]
,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]]
,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [7.5e-2,7.5e-2,7.5e-2,7.5e-2]
+,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
[[]
,[]
,[]
diff --git a/test/tables.opendocument b/test/tables.opendocument
index c331ecc43..5c68476b8 100644
--- a/test/tables.opendocument
+++ b/test/tables.opendocument
@@ -6,64 +6,65 @@
<table:table-column table:style-name="Table1.D" />
<table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P1">Right</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Left</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P2">Center</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Default</text:p>
</table:table-cell>
</table:table-row>
</table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P3">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P4">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P3">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P4">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P3">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P4">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
</table:table-row>
</table:table>
-<text:p text:style-name="Table">Demonstration of simple table syntax.</text:p>
+<text:p text:style-name="Table">Table <text:sequence text:ref-name="refTable0" text:name="Table" text:formula="ooow:Table+1" style:num-format="1">1</text:sequence>: Demonstration
+of simple table syntax.</text:p>
<text:p text:style-name="First_20_paragraph">Simple table without
caption:</text:p>
<table:table table:name="Table2" table:style-name="Table2">
@@ -73,59 +74,59 @@ caption:</text:p>
<table:table-column table:style-name="Table2.D" />
<table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P5">Right</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Left</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P6">Center</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Default</text:p>
</table:table-cell>
</table:table-row>
</table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P7">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P8">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P7">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P8">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P7">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P8">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table2.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
</table:table-row>
@@ -139,64 +140,65 @@ spaces:</text:p>
<table:table-column table:style-name="Table3.D" />
<table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P9">Right</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Left</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P10">Center</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Default</text:p>
</table:table-cell>
</table:table-row>
</table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P11">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P12">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P11">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P12">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P11">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P12">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table3.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
</table:table-row>
</table:table>
-<text:p text:style-name="Table">Demonstration of simple table syntax.</text:p>
+<text:p text:style-name="Table">Table <text:sequence text:ref-name="refTable1" text:name="Table" text:formula="ooow:Table+1" style:num-format="1">2</text:sequence>: Demonstration
+of simple table syntax.</text:p>
<text:p text:style-name="First_20_paragraph">Multiline table with
caption:</text:p>
<table:table table:name="Table4" table:style-name="Table4">
@@ -206,53 +208,53 @@ caption:</text:p>
<table:table-column table:style-name="Table4.D" />
<table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P13">Centered Header</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Left Aligned</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P14">Right Aligned</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Default aligned</text:p>
</table:table-cell>
</table:table-row>
</table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P15">First</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">row</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P16">12.0</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">Example of a row that spans
multiple lines.</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P15">Second</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">row</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P16">5.0</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table4.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">Here’s another one. Note the
blank line between rows.</text:p>
</table:table-cell>
</table:table-row>
</table:table>
-<text:p text:style-name="Table">Here’s the caption. It may span multiple
-lines.</text:p>
+<text:p text:style-name="Table">Table <text:sequence text:ref-name="refTable2" text:name="Table" text:formula="ooow:Table+1" style:num-format="1">3</text:sequence>: Here’s
+the caption. It may span multiple lines.</text:p>
<text:p text:style-name="First_20_paragraph">Multiline table without
caption:</text:p>
<table:table table:name="Table5" table:style-name="Table5">
@@ -262,46 +264,46 @@ caption:</text:p>
<table:table-column table:style-name="Table5.D" />
<table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P17">Centered Header</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Left Aligned</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="P18">Right Aligned</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Default aligned</text:p>
</table:table-cell>
</table:table-row>
</table:table-header-rows>
<table:table-row>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P19">First</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">row</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P20">12.0</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">Example of a row that spans
multiple lines.</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P19">Second</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">row</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P20">5.0</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table5.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">Here’s another one. Note the
blank line between rows.</text:p>
</table:table-cell>
@@ -315,44 +317,44 @@ headers:</text:p>
<table:table-column table:style-name="Table6.C" />
<table:table-column table:style-name="Table6.D" />
<table:table-row>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P24">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P25">12</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P26">12</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P24">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P25">123</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P26">123</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P24">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P25">1</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table6.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P26">1</text:p>
</table:table-cell>
</table:table-row>
@@ -365,31 +367,31 @@ headers:</text:p>
<table:table-column table:style-name="Table7.C" />
<table:table-column table:style-name="Table7.D" />
<table:table-row>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P29">First</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">row</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P30">12.0</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">Example of a row that spans
multiple lines.</text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P29">Second</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">row</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="P30">5.0</text:p>
</table:table-cell>
- <table:table-cell table:style-name="Table7.A1" office:value-type="string">
+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
<text:p text:style-name="Table_20_Contents">Here’s another one. Note the
blank line between rows.</text:p>
</table:table-cell>
diff --git a/test/tables.rst b/test/tables.rst
index 4559883cd..660df61d4 100644
--- a/test/tables.rst
+++ b/test/tables.rst
@@ -2,41 +2,35 @@ Simple table with caption:
.. table:: Demonstration of simple table syntax.
- +-------+------+--------+---------+
- | Right | Left | Center | Default |
- +=======+======+========+=========+
- | 12 | 12 | 12 | 12 |
- +-------+------+--------+---------+
- | 123 | 123 | 123 | 123 |
- +-------+------+--------+---------+
- | 1 | 1 | 1 | 1 |
- +-------+------+--------+---------+
+ ===== ==== ====== =======
+ Right Left Center Default
+ ===== ==== ====== =======
+ 12 12 12 12
+ 123 123 123 123
+ 1 1 1 1
+ ===== ==== ====== =======
Simple table without caption:
-+-------+------+--------+---------+
-| Right | Left | Center | Default |
-+=======+======+========+=========+
-| 12 | 12 | 12 | 12 |
-+-------+------+--------+---------+
-| 123 | 123 | 123 | 123 |
-+-------+------+--------+---------+
-| 1 | 1 | 1 | 1 |
-+-------+------+--------+---------+
+===== ==== ====== =======
+Right Left Center Default
+===== ==== ====== =======
+12 12 12 12
+123 123 123 123
+1 1 1 1
+===== ==== ====== =======
Simple table indented two spaces:
.. table:: Demonstration of simple table syntax.
- +-------+------+--------+---------+
- | Right | Left | Center | Default |
- +=======+======+========+=========+
- | 12 | 12 | 12 | 12 |
- +-------+------+--------+---------+
- | 123 | 123 | 123 | 123 |
- +-------+------+--------+---------+
- | 1 | 1 | 1 | 1 |
- +-------+------+--------+---------+
+ ===== ==== ====== =======
+ Right Left Center Default
+ ===== ==== ====== =======
+ 12 12 12 12
+ 123 123 123 123
+ 1 1 1 1
+ ===== ==== ====== =======
Multiline table with caption:
@@ -70,13 +64,11 @@ Multiline table without caption:
Table without column headers:
-+-----+-----+-----+-----+
-| 12 | 12 | 12 | 12 |
-+-----+-----+-----+-----+
-| 123 | 123 | 123 | 123 |
-+-----+-----+-----+-----+
-| 1 | 1 | 1 | 1 |
-+-----+-----+-----+-----+
+=== === === ===
+12 12 12 12
+123 123 123 123
+1 1 1 1
+=== === === ===
Multiline table without column headers:
diff --git a/test/testsuite.native b/test/testsuite.native
index 0587bddb8..73fcc0633 100644
--- a/test/testsuite.native
+++ b/test/testsuite.native
@@ -324,7 +324,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Spa
,[Plain [Str "Shoes",Space,Str "($20)",Space,Str "and",Space,Str "socks",Space,Str "($5)."]]
,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$."]]]
,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
-,RawBlock (Format "latex") "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}"
+,RawBlock (Format "tex") "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}"
,HorizontalRule
,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"]
,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
@@ -384,14 +384,14 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Spa
,Para [Str "Here\8217s",Space,Str "an",Space,Link ("",[],[]) [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."]
,Para [Str "Here\8217s",Space,Str "an",Space,Link ("",[],[]) [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]
,Header 2 ("autolinks",[],[]) [Str "Autolinks"]
-,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link ("",[],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
+,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link ("",["uri"],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
,BulletList
[[Plain [Str "In",Space,Str "a",Space,Str "list?"]]
- ,[Plain [Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
+ ,[Plain [Link ("",["uri"],[]) [Str "http://example.com/"] ("http://example.com/","")]]
,[Plain [Str "It",Space,Str "should."]]]
-,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link ("",[],[]) [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link ("",["email"],[]) [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
,BlockQuote
- [Para [Str "Blockquoted:",Space,Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
+ [Para [Str "Blockquoted:",Space,Link ("",["uri"],[]) [Str "http://example.com/"] ("http://example.com/","")]]
,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",Space,Code ("",[],[]) "<http://example.com/>"]
,CodeBlock ("",[],[]) "or here: <http://example.com/>"
,HorizontalRule
diff --git a/test/textile-reader.native b/test/textile-reader.native
index 10bf2c857..16b5a87e8 100644
--- a/test/textile-reader.native
+++ b/test/textile-reader.native
@@ -2,7 +2,7 @@ Pandoc (Meta {unMeta = fromList []})
[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Space,Str "Textile",Space,Str "Reader.",Space,Str "Part",Space,Str "of",Space,Str "it",Space,Str "comes",LineBreak,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
,HorizontalRule
,Header 1 ("headers",[],[]) [Str "Headers"]
-,Header 2 ("level-2-with-an-embeded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link ("",[],[]) [Str "embeded",Space,Str "link"] ("http://www.example.com","")]
+,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link ("",[],[]) [Str "embedded",Space,Str "link"] ("http://www.example.com","")]
,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Strong [Str "emphasis"]]
,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"]
,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"]
diff --git a/test/textile-reader.textile b/test/textile-reader.textile
index cca0b83f7..d02310b3d 100644
--- a/test/textile-reader.textile
+++ b/test/textile-reader.textile
@@ -5,7 +5,7 @@ from John Gruber's markdown test suite.
h1. Headers
-h2. Level 2 with an "embeded link":http://www.example.com
+h2. Level 2 with an "embedded link":http://www.example.com
h3. Level 3 with *emphasis*
diff --git a/test/tikiwiki-reader.native b/test/tikiwiki-reader.native
index 2ab053217..79dc4b708 100644
--- a/test/tikiwiki-reader.native
+++ b/test/tikiwiki-reader.native
@@ -43,52 +43,52 @@ Pandoc (Meta {unMeta = fromList []})
,Para [Str "info@example.org"]
,Header 1 ("lists",[],[]) [Str "lists"]
,BulletList
- [[Plain [Str "Start",Space,Str "each",Space,Str "line",Space]]
- ,[Plain [Str "with",Space,Str "an",Space,Str "asterisk",Space,Str "(*).",Space]
+ [[Plain [Str "Start",Space,Str "each",Space,Str "line"]]
+ ,[Plain [Str "with",Space,Str "an",Space,Str "asterisk",Space,Str "(*)."]
,BulletList
- [[Plain [Str "More",Space,Str "asterisks",Space,Str "gives",Space,Str "deeper",Space]
+ [[Plain [Str "More",Space,Str "asterisks",Space,Str "gives",Space,Str "deeper"]
,BulletList
- [[Plain [Str "and",Space,Str "deeper",Space,Str "levels.",Space]]]]]]
- ,[Plain [Str "Line",Space,Str "breaks",LineBreak,Str "don't",Space,Str "break",Space,Str "levels.",Space]]
- ,[Plain [Str "Continuations",Space,Str "are",Space,Str "also",Space,Str "possible",Space]
+ [[Plain [Str "and",Space,Str "deeper",Space,Str "levels."]]]]]]
+ ,[Plain [Str "Line",Space,Str "breaks",LineBreak,Str "don't",Space,Str "break",Space,Str "levels."]]
+ ,[Plain [Str "Continuations",Space,Str "are",Space,Str "also",Space,Str "possible"]
,BulletList
- [[Plain [Str "and",Space,Str "do",Space,Str "not",Space,Str "break",Space,Str "the",Space,Str "list",Space,Str "flow",Space]]]]
- ,[Plain [Str "Level",Space,Str "one",Space]]]
+ [[Plain [Str "and",Space,Str "do",Space,Str "not",Space,Str "break",Space,Str "the",Space,Str "list",Space,Str "flow"]]]]
+ ,[Plain [Str "Level",Space,Str "one"]]]
,Para [Str "Any",Space,Str "other",Space,Str "start",Space,Str "ends",Space,Str "the",Space,Str "list."]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "Start",Space,Str "each",Space,Str "line",Space]]
- ,[Plain [Str "with",Space,Str "a",Space,Str "number",Space,Str "(1.).",Space]
+ [[Plain [Str "Start",Space,Str "each",Space,Str "line"]]
+ ,[Plain [Str "with",Space,Str "a",Space,Str "number",Space,Str "(1.)."]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "More",Space,Str "number",Space,Str "signs",Space,Str "gives",Space,Str "deeper",Space]
+ [[Plain [Str "More",Space,Str "number",Space,Str "signs",Space,Str "gives",Space,Str "deeper"]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "and",Space,Str "deeper",Space]]
- ,[Plain [Str "levels.",Space]]]]]]
- ,[Plain [Str "Line",Space,Str "breaks",LineBreak,Str "don't",Space,Str "break",Space,Str "levels.",Space]]
- ,[Plain [Str "Blank",Space,Str "lines",Space]]]
+ [[Plain [Str "and",Space,Str "deeper"]]
+ ,[Plain [Str "levels."]]]]]]
+ ,[Plain [Str "Line",Space,Str "breaks",LineBreak,Str "don't",Space,Str "break",Space,Str "levels."]]
+ ,[Plain [Str "Blank",Space,Str "lines"]]]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "end",Space,Str "the",Space,Str "list",Space,Str "and",Space,Str "start",Space,Str "another.",Space]]]
+ [[Plain [Str "end",Space,Str "the",Space,Str "list",Space,Str "and",Space,Str "start",Space,Str "another."]]]
,Para [Str "Any",Space,Str "other",Space,Str "start",Space,Str "also",Space,Str "ends",Space,Str "the",Space,Str "list."]
,DefinitionList
[([Str "item",Space,Str "1"],
- [[Plain [Str "definition",Space,Str "1",Space]]])
+ [[Plain [Str "definition",Space,Str "1"]]])
,([Str "item",Space,Str "2"],
- [[Plain [Str "definition",Space,Str "2-1",Space,Str "definition",Space,Str "2-2",Space]]])
+ [[Plain [Str "definition",Space,Str "2-1",Space,Str "definition",Space,Str "2-2"]]])
,([Str "item",Space,Emph [Str "3"]],
- [[Plain [Str "definition",Space,Emph [Str "3"],Space]]])]
+ [[Plain [Str "definition",Space,Emph [Str "3"]]]])]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "one",Space]]
- ,[Plain [Str "two",Space]
+ [[Plain [Str "one"]]
+ ,[Plain [Str "two"]
,BulletList
- [[Plain [Str "two",Space,Str "point",Space,Str "one",Space]]
- ,[Plain [Str "two",Space,Str "point",Space,Str "two",Space]]]]
- ,[Plain [Str "three",Space]]
- ,[Plain [Str "four",Space]]
- ,[Plain [Str "five",Space]
+ [[Plain [Str "two",Space,Str "point",Space,Str "one"]]
+ ,[Plain [Str "two",Space,Str "point",Space,Str "two"]]]]
+ ,[Plain [Str "three"]]
+ ,[Plain [Str "four"]]
+ ,[Plain [Str "five"]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "five",Space,Str "sub",Space,Str "1",Space]
+ [[Plain [Str "five",Space,Str "sub",Space,Str "1"]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "five",Space,Str "sub",Space,Str "1",Space,Str "sub",Space,Str "1",Space]]]]
- ,[Plain [Str "five",Space,Str "sub",Space,Str "2",Space]]]]]
+ [[Plain [Str "five",Space,Str "sub",Space,Str "1",Space,Str "sub",Space,Str "1"]]]]
+ ,[Plain [Str "five",Space,Str "sub",Space,Str "2"]]]]]
,Header 1 ("tables",[],[]) [Str "tables"]
,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
[[Plain [Str ""]]
diff --git a/test/txt2tags.t2t b/test/txt2tags.t2t
index d374b7a85..f736cfa93 100644
--- a/test/txt2tags.t2t
+++ b/test/txt2tags.t2t
@@ -136,7 +136,7 @@ i) ***bold*** ///ital/// ___undr___ ---strk--- ```mono``` """raw"
%%% Syntax: Repetition is greedy
%% When the mark character is repeated many times,
%% the contents are expanded to the largest possible.
-%% Thats why they are greedy, the outer marks are
+%% That's why they are greedy, the outer marks are
%% the ones used.
i) ***** ///// _____ ----- ````` """"" '''''
diff --git a/test/writer.context b/test/writer.context
index bb69f4e43..d6a36f0dd 100644
--- a/test/writer.context
+++ b/test/writer.context
@@ -706,6 +706,12 @@ These shouldn't be math:
Here's a LaTeX table:
+\begin{tabular}{|l|l|}\hline
+Animal & Number \\ \hline
+Dog & 2 \\
+Cat & 1 \\ \hline
+\end{tabular}
+
\thinrule
\section[title={Special Characters},reference={special-characters}]
diff --git a/test/writer.docbook4 b/test/writer.docbook4
index 163255974..38b3cc1ee 100644
--- a/test/writer.docbook4
+++ b/test/writer.docbook4
@@ -1298,7 +1298,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
<title>Autolinks</title>
<para>
With an ampersand:
- <ulink url="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</ulink>
+ <ulink url="http://example.com/?foo=1&amp;bar=2" role="uri">http://example.com/?foo=1&amp;bar=2</ulink>
</para>
<itemizedlist spacing="compact">
<listitem>
@@ -1308,7 +1308,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
</listitem>
<listitem>
<para>
- <ulink url="http://example.com/">http://example.com/</ulink>
+ <ulink url="http://example.com/" role="uri">http://example.com/</ulink>
</para>
</listitem>
<listitem>
@@ -1323,7 +1323,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
<blockquote>
<para>
Blockquoted:
- <ulink url="http://example.com/">http://example.com/</ulink>
+ <ulink url="http://example.com/" role="uri">http://example.com/</ulink>
</para>
</blockquote>
<para>
diff --git a/test/writer.docbook5 b/test/writer.docbook5
index 992cd8b63..9a9eff0c5 100644
--- a/test/writer.docbook5
+++ b/test/writer.docbook5
@@ -1273,7 +1273,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
<title>Autolinks</title>
<para>
With an ampersand:
- <link xlink:href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</link>
+ <link xlink:href="http://example.com/?foo=1&amp;bar=2" role="uri">http://example.com/?foo=1&amp;bar=2</link>
</para>
<itemizedlist spacing="compact">
<listitem>
@@ -1283,7 +1283,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
</listitem>
<listitem>
<para>
- <link xlink:href="http://example.com/">http://example.com/</link>
+ <link xlink:href="http://example.com/" role="uri">http://example.com/</link>
</para>
</listitem>
<listitem>
@@ -1298,7 +1298,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
<blockquote>
<para>
Blockquoted:
- <link xlink:href="http://example.com/">http://example.com/</link>
+ <link xlink:href="http://example.com/" role="uri">http://example.com/</link>
</para>
</blockquote>
<para>
diff --git a/test/writer.fb2 b/test/writer.fb2
index b2d002230..6940e6217 100644
--- a/test/writer.fb2
+++ b/test/writer.fb2
@@ -3,7 +3,6 @@
<description>
<title-info>
<genre>unrecognised</genre>
-<book-title>Pandoc Test Suite</book-title>
<author>
<first-name>John</first-name>
<last-name>MacFarlane</last-name>
@@ -11,6 +10,7 @@
<author>
<nickname>Anonymous</nickname>
</author>
+<book-title>Pandoc Test Suite</book-title>
<date>July 17, 2006</date>
</title-info>
<document-info>
diff --git a/test/writer.haddock b/test/writer.haddock
index 7f783abd1..13f22021d 100644
--- a/test/writer.haddock
+++ b/test/writer.haddock
@@ -455,14 +455,14 @@ ______________________________________________________________________________
#latex#
-
-- 2 + 2 = 4
-- /x/ ∈ /y/
-- /α/ ∧ /ω/
-- 223
-- /p/-Tree
+- \(2+2=4\)
+- \(x \in y\)
+- \(\alpha \wedge \omega\)
+- \(223\)
+- \(p\)-Tree
- Here’s some display math:
- $$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$$
-- Here’s one that has a line break in it: /α/ + /ω/ × /x/2.
+ \[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\]
+- Here’s one that has a line break in it: \(\alpha + \omega \times x^2\).
These shouldn’t be math:
diff --git a/test/writer.html4 b/test/writer.html4
index dc889f07a..bed6617a0 100644
--- a/test/writer.html4
+++ b/test/writer.html4
@@ -508,7 +508,7 @@ Blah
<li><a href="http://example.com/" class="uri">http://example.com/</a></li>
<li>It should.</li>
</ul>
-<p>An e-mail address: <a href="mailto:nobody@nowhere.net">nobody@nowhere.net</a></p>
+<p>An e-mail address: <a href="mailto:nobody@nowhere.net" class="email">nobody@nowhere.net</a></p>
<blockquote>
<p>Blockquoted: <a href="http://example.com/" class="uri">http://example.com/</a></p>
</blockquote>
diff --git a/test/writer.html5 b/test/writer.html5
index 53fcb84e2..46105d0a6 100644
--- a/test/writer.html5
+++ b/test/writer.html5
@@ -19,7 +19,7 @@
<![endif]-->
</head>
<body>
-<header>
+<header id="title-block-header">
<h1 class="title">Pandoc Test Suite</h1>
<p class="author">John MacFarlane</p>
<p class="author">Anonymous</p>
@@ -511,7 +511,7 @@ Blah
<li><a href="http://example.com/" class="uri">http://example.com/</a></li>
<li>It should.</li>
</ul>
-<p>An e-mail address: <a href="mailto:nobody@nowhere.net">nobody@nowhere.net</a></p>
+<p>An e-mail address: <a href="mailto:nobody@nowhere.net" class="email">nobody@nowhere.net</a></p>
<blockquote>
<p>Blockquoted: <a href="http://example.com/" class="uri">http://example.com/</a></p>
</blockquote>
diff --git a/test/writer.jats b/test/writer.jats
index b51addf3b..f87b2325a 100644
--- a/test/writer.jats
+++ b/test/writer.jats
@@ -583,7 +583,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{</preformat>
</boxed-text>
<p>Interpreted markdown in a table:</p>
<p>This is <italic>emphasized</italic></p>
- <p>And this is <bold role="strong">strong</bold></p>
+ <p>And this is <bold>strong</bold></p>
<p>Here’s a simple block:</p>
<boxed-text>
<p>foo</p>
@@ -614,14 +614,13 @@ These should not be escaped: \$ \\ \&gt; \[ \{</preformat>
<sec id="inline-markup">
<title>Inline Markup</title>
<p>This is <italic>emphasized</italic>, and so <italic>is this</italic>.</p>
- <p>This is <bold role="strong">strong</bold>, and so <bold role="strong">is
- this</bold>.</p>
+ <p>This is <bold>strong</bold>, and so <bold>is this</bold>.</p>
<p>An <italic><ext-link ext-link-type="uri" xlink:href="/url">emphasized
link</ext-link></italic>.</p>
- <p><bold role="strong"><italic>This is strong and em.</italic></bold></p>
- <p>So is <bold role="strong"><italic>this</italic></bold> word.</p>
- <p><bold role="strong"><italic>This is strong and em.</italic></bold></p>
- <p>So is <bold role="strong"><italic>this</italic></bold> word.</p>
+ <p><bold><italic>This is strong and em.</italic></bold></p>
+ <p>So is <bold><italic>this</italic></bold> word.</p>
+ <p><bold><italic>This is strong and em.</italic></bold></p>
+ <p>So is <bold><italic>this</italic></bold> word.</p>
<p>This is code: <monospace>&gt;</monospace>, <monospace>$</monospace>,
<monospace>\</monospace>, <monospace>\$</monospace>,
<monospace>&lt;html&gt;</monospace>.</p>
diff --git a/test/writer.muse b/test/writer.muse
index 9492a5517..35d43a751 100644
--- a/test/writer.muse
+++ b/test/writer.muse
@@ -11,7 +11,7 @@ markdown test suite.
** Level 2 with an [[/url][embedded link]]
-*** Level 3 with <em>emphasis</em>
+*** Level 3 with *emphasis*
**** Level 4
@@ -19,7 +19,7 @@ markdown test suite.
* Level 1
-** Level 2 with <em>emphasis</em>
+** Level 2 with *emphasis*
*** Level 3
@@ -271,18 +271,18 @@ Loose:
Multiple blocks with italics:
- <em>apple</em> :: red fruit
+ *apple* :: red fruit
- contains seeds, crisp, pleasant to taste
- <em>orange</em> :: orange fruit
+ contains seeds, crisp, pleasant to taste
+ *orange* :: orange fruit
- <example>
- { orange code block }
- </example>
+ <example>
+ { orange code block }
+ </example>
- <quote>
- orange block quote
- </quote>
+ <quote>
+ orange block quote
+ </quote>
Multiple definitions, tight:
@@ -331,7 +331,7 @@ Interpreted markdown in a table:
<td>
</literal>
-This is <em>emphasized</em>
+This is *emphasized*
<literal style="html">
</td>
@@ -341,7 +341,7 @@ This is <em>emphasized</em>
<td>
</literal>
-And this is <strong>strong</strong>
+And this is **strong**
<literal style="html">
</td>
@@ -461,27 +461,25 @@ Hr’s:
* Inline Markup
-This is <em>emphasized</em>, and so <em>is this</em>.
+This is *emphasized*, and so *is this*.
-This is <strong>strong</strong>, and so <strong>is this</strong>.
+This is **strong**, and so **is this**.
-An <em>[[/url][emphasized link]]</em>.
+An *[[/url][emphasized link]]*.
-<strong><em>This is strong and em.</em></strong>
+***This is strong and em.***
-So is <strong><em>this</em></strong> word.
+So is ***this*** word.
-<strong><em>This is strong and em.</em></strong>
+***This is strong and em.***
-So is <strong><em>this</em></strong> word.
+So is ***this*** word.
-This is code: <code>></code>, <code>$</code>, <code>\</code>, <code>\$</code>,
-<code><html></code>.
+This is code: =>=, =$=, =\=, =\$=, =<html>=.
-<del>This is <em>strikeout</em>.</del>
+<del>This is *strikeout*.</del>
-Superscripts: a<sup>bc</sup>d a<sup><em>hello</em></sup>
-a<sup>hello there</sup>.
+Superscripts: a<sup>bc</sup>d a<sup>*hello*</sup> a<sup>hello there</sup>.
Subscripts: H<sub>2</sub>O, H<sub>23</sub>O, H<sub>many of them</sub>O.
@@ -500,8 +498,8 @@ spaces: a^b c^d, a~b c~d.
‘He said, “I want to go.”’ Were you alive in the 70’s?
-Here is some quoted ‘<code>code</code>’ and a
-“[[http://example.com/?foo=1&bar=2][quoted link]]”.
+Here is some quoted ‘=code=’ and a “[[http://example.com/?foo=1&bar=2][quoted
+link]]”.
Some dashes: one—two — three—four — five.
@@ -515,26 +513,25 @@ Ellipses…and…and….
- <literal style="tex">\cite[22-23]{smith.1899}</literal>
- <verbatim>2 + 2 = 4</verbatim>
- - <em>x</em> ∈ <em>y</em>
- - <em>α</em> ∧ <em>ω</em>
+ - *x* ∈ *y*
+ - *α* ∧ *ω*
- 223
- - <em>p</em>-Tree
+ - *p*-Tree
- Here’s some display math:
<verbatim>$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</verbatim>
- - Here’s one that has a line break in it:
- <em>α</em> + <em>ω</em> × <em>x</em><sup>2</sup>.
+ - Here’s one that has a line break in it: *α* + *ω* × *x*<sup>2</sup>.
These shouldn’t be math:
- To get the famous equation, write <code>$e = mc^2$</code>.
- - $22,000 is a <em>lot</em> of money. So is $34,000. (It worked if “lot” is
+ - $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is
emphasized.)
- Shoes ($20) and socks ($5).
- - Escaped <code>$</code>: $73 <em>this should be emphasized</em> 23$.
+ - Escaped =$=: $73 *this should be emphasized* 23$.
Here’s a LaTeX table:
-<literal style="latex">
+<literal style="tex">
\begin{tabular}{|l|l|}\hline
Animal & Number \\ \hline
Dog & 2 \\
@@ -669,7 +666,7 @@ An e-mail address: [[mailto:nobody@nowhere.net][nobody@nowhere.net]]
Blockquoted: [[http://example.com/]]
</quote>
-Auto-links should not occur here: <code><http://example.com/></code>
+Auto-links should not occur here: =<http://example.com/>=
<example>
or here: <http://example.com/>
@@ -689,7 +686,7 @@ Here is a movie [[movie.jpg][movie]] icon.
* Footnotes
-Here is a footnote reference,[1] and another.[2] This should <em>not</em> be a
+Here is a footnote reference,[1] and another.[2] This should *not* be a
footnote reference, because it contains a space.[^my note] Here is an inline
note.[3]
@@ -716,9 +713,9 @@ This paragraph should not be part of the note, as it is not indented.
If you want, you can indent every line, but you can also be lazy and just
indent the first line of each block.
-[3] This is <em>easier</em> to type. Inline notes may contain
- [[http://google.com][links]] and <code>]</code> verbatim characters, as
- well as [bracketed text].
+[3] This is *easier* to type. Inline notes may contain
+ [[http://google.com][links]] and =]= verbatim characters, as well as
+ [bracketed text].
[4] In quote.
diff --git a/test/writer.native b/test/writer.native
index 0587bddb8..73fcc0633 100644
--- a/test/writer.native
+++ b/test/writer.native
@@ -324,7 +324,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Spa
,[Plain [Str "Shoes",Space,Str "($20)",Space,Str "and",Space,Str "socks",Space,Str "($5)."]]
,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$."]]]
,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
-,RawBlock (Format "latex") "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}"
+,RawBlock (Format "tex") "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}"
,HorizontalRule
,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"]
,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
@@ -384,14 +384,14 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Spa
,Para [Str "Here\8217s",Space,Str "an",Space,Link ("",[],[]) [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."]
,Para [Str "Here\8217s",Space,Str "an",Space,Link ("",[],[]) [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]
,Header 2 ("autolinks",[],[]) [Str "Autolinks"]
-,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link ("",[],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
+,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link ("",["uri"],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
,BulletList
[[Plain [Str "In",Space,Str "a",Space,Str "list?"]]
- ,[Plain [Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
+ ,[Plain [Link ("",["uri"],[]) [Str "http://example.com/"] ("http://example.com/","")]]
,[Plain [Str "It",Space,Str "should."]]]
-,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link ("",[],[]) [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link ("",["email"],[]) [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
,BlockQuote
- [Para [Str "Blockquoted:",Space,Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
+ [Para [Str "Blockquoted:",Space,Link ("",["uri"],[]) [Str "http://example.com/"] ("http://example.com/","")]]
,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",Space,Code ("",[],[]) "<http://example.com/>"]
,CodeBlock ("",[],[]) "or here: <http://example.com/>"
,HorizontalRule
diff --git a/test/writer.opendocument b/test/writer.opendocument
index 081b33971..09a246b52 100644
--- a/test/writer.opendocument
+++ b/test/writer.opendocument
@@ -6,629 +6,1007 @@
<office:automatic-styles>
<text:list-style style:name="L1">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L2">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L3">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L4">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L5">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L6">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L7">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L8">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L9">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L10">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L11">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L12">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L13">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L14">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L15">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L16">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L17">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L18">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L19">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L20">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L21">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L22">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="2" style:num-prefix="(" style:num-suffix=")">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
<text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="i" text:start-value="4" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-number>
<text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" text:start-value="1" style:num-prefix="(" style:num-suffix=")">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L23">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
<text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="I" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-number>
<text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="6" style:num-prefix="(" style:num-suffix=")">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
<text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="a" text:start-value="3" style:num-suffix=")">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L24">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
<text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L25">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<text:list-style style:name="L26">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L27">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L28">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L29">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="0.4in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.1in" fo:margin-left="1.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="0.8in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.1in" fo:margin-left="1.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="1.2000000000000002in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.1in" fo:margin-left="2.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="1.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.1in" fo:margin-left="2.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="2.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.0in" fo:text-indent="-0.1in" fo:margin-left="3.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="2.4000000000000004in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.5in" fo:text-indent="-0.1in" fo:margin-left="3.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">
- <style:list-level-properties text:space-before="2.8000000000000003in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.0in" fo:text-indent="-0.1in" fo:margin-left="4.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">
- <style:list-level-properties text:space-before="3.2in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.5in" fo:text-indent="-0.1in" fo:margin-left="4.5in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
<text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">
- <style:list-level-properties text:space-before="3.6in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.0in" fo:text-indent="-0.1in" fo:margin-left="5.0in" />
+ </style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L30">
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">
- <style:list-level-properties text:space-before="0.0in" text:min-label-width="0.4in" />
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">
+ <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.1in" fo:margin-left="0.5in" />
+ </style:list-level-properties>
</text:list-level-style-number>
</text:list-style>
<style:style style:name="T1" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
@@ -803,23 +1181,31 @@
<text:p text:style-name="Text_20_body">This is a set of tests for pandoc. Most
of them are adapted from John Gruber’s markdown test suite.</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Headers</text:h>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Level 2 with an
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="headers" />Headers<text:bookmark-end text:name="headers" /></text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-an-embedded-link" />Level
+2 with an
<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">embedded
-link</text:span></text:a></text:h>
-<text:h text:style-name="Heading_20_3" text:outline-level="3">Level 3 with
-<text:span text:style-name="T1">emphasis</text:span></text:h>
-<text:h text:style-name="Heading_20_4" text:outline-level="4">Level 4</text:h>
-<text:h text:style-name="Heading_20_5" text:outline-level="5">Level 5</text:h>
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Level 1</text:h>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Level 2 with
-<text:span text:style-name="T1">emphasis</text:span></text:h>
-<text:h text:style-name="Heading_20_3" text:outline-level="3">Level 3</text:h>
+link</text:span></text:a><text:bookmark-end text:name="level-2-with-an-embedded-link" /></text:h>
+<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3-with-emphasis" />Level
+3 with
+<text:span text:style-name="T1">emphasis</text:span><text:bookmark-end text:name="level-3-with-emphasis" /></text:h>
+<text:h text:style-name="Heading_20_4" text:outline-level="4"><text:bookmark-start text:name="level-4" />Level
+4<text:bookmark-end text:name="level-4" /></text:h>
+<text:h text:style-name="Heading_20_5" text:outline-level="5"><text:bookmark-start text:name="level-5" />Level
+5<text:bookmark-end text:name="level-5" /></text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="level-1" />Level
+1<text:bookmark-end text:name="level-1" /></text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-emphasis" />Level
+2 with
+<text:span text:style-name="T1">emphasis</text:span><text:bookmark-end text:name="level-2-with-emphasis" /></text:h>
+<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3" />Level
+3<text:bookmark-end text:name="level-3" /></text:h>
<text:p text:style-name="First_20_paragraph">with no blank line</text:p>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Level 2</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2" />Level
+2<text:bookmark-end text:name="level-2" /></text:h>
<text:p text:style-name="First_20_paragraph">with no blank line</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Paragraphs</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="paragraphs" />Paragraphs<text:bookmark-end text:name="paragraphs" /></text:h>
<text:p text:style-name="First_20_paragraph">Here’s a regular
paragraph.</text:p>
<text:p text:style-name="Text_20_body">In Markdown 1.0.0 and earlier. Version
@@ -830,8 +1216,8 @@ criminey.</text:p>
<text:p text:style-name="Text_20_body">There should be a hard line
break<text:line-break />here.</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Block
-Quotes</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="block-quotes" />Block
+Quotes<text:bookmark-end text:name="block-quotes" /></text:h>
<text:p text:style-name="First_20_paragraph">E-mail style:</text:p>
<text:p text:style-name="P1">This is a block quote. It is pretty
short.</text:p>
@@ -855,8 +1241,8 @@ short.</text:p>
2 &gt; 1.</text:p>
<text:p text:style-name="Text_20_body">And a following paragraph.</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Code
-Blocks</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="code-blocks" />Code
+Blocks<text:bookmark-end text:name="code-blocks" /></text:h>
<text:p text:style-name="First_20_paragraph">Code:</text:p>
<text:p text:style-name="P9">---- (should be four hyphens)</text:p>
<text:p text:style-name="P10"></text:p>
@@ -870,8 +1256,8 @@ Blocks</text:h>
<text:p text:style-name="P17"></text:p>
<text:p text:style-name="P18">These should not be escaped: <text:s text:c="1" />\$ \\ \&gt; \[ \{</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Lists</text:h>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Unordered</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="lists" />Lists<text:bookmark-end text:name="lists" /></text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="unordered" />Unordered<text:bookmark-end text:name="unordered" /></text:h>
<text:p text:style-name="First_20_paragraph">Asterisks tight:</text:p>
<text:list text:style-name="L2">
<text:list-item>
@@ -944,7 +1330,7 @@ Blocks</text:h>
<text:p text:style-name="P24">Minus 3</text:p>
</text:list-item>
</text:list>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Ordered</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="ordered" />Ordered<text:bookmark-end text:name="ordered" /></text:h>
<text:p text:style-name="First_20_paragraph">Tight:</text:p>
<text:list text:style-name="L8">
<text:list-item>
@@ -1007,7 +1393,7 @@ Blocks</text:h>
<text:p text:style-name="P29">Item 3.</text:p>
</text:list-item>
</text:list>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Nested</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="nested" />Nested<text:bookmark-end text:name="nested" /></text:h>
<text:list text:style-name="L13">
<text:list-item>
<text:p text:style-name="P30">Tab</text:p><text:list text:style-name="L14">
@@ -1068,8 +1454,8 @@ paragraphs:</text:p>
<text:p text:style-name="P35">Third</text:p>
</text:list-item>
</text:list>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Tabs and
-spaces</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="tabs-and-spaces" />Tabs
+and spaces<text:bookmark-end text:name="tabs-and-spaces" /></text:h>
<text:list text:style-name="L20">
<text:list-item>
<text:p text:style-name="P37">this is a list item indented with
@@ -1089,8 +1475,8 @@ spaces</text:h>
</text:list>
</text:list-item>
</text:list>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Fancy list
-markers</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="fancy-list-markers" />Fancy
+list markers<text:bookmark-end text:name="fancy-list-markers" /></text:h>
<text:list text:style-name="L22">
<text:list-item>
<text:p text:style-name="P39">begins with 2</text:p>
@@ -1157,8 +1543,8 @@ item:</text:p>
<text:p text:style-name="Text_20_body">M.A. 2007</text:p>
<text:p text:style-name="Text_20_body">B. Williams</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Definition
-Lists</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="definition-lists" />Definition
+Lists<text:bookmark-end text:name="definition-lists" /></text:h>
<text:p text:style-name="First_20_paragraph">Tight using spaces:</text:p>
<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>
<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>
@@ -1225,8 +1611,8 @@ fruit</text:p><text:list text:style-name="L25">
<text:p text:style-name="P44">sublist</text:p>
</text:list-item>
</text:list>
-<text:h text:style-name="Heading_20_1" text:outline-level="1">HTML
-Blocks</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="html-blocks" />HTML
+Blocks<text:bookmark-end text:name="html-blocks" /></text:h>
<text:p text:style-name="First_20_paragraph">Simple block on one
line:</text:p>
<text:p text:style-name="Text_20_body">foo</text:p>
@@ -1262,8 +1648,8 @@ spaces on the line:</text:p>
<text:p text:style-name="P50">&lt;hr /&gt;</text:p>
<text:p text:style-name="First_20_paragraph">Hr’s:</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Inline
-Markup</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="inline-markup" />Inline
+Markup<text:bookmark-end text:name="inline-markup" /></text:h>
<text:p text:style-name="First_20_paragraph">This is
<text:span text:style-name="T1">emphasized</text:span>, and so
<text:span text:style-name="T1">is this</text:span>.</text:p>
@@ -1300,8 +1686,9 @@ H<text:span text:style-name="T8">many of them</text:span>O.</text:p>
<text:p text:style-name="Text_20_body">These should not be superscripts or
subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Smart quotes,
-ellipses, dashes</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="smart-quotes-ellipses-dashes" />Smart
+quotes, ellipses,
+dashes<text:bookmark-end text:name="smart-quotes-ellipses-dashes" /></text:h>
<text:p text:style-name="First_20_paragraph">“Hello,” said the spider.
“‘Shelob’ is my name.”</text:p>
<text:p text:style-name="Text_20_body">‘A’, ‘B’, and ‘C’ are letters.</text:p>
@@ -1319,7 +1706,7 @@ five.</text:p>
1987–1999.</text:p>
<text:p text:style-name="Text_20_body">Ellipses…and…and….</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">LaTeX</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="latex" />LaTeX<text:bookmark-end text:name="latex" /></text:h>
<text:list text:style-name="L26">
<text:list-item>
<text:p text:style-name="P51"></text:p>
@@ -1371,8 +1758,8 @@ five.</text:p>
</text:list>
<text:p text:style-name="First_20_paragraph">Here’s a LaTeX table:</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Special
-Characters</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="special-characters" />Special
+Characters<text:bookmark-end text:name="special-characters" /></text:h>
<text:p text:style-name="First_20_paragraph">Here is some unicode:</text:p>
<text:list text:style-name="L28">
<text:list-item>
@@ -1415,8 +1802,8 @@ it.</text:p>
<text:p text:style-name="Text_20_body">Plus: +</text:p>
<text:p text:style-name="Text_20_body">Minus: -</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Links</text:h>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Explicit</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="links" />Links<text:bookmark-end text:name="links" /></text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="explicit" />Explicit<text:bookmark-end text:name="explicit" /></text:h>
<text:p text:style-name="First_20_paragraph">Just a
<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">URL</text:span></text:a>.</text:p>
<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title"><text:span text:style-name="Definition">URL
@@ -1433,7 +1820,7 @@ and title</text:span></text:a></text:p>
<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">Email
link</text:span></text:a></text:p>
<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="" office:name=""><text:span text:style-name="Definition">Empty</text:span></text:a>.</text:p>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Reference</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="reference" />Reference<text:bookmark-end text:name="reference" /></text:h>
<text:p text:style-name="First_20_paragraph">Foo
<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>
<text:p text:style-name="Text_20_body">With
@@ -1453,8 +1840,8 @@ by itself should be a link.</text:p>
<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with &quot;quotes&quot; inside"><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>
<text:p text:style-name="Text_20_body">Foo
<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with &quot;quote&quot; inside"><text:span text:style-name="Definition">biz</text:span></text:a>.</text:p>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">With
-ampersands</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="with-ampersands" />With
+ampersands<text:bookmark-end text:name="with-ampersands" /></text:h>
<text:p text:style-name="First_20_paragraph">Here’s a
<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">link
with an ampersand in the URL</text:span></text:a>.</text:p>
@@ -1467,7 +1854,7 @@ link</text:span></text:a>.</text:p>
<text:p text:style-name="Text_20_body">Here’s an
<text:a xlink:type="simple" xlink:href="/script?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">inline
link in pointy braces</text:span></text:a>.</text:p>
-<text:h text:style-name="Heading_20_2" text:outline-level="2">Autolinks</text:h>
+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="autolinks" />Autolinks<text:bookmark-end text:name="autolinks" /></text:h>
<text:p text:style-name="First_20_paragraph">With an ampersand:
<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">http://example.com/?foo=1&amp;bar=2</text:span></text:a></text:p>
<text:list text:style-name="L29">
@@ -1489,16 +1876,16 @@ link in pointy braces</text:span></text:a>.</text:p>
<text:span text:style-name="Source_Text">&lt;http://example.com/&gt;</text:span></text:p>
<text:p text:style-name="P57">or here: &lt;http://example.com/&gt;</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Images</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="images" />Images<text:bookmark-end text:name="images" /></text:h>
<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by
Georges Melies (1902):</text:p>
<text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>
-<text:p text:style-name="FigureCaption">lalune</text:p>
+<text:p text:style-name="FigureCaption">Figure <text:sequence text:ref-name="refIllustration0" text:name="Illustration" text:formula="ooow:Illustration+1" style:num-format="1">1</text:sequence>: lalune</text:p>
<text:p text:style-name="Text_20_body">Here is a movie
<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>
icon.</text:p>
<text:p text:style-name="Horizontal_20_Line" />
-<text:h text:style-name="Heading_20_1" text:outline-level="1">Footnotes</text:h>
+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="footnotes" />Footnotes<text:bookmark-end text:name="footnotes" /></text:h>
<text:p text:style-name="First_20_paragraph">Here is a footnote
reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here
is the footnote. It can go anywhere after the footnote reference. It need not
diff --git a/test/writer.org b/test/writer.org
index 1ae0ca8f3..32fcfc404 100644
--- a/test/writer.org
+++ b/test/writer.org
@@ -584,7 +584,7 @@ Superscripts: a^{bc}d a^{/hello/} a^{hello there}.
Subscripts: H_{2}O, H_{23}O, H_{many of them}O.
These should not be superscripts or subscripts, because of the unescaped
-spaces: a\^b c\^d, a~b c~d.
+spaces: a^b c^d, a~b c~d.
--------------
@@ -674,7 +674,7 @@ Backtick: `
Asterisk: *
-Underscore: \_
+Underscore: _
Left brace: {
@@ -724,7 +724,7 @@ Just a [[/url/][URL]].
[[/url/][URL and title]]
-[[/url/with_underscore][with\_underscore]]
+[[/url/with_underscore][with_underscore]]
[[mailto:nobody@nowhere.net][Email link]]
@@ -816,7 +816,7 @@ Here is a movie [[file:movie.jpg]] icon.
:END:
Here is a footnote reference,[fn:1] and another.[fn:2] This should /not/ be a
-footnote reference, because it contains a space.[\^my note] Here is an inline
+footnote reference, because it contains a space.[^my note] Here is an inline
note.[fn:3]
#+BEGIN_QUOTE
diff --git a/test/writer.rst b/test/writer.rst
index 0c986b887..b47490de2 100644
--- a/test/writer.rst
+++ b/test/writer.rst
@@ -385,53 +385,23 @@ HTML Blocks
Simple block on one line:
-.. raw:: html
-
- <div>
-
-foo
+.. container::
-.. raw:: html
-
- </div>
+ foo
And nested without indentation:
-.. raw:: html
-
- <div>
-
-.. raw:: html
-
- <div>
-
-.. raw:: html
-
- <div>
-
-foo
-
-.. raw:: html
-
- </div>
-
-.. raw:: html
-
- </div>
+.. container::
-.. raw:: html
+ .. container::
- <div>
+ .. container::
-bar
+ foo
-.. raw:: html
+ .. container::
- </div>
-
-.. raw:: html
-
- </div>
+ bar
Interpreted markdown in a table:
@@ -477,15 +447,9 @@ And this is **strong**
Here’s a simple block:
-.. raw:: html
-
- <div>
-
-foo
-
-.. raw:: html
+.. container::
- </div>
+ foo
This should be a code block, though:
@@ -503,31 +467,13 @@ As should this:
Now, nested:
-.. raw:: html
-
- <div>
+.. container::
-.. raw:: html
+ .. container::
- <div>
+ .. container::
-.. raw:: html
-
- <div>
-
-foo
-
-.. raw:: html
-
- </div>
-
-.. raw:: html
-
- </div>
-
-.. raw:: html
-
- </div>
+ foo
This should just be an HTML comment:
diff --git a/test/writer.tei b/test/writer.tei
index 779aa337b..587a6fcca 100644
--- a/test/writer.tei
+++ b/test/writer.tei
@@ -8,8 +8,8 @@
<author>Anonymous</author>
</titleStmt>
<publicationStmt>
- <p></p>
- </publicationStmt>
+ <date>July 17, 2006</date>
+ </publicationStmt>
<sourceDesc>
<p>Produced by pandoc.</p>
</sourceDesc>
diff --git a/test/writer.texinfo b/test/writer.texinfo
index f5727d96d..ebc0447ee 100644
--- a/test/writer.texinfo
+++ b/test/writer.texinfo
@@ -5,24 +5,6 @@
~~\text\~~
@end macro
-@macro textsubscript{text}
-@iftex
-@textsubscript{\text\}
-@end iftex
-@ifnottex
-_@{\text\@}
-@end ifnottex
-@end macro
-
-@macro textsuperscript{text}
-@iftex
-@textsuperscript{\text\}
-@end iftex
-@ifnottex
-^@{\text\@}
-@end ifnottex
-@end macro
-
@ifnottex
@paragraphindent 0
@end ifnottex
@@ -738,11 +720,9 @@ This is code: @code{>}, @code{$}, @code{\}, @code{\$}, @code{<html>}.
@textstrikeout{This is @emph{strikeout}.}
-Superscripts: a@textsuperscript{bc}d a@textsuperscript{@emph{hello}}
-a@textsuperscript{hello@ there}.
+Superscripts: a@sup{bc}d a@sup{@emph{hello}} a@sup{hello@ there}.
-Subscripts: H@textsubscript{2}O, H@textsubscript{23}O,
-H@textsubscript{many@ of@ them}O.
+Subscripts: H@sub{2}O, H@sub{23}O, H@sub{many@ of@ them}O.
These should not be superscripts or subscripts, because of the unescaped
spaces: a^b c^d, a~b c~d.
diff --git a/test/writer.textile b/test/writer.textile
index d19b698f9..78e659091 100644
--- a/test/writer.textile
+++ b/test/writer.textile
@@ -660,7 +660,7 @@ With an ampersand: "$":http://example.com/?foo=1&bar=2
* "$":http://example.com/
* It should.
-An e&#45;mail address: "nobody&#64;nowhere.net":mailto:nobody@nowhere.net
+An e&#45;mail address: "(email)nobody&#64;nowhere.net":mailto:nobody@nowhere.net
bq. Blockquoted: "$":http://example.com/
diff --git a/tools/changelog-helper.sh b/tools/changelog-helper.sh
new file mode 100755
index 000000000..dfaefa483
--- /dev/null
+++ b/tools/changelog-helper.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# generate preliminary list of changes since changelog
+# was last modified
+
+lastmod=`git log -n2 --format=oneline changelog | awk '{print $1;}'`
+#git log --format=oneline $starthash..HEAD
+files=`git ls-tree -r master --name-only`
+for x in $files
+do
+ commits=`git log -n1 $lastmod..HEAD $x`
+ if [[ ! -z $commits ]]
+ then
+ if echo $x | grep -q "src\/.*\.hs"
+ then
+ file=`echo $x | sed -e 's/src\///' | sed -e 's/\//\./g' | sed -e 's/\.hs$//'`
+ else
+ file=$x
+ fi
+ echo " * $file"
+ GIT_PAGER=cat git log --pretty=format:'%n%w(78,4,6)+ %s (%an)%n%n%w(78,6,6)%b%n' $lastmod..HEAD $x
+ fi
+done
+
diff --git a/trypandoc/trypandoc.hs b/trypandoc/trypandoc.hs
index a4c21e1f6..f451b3063 100644
--- a/trypandoc/trypandoc.hs
+++ b/trypandoc/trypandoc.hs
@@ -25,7 +25,7 @@ main = run app
app :: Application
app req respond = do
let query = queryToQueryText $ queryString req
- let getParam x = maybe (error $ T.unpack x ++ " paramater not set")
+ let getParam x = maybe (error $ T.unpack x ++ " parameter not set")
return $ lookup x query
text <- getParam "text" >>= checkLength . fromMaybe T.empty
fromFormat <- fromMaybe "" <$> getParam "from"