aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml.bkp (renamed from .travis.yml)4
-rw-r--r--BUGS2
-rw-r--r--Benchmark.hs45
-rw-r--r--INSTALL34
-rw-r--r--MakeManPage.hs30
-rw-r--r--Makefile30
-rw-r--r--README371
-rw-r--r--Setup.hs18
-rw-r--r--benchmark/benchmark-pandoc.hs46
-rw-r--r--pandoc.cabal148
-rw-r--r--src/Text/Pandoc.hs197
-rw-r--r--src/Text/Pandoc/Biblio.hs12
-rw-r--r--src/Text/Pandoc/Highlighting.hs7
-rw-r--r--src/Text/Pandoc/MIME.hs2
-rw-r--r--src/Text/Pandoc/Options.hs277
-rw-r--r--src/Text/Pandoc/Parsing.hs483
-rw-r--r--src/Text/Pandoc/Pretty.hs13
-rw-r--r--src/Text/Pandoc/Readers/DocBook.hs14
-rw-r--r--src/Text/Pandoc/Readers/HTML.hs109
-rw-r--r--src/Text/Pandoc/Readers/LaTeX.hs34
-rw-r--r--src/Text/Pandoc/Readers/Markdown.hs1423
-rw-r--r--src/Text/Pandoc/Readers/Native.hs33
-rw-r--r--src/Text/Pandoc/Readers/RST.hs316
-rw-r--r--src/Text/Pandoc/Readers/TeXMath.hs2
-rw-r--r--src/Text/Pandoc/Readers/Textile.hs204
-rw-r--r--src/Text/Pandoc/SelfContained.hs17
-rw-r--r--src/Text/Pandoc/Shared.hs167
-rw-r--r--src/Text/Pandoc/Templates.hs60
-rw-r--r--src/Text/Pandoc/UTF8.hs2
-rw-r--r--src/Text/Pandoc/Writers/AsciiDoc.hs6
-rw-r--r--src/Text/Pandoc/Writers/ConTeXt.hs47
-rw-r--r--src/Text/Pandoc/Writers/Docbook.hs76
-rw-r--r--src/Text/Pandoc/Writers/Docx.hs19
-rw-r--r--src/Text/Pandoc/Writers/EPUB.hs31
-rw-r--r--src/Text/Pandoc/Writers/FB2.hs616
-rw-r--r--src/Text/Pandoc/Writers/HTML.hs21
-rw-r--r--src/Text/Pandoc/Writers/LaTeX.hs9
-rw-r--r--src/Text/Pandoc/Writers/Man.hs81
-rw-r--r--src/Text/Pandoc/Writers/Markdown.hs330
-rw-r--r--src/Text/Pandoc/Writers/MediaWiki.hs52
-rw-r--r--src/Text/Pandoc/Writers/Native.hs10
-rw-r--r--src/Text/Pandoc/Writers/ODT.hs19
-rw-r--r--src/Text/Pandoc/Writers/OpenDocument.hs2
-rw-r--r--src/Text/Pandoc/Writers/Org.hs60
-rw-r--r--src/Text/Pandoc/Writers/RST.hs51
-rw-r--r--src/Text/Pandoc/Writers/RTF.hs85
-rw-r--r--src/Text/Pandoc/Writers/Texinfo.hs27
-rw-r--r--src/Text/Pandoc/Writers/Textile.hs31
-rw-r--r--src/pandoc.hs250
-rwxr-xr-xstats.sh33
m---------templates14
-rw-r--r--tests/Tests/Arbitrary.hs (renamed from src/Tests/Arbitrary.hs)0
-rw-r--r--tests/Tests/Helpers.hs (renamed from src/Tests/Helpers.hs)12
-rw-r--r--tests/Tests/Old.hs (renamed from src/Tests/Old.hs)35
-rw-r--r--tests/Tests/Readers/LaTeX.hs (renamed from src/Tests/Readers/LaTeX.hs)2
-rw-r--r--tests/Tests/Readers/Markdown.hs (renamed from src/Tests/Readers/Markdown.hs)12
-rw-r--r--tests/Tests/Readers/RST.hs (renamed from src/Tests/Readers/RST.hs)2
-rw-r--r--tests/Tests/Shared.hs (renamed from src/Tests/Shared.hs)0
-rw-r--r--tests/Tests/Writers/ConTeXt.hs (renamed from src/Tests/Writers/ConTeXt.hs)5
-rw-r--r--tests/Tests/Writers/HTML.hs (renamed from src/Tests/Writers/HTML.hs)2
-rw-r--r--tests/Tests/Writers/LaTeX.hs (renamed from src/Tests/Writers/LaTeX.hs)2
-rw-r--r--tests/Tests/Writers/Markdown.hs (renamed from src/Tests/Writers/Markdown.hs)2
-rw-r--r--tests/Tests/Writers/Native.hs (renamed from src/Tests/Writers/Native.hs)4
-rw-r--r--tests/fb2.basic.fb22
-rw-r--r--tests/fb2.basic.markdown33
-rw-r--r--tests/fb2.images-embedded.fb22
-rw-r--r--tests/fb2.images-embedded.html14
-rw-r--r--tests/fb2.images.fb22
-rw-r--r--tests/fb2.images.markdown13
-rw-r--r--tests/fb2.math.fb22
-rw-r--r--tests/fb2.math.markdown10
-rw-r--r--tests/fb2.test-small.pngbin0 -> 4090 bytes
-rw-r--r--tests/fb2.test.jpgbin0 -> 153610 bytes
-rw-r--r--tests/fb2.titles.fb22
-rw-r--r--tests/fb2.titles.markdown10
-rw-r--r--tests/lhs-test.native6
-rw-r--r--tests/markdown-reader-more.native20
-rw-r--r--tests/pipe-tables.native70
-rw-r--r--tests/pipe-tables.txt42
-rw-r--r--tests/rst-reader.native4
-rw-r--r--tests/rst-reader.rst4
-rw-r--r--tests/tables.fb22
-rw-r--r--tests/tables.native44
-rw-r--r--tests/test-pandoc.hs (renamed from src/test-pandoc.hs)3
-rw-r--r--tests/testsuite.native268
-rw-r--r--tests/textile-reader.native1
-rw-r--r--tests/textile-reader.textile2
-rw-r--r--tests/writer.fb22
-rw-r--r--tests/writer.man20
-rw-r--r--tests/writer.native268
-rw-r--r--tests/writer.opendocument100
-rw-r--r--windows/pandoc-setup.iss2
92 files changed, 4372 insertions, 2624 deletions
diff --git a/.travis.yml b/.travis.yml.bkp
index cb221e567..934a8ea5b 100644
--- a/.travis.yml
+++ b/.travis.yml.bkp
@@ -3,5 +3,5 @@ before_install:
- git submodule update --init --recursive
install:
- cabal update
- - cabal install -ftests
-script: cabal configure -ftests && cabal build && cabal test
+ - cabal install --enable-tests
+script: cabal configure --enable-tests && cabal build && cabal test
diff --git a/BUGS b/BUGS
index 5ed2c9a34..10a9db19f 100644
--- a/BUGS
+++ b/BUGS
@@ -1,2 +1,2 @@
To view a list of known bugs, or to enter a bug report, please use
-Pandoc's issue tracker: <http://code.google.com/p/pandoc/issues/list>
+Pandoc's issue tracker: <https://github.com/jgm/pandoc/issues>
diff --git a/Benchmark.hs b/Benchmark.hs
deleted file mode 100644
index 1fd787945..000000000
--- a/Benchmark.hs
+++ /dev/null
@@ -1,45 +0,0 @@
-import Text.Pandoc
-import Text.Pandoc.Shared (readDataFile, normalize)
-import Criterion.Main
-import Data.List (isSuffixOf)
-import Text.JSON.Generic
-
-readerBench :: Pandoc
- -> (String, ParserState -> String -> Pandoc)
- -> Benchmark
-readerBench doc (name, reader) =
- let writer = case lookup name writers of
- Just w -> w
- Nothing -> error $ "Could not find writer for " ++ name
- inp = writer defaultWriterOptions{ writerWrapText = True
- , writerLiterateHaskell =
- "+lhs" `isSuffixOf` name } doc
- -- we compute the length to force full evaluation
- getLength (Pandoc (Meta a b c) d) =
- length a + length b + length c + length d
- in bench (name ++ " reader") $ whnf (getLength .
- reader defaultParserState{ stateSmart = True
- , stateStandalone = True
- , stateLiterateHaskell =
- "+lhs" `isSuffixOf` name }) inp
-
-writerBench :: Pandoc
- -> (String, WriterOptions -> Pandoc -> String)
- -> Benchmark
-writerBench doc (name, writer) = bench (name ++ " writer") $ nf
- (writer defaultWriterOptions{
- writerWrapText = True
- , writerLiterateHaskell = "+lhs" `isSuffixOf` name }) doc
-
-normalizeBench :: Pandoc -> [Benchmark]
-normalizeBench doc = [ bench "normalize - with" $ nf (encodeJSON . normalize) doc
- , bench "normalize - without" $ nf encodeJSON doc
- ]
-
-main = do
- inp <- readDataFile (Just ".") "README"
- let ps = defaultParserState{ stateSmart = True }
- let doc = readMarkdown ps inp
- let readerBs = map (readerBench doc) readers
- defaultMain $ map (writerBench doc) writers ++ readerBs ++ normalizeBench doc
-
diff --git a/INSTALL b/INSTALL
index 8c4a07e2b..a3d2389e5 100644
--- a/INSTALL
+++ b/INSTALL
@@ -136,9 +136,9 @@ Running tests
-------------
Pandoc comes with an automated test suite integrated to cabal.
-To enable the tests, compile pandoc with the `tests` flag:
+To build the tests:
- cabal install -ftests
+ cabal configure --enable-tests && cabal build
Note: If you obtained the source via git, you should first do
@@ -151,11 +151,35 @@ To run the tests:
cabal test
+To run particular tests (pattern-matching on their names), use
+the `-t` option:
+
+ cabal test --test-options='-t markdown'
+
If you add a new feature to pandoc, please add tests as well, following
the pattern of the existing tests. The test suite code is in
-`src/test-pandoc.hs`. If you are adding a new reader or writer, it is
+`tests/test-pandoc.hs`. If you are adding a new reader or writer, it is
probably easiest to add some data files to the `tests` directory, and
-modify `src/Tests/Old.hs`. Otherwise, it is better to modify the module
-under the `src/Tests` hierarchy corresponding to the pandoc module you
+modify `tests/Tests/Old.hs`. Otherwise, it is better to modify the module
+under the `tests/Tests` hierarchy corresponding to the pandoc module you
are changing.
+Running benchmarks
+------------------
+
+To build the benchmarks:
+
+ cabal configure --enable-benchmarks && cabal build
+
+To run the benchmarks:
+
+ cabal bench
+
+To use a smaller sample size so the benchmarks run faster:
+
+ cabal bench --benchmark-options='-s 20'
+
+To run just the markdown benchmarks:
+
+ cabal bench --benchmark-options='markdown'
+
diff --git a/MakeManPage.hs b/MakeManPage.hs
index 8405df70b..c78fb7d77 100644
--- a/MakeManPage.hs
+++ b/MakeManPage.hs
@@ -7,14 +7,10 @@ import Control.Monad
import System.FilePath
import System.Environment (getArgs)
import Text.Pandoc.Shared (normalize)
-import System.Directory (getModificationTime)
-import System.IO.Error (isDoesNotExistError)
-import System.Time (ClockTime(..))
-import Data.Maybe (catMaybes)
main = do
rmContents <- liftM toString $ B.readFile "README"
- let (Pandoc meta blocks) = readMarkdown defaultParserState rmContents
+ let (Pandoc meta blocks) = readMarkdown def rmContents
let manBlocks = removeSect [Str "Wrappers"]
$ removeSect [Str "Pandoc's",Space,Str "markdown"] blocks
let syntaxBlocks = extractSect [Str "Pandoc's",Space,Str "markdown"] blocks
@@ -28,33 +24,19 @@ main = do
makeManPage :: Bool -> FilePath -> Meta -> [Block] -> IO ()
makeManPage verbose page meta blocks = do
let templ = page <.> "template"
- modDeps <- modifiedDependencies page ["README", templ]
- unless (null modDeps) $ do
- manTemplate <- liftM toString $ B.readFile templ
- writeManPage page manTemplate (Pandoc meta blocks)
- when verbose $
- putStrLn $ "Created " ++ page
+ manTemplate <- liftM toString $ B.readFile templ
+ writeManPage page manTemplate (Pandoc meta blocks)
+ when verbose $ putStrLn $ "Created " ++ page
writeManPage :: FilePath -> String -> Pandoc -> IO ()
writeManPage page templ doc = do
- let opts = defaultWriterOptions{ writerStandalone = True
- , writerTemplate = templ }
+ let opts = def{ writerStandalone = True
+ , writerTemplate = templ }
let manPage = writeMan opts $
bottomUp (concatMap removeLinks) $
bottomUp capitalizeHeaders doc
B.writeFile page $ fromString manPage
--- | Returns a list of 'dependencies' that have been modified after 'file'.
-modifiedDependencies :: FilePath -> [FilePath] -> IO [FilePath]
-modifiedDependencies file dependencies = do
- fileModTime <- catch (getModificationTime file) $
- \e -> if isDoesNotExistError e
- then return (TOD 0 0) -- the minimum ClockTime
- else ioError e
- depModTimes <- mapM getModificationTime dependencies
- let modified = zipWith (\dep time -> if time > fileModTime then Just dep else Nothing) dependencies depModTimes
- return $ catMaybes modified
-
removeLinks :: Inline -> [Inline]
removeLinks (Link l _) = l
removeLinks x = [x]
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..73923dc77
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+# This Makefile is for development only. It requires cabal-dev.
+# To get started, do 'make prep' and then 'make' or 'make quick'.
+
+.PHONY: prep, all, quick, bench, clean, install
+
+all:
+ cabal-dev configure --enable-tests --enable-benchmarks && cabal-dev build
+
+prep: pandoc-types citeproc-hs
+ cabal-dev install-deps --enable-tests --enable-benchmarks
+
+quick:
+ cabal-dev configure --enable-tests --disable-optimization && cabal-dev build
+
+bench:
+ cabal-dev configure --enable-benchmarks && cabal-dev build
+
+clean:
+ cabal-dev clean && rm -rf pandoc-types citeproc-hs
+
+pandoc-types:
+ git clone https://github.com/jgm/pandoc-types && \
+ cabal-dev add-source pandoc-types
+
+citeproc-hs: pandoc-types
+ git clone https://github.com/jgm/citeproc-hs && \
+ cabal-dev add-source citeproc-hs
+
+install:
+ cabal-dev install
diff --git a/README b/README
index 0cf8d34e6..2fa8cbce5 100644
--- a/README
+++ b/README
@@ -16,18 +16,18 @@ another, and a command-line tool that uses this library. It can read
[LaTeX], and [DocBook XML]; and it can write plain text, [markdown],
[reStructuredText], [XHTML], [HTML 5], [LaTeX] (including [beamer]
slide shows), [ConTeXt], [RTF], [DocBook XML], [OpenDocument XML],
-[ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [EPUB],
+[ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [EPUB], [FictionBook2],
[Textile], [groff man] pages, [Emacs Org-Mode], [AsciiDoc], and [Slidy],
[Slideous], [DZSlides], or [S5] HTML slide shows. It can also produce
[PDF] output on systems where LaTeX is installed.
Pandoc's enhanced version of markdown includes syntax for footnotes,
-tables, flexible ordered lists, definition lists, delimited code blocks,
+tables, flexible ordered lists, definition lists, fenced code blocks,
superscript, subscript, strikeout, title blocks, automatic tables of
contents, embedded LaTeX math, citations, and markdown inside HTML block
elements. (These enhancements, described below under
-[Pandoc's markdown](#pandocs-markdown), can be disabled using the `--strict`
-option.)
+[Pandoc's markdown](#pandocs-markdown), can be disabled using the
+`markdown_strict` input or output format.)
In contrast to most existing tools for converting markdown to HTML, which
use regex substitutions, Pandoc has a modular design: it consists of a
@@ -117,12 +117,13 @@ and `xunicode` (if `xelatex` is used).
A user who wants a drop-in replacement for `Markdown.pl` may create
a symbolic link to the `pandoc` executable called `hsmarkdown`. When
-invoked under the name `hsmarkdown`, `pandoc` will behave as if the
-`--strict` flag had been selected, and no command-line options will be
-recognized. However, this approach does not work under Cygwin, due to
-problems with its simulation of symbolic links.
+invoked under the name `hsmarkdown`, `pandoc` will behave as if
+invoked with `-f markdown_strict --email-obfuscation=references`,
+and all command-line options will be treated as regular arguments.
+However, this approach does not work under Cygwin, due to problems with
+its simulation of symbolic links.
-[Cygwin]: http://www.cygwin.com/
+[Cygwin]: http://www.cygwin.com/
[`iconv`]: http://www.gnu.org/software/libiconv/
[CTAN]: http://www.ctan.org "Comprehensive TeX Archive Network"
[TeX Live]: http://www.tug.org/texlive/
@@ -136,31 +137,45 @@ General options
`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*
: Specify input format. *FORMAT* can be `native` (native Haskell),
- `json` (JSON version of native AST), `markdown` (markdown),
+ `json` (JSON version of native AST), `markdown` (pandoc's
+ extended markdown), `markdown_strict` (original unextended markdown),
`textile` (Textile), `rst` (reStructuredText), `html` (HTML),
`docbook` (DocBook XML), or `latex` (LaTeX). If `+lhs` is
appended to `markdown`, `rst`, `latex`, the input will be
treated as literate Haskell source: see [Literate Haskell
- support](#literate-haskell-support), below.
+ support](#literate-haskell-support), below. Markdown syntax
+ extensions can be individually enabled or disabled by appending
+ `+EXTENSION` or `-EXTENSION` to the format name. So, for example,
+ `markdown_strict+footnotes+definition_lists` is strict markdown
+ with footnotes and definition lists enabled, and
+ `markdown-pipe_tables+hard_line_breaks` is pandoc's markdown
+ without pipe tables and with hard line breaks. See
+ [Pandoc's markdown](#pandocs-markdown), below, for a list of
+ extensions and their names.
`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*
: Specify output format. *FORMAT* can be `native` (native Haskell),
`json` (JSON version of native AST), `plain` (plain text),
- `markdown` (markdown), `rst` (reStructuredText), `html` (XHTML 1),
- `html5` (HTML 5), `latex` (LaTeX), `beamer` (LaTeX beamer slide show),
- `context` (ConTeXt), `man` (groff man), `mediawiki` (MediaWiki markup),
- `textile` (Textile), `org` (Emacs Org-Mode), `texinfo` (GNU Texinfo),
- `docbook` (DocBook XML), `opendocument` (OpenDocument XML), `odt`
- (OpenOffice text document), `docx` (Word docx), `epub` (EPUB book),
- `asciidoc` (AsciiDoc), `slidy` (Slidy HTML and javascript slide show),
- `slideous` (Slideous HTML and javascript slide show),
- `dzslides` (HTML5 + javascript slide show), `s5` (S5 HTML and javascript
- slide show), or `rtf` (rich text format). Note that `odt` and `epub`
- output will not be directed to *stdout*; an output filename must
- be specified using the `-o/--output` option. If `+lhs` is appended
- to `markdown`, `rst`, `latex`, `beamer`, `html`, or `html5`, the output
- will be rendered as literate Haskell source: see [Literate Haskell
- support](#literate-haskell-support), below.
+ `markdown` (pandoc's extended markdown), `markdown_strict` (original
+ unextended markdown), `rst` (reStructuredText), `html` (XHTML
+ 1), `html5` (HTML 5), `latex` (LaTeX), `beamer` (LaTeX beamer
+ slide show), `context` (ConTeXt), `man` (groff man), `mediawiki`
+ (MediaWiki markup), `textile` (Textile), `org` (Emacs Org-Mode),
+ `texinfo` (GNU Texinfo), `docbook` (DocBook XML), `opendocument`
+ (OpenDocument XML), `odt` (OpenOffice text document), `docx`
+ (Word docx), `epub` (EPUB book), `fb2` (FictionBook2 e-book),
+ `asciidoc` (AsciiDoc), `slidy` (Slidy HTML and javascript slide
+ show), `slideous` (Slideous HTML and javascript slide show),
+ `dzslides` (HTML5 + javascript slide show), `s5` (S5 HTML and
+ javascript slide show), or `rtf` (rich text format). Note that
+ `odt` and `epub` output will not be directed to *stdout*; an output
+ filename must be specified using the `-o/--output` option. If `+lhs`
+ is appended to `markdown`, `rst`, `latex`, `beamer`, `html`, or
+ `html5`, the output will be rendered as literate Haskell source:
+ see [Literate Haskell support](#literate-haskell-support), below.
+ Markdown syntax extensions can be individually enabled or disabled
+ by appending `+EXTENSION` or `-EXTENSION` to the format name, as
+ described above under `-f`.
`-o` *FILE*, `--output=`*FILE*
: Write output to *FILE* instead of *stdout*. If *FILE* is
@@ -191,12 +206,6 @@ General options
Reader options
--------------
-`--strict`
-: Use strict markdown syntax, with no pandoc extensions or variants.
- When the input format is HTML, this means that constructs that have no
- equivalents in standard markdown (e.g. definition lists or strikeout
- text) will be parsed as raw HTML.
-
`-R`, `--parse-raw`
: Parse untranslatable HTML codes and LaTeX environments as raw HTML
or LaTeX, instead of ignoring them. Affects only HTML and LaTeX
@@ -213,9 +222,10 @@ Reader options
to curly quotes, `---` to em-dashes, `--` to en-dashes, and
`...` to ellipses. Nonbreaking spaces are inserted after certain
abbreviations, such as "Mr." (Note: This option is significant only when
- the input format is `markdown` or `textile`. It is selected automatically
- when the input format is `textile` or the output format is `latex` or
- `context`, unless `--no-tex-ligatures` is used.)
+ the input format is `markdown`, `markdown_strict`, or `textile`. It
+ is selected automatically when the input format is `textile` or the
+ output format is `latex` or `context`, unless `--no-tex-ligatures`
+ is used.)
`--old-dashes`
: Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes: `-` before
@@ -236,6 +246,8 @@ Reader options
`-p`, `--preserve-tabs`
: Preserve tabs instead of converting them to spaces (the default).
+ Note that this will only affect tabs in literal code spans and code
+ blocks; tabs in regular text will be treated as spaces.
`--tab-stop=`*NUMBER*
: Specify the number of spaces per tab (default is 4).
@@ -246,7 +258,8 @@ General writer options
`-s`, `--standalone`
: Produce output with an appropriate header and footer (e.g. a
standalone HTML, LaTeX, or RTF file, not a fragment). This option
- is set automatically for `pdf`, `epub`, `docx`, and `odt` output.
+ is set automatically for `pdf`, `epub`, `fb2`, `docx`, and `odt`
+ output.
`--template=`*FILE*
: Use *FILE* as a custom template for the generated document. Implies
@@ -399,8 +412,6 @@ Options affecting specific writers
*none* leaves `mailto:` links as they are. *javascript* obfuscates
them using javascript. *references* obfuscates them by printing their
letters as decimal or hexadecimal character references.
- If `--strict` is specified, *references* is used regardless of the
- presence of this option.
`--id-prefix`=*STRING*
: Specify a prefix to be added to all automatically generated identifiers
@@ -414,7 +425,8 @@ Options affecting specific writers
`--standalone`.
`-c` *URL*, `--css=`*URL*
-: Link to a CSS style sheet.
+: Link to a CSS style sheet. This option can be be used repeatedly to
+ include multiple files. They will be included in the order specified.
`--reference-odt=`*FILE*
: Use the specified file as a style reference in producing an ODT.
@@ -434,7 +446,12 @@ Options affecting specific writers
reference docx is specified on the command line, pandoc will look
for a file `reference.docx` in the user data directory (see
`--data-dir`). If this is not found either, sensible defaults will be
- used.
+ used. The following styles are used by pandoc: [paragraph]
+ Normal, Title, Authors, Date, Heading 1, Heading 2, Heading 3,
+ Heading 4, Heading 5, Block Quote, Definition Term, Definition,
+ Body Text, Table Caption, Picture Caption; [character] Default
+ Paragraph Font, Body Text Char, Verbatim Char, Footnote Reference,
+ Hyperlink.
`--epub-stylesheet=`*FILE*
: Use the specified CSS file to style the EPUB. If no stylesheet
@@ -500,8 +517,8 @@ Options affecting specific writers
The default is `pdflatex`. If the engine is not in your PATH,
the full path of the engine may be specified here.
-Citations
----------
+Citation rendering
+------------------
`--bibliography=`*FILE*
: Specify bibliography database to be used in resolving
@@ -587,7 +604,7 @@ Math rendering in HTML
`--gladtex`
: Enclose TeX math in `<eq>` tags in HTML output. These can then
be processed by [gladTeX] to produce links to images of the typeset
- formulas.
+ formulas.
`--mimetex`[=*URL*]
: Render TeX math using the [mimeTeX] CGI script. If *URL* is not
@@ -624,8 +641,8 @@ Options for wrapper scripts
[LaTeXMathML]: http://math.etsu.edu/LaTeXMathML/
[jsMath]: http://www.math.union.edu/~dpvc/jsmath/
[MathJax]: http://www.mathjax.org/
-[gladTeX]: http://www.math.uio.no/~martingu/gladtex/index.html
-[mimeTeX]: http://www.forkosh.com/mimetex.html
+[gladTeX]: http://ans.hsh.no/home/mgg/gladtex/
+[mimeTeX]: http://www.forkosh.com/mimetex.html
[CSL]: http://CitationStyles.org
Templates
@@ -754,8 +771,12 @@ Pandoc's markdown
Pandoc understands an extended and slightly revised version of
John Gruber's [markdown] syntax. This document explains the syntax,
noting differences from standard markdown. Except where noted, these
-differences can be suppressed by specifying the `--strict` command-line
-option.
+differences can be suppressed by using the `markdown_strict` format instead
+of `markdown`. An extensions can be enabled by adding `+EXTENSION`
+to the format name and disabled by adding `-EXTENSION`. For example,
+`markdown_strict+footnotes` is strict markdown with footnotes
+enabled, while `markdown-footnotes-pipe_tables` is pandoc's
+markdown without footnotes or pipe tables.
Philosophy
----------
@@ -784,8 +805,11 @@ Paragraphs
A paragraph is one or more lines of text followed by one or more blank line.
Newlines are treated as spaces, so you can reflow your paragraphs as you like.
-If you need a hard line break, put two or more spaces at the end of a line,
-or type a backslash followed by a newline.
+If you need a hard line break, put two or more spaces at the end of a line.
+
+**Extension: `escaped_line_breaks`**
+
+A backslash followed by a newline is also a hard line break.
Headers
-------
@@ -821,6 +845,8 @@ As with setext-style headers, the header text can contain formatting:
# A level-one header with a [link](/url) and *emphasis*
+**Extension: `blank_before_header`**
+
Standard markdown syntax does not require a blank line before a header.
Pandoc does require this (except, of course, at the beginning of the
document). The reason for the requirement is that it is all too easy for a
@@ -833,7 +859,7 @@ wrapping). Consider, for example:
### Header identifiers in HTML, LaTeX, and ConTeXt ###
-*Pandoc extension*.
+**Extension**
Each header element in pandoc's HTML and ConTeXt output is given a
unique identifier. This identifier is based on the text of the header.
@@ -913,12 +939,14 @@ other block quotes. That is, block quotes can be nested:
>
> > A block quote within a block quote.
+**Extension: `blank_line_before_blockquote`**
+
Standard markdown syntax does not require a blank line before a block
quote. Pandoc does require this (except, of course, at the beginning of the
document). The reason for the requirement is that it is all too easy for a
`>` to end up at the beginning of a line by accident (perhaps through line
-wrapping). So, unless `--strict` is used, the following does not produce
-a nested block quote in pandoc:
+wrapping). So, unless the `markdown_strict` format is used, the following does
+not produce a nested block quote in pandoc:
> This is a block quote.
>> Nested.
@@ -943,12 +971,12 @@ of the verbatim text, and is removed in the output.
Note: blank lines in the verbatim text need not begin with four spaces.
-### Delimited code blocks ###
+### Fenced code blocks ###
-*Pandoc extension*.
+**Extension: `fenced_code_blocks`**
In addition to standard indented code blocks, Pandoc supports
-*delimited* code blocks. These begin with a row of three or more
+*fenced* code blocks. These begin with a row of three or more
tildes (`~`) or backticks (`` ` ``) and end with a row of tildes or
backticks that must be at least as long as the starting row. Everything
between these lines is treated as code. No indentation is necessary:
@@ -959,7 +987,7 @@ between these lines is treated as code. No indentation is necessary:
}
~~~~~~~
-Like regular code blocks, delimited code blocks must be separated
+Like regular code blocks, fenced code blocks must be separated
from surrounding text by blank lines.
If the code itself contains a row of tildes or backticks, just use a longer
@@ -1126,7 +1154,7 @@ and this one:
7. two
1. three
-*Pandoc extension*.
+**Extension: `fancy_lists`**
Unlike standard markdown, Pandoc allows ordered list items to be marked
with uppercase and lowercase letters and roman numerals, in addition to
@@ -1151,6 +1179,8 @@ capital letter with a period, by at least two spaces.[^2]
(C\) 2007 Joe Smith
+**Extension: `startnum`**
+
Pandoc also pays attention to the type of list marker used, and to the
starting number, and both of these are preserved where possible in the
output format. Thus, the following yields a list with numbers followed
@@ -1181,7 +1211,7 @@ If default list markers are desired, use `#.`:
### Definition lists ###
-*Pandoc extension*.
+**Extension: `definition_lists`**
Pandoc supports definition lists, using a syntax inspired by
[PHP Markdown Extra] and [reStructuredText]:[^3]
@@ -1226,7 +1256,7 @@ definition and the next term:
### Numbered example lists ###
-*Pandoc extension*.
+**Extension: `example_lists`**
The special list marker `@` can be used for sequentially numbered
examples. The first list item with a `@` marker will be numbered '1',
@@ -1255,7 +1285,7 @@ or hyphens.
### Compact and loose lists ###
Pandoc behaves differently from `Markdown.pl` on some "edge
-cases" involving lists. Consider this source:
+cases" involving lists. Consider this source:
+ First
+ Second:
@@ -1272,7 +1302,7 @@ around "Third". Pandoc follows a simple rule: if the text is followed by
a blank line, it is treated as a paragraph. Since "Second" is followed
by a list, and not a blank line, it isn't treated as a paragraph. The
fact that the list is followed by a blank line is irrelevant. (Note:
-Pandoc works this way even when the `--strict` option is specified. This
+Pandoc works this way even when the `markdown_strict` format is specified. This
behavior is consistent with the official markdown syntax description,
even though it is different from that of `Markdown.pl`.)
@@ -1328,12 +1358,16 @@ A line containing a row of three or more `*`, `-`, or `_` characters
Tables
------
-*Pandoc extension*.
+**Extension: `simple_tables`, `multiline_tables`, `grid_tables`,
+`pipe_tables`, `table_captions`**
+
+Four kinds of tables may be used. The first three kinds presuppose the use of
+a fixed-width font, such as Courier. The fourth kind can be used with
+proportionally spaced fonts, as it does not require lining up columns.
-Three kinds of tables may be used. All three kinds presuppose the use of
-a fixed-width font, such as Courier.
+### Simple tables
-**Simple tables** look like this:
+Simple tables look like this:
Right Left Center Default
------- ------ ---------- -------
@@ -1349,7 +1383,7 @@ to the dashed line below it:[^4]
- If the dashed line is flush with the header text on the right side
but extends beyond it on the left, the column is right-aligned.
- - If the dashed line is flush with the header text on the left side
+ - If the dashed line is flush with the header text on the left side
but extends beyond it on the right, the column is left-aligned.
- If the dashed line extends beyond the header text on both sides,
the column is centered.
@@ -1378,7 +1412,9 @@ When headers are omitted, column alignments are determined on the basis
of the first line of the table body. So, in the tables above, the columns
would be right, left, center, and right aligned, respectively.
-**Multiline tables** allow headers and table rows to span multiple lines
+### Multiline tables
+
+Multiline tables allow headers and table rows to span multiple lines
of text (but cells that span multiple columns or rows of the table are
not supported). Here is an example:
@@ -1426,7 +1462,9 @@ It is possible for a multiline table to have just one row, but the row
should be followed by a blank line (and then the row of dashes that ends
the table), or the table may be interpreted as a simple table.
-**Grid tables** look like this:
+### Grid tables
+
+Grid tables look like this:
: Sample grid table.
@@ -1448,11 +1486,55 @@ columns or rows. Grid tables can be created easily using [Emacs table mode].
[Emacs table mode]: http://table.sourceforge.net/
+### Pipe tables
+
+Pipe tables look like this:
+
+ | Right | Left | Default | Center |
+ |------:|:-----|---------|:------:|
+ | 12 | 12 | 12 | 12 |
+ | 123 | 123 | 123 | 123 |
+ | 1 | 1 | 1 | 1 |
+
+ : Demonstration of simple table syntax.
+
+The syntax is the same as in [PHP markdown extra]. The beginning and
+ending pipe characters are optional, but pipes are required between all
+columns. The colons indicate column alignment as shown. The header
+can be omitted, but the horizontal line must still be included, as
+it defines column alignments.
+
+Since the pipes indicate column boundaries, columns need not be vertically
+aligned, as they are in the above example. So, this is a perfectly
+legal (though ugly) pipe table:
+
+ fruit| price
+ -----|-----:
+ apple|2.05
+ pear|1.37
+ orange|3.09
+
+The cells of pipe tables cannot contain block elements like paragraphs
+and lists, and cannot span multiple lines.
+
+ [PHP markdown extra]: http://michelf.ca/projects/php-markdown/extra/#table
+
+Note: Pandoc also recognizes pipe tables of the following
+form, as can produced by Emacs' orgtbl-mode:
+
+ | One | Two |
+ |-----+-------|
+ | my | table |
+ | is | nice |
+
+The difference is that `+` is used instead of `|`. Other orgtbl features
+are not supported. In particular, to get non-default column alignment,
+you'll need to add colons as above.
Title block
-----------
-*Pandoc extension*.
+**Extension: `pandoc_title_block`**
If the file begins with a title block
@@ -1532,6 +1614,8 @@ will also have "Version 4.0" in the header.
Backslash escapes
-----------------
+**Extension: `all_symbols_escapable`**
+
Except inside a code block or inline code, any punctuation or space
character preceded by a backslash will be treated literally, even if it
would normally indicate formatting. Thus, for example, if one writes
@@ -1551,8 +1635,8 @@ which allows only the following characters to be backslash-escaped:
\`*_{}[]()>#+-.!
-(However, if the `--strict` option is supplied, the standard
-markdown rule will be used.)
+(However, if the `markdown_strict` format is used, the standard markdown rule
+will be used.)
A backslash-escaped space is parsed as a nonbreaking space. It will
appear in TeX output as `~` and in HTML and XML as `\&#160;` or
@@ -1569,7 +1653,7 @@ Backslash escapes do not work in verbatim contexts.
Smart punctuation
-----------------
-*Pandoc extension*.
+**Extension**
If the `--smart` option is specified, pandoc will produce typographically
correct output, converting straight quotes to curly quotes, `---` to
@@ -1598,6 +1682,8 @@ will not trigger emphasis:
This is * not emphasized *, and \*neither is this\*.
+**Extension: `intraword_underscores`**
+
Because `_` is sometimes used inside words and identifiers,
pandoc does not interpret a `_` surrounded by alphanumeric
characters as an emphasis marker. If you want to emphasize
@@ -1608,7 +1694,7 @@ just part of a word, use `*`:
### Strikeout ###
-*Pandoc extension*.
+**Extension: `strikeout`**
To strikeout a section of text with a horizontal line, begin and end it
with `~~`. Thus, for example,
@@ -1618,7 +1704,7 @@ with `~~`. Thus, for example,
### Superscripts and subscripts ###
-*Pandoc extension*.
+**Extension: `superscript`, `subscript`**
Superscripts may be written by surrounding the superscripted text by `^`
characters; subscripts may be written by surrounding the subscripted
@@ -1656,15 +1742,17 @@ work in verbatim contexts:
This is a backslash followed by an asterisk: `\*`.
+**Extension: `inline_code_attributes`**
+
Attributes can be attached to verbatim text, just as with
-[delimited code blocks](#delimited-code-blocks):
+[fenced code blocks](#fenced-code-blocks):
`<$>`{.haskell}
Math
----
-*Pandoc extension*.
+**Extension: `tex_math_dollars`**
Anything between two `$` characters will be treated as TeX math. The
opening `$` must have a character immediately to its right, while the
@@ -1710,7 +1798,12 @@ Docbook
Docx
~ It will be rendered using OMML math markup.
-HTML, Slidy, Slideous, DZSlides, S5, EPUB
+FictionBook2
+ ~ If the `--webtex` option is used, formulas are rendered as images
+ using Google Charts or other compatible web service, downloaded
+ and embedded in the e-book. Otherwise, they will appear verbatim.
+
+HTML, Slidy, DZSlides, S5, EPUB
~ The way math is rendered in HTML will depend on the
command-line options selected:
@@ -1753,19 +1846,27 @@ HTML, Slidy, Slideous, DZSlides, S5, EPUB
with the URL provided. If no URL is specified, the Google Chart
API will be used (`http://chart.apis.google.com/chart?cht=tx&chl=`).
+ 7. If the `--mathjax` option is used, TeX math will be displayed
+ between `\(...\)` (for inline math) or `\[...\]` (for display
+ math) and put in `<span>` tags with class `math`.
+ The [MathJax] script will be used to render it as formulas.
Raw HTML
--------
+**Extenion: `raw_html`**
+
Markdown allows you to insert raw HTML (or DocBook) anywhere in a document
(except verbatim contexts, where `<`, `>`, and `&` are interpreted
-literally).
+literally). (Techncially this is not an extension, since standard
+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, and Textile output, and suppressed in other formats.
+DZSlides, EPUB, Markdown, and Textile output, and suppressed in other
+formats.
-*Pandoc extension*.
+**Extension: `markdown_in_html_blocks`**
Standard markdown allows you to include HTML "blocks": blocks
of HTML between balanced tags that are separated from the surrounding text
@@ -1773,8 +1874,8 @@ with blank lines, and start and end at the left margin. Within
these blocks, everything is interpreted as HTML, not markdown;
so (for example), `*` does not signify emphasis.
-Pandoc behaves this way when `--strict` is specified; but by default,
-pandoc interprets material between HTML block tags as markdown.
+Pandoc behaves this way when the `markdown_strict` format is used; but
+by default, pandoc interprets material between HTML block tags as markdown.
Thus, for example, Pandoc will turn
<table>
@@ -1806,7 +1907,7 @@ from being interpreted as markdown.
Raw TeX
-------
-*Pandoc extension*.
+**Extension: `raw_tex`**
In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be
included in a document. Inline TeX commands will be preserved and passed
@@ -1820,7 +1921,7 @@ Note that in LaTeX environments, like
\begin{tabular}{|l|l|}\hline
Age & Frequency \\ \hline
18--25 & 15 \\
- 26--35 & 33 \\
+ 26--35 & 33 \\
36--45 & 22 \\ \hline
\end{tabular}
@@ -1830,7 +1931,10 @@ LaTeX, not as markdown.
Inline LaTeX is ignored in output formats other than Markdown, LaTeX,
and ConTeXt.
-### Macros ###
+LaTeX macros
+------------
+
+**Extension: `latex_macros`**
For output formats other than LaTeX, pandoc will parse LaTeX `\newcommand` and
`\renewcommand` definitions and apply the resulting macros to all LaTeX
@@ -1858,6 +1962,10 @@ will become a link:
<http://google.com>
<sam@green.eggs.ham>
+**Extension: `autolink_code_spans`**
+
+Pandoc will render autolinked URLs and email addresses as
+inline code.
### Inline links ###
@@ -1880,7 +1988,6 @@ before or after the link).
The link consists of link text in square brackets, followed by a label in
square brackets. (There can be space between the two.) The link definition
-must begin at the left margin or indented no more than three spaces. It
consists of the bracketed label, followed by a colon and a space, followed by
the URL, and optionally (after a space) a link title either in quotes or in
parentheses.
@@ -1914,6 +2021,16 @@ empty, or omitted entirely:
[my website]: http://foo.bar.baz
+Note: In `Markdown.pl` and most other markdown implementations,
+reference link definitions cannot occur in nested constructions
+such as list items or block quotes. Pandoc lifts this arbitrary
+seeming restriction. So the following is fine in pandoc, though
+not in most other implementations:
+
+ > My block [quote].
+ >
+ > [quote]: /foo
+
### Internal links
To link to another section of the same document, use the automatically
@@ -1946,7 +2063,7 @@ The link text will be used as the image's alt text:
### Pictures with captions ###
-*Pandoc extension*.
+**Extension**
An image occurring by itself in a paragraph will be rendered as
a figure with a caption.[^5] (In LaTeX, a figure environment will be
@@ -1964,13 +2081,13 @@ If you just want a regular inline image, just make sure it is not
the only thing in the paragraph. One way to do this is to insert a
nonbreaking space after the image:
- ![This image won't be a figure](/url/of/image.png)\
+ ![This image won't be a figure](/url/of/image.png)\
Footnotes
---------
-*Pandoc extension*.
+**Extension: `footnotes`**
Pandoc's markdown allows footnotes, using the following syntax:
@@ -1980,7 +2097,7 @@ Pandoc's markdown allows footnotes, using the following syntax:
[^longnote]: Here's one with multiple blocks.
- Subsequent paragraphs are indented to show that they
+ Subsequent paragraphs are indented to show that they
belong to the previous footnote.
{ some.code }
@@ -2001,6 +2118,8 @@ The footnotes themselves need not be placed at the end of the
document. They may appear anywhere except inside other block elements
(lists, block quotes, tables, etc.).
+**Extension: `inline_notes`**
+
Inline footnotes are also allowed (though, unlike regular notes,
they cannot contain multiple paragraphs). The syntax is as follows:
@@ -2014,7 +2133,7 @@ Inline and regular footnotes may be mixed freely.
Citations
---------
-*Pandoc extension*.
+**Extension: `citations`**
Pandoc can automatically generate citations and a bibliography in a number of
styles (using Andrea Rossato's `hs-citeproc`). In order to use this feature,
@@ -2078,6 +2197,60 @@ document with an appropriate header:
The bibliography will be inserted after this header.
+Non-pandoc extensions
+=====================
+
+The following markdown syntax extensions are not enabled by default
+in pandoc, but may be enabled by adding `+EXTENSION` to the format
+name, where `EXTENSION` is the name of the extension. Thus, for
+example, `markdown+hard_line_breaks` is markdown with hard line breaks.
+
+**Extension: `hard_line_breaks`**\
+Causes all newlines within a paragraph to be interpreted as hard line
+breaks instead of spaces.
+
+**Extension: `tex_math_single_backslash`**\
+Causes anything between `\(` and `\)` to be interpreted as inline
+TeX math, and anything between `\[` and `\]` to be interpreted
+as display TeX math. Note: a drawback of this extension is that
+it precludes escaping `(` and `[`.
+
+**Extension: `tex_math_double_backslash`**\
+Causes anything between `\\(` and `\\)` to be interpreted as inline
+TeX math, and anything between `\\[` and `\\]` to be interpreted
+as display TeX math.
+
+**Extension: `markdown_attribute`**\
+Causes the attribute `markdown=1` to be added to all block-level
+HTML tags that might contain markdown. In pandoc, material inside
+block-level tags is interpreted a markdown by default, but in some
+other implementations, the `markdown=1` tag is needed.
+
+**Extension: `mmd_title_block`**\
+Enables a [MultiMarkdown] style title block at the top of
+the document, for example:
+
+ Title: My title
+ Author: John Doe
+ Date: September 1, 2008
+ Comment: This is a sample mmd title block, with
+ a field spanning multiple lines.
+
+See the MultiMarkdown documentation for details. Note that only title,
+author, and date are recognized; other fields are simply ignored by
+pandoc. If `pandoc_title_block` is enabled, it will take precedence over
+`mmd_title_block`.
+
+ [MultiMarkdown]: http://fletcherpenney.net/multimarkdown/
+
+**Extension: `abbrevations`**\
+Parses PHP Markdown Extra abbreviation keys, like
+
+ *[HTML]: Hyper Text Markup Language
+
+Note that the pandoc document model does not support
+abbreviations, so if this extension is enabled, abbreviation keys are
+simply skipped (as opposed to being parsed as paragraphs).
Producing slide shows with Pandoc
=================================
@@ -2229,9 +2402,9 @@ Literate Haskell support
========================
If you append `+lhs` to an appropriate input or output format (`markdown`,
-`rst`, or `latex` for input or output; `beamer`, `html` or `html5` for
-output only), pandoc will treat the document as literate Haskell source.
-This means that
+`mardkown_strict`, `rst`, or `latex` for input or output; `beamer`,
+`html` or `html5` for output only), pandoc will treat the document as
+literate Haskell source. This means that
- In markdown input, "bird track" sections will be parsed as Haskell
code rather than block quotations. Text between `\begin{code}`
@@ -2282,7 +2455,8 @@ Andrea Rossato, Eric Kow, infinity0x, Luke Plant, shreevatsa.public,
Puneeth Chaganti, Paul Rivier, rodja.trappe, Bradley Kuhn, thsutton,
Nathan Gass, Jonathan Daugherty, Jérémy Bobbio, Justin Bogner, qerub,
Christopher Sawicki, Kelsey Hightower, Masayoshi Takahashi, Antoine
-Latter, Ralf Stephan, Eric Seidel, B. Scott Michel, Gavin Beatty.
+Latter, Ralf Stephan, Eric Seidel, B. Scott Michel, Gavin Beatty,
+Sergey Astanin.
[markdown]: http://daringfireball.net/projects/markdown/
[reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html
@@ -2294,10 +2468,10 @@ Latter, Ralf Stephan, Eric Seidel, B. Scott Michel, Gavin Beatty.
[XHTML]: http://www.w3.org/TR/xhtml1/
[LaTeX]: http://www.latex-project.org/
[beamer]: http://www.tex.ac.uk/CTAN/macros/latex/contrib/beamer
-[ConTeXt]: http://www.pragma-ade.nl/
+[ConTeXt]: http://www.pragma-ade.nl/
[RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format
[DocBook XML]: http://www.docbook.org/
-[OpenDocument XML]: http://opendocument.xml.org/
+[OpenDocument XML]: http://opendocument.xml.org/
[ODT]: http://en.wikipedia.org/wiki/OpenDocument
[Textile]: http://redcloth.org/textile
[MediaWiki markup]: http://www.mediawiki.org/wiki/Help:Formatting
@@ -2312,3 +2486,4 @@ Latter, Ralf Stephan, Eric Seidel, B. Scott Michel, Gavin Beatty.
[ISO 8601 format]: http://www.w3.org/TR/NOTE-datetime
[Word docx]: http://www.microsoft.com/interop/openup/openxml/default.aspx
[PDF]: http://www.adobe.com/pdf/
+[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
diff --git a/Setup.hs b/Setup.hs
index 56df0045d..6d039823e 100644
--- a/Setup.hs
+++ b/Setup.hs
@@ -9,7 +9,8 @@ import Distribution.Verbosity ( Verbosity, silent )
import Distribution.Simple.GHC (ghcPackageDbOptions)
import Distribution.Simple.InstallDirs (mandir, bindir, CopyDest (NoCopyDest))
import Distribution.Simple.Utils (installOrdinaryFiles)
-import Control.Exception ( bracket_ )
+import Prelude hiding (catch)
+import Control.Exception ( bracket_, catch )
import Control.Monad ( unless )
import System.Process ( rawSystem, runCommand, waitForProcess )
import System.FilePath ( (</>) )
@@ -23,8 +24,7 @@ import Data.List ( (\\) )
main :: IO ()
main = do
defaultMainWithHooks $ simpleUserHooks {
- runTests = runTestSuite
- , postBuild = makeManPages
+ postBuild = makeManPages
, postCopy = \ _ flags pkg lbi ->
installManpages pkg lbi (fromFlag $ copyVerbosity flags)
(fromFlag $ copyDest flags)
@@ -33,18 +33,6 @@ main = do
}
exitWith ExitSuccess
--- | Run test suite.
-runTestSuite :: Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO a
-runTestSuite args _ pkg lbi = do
- let testDir = buildDir lbi </> "test-pandoc"
- testDir' <- canonicalizePath testDir
- let testArgs = "--timeout=5" : concatMap (\arg -> ["-t",arg]) args
- if any id [buildable (buildInfo exe) | exe <- executables pkg, exeName exe == "test-pandoc"]
- then inDirectory "tests" $ rawSystem (testDir' </> "test-pandoc") testArgs >>= exitWith
- else do
- putStrLn "Build pandoc with the 'tests' flag to run tests"
- exitWith $ ExitFailure 3
-
-- | Build man pages from markdown sources in man/
makeManPages :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
makeManPages _ flags _ lbi = do
diff --git a/benchmark/benchmark-pandoc.hs b/benchmark/benchmark-pandoc.hs
new file mode 100644
index 000000000..728e45b56
--- /dev/null
+++ b/benchmark/benchmark-pandoc.hs
@@ -0,0 +1,46 @@
+import Text.Pandoc
+import Text.Pandoc.Shared (readDataFile, normalize)
+import Criterion.Main
+import Criterion.Config
+import Text.JSON.Generic
+import System.Environment (getArgs)
+import Data.Monoid
+
+readerBench :: Pandoc
+ -> (String, ReaderOptions -> String -> Pandoc)
+ -> Benchmark
+readerBench doc (name, reader) =
+ let writer = case lookup name writers of
+ Just (PureStringWriter w) -> w
+ _ -> error $ "Could not find writer for " ++ name
+ inp = writer def{ writerWrapText = True } doc
+ -- we compute the length to force full evaluation
+ getLength (Pandoc (Meta a b c) d) =
+ length a + length b + length c + length d
+ in bench (name ++ " reader") $ whnf (getLength .
+ reader def{ readerSmart = True }) inp
+
+writerBench :: Pandoc
+ -> (String, WriterOptions -> Pandoc -> String)
+ -> Benchmark
+writerBench doc (name, writer) = bench (name ++ " writer") $ nf
+ (writer def{ writerWrapText = True }) doc
+
+normalizeBench :: Pandoc -> [Benchmark]
+normalizeBench doc = [ bench "normalize - with" $ nf (encodeJSON . normalize) doc
+ , bench "normalize - without" $ nf encodeJSON doc
+ ]
+
+main :: IO ()
+main = do
+ args <- getArgs
+ (conf,_) <- parseArgs defaultConfig{ cfgSamples = Last $ Just 20 } defaultOptions args
+ inp <- readDataFile (Just ".") "README"
+ inp2 <- readDataFile (Just ".") "tests/testsuite.txt"
+ let opts = def{ readerSmart = True }
+ let doc = readMarkdown opts $ inp ++ unlines (drop 3 $ lines inp2)
+ let readerBs = map (readerBench doc) readers
+ let writers' = [(n,w) | (n, PureStringWriter w) <- writers]
+ defaultMainWith conf (return ()) $
+ map (writerBench doc) writers' ++ readerBs ++ normalizeBench doc
+
diff --git a/pandoc.cabal b/pandoc.cabal
index 139e576ec..e999f1b80 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,5 +1,5 @@
Name: pandoc
-Version: 1.9.4.2
+Version: 1.10
Cabal-Version: >= 1.10
Build-Type: Custom
License: GPL
@@ -20,7 +20,7 @@ Description: Pandoc is a Haskell library for converting from one markup
markdown, reStructuredText, HTML, LaTeX, ConTeXt, Docbook,
OpenDocument, ODT, Word docx, RTF, MediaWiki, Textile,
groff man pages, plain text, Emacs Org-Mode, AsciiDoc, EPUB,
- and S5, Slidy and Slideous HTML slide shows.
+ FictionBook2, and S5, Slidy and Slideous HTML slide shows.
.
Pandoc extends standard markdown syntax with footnotes,
embedded LaTeX, definition lists, tables, and other
@@ -96,8 +96,6 @@ Extra-Source-Files:
-- generated man pages (produced post-build)
man/man1/pandoc.1,
man/man5/pandoc_markdown.5,
- -- benchmarks
- Benchmark.hs,
-- tests
tests/bodybg.gif,
tests/docbook-reader.docbook
@@ -174,7 +172,9 @@ Extra-Source-Files:
tests/lhs-test.latex+lhs,
tests/lhs-test.html,
tests/lhs-test.html+lhs,
- tests/lhs-test.fragment.html+lhs
+ tests/lhs-test.fragment.html+lhs,
+ tests/pipe-tables.txt,
+ tests/pipe-tables.native
Extra-Tmp-Files: man/man1/pandoc.1,
man/man5/pandoc_markdown.5
@@ -188,9 +188,6 @@ Flag executable
Flag library
Description: Build the pandoc library.
Default: True
-Flag tests
- Description: Build test-pandoc.
- Default: False
Flag blaze_html_0_5
Description: Use blaze-html 0.5 and blaze-markup 0.5
Default: False
@@ -217,12 +214,13 @@ Library
random >= 1 && < 1.1,
extensible-exceptions >= 0.1 && < 0.2,
citeproc-hs >= 0.3.4 && < 0.4,
- pandoc-types >= 1.9.0.2 && < 1.10,
+ pandoc-types >= 1.10 && < 1.11,
json >= 0.4 && < 0.6,
tagsoup >= 0.12.5 && < 0.13,
base64-bytestring >= 0.1 && < 0.2,
zlib >= 0.5 && < 0.6,
highlighting-kate >= 0.5.1 && < 0.6,
+ data-default >= 0.4 && < 0.6,
temporary >= 1.1 && < 1.2
if flag(blaze_html_0_5)
build-depends:
@@ -256,6 +254,7 @@ Library
-- END DUPLICATED SECTION
Exposed-Modules: Text.Pandoc,
+ Text.Pandoc.Options,
Text.Pandoc.Pretty,
Text.Pandoc.Shared,
Text.Pandoc.Parsing,
@@ -286,6 +285,7 @@ Library
Text.Pandoc.Writers.ODT,
Text.Pandoc.Writers.Docx,
Text.Pandoc.Writers.EPUB,
+ Text.Pandoc.Writers.FB2,
Text.Pandoc.PDF,
Text.Pandoc.Templates,
Text.Pandoc.Biblio,
@@ -325,12 +325,13 @@ Executable pandoc
random >= 1 && < 1.1,
extensible-exceptions >= 0.1 && < 0.2,
citeproc-hs >= 0.3.4 && < 0.4,
- pandoc-types >= 1.9.0.2 && < 1.10,
+ pandoc-types >= 1.10 && < 1.11,
json >= 0.4 && < 0.6,
tagsoup >= 0.12.5 && < 0.13,
base64-bytestring >= 0.1 && < 0.2,
zlib >= 0.5 && < 0.6,
highlighting-kate >= 0.5.1 && < 0.6,
+ data-default >= 0.4 && < 0.6,
temporary >= 1.1 && < 1.2
if flag(blaze_html_0_5)
build-depends:
@@ -369,47 +370,42 @@ Executable pandoc
else
Buildable: False
-Executable test-pandoc
- Main-Is: test-pandoc.hs
- -- Note: the following is duplicated in all stanzas.
- -- It needs to be duplicated because of the library & executable flags.
- -- BEGIN DUPLICATED SECTION
- Build-Depends: containers >= 0.1 && < 0.5,
- parsec >= 3.1 && < 3.2,
- mtl >= 1.1 && < 2.2,
- network >= 2 && < 2.4,
- filepath >= 1.1 && < 1.4,
- process >= 1 && < 1.2,
- directory >= 1 && < 1.2,
- bytestring >= 0.9 && < 1.0,
- zip-archive >= 0.1.1.7 && < 0.2,
- utf8-string >= 0.3 && < 0.4,
- old-locale >= 1 && < 1.1,
- time >= 1.2 && < 1.5,
- HTTP >= 4000.0.5 && < 4000.3,
- texmath >= 0.6.0.2 && < 0.7,
- xml >= 1.3.12 && < 1.4,
- random >= 1 && < 1.1,
- extensible-exceptions >= 0.1 && < 0.2,
- citeproc-hs >= 0.3.4 && < 0.4,
- pandoc-types >= 1.9.0.2 && < 1.10,
- json >= 0.4 && < 0.6,
- tagsoup >= 0.12.5 && < 0.13,
- base64-bytestring >= 0.1 && < 0.2,
- zlib >= 0.5 && < 0.6,
- highlighting-kate >= 0.5.1 && < 0.6,
- temporary >= 1.1 && < 1.2
- if flag(blaze_html_0_5)
- build-depends:
- blaze-html >= 0.5 && < 0.6,
- blaze-markup >= 0.5.1 && < 0.6
- else
- build-depends:
- blaze-html >= 0.4.3.0 && < 0.5
+Test-Suite test-pandoc
+ Type: exitcode-stdio-1.0
+ Main-Is: test-pandoc.hs
+ Hs-Source-Dirs: tests
if impl(ghc >= 6.10)
Build-depends: base >= 4 && < 5, syb >= 0.1 && < 0.4
else
Build-depends: base >= 3 && < 4
+ Build-Depends: pandoc,
+ pandoc-types >= 1.10 && < 1.11,
+ utf8-string >= 0.3 && < 0.4,
+ bytestring >= 0.9 && < 1.0,
+ directory >= 1 && < 1.2,
+ filepath >= 1.1 && < 1.4,
+ process >= 1 && < 1.2,
+ Diff,
+ test-framework >= 0.3 && < 0.7,
+ test-framework-hunit >= 0.2 && < 0.3,
+ test-framework-quickcheck2 >= 0.2.9 && < 0.3,
+ QuickCheck >= 2.4 && < 2.6,
+ HUnit >= 1.2 && < 1.3,
+ template-haskell >= 2.4 && < 2.8,
+ containers >= 0.1 && < 0.5,
+ ansi-terminal == 0.5.*
+ Other-Modules: Tests.Old
+ Tests.Helpers
+ Tests.Arbitrary
+ Tests.Shared
+ Tests.Readers.LaTeX
+ Tests.Readers.Markdown
+ Tests.Readers.RST
+ Tests.Writers.Native
+ Tests.Writers.ConTeXt
+ Tests.Writers.HTML
+ Tests.Writers.Markdown
+ Tests.Writers.LaTeX
if impl(ghc >= 7.0.1)
Ghc-Options: -O2 -rtsopts -Wall -fno-warn-unused-do-bind -dno-debug-output
else
@@ -417,43 +413,29 @@ Executable test-pandoc
Ghc-Options: -O2 -Wall -fno-warn-unused-do-bind -dno-debug-output
else
Ghc-Options: -O2 -Wall
- if impl(ghc >= 7.0.1)
- Ghc-Prof-Options: -auto-all -caf-all -rtsopts
+ if impl(ghc >= 7)
+ cpp-options: -D_LIT=lit
else
- Ghc-Prof-Options: -auto-all -caf-all
+ cpp-options: -D_LIT=$lit
Default-Language: Haskell98
- Default-Extensions: CPP
- Other-Extensions: PatternGuards, OverloadedStrings,
- ScopedTypeVariables, GeneralizedNewtypeDeriving,
- RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances,
- FlexibleInstances
- Hs-Source-Dirs: src
- -- END DUPLICATED SECTION
- if !flag(tests)
- Buildable: False
+ Default-Extensions: CPP, TemplateHaskell, QuasiQuotes
+
+benchmark benchmark-pandoc
+ Type: exitcode-stdio-1.0
+ Main-Is: benchmark-pandoc.hs
+ Hs-Source-Dirs: benchmark
+ if impl(ghc >= 6.10)
+ Build-depends: base >= 4 && < 5, syb >= 0.1 && < 0.4
else
- Buildable: True
- if impl(ghc >= 7)
- cpp-options: -D_LIT=lit
+ Build-depends: base >= 3 && < 4
+ Build-Depends: pandoc,
+ criterion >= 0.5 && < 0.7,
+ json >= 0.4 && < 0.6
+ if impl(ghc >= 7.0.1)
+ Ghc-Options: -O2 -rtsopts -Wall -fno-warn-unused-do-bind -dno-debug-output
+ else
+ if impl(ghc >= 6.12)
+ Ghc-Options: -O2 -Wall -fno-warn-unused-do-bind -dno-debug-output
else
- cpp-options: -D_LIT=$lit
- Other-Extensions: TemplateHaskell, QuasiQuotes
- Build-Depends: Diff, test-framework >= 0.3 && < 0.7,
- test-framework-hunit >= 0.2 && < 0.3,
- test-framework-quickcheck2 >= 0.2.9 && < 0.3,
- QuickCheck >= 2.4 && < 2.6,
- HUnit >= 1.2 && < 1.3,
- template-haskell >= 2.4 && < 2.8,
- ansi-terminal == 0.5.*
- Other-Modules: Tests.Old
- Tests.Helpers
- Tests.Arbitrary
- Tests.Shared
- Tests.Readers.LaTeX
- Tests.Readers.Markdown
- Tests.Readers.RST
- Tests.Writers.Native
- Tests.Writers.ConTeXt
- Tests.Writers.HTML
- Tests.Writers.Markdown
- Tests.Writers.LaTeX
+ Ghc-Options: -O2 -Wall
+ Default-Language: Haskell98
diff --git a/src/Text/Pandoc.hs b/src/Text/Pandoc.hs
index 432a5c2ba..33706816e 100644
--- a/src/Text/Pandoc.hs
+++ b/src/Text/Pandoc.hs
@@ -20,10 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
+ Stability : alpha
Portability : portable
This helper module exports the main writers, readers, and data
@@ -43,9 +43,8 @@ inline links:
>
> markdownToRST :: String -> String
> markdownToRST =
-> (writeRST defaultWriterOptions {writerReferenceLinks = True}) .
-> readMarkdown defaultParserState
->
+> (writeRST def {writerReferenceLinks = True}) . readMarkdown def
+>
> main = getContents >>= putStrLn . markdownToRST
Note: all of the readers assume that the input text has @'\n'@
@@ -55,11 +54,13 @@ you should remove @'\r'@ characters using @filter (/='\r')@.
-}
module Text.Pandoc
- (
+ (
-- * Definitions
module Text.Pandoc.Definition
-- * Generics
, module Text.Pandoc.Generic
+ -- * Options
+ , module Text.Pandoc.Options
-- * Lists of readers and writers
, readers
, writers
@@ -71,15 +72,8 @@ module Text.Pandoc
, readTextile
, readDocBook
, readNative
- -- * Parser state used in readers
- , ParserState (..)
- , defaultParserState
- , ParserContext (..)
- , QuoteContext (..)
- , KeyTable
- , NoteTable
- , HeaderType (..)
-- * Writers: converting /from/ Pandoc format
+ , Writer (..)
, writeNative
, writeMarkdown
, writePlain
@@ -98,19 +92,16 @@ module Text.Pandoc
, writeODT
, writeDocx
, writeEPUB
+ , writeFB2
, writeOrg
, writeAsciiDoc
- -- * Writer options used in writers
- , WriterOptions (..)
- , HTMLSlideVariant (..)
- , HTMLMathMethod (..)
- , CiteMethod (..)
- , defaultWriterOptions
-- * Rendering templates and default templates
, module Text.Pandoc.Templates
-- * Version
, pandocVersion
-- * Miscellaneous
+ , getReader
+ , getWriter
, rtfEmbedImage
, jsonFilter
, ToJsonFilter(..)
@@ -127,7 +118,7 @@ import Text.Pandoc.Readers.Textile
import Text.Pandoc.Readers.Native
import Text.Pandoc.Writers.Native
import Text.Pandoc.Writers.Markdown
-import Text.Pandoc.Writers.RST
+import Text.Pandoc.Writers.RST
import Text.Pandoc.Writers.LaTeX
import Text.Pandoc.Writers.ConTeXt
import Text.Pandoc.Writers.Texinfo
@@ -135,85 +126,143 @@ import Text.Pandoc.Writers.HTML
import Text.Pandoc.Writers.ODT
import Text.Pandoc.Writers.Docx
import Text.Pandoc.Writers.EPUB
+import Text.Pandoc.Writers.FB2
import Text.Pandoc.Writers.Docbook
import Text.Pandoc.Writers.OpenDocument
import Text.Pandoc.Writers.Man
-import Text.Pandoc.Writers.RTF
+import Text.Pandoc.Writers.RTF
import Text.Pandoc.Writers.MediaWiki
import Text.Pandoc.Writers.Textile
import Text.Pandoc.Writers.Org
import Text.Pandoc.Writers.AsciiDoc
import Text.Pandoc.Templates
-import Text.Pandoc.Parsing
-import Text.Pandoc.Shared
+import Text.Pandoc.Options
+import Text.Pandoc.Shared (safeRead)
+import Data.ByteString.Lazy (ByteString)
+import Data.List (intercalate)
import Data.Version (showVersion)
import Text.JSON.Generic
+import Data.Set (Set)
+import qualified Data.Set as Set
+import Text.Parsec
+import Text.Parsec.Error
import Paths_pandoc (version)
-- | Version number of pandoc library.
pandocVersion :: String
pandocVersion = showVersion version
+parseFormatSpec :: String
+ -> Either ParseError (String, Set Extension -> Set Extension)
+parseFormatSpec = parse formatSpec ""
+ where formatSpec = do
+ name <- formatName
+ extMods <- many extMod
+ return (name, foldl (.) id extMods)
+ formatName = many1 $ noneOf "-+"
+ extMod = do
+ polarity <- oneOf "-+"
+ name <- many $ noneOf "-+"
+ ext <- case safeRead ("Ext_" ++ name) of
+ Just n -> return n
+ Nothing
+ | name == "lhs" -> return Ext_literate_haskell
+ | otherwise -> fail $ "Unknown extension: " ++ name
+ return $ case polarity of
+ '-' -> Set.delete ext
+ _ -> Set.insert ext
+
-- | Association list of formats and readers.
-readers :: [(String, ParserState -> String -> Pandoc)]
+readers :: [(String, ReaderOptions -> String -> Pandoc)]
readers = [("native" , \_ -> readNative)
,("json" , \_ -> decodeJSON)
+ ,("markdown_strict" , readMarkdown)
,("markdown" , readMarkdown)
- ,("markdown+lhs" , \st ->
- readMarkdown st{ stateLiterateHaskell = True})
,("rst" , readRST)
- ,("rst+lhs" , \st ->
- readRST st{ stateLiterateHaskell = True})
,("docbook" , readDocBook)
- ,("textile" , readTextile) -- TODO : textile+lhs
+ ,("textile" , readTextile) -- TODO : textile+lhs
,("html" , readHtml)
,("latex" , readLaTeX)
- ,("latex+lhs" , \st ->
- readLaTeX st{ stateLiterateHaskell = True})
]
--- | Association list of formats and writers (omitting the
--- binary writers, odt, docx, and epub).
-writers :: [ ( String, WriterOptions -> Pandoc -> String ) ]
-writers = [("native" , writeNative)
- ,("json" , \_ -> encodeJSON)
- ,("html" , writeHtmlString)
- ,("html5" , \o ->
- writeHtmlString o{ writerHtml5 = True })
- ,("html+lhs" , \o ->
- writeHtmlString o{ writerLiterateHaskell = True })
- ,("html5+lhs" , \o ->
- writeHtmlString o{ writerLiterateHaskell = True,
- writerHtml5 = True })
- ,("s5" , writeHtmlString)
- ,("slidy" , writeHtmlString)
- ,("slideous" , writeHtmlString)
- ,("dzslides" , writeHtmlString)
- ,("docbook" , writeDocbook)
- ,("opendocument" , writeOpenDocument)
- ,("latex" , writeLaTeX)
- ,("latex+lhs" , \o ->
- writeLaTeX o{ writerLiterateHaskell = True })
- ,("beamer" , \o ->
- writeLaTeX o{ writerBeamer = True })
- ,("beamer+lhs" , \o ->
- writeLaTeX o{ writerBeamer = True, writerLiterateHaskell = True })
- ,("context" , writeConTeXt)
- ,("texinfo" , writeTexinfo)
- ,("man" , writeMan)
- ,("markdown" , writeMarkdown)
- ,("markdown+lhs" , \o ->
- writeMarkdown o{ writerLiterateHaskell = True })
- ,("plain" , writePlain)
- ,("rst" , writeRST)
- ,("rst+lhs" , \o ->
- writeRST o{ writerLiterateHaskell = True })
- ,("mediawiki" , writeMediaWiki)
- ,("textile" , writeTextile)
- ,("rtf" , writeRTF)
- ,("org" , writeOrg)
- ,("asciidoc" , writeAsciiDoc)
- ]
+data Writer = PureStringWriter (WriterOptions -> Pandoc -> String)
+ | IOStringWriter (WriterOptions -> Pandoc -> IO String)
+ | IOByteStringWriter (WriterOptions -> Pandoc -> IO ByteString)
+
+-- | Association list of formats and writers.
+writers :: [ ( String, Writer ) ]
+writers = [
+ ("native" , PureStringWriter writeNative)
+ ,("json" , PureStringWriter $ \_ -> encodeJSON)
+ ,("docx" , IOByteStringWriter writeDocx)
+ ,("odt" , IOByteStringWriter writeODT)
+ ,("epub" , IOByteStringWriter writeEPUB)
+ ,("fb2" , IOStringWriter writeFB2)
+ ,("html" , PureStringWriter writeHtmlString)
+ ,("html5" , PureStringWriter $ \o ->
+ writeHtmlString o{ writerHtml5 = True })
+ ,("s5" , PureStringWriter $ \o ->
+ writeHtmlString o{ writerSlideVariant = S5Slides
+ , writerTableOfContents = False })
+ ,("slidy" , PureStringWriter $ \o ->
+ writeHtmlString o{ writerSlideVariant = SlidySlides })
+ ,("slideous" , PureStringWriter $ \o ->
+ writeHtmlString o{ writerSlideVariant = SlideousSlides })
+ ,("dzslides" , PureStringWriter $ \o ->
+ writeHtmlString o{ writerSlideVariant = DZSlides
+ , writerHtml5 = True })
+ ,("docbook" , PureStringWriter writeDocbook)
+ ,("opendocument" , PureStringWriter writeOpenDocument)
+ ,("latex" , PureStringWriter writeLaTeX)
+ ,("beamer" , PureStringWriter $ \o ->
+ writeLaTeX o{ writerBeamer = True })
+ ,("context" , PureStringWriter writeConTeXt)
+ ,("texinfo" , PureStringWriter writeTexinfo)
+ ,("man" , PureStringWriter writeMan)
+ ,("markdown" , PureStringWriter writeMarkdown)
+ ,("markdown_strict" , PureStringWriter writeMarkdown)
+ ,("plain" , PureStringWriter writePlain)
+ ,("rst" , PureStringWriter writeRST)
+ ,("mediawiki" , PureStringWriter writeMediaWiki)
+ ,("textile" , PureStringWriter writeTextile)
+ ,("rtf" , PureStringWriter writeRTF)
+ ,("org" , PureStringWriter writeOrg)
+ ,("asciidoc" , PureStringWriter writeAsciiDoc)
+ ]
+
+getDefaultExtensions :: String -> Set Extension
+getDefaultExtensions "markdown_strict" = strictExtensions
+getDefaultExtensions _ = pandocExtensions
+
+-- | Retrieve reader based on formatSpec (format+extensions).
+getReader :: String -> Either String (ReaderOptions -> String -> Pandoc)
+getReader s =
+ case parseFormatSpec s of
+ Left e -> Left $ intercalate "\n" $ [m | Message m <- errorMessages e]
+ Right (readerName, setExts) ->
+ case lookup readerName readers of
+ Nothing -> Left $ "Unknown reader: " ++ readerName
+ Just r -> Right $ \o ->
+ r o{ readerExtensions = setExts $
+ getDefaultExtensions readerName }
+
+-- | Retrieve writer based on formatSpec (format+extensions).
+getWriter :: String -> Either String Writer
+getWriter s =
+ case parseFormatSpec s of
+ Left e -> Left $ intercalate "\n" $ [m | Message m <- errorMessages e]
+ Right (writerName, setExts) ->
+ case lookup writerName writers of
+ Nothing -> Left $ "Unknown writer: " ++ writerName
+ Just (PureStringWriter r) -> Right $ PureStringWriter $
+ \o -> r o{ writerExtensions = setExts $
+ getDefaultExtensions writerName }
+ Just (IOStringWriter r) -> Right $ IOStringWriter $
+ \o -> r o{ writerExtensions = setExts $
+ getDefaultExtensions writerName }
+ Just (IOByteStringWriter r) -> Right $ IOByteStringWriter $
+ \o -> r o{ writerExtensions = setExts $
+ getDefaultExtensions writerName }
{-# DEPRECATED jsonFilter "Use toJsonFilter instead" #-}
-- | Converts a transformation on the Pandoc AST into a function
diff --git a/src/Text/Pandoc/Biblio.hs b/src/Text/Pandoc/Biblio.hs
index cece13fba..13569a4d9 100644
--- a/src/Text/Pandoc/Biblio.hs
+++ b/src/Text/Pandoc/Biblio.hs
@@ -38,7 +38,7 @@ import qualified Text.CSL as CSL ( Cite(..) )
import Text.Pandoc.Definition
import Text.Pandoc.Generic
import Text.Pandoc.Shared (stringify)
-import Text.ParserCombinators.Parsec
+import Text.Parsec
import Control.Monad
-- | Process a 'Pandoc' document by adding citations formatted
@@ -165,7 +165,7 @@ locatorWords inp =
breakup (x : xs) = x : breakup xs
splitup = groupBy (\x y -> x /= '\160' && y /= '\160')
-pLocatorWords :: GenParser Inline st (String, [Inline])
+pLocatorWords :: Parsec [Inline] st (String, [Inline])
pLocatorWords = do
l <- pLocator
s <- getInput -- rest is suffix
@@ -173,16 +173,16 @@ pLocatorWords = do
then return (init l, Str "," : s)
else return (l, s)
-pMatch :: (Inline -> Bool) -> GenParser Inline st Inline
+pMatch :: (Inline -> Bool) -> Parsec [Inline] st Inline
pMatch condition = try $ do
t <- anyToken
guard $ condition t
return t
-pSpace :: GenParser Inline st Inline
+pSpace :: Parsec [Inline] st Inline
pSpace = pMatch (\t -> t == Space || t == Str "\160")
-pLocator :: GenParser Inline st String
+pLocator :: Parsec [Inline] st String
pLocator = try $ do
optional $ pMatch (== Str ",")
optional pSpace
@@ -190,7 +190,7 @@ pLocator = try $ do
gs <- many1 pWordWithDigits
return $ stringify f ++ (' ' : unwords gs)
-pWordWithDigits :: GenParser Inline st String
+pWordWithDigits :: Parsec [Inline] st String
pWordWithDigits = try $ do
pSpace
r <- many1 (notFollowedBy pSpace >> anyToken)
diff --git a/src/Text/Pandoc/Highlighting.hs b/src/Text/Pandoc/Highlighting.hs
index 080acebee..95df88099 100644
--- a/src/Text/Pandoc/Highlighting.hs
+++ b/src/Text/Pandoc/Highlighting.hs
@@ -47,6 +47,7 @@ module Text.Pandoc.Highlighting ( languages
, Style
) where
import Text.Pandoc.Definition
+import Text.Pandoc.Shared (safeRead)
import Text.Highlighting.Kate
import Data.List (find)
import Data.Maybe (fromMaybe)
@@ -60,9 +61,9 @@ highlight :: (FormatOptions -> [SourceLine] -> a) -- ^ Formatter
-> String -- ^ Raw contents of the CodeBlock
-> Maybe a -- ^ Maybe the formatted result
highlight formatter (_, classes, keyvals) rawCode =
- let firstNum = case reads (fromMaybe "1" $ lookup "startFrom" keyvals) of
- ((n,_):_) -> n
- [] -> 1
+ let firstNum = case safeRead (fromMaybe "1" $ lookup "startFrom" keyvals) of
+ Just n -> n
+ Nothing -> 1
fmtOpts = defaultFormatOpts{
startNumber = firstNum,
numberLines = any (`elem`
diff --git a/src/Text/Pandoc/MIME.hs b/src/Text/Pandoc/MIME.hs
index f9749cece..9cde57e4d 100644
--- a/src/Text/Pandoc/MIME.hs
+++ b/src/Text/Pandoc/MIME.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.MIME
Copyright : Copyright (C) 2011 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs
new file mode 100644
index 000000000..a9c8bf710
--- /dev/null
+++ b/src/Text/Pandoc/Options.hs
@@ -0,0 +1,277 @@
+{-
+Copyright (C) 2012 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.Options
+ Copyright : Copyright (C) 2012 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+Data structures and functions for representing parser and writer
+options.
+-}
+module Text.Pandoc.Options ( Extension(..)
+ , pandocExtensions
+ , strictExtensions
+ , ReaderOptions(..)
+ , HTMLMathMethod (..)
+ , CiteMethod (..)
+ , ObfuscationMethod (..)
+ , HTMLSlideVariant (..)
+ , WriterOptions (..)
+ , def
+ , isEnabled
+ ) where
+import Data.Set (Set)
+import qualified Data.Set as Set
+import Data.Default
+import Text.Pandoc.Highlighting (Style, pygments)
+
+-- | Individually selectable syntax extensions.
+data Extension =
+ Ext_footnotes -- ^ Pandoc/PHP/MMD style footnotes
+ | Ext_inline_notes -- ^ Pandoc-style inline notes
+ | Ext_pandoc_title_block -- ^ Pandoc title block
+ | Ext_mmd_title_block -- ^ Multimarkdown metadata block
+ | Ext_table_captions -- ^ Pandoc-style table captions
+ -- | Ext_image_captions
+ | Ext_simple_tables -- ^ Pandoc-style simple tables
+ | Ext_multiline_tables -- ^ Pandoc-style multiline tables
+ | Ext_grid_tables -- ^ Grid tables (pandoc, reST)
+ | Ext_pipe_tables -- ^ Pipe tables (as in PHP markdown extra)
+ | Ext_citations -- ^ Pandoc/citeproc citations
+ | Ext_raw_tex -- ^ Allow raw TeX (other than math)
+ | Ext_raw_html -- ^ Allow raw HTML
+ | Ext_tex_math_dollars -- ^ TeX math between $..$ or $$..$$
+ | Ext_tex_math_single_backslash -- ^ TeX math btw \(..\) \[..\]
+ | Ext_tex_math_double_backslash -- ^ TeX math btw \\(..\\) \\[..\\]
+ | Ext_latex_macros -- ^ Parse LaTeX macro definitions (for math only)
+ | Ext_fenced_code_blocks -- ^ Parse fenced code blocks
+ | Ext_fenced_code_attributes -- ^ Allow attributes on fenced code blocks
+ | Ext_backtick_code_blocks -- ^ Github style ``` code blocks
+ | Ext_inline_code_attributes -- ^ Allow attributes on inline code
+ | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks
+ | Ext_markdown_attribute -- ^ Interpret text inside HTML as markdown
+ -- iff container has attribute 'markdown'
+ | Ext_escaped_line_breaks -- ^ Treat a backslash at EOL as linebreak
+ | Ext_autolink_code_spans -- ^ Put autolink text inside code spans
+ | Ext_fancy_lists -- ^ Enable fancy list numbers and delimiters
+ | Ext_startnum -- ^ Make start number of ordered list significant
+ | Ext_definition_lists -- ^ Definition lists as in pandoc, mmd, php
+ | Ext_example_lists -- ^ Markdown-style numbered examples
+ | Ext_all_symbols_escapable -- ^ Make all non-alphanumerics escapable
+ | Ext_intraword_underscores -- ^ Treat underscore inside word as literal
+ | Ext_blank_before_blockquote -- ^ Require blank line before a blockquote
+ | Ext_blank_before_header -- ^ Require blank line before a header
+ -- | Ext_significant_bullets
+ | Ext_strikeout -- ^ Strikeout using ~~this~~ syntax
+ | Ext_superscript -- ^ Superscript using ^this^ syntax
+ | Ext_subscript -- ^ Subscript using ~this~ syntax
+ | Ext_hard_line_breaks -- ^ All newlines become hard line breaks
+ | Ext_literate_haskell -- ^ Enable literate Haskell conventions
+ | Ext_abbreviations -- ^ PHP markdown extra abbreviation definitions
+ deriving (Show, Read, Enum, Eq, Ord, Bounded)
+
+pandocExtensions :: Set Extension
+pandocExtensions = Set.fromList
+ [ Ext_footnotes
+ , Ext_inline_notes
+ , Ext_pandoc_title_block
+ , Ext_table_captions
+ -- , Ext_image_captions
+ , Ext_simple_tables
+ , Ext_multiline_tables
+ , Ext_grid_tables
+ , Ext_pipe_tables
+ , Ext_citations
+ , Ext_raw_tex
+ , Ext_raw_html
+ , Ext_tex_math_dollars
+ , Ext_latex_macros
+ , Ext_fenced_code_blocks
+ , Ext_fenced_code_attributes
+ , Ext_backtick_code_blocks
+ , Ext_inline_code_attributes
+ , Ext_markdown_in_html_blocks
+ , Ext_escaped_line_breaks
+ , Ext_autolink_code_spans
+ , Ext_fancy_lists
+ , Ext_startnum
+ , Ext_definition_lists
+ , Ext_example_lists
+ , Ext_all_symbols_escapable
+ , Ext_intraword_underscores
+ , Ext_blank_before_blockquote
+ , Ext_blank_before_header
+ -- , Ext_significant_bullets
+ , Ext_strikeout
+ , Ext_superscript
+ , Ext_subscript
+ ]
+
+strictExtensions :: Set Extension
+strictExtensions = Set.fromList
+ [ Ext_raw_html ]
+
+data ReaderOptions = ReaderOptions{
+ readerExtensions :: Set Extension -- ^ Syntax extensions
+ , readerSmart :: Bool -- ^ Smart punctuation
+ , readerStrict :: Bool -- ^ FOR TRANSITION ONLY
+ , readerStandalone :: Bool -- ^ Standalone document with header
+ , readerParseRaw :: Bool -- ^ Parse raw HTML, LaTeX
+ , readerColumns :: Int -- ^ Number of columns in terminal
+ , readerTabStop :: Int -- ^ Tab stop
+ , readerOldDashes :: Bool -- ^ Use pandoc <= 1.8.2.1 behavior
+ -- in parsing dashes; -- is em-dash;
+ -- - before numerial is en-dash
+ , readerCitations :: [String] -- ^ List of available citations
+ , readerApplyMacros :: Bool -- ^ Apply macros to TeX math
+ , readerIndentedCodeClasses :: [String] -- ^ Default classes for
+ -- indented code blocks
+} deriving (Show, Read)
+
+instance Default ReaderOptions
+ where def = ReaderOptions{
+ readerExtensions = pandocExtensions
+ , readerSmart = False
+ , readerStrict = False
+ , readerStandalone = False
+ , readerParseRaw = False
+ , readerColumns = 80
+ , readerTabStop = 4
+ , readerOldDashes = False
+ , readerCitations = []
+ , readerApplyMacros = True
+ , readerIndentedCodeClasses = []
+ }
+
+--
+-- Writer options
+--
+
+data HTMLMathMethod = PlainMath
+ | LaTeXMathML (Maybe String) -- url of LaTeXMathML.js
+ | JsMath (Maybe String) -- url of jsMath load script
+ | GladTeX
+ | WebTeX String -- url of TeX->image script.
+ | MathML (Maybe String) -- url of MathMLinHTML.js
+ | MathJax String -- url of MathJax.js
+ deriving (Show, Read, Eq)
+
+data CiteMethod = Citeproc -- use citeproc to render them
+ | Natbib -- output natbib cite commands
+ | Biblatex -- output biblatex cite commands
+ deriving (Show, Read, Eq)
+
+-- | Methods for obfuscating email addresses in HTML.
+data ObfuscationMethod = NoObfuscation
+ | ReferenceObfuscation
+ | JavascriptObfuscation
+ deriving (Show, Read, Eq)
+
+-- | Varieties of HTML slide shows.
+data HTMLSlideVariant = S5Slides
+ | SlidySlides
+ | SlideousSlides
+ | DZSlides
+ | NoSlides
+ deriving (Show, Read, Eq)
+
+-- | Options for writers
+data WriterOptions = WriterOptions
+ { writerStandalone :: Bool -- ^ Include header and footer
+ , writerTemplate :: String -- ^ Template to use in standalone mode
+ , writerVariables :: [(String, String)] -- ^ Variables to set in template
+ , writerEPUBMetadata :: String -- ^ Metadata to include in EPUB
+ , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs
+ , writerTableOfContents :: Bool -- ^ Include table of contents
+ , writerSlideVariant :: HTMLSlideVariant -- ^ Are we writing S5, Slidy or Slideous?
+ , writerIncremental :: Bool -- ^ True if lists should be incremental
+ , writerHTMLMathMethod :: HTMLMathMethod -- ^ How to print math in HTML
+ , writerIgnoreNotes :: Bool -- ^ Ignore footnotes (used in making toc)
+ , writerNumberSections :: Bool -- ^ Number sections in LaTeX
+ , writerSectionDivs :: Bool -- ^ Put sections in div tags in HTML
+ , writerExtensions :: Set Extension -- ^ Markdown extensions that can be used
+ , writerReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst
+ , writerWrapText :: Bool -- ^ Wrap text to line length
+ , writerColumns :: Int -- ^ Characters in a line (for text wrapping)
+ , writerEmailObfuscation :: ObfuscationMethod -- ^ How to obfuscate emails
+ , writerIdentifierPrefix :: String -- ^ Prefix for section & note ids in HTML
+ , writerSourceDirectory :: FilePath -- ^ Directory path of 1st source file
+ , writerUserDataDir :: Maybe FilePath -- ^ Path of user data directory
+ , writerCiteMethod :: CiteMethod -- ^ How to print cites
+ , writerBiblioFiles :: [FilePath] -- ^ Biblio files to use for citations
+ , writerHtml5 :: Bool -- ^ Produce HTML5
+ , writerBeamer :: Bool -- ^ Produce beamer LaTeX slide show
+ , writerSlideLevel :: Maybe Int -- ^ Force header level of slides
+ , writerChapters :: Bool -- ^ Use "chapter" for top-level sects
+ , writerListings :: Bool -- ^ Use listings package for code
+ , writerHighlight :: Bool -- ^ Highlight source code
+ , writerHighlightStyle :: Style -- ^ Style to use for highlighting
+ , writerSetextHeaders :: Bool -- ^ Use setext headers for levels 1-2 in markdown
+ , writerTeXLigatures :: Bool -- ^ Use tex ligatures quotes, dashes in latex
+ , writerEpubStylesheet :: Maybe String -- ^ EPUB stylesheet specified at command line
+ , writerEpubFonts :: [FilePath] -- ^ Paths to fonts to embed
+ , writerReferenceODT :: Maybe FilePath -- ^ Path to reference ODT if specified
+ , writerReferenceDocx :: Maybe FilePath -- ^ Ptah to reference DOCX if specified
+ } deriving Show
+
+instance Default WriterOptions where
+ def = WriterOptions { writerStandalone = False
+ , writerTemplate = ""
+ , writerVariables = []
+ , writerEPUBMetadata = ""
+ , writerTabStop = 4
+ , writerTableOfContents = False
+ , writerSlideVariant = NoSlides
+ , writerIncremental = False
+ , writerHTMLMathMethod = PlainMath
+ , writerIgnoreNotes = False
+ , writerNumberSections = False
+ , writerSectionDivs = False
+ , writerExtensions = pandocExtensions
+ , writerReferenceLinks = False
+ , writerWrapText = True
+ , writerColumns = 72
+ , writerEmailObfuscation = JavascriptObfuscation
+ , writerIdentifierPrefix = ""
+ , writerSourceDirectory = "."
+ , writerUserDataDir = Nothing
+ , writerCiteMethod = Citeproc
+ , writerBiblioFiles = []
+ , writerHtml5 = False
+ , writerBeamer = False
+ , writerSlideLevel = Nothing
+ , writerChapters = False
+ , writerListings = False
+ , writerHighlight = False
+ , writerHighlightStyle = pygments
+ , writerSetextHeaders = True
+ , writerTeXLigatures = True
+ , writerEpubStylesheet = Nothing
+ , writerEpubFonts = []
+ , writerReferenceODT = Nothing
+ , writerReferenceDocx = Nothing
+ }
+
+-- | Returns True if the given extension is enabled.
+isEnabled :: Extension -> WriterOptions -> Bool
+isEnabled ext opts = ext `Set.member` (writerExtensions opts)
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
index cac2b71ca..50691f409 100644
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-
Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
@@ -19,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Parsing
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -48,8 +49,6 @@ module Text.Pandoc.Parsing ( (>>~),
withHorizDisplacement,
withRaw,
nullBlock,
- failIfStrict,
- failUnlessLHS,
escaped,
characterReference,
updateLastStrPos,
@@ -57,37 +56,127 @@ module Text.Pandoc.Parsing ( (>>~),
orderedListMarker,
charRef,
tableWith,
+ widthsFromIndices,
gridTableWith,
readWith,
testStringWith,
+ getOption,
+ guardEnabled,
+ guardDisabled,
ParserState (..),
defaultParserState,
HeaderType (..),
ParserContext (..),
QuoteContext (..),
NoteTable,
+ NoteTable',
KeyTable,
- Key,
+ Key (..),
toKey,
- fromKey,
- lookupKeySrc,
smartPunctuation,
+ withQuoteContext,
+ singleQuoteStart,
+ singleQuoteEnd,
+ doubleQuoteStart,
+ doubleQuoteEnd,
+ ellipses,
+ apostrophe,
+ dash,
macro,
- applyMacros' )
+ applyMacros',
+ Parser,
+ F(..),
+ runF,
+ askF,
+ asksF,
+ -- * Re-exports from Text.Pandoc.Parsec
+ runParser,
+ parse,
+ anyToken,
+ getInput,
+ setInput,
+ unexpected,
+ char,
+ letter,
+ digit,
+ alphaNum,
+ skipMany,
+ skipMany1,
+ spaces,
+ space,
+ anyChar,
+ satisfy,
+ newline,
+ string,
+ count,
+ eof,
+ noneOf,
+ oneOf,
+ lookAhead,
+ notFollowedBy,
+ many,
+ many1,
+ manyTill,
+ (<|>),
+ (<?>),
+ choice,
+ try,
+ sepBy,
+ sepBy1,
+ sepEndBy,
+ sepEndBy1,
+ endBy,
+ endBy1,
+ option,
+ optional,
+ optionMaybe,
+ getState,
+ setState,
+ updateState,
+ getPosition,
+ setPosition,
+ sourceColumn,
+ sourceLine,
+ newPos,
+ token
+ )
where
import Text.Pandoc.Definition
-import Text.Pandoc.Generic
+import Text.Pandoc.Options
+import Text.Pandoc.Builder (Blocks)
import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn)
-import Text.ParserCombinators.Parsec
+import Text.Parsec
+import Text.Parsec.Pos (newPos)
import Data.Char ( toLower, toUpper, ord, isAscii, isAlphaNum, isDigit, isPunctuation )
import Data.List ( intercalate, transpose )
import Network.URI ( parseURI, URI (..), isAllowedInURI )
-import Control.Monad ( join, liftM, guard )
import Text.Pandoc.Shared
import qualified Data.Map as M
import Text.TeXMath.Macros (applyMacros, Macro, parseMacroDefinitions)
import Text.HTML.TagSoup.Entity ( lookupEntity )
+import Data.Default
+import qualified Data.Set as Set
+import Control.Monad.Reader
+import Data.Monoid
+
+type Parser t s = Parsec t s
+
+newtype F a = F { unF :: Reader ParserState a } deriving (Monad, Functor)
+
+runF :: F a -> ParserState -> a
+runF = runReader . unF
+
+askF :: F ParserState
+askF = F ask
+
+asksF :: (ParserState -> a) -> F a
+asksF f = F $ asks f
+
+instance Monoid a => Monoid (F a) where
+ mempty = return mempty
+ mappend = liftM2 mappend
+ mconcat = liftM mconcat . sequence
-- | Like >>, but returns the operation on the left.
-- (Suggested by Tillmann Rendel on Haskell-cafe list.)
@@ -95,62 +184,69 @@ import Text.HTML.TagSoup.Entity ( lookupEntity )
a >>~ b = a >>= \x -> b >> return x
-- | Parse any line of text
-anyLine :: GenParser Char st [Char]
+anyLine :: Parser [Char] st [Char]
anyLine = manyTill anyChar newline
-- | Like @manyTill@, but reads at least one item.
-many1Till :: GenParser tok st a
- -> GenParser tok st end
- -> GenParser tok st [a]
+many1Till :: Parser [tok] st a
+ -> Parser [tok] st end
+ -> Parser [tok] st [a]
many1Till p end = do
first <- p
rest <- manyTill p end
return (first:rest)
--- | A more general form of @notFollowedBy@. This one allows any
+-- | A more general form of @notFollowedBy@. This one allows any
-- type of parser to be specified, and succeeds only if that parser fails.
-- It does not consume any input.
-notFollowedBy' :: Show b => GenParser a st b -> GenParser a st ()
+notFollowedBy' :: Show b => Parser [a] st b -> Parser [a] st ()
notFollowedBy' p = try $ join $ do a <- try p
return (unexpected (show a))
<|>
return (return ())
-- (This version due to Andrew Pimlott on the Haskell mailing list.)
--- | Parses one of a list of strings (tried in order).
-oneOfStrings :: [String] -> GenParser Char st String
-oneOfStrings listOfStrings = choice $ map (try . string) listOfStrings
+-- | Parses one of a list of strings (tried in order).
+oneOfStrings :: [String] -> Parser [Char] st String
+oneOfStrings [] = fail "no strings"
+oneOfStrings strs = do
+ c <- anyChar
+ let strs' = [xs | (x:xs) <- strs, x == c]
+ case strs' of
+ [] -> fail "not found"
+ z | "" `elem` z -> return [c]
+ | otherwise -> (c:) `fmap` oneOfStrings strs'
-- | Parses a space or tab.
-spaceChar :: CharParser st Char
+spaceChar :: Parser [Char] st Char
spaceChar = satisfy $ \c -> c == ' ' || c == '\t'
-- | Parses a nonspace, nonnewline character.
-nonspaceChar :: CharParser st Char
+nonspaceChar :: Parser [Char] st Char
nonspaceChar = satisfy $ \x -> x /= '\t' && x /= '\n' && x /= ' ' && x /= '\r'
-- | Skips zero or more spaces or tabs.
-skipSpaces :: GenParser Char st ()
+skipSpaces :: Parser [Char] st ()
skipSpaces = skipMany spaceChar
-- | Skips zero or more spaces or tabs, then reads a newline.
-blankline :: GenParser Char st Char
+blankline :: Parser [Char] st Char
blankline = try $ skipSpaces >> newline
-- | Parses one or more blank lines and returns a string of newlines.
-blanklines :: GenParser Char st [Char]
+blanklines :: Parser [Char] st [Char]
blanklines = many1 blankline
-- | Parses material enclosed between start and end parsers.
-enclosed :: GenParser Char st t -- ^ start parser
- -> GenParser Char st end -- ^ end parser
- -> GenParser Char st a -- ^ content parser (to be used repeatedly)
- -> GenParser Char st [a]
-enclosed start end parser = try $
+enclosed :: Parser [Char] st t -- ^ start parser
+ -> Parser [Char] st end -- ^ end parser
+ -> Parser [Char] st a -- ^ content parser (to be used repeatedly)
+ -> Parser [Char] st [a]
+enclosed start end parser = try $
start >> notFollowedBy space >> many1Till parser end
-- | Parse string, case insensitive.
-stringAnyCase :: [Char] -> CharParser st String
+stringAnyCase :: [Char] -> Parser [Char] st String
stringAnyCase [] = string ""
stringAnyCase (x:xs) = do
firstChar <- char (toUpper x) <|> char (toLower x)
@@ -158,7 +254,7 @@ stringAnyCase (x:xs) = do
return (firstChar:rest)
-- | Parse contents of 'str' using 'parser' and return result.
-parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a
+parseFromString :: Parser [tok] st a -> [tok] -> Parser [tok] st a
parseFromString parser str = do
oldPos <- getPosition
oldInput <- getInput
@@ -169,8 +265,8 @@ parseFromString parser str = do
return result
-- | Parse raw line block up to and including blank lines.
-lineClump :: GenParser Char st String
-lineClump = blanklines
+lineClump :: Parser [Char] st String
+lineClump = blanklines
<|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines)
-- | Parse a string of characters between an open character
@@ -178,8 +274,8 @@ lineClump = blanklines
-- pairs of open and close, which must be different. For example,
-- @charsInBalanced '(' ')' anyChar@ will parse "(hello (there))"
-- and return "hello (there)".
-charsInBalanced :: Char -> Char -> GenParser Char st Char
- -> GenParser Char st String
+charsInBalanced :: Char -> Char -> Parser [Char] st Char
+ -> Parser [Char] st String
charsInBalanced open close parser = try $ do
char open
let isDelim c = c == open || c == close
@@ -204,13 +300,13 @@ uppercaseRomanDigits = map toUpper lowercaseRomanDigits
-- | Parses a roman numeral (uppercase or lowercase), returns number.
romanNumeral :: Bool -- ^ Uppercase if true
- -> GenParser Char st Int
+ -> Parser [Char] st Int
romanNumeral upperCase = do
- let romanDigits = if upperCase
- then uppercaseRomanDigits
+ let romanDigits = if upperCase
+ then uppercaseRomanDigits
else lowercaseRomanDigits
lookAhead $ oneOf romanDigits
- let [one, five, ten, fifty, hundred, fivehundred, thousand] =
+ let [one, five, ten, fifty, hundred, fivehundred, thousand] =
map char romanDigits
thousands <- many thousand >>= (return . (1000 *) . length)
ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900
@@ -234,14 +330,14 @@ romanNumeral upperCase = do
-- Parsers for email addresses and URIs
-emailChar :: GenParser Char st Char
+emailChar :: Parser [Char] st Char
emailChar = alphaNum <|>
satisfy (\c -> c == '-' || c == '+' || c == '_' || c == '.')
-domainChar :: GenParser Char st Char
+domainChar :: Parser [Char] st Char
domainChar = alphaNum <|> char '-'
-domain :: GenParser Char st [Char]
+domain :: Parser [Char] st [Char]
domain = do
first <- many1 domainChar
dom <- many1 $ try (char '.' >> many1 domainChar )
@@ -249,7 +345,7 @@ domain = do
-- | Parses an email address; returns original and corresponding
-- escaped mailto: URI.
-emailAddress :: GenParser Char st (String, String)
+emailAddress :: Parser [Char] st (String, String)
emailAddress = try $ do
firstLetter <- alphaNum
restAddr <- many emailChar
@@ -260,7 +356,7 @@ emailAddress = try $ do
return (full, escapeURI $ "mailto:" ++ full)
-- | Parses a URI. Returns pair of original and URI-escaped version.
-uri :: GenParser Char st (String, String)
+uri :: Parser [Char] st (String, String)
uri = try $ do
let protocols = [ "http:", "https:", "ftp:", "file:", "mailto:",
"news:", "telnet:" ]
@@ -294,8 +390,8 @@ uri = try $ do
-- displacement (the difference between the source column at the end
-- and the source column at the beginning). Vertical displacement
-- (source row) is ignored.
-withHorizDisplacement :: GenParser Char st a -- ^ Parser to apply
- -> GenParser Char st (a, Int) -- ^ (result, displacement)
+withHorizDisplacement :: Parser [Char] st a -- ^ Parser to apply
+ -> Parser [Char] st (a, Int) -- ^ (result, displacement)
withHorizDisplacement parser = do
pos1 <- getPosition
result <- parser
@@ -304,7 +400,7 @@ withHorizDisplacement parser = do
-- | Applies a parser and returns the raw string that was parsed,
-- along with the value produced by the parser.
-withRaw :: GenParser Char st a -> GenParser Char st (a, [Char])
+withRaw :: Parser [Char] st a -> Parser [Char] st (a, [Char])
withRaw parser = do
pos1 <- getPosition
inp <- getInput
@@ -321,26 +417,16 @@ withRaw parser = do
-- | Parses a character and returns 'Null' (so that the parser can move on
-- if it gets stuck).
-nullBlock :: GenParser Char st Block
+nullBlock :: Parser [Char] st Block
nullBlock = anyChar >> return Null
--- | Fail if reader is in strict markdown syntax mode.
-failIfStrict :: GenParser a ParserState ()
-failIfStrict = do
- state <- getState
- if stateStrict state then fail "strict mode" else return ()
-
--- | Fail unless we're in literate haskell mode.
-failUnlessLHS :: GenParser tok ParserState ()
-failUnlessLHS = getState >>= guard . stateLiterateHaskell
-
-- | Parses backslash, then applies character parser.
-escaped :: GenParser Char st Char -- ^ Parser for character to escape
- -> GenParser Char st Char
+escaped :: Parser [Char] st Char -- ^ Parser for character to escape
+ -> Parser [Char] st Char
escaped parser = try $ char '\\' >> parser
-- | Parse character entity.
-characterReference :: GenParser Char st Char
+characterReference :: Parser [Char] st Char
characterReference = try $ do
char '&'
ent <- many1Till nonspaceChar (char ';')
@@ -349,19 +435,19 @@ characterReference = try $ do
Nothing -> fail "entity not found"
-- | Parses an uppercase roman numeral and returns (UpperRoman, number).
-upperRoman :: GenParser Char st (ListNumberStyle, Int)
+upperRoman :: Parser [Char] st (ListNumberStyle, Int)
upperRoman = do
num <- romanNumeral True
return (UpperRoman, num)
-- | Parses a lowercase roman numeral and returns (LowerRoman, number).
-lowerRoman :: GenParser Char st (ListNumberStyle, Int)
+lowerRoman :: Parser [Char] st (ListNumberStyle, Int)
lowerRoman = do
num <- romanNumeral False
return (LowerRoman, num)
-- | Parses a decimal numeral and returns (Decimal, number).
-decimal :: GenParser Char st (ListNumberStyle, Int)
+decimal :: Parser [Char] st (ListNumberStyle, Int)
decimal = do
num <- many1 digit
return (Decimal, read num)
@@ -370,7 +456,7 @@ decimal = do
-- returns (DefaultStyle, [next example number]). The next
-- example number is incremented in parser state, and the label
-- (if present) is added to the label table.
-exampleNum :: GenParser Char ParserState (ListNumberStyle, Int)
+exampleNum :: Parser [Char] ParserState (ListNumberStyle, Int)
exampleNum = do
char '@'
lab <- many (alphaNum <|> satisfy (\c -> c == '_' || c == '-'))
@@ -384,38 +470,38 @@ exampleNum = do
return (Example, num)
-- | Parses a '#' returns (DefaultStyle, 1).
-defaultNum :: GenParser Char st (ListNumberStyle, Int)
+defaultNum :: Parser [Char] st (ListNumberStyle, Int)
defaultNum = do
char '#'
return (DefaultStyle, 1)
-- | Parses a lowercase letter and returns (LowerAlpha, number).
-lowerAlpha :: GenParser Char st (ListNumberStyle, Int)
+lowerAlpha :: Parser [Char] st (ListNumberStyle, Int)
lowerAlpha = do
ch <- oneOf ['a'..'z']
return (LowerAlpha, ord ch - ord 'a' + 1)
-- | Parses an uppercase letter and returns (UpperAlpha, number).
-upperAlpha :: GenParser Char st (ListNumberStyle, Int)
+upperAlpha :: Parser [Char] st (ListNumberStyle, Int)
upperAlpha = do
ch <- oneOf ['A'..'Z']
return (UpperAlpha, ord ch - ord 'A' + 1)
-- | Parses a roman numeral i or I
-romanOne :: GenParser Char st (ListNumberStyle, Int)
+romanOne :: Parser [Char] st (ListNumberStyle, Int)
romanOne = (char 'i' >> return (LowerRoman, 1)) <|>
(char 'I' >> return (UpperRoman, 1))
-- | Parses an ordered list marker and returns list attributes.
-anyOrderedListMarker :: GenParser Char ParserState ListAttributes
-anyOrderedListMarker = choice $
+anyOrderedListMarker :: Parser [Char] ParserState ListAttributes
+anyOrderedListMarker = choice $
[delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens],
numParser <- [decimal, exampleNum, defaultNum, romanOne,
lowerAlpha, lowerRoman, upperAlpha, upperRoman]]
-- | Parses a list number (num) followed by a period, returns list attributes.
-inPeriod :: GenParser Char st (ListNumberStyle, Int)
- -> GenParser Char st ListAttributes
+inPeriod :: Parser [Char] st (ListNumberStyle, Int)
+ -> Parser [Char] st ListAttributes
inPeriod num = try $ do
(style, start) <- num
char '.'
@@ -423,18 +509,18 @@ inPeriod num = try $ do
then DefaultDelim
else Period
return (start, style, delim)
-
+
-- | Parses a list number (num) followed by a paren, returns list attributes.
-inOneParen :: GenParser Char st (ListNumberStyle, Int)
- -> GenParser Char st ListAttributes
+inOneParen :: Parser [Char] st (ListNumberStyle, Int)
+ -> Parser [Char] st ListAttributes
inOneParen num = try $ do
(style, start) <- num
char ')'
return (start, style, OneParen)
-- | Parses a list number (num) enclosed in parens, returns list attributes.
-inTwoParens :: GenParser Char st (ListNumberStyle, Int)
- -> GenParser Char st ListAttributes
+inTwoParens :: Parser [Char] st (ListNumberStyle, Int)
+ -> Parser [Char] st ListAttributes
inTwoParens num = try $ do
char '('
(style, start) <- num
@@ -443,9 +529,9 @@ inTwoParens num = try $ do
-- | Parses an ordered list marker with a given style and delimiter,
-- returns number.
-orderedListMarker :: ListNumberStyle
- -> ListNumberDelim
- -> GenParser Char ParserState Int
+orderedListMarker :: ListNumberStyle
+ -> ListNumberDelim
+ -> Parser [Char] ParserState Int
orderedListMarker style delim = do
let num = defaultNum <|> -- # can continue any kind of list
case style of
@@ -465,38 +551,34 @@ orderedListMarker style delim = do
return start
-- | Parses a character reference and returns a Str element.
-charRef :: GenParser Char st Inline
+charRef :: Parser [Char] st Inline
charRef = do
c <- characterReference
return $ Str [c]
-- | Parse a table using 'headerParser', 'rowParser',
-- 'lineParser', and 'footerParser'.
-tableWith :: GenParser Char ParserState ([[Block]], [Alignment], [Int])
- -> ([Int] -> GenParser Char ParserState [[Block]])
- -> GenParser Char ParserState sep
- -> GenParser Char ParserState end
- -> GenParser Char ParserState [Inline]
- -> GenParser Char ParserState Block
-tableWith headerParser rowParser lineParser footerParser captionParser = try $ do
- caption' <- option [] captionParser
+tableWith :: Parser [Char] ParserState ([[Block]], [Alignment], [Int])
+ -> ([Int] -> Parser [Char] ParserState [[Block]])
+ -> Parser [Char] ParserState sep
+ -> Parser [Char] ParserState end
+ -> Parser [Char] ParserState Block
+tableWith headerParser rowParser lineParser footerParser = try $ do
(heads, aligns, indices) <- headerParser
- lines' <- rowParser indices `sepEndBy` lineParser
+ lines' <- rowParser indices `sepEndBy1` lineParser
footerParser
- caption <- if null caption'
- then option [] captionParser
- else return caption'
- state <- getState
- let numColumns = stateColumns state
- let widths = widthsFromIndices numColumns indices
- return $ Table caption aligns widths heads lines'
+ numColumns <- getOption readerColumns
+ let widths = if (indices == [])
+ then replicate (length aligns) 0.0
+ else widthsFromIndices numColumns indices
+ return $ Table [] aligns widths heads lines'
-- Calculate relative widths of table columns, based on indices
widthsFromIndices :: Int -- Number of columns on terminal
-> [Int] -- Indices
-> [Double] -- Fractional relative sizes of columns
-widthsFromIndices _ [] = []
-widthsFromIndices numColumns' indices =
+widthsFromIndices _ [] = []
+widthsFromIndices numColumns' indices =
let numColumns = max numColumns' (if null indices then 0 else last indices)
lengths' = zipWith (-) indices (0:indices)
lengths = reverse $
@@ -516,28 +598,30 @@ widthsFromIndices numColumns' indices =
fracs = map (\l -> (fromIntegral l) / quotient) lengths in
tail fracs
+---
+
-- Parse a grid table: starts with row of '-' on top, then header
-- (which may be grid), then the rows,
-- which may be grid, separated by blank lines, and
-- ending with a footer (dashed line followed by blank line).
-gridTableWith :: GenParser Char ParserState Block -- ^ Block parser
- -> GenParser Char ParserState [Inline] -- ^ Caption parser
+gridTableWith :: Parser [Char] ParserState [Block] -- ^ Block list parser
-> Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
-gridTableWith block tableCaption headless =
- tableWith (gridTableHeader headless block) (gridTableRow block) (gridTableSep '-') gridTableFooter tableCaption
+ -> Parser [Char] ParserState Block
+gridTableWith blocks headless =
+ tableWith (gridTableHeader headless blocks) (gridTableRow blocks)
+ (gridTableSep '-') gridTableFooter
gridTableSplitLine :: [Int] -> String -> [String]
gridTableSplitLine indices line = map removeFinalBar $ tail $
splitStringByIndices (init indices) $ removeTrailingSpace line
-gridPart :: Char -> GenParser Char st (Int, Int)
+gridPart :: Char -> Parser [Char] st (Int, Int)
gridPart ch = do
dashes <- many1 (char ch)
char '+'
return (length dashes, length dashes + 1)
-gridDashedLines :: Char -> GenParser Char st [(Int,Int)]
+gridDashedLines :: Char -> Parser [Char] st [(Int,Int)]
gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline
removeFinalBar :: String -> String
@@ -545,18 +629,18 @@ removeFinalBar =
reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse
-- | Separator between rows of grid table.
-gridTableSep :: Char -> GenParser Char ParserState Char
+gridTableSep :: Char -> Parser [Char] ParserState Char
gridTableSep ch = try $ gridDashedLines ch >> return '\n'
-- | Parse header for a grid table.
gridTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
- -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
-gridTableHeader headless block = try $ do
+ -> Parser [Char] ParserState [Block]
+ -> Parser [Char] ParserState ([[Block]], [Alignment], [Int])
+gridTableHeader headless blocks = try $ do
optional blanklines
dashes <- gridDashedLines '-'
rawContent <- if headless
- then return $ repeat ""
+ then return $ repeat ""
else many1
(notFollowedBy (gridTableSep '=') >> char '|' >>
many1Till anyChar newline)
@@ -571,25 +655,25 @@ gridTableHeader headless block = try $ do
then replicate (length dashes) ""
else map (intercalate " ") $ transpose
$ map (gridTableSplitLine indices) rawContent
- heads <- mapM (parseFromString $ many block) $
+ heads <- mapM (parseFromString blocks) $
map removeLeadingTrailingSpace rawHeads
return (heads, aligns, indices)
-gridTableRawLine :: [Int] -> GenParser Char ParserState [String]
+gridTableRawLine :: [Int] -> Parser [Char] ParserState [String]
gridTableRawLine indices = do
char '|'
line <- many1Till anyChar newline
return (gridTableSplitLine indices line)
-- | Parse row of grid table.
-gridTableRow :: GenParser Char ParserState Block
+gridTableRow :: Parser [Char] ParserState [Block]
-> [Int]
- -> GenParser Char ParserState [[Block]]
-gridTableRow block indices = do
+ -> Parser [Char] ParserState [[Block]]
+gridTableRow blocks indices = do
colLines <- many1 (gridTableRawLine indices)
let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
transpose colLines
- mapM (liftM compactifyCell . parseFromString (many block)) cols
+ mapM (liftM compactifyCell . parseFromString blocks) cols
removeOneLeadingSpace :: [String] -> [String]
removeOneLeadingSpace xs =
@@ -603,23 +687,23 @@ compactifyCell :: [Block] -> [Block]
compactifyCell bs = head $ compactify [bs]
-- | Parse footer for a grid table.
-gridTableFooter :: GenParser Char ParserState [Char]
+gridTableFooter :: Parser [Char] ParserState [Char]
gridTableFooter = blanklines
---
-- | Parse a string with a given parser and state.
-readWith :: GenParser t ParserState a -- ^ parser
+readWith :: Parser [t] ParserState a -- ^ parser
-> ParserState -- ^ initial state
-> [t] -- ^ input
-> a
-readWith parser state input =
+readWith parser state input =
case runParser parser state "source" input of
Left err' -> error $ "\nError:\n" ++ show err'
Right result -> result
-- | Parse a string with @parser@ (for testing).
-testStringWith :: (Show a) => GenParser Char ParserState a
+testStringWith :: (Show a) => Parser [Char] ParserState a
-> String
-> IO ()
testStringWith parser str = UTF8.putStrLn $ show $
@@ -627,72 +711,67 @@ testStringWith parser str = UTF8.putStrLn $ show $
-- | Parsing options.
data ParserState = ParserState
- { stateParseRaw :: Bool, -- ^ Parse raw HTML and LaTeX?
+ { stateOptions :: ReaderOptions, -- ^ User options
stateParserContext :: ParserContext, -- ^ Inside list?
stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment?
+ stateAllowLinks :: Bool, -- ^ Allow parsing of links
stateMaxNestingLevel :: Int, -- ^ Max # of nested Strong/Emph
stateLastStrPos :: Maybe SourcePos, -- ^ Position after last str parsed
- stateKeys :: KeyTable, -- ^ List of reference keys
- stateCitations :: [String], -- ^ List of available citations
- stateNotes :: NoteTable, -- ^ List of notes
- stateTabStop :: Int, -- ^ Tab stop
- stateStandalone :: Bool, -- ^ Parse bibliographic info?
+ stateKeys :: KeyTable, -- ^ List of reference keys (with fallbacks)
+ stateNotes :: NoteTable, -- ^ List of notes (raw bodies)
+ stateNotes' :: NoteTable', -- ^ List of notes (parsed bodies)
stateTitle :: [Inline], -- ^ Title of document
stateAuthors :: [[Inline]], -- ^ Authors of document
stateDate :: [Inline], -- ^ Date of document
- stateStrict :: Bool, -- ^ Use strict markdown syntax?
- stateSmart :: Bool, -- ^ Use smart typography?
- stateOldDashes :: Bool, -- ^ Use pandoc <= 1.8.2.1 behavior
- -- in parsing dashes; -- is em-dash;
- -- before numeral is en-dash
- stateLiterateHaskell :: Bool, -- ^ Treat input as literate haskell
- stateColumns :: Int, -- ^ Number of columns in terminal
stateHeaderTable :: [HeaderType], -- ^ Ordered list of header types used
- stateIndentedCodeClasses :: [String], -- ^ Classes to use for indented code blocks
stateNextExample :: Int, -- ^ Number of next example
- stateExamples :: M.Map String Int, -- ^ Map from example labels to numbers
+ stateExamples :: M.Map String Int, -- ^ Map from example labels to numbers
stateHasChapters :: Bool, -- ^ True if \chapter encountered
- stateApplyMacros :: Bool, -- ^ Apply LaTeX macros?
stateMacros :: [Macro], -- ^ List of macros defined so far
stateRstDefaultRole :: String -- ^ Current rST default interpreted text role
}
- deriving Show
+
+instance Default ParserState where
+ def = defaultParserState
defaultParserState :: ParserState
-defaultParserState =
- ParserState { stateParseRaw = False,
+defaultParserState =
+ ParserState { stateOptions = def,
stateParserContext = NullState,
stateQuoteContext = NoQuote,
+ stateAllowLinks = True,
stateMaxNestingLevel = 6,
stateLastStrPos = Nothing,
stateKeys = M.empty,
- stateCitations = [],
stateNotes = [],
- stateTabStop = 4,
- stateStandalone = False,
+ stateNotes' = [],
stateTitle = [],
stateAuthors = [],
stateDate = [],
- stateStrict = False,
- stateSmart = False,
- stateOldDashes = False,
- stateLiterateHaskell = False,
- stateColumns = 80,
stateHeaderTable = [],
- stateIndentedCodeClasses = [],
stateNextExample = 1,
stateExamples = M.empty,
stateHasChapters = False,
- stateApplyMacros = True,
stateMacros = [],
stateRstDefaultRole = "title-reference"}
-data HeaderType
+getOption :: (ReaderOptions -> a) -> Parser s ParserState a
+getOption f = (f . stateOptions) `fmap` getState
+
+-- | Succeed only if the extension is enabled.
+guardEnabled :: Extension -> Parser s ParserState ()
+guardEnabled ext = getOption readerExtensions >>= guard . Set.member ext
+
+-- | Succeed only if the extension is disabled.
+guardDisabled :: Extension -> Parser s ParserState ()
+guardDisabled ext = getOption readerExtensions >>= guard . not . Set.member ext
+
+data HeaderType
= SingleHeader Char -- ^ Single line of characters underneath
| DoubleHeader Char -- ^ Lines of characters above and below
deriving (Eq, Show)
-data ParserContext
+data ParserContext
= ListItemState -- ^ Used when running parser on list item contents
| NullState -- ^ Default state
deriving (Eq, Show)
@@ -705,51 +784,35 @@ data QuoteContext
type NoteTable = [(String, String)]
-newtype Key = Key [Inline] deriving (Show, Read, Eq, Ord)
+type NoteTable' = [(String, F Blocks)] -- used in markdown reader
-toKey :: [Inline] -> Key
-toKey = Key . bottomUp lowercase
- where lowercase :: Inline -> Inline
- lowercase (Str xs) = Str (map toLower xs)
- lowercase (Math t xs) = Math t (map toLower xs)
- lowercase (Code attr xs) = Code attr (map toLower xs)
- lowercase (RawInline f xs) = RawInline f (map toLower xs)
- lowercase LineBreak = Space
- lowercase x = x
+newtype Key = Key String deriving (Show, Read, Eq, Ord)
-fromKey :: Key -> [Inline]
-fromKey (Key xs) = xs
+toKey :: String -> Key
+toKey = Key . map toLower . unwords . words
type KeyTable = M.Map Key Target
--- | Look up key in key table and return target object.
-lookupKeySrc :: KeyTable -- ^ Key table
- -> Key -- ^ Key
- -> Maybe Target
-lookupKeySrc table key = case M.lookup key table of
- Nothing -> Nothing
- Just src -> Just src
-
-- | Fail unless we're in "smart typography" mode.
-failUnlessSmart :: GenParser tok ParserState ()
-failUnlessSmart = getState >>= guard . stateSmart
+failUnlessSmart :: Parser [tok] ParserState ()
+failUnlessSmart = getOption readerSmart >>= guard
-smartPunctuation :: GenParser Char ParserState Inline
- -> GenParser Char ParserState Inline
+smartPunctuation :: Parser [Char] ParserState Inline
+ -> Parser [Char] ParserState Inline
smartPunctuation inlineParser = do
failUnlessSmart
choice [ quoted inlineParser, apostrophe, dash, ellipses ]
-apostrophe :: GenParser Char ParserState Inline
+apostrophe :: Parser [Char] ParserState Inline
apostrophe = (char '\'' <|> char '\8217') >> return (Str "\x2019")
-quoted :: GenParser Char ParserState Inline
- -> GenParser Char ParserState Inline
+quoted :: Parser [Char] ParserState Inline
+ -> Parser [Char] ParserState Inline
quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser
withQuoteContext :: QuoteContext
- -> (GenParser Char ParserState Inline)
- -> GenParser Char ParserState Inline
+ -> Parser [Char] ParserState a
+ -> Parser [Char] ParserState a
withQuoteContext context parser = do
oldState <- getState
let oldQuoteContext = stateQuoteContext oldState
@@ -759,39 +822,39 @@ withQuoteContext context parser = do
setState newState { stateQuoteContext = oldQuoteContext }
return result
-singleQuoted :: GenParser Char ParserState Inline
- -> GenParser Char ParserState Inline
+singleQuoted :: Parser [Char] ParserState Inline
+ -> Parser [Char] ParserState Inline
singleQuoted inlineParser = try $ do
singleQuoteStart
withQuoteContext InSingleQuote $ many1Till inlineParser singleQuoteEnd >>=
return . Quoted SingleQuote . normalizeSpaces
-doubleQuoted :: GenParser Char ParserState Inline
- -> GenParser Char ParserState Inline
+doubleQuoted :: Parser [Char] ParserState Inline
+ -> Parser [Char] ParserState Inline
doubleQuoted inlineParser = try $ do
doubleQuoteStart
withQuoteContext InDoubleQuote $ do
contents <- manyTill inlineParser doubleQuoteEnd
return . Quoted DoubleQuote . normalizeSpaces $ contents
-failIfInQuoteContext :: QuoteContext -> GenParser tok ParserState ()
+failIfInQuoteContext :: QuoteContext -> Parser [tok] ParserState ()
failIfInQuoteContext context = do
st <- getState
if stateQuoteContext st == context
then fail "already inside quotes"
else return ()
-charOrRef :: [Char] -> GenParser Char st Char
+charOrRef :: [Char] -> Parser [Char] st Char
charOrRef cs =
oneOf cs <|> try (do c <- characterReference
guard (c `elem` cs)
return c)
-updateLastStrPos :: GenParser Char ParserState ()
-updateLastStrPos = getPosition >>= \p ->
+updateLastStrPos :: Parser [Char] ParserState ()
+updateLastStrPos = getPosition >>= \p ->
updateState $ \s -> s{ stateLastStrPos = Just p }
-singleQuoteStart :: GenParser Char ParserState ()
+singleQuoteStart :: Parser [Char] ParserState ()
singleQuoteStart = do
failIfInQuoteContext InSingleQuote
pos <- getPosition
@@ -802,61 +865,61 @@ singleQuoteStart = do
notFollowedBy (oneOf ")!],;:-? \t\n")
notFollowedBy (char '.') <|> lookAhead (string "..." >> return ())
notFollowedBy (try (oneOfStrings ["s","t","m","ve","ll","re"] >>
- satisfy (not . isAlphaNum)))
+ satisfy (not . isAlphaNum)))
-- possess/contraction
return ()
-singleQuoteEnd :: GenParser Char st ()
+singleQuoteEnd :: Parser [Char] st ()
singleQuoteEnd = try $ do
charOrRef "'\8217\146"
notFollowedBy alphaNum
-doubleQuoteStart :: GenParser Char ParserState ()
+doubleQuoteStart :: Parser [Char] ParserState ()
doubleQuoteStart = do
failIfInQuoteContext InDoubleQuote
try $ do charOrRef "\"\8220\147"
notFollowedBy (satisfy (\c -> c == ' ' || c == '\t' || c == '\n'))
-doubleQuoteEnd :: GenParser Char st ()
+doubleQuoteEnd :: Parser [Char] st ()
doubleQuoteEnd = do
charOrRef "\"\8221\148"
return ()
-ellipses :: GenParser Char st Inline
+ellipses :: Parser [Char] st Inline
ellipses = do
try (charOrRef "\8230\133") <|> try (string "..." >> return '…')
return (Str "\8230")
-dash :: GenParser Char ParserState Inline
+dash :: Parser [Char] ParserState Inline
dash = do
- oldDashes <- stateOldDashes `fmap` getState
+ oldDashes <- getOption readerOldDashes
if oldDashes
then emDashOld <|> enDashOld
else Str `fmap` (hyphenDash <|> emDash <|> enDash)
-- Two hyphens = en-dash, three = em-dash
-hyphenDash :: GenParser Char st String
+hyphenDash :: Parser [Char] st String
hyphenDash = do
try $ string "--"
option "\8211" (char '-' >> return "\8212")
-emDash :: GenParser Char st String
+emDash :: Parser [Char] st String
emDash = do
try (charOrRef "\8212\151")
return "\8212"
-enDash :: GenParser Char st String
+enDash :: Parser [Char] st String
enDash = do
try (charOrRef "\8212\151")
return "\8211"
-enDashOld :: GenParser Char st Inline
+enDashOld :: Parser [Char] st Inline
enDashOld = do
try (charOrRef "\8211\150") <|>
try (char '-' >> lookAhead (satisfy isDigit) >> return '–')
return (Str "\8211")
-emDashOld :: GenParser Char st Inline
+emDashOld :: Parser [Char] st Inline
emDashOld = do
try (charOrRef "\8212\151") <|> (try $ string "--" >> optional (char '-') >> return '-')
return (Str "\8212")
@@ -866,24 +929,24 @@ emDashOld = do
--
-- | Parse a \newcommand or \renewcommand macro definition.
-macro :: GenParser Char ParserState Block
+macro :: Parser [Char] ParserState Block
macro = do
- apply <- stateApplyMacros `fmap` getState
+ apply <- getOption readerApplyMacros
inp <- getInput
case parseMacroDefinitions inp of
- ([], _) -> pzero
- (ms, rest) -> do def <- count (length inp - length rest) anyChar
+ ([], _) -> mzero
+ (ms, rest) -> do def' <- count (length inp - length rest) anyChar
if apply
then do
updateState $ \st ->
st { stateMacros = ms ++ stateMacros st }
return Null
- else return $ RawBlock "latex" def
+ else return $ RawBlock "latex" def'
-- | Apply current macros to string.
-applyMacros' :: String -> GenParser Char ParserState String
+applyMacros' :: String -> Parser [Char] ParserState String
applyMacros' target = do
- apply <- liftM stateApplyMacros getState
+ apply <- getOption readerApplyMacros
if apply
then do macros <- liftM stateMacros getState
return $ applyMacros macros target
diff --git a/src/Text/Pandoc/Pretty.hs b/src/Text/Pandoc/Pretty.hs
index 0372dbe5d..211fdf20e 100644
--- a/src/Text/Pandoc/Pretty.hs
+++ b/src/Text/Pandoc/Pretty.hs
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111(-1)307 USA
{- |
Module : Text.Pandoc.Pretty
Copyright : Copyright (C) 2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -202,18 +202,17 @@ chomp d = Doc (fromList dl')
outp :: (IsString a, Monoid a)
=> Int -> String -> DocState a
-outp off s | off <= 0 = do
+outp off s | off < 0 = do -- offset < 0 means newline characters
st' <- get
let rawpref = prefix st'
when (column st' == 0 && usePrefix st' && not (null rawpref)) $ do
let pref = reverse $ dropWhile isSpace $ reverse rawpref
modify $ \st -> st{ output = fromString pref : output st
, column = column st + realLength pref }
- when (off < 0) $ do
- modify $ \st -> st { output = fromString s : output st
- , column = 0
- , newlines = newlines st + 1 }
-outp off s = do
+ modify $ \st -> st { output = fromString s : output st
+ , column = 0
+ , newlines = newlines st + 1 }
+outp off s = do -- offset >= 0 (0 might be combining char)
st' <- get
let pref = prefix st'
when (column st' == 0 && usePrefix st' && not (null pref)) $ do
diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs
index 62f7c61a0..685fa1ee4 100644
--- a/src/Text/Pandoc/Readers/DocBook.hs
+++ b/src/Text/Pandoc/Readers/DocBook.hs
@@ -1,6 +1,6 @@
module Text.Pandoc.Readers.DocBook ( readDocBook ) where
import Data.Char (toUpper, isDigit)
-import Text.Pandoc.Parsing (ParserState(..))
+import Text.Pandoc.Options
import Text.Pandoc.Definition
import Text.Pandoc.Builder
import Text.XML.Light
@@ -455,13 +455,13 @@ List of all DocBook tags, with [x] indicating implemented,
[x] tocfront - An entry in a table of contents for a front matter component
[x] toclevel1 - A top-level entry within a table of contents entry for a
chapter-like component
-[x] toclevel2 - A second-level entry within a table of contents entry for a
+[x] toclevel2 - A second-level entry within a table of contents entry for a
chapter-like component
-[x] toclevel3 - A third-level entry within a table of contents entry for a
+[x] toclevel3 - A third-level entry within a table of contents entry for a
chapter-like component
-[x] toclevel4 - A fourth-level entry within a table of contents entry for a
+[x] toclevel4 - A fourth-level entry within a table of contents entry for a
chapter-like component
-[x] toclevel5 - A fifth-level entry within a table of contents entry for a
+[x] toclevel5 - A fifth-level entry within a table of contents entry for a
chapter-like component
[x] tocpart - An entry in a table of contents for a part of a book
[ ] token - A unit of information
@@ -503,7 +503,7 @@ data DBState = DBState{ dbSectionLevel :: Int
, dbBook :: Bool
} deriving Show
-readDocBook :: ParserState -> String -> Pandoc
+readDocBook :: ReaderOptions -> String -> Pandoc
readDocBook _ inp = setTitle (dbDocTitle st')
$ setAuthors (dbDocAuthors st')
$ setDate (dbDocDate st')
@@ -574,7 +574,7 @@ addToStart toadd bs =
(Para xs : rest) -> para (toadd <> fromList xs) <> fromList rest
_ -> bs
--- function that is used by both mediaobject (in parseBlock)
+-- function that is used by both mediaobject (in parseBlock)
-- and inlinemediaobject (in parseInline)
getImage :: Element -> DB Inlines
getImage e = do
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
index 536bddd39..e5c310ffc 100644
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -19,10 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Readers.HTML
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
+ Stability : alpha
Portability : portable
Conversion of HTML to 'Pandoc' document.
@@ -36,18 +36,17 @@ module Text.Pandoc.Readers.HTML ( readHtml
, isCommentTag
) where
-import Text.ParserCombinators.Parsec
-import Text.ParserCombinators.Parsec.Pos
import Text.HTML.TagSoup
import Text.HTML.TagSoup.Match
import Text.Pandoc.Definition
import Text.Pandoc.Builder (text, toList)
import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Parsing
import Data.Maybe ( fromMaybe, isJust )
import Data.List ( intercalate )
-import Data.Char ( isDigit, toLower )
-import Control.Monad ( liftM, guard, when )
+import Data.Char ( isDigit )
+import Control.Monad ( liftM, guard, when, mzero )
isSpace :: Char -> Bool
isSpace ' ' = True
@@ -56,11 +55,11 @@ isSpace '\n' = True
isSpace _ = False
-- | Convert HTML-formatted string to 'Pandoc' document.
-readHtml :: ParserState -- ^ Parser state
+readHtml :: ReaderOptions -- ^ Reader options
-> String -- ^ String to parse (assumes @'\n'@ line endings)
-> Pandoc
-readHtml st inp = Pandoc meta blocks
- where blocks = readWith parseBody st rest
+readHtml opts inp = Pandoc meta blocks
+ where blocks = readWith parseBody def{ stateOptions = opts } rest
tags = canonicalizeTags $
parseTagsOptions parseOptions{ optTagPosition = True } inp
hasHeader = any (~== TagOpen "head" []) tags
@@ -68,7 +67,7 @@ readHtml st inp = Pandoc meta blocks
then parseHeader tags
else (Meta [] [] [], tags)
-type TagParser = GenParser (Tag String) ParserState
+type TagParser = Parser [Tag String] ParserState
-- TODO - fix this - not every header has a title tag
parseHeader :: [Tag String] -> (Meta, [Tag String])
@@ -96,18 +95,6 @@ block = choice
, pRawHtmlBlock
]
--- repeated in SelfContained -- consolidate eventually
-renderTags' :: [Tag String] -> String
-renderTags' = renderTagsOptions
- renderOptions{ optMinimize = \x ->
- let y = map toLower x
- in y == "hr" || y == "br" ||
- y == "img" || y == "meta" ||
- y == "link"
- , optRawTag = \x ->
- let y = map toLower x
- in y == "script" || y == "style" }
-
pList :: TagParser [Block]
pList = pBulletList <|> pOrderedList <|> pDefinitionList
@@ -126,25 +113,22 @@ pBulletList = try $ do
pOrderedList :: TagParser [Block]
pOrderedList = try $ do
TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" [])
- st <- getState
- let (start, style) = if stateStrict st
- then (1, DefaultStyle)
- else (sta', sty')
- where sta = fromMaybe "1" $
- lookup "start" attribs
- sta' = if all isDigit sta
- then read sta
- else 1
- sty = fromMaybe (fromMaybe "" $
- lookup "style" attribs) $
- lookup "class" attribs
- sty' = case sty of
- "lower-roman" -> LowerRoman
- "upper-roman" -> UpperRoman
- "lower-alpha" -> LowerAlpha
- "upper-alpha" -> UpperAlpha
- "decimal" -> Decimal
- _ -> DefaultStyle
+ let (start, style) = (sta', sty')
+ where sta = fromMaybe "1" $
+ lookup "start" attribs
+ sta' = if all isDigit sta
+ then read sta
+ else 1
+ sty = fromMaybe (fromMaybe "" $
+ lookup "style" attribs) $
+ lookup "class" attribs
+ sty' = case sty of
+ "lower-roman" -> LowerRoman
+ "upper-roman" -> UpperRoman
+ "lower-alpha" -> LowerAlpha
+ "upper-alpha" -> UpperAlpha
+ "decimal" -> Decimal
+ _ -> DefaultStyle
let nonItem = pSatisfy (\t ->
not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&
not (t ~== TagClose "ol"))
@@ -196,8 +180,8 @@ pRawTag = do
pRawHtmlBlock :: TagParser [Block]
pRawHtmlBlock = do
raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag
- state <- getState
- if stateParseRaw state && not (null raw)
+ parseRaw <- getOption readerParseRaw
+ if parseRaw && not (null raw)
then return [RawBlock "html" raw]
else return []
@@ -235,7 +219,7 @@ pSimpleTable = try $ do
rows <- pOptInTag "tbody"
$ many1 $ try $ skipMany pBlank >> pInTags "tr" (pCell "td")
skipMany pBlank
- TagClose _ <- pSatisfy (~== TagClose "table")
+ TagClose _ <- pSatisfy (~== TagClose "table")
let cols = maximum $ map length rows
let aligns = replicate cols AlignLeft
let widths = replicate cols 0
@@ -281,10 +265,7 @@ pCodeBlock = try $ do
let attribsId = fromMaybe "" $ lookup "id" attr
let attribsClasses = words $ fromMaybe "" $ lookup "class" attr
let attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr
- st <- getState
- let attribs = if stateStrict st
- then ("",[],[])
- else (attribsId, attribsClasses, attribsKV)
+ let attribs = (attribsId, attribsClasses, attribsKV)
return [CodeBlock attribs result]
inline :: TagParser [Inline]
@@ -310,7 +291,7 @@ pLocation = do
pSat :: (Tag String -> Bool) -> TagParser (Tag String)
pSat f = do
pos <- getPosition
- token show (const pos) (\x -> if f x then Just x else Nothing)
+ token show (const pos) (\x -> if f x then Just x else Nothing)
pSatisfy :: (Tag String -> Bool) -> TagParser (Tag String)
pSatisfy f = try $ optional pLocation >> pSat f
@@ -332,14 +313,13 @@ pStrong :: TagParser [Inline]
pStrong = pInlinesInTags "strong" Strong <|> pInlinesInTags "b" Strong
pSuperscript :: TagParser [Inline]
-pSuperscript = failIfStrict >> pInlinesInTags "sup" Superscript
+pSuperscript = pInlinesInTags "sup" Superscript
pSubscript :: TagParser [Inline]
-pSubscript = failIfStrict >> pInlinesInTags "sub" Subscript
+pSubscript = pInlinesInTags "sub" Subscript
pStrikeout :: TagParser [Inline]
pStrikeout = do
- failIfStrict
pInlinesInTags "s" Strikeout <|>
pInlinesInTags "strike" Strikeout <|>
pInlinesInTags "del" Strikeout <|>
@@ -381,8 +361,8 @@ pCode = try $ do
pRawHtmlInline :: TagParser [Inline]
pRawHtmlInline = do
result <- pSatisfy (tagComment (const True)) <|> pSatisfy isInlineTag
- state <- getState
- if stateParseRaw state
+ parseRaw <- getOption readerParseRaw
+ if parseRaw
then return [RawInline "html" $ renderTags' [result]]
else return []
@@ -417,7 +397,7 @@ pCloses tagtype = try $ do
(TagClose "ul") | tagtype == "li" -> return ()
(TagClose "ol") | tagtype == "li" -> return ()
(TagClose "dl") | tagtype == "li" -> return ()
- _ -> pzero
+ _ -> mzero
pTagText :: TagParser [Inline]
pTagText = try $ do
@@ -432,11 +412,11 @@ pBlank = try $ do
(TagText str) <- pSatisfy isTagText
guard $ all isSpace str
-pTagContents :: GenParser Char ParserState Inline
+pTagContents :: Parser [Char] ParserState Inline
pTagContents =
pStr <|> pSpace <|> smartPunctuation pTagContents <|> pSymbol <|> pBad
-pStr :: GenParser Char ParserState Inline
+pStr :: Parser [Char] ParserState Inline
pStr = do
result <- many1 $ satisfy $ \c ->
not (isSpace c) && not (isSpecial c) && not (isBad c)
@@ -455,13 +435,13 @@ isSpecial '\8220' = True
isSpecial '\8221' = True
isSpecial _ = False
-pSymbol :: GenParser Char ParserState Inline
+pSymbol :: Parser [Char] ParserState Inline
pSymbol = satisfy isSpecial >>= return . Str . (:[])
isBad :: Char -> Bool
isBad c = c >= '\128' && c <= '\159' -- not allowed in HTML
-pBad :: GenParser Char ParserState Inline
+pBad :: Parser [Char] ParserState Inline
pBad = do
c <- satisfy isBad
let c' = case c of
@@ -495,7 +475,7 @@ pBad = do
_ -> '?'
return $ Str [c']
-pSpace :: GenParser Char ParserState Inline
+pSpace :: Parser [Char] ParserState Inline
pSpace = many1 (satisfy isSpace) >> return Space
--
@@ -593,20 +573,19 @@ _ `closes` _ = False
--- parsers for use in markdown, textile readers
-- | Matches a stretch of HTML in balanced tags.
-htmlInBalanced :: (Tag String -> Bool) -> GenParser Char ParserState String
+htmlInBalanced :: (Tag String -> Bool) -> Parser [Char] ParserState String
htmlInBalanced f = try $ do
(TagOpen t _, tag) <- htmlTag f
guard $ '/' `notElem` tag -- not a self-closing tag
- let nonTagChunk = many1 $ satisfy (/= '<')
let stopper = htmlTag (~== TagClose t)
let anytag = liftM snd $ htmlTag (const True)
contents <- many $ notFollowedBy' stopper >>
- (nonTagChunk <|> htmlInBalanced (const True) <|> anytag)
+ (htmlInBalanced f <|> anytag <|> count 1 anyChar)
endtag <- liftM snd stopper
return $ tag ++ concat contents ++ endtag
-- | Matches a tag meeting a certain condition.
-htmlTag :: (Tag String -> Bool) -> GenParser Char ParserState (Tag String, String)
+htmlTag :: (Tag String -> Bool) -> Parser [Char] ParserState (Tag String, String)
htmlTag f = try $ do
lookAhead (char '<')
(next : _) <- getInput >>= return . canonicalizeTags . parseTags
@@ -617,7 +596,7 @@ htmlTag f = try $ do
count (length s + 4) anyChar
skipMany (satisfy (/='>'))
char '>'
- return (next, "<!--" ++ s ++ "-->")
+ return (next, "<!--" ++ s ++ "-->")
_ -> do
rendered <- manyTill anyChar (char '>')
return (next, rendered ++ ">")
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
index 3178945e4..4a5a14d6a 100644
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -33,10 +33,10 @@ module Text.Pandoc.Readers.LaTeX ( readLaTeX,
handleIncludes
) where
-import Text.ParserCombinators.Parsec hiding ((<|>), space, many, optional)
import Text.Pandoc.Definition
import Text.Pandoc.Shared
-import Text.Pandoc.Parsing
+import Text.Pandoc.Options
+import Text.Pandoc.Parsing hiding ((<|>), many, optional, space)
import qualified Text.Pandoc.UTF8 as UTF8
import Data.Char ( chr, ord )
import Control.Monad
@@ -47,12 +47,13 @@ import Data.Monoid
import System.FilePath (replaceExtension)
import Data.List (intercalate)
import qualified Data.Map as M
+import qualified Control.Exception as E
-- | Parse LaTeX from string and return 'Pandoc' document.
-readLaTeX :: ParserState -- ^ Parser state, including options for parser
+readLaTeX :: ReaderOptions -- ^ Reader options
-> String -- ^ String to parse (assumes @'\n'@ line endings)
-> Pandoc
-readLaTeX = readWith parseLaTeX
+readLaTeX opts = readWith parseLaTeX def{ stateOptions = opts }
parseLaTeX :: LP Pandoc
parseLaTeX = do
@@ -64,7 +65,7 @@ parseLaTeX = do
let date' = stateDate st
return $ Pandoc (Meta title' authors' date') $ toList bs
-type LP = GenParser Char ParserState
+type LP = Parser [Char] ParserState
anyControlSeq :: LP String
anyControlSeq = do
@@ -186,7 +187,7 @@ inline = (mempty <$ comment)
<|> (mathInline $ char '$' *> mathChars <* char '$')
<|> (superscript <$> (char '^' *> tok))
<|> (subscript <$> (char '_' *> tok))
- <|> (failUnlessLHS *> char '|' *> doLHSverb)
+ <|> (guardEnabled Ext_literate_haskell *> char '|' *> doLHSverb)
<|> (str <$> count 1 tildeEscape)
<|> (str <$> string "]")
<|> (str <$> string "#") -- TODO print warning?
@@ -230,14 +231,14 @@ ignoreInlines name = (name, doraw <|> (mempty <$ optargs))
where optargs = skipopts *> skipMany (try $ optional sp *> braced)
contseq = '\\':name
doraw = (rawInline "latex" . (contseq ++) . snd) <$>
- (getState >>= guard . stateParseRaw >> (withRaw optargs))
+ (getOption readerParseRaw >>= guard >> (withRaw optargs))
ignoreBlocks :: String -> (String, LP Blocks)
ignoreBlocks name = (name, doraw <|> (mempty <$ optargs))
where optargs = skipopts *> skipMany (try $ optional sp *> braced)
contseq = '\\':name
doraw = (rawBlock "latex" . (contseq ++) . snd) <$>
- (getState >>= guard . stateParseRaw >> (withRaw optargs))
+ (getOption readerParseRaw >>= guard >> (withRaw optargs))
blockCommands :: M.Map String (LP Blocks)
blockCommands = M.fromList $
@@ -321,7 +322,7 @@ inlineCommand :: LP Inlines
inlineCommand = try $ do
name <- anyControlSeq
guard $ not $ isBlockCommand name
- parseRaw <- stateParseRaw `fmap` getState
+ parseRaw <- getOption readerParseRaw
star <- option "" (string "*")
let name' = name ++ star
let rawargs = withRaw (skipopts *> option "" dimenarg
@@ -336,7 +337,7 @@ inlineCommand = try $ do
Nothing -> raw
unlessParseRaw :: LP ()
-unlessParseRaw = getState >>= guard . not . stateParseRaw
+unlessParseRaw = getOption readerParseRaw >>= guard . not
isBlockCommand :: String -> Bool
isBlockCommand s = maybe False (const True) $ M.lookup s blockCommands
@@ -660,7 +661,7 @@ environment = do
rawEnv :: String -> LP Blocks
rawEnv name = do
let addBegin x = "\\begin{" ++ name ++ "}" ++ x
- parseRaw <- stateParseRaw `fmap` getState
+ parseRaw <- getOption readerParseRaw
if parseRaw
then (rawBlock "latex" . addBegin) <$>
(withRaw (env name blocks) >>= applyMacros' . snd)
@@ -671,8 +672,9 @@ handleIncludes :: String -> IO String
handleIncludes [] = return []
handleIncludes ('\\':xs) =
case runParser include defaultParserState "input" ('\\':xs) of
- Right (fs, rest) -> do let getfile f = catch (UTF8.readFile f)
- (\_ -> return "")
+ Right (fs, rest) -> do let getfile f = E.catch (UTF8.readFile f)
+ (\e -> let _ = (e :: E.SomeException)
+ in return "")
yss <- mapM getfile fs
(intercalate "\n" yss ++) `fmap`
handleIncludes rest
@@ -713,10 +715,10 @@ verbatimEnv = do
rest <- getInput
return (r,rest)
-rawLaTeXBlock :: GenParser Char ParserState String
+rawLaTeXBlock :: Parser [Char] ParserState String
rawLaTeXBlock = snd <$> withRaw (environment <|> blockCommand)
-rawLaTeXInline :: GenParser Char ParserState Inline
+rawLaTeXInline :: Parser [Char] ParserState Inline
rawLaTeXInline = do
(res, raw) <- withRaw inlineCommand
if res == mempty
@@ -735,7 +737,7 @@ environments = M.fromList
, ("itemize", bulletList <$> listenv "itemize" (many item))
, ("description", definitionList <$> listenv "description" (many descItem))
, ("enumerate", ordered_list)
- , ("code", failUnlessLHS *>
+ , ("code", guardEnabled Ext_literate_haskell *>
(codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>
verbEnv "code"))
, ("verbatim", codeBlock <$> (verbEnv "verbatim"))
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 51a727996..2407e137c 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -1,4 +1,6 @@
{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7
+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances,
+ GeneralizedNewtypeDeriving #-}
{-
Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
@@ -20,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Readers.Markdown
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -33,26 +35,34 @@ module Text.Pandoc.Readers.Markdown ( readMarkdown ) where
import Data.List ( transpose, sortBy, findIndex, intercalate )
import qualified Data.Map as M
import Data.Ord ( comparing )
-import Data.Char ( isAlphaNum )
+import Data.Char ( isAlphaNum, toLower )
import Data.Maybe
import Text.Pandoc.Definition
-import Text.Pandoc.Generic
-import Text.Pandoc.Shared
-import Text.Pandoc.Parsing
+import qualified Text.Pandoc.Builder as B
+import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>))
+import Text.Pandoc.Options
+import Text.Pandoc.Shared hiding (compactify)
+import Text.Pandoc.Parsing hiding (tableWith)
import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )
import Text.Pandoc.Readers.HTML ( htmlTag, htmlInBalanced, isInlineTag, isBlockTag,
isTextTag, isCommentTag )
import Text.Pandoc.XML ( fromEntities )
-import Text.ParserCombinators.Parsec
-import Control.Monad (when, liftM, guard, mzero)
+import Data.Monoid (mconcat, mempty)
+import Control.Applicative ((<$>), (<*), (*>), (<$))
+import Control.Monad
import Text.HTML.TagSoup
import Text.HTML.TagSoup.Match (tagOpen)
+import qualified Data.Set as Set
-- | Read markdown from an input string and return a Pandoc document.
-readMarkdown :: ParserState -- ^ Parser state, including options for parser
- -> String -- ^ String to parse (assuming @'\n'@ line endings)
+readMarkdown :: ReaderOptions -- ^ Reader options
+ -> String -- ^ String to parse (assuming @'\n'@ line endings)
-> Pandoc
-readMarkdown state s = (readWith parseMarkdown) state (s ++ "\n\n")
+readMarkdown opts s =
+ (readWith parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n")
+
+trimInlinesF :: F Inlines -> F Inlines
+trimInlinesF = liftM trimInlines
--
-- Constants and data structure definitions
@@ -70,7 +80,7 @@ isHruleChar '-' = True
isHruleChar '_' = True
isHruleChar _ = False
-setextHChars :: [Char]
+setextHChars :: String
setextHChars = "=-"
isBlank :: Char -> Bool
@@ -83,71 +93,72 @@ isBlank _ = False
-- auxiliary functions
--
-indentSpaces :: GenParser Char ParserState [Char]
+isNull :: F Inlines -> Bool
+isNull ils = B.isNull $ runF ils def
+
+spnl :: Parser [Char] st ()
+spnl = try $ do
+ skipSpaces
+ optional newline
+ skipSpaces
+ notFollowedBy (char '\n')
+
+indentSpaces :: Parser [Char] ParserState String
indentSpaces = try $ do
- state <- getState
- let tabStop = stateTabStop state
+ tabStop <- getOption readerTabStop
count tabStop (char ' ') <|>
string "\t" <?> "indentation"
-nonindentSpaces :: GenParser Char ParserState [Char]
+nonindentSpaces :: Parser [Char] ParserState String
nonindentSpaces = do
- state <- getState
- let tabStop = stateTabStop state
+ tabStop <- getOption readerTabStop
sps <- many (char ' ')
- if length sps < tabStop
+ if length sps < tabStop
then return sps
else unexpected "indented line"
-skipNonindentSpaces :: GenParser Char ParserState ()
+skipNonindentSpaces :: Parser [Char] ParserState ()
skipNonindentSpaces = do
- state <- getState
- atMostSpaces (stateTabStop state - 1)
+ tabStop <- getOption readerTabStop
+ atMostSpaces (tabStop - 1)
-atMostSpaces :: Int -> GenParser Char ParserState ()
+atMostSpaces :: Int -> Parser [Char] ParserState ()
atMostSpaces 0 = notFollowedBy (char ' ')
atMostSpaces n = (char ' ' >> atMostSpaces (n-1)) <|> return ()
-litChar :: GenParser Char ParserState Char
+litChar :: Parser [Char] ParserState Char
litChar = escapedChar'
<|> noneOf "\n"
<|> (newline >> notFollowedBy blankline >> return ' ')
--- | Fail unless we're at beginning of a line.
-failUnlessBeginningOfLine :: GenParser tok st ()
-failUnlessBeginningOfLine = do
- pos <- getPosition
- if sourceColumn pos == 1 then return () else fail "not beginning of line"
-
-- | Parse a sequence of inline elements between square brackets,
-- including inlines between balanced pairs of square brackets.
-inlinesInBalancedBrackets :: GenParser Char ParserState Inline
- -> GenParser Char ParserState [Inline]
-inlinesInBalancedBrackets parser = try $ do
+inlinesInBalancedBrackets :: Parser [Char] ParserState (F Inlines)
+inlinesInBalancedBrackets = try $ do
char '['
- result <- manyTill ( (do lookAhead $ try $ do (Str res) <- parser
- guard (res == "[")
- bal <- inlinesInBalancedBrackets parser
- return $ [Str "["] ++ bal ++ [Str "]"])
- <|> (count 1 parser))
+ result <- manyTill ( (do lookAhead $ try $ do x <- inline
+ guard (runF x def == B.str "[")
+ bal <- inlinesInBalancedBrackets
+ return $ (\x -> B.str "[" <> x <> B.str "]") <$> bal)
+ <|> inline)
(char ']')
- return $ concat result
+ return $ mconcat result
--
-- document structure
--
-titleLine :: GenParser Char ParserState [Inline]
+titleLine :: Parser [Char] ParserState (F Inlines)
titleLine = try $ do
char '%'
skipSpaces
res <- many $ (notFollowedBy newline >> inline)
<|> try (endline >> whitespace)
newline
- return $ normalizeSpaces res
+ return $ trimInlinesF $ mconcat res
-authorsLine :: GenParser Char ParserState [[Inline]]
-authorsLine = try $ do
+authorsLine :: Parser [Char] ParserState (F [Inlines])
+authorsLine = try $ do
char '%'
skipSpaces
authors <- sepEndBy (many (notFollowedBy (satisfy $ \c ->
@@ -155,67 +166,63 @@ authorsLine = try $ do
(char ';' <|>
try (newline >> notFollowedBy blankline >> spaceChar))
newline
- return $ filter (not . null) $ map normalizeSpaces authors
+ return $ sequence $ filter (not . isNull) $ map (trimInlinesF . mconcat) authors
-dateLine :: GenParser Char ParserState [Inline]
+dateLine :: Parser [Char] ParserState (F Inlines)
dateLine = try $ do
char '%'
skipSpaces
- date <- manyTill inline newline
- return $ normalizeSpaces date
-
-titleBlock :: GenParser Char ParserState ([Inline], [[Inline]], [Inline])
-titleBlock = try $ do
- failIfStrict
- title <- option [] titleLine
- author <- option [] authorsLine
- date <- option [] dateLine
+ trimInlinesF . mconcat <$> manyTill inline newline
+
+titleBlock :: Parser [Char] ParserState (F Inlines, F [Inlines], F Inlines)
+titleBlock = pandocTitleBlock <|> mmdTitleBlock
+
+pandocTitleBlock :: Parser [Char] ParserState (F Inlines, F [Inlines], F Inlines)
+pandocTitleBlock = try $ do
+ guardEnabled Ext_pandoc_title_block
+ title <- option mempty titleLine
+ author <- option (return []) authorsLine
+ date <- option mempty dateLine
optional blanklines
return (title, author, date)
-parseMarkdown :: GenParser Char ParserState Pandoc
+mmdTitleBlock :: Parser [Char] ParserState (F Inlines, F [Inlines], F Inlines)
+mmdTitleBlock = try $ do
+ guardEnabled Ext_mmd_title_block
+ kvPairs <- many1 kvPair
+ blanklines
+ let title = maybe mempty return $ lookup "title" kvPairs
+ let author = maybe mempty (\x -> return [x]) $ lookup "author" kvPairs
+ let date = maybe mempty return $ lookup "date" kvPairs
+ return (title, author, date)
+
+kvPair :: Parser [Char] ParserState (String, Inlines)
+kvPair = try $ do
+ key <- many1Till (alphaNum <|> oneOf "_- ") (char ':')
+ val <- manyTill anyChar
+ (try $ newline >> lookAhead (blankline <|> nonspaceChar))
+ let key' = concat $ words $ map toLower key
+ let val' = trimInlines $ B.text val
+ return (key',val')
+
+parseMarkdown :: Parser [Char] ParserState Pandoc
parseMarkdown = do
-- markdown allows raw HTML
- updateState (\state -> state { stateParseRaw = True })
- startPos <- getPosition
- -- go through once just to get list of reference keys and notes
- -- docMinusKeys is the raw document with blanks where the keys/notes were...
- st <- getState
- let firstPassParser = referenceKey
- <|> (if stateStrict st then pzero else noteBlock)
- <|> liftM snd (withRaw codeBlockDelimited)
- <|> lineClump
- docMinusKeys <- liftM concat $ manyTill firstPassParser eof
- setInput docMinusKeys
- setPosition startPos
- st' <- getState
- let reversedNotes = stateNotes st'
- updateState $ \s -> s { stateNotes = reverse reversedNotes }
- -- now parse it for real...
- (title, author, date) <- option ([],[],[]) titleBlock
+ updateState $ \state -> state { stateOptions =
+ let oldOpts = stateOptions state in
+ oldOpts{ readerParseRaw = True } }
+ (title, authors, date) <- option (mempty,return [],mempty) titleBlock
blocks <- parseBlocks
- let doc = Pandoc (Meta title author date) $ filter (/= Null) blocks
- -- if there are labeled examples, change references into numbers
- examples <- liftM stateExamples getState
- let handleExampleRef :: Inline -> Inline
- handleExampleRef z@(Str ('@':xs)) =
- case M.lookup xs examples of
- Just n -> Str (show n)
- Nothing -> z
- handleExampleRef z = z
- if M.null examples
- then return doc
- else return $ bottomUp handleExampleRef doc
-
---
--- initial pass for references and notes
---
+ st <- getState
+ return $ B.setTitle (runF title st)
+ $ B.setAuthors (runF authors st)
+ $ B.setDate (runF date st)
+ $ B.doc $ runF blocks st
-referenceKey :: GenParser Char ParserState [Char]
+referenceKey :: Parser [Char] ParserState (F Blocks)
referenceKey = try $ do
- startPos <- getPosition
skipNonindentSpaces
- lab <- reference
+ (_,raw) <- reference
char ':'
skipSpaces >> optional newline >> skipSpaces >> notFollowedBy (char '[')
let sourceURL = liftM unwords $ many $ try $ do
@@ -223,22 +230,20 @@ referenceKey = try $ do
skipMany spaceChar
optional $ newline >> notFollowedBy blankline
skipMany spaceChar
- notFollowedBy' reference
+ notFollowedBy' (() <$ reference)
many1 $ escapedChar' <|> satisfy (not . isBlank)
let betweenAngles = try $ char '<' >>
manyTill (escapedChar' <|> litChar) (char '>')
src <- try betweenAngles <|> sourceURL
tit <- option "" referenceTitle
blanklines
- endPos <- getPosition
let target = (escapeURI $ removeTrailingSpace src, tit)
st <- getState
let oldkeys = stateKeys st
- updateState $ \s -> s { stateKeys = M.insert (toKey lab) target oldkeys }
- -- return blanks so line count isn't affected
- return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
+ updateState $ \s -> s { stateKeys = M.insert (toKey raw) target oldkeys }
+ return $ return mempty
-referenceTitle :: GenParser Char ParserState String
+referenceTitle :: Parser [Char] ParserState String
referenceTitle = try $ do
skipSpaces >> optional newline >> skipSpaces
tit <- (charsInBalanced '(' ')' litChar >>= return . unwords . words)
@@ -247,25 +252,38 @@ referenceTitle = try $ do
notFollowedBy (noneOf ")\n")))
return $ fromEntities tit
-noteMarker :: GenParser Char ParserState [Char]
+-- | PHP Markdown Extra style abbreviation key. Currently
+-- we just skip them, since Pandoc doesn't have an element for
+-- an abbreviation.
+abbrevKey :: Parser [Char] ParserState (F Blocks)
+abbrevKey = do
+ guardEnabled Ext_abbreviations
+ try $ do
+ char '*'
+ reference
+ char ':'
+ skipMany (satisfy (/= '\n'))
+ blanklines
+ return $ return mempty
+
+noteMarker :: Parser [Char] ParserState String
noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']')
-rawLine :: GenParser Char ParserState [Char]
+rawLine :: Parser [Char] ParserState String
rawLine = try $ do
notFollowedBy blankline
notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker
optional indentSpaces
anyLine
-rawLines :: GenParser Char ParserState [Char]
+rawLines :: Parser [Char] ParserState String
rawLines = do
first <- anyLine
rest <- many rawLine
return $ unlines (first:rest)
-noteBlock :: GenParser Char ParserState [Char]
+noteBlock :: Parser [Char] ParserState (F Blocks)
noteBlock = try $ do
- startPos <- getPosition
skipNonindentSpaces
ref <- noteMarker
char ':'
@@ -275,87 +293,75 @@ noteBlock = try $ do
(try (blankline >> indentSpaces >>
notFollowedBy blankline))
optional blanklines
- endPos <- getPosition
- let newnote = (ref, (intercalate "\n" raw) ++ "\n\n")
- st <- getState
- let oldnotes = stateNotes st
- updateState $ \s -> s { stateNotes = newnote : oldnotes }
- -- return blanks so line count isn't affected
- return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
+ parsed <- parseFromString parseBlocks $ unlines raw ++ "\n"
+ let newnote = (ref, parsed)
+ updateState $ \s -> s { stateNotes' = newnote : stateNotes' s }
+ return mempty
--
-- parsing blocks
--
-parseBlocks :: GenParser Char ParserState [Block]
-parseBlocks = manyTill block eof
-
-block :: GenParser Char ParserState Block
-block = do
- st <- getState
- choice (if stateStrict st
- then [ header
- , codeBlockIndented
- , blockQuote
- , hrule
- , bulletList
- , orderedList
- , htmlBlock
- , para
- , plain
- , nullBlock ]
- else [ codeBlockDelimited
- , macro
- , header
- , table
- , codeBlockIndented
- , lhsCodeBlock
- , blockQuote
- , hrule
- , bulletList
- , orderedList
- , definitionList
- , rawTeXBlock
- , para
- , rawHtmlBlocks
- , plain
- , nullBlock ]) <?> "block"
+parseBlocks :: Parser [Char] ParserState (F Blocks)
+parseBlocks = mconcat <$> manyTill block eof
+
+block :: Parser [Char] ParserState (F Blocks)
+block = choice [ codeBlockFenced
+ , codeBlockBackticks
+ , guardEnabled Ext_latex_macros *> (mempty <$ macro)
+ , header
+ , rawTeXBlock
+ , htmlBlock
+ , table
+ , codeBlockIndented
+ , lhsCodeBlock
+ , blockQuote
+ , hrule
+ , bulletList
+ , orderedList
+ , definitionList
+ , noteBlock
+ , referenceKey
+ , abbrevKey
+ , para
+ , plain
+ ] <?> "block"
--
-- header blocks
--
-header :: GenParser Char ParserState Block
+header :: Parser [Char] ParserState (F Blocks)
header = setextHeader <|> atxHeader <?> "header"
-atxHeader :: GenParser Char ParserState Block
+atxHeader :: Parser [Char] ParserState (F Blocks)
atxHeader = try $ do
level <- many1 (char '#') >>= return . length
notFollowedBy (char '.' <|> char ')') -- this would be a list
skipSpaces
- text <- manyTill inline atxClosing >>= return . normalizeSpaces
- return $ Header level text
+ text <- trimInlinesF . mconcat <$> manyTill inline atxClosing
+ return $ B.header level <$> text
-atxClosing :: GenParser Char st [Char]
+atxClosing :: Parser [Char] st String
atxClosing = try $ skipMany (char '#') >> blanklines
-setextHeader :: GenParser Char ParserState Block
+setextHeader :: Parser [Char] ParserState (F Blocks)
setextHeader = try $ do
-- This lookahead prevents us from wasting time parsing Inlines
-- unless necessary -- it gives a significant performance boost.
lookAhead $ anyLine >> many1 (oneOf setextHChars) >> blankline
- text <- many1Till inline newline
+ text <- trimInlinesF . mconcat <$> many1Till inline newline
underlineChar <- oneOf setextHChars
many (char underlineChar)
blanklines
let level = (fromMaybe 0 $ findIndex (== underlineChar) setextHChars) + 1
- return $ Header level (normalizeSpaces text)
+ return $ B.header level <$> text
--
-- hrule block
--
-hrule :: GenParser Char st Block
+hrule :: Parser [Char] st (F Blocks)
hrule = try $ do
skipSpaces
start <- satisfy isHruleChar
@@ -363,32 +369,26 @@ hrule = try $ do
skipMany (spaceChar <|> char start)
newline
optional blanklines
- return HorizontalRule
+ return $ return B.horizontalRule
--
-- code blocks
--
-indentedLine :: GenParser Char ParserState [Char]
+indentedLine :: Parser [Char] ParserState String
indentedLine = indentSpaces >> manyTill anyChar newline >>= return . (++ "\n")
blockDelimiter :: (Char -> Bool)
-> Maybe Int
- -> GenParser Char st (Int, (String, [String], [(String, String)]), Char)
+ -> Parser [Char] st Int
blockDelimiter f len = try $ do
c <- lookAhead (satisfy f)
- size <- case len of
- Just l -> count l (char c) >> many (char c) >> return l
- Nothing -> count 3 (char c) >> many (char c) >>=
- return . (+ 3) . length
- many spaceChar
- attr <- option ([],[],[])
- $ attributes -- ~~~ {.ruby}
- <|> (many1 alphaNum >>= \x -> return ([],[x],[])) -- github variant ```ruby
- blankline
- return (size, attr, c)
+ case len of
+ Just l -> count l (char c) >> many (char c) >> return l
+ Nothing -> count 3 (char c) >> many (char c) >>=
+ return . (+ 3) . length
-attributes :: GenParser Char st ([Char], [[Char]], [([Char], [Char])])
+attributes :: Parser [Char] st (String, [String], [(String, String)])
attributes = try $ do
char '{'
spnl
@@ -400,28 +400,28 @@ attributes = try $ do
| otherwise = firstNonNull xs
return (firstNonNull $ reverse ids, concat classes, concat keyvals)
-attribute :: GenParser Char st ([Char], [[Char]], [([Char], [Char])])
+attribute :: Parser [Char] st (String, [String], [(String, String)])
attribute = identifierAttr <|> classAttr <|> keyValAttr
-identifier :: GenParser Char st [Char]
+identifier :: Parser [Char] st String
identifier = do
first <- letter
rest <- many $ alphaNum <|> oneOf "-_:."
return (first:rest)
-identifierAttr :: GenParser Char st ([Char], [a], [a1])
+identifierAttr :: Parser [Char] st (String, [a], [a1])
identifierAttr = try $ do
char '#'
result <- identifier
return (result,[],[])
-classAttr :: GenParser Char st ([Char], [[Char]], [a])
+classAttr :: Parser [Char] st (String, [String], [a])
classAttr = try $ do
char '.'
result <- identifier
return ("",[result],[])
-keyValAttr :: GenParser Char st ([Char], [a], [([Char], [Char])])
+keyValAttr :: Parser [Char] st (String, [a], [(String, String)])
keyValAttr = try $ do
key <- identifier
char '='
@@ -430,33 +430,49 @@ keyValAttr = try $ do
<|> many nonspaceChar
return ("",[],[(key,val)])
-codeBlockDelimited :: GenParser Char st Block
-codeBlockDelimited = try $ do
- (size, attr, c) <- blockDelimiter (\c -> c == '~' || c == '`') Nothing
- contents <- manyTill anyLine (blockDelimiter (== c) (Just size))
+codeBlockFenced :: Parser [Char] ParserState (F Blocks)
+codeBlockFenced = try $ do
+ guardEnabled Ext_fenced_code_blocks
+ size <- blockDelimiter (=='~') Nothing
+ skipMany spaceChar
+ attr <- option ([],[],[]) $
+ guardEnabled Ext_fenced_code_attributes >> attributes
+ blankline
+ contents <- manyTill anyLine (blockDelimiter (=='~') (Just size))
+ blanklines
+ return $ return $ B.codeBlockWith attr $ intercalate "\n" contents
+
+codeBlockBackticks :: Parser [Char] ParserState (F Blocks)
+codeBlockBackticks = try $ do
+ guardEnabled Ext_backtick_code_blocks
+ blockDelimiter (=='`') (Just 3)
+ skipMany spaceChar
+ cls <- many1 alphaNum
+ blankline
+ contents <- manyTill anyLine $ blockDelimiter (=='`') (Just 3)
blanklines
- return $ CodeBlock attr $ intercalate "\n" contents
+ return $ return $ B.codeBlockWith ("",[cls],[]) $ intercalate "\n" contents
-codeBlockIndented :: GenParser Char ParserState Block
+codeBlockIndented :: Parser [Char] ParserState (F Blocks)
codeBlockIndented = do
- contents <- many1 (indentedLine <|>
+ contents <- many1 (indentedLine <|>
try (do b <- blanklines
l <- indentedLine
return $ b ++ l))
optional blanklines
- st <- getState
- return $ CodeBlock ("", stateIndentedCodeClasses st, []) $
+ classes <- getOption readerIndentedCodeClasses
+ return $ return $ B.codeBlockWith ("", classes, []) $
stripTrailingNewlines $ concat contents
-lhsCodeBlock :: GenParser Char ParserState Block
+lhsCodeBlock :: Parser [Char] ParserState (F Blocks)
lhsCodeBlock = do
- failUnlessLHS
- liftM (CodeBlock ("",["sourceCode","literate","haskell"],[]))
- (lhsCodeBlockBird <|> lhsCodeBlockLaTeX)
- <|> liftM (CodeBlock ("",["sourceCode","haskell"],[]))
- lhsCodeBlockInverseBird
+ guardEnabled Ext_literate_haskell
+ (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>
+ (lhsCodeBlockBird <|> lhsCodeBlockLaTeX))
+ <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$>
+ lhsCodeBlockInverseBird)
-lhsCodeBlockLaTeX :: GenParser Char ParserState String
+lhsCodeBlockLaTeX :: Parser [Char] ParserState String
lhsCodeBlockLaTeX = try $ do
string "\\begin{code}"
manyTill spaceChar newline
@@ -464,13 +480,13 @@ lhsCodeBlockLaTeX = try $ do
blanklines
return $ stripTrailingNewlines contents
-lhsCodeBlockBird :: GenParser Char ParserState String
+lhsCodeBlockBird :: Parser [Char] ParserState String
lhsCodeBlockBird = lhsCodeBlockBirdWith '>'
-lhsCodeBlockInverseBird :: GenParser Char ParserState String
+lhsCodeBlockInverseBird :: Parser [Char] ParserState String
lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<'
-lhsCodeBlockBirdWith :: Char -> GenParser Char ParserState String
+lhsCodeBlockBirdWith :: Char -> Parser [Char] ParserState String
lhsCodeBlockBirdWith c = try $ do
pos <- getPosition
when (sourceColumn pos /= 1) $ fail "Not in first column"
@@ -482,25 +498,24 @@ lhsCodeBlockBirdWith c = try $ do
blanklines
return $ intercalate "\n" lns'
-birdTrackLine :: Char -> GenParser Char st [Char]
+birdTrackLine :: Char -> Parser [Char] st String
birdTrackLine c = try $ do
char c
-- allow html tags on left margin:
when (c == '<') $ notFollowedBy letter
manyTill anyChar newline
-
--
-- block quotes
--
-emailBlockQuoteStart :: GenParser Char ParserState Char
+emailBlockQuoteStart :: Parser [Char] ParserState Char
emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' >>~ optional (char ' ')
-emailBlockQuote :: GenParser Char ParserState [[Char]]
+emailBlockQuote :: Parser [Char] ParserState [String]
emailBlockQuote = try $ do
emailBlockQuoteStart
- raw <- sepBy (many (nonEndline <|>
+ raw <- sepBy (many (nonEndline <|>
(try (endline >> notFollowedBy emailBlockQuoteStart >>
return '\n'))))
(try (newline >> emailBlockQuoteStart))
@@ -508,51 +523,50 @@ emailBlockQuote = try $ do
optional blanklines
return raw
-blockQuote :: GenParser Char ParserState Block
-blockQuote = do
+blockQuote :: Parser [Char] ParserState (F Blocks)
+blockQuote = do
raw <- emailBlockQuote
-- parse the extracted block, which may contain various block elements:
contents <- parseFromString parseBlocks $ (intercalate "\n" raw) ++ "\n\n"
- return $ BlockQuote contents
-
+ return $ B.blockQuote <$> contents
+
--
-- list blocks
--
-bulletListStart :: GenParser Char ParserState ()
+bulletListStart :: Parser [Char] ParserState ()
bulletListStart = try $ do
optional newline -- if preceded by a Plain block in a list context
skipNonindentSpaces
- notFollowedBy' hrule -- because hrules start out just like lists
+ notFollowedBy' (() <$ hrule) -- because hrules start out just like lists
satisfy isBulletListMarker
spaceChar
skipSpaces
-anyOrderedListStart :: GenParser Char ParserState (Int, ListNumberStyle, ListNumberDelim)
+anyOrderedListStart :: Parser [Char] ParserState (Int, ListNumberStyle, ListNumberDelim)
anyOrderedListStart = try $ do
optional newline -- if preceded by a Plain block in a list context
skipNonindentSpaces
notFollowedBy $ string "p." >> spaceChar >> digit -- page number
- state <- getState
- if stateStrict state
- then do many1 digit
- char '.'
- spaceChar
- return (1, DefaultStyle, DefaultDelim)
- else do (num, style, delim) <- anyOrderedListMarker
- -- if it could be an abbreviated first name, insist on more than one space
- if delim == Period && (style == UpperAlpha || (style == UpperRoman &&
- num `elem` [1, 5, 10, 50, 100, 500, 1000]))
- then char '\t' <|> (try $ char ' ' >> spaceChar)
- else spaceChar
- skipSpaces
- return (num, style, delim)
-
-listStart :: GenParser Char ParserState ()
+ (guardDisabled Ext_fancy_lists >>
+ do many1 digit
+ char '.'
+ spaceChar
+ return (1, DefaultStyle, DefaultDelim))
+ <|> do (num, style, delim) <- anyOrderedListMarker
+ -- if it could be an abbreviated first name, insist on more than one space
+ if delim == Period && (style == UpperAlpha || (style == UpperRoman &&
+ num `elem` [1, 5, 10, 50, 100, 500, 1000]))
+ then char '\t' <|> (try $ char ' ' >> spaceChar)
+ else spaceChar
+ skipSpaces
+ return (num, style, delim)
+
+listStart :: Parser [Char] ParserState ()
listStart = bulletListStart <|> (anyOrderedListStart >> return ())
-- parse a line of a list item (start = parser for beginning of list item)
-listLine :: GenParser Char ParserState [Char]
+listLine :: Parser [Char] ParserState String
listLine = try $ do
notFollowedBy blankline
notFollowedBy' (do indentSpaces
@@ -562,8 +576,8 @@ listLine = try $ do
return $ concat chunks ++ "\n"
-- parse raw text for one list item, excluding start marker and continuations
-rawListItem :: GenParser Char ParserState a
- -> GenParser Char ParserState [Char]
+rawListItem :: Parser [Char] ParserState a
+ -> Parser [Char] ParserState String
rawListItem start = try $ do
start
first <- listLine
@@ -571,17 +585,17 @@ rawListItem start = try $ do
blanks <- many blankline
return $ concat (first:rest) ++ blanks
--- continuation of a list item - indented and separated by blankline
+-- continuation of a list item - indented and separated by blankline
-- or (in compact lists) endline.
-- note: nested lists are parsed as continuations
-listContinuation :: GenParser Char ParserState [Char]
+listContinuation :: Parser [Char] ParserState String
listContinuation = try $ do
lookAhead indentSpaces
result <- many1 listContinuationLine
blanks <- many blankline
return $ concat result ++ blanks
-listContinuationLine :: GenParser Char ParserState [Char]
+listContinuationLine :: Parser [Char] ParserState String
listContinuationLine = try $ do
notFollowedBy blankline
notFollowedBy' listStart
@@ -589,8 +603,8 @@ listContinuationLine = try $ do
result <- manyTill anyChar newline
return $ result ++ "\n"
-listItem :: GenParser Char ParserState a
- -> GenParser Char ParserState [Block]
+listItem :: Parser [Char] ParserState a
+ -> Parser [Char] ParserState (F Blocks)
listItem start = try $ do
first <- rawListItem start
continuations <- many listContinuation
@@ -606,38 +620,59 @@ listItem start = try $ do
updateState (\st -> st {stateParserContext = oldContext})
return contents
-orderedList :: GenParser Char ParserState Block
+orderedList :: Parser [Char] ParserState (F Blocks)
orderedList = try $ do
(start, style, delim) <- lookAhead anyOrderedListStart
- items <- many1 $ listItem $ try $
- do optional newline -- if preceded by a Plain block in a list context
- skipNonindentSpaces
- orderedListMarker style delim
- return $ OrderedList (start, style, delim) $ compactify items
-
-bulletList :: GenParser Char ParserState Block
-bulletList =
- many1 (listItem bulletListStart) >>= return . BulletList . compactify
+ unless ((style == DefaultStyle || style == Decimal || style == Example) &&
+ (delim == DefaultDelim || delim == Period)) $
+ guardEnabled Ext_fancy_lists
+ when (style == Example) $ guardEnabled Ext_example_lists
+ items <- fmap sequence $ many1 $ listItem
+ ( try $ do
+ optional newline -- if preceded by Plain block in a list
+ skipNonindentSpaces
+ orderedListMarker style delim )
+ start' <- option 1 $ guardEnabled Ext_startnum >> return start
+ return $ B.orderedListWith (start', style, delim) <$> fmap compactify items
+
+-- | Change final list item from @Para@ to @Plain@ if the list contains
+-- no other @Para@ blocks. (From Shared, modified for Blocks rather than [Block].)
+compactify :: [Blocks] -- ^ List of list items (each a list of blocks)
+ -> [Blocks]
+compactify [] = []
+compactify items =
+ let (others, final) = (init items, last items)
+ in case reverse (B.toList final) of
+ (Para a:xs) -> case [Para x | Para x <- concatMap B.toList items] of
+ -- if this is only Para, change to Plain
+ [_] -> others ++ [B.fromList (reverse $ Plain a : xs)]
+ _ -> items
+ _ -> items
+
+bulletList :: Parser [Char] ParserState (F Blocks)
+bulletList = do
+ items <- fmap sequence $ many1 $ listItem bulletListStart
+ return $ B.bulletList <$> fmap compactify items
-- definition lists
-defListMarker :: GenParser Char ParserState ()
+defListMarker :: Parser [Char] ParserState ()
defListMarker = do
sps <- nonindentSpaces
char ':' <|> char '~'
- st <- getState
- let tabStop = stateTabStop st
+ tabStop <- getOption readerTabStop
let remaining = tabStop - (length sps + 1)
if remaining > 0
then count remaining (char ' ') <|> string "\t"
- else pzero
+ else mzero
return ()
-definitionListItem :: GenParser Char ParserState ([Inline], [[Block]])
+definitionListItem :: Parser [Char] ParserState (F (Inlines, [Blocks]))
definitionListItem = try $ do
+ guardEnabled Ext_definition_lists
-- first, see if this has any chance of being a definition list:
lookAhead (anyLine >> optional blankline >> defListMarker)
- term <- manyTill inline newline
+ term <- trimInlinesF . mconcat <$> manyTill inline newline
optional blankline
raw <- many1 defRawBlock
state <- getState
@@ -645,9 +680,9 @@ definitionListItem = try $ do
-- parse the extracted block, which may contain various block elements:
contents <- mapM (parseFromString parseBlocks) raw
updateState (\st -> st {stateParserContext = oldContext})
- return ((normalizeSpaces term), contents)
+ return $ liftM2 (,) term (sequence contents)
-defRawBlock :: GenParser Char ParserState [Char]
+defRawBlock :: Parser [Char] ParserState String
defRawBlock = try $ do
defListMarker
firstline <- anyLine
@@ -659,119 +694,149 @@ defRawBlock = try $ do
return $ unlines lns ++ trl
return $ firstline ++ "\n" ++ unlines rawlines ++ trailing ++ cont
-definitionList :: GenParser Char ParserState Block
+definitionList :: Parser [Char] ParserState (F Blocks)
definitionList = do
- items <- many1 definitionListItem
- -- "compactify" the definition list:
- let defs = map snd items
- let defBlocks = reverse $ concat $ concat defs
- let isPara (Para _) = True
+ items <- fmap sequence $ many1 definitionListItem
+ return $ B.definitionList <$> fmap compactifyDL items
+
+compactifyDL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
+compactifyDL items =
+ let defs = concatMap snd items
+ defBlocks = reverse $ concatMap B.toList defs
+ isPara (Para _) = True
isPara _ = False
- let items' = case take 1 defBlocks of
- [Para x] -> if not $ any isPara (drop 1 defBlocks)
- then let (t,ds) = last items
- lastDef = last ds
- ds' = init ds ++
- [init lastDef ++ [Plain x]]
- in init items ++ [(t, ds')]
- else items
- _ -> items
- return $ DefinitionList items'
+ in case defBlocks of
+ (Para x:_) -> if not $ any isPara (drop 1 defBlocks)
+ then let (t,ds) = last items
+ lastDef = B.toList $ last ds
+ ds' = init ds ++
+ [B.fromList $ init lastDef ++ [Plain x]]
+ in init items ++ [(t, ds')]
+ else items
+ _ -> items
--
-- paragraph block
--
+{-
isHtmlOrBlank :: Inline -> Bool
isHtmlOrBlank (RawInline "html" _) = True
isHtmlOrBlank (Space) = True
isHtmlOrBlank (LineBreak) = True
isHtmlOrBlank _ = False
+-}
-para :: GenParser Char ParserState Block
-para = try $ do
- result <- liftM normalizeSpaces $ many1 inline
- guard $ not . all isHtmlOrBlank $ result
- option (Plain result) $ try $ do
+para :: Parser [Char] ParserState (F Blocks)
+para = try $ do
+ result <- trimInlinesF . mconcat <$> many1 inline
+ -- TODO remove this if not really needed? and remove isHtmlOrBlank
+ -- guard $ not $ F.all isHtmlOrBlank result
+ option (B.plain <$> result) $ try $ do
newline
- blanklines <|>
- (getState >>= guard . stateStrict >>
- lookAhead (blockQuote <|> header) >> return "")
- return $ Para result
+ (blanklines >> return mempty)
+ <|> (guardDisabled Ext_blank_before_blockquote >> lookAhead blockQuote)
+ <|> (guardDisabled Ext_blank_before_header >> lookAhead header)
+ return $ B.para <$> result
-plain :: GenParser Char ParserState Block
-plain = many1 inline >>~ spaces >>= return . Plain . normalizeSpaces
+plain :: Parser [Char] ParserState (F Blocks)
+plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline <* spaces
---
+--
-- raw html
--
-htmlElement :: GenParser Char ParserState [Char]
+htmlElement :: Parser [Char] ParserState String
htmlElement = strictHtmlBlock <|> liftM snd (htmlTag isBlockTag)
-htmlBlock :: GenParser Char ParserState Block
-htmlBlock = try $ do
- failUnlessBeginningOfLine
+htmlBlock :: Parser [Char] ParserState (F Blocks)
+htmlBlock = do
+ guardEnabled Ext_raw_html
+ res <- (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks)
+ <|> htmlBlock'
+ return $ return $ B.rawBlock "html" res
+
+htmlBlock' :: Parser [Char] ParserState String
+htmlBlock' = try $ do
first <- htmlElement
finalSpace <- many spaceChar
finalNewlines <- many newline
- return $ RawBlock "html" $ first ++ finalSpace ++ finalNewlines
+ return $ first ++ finalSpace ++ finalNewlines
-strictHtmlBlock :: GenParser Char ParserState [Char]
-strictHtmlBlock = do
- failUnlessBeginningOfLine
- htmlInBalanced (not . isInlineTag)
+strictHtmlBlock :: Parser [Char] ParserState String
+strictHtmlBlock = htmlInBalanced (not . isInlineTag)
-rawVerbatimBlock :: GenParser Char ParserState String
+rawVerbatimBlock :: Parser [Char] ParserState String
rawVerbatimBlock = try $ do
(TagOpen tag _, open) <- htmlTag (tagOpen (\t ->
- t == "pre" || t == "style" || t == "script")
- (const True))
+ t == "pre" || t == "style" || t == "script")
+ (const True))
contents <- manyTill anyChar (htmlTag (~== TagClose tag))
return $ open ++ contents ++ renderTags [TagClose tag]
-rawTeXBlock :: GenParser Char ParserState Block
+rawTeXBlock :: Parser [Char] ParserState (F Blocks)
rawTeXBlock = do
- failIfStrict
- result <- liftM (RawBlock "latex") rawLaTeXBlock
- <|> liftM (RawBlock "context") rawConTeXtEnvironment
+ guardEnabled Ext_raw_tex
+ result <- (B.rawBlock "latex" <$> rawLaTeXBlock)
+ <|> (B.rawBlock "context" <$> rawConTeXtEnvironment)
spaces
- return result
+ return $ return result
-rawHtmlBlocks :: GenParser Char ParserState Block
+rawHtmlBlocks :: Parser [Char] ParserState String
rawHtmlBlocks = do
- htmlBlocks <- many1 $ do blk <- rawVerbatimBlock <|>
- liftM snd (htmlTag isBlockTag)
- sps <- do sp1 <- many spaceChar
- sp2 <- option "" (blankline >> return "\n")
- sp3 <- many spaceChar
- sp4 <- option "" blanklines
- return $ sp1 ++ sp2 ++ sp3 ++ sp4
- -- note: we want raw html to be able to
- -- precede a code block, when separated
- -- by a blank line
- return $ blk ++ sps
+ htmlBlocks <- many1 $ try $ do
+ s <- rawVerbatimBlock <|> try (
+ do (t,raw) <- htmlTag isBlockTag
+ exts <- getOption readerExtensions
+ -- if open tag, need markdown="1" if
+ -- markdown_attributes extension is set
+ case t of
+ TagOpen _ as
+ | Ext_markdown_attribute `Set.member`
+ exts ->
+ if "markdown" `notElem`
+ map fst as
+ then mzero
+ else return $
+ stripMarkdownAttribute raw
+ | otherwise -> return raw
+ _ -> return raw )
+ sps <- do sp1 <- many spaceChar
+ sp2 <- option "" (blankline >> return "\n")
+ sp3 <- many spaceChar
+ sp4 <- option "" blanklines
+ return $ sp1 ++ sp2 ++ sp3 ++ sp4
+ -- note: we want raw html to be able to
+ -- precede a code block, when separated
+ -- by a blank line
+ return $ s ++ sps
let combined = concat htmlBlocks
- let combined' = if last combined == '\n' then init combined else combined
- return $ RawBlock "html" combined'
+ return $ if last combined == '\n' then init combined else combined
+
+-- remove markdown="1" attribute
+stripMarkdownAttribute :: String -> String
+stripMarkdownAttribute s = renderTags' $ map filterAttrib $ parseTags s
+ where filterAttrib (TagOpen t as) = TagOpen t
+ [(k,v) | (k,v) <- as, k /= "markdown"]
+ filterAttrib x = x
--
-- Tables
---
+--
-- Parse a dashed line with optional trailing spaces; return its length
-- and the length including trailing space.
-dashedLine :: Char
- -> GenParser Char st (Int, Int)
+dashedLine :: Char
+ -> Parser [Char] st (Int, Int)
dashedLine ch = do
dashes <- many1 (char ch)
sp <- many spaceChar
return $ (length dashes, length $ dashes ++ sp)
--- Parse a table header with dashed lines of '-' preceded by
+-- Parse a table header with dashed lines of '-' preceded by
-- one (or zero) line of text.
-simpleTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
+simpleTableHeader :: Bool -- ^ Headerless table
+ -> Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
simpleTableHeader headless = try $ do
rawContent <- if headless
then return ""
@@ -784,84 +849,104 @@ simpleTableHeader headless = try $ do
-- If no header, calculate alignment on basis of first row of text
rawHeads <- liftM (tail . splitStringByIndices (init indices)) $
if headless
- then lookAhead anyLine
+ then lookAhead anyLine
else return rawContent
let aligns = zipWith alignType (map (\a -> [a]) rawHeads) lengths
let rawHeads' = if headless
then replicate (length dashes) ""
- else rawHeads
- heads <- mapM (parseFromString (many plain)) $
- map removeLeadingTrailingSpace rawHeads'
+ else rawHeads
+ heads <- fmap sequence
+ $ mapM (parseFromString (mconcat <$> many plain))
+ $ map removeLeadingTrailingSpace rawHeads'
return (heads, aligns, indices)
+-- Returns an alignment type for a table, based on a list of strings
+-- (the rows of the column header) and a number (the length of the
+-- dashed line under the rows.
+alignType :: [String]
+ -> Int
+ -> Alignment
+alignType [] _ = AlignDefault
+alignType strLst len =
+ let nonempties = filter (not . null) $ map removeTrailingSpace strLst
+ (leftSpace, rightSpace) =
+ case sortBy (comparing length) nonempties of
+ (x:_) -> (head x `elem` " \t", length x < len)
+ [] -> (False, False)
+ in case (leftSpace, rightSpace) of
+ (True, False) -> AlignRight
+ (False, True) -> AlignLeft
+ (True, True) -> AlignCenter
+ (False, False) -> AlignDefault
+
-- Parse a table footer - dashed lines followed by blank line.
-tableFooter :: GenParser Char ParserState [Char]
+tableFooter :: Parser [Char] ParserState String
tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines
-- Parse a table separator - dashed line.
-tableSep :: GenParser Char ParserState Char
+tableSep :: Parser [Char] ParserState Char
tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n'
-- Parse a raw line and split it into chunks by indices.
rawTableLine :: [Int]
- -> GenParser Char ParserState [String]
+ -> Parser [Char] ParserState [String]
rawTableLine indices = do
notFollowedBy' (blanklines <|> tableFooter)
line <- many1Till anyChar newline
- return $ map removeLeadingTrailingSpace $ tail $
+ return $ map removeLeadingTrailingSpace $ tail $
splitStringByIndices (init indices) line
-- Parse a table line and return a list of lists of blocks (columns).
tableLine :: [Int]
- -> GenParser Char ParserState [[Block]]
-tableLine indices = rawTableLine indices >>= mapM (parseFromString (many plain))
+ -> Parser [Char] ParserState (F [Blocks])
+tableLine indices = rawTableLine indices >>=
+ fmap sequence . mapM (parseFromString (mconcat <$> many plain))
-- Parse a multiline table row and return a list of blocks (columns).
multilineRow :: [Int]
- -> GenParser Char ParserState [[Block]]
+ -> Parser [Char] ParserState (F [Blocks])
multilineRow indices = do
colLines <- many1 (rawTableLine indices)
let cols = map unlines $ transpose colLines
- mapM (parseFromString (many plain)) cols
+ fmap sequence $ mapM (parseFromString (mconcat <$> many plain)) cols
-- Parses a table caption: inlines beginning with 'Table:'
-- and followed by blank lines.
-tableCaption :: GenParser Char ParserState [Inline]
+tableCaption :: Parser [Char] ParserState (F Inlines)
tableCaption = try $ do
+ guardEnabled Ext_table_captions
skipNonindentSpaces
string ":" <|> string "Table:"
- result <- many1 inline
- blanklines
- return $ normalizeSpaces result
+ trimInlinesF . mconcat <$> many1 inline <* blanklines
-- Parse a simple table with '---' header and one line per row.
simpleTable :: Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
+ -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
simpleTable headless = do
- Table c a _w h l <- tableWith (simpleTableHeader headless) tableLine
+ (aligns, _widths, heads', lines') <-
+ tableWith (simpleTableHeader headless) tableLine
(return ())
(if headless then tableFooter else tableFooter <|> blanklines)
- tableCaption
-- Simple tables get 0s for relative column widths (i.e., use default)
- return $ Table c a (replicate (length a) 0) h l
+ return (aligns, replicate (length aligns) 0, heads', lines')
-- Parse a multiline table: starts with row of '-' on top, then header
-- (which may be multiline), then the rows,
-- which may be multiline, separated by blank lines, and
-- ending with a footer (dashed line followed by blank line).
multilineTable :: Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
+ -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
multilineTable headless =
- tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter tableCaption
+ tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter
multilineTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
+ -> Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
multilineTableHeader headless = try $ do
if headless
then return '\n'
else tableSep >>~ notFollowedBy blankline
rawContent <- if headless
- then return $ repeat ""
+ then return $ repeat ""
else many1
(notFollowedBy tableSep >> many1Till anyChar newline)
initSp <- nonindentSpaces
@@ -872,54 +957,206 @@ multilineTableHeader headless = try $ do
rawHeadsList <- if headless
then liftM (map (:[]) . tail .
splitStringByIndices (init indices)) $ lookAhead anyLine
- else return $ transpose $ map
+ else return $ transpose $ map
(\ln -> tail $ splitStringByIndices (init indices) ln)
rawContent
let aligns = zipWith alignType rawHeadsList lengths
let rawHeads = if headless
then replicate (length dashes) ""
else map (intercalate " ") rawHeadsList
- heads <- mapM (parseFromString (many plain)) $
+ heads <- fmap sequence $
+ mapM (parseFromString (mconcat <$> many plain)) $
map removeLeadingTrailingSpace rawHeads
return (heads, aligns, indices)
--- Returns an alignment type for a table, based on a list of strings
--- (the rows of the column header) and a number (the length of the
--- dashed line under the rows.
-alignType :: [String]
- -> Int
- -> Alignment
-alignType [] _ = AlignDefault
-alignType strLst len =
- let nonempties = filter (not . null) $ map removeTrailingSpace strLst
- (leftSpace, rightSpace) =
- case sortBy (comparing length) nonempties of
- (x:_) -> (head x `elem` " \t", length x < len)
- [] -> (False, False)
- in case (leftSpace, rightSpace) of
- (True, False) -> AlignRight
- (False, True) -> AlignLeft
- (True, True) -> AlignCenter
- (False, False) -> AlignDefault
-
+-- Parse a grid table: starts with row of '-' on top, then header
+-- (which may be grid), then the rows,
+-- which may be grid, separated by blank lines, and
+-- ending with a footer (dashed line followed by blank line).
gridTable :: Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
-gridTable = gridTableWith block tableCaption
+ -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
+gridTable headless =
+ tableWith (gridTableHeader headless) gridTableRow
+ (gridTableSep '-') gridTableFooter
+
+gridTableSplitLine :: [Int] -> String -> [String]
+gridTableSplitLine indices line = map removeFinalBar $ tail $
+ splitStringByIndices (init indices) $ removeTrailingSpace line
+
+gridPart :: Char -> Parser [Char] st (Int, Int)
+gridPart ch = do
+ dashes <- many1 (char ch)
+ char '+'
+ return (length dashes, length dashes + 1)
-table :: GenParser Char ParserState Block
-table = multilineTable False <|> simpleTable True <|>
- simpleTable False <|> multilineTable True <|>
- gridTable False <|> gridTable True <?> "table"
+gridDashedLines :: Char -> Parser [Char] st [(Int,Int)]
+gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline
+
+removeFinalBar :: String -> String
+removeFinalBar =
+ reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse
+
+-- | Separator between rows of grid table.
+gridTableSep :: Char -> Parser [Char] ParserState Char
+gridTableSep ch = try $ gridDashedLines ch >> return '\n'
+
+-- | Parse header for a grid table.
+gridTableHeader :: Bool -- ^ Headerless table
+ -> Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
+gridTableHeader headless = try $ do
+ optional blanklines
+ dashes <- gridDashedLines '-'
+ rawContent <- if headless
+ then return $ repeat ""
+ else many1
+ (notFollowedBy (gridTableSep '=') >> char '|' >>
+ many1Till anyChar newline)
+ if headless
+ then return ()
+ else gridTableSep '=' >> return ()
+ let lines' = map snd dashes
+ let indices = scanl (+) 0 lines'
+ let aligns = replicate (length lines') AlignDefault
+ -- RST does not have a notion of alignments
+ let rawHeads = if headless
+ then replicate (length dashes) ""
+ else map (intercalate " ") $ transpose
+ $ map (gridTableSplitLine indices) rawContent
+ heads <- fmap sequence $ mapM (parseFromString block) $
+ map removeLeadingTrailingSpace rawHeads
+ return (heads, aligns, indices)
---
+gridTableRawLine :: [Int] -> Parser [Char] ParserState [String]
+gridTableRawLine indices = do
+ char '|'
+ line <- many1Till anyChar newline
+ return (gridTableSplitLine indices line)
+
+-- | Parse row of grid table.
+gridTableRow :: [Int]
+ -> Parser [Char] ParserState (F [Blocks])
+gridTableRow indices = do
+ colLines <- many1 (gridTableRawLine indices)
+ let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
+ transpose colLines
+ fmap compactify <$> fmap sequence (mapM (parseFromString block) cols)
+
+removeOneLeadingSpace :: [String] -> [String]
+removeOneLeadingSpace xs =
+ if all startsWithSpace xs
+ then map (drop 1) xs
+ else xs
+ where startsWithSpace "" = True
+ startsWithSpace (y:_) = y == ' '
+
+-- | Parse footer for a grid table.
+gridTableFooter :: Parser [Char] ParserState [Char]
+gridTableFooter = blanklines
+
+pipeTable :: Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
+pipeTable = try $ do
+ let pipeBreak = nonindentSpaces *> optional (char '|') *>
+ pipeTableHeaderPart `sepBy1` sepPipe <*
+ optional (char '|') <* blankline
+ (heads,aligns) <- try ( pipeBreak >>= \als ->
+ return (return $ replicate (length als) mempty, als))
+ <|> ( pipeTableRow >>= \row -> pipeBreak >>= \als ->
+
+ return (row, als) )
+ lines' <- sequence <$> many1 pipeTableRow
+ blanklines
+ let widths = replicate (length aligns) 0.0
+ return $ (aligns, widths, heads, lines')
+
+sepPipe :: Parser [Char] ParserState ()
+sepPipe = try $ do
+ char '|' <|> char '+'
+ notFollowedBy blankline
+
+-- parse a row, also returning probable alignments for org-table cells
+pipeTableRow :: Parser [Char] ParserState (F [Blocks])
+pipeTableRow = do
+ nonindentSpaces
+ optional (char '|')
+ let cell = mconcat <$>
+ many (notFollowedBy (blankline <|> char '|') >> inline)
+ first <- cell
+ sepPipe
+ rest <- cell `sepBy1` sepPipe
+ optional (char '|')
+ blankline
+ let cells = sequence (first:rest)
+ return $ do
+ cells' <- cells
+ return $ map
+ (\ils ->
+ case trimInlines ils of
+ ils' | B.isNull ils' -> mempty
+ | otherwise -> B.plain $ ils') cells'
+
+pipeTableHeaderPart :: Parser [Char] st Alignment
+pipeTableHeaderPart = do
+ left <- optionMaybe (char ':')
+ many1 (char '-')
+ right <- optionMaybe (char ':')
+ return $
+ case (left,right) of
+ (Nothing,Nothing) -> AlignDefault
+ (Just _,Nothing) -> AlignLeft
+ (Nothing,Just _) -> AlignRight
+ (Just _,Just _) -> AlignCenter
+
+-- Succeed only if current line contains a pipe.
+scanForPipe :: Parser [Char] st ()
+scanForPipe = lookAhead (manyTill (satisfy (/='\n')) (char '|')) >> return ()
+
+-- | Parse a table using 'headerParser', 'rowParser',
+-- 'lineParser', and 'footerParser'. Variant of the version in
+-- Text.Pandoc.Parsing.
+tableWith :: Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
+ -> ([Int] -> Parser [Char] ParserState (F [Blocks]))
+ -> Parser [Char] ParserState sep
+ -> Parser [Char] ParserState end
+ -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
+tableWith headerParser rowParser lineParser footerParser = try $ do
+ (heads, aligns, indices) <- headerParser
+ lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser
+ footerParser
+ numColumns <- getOption readerColumns
+ let widths = if (indices == [])
+ then replicate (length aligns) 0.0
+ else widthsFromIndices numColumns indices
+ return $ (aligns, widths, heads, lines')
+
+table :: Parser [Char] ParserState (F Blocks)
+table = try $ do
+ frontCaption <- option Nothing (Just <$> tableCaption)
+ (aligns, widths, heads, lns) <-
+ try (guardEnabled Ext_pipe_tables >> scanForPipe >> pipeTable) <|>
+ try (guardEnabled Ext_multiline_tables >>
+ multilineTable False) <|>
+ try (guardEnabled Ext_simple_tables >>
+ (simpleTable True <|> simpleTable False)) <|>
+ try (guardEnabled Ext_multiline_tables >>
+ multilineTable True) <|>
+ try (guardEnabled Ext_grid_tables >>
+ (gridTable False <|> gridTable True)) <?> "table"
+ optional blanklines
+ caption <- case frontCaption of
+ Nothing -> option (return mempty) tableCaption
+ Just c -> return c
+ return $ do
+ caption' <- caption
+ heads' <- heads
+ lns' <- lns
+ return $ B.table caption' (zip aligns widths) heads' lns'
+
+--
-- inline
--
-inline :: GenParser Char ParserState Inline
-inline = choice inlineParsers <?> "inline"
-
-inlineParsers :: [GenParser Char ParserState Inline]
-inlineParsers = [ whitespace
+inline :: Parser [Char] ParserState (F Inlines)
+inline = choice [ whitespace
, str
, endline
, code
@@ -927,8 +1164,8 @@ inlineParsers = [ whitespace
, strong
, emph
, note
- , link
, cite
+ , link
, image
, math
, strikeout
@@ -940,115 +1177,127 @@ inlineParsers = [ whitespace
, escapedChar
, rawLaTeXInline'
, exampleRef
- , smartPunctuation inline
- , charRef
+ , smart
+ , return . B.singleton <$> charRef
, symbol
- , ltSign ]
+ , ltSign
+ ] <?> "inline"
-escapedChar' :: GenParser Char ParserState Char
+escapedChar' :: Parser [Char] ParserState Char
escapedChar' = try $ do
char '\\'
- state <- getState
- if stateStrict state
- then oneOf "\\`*_{}[]()>#+-.!~"
- else satisfy (not . isAlphaNum)
+ (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))
+ <|> oneOf "\\`*_{}[]()>#+-.!~"
-escapedChar :: GenParser Char ParserState Inline
+escapedChar :: Parser [Char] ParserState (F Inlines)
escapedChar = do
result <- escapedChar'
- return $ case result of
- ' ' -> Str "\160" -- "\ " is a nonbreaking space
- '\n' -> LineBreak -- "\[newline]" is a linebreak
- _ -> Str [result]
+ case result of
+ ' ' -> return $ return $ B.str "\160" -- "\ " is a nonbreaking space
+ '\n' -> guardEnabled Ext_escaped_line_breaks >>
+ return (return B.linebreak) -- "\[newline]" is a linebreak
+ _ -> return $ return $ B.str [result]
-ltSign :: GenParser Char ParserState Inline
+ltSign :: Parser [Char] ParserState (F Inlines)
ltSign = do
- st <- getState
- if stateStrict st
- then char '<'
- else notFollowedBy' rawHtmlBlocks >> char '<' -- unless it starts html
- return $ Str ['<']
+ guardDisabled Ext_raw_html
+ <|> guardDisabled Ext_markdown_in_html_blocks
+ <|> (notFollowedBy' rawHtmlBlocks >> return ())
+ char '<'
+ return $ return $ B.str "<"
-exampleRef :: GenParser Char ParserState Inline
+exampleRef :: Parser [Char] ParserState (F Inlines)
exampleRef = try $ do
+ guardEnabled Ext_example_lists
char '@'
lab <- many1 (alphaNum <|> oneOf "-_")
- -- We just return a Str. These are replaced with numbers
- -- later. See the end of parseMarkdown.
- return $ Str $ '@' : lab
-
-symbol :: GenParser Char ParserState Inline
-symbol = do
+ return $ do
+ st <- askF
+ return $ case M.lookup lab (stateExamples st) of
+ Just n -> B.str (show n)
+ Nothing -> B.str ('@':lab)
+
+symbol :: Parser [Char] ParserState (F Inlines)
+symbol = do
result <- noneOf "<\\\n\t "
<|> try (do lookAhead $ char '\\'
- notFollowedBy' rawTeXBlock
+ notFollowedBy' (() <$ rawTeXBlock)
char '\\')
- return $ Str [result]
+ return $ return $ B.str [result]
-- parses inline code, between n `s and n `s
-code :: GenParser Char ParserState Inline
-code = try $ do
+code :: Parser [Char] ParserState (F Inlines)
+code = try $ do
starts <- many1 (char '`')
skipSpaces
result <- many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|>
(char '\n' >> notFollowedBy' blankline >> return " "))
- (try (skipSpaces >> count (length starts) (char '`') >>
+ (try (skipSpaces >> count (length starts) (char '`') >>
notFollowedBy (char '`')))
- attr <- option ([],[],[]) (try $ optional whitespace >> attributes)
- return $ Code attr $ removeLeadingTrailingSpace $ concat result
-
-mathWord :: GenParser Char st [Char]
-mathWord = liftM concat $ many1 mathChunk
-
-mathChunk :: GenParser Char st [Char]
-mathChunk = do char '\\'
- c <- anyChar
- return ['\\',c]
- <|> many1 (satisfy $ \c -> not (isBlank c || c == '\\' || c == '$'))
-
-math :: GenParser Char ParserState Inline
-math = (mathDisplay >>= applyMacros' >>= return . Math DisplayMath)
- <|> (mathInline >>= applyMacros' >>= return . Math InlineMath)
-
-mathDisplay :: GenParser Char ParserState String
-mathDisplay = try $ do
- failIfStrict
- string "$$"
- many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string "$$")
-
-mathInline :: GenParser Char ParserState String
-mathInline = try $ do
- failIfStrict
- char '$'
+ attr <- option ([],[],[]) (try $ guardEnabled Ext_inline_code_attributes >>
+ optional whitespace >> attributes)
+ return $ return $ B.codeWith attr $ removeLeadingTrailingSpace $ concat result
+
+math :: Parser [Char] ParserState (F Inlines)
+math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
+ <|> (return . B.math <$> (mathInline >>= applyMacros'))
+
+mathDisplay :: Parser [Char] ParserState String
+mathDisplay =
+ (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
+ <|> (guardEnabled Ext_tex_math_single_backslash >>
+ mathDisplayWith "\\[" "\\]")
+ <|> (guardEnabled Ext_tex_math_double_backslash >>
+ mathDisplayWith "\\\\[" "\\\\]")
+
+mathDisplayWith :: String -> String -> Parser [Char] ParserState String
+mathDisplayWith op cl = try $ do
+ string op
+ many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl)
+
+mathInline :: Parser [Char] ParserState String
+mathInline =
+ (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
+ <|> (guardEnabled Ext_tex_math_single_backslash >>
+ mathInlineWith "\\(" "\\)")
+ <|> (guardEnabled Ext_tex_math_double_backslash >>
+ mathInlineWith "\\\\(" "\\\\)")
+
+mathInlineWith :: String -> String -> Parser [Char] ParserState String
+mathInlineWith op cl = try $ do
+ string op
notFollowedBy space
- words' <- sepBy1 mathWord (many1 (spaceChar <|> (newline >>~ notFollowedBy' blankline)))
- char '$'
- notFollowedBy digit
- return $ intercalate " " words'
+ words' <- many1Till (count 1 (noneOf "\n\\")
+ <|> (char '\\' >> anyChar >>= \c -> return ['\\',c])
+ <|> count 1 newline <* notFollowedBy' blankline
+ *> return " ")
+ (try $ string cl)
+ notFollowedBy digit -- to prevent capture of $5
+ return $ concat words'
-- to avoid performance problems, treat 4 or more _ or * or ~ or ^ in a row
-- as a literal rather than attempting to parse for emph/strong/strikeout/super/sub
-fours :: GenParser Char st Inline
+fours :: Parser [Char] st (F Inlines)
fours = try $ do
x <- char '*' <|> char '_' <|> char '~' <|> char '^'
count 2 $ satisfy (==x)
rest <- many1 (satisfy (==x))
- return $ Str (x:x:x:rest)
+ return $ return $ B.str (x:x:x:rest)
-- | Parses a list of inlines between start and end delimiters.
inlinesBetween :: (Show b)
- => GenParser Char ParserState a
- -> GenParser Char ParserState b
- -> GenParser Char ParserState [Inline]
+ => Parser [Char] ParserState a
+ -> Parser [Char] ParserState b
+ -> Parser [Char] ParserState (F Inlines)
inlinesBetween start end =
- normalizeSpaces `liftM` try (start >> many1Till inner end)
- where inner = innerSpace <|> (notFollowedBy' whitespace >> inline)
+ (trimInlinesF . mconcat) <$> try (start >> many1Till inner end)
+ where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
innerSpace = try $ whitespace >>~ notFollowedBy' end
-- This is used to prevent exponential blowups for things like:
-- a**a*a**a*a**a*a**a*a**a*a**a*a**
-nested :: GenParser Char ParserState a
- -> GenParser Char ParserState a
+nested :: Parser [Char] ParserState a
+ -> Parser [Char] ParserState a
nested p = do
nestlevel <- stateMaxNestingLevel `fmap` getState
guard $ nestlevel > 0
@@ -1057,54 +1306,57 @@ nested p = do
updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }
return res
-emph :: GenParser Char ParserState Inline
-emph = Emph `fmap` nested
+emph :: Parser [Char] ParserState (F Inlines)
+emph = fmap B.emph <$> nested
(inlinesBetween starStart starEnd <|> inlinesBetween ulStart ulEnd)
where starStart = char '*' >> lookAhead nonspaceChar
- starEnd = notFollowedBy' strong >> char '*'
+ starEnd = notFollowedBy' (() <$ strong) >> char '*'
ulStart = char '_' >> lookAhead nonspaceChar
- ulEnd = notFollowedBy' strong >> char '_'
+ ulEnd = notFollowedBy' (() <$ strong) >> char '_'
-strong :: GenParser Char ParserState Inline
-strong = Strong `liftM` nested
+strong :: Parser [Char] ParserState (F Inlines)
+strong = fmap B.strong <$> nested
(inlinesBetween starStart starEnd <|> inlinesBetween ulStart ulEnd)
where starStart = string "**" >> lookAhead nonspaceChar
starEnd = try $ string "**"
ulStart = string "__" >> lookAhead nonspaceChar
ulEnd = try $ string "__"
-strikeout :: GenParser Char ParserState Inline
-strikeout = Strikeout `liftM`
- (failIfStrict >> inlinesBetween strikeStart strikeEnd)
+strikeout :: Parser [Char] ParserState (F Inlines)
+strikeout = fmap B.strikeout <$>
+ (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)
where strikeStart = string "~~" >> lookAhead nonspaceChar
>> notFollowedBy (char '~')
strikeEnd = try $ string "~~"
-superscript :: GenParser Char ParserState Inline
-superscript = failIfStrict >> enclosed (char '^') (char '^')
- (notFollowedBy spaceChar >> inline) >>= -- may not contain Space
- return . Superscript
+superscript :: Parser [Char] ParserState (F Inlines)
+superscript = fmap B.superscript <$> try (do
+ guardEnabled Ext_superscript
+ char '^'
+ mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^'))
-subscript :: GenParser Char ParserState Inline
-subscript = failIfStrict >> enclosed (char '~') (char '~')
- (notFollowedBy spaceChar >> inline) >>= -- may not contain Space
- return . Subscript
+subscript :: Parser [Char] ParserState (F Inlines)
+subscript = fmap B.subscript <$> try (do
+ guardEnabled Ext_subscript
+ char '~'
+ mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~'))
-whitespace :: GenParser Char ParserState Inline
-whitespace = spaceChar >>
- ( (spaceChar >> skipMany spaceChar >> option Space (endline >> return LineBreak))
- <|> (skipMany spaceChar >> return Space) ) <?> "whitespace"
+whitespace :: Parser [Char] ParserState (F Inlines)
+whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"
+ where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)
+ regsp = skipMany spaceChar >> return B.space
-nonEndline :: GenParser Char st Char
+nonEndline :: Parser [Char] st Char
nonEndline = satisfy (/='\n')
-str :: GenParser Char ParserState Inline
+str :: Parser [Char] ParserState (F Inlines)
str = do
- smart <- stateSmart `fmap` getState
+ isSmart <- readerSmart . stateOptions <$> getState
a <- alphaNum
as <- many $ alphaNum
- <|> (try $ char '_' >>~ lookAhead alphaNum)
- <|> if smart
+ <|> (guardEnabled Ext_intraword_underscores >>
+ try (char '_' >>~ lookAhead alphaNum))
+ <|> if isSmart
then (try $ satisfy (\c -> c == '\'' || c == '\x2019') >>
lookAhead alphaNum >> return '\x2019')
-- for things like l'aide
@@ -1113,15 +1365,16 @@ str = do
updateState $ \s -> s{ stateLastStrPos = Just pos }
let result = a:as
let spacesToNbr = map (\c -> if c == ' ' then '\160' else c)
- if smart
+ if isSmart
then case likelyAbbrev result of
- [] -> return $ Str result
+ [] -> return $ return $ B.str result
xs -> choice (map (\x ->
try (string x >> oneOf " \n" >>
lookAhead alphaNum >>
- return (Str $ result ++ spacesToNbr x ++ "\160"))) xs)
- <|> (return $ Str result)
- else return $ Str result
+ return (return $ B.str
+ $ result ++ spacesToNbr x ++ "\160"))) xs)
+ <|> (return $ return $ B.str result)
+ else return $ return $ B.str result
-- | if the string matches the beginning of an abbreviation (before
-- the first period, return strings that would finish the abbreviation.
@@ -1136,39 +1389,38 @@ likelyAbbrev x =
in map snd $ filter (\(y,_) -> y == x) abbrPairs
-- an endline character that can be treated as a space, not a structural break
-endline :: GenParser Char ParserState Inline
+endline :: Parser [Char] ParserState (F Inlines)
endline = try $ do
newline
notFollowedBy blankline
- st <- getState
- when (stateStrict st) $ do
- notFollowedBy emailBlockQuoteStart
- notFollowedBy (char '#') -- atx header
+ guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart
+ guardEnabled Ext_blank_before_header <|> notFollowedBy (char '#') -- atx header
-- parse potential list-starts differently if in a list:
+ st <- getState
when (stateParserContext st == ListItemState) $ do
notFollowedBy' bulletListStart
notFollowedBy' anyOrderedListStart
- return Space
+ (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))
+ <|> (return $ return B.space)
--
-- links
--
-- a reference label for a link
-reference :: GenParser Char ParserState [Inline]
+reference :: Parser [Char] ParserState (F Inlines, String)
reference = do notFollowedBy' (string "[^") -- footnote reference
- result <- inlinesInBalancedBrackets inline
- return $ normalizeSpaces result
+ withRaw $ trimInlinesF <$> inlinesInBalancedBrackets
-- source for a link, with optional title
-source :: GenParser Char ParserState (String, [Char])
+source :: Parser [Char] ParserState (String, String)
source =
(try $ charsInBalanced '(' ')' litChar >>= parseFromString source') <|>
-- the following is needed for cases like: [ref](/url(a).
(enclosed (char '(') (char ')') litChar >>= parseFromString source')
-- auxiliary function for source
-source' :: GenParser Char ParserState (String, [Char])
+source' :: Parser [Char] ParserState (String, String)
source' = do
skipSpaces
let nl = char '\n' >>~ notFollowedBy blankline
@@ -1186,7 +1438,7 @@ source' = do
eof
return (escapeURI $ removeTrailingSpace src, tit)
-linkTitle :: GenParser Char ParserState String
+linkTitle :: Parser [Char] ParserState String
linkTitle = try $ do
(many1 spaceChar >> option '\n' newline) <|> newline
skipSpaces
@@ -1194,78 +1446,88 @@ linkTitle = try $ do
tit <- manyTill litChar (try (char delim >> skipSpaces >> eof))
return $ fromEntities tit
-link :: GenParser Char ParserState Inline
+link :: Parser [Char] ParserState (F Inlines)
link = try $ do
- lab <- reference
- (src, tit) <- source <|> referenceLink lab
- return $ Link (delinkify lab) (src, tit)
-
-delinkify :: [Inline] -> [Inline]
-delinkify = bottomUp $ concatMap go
- where go (Link lab _) = lab
- go x = [x]
+ st <- getState
+ guard $ stateAllowLinks st
+ setState $ st{ stateAllowLinks = False }
+ (lab,raw) <- reference
+ setState $ st{ stateAllowLinks = True }
+ regLink B.link lab <|> referenceLink B.link (lab,raw)
+
+regLink :: (String -> String -> Inlines -> Inlines)
+ -> F Inlines -> Parser [Char] ParserState (F Inlines)
+regLink constructor lab = try $ do
+ (src, tit) <- source
+ return $ constructor src tit <$> lab
-- a link like [this][ref] or [this][] or [this]
-referenceLink :: [Inline]
- -> GenParser Char ParserState (String, [Char])
-referenceLink lab = do
- ref <- option [] (try (optional (char ' ') >>
- optional (newline >> skipSpaces) >> reference))
- let ref' = if null ref then lab else ref
- state <- getState
- case lookupKeySrc (stateKeys state) (toKey ref') of
- Nothing -> fail "no corresponding key"
- Just target -> return target
-
-autoLink :: GenParser Char ParserState Inline
+referenceLink :: (String -> String -> Inlines -> Inlines)
+ -> (F Inlines, String) -> Parser [Char] ParserState (F Inlines)
+referenceLink constructor (lab, raw) = do
+ raw' <- try (optional (char ' ') >>
+ optional (newline >> skipSpaces) >>
+ (snd <$> reference)) <|> return ""
+ let key = toKey $ if raw' == "[]" || raw' == "" then raw else raw'
+ let dropRB (']':xs) = xs
+ dropRB xs = xs
+ let dropLB ('[':xs) = xs
+ dropLB xs = xs
+ let dropBrackets = reverse . dropRB . reverse . dropLB
+ fallback <- parseFromString (mconcat <$> many inline) $ dropBrackets raw
+ return $ do
+ keys <- asksF stateKeys
+ case M.lookup key keys of
+ Nothing -> (\x -> B.str "[" <> x <> B.str "]" <> B.str raw') <$> fallback
+ Just (src,tit) -> constructor src tit <$> lab
+
+autoLink :: Parser [Char] ParserState (F Inlines)
autoLink = try $ do
char '<'
(orig, src) <- uri <|> emailAddress
char '>'
- st <- getState
- return $ if stateStrict st
- then Link [Str orig] (src, "")
- else Link [Code ("",["url"],[]) orig] (src, "")
+ (guardEnabled Ext_autolink_code_spans >>
+ return (return $ B.link src "" (B.codeWith ("",["url"],[]) orig)))
+ <|> return (return $ B.link src "" (B.str orig))
-image :: GenParser Char ParserState Inline
+image :: Parser [Char] ParserState (F Inlines)
image = try $ do
char '!'
- lab <- reference
- (src, tit) <- source <|> referenceLink lab
- return $ Image lab (src,tit)
+ (lab,raw) <- reference
+ regLink B.image lab <|> referenceLink B.image (lab,raw)
-note :: GenParser Char ParserState Inline
+note :: Parser [Char] ParserState (F Inlines)
note = try $ do
- failIfStrict
+ guardEnabled Ext_footnotes
ref <- noteMarker
- state <- getState
- let notes = stateNotes state
- case lookup ref notes of
- Nothing -> fail "note not found"
- Just raw -> do
- -- We temporarily empty the note list while parsing the note,
- -- so that we don't get infinite loops with notes inside notes...
- -- Note references inside other notes do not work.
- updateState $ \st -> st{ stateNotes = [] }
- contents <- parseFromString parseBlocks raw
- updateState $ \st -> st{ stateNotes = notes }
- return $ Note contents
-
-inlineNote :: GenParser Char ParserState Inline
+ return $ do
+ notes <- asksF stateNotes'
+ case lookup ref notes of
+ Nothing -> return $ B.str $ "[^" ++ ref ++ "]"
+ Just contents -> do
+ st <- askF
+ -- process the note in a context that doesn't resolve
+ -- notes, to avoid infinite looping with notes inside
+ -- notes:
+ let contents' = runF contents st{ stateNotes' = [] }
+ return $ B.note contents'
+
+inlineNote :: Parser [Char] ParserState (F Inlines)
inlineNote = try $ do
- failIfStrict
+ guardEnabled Ext_inline_notes
char '^'
- contents <- inlinesInBalancedBrackets inline
- return $ Note [Para contents]
+ contents <- inlinesInBalancedBrackets
+ return $ B.note . B.para <$> contents
-rawLaTeXInline' :: GenParser Char ParserState Inline
+rawLaTeXInline' :: Parser [Char] ParserState (F Inlines)
rawLaTeXInline' = try $ do
- failIfStrict
+ guardEnabled Ext_raw_tex
lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env
RawInline _ s <- rawLaTeXInline
- return $ RawInline "tex" s -- "tex" because it might be context or latex
+ return $ return $ B.rawInline "tex" s
+ -- "tex" because it might be context or latex
-rawConTeXtEnvironment :: GenParser Char st String
+rawConTeXtEnvironment :: Parser [Char] st String
rawConTeXtEnvironment = try $ do
string "\\start"
completion <- inBrackets (letter <|> digit <|> spaceChar)
@@ -1274,37 +1536,33 @@ rawConTeXtEnvironment = try $ do
(try $ string "\\stop" >> string completion)
return $ "\\start" ++ completion ++ concat contents ++ "\\stop" ++ completion
-inBrackets :: (GenParser Char st Char) -> GenParser Char st String
+inBrackets :: (Parser [Char] st Char) -> Parser [Char] st String
inBrackets parser = do
char '['
contents <- many parser
char ']'
return $ "[" ++ contents ++ "]"
-rawHtmlInline :: GenParser Char ParserState Inline
+rawHtmlInline :: Parser [Char] ParserState (F Inlines)
rawHtmlInline = do
- st <- getState
- (_,result) <- if stateStrict st
- then htmlTag (not . isTextTag)
- else htmlTag isInlineTag
- return $ RawInline "html" result
+ guardEnabled Ext_raw_html
+ mdInHtml <- option False $
+ guardEnabled Ext_markdown_in_html_blocks >> return True
+ (_,result) <- if mdInHtml
+ then htmlTag isInlineTag
+ else htmlTag (not . isTextTag)
+ return $ return $ B.rawInline "html" result
-- Citations
-cite :: GenParser Char ParserState Inline
+cite :: Parser [Char] ParserState (F Inlines)
cite = do
- failIfStrict
+ guardEnabled Ext_citations
+ getOption readerCitations >>= guard . not . null
citations <- textualCite <|> normalCite
- return $ Cite citations []
+ return $ flip B.cite mempty <$> citations
-spnl :: GenParser Char st ()
-spnl = try $ do
- skipSpaces
- optional newline
- skipSpaces
- notFollowedBy (char '\n')
-
-textualCite :: GenParser Char ParserState [Citation]
+textualCite :: Parser [Char] ParserState (F [Citation])
textualCite = try $ do
(_, key) <- citeKey
let first = Citation{ citationId = key
@@ -1314,22 +1572,25 @@ textualCite = try $ do
, citationNoteNum = 0
, citationHash = 0
}
- rest <- option [] $ try $ spnl >> normalCite
- if null rest
- then option [first] $ bareloc first
- else return $ first : rest
+ mbrest <- option Nothing $ try $ spnl >> Just <$> normalCite
+ case mbrest of
+ Just rest -> return $ (first:) <$> rest
+ Nothing -> option (return [first]) $ bareloc first
-bareloc :: Citation -> GenParser Char ParserState [Citation]
+bareloc :: Citation -> Parser [Char] ParserState (F [Citation])
bareloc c = try $ do
spnl
char '['
suff <- suffix
- rest <- option [] $ try $ char ';' >> citeList
+ rest <- option (return []) $ try $ char ';' >> citeList
spnl
char ']'
- return $ c{ citationSuffix = suff } : rest
+ return $ do
+ suff' <- suff
+ rest' <- rest
+ return $ c{ citationSuffix = B.toList suff' } : rest'
-normalCite :: GenParser Char ParserState [Citation]
+normalCite :: Parser [Char] ParserState (F [Citation])
normalCite = try $ do
char '['
spnl
@@ -1338,7 +1599,7 @@ normalCite = try $ do
char ']'
return citations
-citeKey :: GenParser Char ParserState (Bool, String)
+citeKey :: Parser [Char] ParserState (Bool, String)
citeKey = try $ do
suppress_author <- option False (char '-' >> return True)
char '@'
@@ -1346,34 +1607,37 @@ citeKey = try $ do
let internal p = try $ p >>~ lookAhead (letter <|> digit)
rest <- many $ letter <|> digit <|> internal (oneOf ":.#$%&-_?<>~")
let key = first:rest
- st <- getState
- guard $ key `elem` stateCitations st
+ citations' <- getOption readerCitations
+ guard $ key `elem` citations'
return (suppress_author, key)
-suffix :: GenParser Char ParserState [Inline]
+suffix :: Parser [Char] ParserState (F Inlines)
suffix = try $ do
hasSpace <- option False (notFollowedBy nonspaceChar >> return True)
spnl
- rest <- liftM normalizeSpaces $ many $ notFollowedBy (oneOf ";]") >> inline
+ rest <- trimInlinesF . mconcat <$> many (notFollowedBy (oneOf ";]") >> inline)
return $ if hasSpace
- then Space : rest
+ then (B.space <>) <$> rest
else rest
-prefix :: GenParser Char ParserState [Inline]
-prefix = liftM normalizeSpaces $
+prefix :: Parser [Char] ParserState (F Inlines)
+prefix = trimInlinesF . mconcat <$>
manyTill inline (char ']' <|> liftM (const ']') (lookAhead citeKey))
-citeList :: GenParser Char ParserState [Citation]
-citeList = sepBy1 citation (try $ char ';' >> spnl)
+citeList :: Parser [Char] ParserState (F [Citation])
+citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl)
-citation :: GenParser Char ParserState Citation
+citation :: Parser [Char] ParserState (F Citation)
citation = try $ do
pref <- prefix
(suppress_author, key) <- citeKey
suff <- suffix
- return $ Citation{ citationId = key
- , citationPrefix = pref
- , citationSuffix = suff
+ return $ do
+ x <- pref
+ y <- suff
+ return $ Citation{ citationId = key
+ , citationPrefix = B.toList x
+ , citationSuffix = B.toList y
, citationMode = if suppress_author
then SuppressAuthor
else NormalCitation
@@ -1381,3 +1645,22 @@ citation = try $ do
, citationHash = 0
}
+smart :: Parser [Char] ParserState (F Inlines)
+smart = do
+ getOption readerSmart >>= guard
+ doubleQuoted <|> singleQuoted <|>
+ choice (map (return . B.singleton <$>) [apostrophe, dash, ellipses])
+
+singleQuoted :: Parser [Char] ParserState (F Inlines)
+singleQuoted = try $ do
+ singleQuoteStart
+ withQuoteContext InSingleQuote $
+ fmap B.singleQuoted . trimInlinesF . mconcat <$>
+ many1Till inline singleQuoteEnd
+
+doubleQuoted :: Parser [Char] ParserState (F Inlines)
+doubleQuoted = try $ do
+ doubleQuoteStart
+ withQuoteContext InDoubleQuote $
+ fmap B.doubleQuoted . trimInlinesF . mconcat <$>
+ many1Till inline doubleQuoteEnd
diff --git a/src/Text/Pandoc/Readers/Native.hs b/src/Text/Pandoc/Readers/Native.hs
index 2c6fcc6e6..a0e5a0635 100644
--- a/src/Text/Pandoc/Readers/Native.hs
+++ b/src/Text/Pandoc/Readers/Native.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Readers.Native
Copyright : Copyright (C) 2011 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -31,6 +31,7 @@ Conversion of a string representation of a pandoc type (@Pandoc@,
module Text.Pandoc.Readers.Native ( readNative ) where
import Text.Pandoc.Definition
+import Text.Pandoc.Shared (safeRead)
nullMeta :: Meta
nullMeta = Meta{ docTitle = []
@@ -51,31 +52,31 @@ nullMeta = Meta{ docTitle = []
readNative :: String -- ^ String to parse (assuming @'\n'@ line endings)
-> Pandoc
readNative s =
- case reads s of
- (d,_):_ -> d
- [] -> Pandoc nullMeta $ readBlocks s
+ case safeRead s of
+ Just d -> d
+ Nothing -> Pandoc nullMeta $ readBlocks s
readBlocks :: String -> [Block]
readBlocks s =
- case reads s of
- (d,_):_ -> d
- [] -> [readBlock s]
+ case safeRead s of
+ Just d -> d
+ Nothing -> [readBlock s]
readBlock :: String -> Block
readBlock s =
- case reads s of
- (d,_):_ -> d
- [] -> Plain $ readInlines s
+ case safeRead s of
+ Just d -> d
+ Nothing -> Plain $ readInlines s
readInlines :: String -> [Inline]
readInlines s =
- case reads s of
- (d,_):_ -> d
- [] -> [readInline s]
+ case safeRead s of
+ Just d -> d
+ Nothing -> [readInline s]
readInline :: String -> Inline
readInline s =
- case reads s of
- (d,_):_ -> d
- [] -> error "Cannot parse document"
+ case safeRead s of
+ Just d -> d
+ Nothing -> error "Cannot parse document"
diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs
index d1010a736..9fb976903 100644
--- a/src/Text/Pandoc/Readers/RST.hs
+++ b/src/Text/Pandoc/Readers/RST.hs
@@ -17,9 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
- Module : Text.Pandoc.Readers.RST
+ Module : Text.Pandoc.Readers.RST
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -27,24 +27,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Conversion from reStructuredText to 'Pandoc' document.
-}
-module Text.Pandoc.Readers.RST (
+module Text.Pandoc.Readers.RST (
readRST
) where
import Text.Pandoc.Definition
import Text.Pandoc.Shared
import Text.Pandoc.Parsing
-import Text.ParserCombinators.Parsec
-import Control.Monad ( when, liftM )
+import Text.Pandoc.Options
+import Control.Monad ( when, liftM, guard, mzero )
import Data.List ( findIndex, intercalate, transpose, sort, deleteFirstsBy )
import qualified Data.Map as M
import Text.Printf ( printf )
import Data.Maybe ( catMaybes )
-- | Parse reStructuredText string and return Pandoc document.
-readRST :: ParserState -- ^ Parser state, including options for parser
- -> String -- ^ String to parse (assuming @'\n'@ line endings)
+readRST :: ReaderOptions -- ^ Reader options
+ -> String -- ^ String to parse (assuming @'\n'@ line endings)
-> Pandoc
-readRST state s = (readWith parseRST) state (s ++ "\n\n")
+readRST opts s = (readWith parseRST) def{ stateOptions = opts } (s ++ "\n\n")
--
-- Constants and data structure definitions
@@ -58,7 +58,7 @@ underlineChars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
-- treat these as potentially non-text when parsing inline:
specialChars :: [Char]
-specialChars = "\\`|*_<>$:[]()-.\"'\8216\8217\8220\8221"
+specialChars = "\\`|*_<>$:/[]{}()-.\"'\8216\8217\8220\8221"
--
-- parsing documents
@@ -71,14 +71,14 @@ isHeader _ _ = False
-- | Promote all headers in a list of blocks. (Part of
-- title transformation for RST.)
promoteHeaders :: Int -> [Block] -> [Block]
-promoteHeaders num ((Header level text):rest) =
+promoteHeaders num ((Header level text):rest) =
(Header (level - num) text):(promoteHeaders num rest)
promoteHeaders num (other:rest) = other:(promoteHeaders num rest)
promoteHeaders _ [] = []
-- | If list of blocks starts with a header (or a header and subheader)
-- of level that are not found elsewhere, return it as a title and
--- promote all the other headers.
+-- promote all the other headers.
titleTransform :: [Block] -- ^ list of blocks
-> ([Block], [Inline]) -- ^ modified list of blocks, title
titleTransform ((Header 1 head1):(Header 2 head2):rest) |
@@ -89,7 +89,7 @@ titleTransform ((Header 1 head1):rest) |
(promoteHeaders 1 rest, head1)
titleTransform blocks = (blocks, [])
-parseRST :: GenParser Char ParserState Pandoc
+parseRST :: Parser [Char] ParserState Pandoc
parseRST = do
optional blanklines -- skip blank lines at beginning of file
startPos <- getPosition
@@ -103,12 +103,13 @@ parseRST = do
let reversedNotes = stateNotes st'
updateState $ \s -> s { stateNotes = reverse reversedNotes }
-- now parse it for real...
- blocks <- parseBlocks
+ blocks <- parseBlocks
let blocks' = filter (/= Null) blocks
- state <- getState
- let (blocks'', title) = if stateStandalone state
+ standalone <- getOption readerStandalone
+ let (blocks'', title) = if standalone
then titleTransform blocks'
else (blocks', [])
+ state <- getState
let authors = stateAuthors state
let date = stateDate state
let title' = if (null title) then (stateTitle state) else title
@@ -118,10 +119,10 @@ parseRST = do
-- parsing blocks
--
-parseBlocks :: GenParser Char ParserState [Block]
+parseBlocks :: Parser [Char] ParserState [Block]
parseBlocks = manyTill block eof
-block :: GenParser Char ParserState Block
+block :: Parser [Char] ParserState Block
block = choice [ codeBlock
, rawBlock
, blockQuote
@@ -146,7 +147,7 @@ block = choice [ codeBlock
-- field list
--
-rawFieldListItem :: String -> GenParser Char ParserState (String, String)
+rawFieldListItem :: String -> Parser [Char] ParserState (String, String)
rawFieldListItem indent = try $ do
string indent
char ':'
@@ -160,7 +161,7 @@ rawFieldListItem indent = try $ do
return (name, raw)
fieldListItem :: String
- -> GenParser Char ParserState (Maybe ([Inline], [[Block]]))
+ -> Parser [Char] ParserState (Maybe ([Inline], [[Block]]))
fieldListItem indent = try $ do
(name, raw) <- rawFieldListItem indent
let term = [Str name]
@@ -187,7 +188,7 @@ extractContents [Plain auth] = auth
extractContents [Para auth] = auth
extractContents _ = []
-fieldList :: GenParser Char ParserState Block
+fieldList :: Parser [Char] ParserState Block
fieldList = try $ do
indent <- lookAhead $ many spaceChar
items <- many1 $ fieldListItem indent
@@ -199,7 +200,7 @@ fieldList = try $ do
-- line block
--
-lineBlockLine :: GenParser Char ParserState [Inline]
+lineBlockLine :: Parser [Char] ParserState [Inline]
lineBlockLine = try $ do
char '|'
char ' ' <|> lookAhead (char '\n')
@@ -210,7 +211,7 @@ lineBlockLine = try $ do
then normalizeSpaces line
else Str white : normalizeSpaces line
-lineBlock :: GenParser Char ParserState Block
+lineBlock :: Parser [Char] ParserState Block
lineBlock = try $ do
lines' <- many1 lineBlockLine
blanklines
@@ -220,14 +221,14 @@ lineBlock = try $ do
-- paragraph block
--
-para :: GenParser Char ParserState Block
+para :: Parser [Char] ParserState Block
para = paraBeforeCodeBlock <|> paraNormal <?> "paragraph"
-codeBlockStart :: GenParser Char st Char
+codeBlockStart :: Parser [Char] st Char
codeBlockStart = string "::" >> blankline >> blankline
-- paragraph that ends in a :: starting a code block
-paraBeforeCodeBlock :: GenParser Char ParserState Block
+paraBeforeCodeBlock :: Parser [Char] ParserState Block
paraBeforeCodeBlock = try $ do
result <- many1 (notFollowedBy' codeBlockStart >> inline)
lookAhead (string "::")
@@ -236,21 +237,21 @@ paraBeforeCodeBlock = try $ do
else (normalizeSpaces result) ++ [Str ":"]
-- regular paragraph
-paraNormal :: GenParser Char ParserState Block
-paraNormal = try $ do
+paraNormal :: Parser [Char] ParserState Block
+paraNormal = try $ do
result <- many1 inline
newline
blanklines
return $ Para $ normalizeSpaces result
-plain :: GenParser Char ParserState Block
-plain = many1 inline >>= return . Plain . normalizeSpaces
+plain :: Parser [Char] ParserState Block
+plain = many1 inline >>= return . Plain . normalizeSpaces
--
-- image block
--
-imageBlock :: GenParser Char ParserState Block
+imageBlock :: Parser [Char] ParserState Block
imageBlock = try $ do
string ".. image:: "
src <- manyTill anyChar newline
@@ -265,11 +266,11 @@ imageBlock = try $ do
-- header blocks
--
-header :: GenParser Char ParserState Block
+header :: Parser [Char] ParserState Block
header = doubleHeader <|> singleHeader <?> "header"
-- a header with lines on top and bottom
-doubleHeader :: GenParser Char ParserState Block
+doubleHeader :: Parser [Char] ParserState Block
doubleHeader = try $ do
c <- oneOf underlineChars
rest <- many (char c) -- the top line
@@ -283,7 +284,7 @@ doubleHeader = try $ do
blankline -- spaces and newline
count lenTop (char c) -- the bottom line
blanklines
- -- check to see if we've had this kind of header before.
+ -- check to see if we've had this kind of header before.
-- if so, get appropriate level. if not, add to list.
state <- getState
let headerTable = stateHeaderTable state
@@ -294,8 +295,8 @@ doubleHeader = try $ do
return $ Header level (normalizeSpaces txt)
-- a header with line on the bottom only
-singleHeader :: GenParser Char ParserState Block
-singleHeader = try $ do
+singleHeader :: Parser [Char] ParserState Block
+singleHeader = try $ do
notFollowedBy' whitespace
txt <- many1 (do {notFollowedBy blankline; inline})
pos <- getPosition
@@ -317,7 +318,7 @@ singleHeader = try $ do
-- hrule block
--
-hrule :: GenParser Char st Block
+hrule :: Parser [Char] st Block
hrule = try $ do
chr <- oneOf underlineChars
count 3 (char chr)
@@ -331,14 +332,14 @@ hrule = try $ do
--
-- read a line indented by a given string
-indentedLine :: String -> GenParser Char st [Char]
+indentedLine :: String -> Parser [Char] st [Char]
indentedLine indents = try $ do
string indents
manyTill anyChar newline
-- one or more indented lines, possibly separated by blank lines.
-- any amount of indentation will work.
-indentedBlock :: GenParser Char st [Char]
+indentedBlock :: Parser [Char] st [Char]
indentedBlock = try $ do
indents <- lookAhead $ many1 spaceChar
lns <- many1 $ try $ do b <- option "" blanklines
@@ -347,7 +348,7 @@ indentedBlock = try $ do
optional blanklines
return $ unlines lns
-codeBlock :: GenParser Char st Block
+codeBlock :: Parser [Char] st Block
codeBlock = try $ do
codeBlockStart
result <- indentedBlock
@@ -355,7 +356,7 @@ codeBlock = try $ do
-- | The 'code-block' directive (from Sphinx) that allows a language to be
-- specified.
-customCodeBlock :: GenParser Char st Block
+customCodeBlock :: Parser [Char] st Block
customCodeBlock = try $ do
string ".. code-block:: "
language <- manyTill anyChar newline
@@ -364,7 +365,7 @@ customCodeBlock = try $ do
return $ CodeBlock ("", ["sourceCode", language], []) $ stripTrailingNewlines result
-figureBlock :: GenParser Char ParserState Block
+figureBlock :: Parser [Char] ParserState Block
figureBlock = try $ do
string ".. figure::"
src <- removeLeadingTrailingSpace `fmap` manyTill anyChar newline
@@ -372,24 +373,24 @@ figureBlock = try $ do
caption <- parseFromString extractCaption body
return $ Para [Image caption (src,"")]
-extractCaption :: GenParser Char ParserState [Inline]
+extractCaption :: Parser [Char] ParserState [Inline]
extractCaption = try $ do
manyTill anyLine blanklines
many inline
-- | The 'math' directive (from Sphinx) for display math.
-mathBlock :: GenParser Char st Block
+mathBlock :: Parser [Char] st Block
mathBlock = try $ do
string ".. math::"
mathBlockMultiline <|> mathBlockOneLine
-mathBlockOneLine :: GenParser Char st Block
+mathBlockOneLine :: Parser [Char] st Block
mathBlockOneLine = try $ do
result <- manyTill anyChar newline
blanklines
return $ Para [Math DisplayMath $ removeLeadingTrailingSpace result]
-mathBlockMultiline :: GenParser Char st Block
+mathBlockMultiline :: Parser [Char] st Block
mathBlockMultiline = try $ do
blanklines
result <- indentedBlock
@@ -404,9 +405,9 @@ mathBlockMultiline = try $ do
$ filter (not . null) $ splitBy null lns'
return $ Para $ map (Math DisplayMath) eqs
-lhsCodeBlock :: GenParser Char ParserState Block
+lhsCodeBlock :: Parser [Char] ParserState Block
lhsCodeBlock = try $ do
- failUnlessLHS
+ guardEnabled Ext_literate_haskell
optional codeBlockStart
pos <- getPosition
when (sourceColumn pos /= 1) $ fail "Not in first column"
@@ -418,7 +419,7 @@ lhsCodeBlock = try $ do
blanklines
return $ CodeBlock ("", ["sourceCode", "literate", "haskell"], []) $ intercalate "\n" lns'
-birdTrackLine :: GenParser Char st [Char]
+birdTrackLine :: Parser [Char] st [Char]
birdTrackLine = do
char '>'
manyTill anyChar newline
@@ -427,7 +428,7 @@ birdTrackLine = do
-- raw html/latex/etc
--
-rawBlock :: GenParser Char st Block
+rawBlock :: Parser [Char] st Block
rawBlock = try $ do
string ".. raw:: "
lang <- many1 (letter <|> digit)
@@ -439,7 +440,7 @@ rawBlock = try $ do
-- block quotes
--
-blockQuote :: GenParser Char ParserState Block
+blockQuote :: Parser [Char] ParserState Block
blockQuote = do
raw <- indentedBlock
-- parse the extracted block, which may contain various block elements:
@@ -450,10 +451,10 @@ blockQuote = do
-- list blocks
--
-list :: GenParser Char ParserState Block
+list :: Parser [Char] ParserState Block
list = choice [ bulletList, orderedList, definitionList ] <?> "list"
-definitionListItem :: GenParser Char ParserState ([Inline], [[Block]])
+definitionListItem :: Parser [Char] ParserState ([Inline], [[Block]])
definitionListItem = try $ do
-- avoid capturing a directive or comment
notFollowedBy (try $ char '.' >> char '.')
@@ -463,11 +464,11 @@ definitionListItem = try $ do
contents <- parseFromString parseBlocks $ raw ++ "\n"
return (normalizeSpaces term, [contents])
-definitionList :: GenParser Char ParserState Block
+definitionList :: Parser [Char] ParserState Block
definitionList = many1 definitionListItem >>= return . DefinitionList
-- parses bullet list start and returns its length (inc. following whitespace)
-bulletListStart :: GenParser Char st Int
+bulletListStart :: Parser [Char] st Int
bulletListStart = try $ do
notFollowedBy' hrule -- because hrules start out just like lists
marker <- oneOf bulletListMarkers
@@ -477,14 +478,14 @@ bulletListStart = try $ do
-- parses ordered list start and returns its length (inc following whitespace)
orderedListStart :: ListNumberStyle
-> ListNumberDelim
- -> GenParser Char ParserState Int
+ -> Parser [Char] ParserState Int
orderedListStart style delim = try $ do
(_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)
white <- many1 spaceChar
return $ markerLen + length white
-- parse a line of a list item
-listLine :: Int -> GenParser Char ParserState [Char]
+listLine :: Int -> Parser [Char] ParserState [Char]
listLine markerLength = try $ do
notFollowedBy blankline
indentWith markerLength
@@ -492,36 +493,35 @@ listLine markerLength = try $ do
return $ line ++ "\n"
-- indent by specified number of spaces (or equiv. tabs)
-indentWith :: Int -> GenParser Char ParserState [Char]
+indentWith :: Int -> Parser [Char] ParserState [Char]
indentWith num = do
- state <- getState
- let tabStop = stateTabStop state
+ tabStop <- getOption readerTabStop
if (num < tabStop)
then count num (char ' ')
- else choice [ try (count num (char ' ')),
- (try (char '\t' >> count (num - tabStop) (char ' '))) ]
+ else choice [ try (count num (char ' ')),
+ (try (char '\t' >> count (num - tabStop) (char ' '))) ]
-- parse raw text for one list item, excluding start marker and continuations
-rawListItem :: GenParser Char ParserState Int
- -> GenParser Char ParserState (Int, [Char])
+rawListItem :: Parser [Char] ParserState Int
+ -> Parser [Char] ParserState (Int, [Char])
rawListItem start = try $ do
markerLength <- start
firstLine <- manyTill anyChar newline
restLines <- many (listLine markerLength)
return (markerLength, (firstLine ++ "\n" ++ (concat restLines)))
--- continuation of a list item - indented and separated by blankline or
--- (in compact lists) endline.
+-- continuation of a list item - indented and separated by blankline or
+-- (in compact lists) endline.
-- Note: nested lists are parsed as continuations.
-listContinuation :: Int -> GenParser Char ParserState [Char]
+listContinuation :: Int -> Parser [Char] ParserState [Char]
listContinuation markerLength = try $ do
blanks <- many1 blankline
result <- many1 (listLine markerLength)
return $ blanks ++ concat result
-listItem :: GenParser Char ParserState Int
- -> GenParser Char ParserState [Block]
-listItem start = try $ do
+listItem :: Parser [Char] ParserState Int
+ -> Parser [Char] ParserState [Block]
+listItem start = try $ do
(markerLength, first) <- rawListItem start
rest <- many (listContinuation markerLength)
blanks <- choice [ try (many blankline >>~ lookAhead start),
@@ -537,22 +537,22 @@ listItem start = try $ do
updateState (\st -> st {stateParserContext = oldContext})
return parsed
-orderedList :: GenParser Char ParserState Block
+orderedList :: Parser [Char] ParserState Block
orderedList = try $ do
(start, style, delim) <- lookAhead (anyOrderedListMarker >>~ spaceChar)
items <- many1 (listItem (orderedListStart style delim))
let items' = compactify items
return $ OrderedList (start, style, delim) items'
-bulletList :: GenParser Char ParserState Block
-bulletList = many1 (listItem bulletListStart) >>=
+bulletList :: Parser [Char] ParserState Block
+bulletList = many1 (listItem bulletListStart) >>=
return . BulletList . compactify
--
-- default-role block
--
-defaultRoleBlock :: GenParser Char ParserState Block
+defaultRoleBlock :: Parser [Char] ParserState Block
defaultRoleBlock = try $ do
string ".. default-role::"
-- doesn't enforce any restrictions on the role name; embedded spaces shouldn't be allowed, for one
@@ -570,7 +570,7 @@ defaultRoleBlock = try $ do
-- unknown directive (e.g. comment)
--
-unknownDirective :: GenParser Char st Block
+unknownDirective :: Parser [Char] st Block
unknownDirective = try $ do
string ".."
notFollowedBy (noneOf " \t\n")
@@ -582,7 +582,7 @@ unknownDirective = try $ do
--- note block
---
-noteBlock :: GenParser Char ParserState [Char]
+noteBlock :: Parser [Char] ParserState [Char]
noteBlock = try $ do
startPos <- getPosition
string ".."
@@ -601,7 +601,7 @@ noteBlock = try $ do
-- return blanks so line count isn't affected
return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
-noteMarker :: GenParser Char ParserState [Char]
+noteMarker :: Parser [Char] ParserState [Char]
noteMarker = do
char '['
res <- many1 digit
@@ -614,13 +614,13 @@ noteMarker = do
-- reference key
--
-quotedReferenceName :: GenParser Char ParserState [Inline]
+quotedReferenceName :: Parser [Char] ParserState [Inline]
quotedReferenceName = try $ do
char '`' >> notFollowedBy (char '`') -- `` means inline code!
- label' <- many1Till inline (char '`')
+ label' <- many1Till inline (char '`')
return label'
-unquotedReferenceName :: GenParser Char ParserState [Inline]
+unquotedReferenceName :: Parser [Char] ParserState [Inline]
unquotedReferenceName = try $ do
label' <- many1Till inline (lookAhead $ char ':')
return label'
@@ -629,24 +629,24 @@ unquotedReferenceName = try $ do
-- plus isolated (no two adjacent) internal hyphens, underscores,
-- periods, colons and plus signs; no whitespace or other characters
-- are allowed.
-simpleReferenceName' :: GenParser Char st String
+simpleReferenceName' :: Parser [Char] st String
simpleReferenceName' = do
x <- alphaNum
xs <- many $ alphaNum
<|> (try $ oneOf "-_:+." >> lookAhead alphaNum)
return (x:xs)
-simpleReferenceName :: GenParser Char st [Inline]
+simpleReferenceName :: Parser [Char] st [Inline]
simpleReferenceName = do
raw <- simpleReferenceName'
return [Str raw]
-referenceName :: GenParser Char ParserState [Inline]
+referenceName :: Parser [Char] ParserState [Inline]
referenceName = quotedReferenceName <|>
(try $ simpleReferenceName >>~ lookAhead (char ':')) <|>
unquotedReferenceName
-referenceKey :: GenParser Char ParserState [Char]
+referenceKey :: Parser [Char] ParserState [Char]
referenceKey = do
startPos <- getPosition
(key, target) <- choice [imageKey, anonymousKey, regularKey]
@@ -658,38 +658,43 @@ referenceKey = do
-- return enough blanks to replace key
return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
-targetURI :: GenParser Char st [Char]
+targetURI :: Parser [Char] st [Char]
targetURI = do
skipSpaces
optional newline
- contents <- many1 (try (many spaceChar >> newline >>
+ contents <- many1 (try (many spaceChar >> newline >>
many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")
blanklines
return $ escapeURI $ removeLeadingTrailingSpace $ contents
-imageKey :: GenParser Char ParserState (Key, Target)
+imageKey :: Parser [Char] ParserState (Key, Target)
imageKey = try $ do
string ".. |"
- ref <- manyTill inline (char '|')
+ (_,ref) <- withRaw (manyTill inline (char '|'))
skipSpaces
string "image::"
src <- targetURI
- return (toKey (normalizeSpaces ref), (src, ""))
+ return (toKey $ init ref, (src, ""))
-anonymousKey :: GenParser Char st (Key, Target)
+anonymousKey :: Parser [Char] st (Key, Target)
anonymousKey = try $ do
oneOfStrings [".. __:", "__"]
src <- targetURI
pos <- getPosition
- return (toKey [Str $ "_" ++ printf "%09d" (sourceLine pos)], (src, ""))
+ return (toKey $ "_" ++ printf "%09d" (sourceLine pos), (src, ""))
-regularKey :: GenParser Char ParserState (Key, Target)
+stripTicks :: String -> String
+stripTicks = reverse . stripTick . reverse . stripTick
+ where stripTick ('`':xs) = xs
+ stripTick xs = xs
+
+regularKey :: Parser [Char] ParserState (Key, Target)
regularKey = try $ do
string ".. _"
- ref <- referenceName
+ (_,ref) <- withRaw referenceName
char ':'
src <- targetURI
- return (toKey (normalizeSpaces ref), (src, ""))
+ return (toKey $ stripTicks ref, (src, ""))
--
-- tables
@@ -702,37 +707,37 @@ regularKey = try $ do
-- Simple tables TODO:
-- - column spans
-- - multiline support
--- - ensure that rightmost column span does not need to reach end
+-- - ensure that rightmost column span does not need to reach end
-- - require at least 2 columns
--
-- Grid tables TODO:
-- - column spans
-dashedLine :: Char -> GenParser Char st (Int, Int)
+dashedLine :: Char -> Parser [Char] st (Int, Int)
dashedLine ch = do
dashes <- many1 (char ch)
sp <- many (char ' ')
return (length dashes, length $ dashes ++ sp)
-simpleDashedLines :: Char -> GenParser Char st [(Int,Int)]
+simpleDashedLines :: Char -> Parser [Char] st [(Int,Int)]
simpleDashedLines ch = try $ many1 (dashedLine ch)
-- Parse a table row separator
-simpleTableSep :: Char -> GenParser Char ParserState Char
+simpleTableSep :: Char -> Parser [Char] ParserState Char
simpleTableSep ch = try $ simpleDashedLines ch >> newline
-- Parse a table footer
-simpleTableFooter :: GenParser Char ParserState [Char]
+simpleTableFooter :: Parser [Char] ParserState [Char]
simpleTableFooter = try $ simpleTableSep '=' >> blanklines
-- Parse a raw line and split it into chunks by indices.
-simpleTableRawLine :: [Int] -> GenParser Char ParserState [String]
+simpleTableRawLine :: [Int] -> Parser [Char] ParserState [String]
simpleTableRawLine indices = do
line <- many1Till anyChar newline
return (simpleTableSplitLine indices line)
-- Parse a table row and return a list of blocks (columns).
-simpleTableRow :: [Int] -> GenParser Char ParserState [[Block]]
+simpleTableRow :: [Int] -> Parser [Char] ParserState [[Block]]
simpleTableRow indices = do
notFollowedBy' simpleTableFooter
firstLine <- simpleTableRawLine indices
@@ -745,8 +750,8 @@ simpleTableSplitLine indices line =
map removeLeadingTrailingSpace
$ tail $ splitByIndices (init indices) line
-simpleTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
+simpleTableHeader :: Bool -- ^ Headerless table
+ -> Parser [Char] ParserState ([[Block]], [Alignment], [Int])
simpleTableHeader headless = try $ do
optional blanklines
rawContent <- if headless
@@ -766,28 +771,28 @@ simpleTableHeader headless = try $ do
-- Parse a simple table.
simpleTable :: Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
+ -> Parser [Char] ParserState Block
simpleTable headless = do
- Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter (return [])
+ Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter
-- Simple tables get 0s for relative column widths (i.e., use default)
return $ Table c a (replicate (length a) 0) h l
where
sep = return () -- optional (simpleTableSep '-')
gridTable :: Bool -- ^ Headerless table
- -> GenParser Char ParserState Block
-gridTable = gridTableWith block (return [])
+ -> Parser [Char] ParserState Block
+gridTable = gridTableWith parseBlocks
-table :: GenParser Char ParserState Block
+table :: Parser [Char] ParserState Block
table = gridTable False <|> simpleTable False <|>
gridTable True <|> simpleTable True <?> "table"
- --
+ --
-- inline
--
-inline :: GenParser Char ParserState Inline
+inline :: Parser [Char] ParserState Inline
inline = choice [ whitespace
, link
, str
@@ -805,44 +810,53 @@ inline = choice [ whitespace
, escapedChar
, symbol ] <?> "inline"
-hyphens :: GenParser Char ParserState Inline
+hyphens :: Parser [Char] ParserState Inline
hyphens = do
result <- many1 (char '-')
- option Space endline
+ option Space endline
-- don't want to treat endline after hyphen or dash as a space
return $ Str result
-escapedChar :: GenParser Char st Inline
+escapedChar :: Parser [Char] st Inline
escapedChar = do c <- escaped anyChar
return $ if c == ' ' -- '\ ' is null in RST
then Str ""
else Str [c]
-symbol :: GenParser Char ParserState Inline
-symbol = do
+symbol :: Parser [Char] ParserState Inline
+symbol = do
result <- oneOf specialChars
return $ Str [result]
-- parses inline code, between codeStart and codeEnd
-code :: GenParser Char ParserState Inline
-code = try $ do
+code :: Parser [Char] ParserState Inline
+code = try $ do
string "``"
result <- manyTill anyChar (try (string "``"))
return $ Code nullAttr
$ removeLeadingTrailingSpace $ intercalate " " $ lines result
-emph :: GenParser Char ParserState Inline
-emph = enclosed (char '*') (char '*') inline >>=
+-- succeeds only if we're not right after a str (ie. in middle of word)
+atStart :: Parser [Char] ParserState a -> Parser [Char] ParserState a
+atStart p = do
+ pos <- getPosition
+ st <- getState
+ -- single quote start can't be right after str
+ guard $ stateLastStrPos st /= Just pos
+ p
+
+emph :: Parser [Char] ParserState Inline
+emph = enclosed (atStart $ char '*') (char '*') inline >>=
return . Emph . normalizeSpaces
-strong :: GenParser Char ParserState Inline
-strong = enclosed (string "**") (try $ string "**") inline >>=
+strong :: Parser [Char] ParserState Inline
+strong = enclosed (atStart $ string "**") (try $ string "**") inline >>=
return . Strong . normalizeSpaces
-- Parses inline interpreted text which is required to have the given role.
-- This decision is based on the role marker (if present),
-- and the current default interpreted text role.
-interpreted :: [Char] -> GenParser Char ParserState [Char]
+interpreted :: [Char] -> Parser [Char] ParserState [Char]
interpreted role = try $ do
state <- getState
if role == stateRstDefaultRole state
@@ -856,30 +870,30 @@ interpreted role = try $ do
-- http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#inline-markup-recognition-rules
-- but it should be good enough for most purposes
unmarkedInterpretedText = do
- result <- enclosed (char '`') (char '`') anyChar
+ result <- enclosed (atStart $ char '`') (char '`') anyChar
return result
-superscript :: GenParser Char ParserState Inline
+superscript :: Parser [Char] ParserState Inline
superscript = interpreted "sup" >>= \x -> return (Superscript [Str x])
-subscript :: GenParser Char ParserState Inline
+subscript :: Parser [Char] ParserState Inline
subscript = interpreted "sub" >>= \x -> return (Subscript [Str x])
-math :: GenParser Char ParserState Inline
+math :: Parser [Char] ParserState Inline
math = interpreted "math" >>= \x -> return (Math InlineMath x)
-whitespace :: GenParser Char ParserState Inline
+whitespace :: Parser [Char] ParserState Inline
whitespace = many1 spaceChar >> return Space <?> "whitespace"
-str :: GenParser Char ParserState Inline
+str :: Parser [Char] ParserState Inline
str = do
- result <- many1 (noneOf (specialChars ++ "\t\n "))
- pos <- getPosition
- updateState $ \s -> s{ stateLastStrPos = Just pos }
+ let strChar = noneOf ("\t\n " ++ specialChars)
+ result <- many1 strChar
+ updateLastStrPos
return $ Str result
-- an endline character that can be treated as a space, not a structural break
-endline :: GenParser Char ParserState Inline
+endline :: Parser [Char] ParserState Inline
endline = try $ do
newline
notFollowedBy blankline
@@ -895,14 +909,14 @@ endline = try $ do
-- links
--
-link :: GenParser Char ParserState Inline
+link :: Parser [Char] ParserState Inline
link = choice [explicitLink, referenceLink, autoLink] <?> "link"
-explicitLink :: GenParser Char ParserState Inline
+explicitLink :: Parser [Char] ParserState Inline
explicitLink = try $ do
char '`'
notFollowedBy (char '`') -- `` marks start of inline code
- label' <- manyTill (notFollowedBy (char '`') >> inline)
+ label' <- manyTill (notFollowedBy (char '`') >> inline)
(try (spaces >> char '<'))
src <- manyTill (noneOf ">\n") (char '>')
skipSpaces
@@ -910,53 +924,53 @@ explicitLink = try $ do
return $ Link (normalizeSpaces label')
(escapeURI $ removeLeadingTrailingSpace src, "")
-referenceLink :: GenParser Char ParserState Inline
+referenceLink :: Parser [Char] ParserState Inline
referenceLink = try $ do
- label' <- (quotedReferenceName <|> simpleReferenceName) >>~ char '_'
+ (label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) >>~
+ char '_'
state <- getState
let keyTable = stateKeys state
- let isAnonKey x = case fromKey x of
- [Str ('_':_)] -> True
- _ -> False
- key <- option (toKey label') $
+ let isAnonKey (Key ('_':_)) = True
+ isAnonKey _ = False
+ key <- option (toKey $ stripTicks ref) $
do char '_'
let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
if null anonKeys
- then pzero
+ then mzero
else return (head anonKeys)
- (src,tit) <- case lookupKeySrc keyTable key of
+ (src,tit) <- case M.lookup key keyTable of
Nothing -> fail "no corresponding key"
Just target -> return target
-- if anonymous link, remove key so it won't be used again
when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable }
- return $ Link (normalizeSpaces label') (src, tit)
+ return $ Link (normalizeSpaces label') (src, tit)
-autoURI :: GenParser Char ParserState Inline
+autoURI :: Parser [Char] ParserState Inline
autoURI = do
(orig, src) <- uri
return $ Link [Str orig] (src, "")
-autoEmail :: GenParser Char ParserState Inline
+autoEmail :: Parser [Char] ParserState Inline
autoEmail = do
(orig, src) <- emailAddress
return $ Link [Str orig] (src, "")
-autoLink :: GenParser Char ParserState Inline
+autoLink :: Parser [Char] ParserState Inline
autoLink = autoURI <|> autoEmail
-- For now, we assume that all substitution references are for images.
-image :: GenParser Char ParserState Inline
+image :: Parser [Char] ParserState Inline
image = try $ do
char '|'
- ref <- manyTill inline (char '|')
+ (alt,ref) <- withRaw (manyTill inline (char '|'))
state <- getState
let keyTable = stateKeys state
- (src,tit) <- case lookupKeySrc keyTable (toKey ref) of
+ (src,tit) <- case M.lookup (toKey $ init ref) keyTable of
Nothing -> fail "no corresponding key"
Just target -> return target
- return $ Image (normalizeSpaces ref) (src, tit)
+ return $ Image (normalizeSpaces alt) (src, tit)
-note :: GenParser Char ParserState Inline
+note :: Parser [Char] ParserState Inline
note = try $ do
ref <- noteMarker
char '_'
diff --git a/src/Text/Pandoc/Readers/TeXMath.hs b/src/Text/Pandoc/Readers/TeXMath.hs
index 67dfe6753..fe49a992e 100644
--- a/src/Text/Pandoc/Readers/TeXMath.hs
+++ b/src/Text/Pandoc/Readers/TeXMath.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Readers.TeXMath
Copyright : Copyright (C) 2007-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
index 348900d38..89f281ae8 100644
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Readers.Textile
Copyright : Copyright (C) 2010-2012 Paul Rivier and John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : Paul Rivier <paul*rivier#demotera*com>
Stability : alpha
@@ -56,29 +56,34 @@ TODO : refactor common patterns across readers :
module Text.Pandoc.Readers.Textile ( readTextile) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Parsing
import Text.Pandoc.Readers.HTML ( htmlTag, isInlineTag, isBlockTag )
import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )
-import Text.ParserCombinators.Parsec
import Text.HTML.TagSoup.Match
import Data.Char ( digitToInt, isUpper )
import Control.Monad ( guard, liftM )
import Control.Applicative ((<$>), (*>), (<*))
-- | Parse a Textile text and return a Pandoc document.
-readTextile :: ParserState -- ^ Parser state, including options for parser
- -> String -- ^ String to parse (assuming @'\n'@ line endings)
- -> Pandoc
-readTextile state s =
- (readWith parseTextile) state{ stateOldDashes = True } (s ++ "\n\n")
+readTextile :: ReaderOptions -- ^ Reader options
+ -> String -- ^ String to parse (assuming @'\n'@ line endings)
+ -> Pandoc
+readTextile opts s =
+ (readWith parseTextile) def{ stateOptions = opts } (s ++ "\n\n")
-- | Generate a Pandoc ADT from a textile document
-parseTextile :: GenParser Char ParserState Pandoc
+parseTextile :: Parser [Char] ParserState Pandoc
parseTextile = do
-- textile allows raw HTML and does smart punctuation by default
- updateState (\state -> state { stateParseRaw = True, stateSmart = True })
+ oldOpts <- stateOptions `fmap` getState
+ updateState $ \state -> state{ stateOptions =
+ oldOpts{ readerSmart = True
+ , readerParseRaw = True
+ , readerOldDashes = True
+ } }
many blankline
startPos <- getPosition
-- go through once just to get list of reference keys and notes
@@ -93,10 +98,10 @@ parseTextile = do
blocks <- parseBlocks
return $ Pandoc (Meta [] [] []) blocks -- FIXME
-noteMarker :: GenParser Char ParserState [Char]
+noteMarker :: Parser [Char] ParserState [Char]
noteMarker = skipMany spaceChar >> string "fn" >> manyTill digit (char '.')
-noteBlock :: GenParser Char ParserState [Char]
+noteBlock :: Parser [Char] ParserState [Char]
noteBlock = try $ do
startPos <- getPosition
ref <- noteMarker
@@ -111,11 +116,11 @@ noteBlock = try $ do
return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
-- | Parse document blocks
-parseBlocks :: GenParser Char ParserState [Block]
+parseBlocks :: Parser [Char] ParserState [Block]
parseBlocks = manyTill block eof
-- | Block parsers list tried in definition order
-blockParsers :: [GenParser Char ParserState Block]
+blockParsers :: [Parser [Char] ParserState Block]
blockParsers = [ codeBlock
, header
, blockQuote
@@ -128,20 +133,20 @@ blockParsers = [ codeBlock
, nullBlock ]
-- | Any block in the order of definition of blockParsers
-block :: GenParser Char ParserState Block
+block :: Parser [Char] ParserState Block
block = choice blockParsers <?> "block"
-codeBlock :: GenParser Char ParserState Block
+codeBlock :: Parser [Char] ParserState Block
codeBlock = codeBlockBc <|> codeBlockPre
-codeBlockBc :: GenParser Char ParserState Block
+codeBlockBc :: Parser [Char] ParserState Block
codeBlockBc = try $ do
string "bc. "
contents <- manyTill anyLine blanklines
return $ CodeBlock ("",[],[]) $ unlines contents
-- | Code Blocks in Textile are between <pre> and </pre>
-codeBlockPre :: GenParser Char ParserState Block
+codeBlockPre :: Parser [Char] ParserState Block
codeBlockPre = try $ do
htmlTag (tagOpen (=="pre") null)
result' <- manyTill anyChar (try $ htmlTag (tagClose (=="pre")) >> blockBreak)
@@ -156,7 +161,7 @@ codeBlockPre = try $ do
return $ CodeBlock ("",[],[]) result'''
-- | Header of the form "hN. content" with N in 1..6
-header :: GenParser Char ParserState Block
+header :: Parser [Char] ParserState Block
header = try $ do
char 'h'
level <- digitToInt <$> oneOf "123456"
@@ -165,14 +170,14 @@ header = try $ do
return $ Header level name
-- | Blockquote of the form "bq. content"
-blockQuote :: GenParser Char ParserState Block
+blockQuote :: Parser [Char] ParserState Block
blockQuote = try $ do
string "bq" >> optional attributes >> char '.' >> whitespace
BlockQuote . singleton <$> para
-- Horizontal rule
-hrule :: GenParser Char st Block
+hrule :: Parser [Char] st Block
hrule = try $ do
skipSpaces
start <- oneOf "-*"
@@ -187,39 +192,39 @@ hrule = try $ do
-- | Can be a bullet list or an ordered list. This implementation is
-- strict in the nesting, sublist must start at exactly "parent depth
-- plus one"
-anyList :: GenParser Char ParserState Block
+anyList :: Parser [Char] ParserState Block
anyList = try $ ( (anyListAtDepth 1) <* blanklines )
-- | This allow one type of list to be nested into an other type,
-- provided correct nesting
-anyListAtDepth :: Int -> GenParser Char ParserState Block
+anyListAtDepth :: Int -> Parser [Char] ParserState Block
anyListAtDepth depth = choice [ bulletListAtDepth depth,
orderedListAtDepth depth,
definitionList ]
-- | Bullet List of given depth, depth being the number of leading '*'
-bulletListAtDepth :: Int -> GenParser Char ParserState Block
+bulletListAtDepth :: Int -> Parser [Char] ParserState Block
bulletListAtDepth depth = try $ BulletList <$> many1 (bulletListItemAtDepth depth)
-- | Bullet List Item of given depth, depth being the number of
-- leading '*'
-bulletListItemAtDepth :: Int -> GenParser Char ParserState [Block]
+bulletListItemAtDepth :: Int -> Parser [Char] ParserState [Block]
bulletListItemAtDepth = genericListItemAtDepth '*'
-- | Ordered List of given depth, depth being the number of
-- leading '#'
-orderedListAtDepth :: Int -> GenParser Char ParserState Block
+orderedListAtDepth :: Int -> Parser [Char] ParserState Block
orderedListAtDepth depth = try $ do
items <- many1 (orderedListItemAtDepth depth)
return (OrderedList (1, DefaultStyle, DefaultDelim) items)
-- | Ordered List Item of given depth, depth being the number of
-- leading '#'
-orderedListItemAtDepth :: Int -> GenParser Char ParserState [Block]
+orderedListItemAtDepth :: Int -> Parser [Char] ParserState [Block]
orderedListItemAtDepth = genericListItemAtDepth '#'
-- | Common implementation of list items
-genericListItemAtDepth :: Char -> Int -> GenParser Char ParserState [Block]
+genericListItemAtDepth :: Char -> Int -> Parser [Char] ParserState [Block]
genericListItemAtDepth c depth = try $ do
count depth (char c) >> optional attributes >> whitespace
p <- inlines
@@ -227,22 +232,22 @@ genericListItemAtDepth c depth = try $ do
return ((Plain p):sublist)
-- | A definition list is a set of consecutive definition items
-definitionList :: GenParser Char ParserState Block
+definitionList :: Parser [Char] ParserState Block
definitionList = try $ DefinitionList <$> many1 definitionListItem
-
+
-- | A definition list item in textile begins with '- ', followed by
-- the term defined, then spaces and ":=". The definition follows, on
-- the same single line, or spaned on multiple line, after a line
-- break.
-definitionListItem :: GenParser Char ParserState ([Inline], [[Block]])
+definitionListItem :: Parser [Char] ParserState ([Inline], [[Block]])
definitionListItem = try $ do
string "- "
term <- many1Till inline (try (whitespace >> string ":="))
- def <- inlineDef <|> multilineDef
- return (term, def)
- where inlineDef :: GenParser Char ParserState [[Block]]
+ def' <- inlineDef <|> multilineDef
+ return (term, def')
+ where inlineDef :: Parser [Char] ParserState [[Block]]
inlineDef = liftM (\d -> [[Plain d]]) $ try (whitespace >> inlines)
- multilineDef :: GenParser Char ParserState [[Block]]
+ multilineDef :: Parser [Char] ParserState [[Block]]
multilineDef = try $ do
optional whitespace >> newline
s <- many1Till anyChar (try (string "=:" >> newline))
@@ -252,76 +257,76 @@ definitionListItem = try $ do
-- | This terminates a block such as a paragraph. Because of raw html
-- blocks support, we have to lookAhead for a rawHtmlBlock.
-blockBreak :: GenParser Char ParserState ()
+blockBreak :: Parser [Char] ParserState ()
blockBreak = try (newline >> blanklines >> return ()) <|>
(lookAhead rawHtmlBlock >> return ())
-- raw content
-- | A raw Html Block, optionally followed by blanklines
-rawHtmlBlock :: GenParser Char ParserState Block
+rawHtmlBlock :: Parser [Char] ParserState Block
rawHtmlBlock = try $ do
(_,b) <- htmlTag isBlockTag
optional blanklines
return $ RawBlock "html" b
-- | Raw block of LaTeX content
-rawLaTeXBlock' :: GenParser Char ParserState Block
+rawLaTeXBlock' :: Parser [Char] ParserState Block
rawLaTeXBlock' = do
- failIfStrict
+ guardEnabled Ext_raw_tex
RawBlock "latex" <$> (rawLaTeXBlock <* spaces)
-- | In textile, paragraphs are separated by blank lines.
-para :: GenParser Char ParserState Block
+para :: Parser [Char] ParserState Block
para = try $ Para . normalizeSpaces <$> manyTill inline blockBreak
-- Tables
-
+
-- | A table cell spans until a pipe |
-tableCell :: GenParser Char ParserState TableCell
+tableCell :: Parser [Char] ParserState TableCell
tableCell = do
c <- many1 (noneOf "|\n")
content <- parseFromString (many1 inline) c
return $ [ Plain $ normalizeSpaces content ]
-- | A table row is made of many table cells
-tableRow :: GenParser Char ParserState [TableCell]
+tableRow :: Parser [Char] ParserState [TableCell]
tableRow = try $ ( char '|' *> (endBy1 tableCell (char '|')) <* newline)
-- | Many table rows
-tableRows :: GenParser Char ParserState [[TableCell]]
+tableRows :: Parser [Char] ParserState [[TableCell]]
tableRows = many1 tableRow
-- | Table headers are made of cells separated by a tag "|_."
-tableHeaders :: GenParser Char ParserState [TableCell]
+tableHeaders :: Parser [Char] ParserState [TableCell]
tableHeaders = let separator = (try $ string "|_.") in
try $ ( separator *> (sepBy1 tableCell separator) <* char '|' <* newline )
-
+
-- | A table with an optional header. Current implementation can
-- handle tables with and without header, but will parse cells
-- alignment attributes as content.
-table :: GenParser Char ParserState Block
+table :: Parser [Char] ParserState Block
table = try $ do
headers <- option [] tableHeaders
rows <- tableRows
blanklines
let nbOfCols = max (length headers) (length $ head rows)
- return $ Table []
+ return $ Table []
(replicate nbOfCols AlignDefault)
(replicate nbOfCols 0.0)
headers
rows
-
+
-- | Blocks like 'p' and 'table' do not need explicit block tag.
-- However, they can be used to set HTML/CSS attributes when needed.
maybeExplicitBlock :: String -- ^ block tag name
- -> GenParser Char ParserState Block -- ^ implicit block
- -> GenParser Char ParserState Block
+ -> Parser [Char] ParserState Block -- ^ implicit block
+ -> Parser [Char] ParserState Block
maybeExplicitBlock name blk = try $ do
- optional $ try $ string name >> optional attributes >> char '.' >>
+ optional $ try $ string name >> optional attributes >> char '.' >>
((try whitespace) <|> endline)
blk
@@ -333,15 +338,15 @@ maybeExplicitBlock name blk = try $ do
-- | Any inline element
-inline :: GenParser Char ParserState Inline
+inline :: Parser [Char] ParserState Inline
inline = choice inlineParsers <?> "inline"
-- | List of consecutive inlines before a newline
-inlines :: GenParser Char ParserState [Inline]
+inlines :: Parser [Char] ParserState [Inline]
inlines = manyTill inline newline
-- | Inline parsers tried in order
-inlineParsers :: [GenParser Char ParserState Inline]
+inlineParsers :: [Parser [Char] ParserState Inline]
inlineParsers = [ autoLink
, str
, whitespace
@@ -362,7 +367,7 @@ inlineParsers = [ autoLink
]
-- | Inline markups
-inlineMarkup :: GenParser Char ParserState Inline
+inlineMarkup :: Parser [Char] ParserState Inline
inlineMarkup = choice [ simpleInline (string "??") (Cite [])
, simpleInline (string "**") Strong
, simpleInline (string "__") Emph
@@ -375,29 +380,29 @@ inlineMarkup = choice [ simpleInline (string "??") (Cite [])
]
-- | Trademark, registered, copyright
-mark :: GenParser Char st Inline
+mark :: Parser [Char] st Inline
mark = try $ char '(' >> (try tm <|> try reg <|> copy)
-reg :: GenParser Char st Inline
+reg :: Parser [Char] st Inline
reg = do
oneOf "Rr"
char ')'
return $ Str "\174"
-tm :: GenParser Char st Inline
+tm :: Parser [Char] st Inline
tm = do
oneOf "Tt"
oneOf "Mm"
char ')'
return $ Str "\8482"
-copy :: GenParser Char st Inline
+copy :: Parser [Char] st Inline
copy = do
oneOf "Cc"
char ')'
return $ Str "\169"
-note :: GenParser Char ParserState Inline
+note :: Parser [Char] ParserState Inline
note = try $ do
ref <- (char '[' *> many1 digit <* char ']')
notes <- stateNotes <$> getState
@@ -405,7 +410,7 @@ note = try $ do
Nothing -> fail "note not found"
Just raw -> liftM Note $ parseFromString parseBlocks raw
--- | Special chars
+-- | Special chars
markupChars :: [Char]
markupChars = "\\[]*#_@~-+^|%="
@@ -421,17 +426,17 @@ wordBoundaries :: [Char]
wordBoundaries = markupChars ++ stringBreakers
-- | Parse a hyphened sequence of words
-hyphenedWords :: GenParser Char ParserState String
+hyphenedWords :: Parser [Char] ParserState String
hyphenedWords = try $ do
hd <- noneOf wordBoundaries
- tl <- many ( (noneOf wordBoundaries) <|>
+ tl <- many ( (noneOf wordBoundaries) <|>
try (oneOf markupChars <* lookAhead (noneOf wordBoundaries) ) )
let wd = hd:tl
- option wd $ try $
+ option wd $ try $
(\r -> concat [wd, "-", r]) <$> (char '-' *> hyphenedWords)
-- | Any string
-str :: GenParser Char ParserState Inline
+str :: Parser [Char] ParserState Inline
str = do
baseStr <- hyphenedWords
-- RedCloth compliance : if parsed word is uppercase and immediatly
@@ -444,44 +449,57 @@ str = do
return $ Str fullStr
-- | Textile allows HTML span infos, we discard them
-htmlSpan :: GenParser Char ParserState Inline
+htmlSpan :: Parser [Char] ParserState Inline
htmlSpan = try $ Str <$> ( char '%' *> attributes *> manyTill anyChar (char '%') )
-- | Some number of space chars
-whitespace :: GenParser Char ParserState Inline
+whitespace :: Parser [Char] ParserState Inline
whitespace = many1 spaceChar >> return Space <?> "whitespace"
-- | In Textile, an isolated endline character is a line break
-endline :: GenParser Char ParserState Inline
+endline :: Parser [Char] ParserState Inline
endline = try $ do
newline >> notFollowedBy blankline
return LineBreak
-rawHtmlInline :: GenParser Char ParserState Inline
+rawHtmlInline :: Parser [Char] ParserState Inline
rawHtmlInline = RawInline "html" . snd <$> htmlTag isInlineTag
-
--- | Raw LaTeX Inline
-rawLaTeXInline' :: GenParser Char ParserState Inline
+
+-- | Raw LaTeX Inline
+rawLaTeXInline' :: Parser [Char] ParserState Inline
rawLaTeXInline' = try $ do
- failIfStrict
+ guardEnabled Ext_raw_tex
rawLaTeXInline
--- | Textile standard link syntax is "label":target
-link :: GenParser Char ParserState Inline
-link = try $ do
+-- | Textile standard link syntax is "label":target. But we
+-- can also have ["label":target].
+link :: Parser [Char] ParserState Inline
+link = linkB <|> linkNoB
+
+linkNoB :: Parser [Char] ParserState Inline
+linkNoB = try $ do
+ name <- surrounded (char '"') inline
+ char ':'
+ let stopChars = "!.,;:"
+ url <- manyTill nonspaceChar (lookAhead $ space <|> try (oneOf stopChars >> (space <|> newline)))
+ return $ Link name (url, "")
+
+linkB :: Parser [Char] ParserState Inline
+linkB = try $ do
+ char '['
name <- surrounded (char '"') inline
char ':'
- url <- manyTill (anyChar) (lookAhead $ (space <|> try (oneOf ".;,:" >> (space <|> newline))))
+ url <- manyTill nonspaceChar (char ']')
return $ Link name (url, "")
-- | Detect plain links to http or email.
-autoLink :: GenParser Char ParserState Inline
+autoLink :: Parser [Char] ParserState Inline
autoLink = do
(orig, src) <- (try uri <|> try emailAddress)
return $ Link [Str orig] (src, "")
-- | image embedding
-image :: GenParser Char ParserState Inline
+image :: Parser [Char] ParserState Inline
image = try $ do
char '!' >> notFollowedBy space
src <- manyTill anyChar (lookAhead $ oneOf "!(")
@@ -489,49 +507,49 @@ image = try $ do
char '!'
return $ Image [Str alt] (src, alt)
-escapedInline :: GenParser Char ParserState Inline
+escapedInline :: Parser [Char] ParserState Inline
escapedInline = escapedEqs <|> escapedTag
-escapedEqs :: GenParser Char ParserState Inline
+escapedEqs :: Parser [Char] ParserState Inline
escapedEqs = Str <$> (try $ string "==" *> manyTill anyChar (try $ string "=="))
-- | literal text escaped btw <notextile> tags
-escapedTag :: GenParser Char ParserState Inline
+escapedTag :: Parser [Char] ParserState Inline
escapedTag = Str <$>
(try $ string "<notextile>" *> manyTill anyChar (try $ string "</notextile>"))
-- | Any special symbol defined in wordBoundaries
-symbol :: GenParser Char ParserState Inline
+symbol :: Parser [Char] ParserState Inline
symbol = Str . singleton <$> oneOf wordBoundaries
-- | Inline code
-code :: GenParser Char ParserState Inline
+code :: Parser [Char] ParserState Inline
code = code1 <|> code2
-code1 :: GenParser Char ParserState Inline
+code1 :: Parser [Char] ParserState Inline
code1 = Code nullAttr <$> surrounded (char '@') anyChar
-code2 :: GenParser Char ParserState Inline
+code2 :: Parser [Char] ParserState Inline
code2 = do
htmlTag (tagOpen (=="tt") null)
Code nullAttr <$> manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
-- | Html / CSS attributes
-attributes :: GenParser Char ParserState String
+attributes :: Parser [Char] ParserState String
attributes = choice [ enclosed (char '(') (char ')') anyChar,
enclosed (char '{') (char '}') anyChar,
enclosed (char '[') (char ']') anyChar]
-- | Parses material surrounded by a parser.
-surrounded :: GenParser Char st t -- ^ surrounding parser
- -> GenParser Char st a -- ^ content parser (to be used repeatedly)
- -> GenParser Char st [a]
+surrounded :: Parser [Char] st t -- ^ surrounding parser
+ -> Parser [Char] st a -- ^ content parser (to be used repeatedly)
+ -> Parser [Char] st [a]
surrounded border = enclosed border (try border)
-- | Inlines are most of the time of the same form
-simpleInline :: GenParser Char ParserState t -- ^ surrounding parser
+simpleInline :: Parser [Char] ParserState t -- ^ surrounding parser
-> ([Inline] -> Inline) -- ^ Inline constructor
- -> GenParser Char ParserState Inline -- ^ content parser (to be used repeatedly)
+ -> Parser [Char] ParserState Inline -- ^ content parser (to be used repeatedly)
simpleInline border construct = surrounded border (inlineWithAttribute) >>=
return . construct . normalizeSpaces
where inlineWithAttribute = (try $ optional attributes) >> inline
diff --git a/src/Text/Pandoc/SelfContained.hs b/src/Text/Pandoc/SelfContained.hs
index a80ab0c63..7a21f6f3a 100644
--- a/src/Text/Pandoc/SelfContained.hs
+++ b/src/Text/Pandoc/SelfContained.hs
@@ -42,7 +42,7 @@ import System.FilePath (takeExtension, dropExtension, takeDirectory, (</>))
import Data.Char (toLower, isAscii, isAlphaNum)
import Codec.Compression.GZip as Gzip
import qualified Data.ByteString.Lazy as L
-import Text.Pandoc.Shared (findDataFile)
+import Text.Pandoc.Shared (findDataFile, renderTags')
import Text.Pandoc.MIME (getMimeType)
import System.Directory (doesFileExist)
@@ -102,14 +102,14 @@ convertTag userdata t@(TagOpen "script" as) =
src -> do
(raw, mime) <- getRaw userdata (fromAttrib "type" t) src
let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw)
- return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
+ return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
convertTag userdata t@(TagOpen "link" as) =
case fromAttrib "href" t of
[] -> return t
src -> do
(raw, mime) <- getRaw userdata (fromAttrib "type" t) src
let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw)
- return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"])
+ return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"])
convertTag _ t = return t
cssURLs :: Maybe FilePath -> FilePath -> ByteString -> IO ByteString
@@ -163,14 +163,3 @@ makeSelfContained userdata inp = do
out' <- mapM (convertTag userdata) tags
return $ renderTags' out'
--- repeated from HTML reader:
-renderTags' :: [Tag String] -> String
-renderTags' = renderTagsOptions
- renderOptions{ optMinimize = \x ->
- let y = map toLower x
- in y == "hr" || y == "br" ||
- y == "img" || y == "meta" ||
- y == "link"
- , optRawTag = \x ->
- let y = map toLower x
- in y == "script" || y == "style" }
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index f14a57c1f..d86f9a390 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Shared
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -59,13 +59,8 @@ module Text.Pandoc.Shared (
uniqueIdent,
isHeaderBlock,
headerShift,
- -- * Writer options
- HTMLMathMethod (..),
- CiteMethod (..),
- ObfuscationMethod (..),
- HTMLSlideVariant (..),
- WriterOptions (..),
- defaultWriterOptions,
+ -- * TagSoup HTML handling
+ renderTags',
-- * File handling
inDirectory,
findDataFile,
@@ -73,6 +68,8 @@ module Text.Pandoc.Shared (
-- * Error handling
err,
warn,
+ -- * Safe read
+ safeRead
) where
import Text.Pandoc.Definition
@@ -90,11 +87,12 @@ import Data.Generics (Typeable, Data)
import qualified Control.Monad.State as S
import Control.Monad (msum)
import Paths_pandoc (getDataFileName)
-import Text.Pandoc.Highlighting (Style, pygments)
import Text.Pandoc.Pretty (charWidth)
import System.Locale (defaultTimeLocale)
import Data.Time
import System.IO (stderr)
+import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..),
+ renderOptions)
--
-- List processing
@@ -149,7 +147,7 @@ backslashEscapes = map (\ch -> (ch, ['\\',ch]))
-- characters and strings.
escapeStringUsing :: [(Char, String)] -> String -> String
escapeStringUsing _ [] = ""
-escapeStringUsing escapeTable (x:xs) =
+escapeStringUsing escapeTable (x:xs) =
case (lookup x escapeTable) of
Just str -> str ++ rest
Nothing -> x:rest
@@ -176,7 +174,7 @@ stripFirstAndLast :: String -> String
stripFirstAndLast str =
drop 1 $ take ((length str) - 1) str
--- | Change CamelCase word to hyphenated lowercase (e.g., camel-case).
+-- | Change CamelCase word to hyphenated lowercase (e.g., camel-case).
camelCaseToHyphenated :: String -> String
camelCaseToHyphenated [] = ""
camelCaseToHyphenated (a:b:rest) | isLower a && isUpper b =
@@ -247,13 +245,13 @@ normalizeDate s = fmap (formatTime defaultTimeLocale "%F")
-- | Generate infinite lazy list of markers for an ordered list,
-- depending on list attributes.
orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [String]
-orderedListMarkers (start, numstyle, numdelim) =
+orderedListMarkers (start, numstyle, numdelim) =
let singleton c = [c]
nums = case numstyle of
DefaultStyle -> map show [start..]
Example -> map show [start..]
Decimal -> map show [start..]
- UpperAlpha -> drop (start - 1) $ cycle $
+ UpperAlpha -> drop (start - 1) $ cycle $
map singleton ['A'..'Z']
LowerAlpha -> drop (start - 1) $ cycle $
map singleton ['a'..'z']
@@ -271,13 +269,12 @@ orderedListMarkers (start, numstyle, numdelim) =
-- remove empty Str elements.
normalizeSpaces :: [Inline] -> [Inline]
normalizeSpaces = cleanup . dropWhile isSpaceOrEmpty
- where cleanup [] = []
- cleanup (Space:rest) = let rest' = dropWhile isSpaceOrEmpty rest
- in case rest' of
- [] -> []
- _ -> Space : cleanup rest'
+ where cleanup [] = []
+ cleanup (Space:rest) = case dropWhile isSpaceOrEmpty rest of
+ [] -> []
+ (x:xs) -> Space : x : cleanup xs
cleanup ((Str ""):rest) = cleanup rest
- cleanup (x:rest) = x : cleanup rest
+ cleanup (x:rest) = x : cleanup rest
isSpaceOrEmpty :: Inline -> Bool
isSpaceOrEmpty Space = True
@@ -386,7 +383,7 @@ isPara (Para _) = True
isPara _ = False
-- | Data structure for defining hierarchical Pandoc documents
-data Element = Blk Block
+data Element = Blk Block
| Sec Int [Int] String [Inline] [Element]
-- lvl num ident label contents
deriving (Eq, Read, Show, Typeable, Data)
@@ -414,7 +411,7 @@ hierarchicalizeWithIds ((Header level title'):xs) = do
let ident = uniqueIdent title' usedIdents
let lastnum' = take level lastnum
let newnum = if length lastnum' >= level
- then init lastnum' ++ [last lastnum' + 1]
+ then init lastnum' ++ [last lastnum' + 1]
else lastnum ++ replicate (level - length lastnum - 1) 0 ++ [1]
S.put (newnum, (ident : usedIdents))
let (sectionContents, rest) = break (headerLtEq level) xs
@@ -456,112 +453,20 @@ headerShift n = bottomUp shift
shift x = x
--
--- Writer options
+-- TagSoup HTML handling
--
-data HTMLMathMethod = PlainMath
- | LaTeXMathML (Maybe String) -- url of LaTeXMathML.js
- | JsMath (Maybe String) -- url of jsMath load script
- | GladTeX
- | WebTeX String -- url of TeX->image script.
- | MathML (Maybe String) -- url of MathMLinHTML.js
- | MathJax String -- url of MathJax.js
- deriving (Show, Read, Eq)
-
-data CiteMethod = Citeproc -- use citeproc to render them
- | Natbib -- output natbib cite commands
- | Biblatex -- output biblatex cite commands
- deriving (Show, Read, Eq)
-
--- | Methods for obfuscating email addresses in HTML.
-data ObfuscationMethod = NoObfuscation
- | ReferenceObfuscation
- | JavascriptObfuscation
- deriving (Show, Read, Eq)
-
--- | Varieties of HTML slide shows.
-data HTMLSlideVariant = S5Slides
- | SlidySlides
- | SlideousSlides
- | DZSlides
- | NoSlides
- deriving (Show, Read, Eq)
-
--- | Options for writers
-data WriterOptions = WriterOptions
- { writerStandalone :: Bool -- ^ Include header and footer
- , writerTemplate :: String -- ^ Template to use in standalone mode
- , writerVariables :: [(String, String)] -- ^ Variables to set in template
- , writerEPUBMetadata :: String -- ^ Metadata to include in EPUB
- , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs
- , writerTableOfContents :: Bool -- ^ Include table of contents
- , writerSlideVariant :: HTMLSlideVariant -- ^ Are we writing S5, Slidy or Slideous?
- , writerIncremental :: Bool -- ^ True if lists should be incremental
- , writerXeTeX :: Bool -- ^ Create latex suitable for use by xetex
- , writerHTMLMathMethod :: HTMLMathMethod -- ^ How to print math in HTML
- , writerIgnoreNotes :: Bool -- ^ Ignore footnotes (used in making toc)
- , writerNumberSections :: Bool -- ^ Number sections in LaTeX
- , writerSectionDivs :: Bool -- ^ Put sections in div tags in HTML
- , writerStrictMarkdown :: Bool -- ^ Use strict markdown syntax
- , writerReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst
- , writerWrapText :: Bool -- ^ Wrap text to line length
- , writerColumns :: Int -- ^ Characters in a line (for text wrapping)
- , writerLiterateHaskell :: Bool -- ^ Write as literate haskell
- , writerEmailObfuscation :: ObfuscationMethod -- ^ How to obfuscate emails
- , writerIdentifierPrefix :: String -- ^ Prefix for section & note ids in HTML
- , writerSourceDirectory :: FilePath -- ^ Directory path of 1st source file
- , writerUserDataDir :: Maybe FilePath -- ^ Path of user data directory
- , writerCiteMethod :: CiteMethod -- ^ How to print cites
- , writerBiblioFiles :: [FilePath] -- ^ Biblio files to use for citations
- , writerHtml5 :: Bool -- ^ Produce HTML5
- , writerBeamer :: Bool -- ^ Produce beamer LaTeX slide show
- , writerSlideLevel :: Maybe Int -- ^ Force header level of slides
- , writerChapters :: Bool -- ^ Use "chapter" for top-level sects
- , writerListings :: Bool -- ^ Use listings package for code
- , writerHighlight :: Bool -- ^ Highlight source code
- , writerHighlightStyle :: Style -- ^ Style to use for highlighting
- , writerSetextHeaders :: Bool -- ^ Use setext headers for levels 1-2 in markdown
- , writerTeXLigatures :: Bool -- ^ Use tex ligatures quotes, dashes in latex
- } deriving Show
-
-{-# DEPRECATED writerXeTeX "writerXeTeX no longer does anything" #-}
--- | Default writer options.
-defaultWriterOptions :: WriterOptions
-defaultWriterOptions =
- WriterOptions { writerStandalone = False
- , writerTemplate = ""
- , writerVariables = []
- , writerEPUBMetadata = ""
- , writerTabStop = 4
- , writerTableOfContents = False
- , writerSlideVariant = NoSlides
- , writerIncremental = False
- , writerXeTeX = False
- , writerHTMLMathMethod = PlainMath
- , writerIgnoreNotes = False
- , writerNumberSections = False
- , writerSectionDivs = False
- , writerStrictMarkdown = False
- , writerReferenceLinks = False
- , writerWrapText = True
- , writerColumns = 72
- , writerLiterateHaskell = False
- , writerEmailObfuscation = JavascriptObfuscation
- , writerIdentifierPrefix = ""
- , writerSourceDirectory = "."
- , writerUserDataDir = Nothing
- , writerCiteMethod = Citeproc
- , writerBiblioFiles = []
- , writerHtml5 = False
- , writerBeamer = False
- , writerSlideLevel = Nothing
- , writerChapters = False
- , writerListings = False
- , writerHighlight = False
- , writerHighlightStyle = pygments
- , writerSetextHeaders = True
- , writerTeXLigatures = True
- }
+-- | Render HTML tags.
+renderTags' :: [Tag String] -> String
+renderTags' = renderTagsOptions
+ renderOptions{ optMinimize = \x ->
+ let y = map toLower x
+ in y == "hr" || y == "br" ||
+ y == "img" || y == "meta" ||
+ y == "link"
+ , optRawTag = \x ->
+ let y = map toLower x
+ in y == "script" || y == "style" }
--
-- File handling
@@ -606,3 +511,15 @@ warn :: String -> IO ()
warn msg = do
name <- getProgName
UTF8.hPutStrLn stderr $ name ++ ": " ++ msg
+
+--
+-- Safe read
+--
+
+safeRead :: (Monad m, Read a) => String -> m a
+safeRead s = case reads s of
+ (d,x):_
+ | all isSpace x -> return d
+ _ -> fail $ "Could not read `" ++ s ++ "'"
+
+
diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs
index dfdcd8e63..4f5ad54bd 100644
--- a/src/Text/Pandoc/Templates.hs
+++ b/src/Text/Pandoc/Templates.hs
@@ -30,7 +30,7 @@ A simple templating system with variable substitution and conditionals.
Example:
> renderTemplate [("name","Sam"),("salary","50,000")] $
-> "Hi, $name$. $if(salary)$You make $$$salary$.$else$No salary data.$endif$"
+> "Hi, $name$. $if(salary)$You make $$$salary$.$else$No salary data.$endif$"
> "Hi, John. You make $50,000."
A slot for an interpolated variable is a variable name surrounded
@@ -68,8 +68,8 @@ module Text.Pandoc.Templates ( renderTemplate
, TemplateTarget
, getDefaultTemplate ) where
-import Text.ParserCombinators.Parsec
-import Control.Monad (liftM, when, forM)
+import Text.Parsec
+import Control.Monad (liftM, when, forM, mzero)
import System.FilePath
import Data.List (intercalate, intersperse)
#if MIN_VERSION_blaze_html(0,5,0)
@@ -83,22 +83,26 @@ import Text.Pandoc.Shared (readDataFile)
import qualified Control.Exception.Extensible as E (try, IOException)
-- | Get default template for the specified writer.
-getDefaultTemplate :: (Maybe FilePath) -- ^ User data directory to search first
- -> String -- ^ Name of writer
+getDefaultTemplate :: (Maybe FilePath) -- ^ User data directory to search first
+ -> String -- ^ Name of writer
-> IO (Either E.IOException String)
-getDefaultTemplate _ "native" = return $ Right ""
-getDefaultTemplate _ "json" = return $ Right ""
-getDefaultTemplate _ "docx" = return $ Right ""
-getDefaultTemplate user "odt" = getDefaultTemplate user "opendocument"
-getDefaultTemplate user "epub" = getDefaultTemplate user "html"
getDefaultTemplate user writer = do
- let format = takeWhile (/='+') writer -- strip off "+lhs" if present
- let fname = "templates" </> "default" <.> format
- E.try $ readDataFile user fname
+ let format = takeWhile (`notElem` "+-") writer -- strip off extensions
+ case format of
+ "native" -> return $ Right ""
+ "json" -> return $ Right ""
+ "docx" -> return $ Right ""
+ "epub" -> return $ Right ""
+ "odt" -> getDefaultTemplate user "opendocument"
+ "markdown_strict" -> getDefaultTemplate user "markdown"
+ "multimarkdown" -> getDefaultTemplate user "markdown"
+ "markdown_github" -> getDefaultTemplate user "markdown"
+ _ -> let fname = "templates" </> "default" <.> format
+ in E.try $ readDataFile user fname
data TemplateState = TemplateState Int [(String,String)]
-adjustPosition :: String -> GenParser Char TemplateState String
+adjustPosition :: String -> Parsec [Char] TemplateState String
adjustPosition str = do
let lastline = takeWhile (/= '\n') $ reverse str
updateState $ \(TemplateState pos x) ->
@@ -108,18 +112,18 @@ adjustPosition str = do
return str
class TemplateTarget a where
- toTarget :: String -> a
+ toTarget :: String -> a
instance TemplateTarget String where
toTarget = id
-instance TemplateTarget ByteString where
+instance TemplateTarget ByteString where
toTarget = fromString
instance TemplateTarget Html where
toTarget = preEscapedString
--- | Renders a template
+-- | Renders a template
renderTemplate :: TemplateTarget a
=> [(String,String)] -- ^ Assoc. list of values for variables
-> String -- ^ Template
@@ -132,21 +136,21 @@ renderTemplate vals templ =
reservedWords :: [String]
reservedWords = ["else","endif","for","endfor","sep"]
-parseTemplate :: GenParser Char TemplateState [String]
+parseTemplate :: Parsec [Char] TemplateState [String]
parseTemplate =
many $ (plaintext <|> escapedDollar <|> conditional <|> for <|> variable)
>>= adjustPosition
-plaintext :: GenParser Char TemplateState String
+plaintext :: Parsec [Char] TemplateState String
plaintext = many1 $ noneOf "$"
-escapedDollar :: GenParser Char TemplateState String
+escapedDollar :: Parsec [Char] TemplateState String
escapedDollar = try $ string "$$" >> return "$"
-skipEndline :: GenParser Char st ()
+skipEndline :: Parsec [Char] st ()
skipEndline = try $ skipMany (oneOf " \t") >> newline >> return ()
-conditional :: GenParser Char TemplateState String
+conditional :: Parsec [Char] TemplateState String
conditional = try $ do
TemplateState pos vars <- getState
string "$if("
@@ -170,7 +174,7 @@ conditional = try $ do
then ifContents
else elseContents
-for :: GenParser Char TemplateState String
+for :: Parsec [Char] TemplateState String
for = try $ do
TemplateState pos vars <- getState
string "$for("
@@ -178,14 +182,14 @@ for = try $ do
string ")$"
-- if newline after the "for", then a newline after "endfor" will be swallowed
multiline <- option False $ try $ skipEndline >> return True
- let matches = filter (\(k,_) -> k == id') vars
+ let matches = filter (\(k,_) -> k == id') vars
let indent = replicate pos ' '
contents <- forM matches $ \m -> do
updateState $ \(TemplateState p v) -> TemplateState p (m:v)
raw <- liftM concat $ lookAhead parseTemplate
return $ intercalate ('\n':indent) $ lines $ raw ++ "\n"
parseTemplate
- sep <- option "" $ do try (string "$sep$")
+ sep <- option "" $ do try (string "$sep$")
when multiline $ optional skipEndline
liftM concat parseTemplate
string "$endfor$"
@@ -193,16 +197,16 @@ for = try $ do
setState $ TemplateState pos vars
return $ concat $ intersperse sep contents
-ident :: GenParser Char TemplateState String
+ident :: Parsec [Char] TemplateState String
ident = do
first <- letter
rest <- many (alphaNum <|> oneOf "_-")
let id' = first : rest
if id' `elem` reservedWords
- then pzero
+ then mzero
else return id'
-variable :: GenParser Char TemplateState String
+variable :: Parsec [Char] TemplateState String
variable = try $ do
char '$'
id' <- ident
diff --git a/src/Text/Pandoc/UTF8.hs b/src/Text/Pandoc/UTF8.hs
index e2959eae7..508ad30a9 100644
--- a/src/Text/Pandoc/UTF8.hs
+++ b/src/Text/Pandoc/UTF8.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.UTF8
Copyright : Copyright (C) 2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
diff --git a/src/Text/Pandoc/Writers/AsciiDoc.hs b/src/Text/Pandoc/Writers/AsciiDoc.hs
index 1913eb92b..e314cf70e 100644
--- a/src/Text/Pandoc/Writers/AsciiDoc.hs
+++ b/src/Text/Pandoc/Writers/AsciiDoc.hs
@@ -40,8 +40,8 @@ module Text.Pandoc.Writers.AsciiDoc (writeAsciiDoc) where
import Text.Pandoc.Definition
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.Shared
-import Text.Pandoc.Parsing hiding (blankline)
-import Text.ParserCombinators.Parsec ( runParser, GenParser )
+import Text.Pandoc.Options
+import Text.Pandoc.Parsing hiding (blankline, space)
import Data.List ( isPrefixOf, intersperse, intercalate )
import Text.Pandoc.Pretty
import Control.Monad.State
@@ -93,7 +93,7 @@ escapeString = escapeStringUsing escs
where escs = backslashEscapes "{"
-- | Ordered list start parser for use in Para below.
-olMarker :: GenParser Char ParserState Char
+olMarker :: Parser [Char] ParserState Char
olMarker = do (start, style', delim) <- anyOrderedListMarker
if delim == Period &&
(style' == UpperAlpha || (style' == UpperRoman &&
diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs
index 964320eb2..df11d79cc 100644
--- a/src/Text/Pandoc/Writers/ConTeXt.hs
+++ b/src/Text/Pandoc/Writers/ConTeXt.hs
@@ -20,10 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.ConTeXt
Copyright : Copyright (C) 2007-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
+ Stability : alpha
Portability : portable
Conversion of 'Pandoc' format into ConTeXt.
@@ -31,6 +31,7 @@ Conversion of 'Pandoc' format into ConTeXt.
module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where
import Text.Pandoc.Definition
import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Generic (queryWith)
import Text.Printf ( printf )
import Data.List ( intercalate )
@@ -39,23 +40,23 @@ import Text.Pandoc.Pretty
import Text.Pandoc.Templates ( renderTemplate )
import Network.URI ( isURI, unEscapeString )
-data WriterState =
+data WriterState =
WriterState { stNextRef :: Int -- number of next URL reference
, stOrderedListLevel :: Int -- level of ordered list
, stOptions :: WriterOptions -- writer options
}
orderedListStyles :: [[Char]]
-orderedListStyles = cycle ["[n]","[a]", "[r]", "[g]"]
+orderedListStyles = cycle ["[n]","[a]", "[r]", "[g]"]
-- | Convert Pandoc to ConTeXt.
writeConTeXt :: WriterOptions -> Pandoc -> String
-writeConTeXt options document =
+writeConTeXt options document =
let defaultWriterState = WriterState { stNextRef = 1
, stOrderedListLevel = 0
, stOptions = options
- }
- in evalState (pandocToConTeXt options document) defaultWriterState
+ }
+ in evalState (pandocToConTeXt options document) defaultWriterState
pandocToConTeXt :: WriterOptions -> Pandoc -> State WriterState String
pandocToConTeXt options (Pandoc (Meta title authors date) blocks) = do
@@ -120,7 +121,7 @@ elementToConTeXt opts (Sec level _ id' title' elements) = do
return $ vcat (header' : innerContents)
-- | Convert Pandoc block element to ConTeXt.
-blockToConTeXt :: Block
+blockToConTeXt :: Block
-> State WriterState Doc
blockToConTeXt Null = return empty
blockToConTeXt (Plain lst) = inlineListToConTeXt lst
@@ -128,7 +129,7 @@ blockToConTeXt (Para [Image txt (src,_)]) = do
capt <- inlineListToConTeXt txt
return $ blankline $$ "\\placefigure[here,nonumber]" <> braces capt <>
braces ("\\externalfigure" <> brackets (text src)) <> blankline
-blockToConTeXt (Para lst) = do
+blockToConTeXt (Para lst) = do
contents <- inlineListToConTeXt lst
return $ contents <> blankline
blockToConTeXt (BlockQuote lst) = do
@@ -147,18 +148,18 @@ blockToConTeXt (OrderedList (start, style', delim) lst) = do
let level = stOrderedListLevel st
put $ st {stOrderedListLevel = level + 1}
contents <- mapM listItemToConTeXt lst
- put $ st {stOrderedListLevel = level}
+ put $ st {stOrderedListLevel = level}
let start' = if start == 1 then "" else "start=" ++ show start
let delim' = case delim of
DefaultDelim -> ""
- Period -> "stopper=."
- OneParen -> "stopper=)"
+ Period -> "stopper=."
+ OneParen -> "stopper=)"
TwoParens -> "left=(,stopper=)"
- let width = maximum $ map length $ take (length contents)
+ let width = maximum $ map length $ take (length contents)
(orderedListMarkers (start, style', delim))
let width' = (toEnum width + 1) / 2
- let width'' = if width' > (1.5 :: Double)
- then "width=" ++ show width' ++ "em"
+ let width'' = if width' > (1.5 :: Double)
+ then "width=" ++ show width' ++ "em"
else ""
let specs2Items = filter (not . null) [start', delim', width'']
let specs2 = if null specs2Items
@@ -166,8 +167,8 @@ blockToConTeXt (OrderedList (start, style', delim) lst) = do
else "[" ++ intercalate "," specs2Items ++ "]"
let style'' = case style' of
DefaultStyle -> orderedListStyles !! level
- Decimal -> "[n]"
- Example -> "[n]"
+ Decimal -> "[n]"
+ Example -> "[n]"
LowerRoman -> "[r]"
UpperRoman -> "[R]"
LowerAlpha -> "[a]"
@@ -182,21 +183,21 @@ blockToConTeXt HorizontalRule = return $ "\\thinrule" <> blankline
blockToConTeXt (Header level lst) = sectionHeader "" level lst
blockToConTeXt (Table caption aligns widths heads rows) = do
let colDescriptor colWidth alignment = (case alignment of
- AlignLeft -> 'l'
+ AlignLeft -> 'l'
AlignRight -> 'r'
AlignCenter -> 'c'
AlignDefault -> 'l'):
if colWidth == 0
then "|"
else ("p(" ++ printf "%.2f" colWidth ++ "\\textwidth)|")
- let colDescriptors = "|" ++ (concat $
+ let colDescriptors = "|" ++ (concat $
zipWith colDescriptor widths aligns)
headers <- if all null heads
then return empty
- else liftM ($$ "\\HL") $ tableRowToConTeXt heads
- captionText <- inlineListToConTeXt caption
+ else liftM ($$ "\\HL") $ tableRowToConTeXt heads
+ captionText <- inlineListToConTeXt caption
let captionText' = if null caption then text "none" else captionText
- rows' <- mapM tableRowToConTeXt rows
+ rows' <- mapM tableRowToConTeXt rows
return $ "\\placetable[here]" <> braces captionText' $$
"\\starttable" <> brackets (text colDescriptors) $$
"\\HL" $$ headers $$
@@ -230,7 +231,7 @@ inlineListToConTeXt lst = liftM hcat $ mapM inlineToConTeXt lst
-- | Convert inline element to ConTeXt
inlineToConTeXt :: Inline -- ^ Inline to convert
-> State WriterState Doc
-inlineToConTeXt (Emph lst) = do
+inlineToConTeXt (Emph lst) = do
contents <- inlineListToConTeXt lst
return $ braces $ "\\em " <> contents
inlineToConTeXt (Strong lst) = do
diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs
index 1bcf99dcf..e696fc63e 100644
--- a/src/Text/Pandoc/Writers/Docbook.hs
+++ b/src/Text/Pandoc/Writers/Docbook.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.Docbook
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -31,6 +31,7 @@ module Text.Pandoc.Writers.Docbook ( writeDocbook) where
import Text.Pandoc.Definition
import Text.Pandoc.XML
import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.Readers.TeXMath
import Data.List ( isPrefixOf, intercalate, isSuffixOf )
@@ -47,23 +48,23 @@ authorToDocbook opts name' =
let name = render Nothing $ inlinesToDocbook opts name'
in if ',' `elem` name
then -- last name first
- let (lastname, rest) = break (==',') name
+ let (lastname, rest) = break (==',') name
firstname = removeLeadingSpace rest in
- inTagsSimple "firstname" (text $ escapeStringForXML firstname) <>
- inTagsSimple "surname" (text $ escapeStringForXML lastname)
+ inTagsSimple "firstname" (text $ escapeStringForXML firstname) <>
+ inTagsSimple "surname" (text $ escapeStringForXML lastname)
else -- last name last
let namewords = words name
- lengthname = length namewords
+ lengthname = length namewords
(firstname, lastname) = case lengthname of
- 0 -> ("","")
+ 0 -> ("","")
1 -> ("", name)
n -> (intercalate " " (take (n-1) namewords), last namewords)
- in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$
- inTagsSimple "surname" (text $ escapeStringForXML lastname)
+ in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$
+ inTagsSimple "surname" (text $ escapeStringForXML lastname)
-- | Convert Pandoc document to string in Docbook format.
writeDocbook :: WriterOptions -> Pandoc -> String
-writeDocbook opts (Pandoc (Meta tit auths dat) blocks) =
+writeDocbook opts (Pandoc (Meta tit auths dat) blocks) =
let title = inlinesToDocbook opts tit
authors = map (authorToDocbook opts) auths
date = inlinesToDocbook opts dat
@@ -92,7 +93,7 @@ writeDocbook opts (Pandoc (Meta tit auths dat) blocks) =
-- | Convert an Element to Docbook.
elementToDocbook :: WriterOptions -> Int -> Element -> Doc
-elementToDocbook opts _ (Blk block) = blockToDocbook opts block
+elementToDocbook opts _ (Blk block) = blockToDocbook opts block
elementToDocbook opts lvl (Sec _ _num id' title elements) =
-- Docbook doesn't allow sections with no content, so insert some if needed
let elements' = if null elements
@@ -115,10 +116,10 @@ plainToPara :: Block -> Block
plainToPara (Plain x) = Para x
plainToPara x = x
--- | Convert a list of pairs of terms and definitions into a list of
+-- | Convert a list of pairs of terms and definitions into a list of
-- Docbook varlistentrys.
deflistItemsToDocbook :: WriterOptions -> [([Inline],[[Block]])] -> Doc
-deflistItemsToDocbook opts items =
+deflistItemsToDocbook opts items =
vcat $ map (\(term, defs) -> deflistItemToDocbook opts term defs) items
-- | Convert a term and a list of blocks into a Docbook varlistentry.
@@ -144,13 +145,16 @@ blockToDocbook _ Null = empty
blockToDocbook _ (Header _ _) = empty -- should not occur after hierarchicalize
blockToDocbook opts (Plain lst) = inlinesToDocbook opts lst
blockToDocbook opts (Para [Image txt (src,_)]) =
- let capt = inlinesToDocbook opts txt
+ let alt = inlinesToDocbook opts txt
+ capt = if null txt
+ then empty
+ else inTagsSimple "title" alt
in inTagsIndented "figure" $
- inTagsSimple "title" capt $$
+ capt $$
(inTagsIndented "mediaobject" $
(inTagsIndented "imageobject"
(selfClosingTag "imagedata" [("fileref",src)])) $$
- inTagsSimple "textobject" (inTagsSimple "phrase" capt))
+ inTagsSimple "textobject" (inTagsSimple "phrase" alt))
blockToDocbook opts (Para lst) =
inTagsIndented "para" $ inlinesToDocbook opts lst
blockToDocbook opts (BlockQuote blocks) =
@@ -167,9 +171,9 @@ blockToDocbook _ (CodeBlock (_,classes,_) str) =
then [s]
else languagesByExtension . map toLower $ s
langs = concatMap langsFrom classes
-blockToDocbook opts (BulletList lst) =
- inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst
-blockToDocbook _ (OrderedList _ []) = empty
+blockToDocbook opts (BulletList lst) =
+ inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst
+blockToDocbook _ (OrderedList _ []) = empty
blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) =
let attribs = case numstyle of
DefaultStyle -> []
@@ -182,12 +186,12 @@ blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) =
items = if start == 1
then listItemsToDocbook opts (first:rest)
else (inTags True "listitem" [("override",show start)]
- (blocksToDocbook opts $ map plainToPara first)) $$
- listItemsToDocbook opts rest
+ (blocksToDocbook opts $ map plainToPara first)) $$
+ listItemsToDocbook opts rest
in inTags True "orderedlist" attribs items
-blockToDocbook opts (DefinitionList lst) =
- inTagsIndented "variablelist" $ deflistItemsToDocbook opts lst
-blockToDocbook _ (RawBlock "docbook" str) = text str -- raw XML block
+blockToDocbook opts (DefinitionList lst) =
+ inTagsIndented "variablelist" $ deflistItemsToDocbook opts lst
+blockToDocbook _ (RawBlock "docbook" str) = text str -- raw XML block
-- we allow html for compatibility with earlier versions of pandoc
blockToDocbook _ (RawBlock "html" str) = text str -- raw XML block
blockToDocbook _ (RawBlock _ _) = empty
@@ -237,26 +241,26 @@ inlinesToDocbook opts lst = hcat $ map (inlineToDocbook opts) lst
-- | Convert an inline element to Docbook.
inlineToDocbook :: WriterOptions -> Inline -> Doc
-inlineToDocbook _ (Str str) = text $ escapeStringForXML str
-inlineToDocbook opts (Emph lst) =
+inlineToDocbook _ (Str str) = text $ escapeStringForXML str
+inlineToDocbook opts (Emph lst) =
inTagsSimple "emphasis" $ inlinesToDocbook opts lst
-inlineToDocbook opts (Strong lst) =
+inlineToDocbook opts (Strong lst) =
inTags False "emphasis" [("role", "strong")] $ inlinesToDocbook opts lst
-inlineToDocbook opts (Strikeout lst) =
+inlineToDocbook opts (Strikeout lst) =
inTags False "emphasis" [("role", "strikethrough")] $
inlinesToDocbook opts lst
-inlineToDocbook opts (Superscript lst) =
+inlineToDocbook opts (Superscript lst) =
inTagsSimple "superscript" $ inlinesToDocbook opts lst
-inlineToDocbook opts (Subscript lst) =
+inlineToDocbook opts (Subscript lst) =
inTagsSimple "subscript" $ inlinesToDocbook opts lst
-inlineToDocbook opts (SmallCaps lst) =
+inlineToDocbook opts (SmallCaps lst) =
inTags False "emphasis" [("role", "smallcaps")] $
inlinesToDocbook opts lst
-inlineToDocbook opts (Quoted _ lst) =
+inlineToDocbook opts (Quoted _ lst) =
inTagsSimple "quote" $ inlinesToDocbook opts lst
inlineToDocbook opts (Cite _ lst) =
- inlinesToDocbook opts lst
-inlineToDocbook _ (Code _ str) =
+ inlinesToDocbook opts lst
+inlineToDocbook _ (Code _ str) =
inTagsSimple "literal" $ text (escapeStringForXML str)
inlineToDocbook opts (Math t str)
| isMathML (writerHTMLMathMethod opts) =
@@ -282,7 +286,7 @@ inlineToDocbook _ Space = space
inlineToDocbook opts (Link txt (src, _)) =
if isPrefixOf "mailto:" src
then let src' = drop 7 src
- emailLink = inTagsSimple "email" $ text $
+ emailLink = inTagsSimple "email" $ text $
escapeStringForXML $ src'
in case txt of
[Code _ s] | s == src' -> emailLink
@@ -292,14 +296,14 @@ inlineToDocbook opts (Link txt (src, _)) =
then inTags False "link" [("linkend", drop 1 src)]
else inTags False "ulink" [("url", src)]) $
inlinesToDocbook opts txt
-inlineToDocbook _ (Image _ (src, tit)) =
+inlineToDocbook _ (Image _ (src, tit)) =
let titleDoc = if null tit
then empty
else inTagsIndented "objectinfo" $
inTagsIndented "title" (text $ escapeStringForXML tit)
in inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $
titleDoc $$ selfClosingTag "imagedata" [("fileref", src)]
-inlineToDocbook opts (Note contents) =
+inlineToDocbook opts (Note contents) =
inTagsIndented "footnote" $ blocksToDocbook opts contents
isMathML :: HTMLMathMethod -> Bool
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
index 396e7a482..05c9555c6 100644
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -43,6 +43,7 @@ import Text.Pandoc.Generic
import System.Directory
import Text.Pandoc.ImageSize
import Text.Pandoc.Shared hiding (Element)
+import Text.Pandoc.Options
import Text.Pandoc.Readers.TeXMath
import Text.Pandoc.Highlighting ( highlight )
import Text.Highlighting.Kate.Types ()
@@ -93,14 +94,13 @@ mknode s attrs =
add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) . node (unqual s)
-- | Produce an Docx file from a Pandoc document.
-writeDocx :: Maybe FilePath -- ^ Path specified by --reference-docx
- -> WriterOptions -- ^ Writer options
+writeDocx :: WriterOptions -- ^ Writer options
-> Pandoc -- ^ Document to convert
-> IO B.ByteString
-writeDocx mbRefDocx opts doc@(Pandoc (Meta tit auths date) _) = do
+writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
let datadir = writerUserDataDir opts
refArchive <- liftM toArchive $
- case mbRefDocx of
+ case writerReferenceDocx opts of
Just f -> B.readFile f
Nothing -> do
let defaultDocx = getDataFileName "reference.docx" >>= B.readFile
@@ -543,7 +543,7 @@ inlineToOpenXML opts (SmallCaps lst) =
inlineToOpenXML opts (Strikeout lst) =
withTextProp (mknode "w:strike" [] ())
$ inlinesToOpenXML opts lst
-inlineToOpenXML _ LineBreak = return [ mknode "w:br" [] () ]
+inlineToOpenXML _ LineBreak = return [br]
inlineToOpenXML _ (RawInline f str)
| f == "openxml" = return [ x | Elem x <- parseXML str ]
| otherwise = return []
@@ -562,16 +562,14 @@ inlineToOpenXML opts (Math DisplayMath str) =
Left _ -> do
fallback <- inlinesToOpenXML opts (readTeXMath str)
return $ [br] ++ fallback ++ [br]
- where br = mknode "w:br" [] ()
inlineToOpenXML opts (Cite _ lst) = inlinesToOpenXML opts lst
inlineToOpenXML _ (Code attrs str) =
withTextProp (rStyle "VerbatimChar")
$ case highlight formatOpenXML attrs str of
- Nothing -> intercalate [mknode "w:br" [] ()]
+ Nothing -> intercalate [br]
`fmap` (mapM formattedString $ lines str)
Just h -> return h
- where formatOpenXML _fmtOpts = intercalate [mknode "w:br" [] ()] .
- map (map toHlTok)
+ where formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)
toHlTok (toktype,tok) = mknode "w:r" []
[ mknode "w:rPr" []
[ rStyle $ show toktype ]
@@ -669,3 +667,6 @@ inlineToOpenXML opts (Image alt (src, tit)) = do
liftIO $ UTF8.hPutStrLn stderr $
"Could not find image `" ++ src ++ "', skipping..."
inlinesToOpenXML opts alt
+
+br :: Element
+br = mknode "w:r" [] [mknode "w:cr" [] () ]
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
index b423f136f..46310e398 100644
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -38,6 +38,7 @@ import Data.ByteString.Lazy.UTF8 ( fromString )
import Codec.Archive.Zip
import Data.Time.Clock.POSIX
import Text.Pandoc.Shared hiding ( Element )
+import Text.Pandoc.Options
import Text.Pandoc.Definition
import Text.Pandoc.Generic
import Control.Monad.State
@@ -52,12 +53,10 @@ import Prelude hiding (catch)
import Control.Exception (catch, SomeException)
-- | Produce an EPUB file from a Pandoc document.
-writeEPUB :: Maybe String -- ^ EPUB stylesheet specified at command line
- -> [FilePath] -- ^ Paths to fonts to embed
- -> WriterOptions -- ^ Writer options
+writeEPUB :: WriterOptions -- ^ Writer options
-> Pandoc -- ^ Document to convert
-> IO B.ByteString
-writeEPUB mbStylesheet fonts opts doc@(Pandoc meta _) = do
+writeEPUB opts doc@(Pandoc meta _) = do
epochtime <- floor `fmap` getPOSIXTime
let mkEntry path content = toEntry path epochtime content
let opts' = opts{ writerEmailObfuscation = NoObfuscation
@@ -107,7 +106,7 @@ writeEPUB mbStylesheet fonts opts doc@(Pandoc meta _) = do
-- handle fonts
let mkFontEntry f = mkEntry (takeFileName f) `fmap` B.readFile f
- fontEntries <- mapM mkFontEntry fonts
+ fontEntries <- mapM mkFontEntry $ writerEpubFonts opts
-- body pages
let isH1 (Header 1 _) = True
@@ -232,7 +231,7 @@ writeEPUB mbStylesheet fonts opts doc@(Pandoc meta _) = do
let appleEntry = mkEntry "META-INF/com.apple.ibooks.display-options.xml" apple
-- stylesheet
- stylesheet <- case mbStylesheet of
+ stylesheet <- case writerEpubStylesheet opts of
Just s -> return s
Nothing -> readDataFile (writerUserDataDir opts) "epub.css"
let stylesheetEntry = mkEntry "stylesheet.css" $ fromString stylesheet
@@ -249,12 +248,14 @@ metadataElement metadataXML uuid lang title authors date mbCoverImage =
let userNodes = parseXML metadataXML
elt = unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/")
,("xmlns:opf","http://www.idpf.org/2007/opf")] $
- filter isDublinCoreElement $ onlyElems userNodes
+ filter isMetadataElement $ onlyElems userNodes
dublinElements = ["contributor","coverage","creator","date",
"description","format","identifier","language","publisher",
"relation","rights","source","subject","title","type"]
- isDublinCoreElement e = qPrefix (elName e) == Just "dc" &&
- qName (elName e) `elem` dublinElements
+ isMetadataElement e = (qPrefix (elName e) == Just "dc" &&
+ qName (elName e) `elem` dublinElements) ||
+ (qPrefix (elName e) == Nothing &&
+ qName (elName e) `elem` ["link","meta"])
contains e n = not (null (findElements (QName n Nothing (Just "dc")) e))
newNodes = [ unode "dc:title" title | not (elt `contains` "title") ] ++
[ unode "dc:language" lang | not (elt `contains` "language") ] ++
@@ -288,10 +289,8 @@ transformInlines _ sourceDir picsRef (Image lab (src,tit) : xs) = do
transformInlines (MathML _) _ _ (x@(Math _ _) : xs) = do
let writeHtmlInline opts z = removeTrailingSpace $
writeHtmlString opts $ Pandoc (Meta [] [] []) [Plain [z]]
- mathml = writeHtmlInline defaultWriterOptions{
- writerHTMLMathMethod = MathML Nothing } x
- fallback = writeHtmlInline defaultWriterOptions{
- writerHTMLMathMethod = PlainMath } x
+ mathml = writeHtmlInline def{writerHTMLMathMethod = MathML Nothing } x
+ fallback = writeHtmlInline def{writerHTMLMathMethod = PlainMath } x
inOps = "<ops:switch xmlns:ops=\"http://www.idpf.org/2007/ops\">" ++
"<ops:case required-namespace=\"http://www.w3.org/1998/Math/MathML\">" ++
mathml ++ "</ops:case><ops:default>" ++ fallback ++ "</ops:default>" ++
@@ -312,9 +311,9 @@ ppTopElement = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++) . unEntity .
unEntity ('&':'#':xs) =
let (ds,ys) = break (==';') xs
rest = drop 1 ys
- in case reads ('\'':'\\':ds ++ "'") of
- ((x,_):_) -> x : unEntity rest
- _ -> '&':'#':unEntity xs
+ in case safeRead ('\'':'\\':ds ++ "'") of
+ Just x -> x : unEntity rest
+ Nothing -> '&':'#':unEntity xs
unEntity (x:xs) = x : unEntity xs
imageTypeOf :: FilePath -> Maybe String
diff --git a/src/Text/Pandoc/Writers/FB2.hs b/src/Text/Pandoc/Writers/FB2.hs
new file mode 100644
index 000000000..301d80c54
--- /dev/null
+++ b/src/Text/Pandoc/Writers/FB2.hs
@@ -0,0 +1,616 @@
+{-
+Copyright (c) 2011-2012, Sergey Astanin
+All rights reserved.
+
+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
+-}
+
+{- | Conversion of 'Pandoc' documents to FB2 (FictionBook2) format.
+
+FictionBook is an XML-based e-book format. For more information see:
+<http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1>
+
+-}
+module Text.Pandoc.Writers.FB2 (writeFB2) where
+
+import Control.Monad.State (StateT, evalStateT, get, modify)
+import Control.Monad.State (liftM, liftM2, liftIO)
+import Data.ByteString.Base64 (encode)
+import Data.Char (toUpper, toLower, isSpace, isAscii, isControl)
+import Data.List (intersperse, intercalate, isPrefixOf)
+import Data.Either (lefts, rights)
+import Network.Browser (browse, request, setAllowRedirects, setOutHandler)
+import Network.HTTP (catchIO_, getRequest, getHeaders, getResponseBody)
+import Network.HTTP (lookupHeader, HeaderName(..), urlEncode)
+import Network.URI (isURI, unEscapeString)
+import System.FilePath (takeExtension)
+import Text.XML.Light
+import qualified Control.Exception as E
+import qualified Data.ByteString as B
+import qualified Text.XML.Light as X
+import qualified Text.XML.Light.Cursor as XC
+
+import Text.Pandoc.Definition
+import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)
+import Text.Pandoc.Shared (orderedListMarkers)
+import Text.Pandoc.Generic (bottomUp)
+
+-- | Data to be written at the end of the document:
+-- (foot)notes, URLs, references, images.
+data FbRenderState = FbRenderState
+ { footnotes :: [ (Int, String, [Content]) ] -- ^ #, ID, text
+ , imagesToFetch :: [ (String, String) ] -- ^ filename, URL or path
+ , parentListMarker :: String -- ^ list marker of the parent ordered list
+ , parentBulletLevel :: Int -- ^ nesting level of the unordered list
+ , writerOptions :: WriterOptions
+ } deriving (Show)
+
+-- | FictionBook building monad.
+type FBM = StateT FbRenderState IO
+
+newFB :: FbRenderState
+newFB = FbRenderState { footnotes = [], imagesToFetch = []
+ , parentListMarker = "", parentBulletLevel = 0
+ , writerOptions = def }
+
+data ImageMode = NormalImage | InlineImage deriving (Eq)
+instance Show ImageMode where
+ show NormalImage = "imageType"
+ show InlineImage = "inlineImageType"
+
+-- | Produce an FB2 document from a 'Pandoc' document.
+writeFB2 :: WriterOptions -- ^ conversion options
+ -> Pandoc -- ^ document to convert
+ -> IO String -- ^ FictionBook2 document (not encoded yet)
+writeFB2 opts (Pandoc meta blocks) = flip evalStateT newFB $ do
+ modify (\s -> s { writerOptions = opts { writerStandalone = True } })
+ desc <- description meta
+ fp <- frontpage meta
+ secs <- renderSections 1 blocks
+ let body = el "body" $ fp ++ secs
+ notes <- renderFootnotes
+ (imgs,missing) <- liftM imagesToFetch get >>= \s -> liftIO (fetchImages s)
+ let body' = replaceImagesWithAlt missing body
+ let fb2_xml = el "FictionBook" (fb2_attrs, [desc, body'] ++ notes ++ imgs)
+ return $ xml_head ++ (showContent fb2_xml)
+ where
+ xml_head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ fb2_attrs =
+ let xmlns = "http://www.gribuser.ru/xml/fictionbook/2.0"
+ xlink = "http://www.w3.org/1999/xlink"
+ in [ uattr "xmlns" xmlns
+ , attr ("xmlns", "l") xlink ]
+ --
+ frontpage :: Meta -> FBM [Content]
+ frontpage meta' = do
+ t <- cMapM toXml . docTitle $ meta'
+ return $
+ [ el "title" (el "p" t)
+ , el "annotation" (map (el "p" . cMap plain)
+ (docAuthors meta' ++ [docDate meta']))
+ ]
+ description :: Meta -> FBM Content
+ description meta' = do
+ bt <- booktitle meta'
+ let as = authors meta'
+ dd <- docdate meta'
+ return $ el "description"
+ [ el "title-info" (bt ++ as ++ dd)
+ , el "document-info" [ el "program-used" "pandoc" ] -- FIXME: +version
+ ]
+ booktitle :: Meta -> FBM [Content]
+ booktitle meta' = do
+ t <- cMapM toXml . docTitle $ meta'
+ return $ if null t
+ then []
+ else [ el "book-title" t ]
+ authors :: Meta -> [Content]
+ authors meta' = cMap author (docAuthors meta')
+ author :: [Inline] -> [Content]
+ author ss =
+ let ws = words . cMap plain $ ss
+ email = (el "email") `fmap` (take 1 $ filter ('@' `elem`) ws)
+ ws' = filter ('@' `notElem`) ws
+ names = case ws' of
+ (nickname:[]) -> [ el "nickname" nickname ]
+ (fname:lname:[]) -> [ el "first-name" fname
+ , el "last-name" lname ]
+ (fname:rest) -> [ el "first-name" fname
+ , el "middle-name" (concat . init $ rest)
+ , el "last-name" (last rest) ]
+ ([]) -> []
+ in list $ el "author" (names ++ email)
+ docdate :: Meta -> FBM [Content]
+ docdate meta' = do
+ let ss = docDate meta'
+ d <- cMapM toXml ss
+ return $ if null d
+ then []
+ else [el "date" d]
+
+-- | Divide the stream of blocks into sections and convert to XML
+-- representation.
+renderSections :: Int -> [Block] -> FBM [Content]
+renderSections level blocks = do
+ let secs = splitSections level blocks
+ mapM (renderSection level) secs
+
+renderSection :: Int -> ([Inline], [Block]) -> FBM Content
+renderSection level (ttl, body) = do
+ title <- if null ttl
+ then return []
+ else return . list . el "title" . formatTitle $ ttl
+ content <- if (hasSubsections body)
+ then renderSections (level + 1) body
+ else cMapM blockToXml body
+ return $ el "section" (title ++ content)
+ where
+ hasSubsections = any isHeader
+ isHeader (Header _ _) = True
+ isHeader _ = False
+
+-- | Only <p> and <empty-line> are allowed within <title> in FB2.
+formatTitle :: [Inline] -> [Content]
+formatTitle inlines =
+ let lns = split isLineBreak inlines
+ lns' = map (el "p" . cMap plain) lns
+ in intersperse (el "empty-line" ()) lns'
+
+split :: (a -> Bool) -> [a] -> [[a]]
+split _ [] = []
+split cond xs = let (b,a) = break cond xs
+ in (b:split cond (drop 1 a))
+
+isLineBreak :: Inline -> Bool
+isLineBreak LineBreak = True
+isLineBreak _ = False
+
+-- | Divide the stream of block elements into sections: [(title, blocks)].
+splitSections :: Int -> [Block] -> [([Inline], [Block])]
+splitSections level blocks = reverse $ revSplit (reverse blocks)
+ where
+ revSplit [] = []
+ revSplit rblocks =
+ let (lastsec, before) = break sameLevel rblocks
+ (header, prevblocks) =
+ case before of
+ ((Header n title):prevblocks') ->
+ if n == level
+ then (title, prevblocks')
+ else ([], before)
+ _ -> ([], before)
+ in (header, reverse lastsec) : revSplit prevblocks
+ sameLevel (Header n _) = n == level
+ sameLevel _ = False
+
+-- | Make another FictionBook body with footnotes.
+renderFootnotes :: FBM [Content]
+renderFootnotes = do
+ fns <- footnotes `liftM` get
+ if null fns
+ then return [] -- no footnotes
+ else return . list $
+ el "body" ([uattr "name" "notes"], map renderFN (reverse fns))
+ where
+ renderFN (n, idstr, cs) =
+ let fn_texts = (el "title" (el "p" (show n))) : cs
+ in el "section" ([uattr "id" idstr], fn_texts)
+
+-- | Fetch images and encode them for the FictionBook XML.
+-- Return image data and a list of hrefs of the missing images.
+fetchImages :: [(String,String)] -> IO ([Content],[String])
+fetchImages links = do
+ imgs <- mapM (uncurry fetchImage) links
+ return $ (rights imgs, lefts imgs)
+
+-- | Fetch image data from disk or from network and make a <binary> XML section.
+-- Return either (Left hrefOfMissingImage) or (Right xmlContent).
+fetchImage :: String -> String -> IO (Either String Content)
+fetchImage href link = do
+ mbimg <-
+ case (isURI link, readDataURI link) of
+ (True, Just (mime,_,True,base64)) ->
+ let mime' = map toLower mime
+ in if mime' == "image/png" || mime' == "image/jpeg"
+ then return (Just (mime',base64))
+ else return Nothing
+ (True, Just _) -> return Nothing -- not base64-encoded
+ (True, Nothing) -> fetchURL link
+ (False, _) -> do
+ d <- nothingOnError $ B.readFile (unEscapeString link)
+ let t = case map toLower (takeExtension link) of
+ ".png" -> Just "image/png"
+ ".jpg" -> Just "image/jpeg"
+ ".jpeg" -> Just "image/jpeg"
+ ".jpe" -> Just "image/jpeg"
+ _ -> Nothing -- only PNG and JPEG are supported in FB2
+ return $ liftM2 (,) t (liftM (toStr . encode) d)
+ case mbimg of
+ Just (imgtype, imgdata) -> do
+ return . Right $ el "binary"
+ ( [uattr "id" href
+ , uattr "content-type" imgtype]
+ , txt imgdata )
+ _ -> return (Left ('#':href))
+ where
+ nothingOnError :: (IO B.ByteString) -> (IO (Maybe B.ByteString))
+ nothingOnError action = liftM Just action `E.catch` omnihandler
+ omnihandler :: E.SomeException -> IO (Maybe B.ByteString)
+ omnihandler _ = return Nothing
+
+-- | Extract mime type and encoded data from the Data URI.
+readDataURI :: String -- ^ URI
+ -> Maybe (String,String,Bool,String)
+ -- ^ Maybe (mime,charset,isBase64,data)
+readDataURI uri =
+ let prefix = "data:"
+ in if not (prefix `isPrefixOf` uri)
+ then Nothing
+ else
+ let rest = drop (length prefix) uri
+ meta = takeWhile (/= ',') rest -- without trailing ','
+ uridata = drop (length meta + 1) rest
+ parts = split (== ';') meta
+ (mime,cs,enc)=foldr upd ("text/plain","US-ASCII",False) parts
+ in Just (mime,cs,enc,uridata)
+ where
+ upd str m@(mime,cs,enc)
+ | isMimeType str = (str,cs,enc)
+ | "charset=" `isPrefixOf` str = (mime,drop (length "charset=") str,enc)
+ | str == "base64" = (mime,cs,True)
+ | otherwise = m
+
+-- Without parameters like ;charset=...; see RFC 2045, 5.1
+isMimeType :: String -> Bool
+isMimeType s =
+ case split (=='/') s of
+ [mtype,msubtype] ->
+ ((map toLower mtype) `elem` types
+ || "x-" `isPrefixOf` (map toLower mtype))
+ && all valid mtype
+ && all valid msubtype
+ _ -> False
+ where
+ types = ["text","image","audio","video","application","message","multipart"]
+ valid c = isAscii c && not (isControl c) && not (isSpace c) &&
+ c `notElem` "()<>@,;:\\\"/[]?="
+
+-- | Fetch URL, return its Content-Type and binary data on success.
+fetchURL :: String -> IO (Maybe (String, String))
+fetchURL url = do
+ flip catchIO_ (return Nothing) $ do
+ r <- browse $ do
+ setOutHandler (const (return ()))
+ setAllowRedirects True
+ liftM snd . request . getRequest $ url
+ let content_type = lookupHeader HdrContentType (getHeaders r)
+ content <- liftM (Just . toStr . encode . toBS) . getResponseBody $ Right r
+ return $ liftM2 (,) content_type content
+ where
+
+toBS :: String -> B.ByteString
+toBS = B.pack . map (toEnum . fromEnum)
+
+toStr :: B.ByteString -> String
+toStr = map (toEnum . fromEnum) . B.unpack
+
+footnoteID :: Int -> String
+footnoteID i = "n" ++ (show i)
+
+linkID :: Int -> String
+linkID i = "l" ++ (show i)
+
+-- | Convert a block-level Pandoc's element to FictionBook XML representation.
+blockToXml :: Block -> FBM [Content]
+blockToXml (Plain ss) = cMapM toXml ss -- FIXME: can lead to malformed FB2
+blockToXml (Para [Math DisplayMath formula]) = insertMath NormalImage formula
+blockToXml (Para [img@(Image _ _)]) = insertImage NormalImage img
+blockToXml (Para ss) = liftM (list . el "p") $ cMapM toXml ss
+blockToXml (CodeBlock _ s) = return . spaceBeforeAfter .
+ map (el "p" . el "code") . lines $ s
+blockToXml (RawBlock _ s) = return . spaceBeforeAfter .
+ map (el "p" . el "code") . lines $ s
+blockToXml (BlockQuote bs) = liftM (list . el "cite") $ cMapM blockToXml bs
+blockToXml (OrderedList a bss) = do
+ state <- get
+ let pmrk = parentListMarker state
+ let markers = map ((pmrk ++ " ") ++) $ orderedListMarkers a
+ let mkitem mrk bs = do
+ modify (\s -> s { parentListMarker = mrk })
+ itemtext <- cMapM blockToXml . paraToPlain $ bs
+ modify (\s -> s { parentListMarker = pmrk }) -- old parent marker
+ return . el "p" $ [ txt mrk, txt " " ] ++ itemtext
+ mapM (uncurry mkitem) (zip markers bss)
+blockToXml (BulletList bss) = do
+ state <- get
+ let level = parentBulletLevel state
+ let pmrk = parentListMarker state
+ let prefix = replicate (length pmrk) ' '
+ let bullets = ["\x2022", "\x25e6", "*", "\x2043", "\x2023"]
+ let mrk = prefix ++ bullets !! (level `mod` (length bullets))
+ let mkitem bs = do
+ modify (\s -> s { parentBulletLevel = (level+1) })
+ itemtext <- cMapM blockToXml . paraToPlain $ bs
+ modify (\s -> s { parentBulletLevel = level }) -- restore bullet level
+ return $ el "p" $ [ txt (mrk ++ " ") ] ++ itemtext
+ mapM mkitem bss
+blockToXml (DefinitionList defs) =
+ cMapM mkdef defs
+ where
+ mkdef (term, bss) = do
+ def' <- cMapM (cMapM blockToXml . sep . paraToPlain . map indent) bss
+ t <- wrap "strong" term
+ return [ el "p" t, el "p" def' ]
+ sep blocks =
+ if all needsBreak blocks then
+ blocks ++ [Plain [LineBreak]]
+ else
+ blocks
+ needsBreak (Para _) = False
+ needsBreak (Plain ins) = LineBreak `notElem` ins
+ needsBreak _ = True
+blockToXml (Header _ _) = -- should never happen, see renderSections
+ error "unexpected header in section text"
+blockToXml HorizontalRule = return
+ [ el "empty-line" ()
+ , el "p" (txt (replicate 10 '—'))
+ , el "empty-line" () ]
+blockToXml (Table caption aligns _ headers rows) = do
+ hd <- mkrow "th" headers aligns
+ bd <- mapM (\r -> mkrow "td" r aligns) rows
+ c <- return . el "emphasis" =<< cMapM toXml caption
+ return [el "table" (hd : bd), el "p" c]
+ where
+ mkrow :: String -> [TableCell] -> [Alignment] -> FBM Content
+ mkrow tag cells aligns' =
+ (el "tr") `liftM` (mapM (mkcell tag) (zip cells aligns'))
+ --
+ mkcell :: String -> (TableCell, Alignment) -> FBM Content
+ mkcell tag (cell, align) = do
+ cblocks <- cMapM blockToXml cell
+ return $ el tag ([align_attr align], cblocks)
+ --
+ align_attr a = Attr (QName "align" Nothing Nothing) (align_str a)
+ align_str AlignLeft = "left"
+ align_str AlignCenter = "center"
+ align_str AlignRight = "right"
+ align_str AlignDefault = "left"
+blockToXml Null = return []
+
+-- Replace paragraphs with plain text and line break.
+-- Necessary to simulate multi-paragraph lists in FB2.
+paraToPlain :: [Block] -> [Block]
+paraToPlain [] = []
+paraToPlain (Para inlines : rest) =
+ let p = (Plain (inlines ++ [LineBreak]))
+ in p : paraToPlain rest
+paraToPlain (p:rest) = p : paraToPlain rest
+
+-- Simulate increased indentation level. Will not really work
+-- for multi-line paragraphs.
+indent :: Block -> Block
+indent = indentBlock
+ where
+ -- indentation space
+ spacer :: String
+ spacer = replicate 4 ' '
+ --
+ indentBlock (Plain ins) = Plain ((Str spacer):ins)
+ indentBlock (Para ins) = Para ((Str spacer):ins)
+ indentBlock (CodeBlock a s) =
+ let s' = unlines . map (spacer++) . lines $ s
+ in CodeBlock a s'
+ indentBlock (BlockQuote bs) = BlockQuote (map indent bs)
+ indentBlock (Header l ins) = Header l (indentLines ins)
+ indentBlock everythingElse = everythingElse
+ -- indent every (explicit) line
+ indentLines :: [Inline] -> [Inline]
+ indentLines ins = let lns = split isLineBreak ins :: [[Inline]]
+ in intercalate [LineBreak] $ map ((Str spacer):) lns
+
+-- | Convert a Pandoc's Inline element to FictionBook XML representation.
+toXml :: Inline -> FBM [Content]
+toXml (Str s) = return [txt s]
+toXml (Emph ss) = list `liftM` wrap "emphasis" ss
+toXml (Strong ss) = list `liftM` wrap "strong" ss
+toXml (Strikeout ss) = list `liftM` wrap "strikethrough" ss
+toXml (Superscript ss) = list `liftM` wrap "sup" ss
+toXml (Subscript ss) = list `liftM` wrap "sub" ss
+toXml (SmallCaps ss) = cMapM toXml $ bottomUp (map toUpper) ss
+toXml (Quoted SingleQuote ss) = do -- FIXME: should be language-specific
+ inner <- cMapM toXml ss
+ return $ [txt "‘"] ++ inner ++ [txt "’"]
+toXml (Quoted DoubleQuote ss) = do
+ inner <- cMapM toXml ss
+ return $ [txt "“"] ++ inner ++ [txt "”"]
+toXml (Cite _ ss) = cMapM toXml ss -- FIXME: support citation styles
+toXml (Code _ s) = return [el "code" s]
+toXml Space = return [txt " "]
+toXml LineBreak = return [el "empty-line" ()]
+toXml (Math _ formula) = insertMath InlineImage formula
+toXml (RawInline _ _) = return [] -- raw TeX and raw HTML are suppressed
+toXml (Link text (url,ttl)) = do
+ fns <- footnotes `liftM` get
+ let n = 1 + length fns
+ let ln_id = linkID n
+ let ln_ref = list . el "sup" . txt $ "[" ++ show n ++ "]"
+ ln_text <- cMapM toXml text
+ let ln_desc =
+ let ttl' = dropWhile isSpace ttl
+ in if null ttl'
+ then list . el "p" $ el "code" url
+ else list . el "p" $ [ txt (ttl' ++ ": "), el "code" url ]
+ modify (\s -> s { footnotes = (n, ln_id, ln_desc) : fns })
+ return $ ln_text ++
+ [ el "a"
+ ( [ attr ("l","href") ('#':ln_id)
+ , uattr "type" "note" ]
+ , ln_ref) ]
+toXml img@(Image _ _) = insertImage InlineImage img
+toXml (Note bs) = do
+ fns <- footnotes `liftM` get
+ let n = 1 + length fns
+ let fn_id = footnoteID n
+ fn_desc <- cMapM blockToXml bs
+ modify (\s -> s { footnotes = (n, fn_id, fn_desc) : fns })
+ let fn_ref = el "sup" . txt $ "[" ++ show n ++ "]"
+ return . list $ el "a" ( [ attr ("l","href") ('#':fn_id)
+ , uattr "type" "note" ]
+ , fn_ref )
+
+insertMath :: ImageMode -> String -> FBM [Content]
+insertMath immode formula = do
+ htmlMath <- return . writerHTMLMathMethod . writerOptions =<< get
+ case htmlMath of
+ WebTeX url -> do
+ let alt = [Code nullAttr formula]
+ let imgurl = url ++ urlEncode formula
+ let img = Image alt (imgurl, "")
+ insertImage immode img
+ _ -> return [el "code" formula]
+
+insertImage :: ImageMode -> Inline -> FBM [Content]
+insertImage immode (Image alt (url,ttl)) = do
+ images <- imagesToFetch `liftM` get
+ let n = 1 + length images
+ let fname = "image" ++ show n
+ modify (\s -> s { imagesToFetch = (fname, url) : images })
+ let ttlattr = case (immode, null ttl) of
+ (NormalImage, False) -> [ uattr "title" ttl ]
+ _ -> []
+ return . list $
+ el "image" $
+ [ attr ("l","href") ('#':fname)
+ , attr ("l","type") (show immode)
+ , uattr "alt" (cMap plain alt) ]
+ ++ ttlattr
+insertImage _ _ = error "unexpected inline instead of image"
+
+replaceImagesWithAlt :: [String] -> Content -> Content
+replaceImagesWithAlt missingHrefs body =
+ let cur = XC.fromContent body
+ cur' = replaceAll cur
+ in XC.toTree . XC.root $ cur'
+ where
+ --
+ replaceAll :: XC.Cursor -> XC.Cursor
+ replaceAll c =
+ let n = XC.current c
+ c' = if isImage n && isMissing n
+ then XC.modifyContent replaceNode c
+ else c
+ in case XC.nextDF c' of
+ (Just cnext) -> replaceAll cnext
+ Nothing -> c' -- end of document
+ --
+ isImage :: Content -> Bool
+ isImage (Elem e) = (elName e) == (uname "image")
+ isImage _ = False
+ --
+ isMissing (Elem img@(Element _ _ _ _)) =
+ let imgAttrs = elAttribs img
+ badAttrs = map (attr ("l","href")) missingHrefs
+ in any (`elem` imgAttrs) badAttrs
+ isMissing _ = False
+ --
+ replaceNode :: Content -> Content
+ replaceNode n@(Elem img@(Element _ _ _ _)) =
+ let attrs = elAttribs img
+ alt = getAttrVal attrs (uname "alt")
+ imtype = getAttrVal attrs (qname "l" "type")
+ in case (alt, imtype) of
+ (Just alt', Just imtype') ->
+ if imtype' == show NormalImage
+ then el "p" alt'
+ else txt alt'
+ (Just alt', Nothing) -> txt alt' -- no type attribute
+ _ -> n -- don't replace if alt text is not found
+ replaceNode n = n
+ --
+ getAttrVal :: [X.Attr] -> QName -> Maybe String
+ getAttrVal attrs name =
+ case filter ((name ==) . attrKey) attrs of
+ (a:_) -> Just (attrVal a)
+ _ -> Nothing
+
+
+-- | Wrap all inlines with an XML tag (given its unqualified name).
+wrap :: String -> [Inline] -> FBM Content
+wrap tagname inlines = el tagname `liftM` cMapM toXml inlines
+
+-- " Create a singleton list.
+list :: a -> [a]
+list = (:[])
+
+-- | Convert an 'Inline' to plaintext.
+plain :: Inline -> String
+plain (Str s) = s
+plain (Emph ss) = concat (map plain ss)
+plain (Strong ss) = concat (map plain ss)
+plain (Strikeout ss) = concat (map plain ss)
+plain (Superscript ss) = concat (map plain ss)
+plain (Subscript ss) = concat (map plain ss)
+plain (SmallCaps ss) = concat (map plain ss)
+plain (Quoted _ ss) = concat (map plain ss)
+plain (Cite _ ss) = concat (map plain ss) -- FIXME
+plain (Code _ s) = s
+plain Space = " "
+plain LineBreak = "\n"
+plain (Math _ s) = s
+plain (RawInline _ s) = s
+plain (Link text (url,_)) = concat (map plain text ++ [" <", url, ">"])
+plain (Image alt _) = concat (map plain alt)
+plain (Note _) = "" -- FIXME
+
+-- | Create an XML element.
+el :: (Node t)
+ => String -- ^ unqualified element name
+ -> t -- ^ node contents
+ -> Content -- ^ XML content
+el name cs = Elem $ unode name cs
+
+-- | Put empty lines around content
+spaceBeforeAfter :: [Content] -> [Content]
+spaceBeforeAfter cs =
+ let emptyline = el "empty-line" ()
+ in [emptyline] ++ cs ++ [emptyline]
+
+-- | Create a plain-text XML content.
+txt :: String -> Content
+txt s = Text $ CData CDataText s Nothing
+
+-- | Create an XML attribute with an unqualified name.
+uattr :: String -> String -> Text.XML.Light.Attr
+uattr name val = Attr (uname name) val
+
+-- | Create an XML attribute with a qualified name from given namespace.
+attr :: (String, String) -> String -> Text.XML.Light.Attr
+attr (ns, name) val = Attr (qname ns name) val
+
+-- | Unqualified name
+uname :: String -> QName
+uname name = QName name Nothing Nothing
+
+-- | Qualified name
+qname :: String -> String -> QName
+qname ns name = QName name Nothing (Just ns)
+
+-- | Abbreviation for 'concatMap'.
+cMap :: (a -> [b]) -> [a] -> [b]
+cMap = concatMap
+
+-- | Monadic equivalent of 'concatMap'.
+cMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]
+cMapM f xs = concat `liftM` mapM f xs \ No newline at end of file
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
index b8474ee3f..c6c4a8fd7 100644
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -32,6 +32,7 @@ Conversion of 'Pandoc' documents to HTML.
module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where
import Text.Pandoc.Definition
import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Templates
import Text.Pandoc.Generic
import Text.Pandoc.Readers.TeXMath
@@ -272,7 +273,7 @@ elementToHtml slideLevel opts (Sec level num id' title' elements) = do
-- title slides have no content of their own
then filter isSec elements
else elements
- let header'' = if (writerStrictMarkdown opts || writerSectionDivs opts ||
+ let header'' = if (writerSectionDivs opts ||
writerSlideVariant opts == S5Slides || slide)
then header'
else header' ! prefixedId opts id'
@@ -378,13 +379,17 @@ blockToHtml _ Null = return mempty
blockToHtml opts (Plain lst) = inlineListToHtml opts lst
blockToHtml opts (Para [Image txt (s,tit)]) = do
img <- inlineToHtml opts (Image txt (s,tit))
- capt <- inlineListToHtml opts txt
+ let tocapt = if writerHtml5 opts
+ then H5.figcaption
+ else H.p ! A.class_ "caption"
+ capt <- if null txt
+ then return mempty
+ else tocapt `fmap` inlineListToHtml opts txt
return $ if writerHtml5 opts
then H5.figure $ mconcat
- [nl opts, img, H5.figcaption capt, nl opts]
+ [nl opts, img, capt, nl opts]
else H.div ! A.class_ "figure" $ mconcat
- [nl opts, img, H.p ! A.class_ "caption" $ capt,
- nl opts]
+ [nl opts, img, capt, nl opts]
blockToHtml opts (Para lst) = do
contents <- inlineListToHtml opts lst
return $ H.p contents
@@ -392,7 +397,7 @@ blockToHtml _ (RawBlock "html" str) = return $ preEscapedString str
blockToHtml _ (RawBlock _ _) = return mempty
blockToHtml opts (HorizontalRule) = return $ if writerHtml5 opts then H5.hr else H.hr
blockToHtml opts (CodeBlock (id',classes,keyvals) rawCode) = do
- let tolhs = writerLiterateHaskell opts &&
+ let tolhs = isEnabled Ext_literate_haskell opts &&
any (\c -> map toLower c == "haskell") classes &&
any (\c -> map toLower c == "literate") classes
classes' = if tolhs
@@ -618,7 +623,7 @@ inlineToHtml opts inline =
! A.src (toValue $ url ++ urlEncode str)
! A.alt (toValue str)
! A.title (toValue str)
- let brtag = if writerHtml5 opts then H5.br else H.br
+ let brtag = if writerHtml5 opts then H5.br else H.br
return $ case t of
InlineMath -> m
DisplayMath -> brtag >> m >> brtag
@@ -638,7 +643,7 @@ inlineToHtml opts inline =
Left _ -> inlineListToHtml opts
(readTeXMath str) >>= return .
(H.span ! A.class_ "math")
- MathJax _ -> return $ toHtml $
+ MathJax _ -> return $ H.span ! A.class_ "math" $ toHtml $
case t of
InlineMath -> "\\(" ++ str ++ "\\)"
DisplayMath -> "\\[" ++ str ++ "\\]"
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
index 7beee2d42..abbbd4d01 100644
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -32,6 +32,7 @@ module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where
import Text.Pandoc.Definition
import Text.Pandoc.Generic
import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Templates
import Text.Printf ( printf )
import Network.URI ( isAbsoluteURI, unEscapeString )
@@ -265,10 +266,12 @@ blockToLaTeX :: Block -- ^ Block to convert
blockToLaTeX Null = return empty
blockToLaTeX (Plain lst) = inlineListToLaTeX lst
blockToLaTeX (Para [Image txt (src,tit)]) = do
- capt <- inlineListToLaTeX txt
+ capt <- if null txt
+ then return empty
+ else (\c -> "\\caption" <> braces c) `fmap` inlineListToLaTeX txt
img <- inlineToLaTeX (Image txt (src,tit))
return $ "\\begin{figure}[htbp]" $$ "\\centering" $$ img $$
- ("\\caption{" <> capt <> char '}') $$ "\\end{figure}"
+ capt $$ "\\end{figure}"
blockToLaTeX (Para lst) = do
result <- inlineListToLaTeX lst
return result
@@ -287,7 +290,7 @@ blockToLaTeX (BlockQuote lst) = do
blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do
opts <- gets stOptions
case () of
- _ | writerLiterateHaskell opts && "haskell" `elem` classes &&
+ _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes &&
"literate" `elem` classes -> lhsCodeBlock
| writerListings opts -> listingsCodeBlock
| writerHighlight opts && not (null classes) -> highlightedCodeBlock
diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs
index c481e6c87..bececde25 100644
--- a/src/Text/Pandoc/Writers/Man.hs
+++ b/src/Text/Pandoc/Writers/Man.hs
@@ -17,9 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
- Module : Text.Pandoc.Writers.Man
+ Module : Text.Pandoc.Writers.Man
Copyright : Copyright (C) 2007-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -32,6 +32,7 @@ module Text.Pandoc.Writers.Man ( writeMan) where
import Text.Pandoc.Definition
import Text.Pandoc.Templates
import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.Readers.TeXMath
import Text.Printf ( printf )
import Data.List ( isPrefixOf, intersperse, intercalate )
@@ -44,21 +45,21 @@ data WriterState = WriterState { stNotes :: Notes
-- | Convert Pandoc to Man.
writeMan :: WriterOptions -> Pandoc -> String
-writeMan opts document = evalState (pandocToMan opts document) (WriterState [] False)
+writeMan opts document = evalState (pandocToMan opts document) (WriterState [] False)
-- | Return groff man representation of document.
pandocToMan :: WriterOptions -> Pandoc -> State WriterState String
pandocToMan opts (Pandoc (Meta title authors date) blocks) = do
titleText <- inlineListToMan opts title
authors' <- mapM (inlineListToMan opts) authors
- date' <- inlineListToMan opts date
+ date' <- inlineListToMan opts date
let colwidth = if writerWrapText opts
then Just $ writerColumns opts
else Nothing
let render' = render colwidth
let (cmdName, rest) = break (== ' ') $ render' titleText
let (title', section) = case reverse cmdName of
- (')':d:'(':xs) | d `elem` ['0'..'9'] ->
+ (')':d:'(':xs) | d `elem` ['0'..'9'] ->
(text (reverse xs), char d)
xs -> (text (reverse xs), doubleQuotes empty)
let description = hsep $
@@ -86,7 +87,7 @@ notesToMan :: WriterOptions -> [[Block]] -> State WriterState Doc
notesToMan opts notes =
if null notes
then return empty
- else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>=
+ else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>=
return . (text ".SH NOTES" $$) . vcat
-- | Return man representation of a note.
@@ -94,7 +95,7 @@ noteToMan :: WriterOptions -> Int -> [Block] -> State WriterState Doc
noteToMan opts num note = do
contents <- blockListToMan opts note
let marker = cr <> text ".SS " <> brackets (text (show num))
- return $ marker $$ contents
+ return $ marker $$ contents
-- | Association list of characters to escape.
manEscapes :: [(Char, String)]
@@ -104,7 +105,7 @@ manEscapes = [ ('\160', "\\ ")
, ('\x2014', "\\[em]")
, ('\x2013', "\\[en]")
, ('\x2026', "\\&...")
- ] ++ backslashEscapes "@\\"
+ ] ++ backslashEscapes "-@\\"
-- | Escape special characters for Man.
escapeString :: String -> String
@@ -113,7 +114,7 @@ escapeString = escapeStringUsing manEscapes
-- | Escape a literal (code) section for Man.
escapeCode :: String -> String
escapeCode = concat . intersperse "\n" . map escapeLine . lines where
- escapeLine codeline =
+ escapeLine codeline =
case escapeStringUsing (manEscapes ++ backslashEscapes "\t ") codeline of
a@('.':_) -> "\\&" ++ a
b -> b
@@ -150,14 +151,14 @@ splitSentences xs =
-- | Convert Pandoc block element to man.
blockToMan :: WriterOptions -- ^ Options
-> Block -- ^ Block element
- -> State WriterState Doc
+ -> State WriterState Doc
blockToMan _ Null = return empty
-blockToMan opts (Plain inlines) =
+blockToMan opts (Plain inlines) =
liftM vcat $ mapM (inlineListToMan opts) $ splitSentences inlines
blockToMan opts (Para inlines) = do
contents <- liftM vcat $ mapM (inlineListToMan opts) $
splitSentences inlines
- return $ text ".PP" $$ contents
+ return $ text ".PP" $$ contents
blockToMan _ (RawBlock "man" str) = return $ text str
blockToMan _ (RawBlock _ _) = return empty
blockToMan _ HorizontalRule = return $ text ".PP" $$ text " * * * * *"
@@ -166,7 +167,7 @@ blockToMan opts (Header level inlines) = do
let heading = case level of
1 -> ".SH "
_ -> ".SS "
- return $ text heading <> contents
+ return $ text heading <> contents
blockToMan _ (CodeBlock _ str) = return $
text ".IP" $$
text ".nf" $$
@@ -174,10 +175,10 @@ blockToMan _ (CodeBlock _ str) = return $
text (escapeCode str) $$
text "\\f[]" $$
text ".fi"
-blockToMan opts (BlockQuote blocks) = do
+blockToMan opts (BlockQuote blocks) = do
contents <- blockListToMan opts blocks
return $ text ".RS" $$ contents $$ text ".RE"
-blockToMan opts (Table caption alignments widths headers rows) =
+blockToMan opts (Table caption alignments widths headers rows) =
let aligncode AlignLeft = "l"
aligncode AlignRight = "r"
aligncode AlignCenter = "c"
@@ -190,53 +191,53 @@ blockToMan opts (Table caption alignments widths headers rows) =
else map (printf "w(%0.2fn)" . (70 *)) widths
-- 78n default width - 8n indent = 70n
let coldescriptions = text $ intercalate " "
- (zipWith (\align width -> aligncode align ++ width)
+ (zipWith (\align width -> aligncode align ++ width)
alignments iwidths) ++ "."
colheadings <- mapM (blockListToMan opts) headers
- let makeRow cols = text "T{" $$
- (vcat $ intersperse (text "T}@T{") cols) $$
+ let makeRow cols = text "T{" $$
+ (vcat $ intersperse (text "T}@T{") cols) $$
text "T}"
let colheadings' = if all null headers
then empty
else makeRow colheadings $$ char '_'
- body <- mapM (\row -> do
+ body <- mapM (\row -> do
cols <- mapM (blockListToMan opts) row
return $ makeRow cols) rows
- return $ text ".PP" $$ caption' $$
- text ".TS" $$ text "tab(@);" $$ coldescriptions $$
+ return $ text ".PP" $$ caption' $$
+ text ".TS" $$ text "tab(@);" $$ coldescriptions $$
colheadings' $$ vcat body $$ text ".TE"
blockToMan opts (BulletList items) = do
contents <- mapM (bulletListItemToMan opts) items
- return (vcat contents)
+ return (vcat contents)
blockToMan opts (OrderedList attribs items) = do
- let markers = take (length items) $ orderedListMarkers attribs
+ let markers = take (length items) $ orderedListMarkers attribs
let indent = 1 + (maximum $ map length markers)
contents <- mapM (\(num, item) -> orderedListItemToMan opts num indent item) $
- zip markers items
+ zip markers items
return (vcat contents)
-blockToMan opts (DefinitionList items) = do
+blockToMan opts (DefinitionList items) = do
contents <- mapM (definitionListItemToMan opts) items
return (vcat contents)
-- | Convert bullet list item (list of blocks) to man.
bulletListItemToMan :: WriterOptions -> [Block] -> State WriterState Doc
bulletListItemToMan _ [] = return empty
-bulletListItemToMan opts ((Para first):rest) =
+bulletListItemToMan opts ((Para first):rest) =
bulletListItemToMan opts ((Plain first):rest)
bulletListItemToMan opts ((Plain first):rest) = do
- first' <- blockToMan opts (Plain first)
+ first' <- blockToMan opts (Plain first)
rest' <- blockListToMan opts rest
let first'' = text ".IP \\[bu] 2" $$ first'
let rest'' = if null rest
then empty
else text ".RS 2" $$ rest' $$ text ".RE"
- return (first'' $$ rest'')
+ return (first'' $$ rest'')
bulletListItemToMan opts (first:rest) = do
first' <- blockToMan opts first
rest' <- blockListToMan opts rest
return $ text "\\[bu] .RS 2" $$ first' $$ rest' $$ text ".RE"
-
+
-- | Convert ordered list item (a list of blocks) to man.
orderedListItemToMan :: WriterOptions -- ^ options
-> String -- ^ order marker for list item
@@ -244,7 +245,7 @@ orderedListItemToMan :: WriterOptions -- ^ options
-> [Block] -- ^ list item (list of blocks)
-> State WriterState Doc
orderedListItemToMan _ _ _ [] = return empty
-orderedListItemToMan opts num indent ((Para first):rest) =
+orderedListItemToMan opts num indent ((Para first):rest) =
orderedListItemToMan opts num indent ((Plain first):rest)
orderedListItemToMan opts num indent (first:rest) = do
first' <- blockToMan opts first
@@ -254,17 +255,17 @@ orderedListItemToMan opts num indent (first:rest) = do
let rest'' = if null rest
then empty
else text ".RS 4" $$ rest' $$ text ".RE"
- return $ first'' $$ rest''
+ return $ first'' $$ rest''
-- | Convert definition list item (label, list of blocks) to man.
definitionListItemToMan :: WriterOptions
- -> ([Inline],[[Block]])
+ -> ([Inline],[[Block]])
-> State WriterState Doc
definitionListItemToMan opts (label, defs) = do
labelText <- inlineListToMan opts label
- contents <- if null defs
+ contents <- if null defs
then return empty
- else liftM vcat $ forM defs $ \blocks -> do
+ else liftM vcat $ forM defs $ \blocks -> do
let (first, rest) = case blocks of
((Para x):y) -> (Plain x,y)
(x:y) -> (x,y)
@@ -278,7 +279,7 @@ definitionListItemToMan opts (label, defs) = do
-- | Convert list of Pandoc block elements to man.
blockListToMan :: WriterOptions -- ^ Options
-> [Block] -- ^ List of block elements
- -> State WriterState Doc
+ -> State WriterState Doc
blockListToMan opts blocks =
mapM (blockToMan opts) blocks >>= (return . vcat)
@@ -292,7 +293,7 @@ inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat)
-- | Convert Pandoc inline element to man.
inlineToMan :: WriterOptions -> Inline -> State WriterState Doc
-inlineToMan opts (Emph lst) = do
+inlineToMan opts (Emph lst) = do
contents <- inlineListToMan opts lst
return $ text "\\f[I]" <> contents <> text "\\f[]"
inlineToMan opts (Strong lst) = do
@@ -333,16 +334,16 @@ inlineToMan opts (Link txt (src, _)) = do
let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src
return $ case txt of
[Code _ s]
- | s == srcSuffix -> char '<' <> text srcSuffix <> char '>'
+ | s == srcSuffix -> char '<' <> text srcSuffix <> char '>'
_ -> linktext <> text " (" <> text src <> char ')'
inlineToMan opts (Image alternate (source, tit)) = do
- let txt = if (null alternate) || (alternate == [Str ""]) ||
+ let txt = if (null alternate) || (alternate == [Str ""]) ||
(alternate == [Str source]) -- to prevent autolinks
then [Str "image"]
else alternate
- linkPart <- inlineToMan opts (Link txt (source, tit))
+ linkPart <- inlineToMan opts (Link txt (source, tit))
return $ char '[' <> text "IMAGE: " <> linkPart <> char ']'
-inlineToMan _ (Note contents) = do
+inlineToMan _ (Note contents) = do
-- add to notes in state
modify $ \st -> st{ stNotes = contents : stNotes st }
notes <- liftM stNotes get
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
index 9cbcaeb47..d88419feb 100644
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, TupleSections #-}
{-
Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
@@ -18,9 +18,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
- Module : Text.Pandoc.Writers.Markdown
+ Module : Text.Pandoc.Writers.Markdown
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -35,11 +35,15 @@ import Text.Pandoc.Definition
import Text.Pandoc.Generic
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.Shared
-import Text.Pandoc.Parsing hiding (blankline)
-import Text.ParserCombinators.Parsec ( runParser, GenParser )
+import Text.Pandoc.Options
+import Text.Pandoc.Parsing hiding (blankline, char, space)
import Data.List ( group, isPrefixOf, find, intersperse, transpose )
import Text.Pandoc.Pretty
import Control.Monad.State
+import qualified Data.Set as Set
+import Text.Pandoc.Writers.HTML (writeHtmlString)
+import Text.Pandoc.Readers.TeXMath (readTeXMath)
+import Text.HTML.TagSoup (renderTags, parseTags, isTagText, Tag(..))
type Notes = [[Block]]
type Refs = [([Inline], Target)]
@@ -49,7 +53,7 @@ data WriterState = WriterState { stNotes :: Notes
-- | Convert Pandoc to Markdown.
writeMarkdown :: WriterOptions -> Pandoc -> String
-writeMarkdown opts document =
+writeMarkdown opts document =
evalState (pandocToMarkdown opts document) WriterState{ stNotes = []
, stRefs = []
, stPlain = False }
@@ -58,7 +62,9 @@ writeMarkdown opts document =
-- pictures, or inline formatting).
writePlain :: WriterOptions -> Pandoc -> String
writePlain opts document =
- evalState (pandocToMarkdown opts{writerStrictMarkdown = True}
+ evalState (pandocToMarkdown opts{
+ writerExtensions = Set.delete Ext_escaped_line_breaks $
+ writerExtensions opts }
document') WriterState{ stNotes = []
, stRefs = []
, stPlain = True }
@@ -81,15 +87,41 @@ plainify = bottomUp go
go (Cite _ cits) = SmallCaps cits
go x = x
+pandocTitleBlock :: Doc -> [Doc] -> Doc -> Doc
+pandocTitleBlock tit auths dat =
+ hang 2 (text "% ") tit <> cr <>
+ hang 2 (text "% ") (hcat (intersperse (text "; ") auths)) <> cr <>
+ hang 2 (text "% ") dat <> cr
+
+mmdTitleBlock :: Doc -> [Doc] -> Doc -> Doc
+mmdTitleBlock tit auths dat =
+ hang 8 (text "Title: ") tit <> cr <>
+ hang 8 (text "Author: ") (hcat (intersperse (text "; ") auths)) <> cr <>
+ hang 8 (text "Date: ") dat <> cr
+
+plainTitleBlock :: Doc -> [Doc] -> Doc -> Doc
+plainTitleBlock tit auths dat =
+ tit <> cr <>
+ (hcat (intersperse (text "; ") auths)) <> cr <>
+ dat <> cr
+
-- | Return markdown representation of document.
pandocToMarkdown :: WriterOptions -> Pandoc -> State WriterState String
pandocToMarkdown opts (Pandoc (Meta title authors date) blocks) = do
title' <- inlineListToMarkdown opts title
authors' <- mapM (inlineListToMarkdown opts) authors
date' <- inlineListToMarkdown opts date
- let titleblock = not $ null title && null authors && null date
+ isPlain <- gets stPlain
+ let titleblock = case True of
+ _ | isPlain ->
+ plainTitleBlock title' authors' date'
+ | isEnabled Ext_pandoc_title_block opts ->
+ pandocTitleBlock title' authors' date'
+ | isEnabled Ext_mmd_title_block opts ->
+ mmdTitleBlock title' authors' date'
+ | otherwise -> empty
let headerBlocks = filter isHeaderBlock blocks
- let toc = if writerTableOfContents opts
+ let toc = if writerTableOfContents opts
then tableOfContents opts headerBlocks
else empty
body <- blockListToMarkdown opts blocks
@@ -106,11 +138,9 @@ pandocToMarkdown opts (Pandoc (Meta title authors date) blocks) = do
let context = writerVariables opts ++
[ ("toc", render colwidth toc)
, ("body", main)
- , ("title", render colwidth title')
- , ("date", render colwidth date')
] ++
- [ ("titleblock", "yes") | titleblock ] ++
- [ ("author", render colwidth a) | a <- authors' ]
+ [ ("titleblock", render colwidth titleblock)
+ | not (null title && null authors && null date) ]
if writerStandalone opts
then return $ renderTemplate context $ writerTemplate opts
else return main
@@ -119,9 +149,9 @@ pandocToMarkdown opts (Pandoc (Meta title authors date) blocks) = do
refsToMarkdown :: WriterOptions -> Refs -> State WriterState Doc
refsToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat
--- | Return markdown representation of a reference key.
-keyToMarkdown :: WriterOptions
- -> ([Inline], (String, String))
+-- | Return markdown representation of a reference key.
+keyToMarkdown :: WriterOptions
+ -> ([Inline], (String, String))
-> State WriterState Doc
keyToMarkdown opts (label, (src, tit)) = do
label' <- inlineListToMarkdown opts label
@@ -133,7 +163,7 @@ keyToMarkdown opts (label, (src, tit)) = do
-- | Return markdown representation of notes.
notesToMarkdown :: WriterOptions -> [[Block]] -> State WriterState Doc
-notesToMarkdown opts notes =
+notesToMarkdown opts notes =
mapM (\(num, note) -> noteToMarkdown opts num note) (zip [1..] notes) >>=
return . vsep
@@ -142,12 +172,16 @@ noteToMarkdown :: WriterOptions -> Int -> [Block] -> State WriterState Doc
noteToMarkdown opts num blocks = do
contents <- blockListToMarkdown opts blocks
let num' = text $ show num
- let marker = text "[^" <> num' <> text "]:"
+ let marker = if isEnabled Ext_footnotes opts
+ then text "[^" <> num' <> text "]:"
+ else text "[" <> num' <> text "]"
let markerSize = 4 + offset num'
let spacer = case writerTabStop opts - markerSize of
n | n > 0 -> text $ replicate n ' '
_ -> text " "
- return $ hang (writerTabStop opts) (marker <> spacer) contents
+ return $ if isEnabled Ext_footnotes opts
+ then hang (writerTabStop opts) (marker <> spacer) contents
+ else marker <> spacer <> contents
-- | Escape special characters for Markdown.
escapeString :: String -> String
@@ -155,7 +189,7 @@ escapeString = escapeStringUsing markdownEscapes
where markdownEscapes = backslashEscapes "\\`*_$<>#~^"
-- | Construct table of contents from list of header blocks.
-tableOfContents :: WriterOptions -> [Block] -> Doc
+tableOfContents :: WriterOptions -> [Block] -> Doc
tableOfContents opts headers =
let opts' = opts { writerIgnoreNotes = True }
contents = BulletList $ map elementToListItem $ hierarchicalize headers
@@ -166,7 +200,7 @@ tableOfContents opts headers =
-- | Converts an Element to a list item for a table of contents,
elementToListItem :: Element -> [Block]
elementToListItem (Blk _) = []
-elementToListItem (Sec _ _ _ headerText subsecs) = [Plain headerText] ++
+elementToListItem (Sec _ _ _ headerText subsecs) = [Plain headerText] ++
if null subsecs
then []
else [BulletList $ map elementToListItem subsecs]
@@ -188,9 +222,9 @@ attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys]
<> "=\"" <> text v <> "\"") ks
-- | Ordered list start parser for use in Para below.
-olMarker :: GenParser Char ParserState Char
+olMarker :: Parser [Char] ParserState Char
olMarker = do (start, style', delim) <- anyOrderedListMarker
- if delim == Period &&
+ if delim == Period &&
(style' == UpperAlpha || (style' == UpperRoman &&
start `elem` [1, 5, 10, 50, 100, 500, 1000]))
then spaceChar >> spaceChar
@@ -206,7 +240,7 @@ beginsWithOrderedListMarker str =
-- | Convert Pandoc block element to markdown.
blockToMarkdown :: WriterOptions -- ^ Options
-> Block -- ^ Block element
- -> State WriterState Doc
+ -> State WriterState Doc
blockToMarkdown _ Null = return empty
blockToMarkdown opts (Plain inlines) = do
contents <- inlineListToMarkdown opts inlines
@@ -215,14 +249,21 @@ blockToMarkdown opts (Para inlines) = do
contents <- inlineListToMarkdown opts inlines
-- escape if para starts with ordered list marker
st <- get
- let esc = if (not (writerStrictMarkdown opts)) &&
+ let esc = if isEnabled Ext_all_symbols_escapable opts &&
not (stPlain st) &&
beginsWithOrderedListMarker (render Nothing contents)
then text "\x200B" -- zero-width space, a hack
else empty
return $ esc <> contents <> blankline
-blockToMarkdown _ (RawBlock f str)
- | f == "html" || f == "latex" || f == "tex" || f == "markdown" = do
+blockToMarkdown opts (RawBlock f str)
+ | f == "html" = do
+ st <- get
+ if stPlain st
+ then return empty
+ else return $ if isEnabled Ext_markdown_attribute opts
+ then text (addMarkdownAttribute str) <> text "\n"
+ else text str <> text "\n"
+ | f == "latex" || f == "tex" || f == "markdown" = do
st <- get
if stPlain st
then return empty
@@ -243,88 +284,148 @@ blockToMarkdown opts (Header level inlines) = do
contents <> cr <> text (replicate (offset contents) '-') <>
blankline
-- ghc interprets '#' characters in column 1 as linenum specifiers.
- _ | stPlain st || writerLiterateHaskell opts ->
+ _ | stPlain st || isEnabled Ext_literate_haskell opts ->
contents <> blankline
_ -> text (replicate level '#') <> space <> contents <> blankline
blockToMarkdown opts (CodeBlock (_,classes,_) str)
| "haskell" `elem` classes && "literate" `elem` classes &&
- writerLiterateHaskell opts =
+ isEnabled Ext_literate_haskell opts =
return $ prefixed "> " (text str) <> blankline
blockToMarkdown opts (CodeBlock attribs str) = return $
- if writerStrictMarkdown opts || attribs == nullAttr
- then nest (writerTabStop opts) (text str) <> blankline
- else -- use delimited code block
- (tildes <> space <> attrs <> cr <> text str <>
- cr <> tildes) <> blankline
- where tildes = text "~~~~"
- attrs = attrsToMarkdown attribs
+ case attribs of
+ x | x /= nullAttr && isEnabled Ext_fenced_code_blocks opts ->
+ tildes <> space <> attrs <> cr <> text str <>
+ cr <> tildes <> blankline
+ (_,(cls:_),_) | isEnabled Ext_backtick_code_blocks opts ->
+ backticks <> space <> text cls <> cr <> text str <>
+ cr <> backticks <> blankline
+ _ -> nest (writerTabStop opts) (text str) <> blankline
+ where tildes = text $ case [ln | ln <- lines str, all (=='~') ln] of
+ [] -> "~~~~"
+ xs -> case maximum $ map length xs of
+ n | n < 3 -> "~~~~"
+ | otherwise -> replicate (n+1) '~'
+ backticks = text "```"
+ attrs = if isEnabled Ext_fenced_code_attributes opts
+ then attrsToMarkdown attribs
+ else empty
blockToMarkdown opts (BlockQuote blocks) = do
st <- get
-- if we're writing literate haskell, put a space before the bird tracks
-- so they won't be interpreted as lhs...
- let leader = if writerLiterateHaskell opts
+ let leader = if isEnabled Ext_literate_haskell opts
then " > "
else if stPlain st
then " "
else "> "
contents <- blockListToMarkdown opts blocks
return $ (prefixed leader contents) <> blankline
-blockToMarkdown opts (Table caption aligns widths headers rows) = do
+blockToMarkdown opts t@(Table caption aligns widths headers rows) = do
caption' <- inlineListToMarkdown opts caption
- let caption'' = if null caption
+ let caption'' = if null caption || not (isEnabled Ext_table_captions opts)
then empty
else blankline <> ": " <> caption' <> blankline
- headers' <- mapM (blockListToMarkdown opts) headers
+ rawHeaders <- mapM (blockListToMarkdown opts) headers
+ rawRows <- mapM (mapM (blockListToMarkdown opts)) rows
+ let isSimple = all (==0) widths
+ (nst,tbl) <- case isSimple of
+ True | isEnabled Ext_simple_tables opts -> fmap (nest 2,) $
+ pandocTable opts (all null headers) aligns widths
+ rawHeaders rawRows
+ | isEnabled Ext_pipe_tables opts -> fmap (id,) $
+ pipeTable (all null headers) aligns rawHeaders rawRows
+ | otherwise -> fmap (id,) $
+ return $ text $ writeHtmlString def
+ $ Pandoc (Meta [] [] []) [t]
+ False | isEnabled Ext_multiline_tables opts -> fmap (nest 2,) $
+ pandocTable opts (all null headers) aligns widths
+ rawHeaders rawRows
+ | otherwise -> fmap (id,) $
+ return $ text $ writeHtmlString def
+ $ Pandoc (Meta [] [] []) [t]
+ return $ nst $ tbl $$ blankline $$ caption'' $$ blankline
+blockToMarkdown opts (BulletList items) = do
+ contents <- mapM (bulletListItemToMarkdown opts) items
+ return $ cat contents <> blankline
+blockToMarkdown opts (OrderedList (start,sty,delim) items) = do
+ let start' = if isEnabled Ext_startnum opts then start else 1
+ let sty' = if isEnabled Ext_fancy_lists opts then sty else DefaultStyle
+ let delim' = if isEnabled Ext_fancy_lists opts then delim else DefaultDelim
+ let attribs = (start', sty', delim')
+ let markers = orderedListMarkers attribs
+ let markers' = map (\m -> if length m < 3
+ then m ++ replicate (3 - length m) ' '
+ else m) markers
+ contents <- mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $
+ zip markers' items
+ return $ cat contents <> blankline
+blockToMarkdown opts (DefinitionList items) = do
+ contents <- mapM (definitionListItemToMarkdown opts) items
+ return $ cat contents <> blankline
+
+addMarkdownAttribute :: String -> String
+addMarkdownAttribute s =
+ case span isTagText $ reverse $ parseTags s of
+ (xs,(TagOpen t attrs:rest)) ->
+ renderTags $ reverse rest ++ (TagOpen t attrs' : reverse xs)
+ where attrs' = ("markdown","1"):[(x,y) | (x,y) <- attrs,
+ x /= "markdown"]
+ _ -> s
+
+pipeTable :: Bool -> [Alignment] -> [Doc] -> [[Doc]] -> State WriterState Doc
+pipeTable headless aligns rawHeaders rawRows = do
+ let torow cs = nowrap $ text "|" <>
+ hcat (intersperse (text "|") $ map chomp cs) <> text "|"
+ let toborder (a, h) = let wid = max (offset h) 3
+ in text $ case a of
+ AlignLeft -> ':':replicate (wid - 1) '-'
+ AlignCenter -> ':':replicate (wid - 2) '-' ++ ":"
+ AlignRight -> replicate (wid - 1) '-' ++ ":"
+ AlignDefault -> replicate wid '-'
+ let header = if headless then empty else torow rawHeaders
+ let border = torow $ map toborder $ zip aligns rawHeaders
+ let body = vcat $ map torow rawRows
+ return $ header $$ border $$ body
+
+pandocTable :: WriterOptions -> Bool -> [Alignment] -> [Double]
+ -> [Doc] -> [[Doc]] -> State WriterState Doc
+pandocTable opts headless aligns widths rawHeaders rawRows = do
+ let isSimple = all (==0) widths
let alignHeader alignment = case alignment of
AlignLeft -> lblock
AlignCenter -> cblock
AlignRight -> rblock
AlignDefault -> lblock
- rawRows <- mapM (mapM (blockListToMarkdown opts)) rows
- let isSimple = all (==0) widths
let numChars = maximum . map offset
- let widthsInChars =
- if isSimple
- then map ((+2) . numChars) $ transpose (headers' : rawRows)
- else map (floor . (fromIntegral (writerColumns opts) *)) widths
+ let widthsInChars = if isSimple
+ then map ((+2) . numChars)
+ $ transpose (rawHeaders : rawRows)
+ else map
+ (floor . (fromIntegral (writerColumns opts) *))
+ widths
let makeRow = hcat . intersperse (lblock 1 (text " ")) .
(zipWith3 alignHeader aligns widthsInChars)
let rows' = map makeRow rawRows
- let head' = makeRow headers'
+ let head' = makeRow rawHeaders
let maxRowHeight = maximum $ map height (head':rows')
let underline = cat $ intersperse (text " ") $
map (\width -> text (replicate width '-')) widthsInChars
let border = if maxRowHeight > 1
then text (replicate (sum widthsInChars +
length widthsInChars - 1) '-')
- else if all null headers
+ else if headless
then underline
else empty
- let head'' = if all null headers
+ let head'' = if headless
then empty
else border <> cr <> head'
let body = if maxRowHeight > 1
then vsep rows'
else vcat rows'
- let bottom = if all null headers
+ let bottom = if headless
then underline
else border
- return $ nest 2 $ head'' $$ underline $$ body $$
- bottom $$ blankline $$ caption'' $$ blankline
-blockToMarkdown opts (BulletList items) = do
- contents <- mapM (bulletListItemToMarkdown opts) items
- return $ cat contents <> blankline
-blockToMarkdown opts (OrderedList attribs items) = do
- let markers = orderedListMarkers attribs
- let markers' = map (\m -> if length m < 3
- then m ++ replicate (3 - length m) ' '
- else m) markers
- contents <- mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $
- zip markers' items
- return $ cat contents <> blankline
-blockToMarkdown opts (DefinitionList items) = do
- contents <- mapM (definitionListItemToMarkdown opts) items
- return $ cat contents <> blankline
+ return $ head'' $$ underline $$ body $$ bottom
-- | Convert bullet list item (list of blocks) to markdown.
bulletListItemToMarkdown :: WriterOptions -> [Block] -> State WriterState Doc
@@ -349,32 +450,38 @@ orderedListItemToMarkdown opts marker items = do
-- | Convert definition list item (label, list of blocks) to markdown.
definitionListItemToMarkdown :: WriterOptions
- -> ([Inline],[[Block]])
+ -> ([Inline],[[Block]])
-> State WriterState Doc
definitionListItemToMarkdown opts (label, defs) = do
labelText <- inlineListToMarkdown opts label
- let tabStop = writerTabStop opts
- st <- get
- let leader = if stPlain st then " " else ": "
- let sps = case writerTabStop opts - 3 of
- n | n > 0 -> text $ replicate n ' '
- _ -> text " "
defs' <- mapM (mapM (blockToMarkdown opts)) defs
- let contents = vcat $ map (\d -> hang tabStop (leader <> sps) $ vcat d <> cr) defs'
- return $ nowrap labelText <> cr <> contents <> cr
+ if isEnabled Ext_definition_lists opts
+ then do
+ let tabStop = writerTabStop opts
+ st <- get
+ let leader = if stPlain st then " " else ": "
+ let sps = case writerTabStop opts - 3 of
+ n | n > 0 -> text $ replicate n ' '
+ _ -> text " "
+ let contents = vcat $ map (\d -> hang tabStop (leader <> sps) $ vcat d <> cr) defs'
+ return $ nowrap labelText <> cr <> contents <> cr
+ else do
+ return $ nowrap labelText <> text " " <> cr <>
+ vsep (map vsep defs') <> blankline
-- | Convert list of Pandoc block elements to markdown.
blockListToMarkdown :: WriterOptions -- ^ Options
-> [Block] -- ^ List of block elements
- -> State WriterState Doc
+ -> State WriterState Doc
blockListToMarkdown opts blocks =
mapM (blockToMarkdown opts) (fixBlocks blocks) >>= return . cat
-- insert comment between list and indented code block, or the
-- code block will be treated as a list continuation paragraph
where fixBlocks (b : CodeBlock attr x : rest)
- | (writerStrictMarkdown opts || attr == nullAttr) && isListBlock b =
+ | (not (isEnabled Ext_fenced_code_blocks opts) || attr == nullAttr)
+ && isListBlock b =
b : RawBlock "html" "<!-- -->\n" : CodeBlock attr x :
- fixBlocks rest
+ fixBlocks rest
fixBlocks (x : xs) = x : fixBlocks xs
fixBlocks [] = []
isListBlock (BulletList _) = True
@@ -412,7 +519,7 @@ escapeSpaces x = x
-- | Convert Pandoc inline element to markdown.
inlineToMarkdown :: WriterOptions -> Inline -> State WriterState Doc
-inlineToMarkdown opts (Emph lst) = do
+inlineToMarkdown opts (Emph lst) = do
contents <- inlineListToMarkdown opts lst
return $ "*" <> contents <> "*"
inlineToMarkdown opts (Strong lst) = do
@@ -420,15 +527,21 @@ inlineToMarkdown opts (Strong lst) = do
return $ "**" <> contents <> "**"
inlineToMarkdown opts (Strikeout lst) = do
contents <- inlineListToMarkdown opts lst
- return $ "~~" <> contents <> "~~"
+ return $ if isEnabled Ext_strikeout opts
+ then "~~" <> contents <> "~~"
+ else "<s>" <> contents <> "</s>"
inlineToMarkdown opts (Superscript lst) = do
let lst' = bottomUp escapeSpaces lst
contents <- inlineListToMarkdown opts lst'
- return $ "^" <> contents <> "^"
+ return $ if isEnabled Ext_superscript opts
+ then "^" <> contents <> "^"
+ else "<sup>" <> contents <> "</sup>"
inlineToMarkdown opts (Subscript lst) = do
let lst' = bottomUp escapeSpaces lst
contents <- inlineListToMarkdown opts lst'
- return $ "~" <> contents <> "~"
+ return $ if isEnabled Ext_subscript opts
+ then "~" <> contents <> "~"
+ else "<sub>" <> contents <> "</sub>"
inlineToMarkdown opts (SmallCaps lst) = inlineListToMarkdown opts lst
inlineToMarkdown opts (Quoted SingleQuote lst) = do
contents <- inlineListToMarkdown opts lst
@@ -437,33 +550,46 @@ inlineToMarkdown opts (Quoted DoubleQuote lst) = do
contents <- inlineListToMarkdown opts lst
return $ "“" <> contents <> "”"
inlineToMarkdown opts (Code attr str) =
- let tickGroups = filter (\s -> '`' `elem` s) $ group str
+ let tickGroups = filter (\s -> '`' `elem` s) $ group str
longest = if null tickGroups
then 0
- else maximum $ map length tickGroups
- marker = replicate (longest + 1) '`'
+ else maximum $ map length tickGroups
+ marker = replicate (longest + 1) '`'
spacer = if (longest == 0) then "" else " "
- attrs = if writerStrictMarkdown opts || attr == nullAttr
- then empty
- else attrsToMarkdown attr
+ attrs = if isEnabled Ext_inline_code_attributes opts && attr /= nullAttr
+ then attrsToMarkdown attr
+ else empty
in return $ text (marker ++ spacer ++ str ++ spacer ++ marker) <> attrs
inlineToMarkdown _ (Str str) = do
st <- get
if stPlain st
then return $ text str
else return $ text $ escapeString str
-inlineToMarkdown _ (Math InlineMath str) =
- return $ "$" <> text str <> "$"
-inlineToMarkdown _ (Math DisplayMath str) =
- return $ "$$" <> text str <> "$$"
-inlineToMarkdown _ (RawInline f str)
- | f == "html" || f == "latex" || f == "tex" || f == "markdown" =
+inlineToMarkdown opts (Math InlineMath str)
+ | isEnabled Ext_tex_math_dollars opts =
+ return $ "$" <> text str <> "$"
+ | isEnabled Ext_tex_math_single_backslash opts =
+ return $ "\\(" <> text str <> "\\)"
+ | isEnabled Ext_tex_math_double_backslash opts =
+ return $ "\\\\(" <> text str <> "\\\\)"
+ | otherwise = inlineListToMarkdown opts $ readTeXMath str
+inlineToMarkdown opts (Math DisplayMath str)
+ | isEnabled Ext_tex_math_dollars opts =
+ return $ "$$" <> text str <> "$$"
+ | isEnabled Ext_tex_math_single_backslash opts =
+ return $ "\\[" <> text str <> "\\]"
+ | isEnabled Ext_tex_math_double_backslash opts =
+ return $ "\\\\[" <> text str <> "\\\\]"
+ | otherwise = (\x -> cr <> x <> cr) `fmap`
+ inlineListToMarkdown opts (readTeXMath str)
+inlineToMarkdown opts (RawInline f str)
+ | f == "html" || f == "markdown" ||
+ (isEnabled Ext_raw_tex opts && (f == "latex" || f == "tex")) =
return $ text str
inlineToMarkdown _ (RawInline _ _) = return empty
-inlineToMarkdown opts (LineBreak) = return $
- if writerStrictMarkdown opts
- then " " <> cr
- else "\\" <> cr
+inlineToMarkdown opts (LineBreak)
+ | isEnabled Ext_escaped_line_breaks opts = return $ "\\" <> cr
+ | otherwise = return $ " " <> cr
inlineToMarkdown _ Space = return space
inlineToMarkdown opts (Cite (c:cs) lst)
| writerCiteMethod opts == Citeproc = inlineListToMarkdown opts lst
@@ -513,7 +639,7 @@ inlineToMarkdown opts (Link txt (src, tit)) = do
then "[]"
else "[" <> reftext <> "]"
in first <> second
- else "[" <> linktext <> "](" <>
+ else "[" <> linktext <> "](" <>
text src <> linktitle <> ")"
inlineToMarkdown opts (Image alternate (source, tit)) = do
let txt = if null alternate || alternate == [Str source]
@@ -522,8 +648,10 @@ inlineToMarkdown opts (Image alternate (source, tit)) = do
else alternate
linkPart <- inlineToMarkdown opts (Link txt (source, tit))
return $ "!" <> linkPart
-inlineToMarkdown _ (Note contents) = do
+inlineToMarkdown opts (Note contents) = do
modify (\st -> st{ stNotes = contents : stNotes st })
st <- get
let ref = show $ (length $ stNotes st)
- return $ "[^" <> text ref <> "]"
+ if isEnabled Ext_footnotes opts
+ then return $ "[^" <> text ref <> "]"
+ else return $ "[" <> text ref <> "]"
diff --git a/src/Text/Pandoc/Writers/MediaWiki.hs b/src/Text/Pandoc/Writers/MediaWiki.hs
index b32c5327d..84d7393c1 100644
--- a/src/Text/Pandoc/Writers/MediaWiki.hs
+++ b/src/Text/Pandoc/Writers/MediaWiki.hs
@@ -17,9 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
- Module : Text.Pandoc.Writers.MediaWiki
+ Module : Text.Pandoc.Writers.MediaWiki
Copyright : Copyright (C) 2008-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -31,7 +31,8 @@ MediaWiki: <http://www.mediawiki.org/wiki/MediaWiki>
-}
module Text.Pandoc.Writers.MediaWiki ( writeMediaWiki ) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Options
+import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.XML ( escapeStringForXML )
import Data.List ( intersect, intercalate )
@@ -46,9 +47,9 @@ data WriterState = WriterState {
-- | Convert Pandoc to MediaWiki.
writeMediaWiki :: WriterOptions -> Pandoc -> String
-writeMediaWiki opts document =
- evalState (pandocToMediaWiki opts document)
- (WriterState { stNotes = False, stListLevel = [], stUseTags = False })
+writeMediaWiki opts document =
+ evalState (pandocToMediaWiki opts document)
+ (WriterState { stNotes = False, stListLevel = [], stUseTags = False })
-- | Return MediaWiki representation of document.
pandocToMediaWiki :: WriterOptions -> Pandoc -> State WriterState String
@@ -57,7 +58,7 @@ pandocToMediaWiki opts (Pandoc _ blocks) = do
notesExist <- get >>= return . stNotes
let notes = if notesExist
then "\n<references />"
- else ""
+ else ""
let main = body ++ notes
let context = writerVariables opts ++
[ ("body", main) ] ++
@@ -70,22 +71,23 @@ pandocToMediaWiki opts (Pandoc _ blocks) = do
escapeString :: String -> String
escapeString = escapeStringForXML
--- | Convert Pandoc block element to MediaWiki.
+-- | Convert Pandoc block element to MediaWiki.
blockToMediaWiki :: WriterOptions -- ^ Options
-> Block -- ^ Block element
- -> State WriterState String
+ -> State WriterState String
blockToMediaWiki _ Null = return ""
-blockToMediaWiki opts (Plain inlines) =
+blockToMediaWiki opts (Plain inlines) =
inlineListToMediaWiki opts inlines
blockToMediaWiki opts (Para [Image txt (src,tit)]) = do
- capt <- inlineListToMediaWiki opts txt
+ capt <- if null txt
+ then return ""
+ else ("|caption " ++) `fmap` inlineListToMediaWiki opts txt
let opt = if null txt
then ""
- else "|alt=" ++ if null tit then capt else tit ++
- "|caption " ++ capt
+ else "|alt=" ++ if null tit then capt else tit ++ capt
return $ "[[Image:" ++ src ++ "|frame|none" ++ opt ++ "]]\n"
blockToMediaWiki opts (Para inlines) = do
@@ -115,7 +117,7 @@ blockToMediaWiki _ (CodeBlock (_,classes,_) str) = do
"javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc",
"ocaml", "ocaml-brief", "oobas", "oracle8", "pascal", "perl", "php", "php-brief", "plsql",
"python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic",
- "smalltalk", "smarty", "sql", "tcl", "", "thinbasic", "tsql", "vb", "vbnet", "vhdl",
+ "smalltalk", "smarty", "sql", "tcl", "", "thinbasic", "tsql", "vb", "vbnet", "vhdl",
"visualfoxpro", "winbatch", "xml", "xpp", "z80"]
let (beg, end) = if null at
then ("<pre" ++ if null classes then ">" else " class=\"" ++ unwords classes ++ "\">", "</pre>")
@@ -124,7 +126,7 @@ blockToMediaWiki _ (CodeBlock (_,classes,_) str) = do
blockToMediaWiki opts (BlockQuote blocks) = do
contents <- blockListToMediaWiki opts blocks
- return $ "<blockquote>" ++ contents ++ "</blockquote>"
+ return $ "<blockquote>" ++ contents ++ "</blockquote>"
blockToMediaWiki opts (Table capt aligns widths headers rows') = do
let alignStrings = map alignmentToString aligns
@@ -221,7 +223,7 @@ listItemToMediaWiki opts items = do
-- | Convert definition list item (label, list of blocks) to MediaWiki.
definitionListItemToMediaWiki :: WriterOptions
- -> ([Inline],[[Block]])
+ -> ([Inline],[[Block]])
-> State WriterState String
definitionListItemToMediaWiki opts (label, items) = do
labelText <- inlineListToMediaWiki opts label
@@ -242,7 +244,7 @@ isSimpleList x =
BulletList items -> all isSimpleListItem items
OrderedList (num, sty, _) items -> all isSimpleListItem items &&
num == 1 && sty `elem` [DefaultStyle, Decimal]
- DefinitionList items -> all isSimpleListItem $ concatMap snd items
+ DefinitionList items -> all isSimpleListItem $ concatMap snd items
_ -> False
-- | True if list item can be handled with the simple wiki syntax. False if
@@ -287,8 +289,8 @@ tableRowToMediaWiki opts alignStrings rownum cols' = do
0 -> "header"
x | x `rem` 2 == 1 -> "odd"
_ -> "even"
- cols'' <- sequence $ zipWith
- (\alignment item -> tableItemToMediaWiki opts celltype alignment item)
+ cols'' <- sequence $ zipWith
+ (\alignment item -> tableItemToMediaWiki opts celltype alignment item)
alignStrings cols'
return $ "<tr class=\"" ++ rowclass ++ "\">\n" ++ unlines cols'' ++ "</tr>"
@@ -313,7 +315,7 @@ tableItemToMediaWiki opts celltype align' item = do
-- | Convert list of Pandoc block elements to MediaWiki.
blockListToMediaWiki :: WriterOptions -- ^ Options
-> [Block] -- ^ List of block elements
- -> State WriterState String
+ -> State WriterState String
blockListToMediaWiki opts blocks =
mapM (blockToMediaWiki opts) blocks >>= return . vcat
@@ -325,9 +327,9 @@ inlineListToMediaWiki opts lst =
-- | Convert Pandoc inline element to MediaWiki.
inlineToMediaWiki :: WriterOptions -> Inline -> State WriterState String
-inlineToMediaWiki opts (Emph lst) = do
+inlineToMediaWiki opts (Emph lst) = do
contents <- inlineListToMediaWiki opts lst
- return $ "''" ++ contents ++ "''"
+ return $ "''" ++ contents ++ "''"
inlineToMediaWiki opts (Strong lst) = do
contents <- inlineListToMediaWiki opts lst
@@ -365,8 +367,8 @@ inlineToMediaWiki _ (Str str) = return $ escapeString str
inlineToMediaWiki _ (Math _ str) = return $ "<math>" ++ str ++ "</math>"
-- note: str should NOT be escaped
-inlineToMediaWiki _ (RawInline "mediawiki" str) = return str
-inlineToMediaWiki _ (RawInline "html" str) = return str
+inlineToMediaWiki _ (RawInline "mediawiki" str) = return str
+inlineToMediaWiki _ (RawInline "html" str) = return str
inlineToMediaWiki _ (RawInline _ _) = return ""
inlineToMediaWiki _ (LineBreak) = return "<br />\n"
@@ -392,7 +394,7 @@ inlineToMediaWiki opts (Image alt (source, tit)) = do
else "|" ++ tit
return $ "[[Image:" ++ source ++ txt ++ "]]"
-inlineToMediaWiki opts (Note contents) = do
+inlineToMediaWiki opts (Note contents) = do
contents' <- blockListToMediaWiki opts contents
modify (\s -> s { stNotes = True })
return $ "<ref>" ++ contents' ++ "</ref>"
diff --git a/src/Text/Pandoc/Writers/Native.hs b/src/Text/Pandoc/Writers/Native.hs
index d2b56cd17..7fb304e86 100644
--- a/src/Text/Pandoc/Writers/Native.hs
+++ b/src/Text/Pandoc/Writers/Native.hs
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.Native
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -34,7 +34,7 @@ metadata.
-}
module Text.Pandoc.Writers.Native ( writeNative )
where
-import Text.Pandoc.Shared ( WriterOptions(..) )
+import Text.Pandoc.Options ( WriterOptions(..) )
import Data.List ( intersperse )
import Text.Pandoc.Definition
import Text.Pandoc.Pretty
@@ -47,17 +47,17 @@ prettyList ds =
prettyBlock :: Block -> Doc
prettyBlock (BlockQuote blocks) =
"BlockQuote" $$ prettyList (map prettyBlock blocks)
-prettyBlock (OrderedList attribs blockLists) =
+prettyBlock (OrderedList attribs blockLists) =
"OrderedList" <> space <> text (show attribs) $$
(prettyList $ map (prettyList . map prettyBlock) blockLists)
-prettyBlock (BulletList blockLists) =
+prettyBlock (BulletList blockLists) =
"BulletList" $$
(prettyList $ map (prettyList . map prettyBlock) blockLists)
prettyBlock (DefinitionList items) = "DefinitionList" $$
(prettyList $ map deflistitem items)
where deflistitem (term, defs) = "(" <> text (show term) <> "," <> cr <>
nest 1 (prettyList $ map (prettyList . map prettyBlock) defs) <> ")"
-prettyBlock (Table caption aligns widths header rows) =
+prettyBlock (Table caption aligns widths header rows) =
"Table " <> text (show caption) <> " " <> text (show aligns) <> " " <>
text (show widths) $$
prettyRow header $$
diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs
index 9e3dba98a..f43d0a087 100644
--- a/src/Text/Pandoc/Writers/ODT.hs
+++ b/src/Text/Pandoc/Writers/ODT.hs
@@ -36,7 +36,8 @@ import Data.ByteString.Lazy.UTF8 ( fromString )
import Codec.Archive.Zip
import Data.Time.Clock.POSIX
import Paths_pandoc ( getDataFileName )
-import Text.Pandoc.Shared hiding (Element)
+import Text.Pandoc.Options ( WriterOptions(..) )
+import Text.Pandoc.Shared ( stringify )
import Text.Pandoc.ImageSize ( readImageSize, sizeInPoints )
import Text.Pandoc.MIME ( getMimeType )
import Text.Pandoc.Definition
@@ -47,16 +48,16 @@ import Control.Monad (liftM)
import Network.URI ( unEscapeString )
import Text.Pandoc.XML
import Text.Pandoc.Pretty
+import qualified Control.Exception as E
-- | Produce an ODT file from a Pandoc document.
-writeODT :: Maybe FilePath -- ^ Path specified by --reference-odt
- -> WriterOptions -- ^ Writer options
+writeODT :: WriterOptions -- ^ Writer options
-> Pandoc -- ^ Document to convert
-> IO B.ByteString
-writeODT mbRefOdt opts doc@(Pandoc (Meta title _ _) _) = do
+writeODT opts doc@(Pandoc (Meta title _ _) _) = do
let datadir = writerUserDataDir opts
refArchive <- liftM toArchive $
- case mbRefOdt of
+ case writerReferenceODT opts of
Just f -> B.readFile f
Nothing -> do
let defaultODT = getDataFileName "reference.odt" >>= B.readFile
@@ -128,9 +129,9 @@ transformPic sourceDir entriesRef (Image lab (src,tit)) = do
Nothing -> tit
entries <- readIORef entriesRef
let newsrc = "Pictures/" ++ show (length entries) ++ takeExtension src'
- catch (readEntry [] (sourceDir </> src') >>= \entry ->
- modifyIORef entriesRef (entry{ eRelativePath = newsrc } :) >>
- return (Image lab (newsrc, tit')))
- (\_ -> return (Emph lab))
+ E.catch (readEntry [] (sourceDir </> src') >>= \entry ->
+ modifyIORef entriesRef (entry{ eRelativePath = newsrc } :) >>
+ return (Image lab (newsrc, tit')))
+ (\e -> let _ = (e :: E.SomeException) in return (Emph lab))
transformPic _ _ x = return x
diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs
index a0317511a..027ddfda1 100644
--- a/src/Text/Pandoc/Writers/OpenDocument.hs
+++ b/src/Text/Pandoc/Writers/OpenDocument.hs
@@ -31,7 +31,7 @@ Conversion of 'Pandoc' documents to OpenDocument XML.
-}
module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Options
import Text.Pandoc.XML
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.Readers.TeXMath
diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs
index 7eb943a22..b885a7a40 100644
--- a/src/Text/Pandoc/Writers/Org.hs
+++ b/src/Text/Pandoc/Writers/Org.hs
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.Org
Copyright : Copyright (C) 2010 Puneeth Chaganti
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : Puneeth Chaganti <punchagan@gmail.com>
Stability : alpha
@@ -32,14 +32,15 @@ Org-Mode: <http://orgmode.org>
-}
module Text.Pandoc.Writers.Org ( writeOrg) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Options
+import Text.Pandoc.Shared
import Text.Pandoc.Pretty
import Text.Pandoc.Templates (renderTemplate)
import Data.List ( intersect, intersperse, transpose )
import Control.Monad.State
import Control.Applicative ( (<$>) )
-data WriterState =
+data WriterState =
WriterState { stNotes :: [[Block]]
, stLinks :: Bool
, stImages :: Bool
@@ -49,7 +50,7 @@ data WriterState =
-- | Convert Pandoc to Org.
writeOrg :: WriterOptions -> Pandoc -> String
-writeOrg opts document =
+writeOrg opts document =
let st = WriterState { stNotes = [], stLinks = False,
stImages = False, stHasMath = False,
stOptions = opts }
@@ -82,8 +83,8 @@ pandocToOrg (Pandoc (Meta tit auth dat) blocks) = do
-- | Return Org representation of notes.
notesToOrg :: [[Block]] -> State WriterState Doc
-notesToOrg notes =
- mapM (\(num, note) -> noteToOrg num note) (zip [1..] notes) >>=
+notesToOrg notes =
+ mapM (\(num, note) -> noteToOrg num note) (zip [1..] notes) >>=
return . vsep
-- | Return Org representation of a note.
@@ -106,21 +107,24 @@ titleToOrg :: [Inline] -> State WriterState Doc
titleToOrg [] = return empty
titleToOrg lst = do
contents <- inlineListToOrg lst
- return $ "#+TITLE: " <> contents
+ return $ "#+TITLE: " <> contents
--- | Convert Pandoc block element to Org.
+-- | Convert Pandoc block element to Org.
blockToOrg :: Block -- ^ Block element
- -> State WriterState Doc
+ -> State WriterState Doc
blockToOrg Null = return empty
blockToOrg (Plain inlines) = inlineListToOrg inlines
blockToOrg (Para [Image txt (src,tit)]) = do
- capt <- inlineListToOrg txt
+ capt <- if null txt
+ then return empty
+ else (\c -> "#+CAPTION: " <> c <> blankline) `fmap`
+ inlineListToOrg txt
img <- inlineToOrg (Image txt (src,tit))
- return $ "#+CAPTION: " <> capt <> blankline <> img
+ return $ capt <> img
blockToOrg (Para inlines) = do
contents <- inlineListToOrg inlines
return $ contents <> blankline
-blockToOrg (RawBlock "html" str) =
+blockToOrg (RawBlock "html" str) =
return $ blankline $$ "#+BEGIN_HTML" $$
nest 2 (text str) $$ "#+END_HTML" $$ blankline
blockToOrg (RawBlock f str) | f == "org" || f == "latex" || f == "tex" =
@@ -134,17 +138,17 @@ blockToOrg (Header level inlines) = do
blockToOrg (CodeBlock (_,classes,_) str) = do
opts <- stOptions <$> get
let tabstop = writerTabStop opts
- let at = classes `intersect` ["asymptote", "C", "clojure", "css", "ditaa",
- "dot", "emacs-lisp", "gnuplot", "haskell", "js", "latex",
- "ledger", "lisp", "matlab", "mscgen", "ocaml", "octave",
- "oz", "perl", "plantuml", "python", "R", "ruby", "sass",
+ let at = classes `intersect` ["asymptote", "C", "clojure", "css", "ditaa",
+ "dot", "emacs-lisp", "gnuplot", "haskell", "js", "latex",
+ "ledger", "lisp", "matlab", "mscgen", "ocaml", "octave",
+ "oz", "perl", "plantuml", "python", "R", "ruby", "sass",
"scheme", "screen", "sh", "sql", "sqlite"]
let (beg, end) = case at of
[] -> ("#+BEGIN_EXAMPLE", "#+END_EXAMPLE")
(x:_) -> ("#+BEGIN_SRC " ++ x, "#+END_SRC")
return $ text beg $$ nest tabstop (text str) $$ text end $$ blankline
blockToOrg (BlockQuote blocks) = do
- contents <- blockListToOrg blocks
+ contents <- blockListToOrg blocks
return $ blankline $$ "#+BEGIN_QUOTE" $$
nest 2 contents $$ "#+END_QUOTE" $$ blankline
blockToOrg (Table caption' _ _ headers rows) = do
@@ -155,11 +159,11 @@ blockToOrg (Table caption' _ _ headers rows) = do
headers' <- mapM blockListToOrg headers
rawRows <- mapM (mapM blockListToOrg) rows
let numChars = maximum . map offset
- -- FIXME: width is not being used.
+ -- FIXME: width is not being used.
let widthsInChars =
map ((+2) . numChars) $ transpose (headers' : rawRows)
- -- FIXME: Org doesn't allow blocks with height more than 1.
- let hpipeBlocks blocks = hcat [beg, middle, end]
+ -- FIXME: Org doesn't allow blocks with height more than 1.
+ let hpipeBlocks blocks = hcat [beg, middle, end]
where h = maximum (map height blocks)
sep' = lblock 3 $ vcat (map text $ replicate h " | ")
beg = lblock 2 $ vcat (map text $ replicate h "| ")
@@ -170,7 +174,7 @@ blockToOrg (Table caption' _ _ headers rows) = do
rows' <- mapM (\row -> do cols <- mapM blockListToOrg row
return $ makeRow cols) rows
let border ch = char '|' <> char ch <>
- (hcat $ intersperse (char ch <> char '+' <> char ch) $
+ (hcat $ intersperse (char ch <> char '+' <> char ch) $
map (\l -> text $ replicate l ch) widthsInChars) <>
char ch <> char '|'
let body = vcat rows'
@@ -186,7 +190,7 @@ blockToOrg (OrderedList (start, _, delim) items) = do
let delim' = case delim of
TwoParens -> OneParen
x -> x
- let markers = take (length items) $ orderedListMarkers
+ let markers = take (length items) $ orderedListMarkers
(start, Decimal, delim')
let maxMarkerLength = maximum $ map length markers
let markers' = map (\m -> let s = maxMarkerLength - length m
@@ -222,7 +226,7 @@ definitionListItemToOrg (label, defs) = do
-- | Convert list of Pandoc block elements to Org.
blockListToOrg :: [Block] -- ^ List of block elements
- -> State WriterState Doc
+ -> State WriterState Doc
blockListToOrg blocks = mapM blockToOrg blocks >>= return . vcat
-- | Convert list of Pandoc inline elements to Org.
@@ -231,19 +235,19 @@ inlineListToOrg lst = mapM inlineToOrg lst >>= return . hcat
-- | Convert Pandoc inline element to Org.
inlineToOrg :: Inline -> State WriterState Doc
-inlineToOrg (Emph lst) = do
+inlineToOrg (Emph lst) = do
contents <- inlineListToOrg lst
return $ "/" <> contents <> "/"
inlineToOrg (Strong lst) = do
contents <- inlineListToOrg lst
return $ "*" <> contents <> "*"
-inlineToOrg (Strikeout lst) = do
+inlineToOrg (Strikeout lst) = do
contents <- inlineListToOrg lst
return $ "+" <> contents <> "+"
-inlineToOrg (Superscript lst) = do
+inlineToOrg (Superscript lst) = do
contents <- inlineListToOrg lst
return $ "^{" <> contents <> "}"
-inlineToOrg (Subscript lst) = do
+inlineToOrg (Subscript lst) = do
contents <- inlineListToOrg lst
return $ "_{" <> contents <> "}"
inlineToOrg (SmallCaps lst) = inlineListToOrg lst
@@ -276,7 +280,7 @@ inlineToOrg (Link txt (src, _)) = do
inlineToOrg (Image _ (source, _)) = do
modify $ \s -> s{ stImages = True }
return $ "[[" <> text source <> "]]"
-inlineToOrg (Note contents) = do
+inlineToOrg (Note contents) = do
-- add to notes in state
notes <- get >>= (return . stNotes)
modify $ \st -> st { stNotes = contents:notes }
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
index d98079940..5b0b5a414 100644
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -18,9 +18,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
- Module : Text.Pandoc.Writers.RST
+ Module : Text.Pandoc.Writers.RST
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -32,7 +32,8 @@ reStructuredText: <http://docutils.sourceforge.net/rst.html>
-}
module Text.Pandoc.Writers.RST ( writeRST) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Options
+import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate)
import Data.List ( isPrefixOf, intersperse, transpose )
import Text.Pandoc.Pretty
@@ -42,7 +43,7 @@ import Data.Char (isSpace)
type Refs = [([Inline], Target)]
-data WriterState =
+data WriterState =
WriterState { stNotes :: [[Block]]
, stLinks :: Refs
, stImages :: Refs
@@ -52,7 +53,7 @@ data WriterState =
-- | Convert Pandoc to RST.
writeRST :: WriterOptions -> Pandoc -> String
-writeRST opts document =
+writeRST opts document =
let st = WriterState { stNotes = [], stLinks = [],
stImages = [], stHasMath = False,
stOptions = opts }
@@ -89,8 +90,8 @@ pandocToRST (Pandoc (Meta tit auth dat) blocks) = do
refsToRST :: Refs -> State WriterState Doc
refsToRST refs = mapM keyToRST refs >>= return . vcat
--- | Return RST representation of a reference key.
-keyToRST :: ([Inline], (String, String))
+-- | Return RST representation of a reference key.
+keyToRST :: ([Inline], (String, String))
-> State WriterState Doc
keyToRST (label, (src, _)) = do
label' <- inlineListToRST label
@@ -101,7 +102,7 @@ keyToRST (label, (src, _)) = do
-- | Return RST representation of notes.
notesToRST :: [[Block]] -> State WriterState Doc
-notesToRST notes =
+notesToRST notes =
mapM (\(num, note) -> noteToRST num note) (zip [1..] notes) >>=
return . vsep
@@ -116,8 +117,8 @@ noteToRST num note = do
pictRefsToRST :: Refs -> State WriterState Doc
pictRefsToRST refs = mapM pictToRST refs >>= return . vcat
--- | Return RST representation of a picture substitution reference.
-pictToRST :: ([Inline], (String, String))
+-- | Return RST representation of a picture substitution reference.
+pictToRST :: ([Inline], (String, String))
-> State WriterState Doc
pictToRST (label, (src, _)) = do
label' <- inlineListToRST label
@@ -135,9 +136,9 @@ titleToRST lst = do
let border = text (replicate titleLength '=')
return $ border $$ contents $$ border
--- | Convert Pandoc block element to RST.
+-- | Convert Pandoc block element to RST.
blockToRST :: Block -- ^ Block element
- -> State WriterState Doc
+ -> State WriterState Doc
blockToRST Null = return empty
blockToRST (Plain inlines) = inlineListToRST inlines
blockToRST (Para [Image txt (src,tit)]) = do
@@ -163,12 +164,12 @@ blockToRST (CodeBlock (_,classes,_) str) = do
opts <- stOptions <$> get
let tabstop = writerTabStop opts
if "haskell" `elem` classes && "literate" `elem` classes &&
- writerLiterateHaskell opts
+ isEnabled Ext_literate_haskell opts
then return $ prefixed "> " (text str) $$ blankline
else return $ "::" $+$ nest tabstop (text str) $$ blankline
blockToRST (BlockQuote blocks) = do
tabstop <- get >>= (return . writerTabStop . stOptions)
- contents <- blockListToRST blocks
+ contents <- blockListToRST blocks
return $ (nest tabstop contents) <> blankline
blockToRST (Table caption _ widths headers rows) = do
caption' <- inlineListToRST caption
@@ -184,7 +185,7 @@ blockToRST (Table caption _ widths headers rows) = do
if isSimple
then map ((+2) . numChars) $ transpose (headers' : rawRows)
else map (floor . (fromIntegral (writerColumns opts) *)) widths
- let hpipeBlocks blocks = hcat [beg, middle, end]
+ let hpipeBlocks blocks = hcat [beg, middle, end]
where h = maximum (map height blocks)
sep' = lblock 3 $ vcat (map text $ replicate h " | ")
beg = lblock 2 $ vcat (map text $ replicate h "| ")
@@ -195,7 +196,7 @@ blockToRST (Table caption _ widths headers rows) = do
rows' <- mapM (\row -> do cols <- mapM blockListToRST row
return $ makeRow cols) rows
let border ch = char '+' <> char ch <>
- (hcat $ intersperse (char ch <> char '+' <> char ch) $
+ (hcat $ intersperse (char ch <> char '+' <> char ch) $
map (\l -> text $ replicate l ch) widthsInChars) <>
char ch <> char '+'
let body = vcat $ intersperse (border '-') rows'
@@ -208,9 +209,9 @@ blockToRST (BulletList items) = do
-- ensure that sublists have preceding blank line
return $ blankline $$ vcat contents $$ blankline
blockToRST (OrderedList (start, style', delim) items) = do
- let markers = if start == 1 && style' == DefaultStyle && delim == DefaultDelim
+ let markers = if start == 1 && style' == DefaultStyle && delim == DefaultDelim
then take (length items) $ repeat "#."
- else take (length items) $ orderedListMarkers
+ else take (length items) $ orderedListMarkers
(start, style', delim)
let maxMarkerLength = maximum $ map length markers
let markers' = map (\m -> let s = maxMarkerLength - length m
@@ -249,7 +250,7 @@ definitionListItemToRST (label, defs) = do
-- | Convert list of Pandoc block elements to RST.
blockListToRST :: [Block] -- ^ List of block elements
- -> State WriterState Doc
+ -> State WriterState Doc
blockListToRST blocks = mapM blockToRST blocks >>= return . vcat
-- | Convert list of Pandoc inline elements to RST.
@@ -303,19 +304,19 @@ inlineListToRST lst = mapM inlineToRST (insertBS lst) >>= return . hcat
-- | Convert Pandoc inline element to RST.
inlineToRST :: Inline -> State WriterState Doc
-inlineToRST (Emph lst) = do
+inlineToRST (Emph lst) = do
contents <- inlineListToRST lst
return $ "*" <> contents <> "*"
inlineToRST (Strong lst) = do
contents <- inlineListToRST lst
return $ "**" <> contents <> "**"
-inlineToRST (Strikeout lst) = do
+inlineToRST (Strikeout lst) = do
contents <- inlineListToRST lst
return $ "[STRIKEOUT:" <> contents <> "]"
-inlineToRST (Superscript lst) = do
+inlineToRST (Superscript lst) = do
contents <- inlineListToRST lst
return $ ":sup:`" <> contents <> "`"
-inlineToRST (Subscript lst) = do
+inlineToRST (Subscript lst) = do
contents <- inlineListToRST lst
return $ ":sub:`" <> contents <> "`"
inlineToRST (SmallCaps lst) = inlineListToRST lst
@@ -358,7 +359,7 @@ inlineToRST (Link txt (src, tit)) = do
else return $ "`" <> linktext <> " <" <> text src <> ">`_"
inlineToRST (Image alternate (source, tit)) = do
pics <- get >>= return . stImages
- let labelsUsed = map fst pics
+ let labelsUsed = map fst pics
let txt = if null alternate || alternate == [Str ""] ||
alternate `elem` labelsUsed
then [Str $ "image" ++ show (length pics)]
@@ -369,7 +370,7 @@ inlineToRST (Image alternate (source, tit)) = do
modify $ \st -> st { stImages = pics' }
label <- inlineListToRST txt
return $ "|" <> label <> "|"
-inlineToRST (Note contents) = do
+inlineToRST (Note contents) = do
-- add to notes in state
notes <- get >>= return . stNotes
modify $ \st -> st { stNotes = contents:notes }
diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs
index 4e7c2a7cd..1919eb3f2 100644
--- a/src/Text/Pandoc/Writers/RTF.hs
+++ b/src/Text/Pandoc/Writers/RTF.hs
@@ -19,16 +19,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.RTF
Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
+ Stability : alpha
Portability : portable
Conversion of 'Pandoc' documents to RTF (rich text format).
-}
module Text.Pandoc.Writers.RTF ( writeRTF, rtfEmbedImage ) where
import Text.Pandoc.Definition
+import Text.Pandoc.Options
import Text.Pandoc.Shared
import Text.Pandoc.Readers.TeXMath
import Text.Pandoc.Templates (renderTemplate)
@@ -38,6 +39,7 @@ import System.FilePath ( takeExtension )
import qualified Data.ByteString as B
import Text.Printf ( printf )
import Network.URI ( isAbsoluteURI, unEscapeString )
+import qualified Control.Exception as E
-- | Convert Image inlines into a raw RTF embedded image, read from a file.
-- If file not found or filetype not jpeg or png, leave the inline unchanged.
@@ -47,7 +49,8 @@ rtfEmbedImage x@(Image _ (src,_)) = do
if ext `elem` [".jpg",".jpeg",".png"] && not (isAbsoluteURI src)
then do
let src' = unEscapeString src
- imgdata <- catch (B.readFile src') (\_ -> return B.empty)
+ imgdata <- E.catch (B.readFile src')
+ (\e -> let _ = (e :: E.SomeException) in return B.empty)
let bytes = map (printf "%02x") $ B.unpack imgdata
let filetype = case ext of
".jpg" -> "\\jpegblip"
@@ -63,7 +66,7 @@ rtfEmbedImage x = return x
-- | Convert Pandoc to a string in rich text format.
writeRTF :: WriterOptions -> Pandoc -> String
-writeRTF options (Pandoc (Meta title authors date) blocks) =
+writeRTF options (Pandoc (Meta title authors date) blocks) =
let titletext = inlineListToRTF title
authorstext = map inlineListToRTF authors
datetext = inlineListToRTF date
@@ -82,11 +85,11 @@ writeRTF options (Pandoc (Meta title authors date) blocks) =
else body
-- | Construct table of contents from list of header blocks.
-tableOfContents :: [Block] -> String
+tableOfContents :: [Block] -> String
tableOfContents headers =
let contentsTree = hierarchicalize headers
- in concatMap (blockToRTF 0 AlignDefault) $
- [Header 1 [Str "Contents"],
+ in concatMap (blockToRTF 0 AlignDefault) $
+ [Header 1 [Str "Contents"],
BulletList (map elementToListItem contentsTree)]
elementToListItem :: Element -> [Block]
@@ -100,7 +103,7 @@ elementToListItem (Sec _ _ _ sectext subsecs) = [Plain sectext] ++
handleUnicode :: String -> String
handleUnicode [] = []
handleUnicode (c:cs) =
- if ord c > 127
+ if ord c > 127
then '\\':'u':(show (ord c)) ++ "?" ++ handleUnicode cs
else c:(handleUnicode cs)
@@ -130,32 +133,32 @@ rtfParSpaced :: Int -- ^ space after (in twips)
-> Int -- ^ first line indent (relative to block) (in twips)
-> Alignment -- ^ alignment
-> String -- ^ string with content
- -> String
-rtfParSpaced spaceAfter indent firstLineIndent alignment content =
+ -> String
+rtfParSpaced spaceAfter indent firstLineIndent alignment content =
let alignString = case alignment of
AlignLeft -> "\\ql "
AlignRight -> "\\qr "
AlignCenter -> "\\qc "
AlignDefault -> "\\ql "
in "{\\pard " ++ alignString ++
- "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++
+ "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++
" \\fi" ++ (show firstLineIndent) ++ " " ++ content ++ "\\par}\n"
--- | Default paragraph.
+-- | Default paragraph.
rtfPar :: Int -- ^ block indent (in twips)
-> Int -- ^ first line indent (relative to block) (in twips)
-> Alignment -- ^ alignment
-> String -- ^ string with content
- -> String
-rtfPar = rtfParSpaced 180
+ -> String
+rtfPar = rtfParSpaced 180
-- | Compact paragraph (e.g. for compact list items).
rtfCompact :: Int -- ^ block indent (in twips)
-> Int -- ^ first line indent (relative to block) (in twips)
-> Alignment -- ^ alignment
-> String -- ^ string with content
- -> String
-rtfCompact = rtfParSpaced 0
+ -> String
+rtfCompact = rtfParSpaced 0
-- number of twips to indent
indentIncrement :: Int
@@ -172,7 +175,7 @@ bulletMarker indent = case indent `mod` 720 of
-- | Returns appropriate (list of) ordered list markers for indent level.
orderedMarkers :: Int -> ListAttributes -> [String]
-orderedMarkers indent (start, style, delim) =
+orderedMarkers indent (start, style, delim) =
if style == DefaultStyle && delim == DefaultDelim
then case indent `mod` 720 of
0 -> orderedListMarkers (start, Decimal, Period)
@@ -185,30 +188,30 @@ blockToRTF :: Int -- ^ indent level
-> Block -- ^ block to convert
-> String
blockToRTF _ _ Null = ""
-blockToRTF indent alignment (Plain lst) =
+blockToRTF indent alignment (Plain lst) =
rtfCompact indent 0 alignment $ inlineListToRTF lst
-blockToRTF indent alignment (Para lst) =
+blockToRTF indent alignment (Para lst) =
rtfPar indent 0 alignment $ inlineListToRTF lst
-blockToRTF indent alignment (BlockQuote lst) =
- concatMap (blockToRTF (indent + indentIncrement) alignment) lst
+blockToRTF indent alignment (BlockQuote lst) =
+ concatMap (blockToRTF (indent + indentIncrement) alignment) lst
blockToRTF indent _ (CodeBlock _ str) =
rtfPar indent 0 AlignLeft ("\\f1 " ++ (codeStringToRTF str))
blockToRTF _ _ (RawBlock "rtf" str) = str
blockToRTF _ _ (RawBlock _ _) = ""
-blockToRTF indent alignment (BulletList lst) = spaceAtEnd $
+blockToRTF indent alignment (BulletList lst) = spaceAtEnd $
concatMap (listItemToRTF alignment indent (bulletMarker indent)) lst
-blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $
+blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $
zipWith (listItemToRTF alignment indent) (orderedMarkers indent attribs) lst
-blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $
+blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $
concatMap (definitionListItemToRTF alignment indent) lst
-blockToRTF indent _ HorizontalRule =
+blockToRTF indent _ HorizontalRule =
rtfPar indent 0 AlignCenter "\\emdash\\emdash\\emdash\\emdash\\emdash"
blockToRTF indent alignment (Header level lst) = rtfPar indent 0 alignment $
"\\b \\fs" ++ (show (40 - (level * 4))) ++ " " ++ inlineListToRTF lst
-blockToRTF indent alignment (Table caption aligns sizes headers rows) =
+blockToRTF indent alignment (Table caption aligns sizes headers rows) =
(if all null headers
then ""
- else tableRowToRTF True indent aligns sizes headers) ++
+ else tableRowToRTF True indent aligns sizes headers) ++
concatMap (tableRowToRTF False indent aligns sizes) rows ++
rtfPar indent 0 alignment (inlineListToRTF caption)
@@ -230,7 +233,7 @@ tableRowToRTF header indent aligns sizes' cols =
end = "}\n\\intbl\\row}\n"
in start ++ columns ++ end
-tableItemToRTF :: Int -> Alignment -> [Block] -> String
+tableItemToRTF :: Int -> Alignment -> [Block] -> String
tableItemToRTF indent alignment item =
let contents = concatMap (blockToRTF indent alignment) item
in "{\\intbl " ++ contents ++ "\\cell}\n"
@@ -238,7 +241,7 @@ tableItemToRTF indent alignment item =
-- | Ensure that there's the same amount of space after compact
-- lists as after regular lists.
spaceAtEnd :: String -> String
-spaceAtEnd str =
+spaceAtEnd str =
if isSuffixOf "\\par}\n" str
then (take ((length str) - 6) str) ++ "\\sa180\\par}\n"
else str
@@ -249,10 +252,10 @@ listItemToRTF :: Alignment -- ^ alignment
-> String -- ^ list start marker
-> [Block] -- ^ list item (list of blocks)
-> [Char]
-listItemToRTF alignment indent marker [] =
- rtfCompact (indent + listIncrement) (0 - listIncrement) alignment
- (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ")
-listItemToRTF alignment indent marker list =
+listItemToRTF alignment indent marker [] =
+ rtfCompact (indent + listIncrement) (0 - listIncrement) alignment
+ (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ")
+listItemToRTF alignment indent marker list =
let (first:rest) = map (blockToRTF (indent + listIncrement) alignment) list
listMarker = "\\fi" ++ show (0 - listIncrement) ++ " " ++ marker ++ "\\tx" ++
show listIncrement ++ "\\tab"
@@ -275,7 +278,7 @@ definitionListItemToRTF alignment indent (label, defs) =
let labelText = blockToRTF indent alignment (Plain label)
itemsText = concatMap (blockToRTF (indent + listIncrement) alignment) $
concat defs
- in labelText ++ itemsText
+ in labelText ++ itemsText
-- | Convert list of inline items to RTF.
inlineListToRTF :: [Inline] -- ^ list of inlines to convert
@@ -291,9 +294,9 @@ inlineToRTF (Strikeout lst) = "{\\strike " ++ (inlineListToRTF lst) ++ "}"
inlineToRTF (Superscript lst) = "{\\super " ++ (inlineListToRTF lst) ++ "}"
inlineToRTF (Subscript lst) = "{\\sub " ++ (inlineListToRTF lst) ++ "}"
inlineToRTF (SmallCaps lst) = "{\\scaps " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (Quoted SingleQuote lst) =
+inlineToRTF (Quoted SingleQuote lst) =
"\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'"
-inlineToRTF (Quoted DoubleQuote lst) =
+inlineToRTF (Quoted DoubleQuote lst) =
"\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\""
inlineToRTF (Code _ str) = "{\\f1 " ++ (codeStringToRTF str) ++ "}"
inlineToRTF (Str str) = stringToRTF str
@@ -303,11 +306,11 @@ inlineToRTF (RawInline "rtf" str) = str
inlineToRTF (RawInline _ _) = ""
inlineToRTF (LineBreak) = "\\line "
inlineToRTF Space = " "
-inlineToRTF (Link text (src, _)) =
- "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++
+inlineToRTF (Link text (src, _)) =
+ "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++
"\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n"
-inlineToRTF (Image _ (source, _)) =
- "{\\cf1 [image: " ++ source ++ "]\\cf0}"
+inlineToRTF (Image _ (source, _)) =
+ "{\\cf1 [image: " ++ source ++ "]\\cf0}"
inlineToRTF (Note contents) =
- "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++
+ "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++
(concatMap (blockToRTF 0 AlignDefault) contents) ++ "}"
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
index 6bb782899..40e76c615 100644
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -19,16 +19,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.Texinfo
Copyright : Copyright (C) 2008-2010 John MacFarlane and Peter Wang
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
+ Stability : alpha
Portability : portable
Conversion of 'Pandoc' format into Texinfo.
-}
module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where
import Text.Pandoc.Definition
+import Text.Pandoc.Options
import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate)
import Text.Printf ( printf )
@@ -40,7 +41,7 @@ import Text.Pandoc.Pretty
import Network.URI ( isAbsoluteURI, unEscapeString )
import System.FilePath
-data WriterState =
+data WriterState =
WriterState { stStrikeout :: Bool -- document contains strikeout
, stSuperscript :: Bool -- document contains superscript
, stSubscript :: Bool -- document contains subscript
@@ -53,8 +54,8 @@ data WriterState =
-- | Convert Pandoc to Texinfo.
writeTexinfo :: WriterOptions -> Pandoc -> String
-writeTexinfo options document =
- evalState (pandocToTexinfo options $ wrapTop document) $
+writeTexinfo options document =
+ evalState (pandocToTexinfo options $ wrapTop document) $
WriterState { stStrikeout = False, stSuperscript = False, stSubscript = False }
-- | Add a "Top" node around the document, needed by Texinfo.
@@ -116,10 +117,12 @@ blockToTexinfo (Plain lst) =
inlineListToTexinfo lst
blockToTexinfo (Para [Image txt (src,tit)]) = do
- capt <- inlineListToTexinfo txt
+ capt <- if null txt
+ then return empty
+ else (\c -> text "@caption" <> braces c) `fmap`
+ inlineListToTexinfo txt
img <- inlineToTexinfo (Image txt (src,tit))
- return $ text "@float" $$ img $$ (text "@caption{" <> capt <> char '}') $$
- text "@end float"
+ return $ text "@float" $$ img $$ capt $$ text "@end float"
blockToTexinfo (Para lst) =
inlineListToTexinfo lst -- this is handled differently from Plain in blockListToTexinfo
@@ -217,7 +220,7 @@ blockToTexinfo (Table caption aligns widths heads rows) = do
else return $ "@columnfractions " ++ concatMap (printf "%.2f ") widths
let tableBody = text ("@multitable " ++ colDescriptors) $$
headers $$
- vcat rowsText $$
+ vcat rowsText $$
text "@end multitable"
return $ if isEmpty captionText
then tableBody <> blankline
@@ -241,7 +244,7 @@ tableAnyRowToTexinfo :: String
-> [[Block]]
-> State WriterState Doc
tableAnyRowToTexinfo itemtype aligns cols =
- zipWithM alignedBlock aligns cols >>=
+ zipWithM alignedBlock aligns cols >>=
return . (text itemtype $$) . foldl (\row item -> row $$
(if isEmpty row then empty else text " @tab ") <> item) empty
@@ -358,8 +361,8 @@ inlineToTexinfo :: Inline -- ^ Inline to convert
inlineToTexinfo (Emph lst) =
inlineListToTexinfo lst >>= return . inCmd "emph"
-inlineToTexinfo (Strong lst) =
- inlineListToTexinfo lst >>= return . inCmd "strong"
+inlineToTexinfo (Strong lst) =
+ inlineListToTexinfo lst >>= return . inCmd "strong"
inlineToTexinfo (Strikeout lst) = do
modify $ \st -> st{ stStrikeout = True }
diff --git a/src/Text/Pandoc/Writers/Textile.hs b/src/Text/Pandoc/Writers/Textile.hs
index 26d5ec6d7..5f3bb6bcd 100644
--- a/src/Text/Pandoc/Writers/Textile.hs
+++ b/src/Text/Pandoc/Writers/Textile.hs
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Writers.Textile
Copyright : Copyright (C) 2010 John MacFarlane
- License : GNU GPL, version 2 or above
+ License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
@@ -31,7 +31,8 @@ Textile: <http://thresholdstate.com/articles/4312/the-textile-reference-manual>
-}
module Text.Pandoc.Writers.Textile ( writeTextile ) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Options
+import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.XML ( escapeStringForXML )
import Data.List ( intercalate )
@@ -46,9 +47,9 @@ data WriterState = WriterState {
-- | Convert Pandoc to Textile.
writeTextile :: WriterOptions -> Pandoc -> String
-writeTextile opts document =
- evalState (pandocToTextile opts document)
- (WriterState { stNotes = [], stListLevel = [], stUseTags = False })
+writeTextile opts document =
+ evalState (pandocToTextile opts document)
+ (WriterState { stNotes = [], stListLevel = [], stUseTags = False })
-- | Return Textile representation of document.
pandocToTextile :: WriterOptions -> Pandoc -> State WriterState String
@@ -90,14 +91,14 @@ escapeCharForTextile x = case x of
escapeStringForTextile :: String -> String
escapeStringForTextile = concatMap escapeCharForTextile
--- | Convert Pandoc block element to Textile.
+-- | Convert Pandoc block element to Textile.
blockToTextile :: WriterOptions -- ^ Options
-> Block -- ^ Block element
- -> State WriterState String
+ -> State WriterState String
blockToTextile _ Null = return ""
-blockToTextile opts (Plain inlines) =
+blockToTextile opts (Plain inlines) =
inlineListToTextile opts inlines
blockToTextile opts (Para [Image txt (src,tit)]) = do
@@ -236,7 +237,7 @@ listItemToTextile opts items = do
-- | Convert definition list item (label, list of blocks) to Textile.
definitionListItemToTextile :: WriterOptions
- -> ([Inline],[[Block]])
+ -> ([Inline],[[Block]])
-> State WriterState String
definitionListItemToTextile opts (label, items) = do
labelText <- inlineListToTextile opts label
@@ -294,8 +295,8 @@ tableRowToTextile opts alignStrings rownum cols' = do
0 -> "header"
x | x `rem` 2 == 1 -> "odd"
_ -> "even"
- cols'' <- sequence $ zipWith
- (\alignment item -> tableItemToTextile opts celltype alignment item)
+ cols'' <- sequence $ zipWith
+ (\alignment item -> tableItemToTextile opts celltype alignment item)
alignStrings cols'
return $ "<tr class=\"" ++ rowclass ++ "\">\n" ++ unlines cols'' ++ "</tr>"
@@ -320,7 +321,7 @@ tableItemToTextile opts celltype align' item = do
-- | Convert list of Pandoc block elements to Textile.
blockListToTextile :: WriterOptions -- ^ Options
-> [Block] -- ^ List of block elements
- -> State WriterState String
+ -> State WriterState String
blockListToTextile opts blocks =
mapM (blockToTextile opts) blocks >>= return . vcat
@@ -332,11 +333,11 @@ inlineListToTextile opts lst =
-- | Convert Pandoc inline element to Textile.
inlineToTextile :: WriterOptions -> Inline -> State WriterState String
-inlineToTextile opts (Emph lst) = do
+inlineToTextile opts (Emph lst) = do
contents <- inlineListToTextile opts lst
return $ if '_' `elem` contents
then "<em>" ++ contents ++ "</em>"
- else "_" ++ contents ++ "_"
+ else "_" ++ contents ++ "_"
inlineToTextile opts (Strong lst) = do
contents <- inlineListToTextile opts lst
@@ -377,7 +378,7 @@ inlineToTextile opts (Cite _ lst) = inlineListToTextile opts lst
inlineToTextile _ (Code _ str) =
return $ if '@' `elem` str
then "<tt>" ++ escapeStringForXML str ++ "</tt>"
- else "@" ++ str ++ "@"
+ else "@" ++ str ++ "@"
inlineToTextile _ (Str str) = return $ escapeStringForTextile str
diff --git a/src/pandoc.hs b/src/pandoc.hs
index 2f85906d5..63a0df51a 100644
--- a/src/pandoc.hs
+++ b/src/pandoc.hs
@@ -33,7 +33,7 @@ module Main where
import Text.Pandoc
import Text.Pandoc.PDF (tex2pdf)
import Text.Pandoc.Readers.LaTeX (handleIncludes)
-import Text.Pandoc.Shared ( tabFilter, ObfuscationMethod (..), readDataFile,
+import Text.Pandoc.Shared ( tabFilter, readDataFile, safeRead,
headerShift, findDataFile, normalize, err, warn )
import Text.Pandoc.XML ( toEntities, fromEntities )
import Text.Pandoc.SelfContained ( makeSelfContained )
@@ -44,10 +44,11 @@ import System.Exit ( exitWith, ExitCode (..) )
import System.FilePath
import System.Console.GetOpt
import Data.Char ( toLower )
-import Data.List ( intercalate, isSuffixOf, isPrefixOf )
+import Data.List ( intercalate, isPrefixOf )
import System.Directory ( getAppUserDataDirectory, doesFileExist, findExecutable )
import System.IO ( stdout )
import System.IO.Error ( isDoesNotExistError )
+import qualified Control.Exception as E
import Control.Exception.Extensible ( throwIO )
import qualified Text.Pandoc.UTF8 as UTF8
import qualified Text.CSL as CSL
@@ -56,7 +57,7 @@ import Control.Monad (when, unless, liftM)
import Network.HTTP (simpleHTTP, mkRequest, getResponseBody, RequestMethod(..))
import Network.URI (parseURI, isURI, URI(..))
import qualified Data.ByteString.Lazy as B
-import Data.ByteString.Lazy.UTF8 (toString )
+import Data.ByteString.Lazy.UTF8 (toString)
import Text.CSL.Reference (Reference(..))
#if MIN_VERSION_base(4,4,0)
#else
@@ -97,8 +98,8 @@ wrapWords indent c = wrap' (c - indent) (c - indent)
then ",\n" ++ replicate indent ' ' ++ x ++ wrap' cols (cols - length x) xs
else ", " ++ x ++ wrap' cols (remaining - (length x + 2)) xs
-nonTextFormats :: [String]
-nonTextFormats = ["odt","docx","epub"]
+isTextFormat :: String -> Bool
+isTextFormat s = takeWhile (`notElem` "+-") s `notElem` ["odt","docx","epub"]
-- | Data structure for command line options.
data Opt = Opt
@@ -131,7 +132,6 @@ data Opt = Opt
, optEPUBFonts :: [FilePath] -- ^ EPUB fonts to embed
, optDumpArgs :: Bool -- ^ Output command-line arguments
, optIgnoreArgs :: Bool -- ^ Ignore command-line arguments
- , optStrict :: Bool -- ^ Use strict markdown syntax
, optReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst
, optWrapText :: Bool -- ^ Wrap text
, optColumns :: Int -- ^ Line length in characters
@@ -184,7 +184,6 @@ defaultOpts = Opt
, optEPUBFonts = []
, optDumpArgs = False
, optIgnoreArgs = False
- , optStrict = False
, optReferenceLinks = False
, optWrapText = True
, optColumns = 72
@@ -235,7 +234,10 @@ options =
, Option "" ["strict"]
(NoArg
- (\opt -> return opt { optStrict = True } ))
+ (\opt -> do
+ err 59 $ "The --strict option has been removed.\n" ++
+ "Use `markdown_strict' input or output format instead."
+ return opt ))
"" -- "Disable markdown syntax extensions"
, Option "R" ["parse-raw"]
@@ -257,13 +259,13 @@ options =
, Option "" ["base-header-level"]
(ReqArg
(\arg opt ->
- case reads arg of
- [(t,"")] | t > 0 -> do
+ case safeRead arg of
+ Just t | t > 0 -> do
let oldTransforms = optTransforms opt
let shift = t - 1
return opt{ optTransforms =
headerShift shift : oldTransforms }
- _ -> err 19
+ _ -> err 19
"base-header-level must be a number > 0")
"NUMBER")
"" -- "Headers base level"
@@ -289,9 +291,9 @@ options =
, Option "" ["tab-stop"]
(ReqArg
(\arg opt ->
- case reads arg of
- [(t,"")] | t > 0 -> return opt { optTabStop = t }
- _ -> err 31
+ case safeRead arg of
+ Just t | t > 0 -> return opt { optTabStop = t }
+ _ -> err 31
"tab-stop must be a number greater than 0")
"NUMBER")
"" -- "Tab stop (default 4)"
@@ -338,9 +340,9 @@ options =
, Option "" ["columns"]
(ReqArg
(\arg opt ->
- case reads arg of
- [(t,"")] | t > 0 -> return opt { optColumns = t }
- _ -> err 33 $
+ case safeRead arg of
+ Just t | t > 0 -> return opt { optColumns = t }
+ _ -> err 33 $
"columns must be a number greater than 0")
"NUMBER")
"" -- "Length of line in characters"
@@ -472,10 +474,10 @@ options =
, Option "" ["slide-level"]
(ReqArg
(\arg opt -> do
- case reads arg of
- [(t,"")] | t >= 1 && t <= 6 ->
+ case safeRead arg of
+ Just t | t >= 1 && t <= 6 ->
return opt { optSlideLevel = Just t }
- _ -> err 39 $
+ _ -> err 39 $
"slide level must be a number between 1 and 6")
"NUMBER")
"" -- "Force header level for slides"
@@ -690,12 +692,20 @@ options =
]
+readExtension :: String -> IO Extension
+readExtension s = case safeRead ('E':'x':'t':'_':map toLower s) of
+ Just ext -> return ext
+ Nothing -> err 59 $ "Unknown extension: " ++ s
+
-- Returns usage message
usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String
usageMessage programName = usageInfo
(programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++
- (wrapWords 16 78 $ map fst readers) ++ "\nOutput formats: " ++
- (wrapWords 16 78 $ map fst writers ++ nonTextFormats) ++ "\nOptions:")
+ (wrapWords 16 78 $ readers'names) ++ "\nOutput formats: " ++
+ (wrapWords 16 78 $ writers'names) ++ "\nOptions:")
+ where
+ writers'names = map fst writers
+ readers'names = map fst readers
-- Determine default reader based on source file extensions
defaultReaderName :: String -> [FilePath] -> String
@@ -752,6 +762,7 @@ defaultWriterName x =
".org" -> "org"
".asciidoc" -> "asciidoc"
".pdf" -> "latex"
+ ".fb2" -> "fb2"
['.',y] | y `elem` ['1'..'9'] -> "man"
_ -> "html"
@@ -771,9 +782,10 @@ main = do
["Try " ++ prg ++ " --help for more information."]
let defaultOpts' = if compatMode
- then defaultOpts { optReader = "markdown"
+ then defaultOpts { optReader = "markdown_strict"
, optWriter = "html"
- , optStrict = True }
+ , optEmailObfuscation =
+ ReferenceObfuscation }
else defaultOpts
-- thread option data structure through all supplied option actions
@@ -808,7 +820,6 @@ main = do
, optEPUBFonts = epubFonts
, optDumpArgs = dumpArgs
, optIgnoreArgs = ignoreArgs
- , optStrict = strict
, optReferenceLinks = referenceLinks
, optWrapText = wrap
, optColumns = columns
@@ -836,9 +847,10 @@ main = do
let sources = if ignoreArgs then [] else args
datadir <- case mbDataDir of
- Nothing -> catch
+ Nothing -> E.catch
(liftM Just $ getAppUserDataDirectory "pandoc")
- (const $ return Nothing)
+ (\e -> let _ = (e :: E.SomeException)
+ in return Nothing)
Just _ -> return mbDataDir
-- assign reader and writer based on options and filenames
@@ -855,8 +867,8 @@ main = do
let pdfOutput = map toLower (takeExtension outputFile) == ".pdf"
- let laTeXOutput = writerName' == "latex" || writerName' == "beamer" ||
- writerName' == "latex+lhs" || writerName' == "beamer+lhs"
+ let laTeXOutput = "latex" `isPrefixOf` writerName' ||
+ "beamer" `isPrefixOf` writerName'
when pdfOutput $ do
-- make sure writer is latex or beamer
@@ -870,11 +882,11 @@ main = do
latexEngine ++ " is needed for pdf output."
Just _ -> return ()
- reader <- case (lookup readerName' readers) of
- Just r -> return r
- Nothing -> err 7 ("Unknown reader: " ++ readerName')
+ reader <- case getReader readerName' of
+ Right r -> return r
+ Left e -> err 7 e
- let standalone' = standalone || writerName' `elem` nonTextFormats || pdfOutput
+ let standalone' = standalone || not (isTextFormat writerName') || pdfOutput
templ <- case templatePath of
_ | not standalone' -> return ""
@@ -884,26 +896,20 @@ main = do
Left e -> throwIO e
Right t -> return t
Just tp -> do
- -- strip off "+lhs" if present
- let format = takeWhile (/='+') writerName'
+ -- strip off extensions
+ let format = takeWhile (`notElem` "+-") writerName'
let tp' = case takeExtension tp of
"" -> tp <.> format
_ -> tp
- catch (UTF8.readFile tp')
+ E.catch (UTF8.readFile tp')
(\e -> if isDoesNotExistError e
- then catch
+ then E.catch
(readDataFile datadir $
"templates" </> tp')
- (\_ -> throwIO e)
+ (\e' -> let _ = (e' :: E.SomeException)
+ in throwIO e')
else throwIO e)
- let slideVariant = case writerName' of
- "s5" -> S5Slides
- "slidy" -> SlidySlides
- "slideous" -> SlideousSlides
- "dzslides" -> DZSlides
- _ -> NoSlides
-
variables' <- case mathMethod of
LaTeXMathML Nothing -> do
s <- readDataFile datadir $ "data" </> "LaTeXMathML.js"
@@ -913,20 +919,22 @@ main = do
return $ ("mathml-script", s) : variables
_ -> return variables
- variables'' <- case slideVariant of
- DZSlides -> do
+ variables'' <- if "dzslides" `isPrefixOf` writerName'
+ then do
dztempl <- readDataFile datadir $ "dzslides" </> "template.html"
let dzcore = unlines $ dropWhile (not . isPrefixOf "<!-- {{{{ dzslides core")
$ lines dztempl
return $ ("dzslides-core", dzcore) : variables'
- _ -> return variables'
+ else return variables'
-- unescape reference ids, which may contain XML entities, so
-- that we can do lookups with regular string equality
let unescapeRefId ref = ref{ refId = fromEntities (refId ref) }
- refs <- mapM (\f -> catch (CSL.readBiblioFile f) $ \e ->
- err 23 $ "Error reading bibliography `" ++ f ++ "'" ++ "\n" ++ show e)
+ refs <- mapM (\f -> E.catch (CSL.readBiblioFile f)
+ (\e -> let _ = (e :: E.SomeException)
+ in err 23 $ "Error reading bibliography `" ++ f ++
+ "'" ++ "\n" ++ show e))
reffiles >>=
return . map unescapeRefId . concat
@@ -934,62 +942,54 @@ main = do
then "."
else takeDirectory (head sources)
- let startParserState =
- defaultParserState { stateParseRaw = parseRaw,
- stateTabStop = tabStop,
- stateLiterateHaskell = "+lhs" `isSuffixOf` readerName' ||
- lhsExtension sources,
- stateStandalone = standalone',
- stateCitations = map CSL.refId refs,
- stateSmart = smart || (texLigatures &&
- (laTeXOutput || writerName' == "context")),
- stateOldDashes = oldDashes,
- stateColumns = columns,
- stateStrict = strict,
- stateIndentedCodeClasses = codeBlockClasses,
- stateApplyMacros = not laTeXOutput
- }
-
- let writerOptions = defaultWriterOptions
- { writerStandalone = standalone',
- writerTemplate = templ,
- writerVariables = variables'',
- writerEPUBMetadata = epubMetadata,
- writerTabStop = tabStop,
- writerTableOfContents = toc &&
- writerName' /= "s5",
- writerHTMLMathMethod = mathMethod,
- writerSlideVariant = slideVariant,
- writerIncremental = incremental,
- writerCiteMethod = citeMethod,
- writerBiblioFiles = reffiles,
- writerIgnoreNotes = False,
- writerNumberSections = numberSections,
- writerSectionDivs = sectionDivs,
- writerStrictMarkdown = strict,
- writerReferenceLinks = referenceLinks,
- writerWrapText = wrap,
- writerColumns = columns,
- writerLiterateHaskell = False,
- writerEmailObfuscation = if strict
- then ReferenceObfuscation
- else obfuscationMethod,
- writerIdentifierPrefix = idPrefix,
- writerSourceDirectory = sourceDir,
- writerUserDataDir = datadir,
- writerHtml5 = html5 ||
- slideVariant == DZSlides,
- writerChapters = chapters,
- writerListings = listings,
- writerBeamer = False,
- writerSlideLevel = slideLevel,
- writerHighlight = highlight,
- writerHighlightStyle = highlightStyle,
- writerSetextHeaders = setextHeaders,
- writerTeXLigatures = texLigatures
- }
-
- when (writerName' `elem` nonTextFormats&& outputFile == "-") $
+ let readerOpts = def{ readerSmart = smart || (texLigatures &&
+ (laTeXOutput || "context" `isPrefixOf` writerName'))
+ , readerStandalone = standalone'
+ , readerParseRaw = parseRaw
+ , readerColumns = columns
+ , readerTabStop = tabStop
+ , readerOldDashes = oldDashes
+ , readerCitations = map CSL.refId refs
+ , readerIndentedCodeClasses = codeBlockClasses
+ , readerApplyMacros = not laTeXOutput
+ }
+
+ let writerOptions = def { writerStandalone = standalone',
+ writerTemplate = templ,
+ writerVariables = variables'',
+ writerEPUBMetadata = epubMetadata,
+ writerTabStop = tabStop,
+ writerTableOfContents = toc,
+ writerHTMLMathMethod = mathMethod,
+ writerIncremental = incremental,
+ writerCiteMethod = citeMethod,
+ writerBiblioFiles = reffiles,
+ writerIgnoreNotes = False,
+ writerNumberSections = numberSections,
+ writerSectionDivs = sectionDivs,
+ writerReferenceLinks = referenceLinks,
+ writerWrapText = wrap,
+ writerColumns = columns,
+ writerEmailObfuscation = obfuscationMethod,
+ writerIdentifierPrefix = idPrefix,
+ writerSourceDirectory = sourceDir,
+ writerUserDataDir = datadir,
+ writerHtml5 = html5,
+ writerChapters = chapters,
+ writerListings = listings,
+ writerBeamer = False,
+ writerSlideLevel = slideLevel,
+ writerHighlight = highlight,
+ writerHighlightStyle = highlightStyle,
+ writerSetextHeaders = setextHeaders,
+ writerTeXLigatures = texLigatures,
+ writerEpubStylesheet = epubStylesheet,
+ writerEpubFonts = epubFonts,
+ writerReferenceODT = referenceODT,
+ writerReferenceDocx = referenceDocx
+ }
+
+ when (not (isTextFormat writerName') && outputFile == "-") $
err 5 $ "Cannot write " ++ writerName' ++ " output to stdout.\n" ++
"Specify an output file using the -o option."
@@ -1009,12 +1009,12 @@ main = do
then handleIncludes
else return
- doc <- (reader startParserState) `fmap` (readSources sources >>=
+ doc <- (reader readerOpts) `fmap` (readSources sources >>=
handleIncludes' . convertTabs . intercalate "\n")
let doc0 = foldr ($) doc transforms
- doc1 <- if writerName' == "rtf"
+ doc1 <- if "rtf" `isPrefixOf` writerName'
then bottomUpM rtfEmbedImage doc0
else return doc0
@@ -1042,31 +1042,25 @@ main = do
writerFn "-" = UTF8.putStr
writerFn f = UTF8.writeFile f
- case lookup writerName' writers of
- Nothing
- | writerName' == "epub" ->
- writeEPUB epubStylesheet epubFonts writerOptions doc2
- >>= writeBinary
- | writerName' == "odt" ->
- writeODT referenceODT writerOptions doc2 >>= writeBinary
- | writerName' == "docx" ->
- writeDocx referenceDocx writerOptions doc2 >>= writeBinary
- | otherwise -> err 9 ("Unknown writer: " ++ writerName')
- Just w
- | pdfOutput -> do
- res <- tex2pdf latexEngine $ w writerOptions doc2
+ case getWriter writerName' of
+ Left e -> err 9 e
+ Right (IOStringWriter f) -> f writerOptions doc2 >>= writerFn outputFile
+ Right (IOByteStringWriter f) -> f writerOptions doc2 >>= writeBinary
+ Right (PureStringWriter f)
+ | pdfOutput -> do
+ res <- tex2pdf latexEngine $ f writerOptions doc2
case res of
Right pdf -> writeBinary pdf
Left err' -> err 43 $ toString err'
- Just w
- | htmlFormat && ascii ->
- writerFn outputFile =<< selfcontain (toEntities result)
- | otherwise ->
- writerFn outputFile =<< selfcontain result
- where result = w writerOptions doc2 ++ ['\n' | not standalone']
- htmlFormat = writerName' `elem`
+ | otherwise -> selfcontain (f writerOptions doc2 ++
+ ['\n' | not standalone'])
+ >>= writerFn outputFile . handleEntities
+ where htmlFormat = writerName' `elem`
["html","html+lhs","html5","html5+lhs",
"s5","slidy","slideous","dzslides"]
selfcontain = if selfContained && htmlFormat
then makeSelfContained datadir
else return
+ handleEntities = if htmlFormat && ascii
+ then toEntities
+ else id
diff --git a/stats.sh b/stats.sh
deleted file mode 100755
index 3bb168e89..000000000
--- a/stats.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-# Generates statistics on pandoc: benchmarks and lines of code
-# The stats are put in the stats directory, marked with date and revision hash.
-
-STATSDIR=stats
-mkdir $STATSDIR
-
-DATE=`date +%Y_%m_%d`
-REV=`git rev-parse --short HEAD`
-
-EXT=$DATE.$REV
-BENCH=$STATSDIR/benchmark.$EXT
-LOC=$STATSDIR/loc.$EXT
-SUMMARY=$STATSDIR/summary.$EXT
-
-runghc Benchmark.hs > $BENCH
-find src -name '*.hs' | xargs wc -l > $LOC
-
-LOCSUM=`tail -1 $LOC | sed -Ee 's/^ *([0-9]+).*/\1/'`
-
-echo "Revision $REV" > $SUMMARY
-echo `date` >> $SUMMARY
-echo "$LOCSUM lines of code" >> $SUMMARY
-echo "" >> $SUMMARY
-
-sed -nEe '/^(benchmarking|mean:)/p' $BENCH | \
- sed -Ee '/benchmarking/N;s/\n/: /' | \
- sed -Ee 's/benchmarking (.*)/\1/' | \
- sed -Ee 's/mean: ([^ ]*) *([^,]*).*/\1:\2/' | \
- awk 'BEGIN { FS = ": *" } ; { printf("%s:%7.2f %s\n", $1, $2, $3); }' | \
- column -t -s ":" >> $SUMMARY
-
diff --git a/templates b/templates
-Subproject 4b27abf40461c7421c3a14cd5547a9018eb1acc
+Subproject c08ed3f61a5dda0a33cda08106140be5a5cd6da
diff --git a/src/Tests/Arbitrary.hs b/tests/Tests/Arbitrary.hs
index 9d65e1f1f..9d65e1f1f 100644
--- a/src/Tests/Arbitrary.hs
+++ b/tests/Tests/Arbitrary.hs
diff --git a/src/Tests/Helpers.hs b/tests/Tests/Helpers.hs
index 66879efed..86a92fb0c 100644
--- a/src/Tests/Helpers.hs
+++ b/tests/Tests/Helpers.hs
@@ -17,8 +17,8 @@ import Test.Framework
import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2
import Test.HUnit (assertBool)
-import Text.Pandoc.Shared (normalize, defaultWriterOptions,
- WriterOptions(..), removeTrailingSpace)
+import Text.Pandoc.Shared (normalize, removeTrailingSpace)
+import Text.Pandoc.Options
import Text.Pandoc.Writers.Native (writeNative)
import Language.Haskell.TH.Quote (QuasiQuoter(..))
import Language.Haskell.TH.Syntax (Q, runIO)
@@ -85,18 +85,16 @@ class ToString a where
toString :: a -> String
instance ToString Pandoc where
- toString d = writeNative defaultWriterOptions{ writerStandalone = s }
- $ toPandoc d
+ toString d = writeNative def{ writerStandalone = s } $ toPandoc d
where s = case d of
(Pandoc (Meta [] [] []) _) -> False
_ -> True
instance ToString Blocks where
- toString = writeNative defaultWriterOptions . toPandoc
+ toString = writeNative def . toPandoc
instance ToString Inlines where
- toString = removeTrailingSpace . writeNative defaultWriterOptions .
- toPandoc
+ toString = removeTrailingSpace . writeNative def . toPandoc
instance ToString String where
toString = id
diff --git a/src/Tests/Old.hs b/tests/Tests/Old.hs
index 67eb51573..8899fef6f 100644
--- a/src/Tests/Old.hs
+++ b/tests/Tests/Old.hs
@@ -10,7 +10,8 @@ import System.FilePath ( (</>), (<.>) )
import System.Directory
import System.Exit
import Data.Algorithm.Diff
-import Text.Pandoc.Shared ( normalize, defaultWriterOptions )
+import Text.Pandoc.Shared ( normalize )
+import Text.Pandoc.Options
import Text.Pandoc.Writers.Native ( writeNative )
import Text.Pandoc.Readers.Native ( readNative )
import Prelude hiding ( readFile )
@@ -56,6 +57,8 @@ tests = [ testGroup "markdown"
"testsuite.txt" "testsuite.native"
, test "tables" ["-r", "markdown", "-w", "native", "--columns=80"]
"tables.txt" "tables.native"
+ , test "pipe tables" ["-r", "markdown", "-w", "native", "--columns=80"]
+ "pipe-tables.txt" "pipe-tables.native"
, test "more" ["-r", "markdown", "-w", "native", "-S"]
"markdown-reader-more.txt" "markdown-reader-more.native"
, lhsReaderTest "markdown+lhs"
@@ -107,6 +110,15 @@ tests = [ testGroup "markdown"
, test "reader" ["-r", "native", "-w", "native", "-s"]
"testsuite.native" "testsuite.native"
]
+ , testGroup "fb2"
+ [ fb2WriterTest "basic" [] "fb2.basic.markdown" "fb2.basic.fb2"
+ , fb2WriterTest "titles" [] "fb2.titles.markdown" "fb2.titles.fb2"
+ , fb2WriterTest "images" [] "fb2.images.markdown" "fb2.images.fb2"
+ , fb2WriterTest "images-embedded" [] "fb2.images-embedded.html" "fb2.images-embedded.fb2"
+ , fb2WriterTest "tables" [] "tables.native" "tables.fb2"
+ , fb2WriterTest "math" [] "fb2.math.markdown" "fb2.math.fb2"
+ , fb2WriterTest "testsuite" [] "testsuite.native" "writer.fb2"
+ ]
, testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
[ "opendocument" , "context" , "texinfo"
, "man" , "plain" , "mediawiki", "rtf", "org", "asciidoc"
@@ -131,7 +143,7 @@ lhsReaderTest :: String -> Test
lhsReaderTest format =
testWithNormalize normalizer "lhs" ["-r", format, "-w", "native"]
("lhs-test" <.> format) "lhs-test.native"
- where normalizer = writeNative defaultWriterOptions . normalize . readNative
+ where normalizer = writeNative def . normalize . readNative
writerTests :: String -> [Test]
writerTests format
@@ -142,14 +154,27 @@ writerTests format
opts = ["-r", "native", "-w", format, "--columns=78"]
s5WriterTest :: String -> [String] -> String -> Test
-s5WriterTest modifier opts format
+s5WriterTest modifier opts format
= test (format ++ " writer (" ++ modifier ++ ")")
- (["-r", "native", "-w", format] ++ opts)
+ (["-r", "native", "-w", format] ++ opts)
"s5.native" ("s5." ++ modifier <.> "html")
+fb2WriterTest :: String -> [String] -> String -> String -> Test
+fb2WriterTest title opts inputfile normfile =
+ testWithNormalize (ignoreBinary . formatXML)
+ title (["-t", "fb2"]++opts) inputfile normfile
+ where
+ formatXML xml = splitTags $ zip xml (drop 1 xml)
+ splitTags [] = []
+ splitTags [end] = fst end : snd end : []
+ splitTags (('>','<'):rest) = ">\n" ++ splitTags rest
+ splitTags ((c,_):rest) = c : splitTags rest
+ ignoreBinary = unlines . filter (not . startsWith "<binary ") . lines
+ startsWith tag str = all (uncurry (==)) $ zip tag str
+
markdownCitationTests :: [Test]
markdownCitationTests
- = map styleToTest ["chicago-author-date","ieee","mhra"]
+ = map styleToTest ["chicago-author-date","ieee","mhra"]
++ [test "natbib" wopts "markdown-citations.txt"
"markdown-citations.txt"]
where
diff --git a/src/Tests/Readers/LaTeX.hs b/tests/Tests/Readers/LaTeX.hs
index d60026b20..febc91765 100644
--- a/src/Tests/Readers/LaTeX.hs
+++ b/tests/Tests/Readers/LaTeX.hs
@@ -9,7 +9,7 @@ import Text.Pandoc.Builder
import Text.Pandoc
latex :: String -> Pandoc
-latex = readLaTeX defaultParserState
+latex = readLaTeX def
infix 4 =:
(=:) :: ToString c
diff --git a/src/Tests/Readers/Markdown.hs b/tests/Tests/Readers/Markdown.hs
index 5ad974adf..8d0b567e9 100644
--- a/src/Tests/Readers/Markdown.hs
+++ b/tests/Tests/Readers/Markdown.hs
@@ -6,14 +6,15 @@ import Test.Framework
import Tests.Helpers
import Tests.Arbitrary()
import Text.Pandoc.Builder
+import qualified Data.Set as Set
-- import Text.Pandoc.Shared ( normalize )
import Text.Pandoc
markdown :: String -> Pandoc
-markdown = readMarkdown defaultParserState{ stateStandalone = True }
+markdown = readMarkdown def
markdownSmart :: String -> Pandoc
-markdownSmart = readMarkdown defaultParserState{ stateSmart = True }
+markdownSmart = readMarkdown def { readerSmart = True }
infix 4 =:
(=:) :: ToString c
@@ -25,8 +26,8 @@ p_markdown_round_trip :: Block -> Bool
p_markdown_round_trip b = matches d' d''
where d' = normalize $ Pandoc (Meta [] [] []) [b]
d'' = normalize
- $ readMarkdown defaultParserState{ stateSmart = True }
- $ writeMarkdown defaultWriterOptions d'
+ $ readMarkdown def { readerSmart = True }
+ $ writeMarkdown def d'
matches (Pandoc _ [Plain []]) (Pandoc _ []) = True
matches (Pandoc _ [Para []]) (Pandoc _ []) = True
matches (Pandoc _ [Plain xs]) (Pandoc _ [Para xs']) = xs == xs'
@@ -91,7 +92,8 @@ tests = [ testGroup "inline code"
=?> para (note (para "See [^1]"))
]
, testGroup "lhs"
- [ test (readMarkdown defaultParserState{stateLiterateHaskell = True})
+ [ test (readMarkdown def{ readerExtensions = Set.insert
+ Ext_literate_haskell $ readerExtensions def })
"inverse bird tracks and html" $
"> a\n\n< b\n\n<div>\n"
=?> codeBlockWith ("",["sourceCode","literate","haskell"],[]) "a"
diff --git a/src/Tests/Readers/RST.hs b/tests/Tests/Readers/RST.hs
index 3269092a6..fdce7c8f6 100644
--- a/src/Tests/Readers/RST.hs
+++ b/tests/Tests/Readers/RST.hs
@@ -9,7 +9,7 @@ import Text.Pandoc.Builder
import Text.Pandoc
rst :: String -> Pandoc
-rst = readRST defaultParserState{ stateStandalone = True }
+rst = readRST def
infix 4 =:
(=:) :: ToString c
diff --git a/src/Tests/Shared.hs b/tests/Tests/Shared.hs
index f4bf13da4..f4bf13da4 100644
--- a/src/Tests/Shared.hs
+++ b/tests/Tests/Shared.hs
diff --git a/src/Tests/Writers/ConTeXt.hs b/tests/Tests/Writers/ConTeXt.hs
index beb6411f0..2cb8ececa 100644
--- a/src/Tests/Writers/ConTeXt.hs
+++ b/tests/Tests/Writers/ConTeXt.hs
@@ -8,11 +8,10 @@ import Tests.Helpers
import Tests.Arbitrary()
context :: (ToString a, ToPandoc a) => a -> String
-context = writeConTeXt defaultWriterOptions . toPandoc
+context = writeConTeXt def . toPandoc
context' :: (ToString a, ToPandoc a) => a -> String
-context' = writeConTeXt defaultWriterOptions{ writerWrapText = False }
- . toPandoc
+context' = writeConTeXt def{ writerWrapText = False } . toPandoc
{-
"my test" =: X =?> Y
diff --git a/src/Tests/Writers/HTML.hs b/tests/Tests/Writers/HTML.hs
index 8561aa421..5d6e301c5 100644
--- a/src/Tests/Writers/HTML.hs
+++ b/tests/Tests/Writers/HTML.hs
@@ -9,7 +9,7 @@ import Tests.Arbitrary()
import Text.Pandoc.Highlighting (languages) -- null if no hl support
html :: (ToString a, ToPandoc a) => a -> String
-html = writeHtmlString defaultWriterOptions{ writerWrapText = False } . toPandoc
+html = writeHtmlString def{ writerWrapText = False } . toPandoc
{-
"my test" =: X =?> Y
diff --git a/src/Tests/Writers/LaTeX.hs b/tests/Tests/Writers/LaTeX.hs
index 7987716f3..16e0c3f23 100644
--- a/src/Tests/Writers/LaTeX.hs
+++ b/tests/Tests/Writers/LaTeX.hs
@@ -8,7 +8,7 @@ import Tests.Helpers
import Tests.Arbitrary()
latex :: (ToString a, ToPandoc a) => a -> String
-latex = writeLaTeX defaultWriterOptions . toPandoc
+latex = writeLaTeX def . toPandoc
{-
"my test" =: X =?> Y
diff --git a/src/Tests/Writers/Markdown.hs b/tests/Tests/Writers/Markdown.hs
index d90dc83b1..22ce8b27c 100644
--- a/src/Tests/Writers/Markdown.hs
+++ b/tests/Tests/Writers/Markdown.hs
@@ -8,7 +8,7 @@ import Tests.Helpers
import Tests.Arbitrary()
markdown :: (ToString a, ToPandoc a) => a -> String
-markdown = writeMarkdown defaultWriterOptions . toPandoc
+markdown = writeMarkdown def . toPandoc
{-
"my test" =: X =?> Y
diff --git a/src/Tests/Writers/Native.hs b/tests/Tests/Writers/Native.hs
index 19740e0f4..e199cf94e 100644
--- a/src/Tests/Writers/Native.hs
+++ b/tests/Tests/Writers/Native.hs
@@ -8,11 +8,11 @@ import Tests.Arbitrary()
p_write_rt :: Pandoc -> Bool
p_write_rt d =
- read (writeNative defaultWriterOptions{ writerStandalone = True } d) == d
+ read (writeNative def{ writerStandalone = True } d) == d
p_write_blocks_rt :: [Block] -> Bool
p_write_blocks_rt bs = length bs > 20 ||
- read (writeNative defaultWriterOptions (Pandoc (Meta [] [] []) bs)) ==
+ read (writeNative def (Pandoc (Meta [] [] []) bs)) ==
bs
tests :: [Test]
diff --git a/tests/fb2.basic.fb2 b/tests/fb2.basic.fb2
new file mode 100644
index 000000000..14b03fbea
--- /dev/null
+++ b/tests/fb2.basic.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><title><p>Top-level title</p></title><section><title><p>Section</p></title><section><title><p>Subsection</p></title><p>This <emphasis>emphasized</emphasis> <strong>strong</strong> <code>verbatim</code> markdown. See this link<a l:href="#l1" type="note"><sup>[1]</sup></a>.</p><p>Ordered list:</p><p> 1. one</p><p> 2. two</p><p> 3. three</p><cite><p>Blockquote is for citatons.</p></cite><empty-line /><p><code>Code</code></p><p><code>block</code></p><p><code>is</code></p><p><code>for</code></p><p><code>code.</code></p><empty-line /><p><strikethrough>Strikeout</strikethrough> is Pandoc&#39;s extension. Superscript and subscripts too: H<sub>2</sub>O is a liquid<a l:href="#n2" type="note"><sup>[2]</sup></a>. 2<sup>10</sup> is 1024.</p><p>Math is another Pandoc extension: <code>E = m c^2</code>.</p></section></section></section></body><body name="notes"><section id="l1"><title><p>1</p></title><p><code>http://example.com/</code></p></section><section id="n2"><title><p>2</p></title><p>Sometimes.</p></section></body></FictionBook> \ No newline at end of file
diff --git a/tests/fb2.basic.markdown b/tests/fb2.basic.markdown
new file mode 100644
index 000000000..b798b13a4
--- /dev/null
+++ b/tests/fb2.basic.markdown
@@ -0,0 +1,33 @@
+# Top-level title
+
+## Section
+
+### Subsection
+
+This *emphasized* **strong** `verbatim` markdown.
+See this [link](http://example.com/).
+
+Ordered list:
+
+ 1. one
+ 1. two
+ 1. three
+
+> Blockquote
+> is
+> for
+> citatons.
+
+ Code
+ block
+ is
+ for
+ code.
+
+~~Strikeout~~ is Pandoc's extension.
+Superscript and subscripts too: H~2~O is a liquid[^1].
+2^10^ is 1024.
+
+Math is another Pandoc extension: $E = m c^2$.
+
+[^1]: Sometimes.
diff --git a/tests/fb2.images-embedded.fb2 b/tests/fb2.images-embedded.fb2
new file mode 100644
index 000000000..373eda7ff
--- /dev/null
+++ b/tests/fb2.images-embedded.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><image l:href="#image1" l:type="imageType" alt="This image was embedded using data URI scheme" /><p>This image was embedded using data URI scheme</p></section></body><binary id="image1" content-type="image/png">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</binary></FictionBook> \ No newline at end of file
diff --git a/tests/fb2.images-embedded.html b/tests/fb2.images-embedded.html
new file mode 100644
index 000000000..19c8f7c7a
--- /dev/null
+++ b/tests/fb2.images-embedded.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+ <meta name="generator" content="pandoc" />
+ <title></title>
+</head>
+<body>
+<div class="figure">
+<img src="data:image/png;base64,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" alt="This image was embedded using data URI scheme" /><p class="caption">This image was embedded using data URI scheme</p>
+</div>
+</body>
+</html>
diff --git a/tests/fb2.images.fb2 b/tests/fb2.images.fb2
new file mode 100644
index 000000000..8b783edf5
--- /dev/null
+++ b/tests/fb2.images.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><p>This example test if Pandoc correctly embeds images into FictionBook.</p><p>Small inline image: <image l:href="#image1" l:type="inlineImageType" alt="alt text a small PNG image" />.</p><p>Paragraph image:</p><image l:href="#image2" l:type="imageType" alt="alt text of a big JPEG image" title="image title text" /><p>alt text of a big missing image</p><p>A missing image inline: alt text of missing image.</p></section></body><binary id="image2" content-type="image/jpeg">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</binary><binary id="image1" content-type="image/png">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</binary></FictionBook> \ No newline at end of file
diff --git a/tests/fb2.images.markdown b/tests/fb2.images.markdown
new file mode 100644
index 000000000..419be7c44
--- /dev/null
+++ b/tests/fb2.images.markdown
@@ -0,0 +1,13 @@
+This example test if Pandoc correctly embeds images into FictionBook.
+
+Small inline image: ![alt text a small PNG image][inline-image].
+
+Paragraph image:
+
+![alt text of a big JPEG image](fb2.test.jpg "image title text")
+
+![alt text of a big missing image](missing.jpg)
+
+A missing image inline: ![alt text of missing image](missing.jpg).
+
+[inline-image]: fb2.test-small.png
diff --git a/tests/fb2.math.fb2 b/tests/fb2.math.fb2
new file mode 100644
index 000000000..5a69556c1
--- /dev/null
+++ b/tests/fb2.math.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><p>List math:</p><p>• <code>E = m c^2</code></p><p>• <code>A = \pi r^2</code></p><p>Inline math: <code>x=\frac{-b \pm \sqrt {b^2-4ac}}{2a}</code>.</p><p>Display math:</p><code>\int_a^b \! f(x)\,dx = F(b) - F(a).</code></section></body></FictionBook> \ No newline at end of file
diff --git a/tests/fb2.math.markdown b/tests/fb2.math.markdown
new file mode 100644
index 000000000..a88fb6cf1
--- /dev/null
+++ b/tests/fb2.math.markdown
@@ -0,0 +1,10 @@
+List math:
+
+- $E = m c^2$
+- $A = \pi r^2$
+
+Inline math: $x=\frac{-b \pm \sqrt {b^2-4ac}}{2a}$.
+
+Display math:
+
+$$\int_a^b \! f(x)\,dx = F(b) - F(a).$$
diff --git a/tests/fb2.test-small.png b/tests/fb2.test-small.png
new file mode 100644
index 000000000..16e177219
--- /dev/null
+++ b/tests/fb2.test-small.png
Binary files differ
diff --git a/tests/fb2.test.jpg b/tests/fb2.test.jpg
new file mode 100644
index 000000000..99d57db17
--- /dev/null
+++ b/tests/fb2.test.jpg
Binary files differ
diff --git a/tests/fb2.titles.fb2 b/tests/fb2.titles.fb2
new file mode 100644
index 000000000..d8fc1e424
--- /dev/null
+++ b/tests/fb2.titles.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><title><p>Simple title</p></title><p>This example tests if Pandoc doesn&#39;t insert forbidden elements in FictionBook titles.</p></section><section><title><p>Emphasized Strong Title</p></title></section><section><title><p>Title with</p><empty-line /><p>line break</p></title></section></body></FictionBook> \ No newline at end of file
diff --git a/tests/fb2.titles.markdown b/tests/fb2.titles.markdown
new file mode 100644
index 000000000..cc3d0e0d0
--- /dev/null
+++ b/tests/fb2.titles.markdown
@@ -0,0 +1,10 @@
+# Simple title
+
+This example tests if Pandoc doesn't insert forbidden elements in FictionBook titles.
+
+# *Emphasized* **Strong** Title
+
+# Title with\
+line break
+
+
diff --git a/tests/lhs-test.native b/tests/lhs-test.native
index 4b5a3e112..5b8e908de 100644
--- a/tests/lhs-test.native
+++ b/tests/lhs-test.native
@@ -1,8 +1,8 @@
[Header 1 [Str "lhs",Space,Str "test"]
-,Para [Code ("",[],[]) "unsplit",Space,Str "is",Space,Str "an",Space,Str "arrow",Space,Str "that",Space,Str "takes",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "and",Space,Str "combines",Space,Str "them",Space,Str "to",Space,Str "return",Space,Str "a",Space,Str "single",Space,Str "value",Str ":"]
+,Para [Code ("",[],[]) "unsplit",Space,Str "is",Space,Str "an",Space,Str "arrow",Space,Str "that",Space,Str "takes",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "and",Space,Str "combines",Space,Str "them",Space,Str "to",Space,Str "return",Space,Str "a",Space,Str "single",Space,Str "value:"]
,CodeBlock ("",["sourceCode","literate","haskell"],[]) "unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d\nunsplit = arr . uncurry \n -- arr (\\op (x,y) -> x `op` y) "
-,Para [Code ("",[],[]) "(***)",Space,Str "combines",Space,Str "two",Space,Str "arrows",Space,Str "into",Space,Str "a",Space,Str "new",Space,Str "arrow",Space,Str "by",Space,Str "running",Space,Str "the",Space,Str "two",Space,Str "arrows",Space,Str "on",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "(one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "first",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair",Space,Str "and",Space,Str "one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "second",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair)",Str "."]
+,Para [Code ("",[],[]) "(***)",Space,Str "combines",Space,Str "two",Space,Str "arrows",Space,Str "into",Space,Str "a",Space,Str "new",Space,Str "arrow",Space,Str "by",Space,Str "running",Space,Str "the",Space,Str "two",Space,Str "arrows",Space,Str "on",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "(one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "first",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair",Space,Str "and",Space,Str "one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "second",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair)."]
,CodeBlock ("",[],[]) "f *** g = first f >>> second g"
-,Para [Str "Block",Space,Str "quote",Str ":"]
+,Para [Str "Block",Space,Str "quote:"]
,BlockQuote
[Para [Str "foo",Space,Str "bar"]]]
diff --git a/tests/markdown-reader-more.native b/tests/markdown-reader-more.native
index a24e48e86..56cf60c82 100644
--- a/tests/markdown-reader-more.native
+++ b/tests/markdown-reader-more.native
@@ -12,11 +12,11 @@
,HorizontalRule
,HorizontalRule
,Header 2 [Str "Raw",Space,Str "HTML",Space,Str "before",Space,Str "header"]
-,Plain [RawInline "html" "<a>",RawInline "html" "</a>"]
+,Para [RawInline "html" "<a>",RawInline "html" "</a>"]
,Header 3 [Str "my",Space,Str "header"]
,Header 2 [Str "$",Space,Str "in",Space,Str "math"]
,Para [Math InlineMath "\\$2 + \\$3"]
-,Header 2 [Str "Commented",Str "-",Str "out",Space,Str "list",Space,Str "item"]
+,Header 2 [Str "Commented-out",Space,Str "list",Space,Str "item"]
,BulletList
[[Plain [Str "one",Space,RawInline "html" "<!--\n- two\n-->"]]
,[Plain [Str "three"]]]
@@ -26,22 +26,22 @@
,Para [Code ("",[],[]) "hi\\"]
,Para [Code ("",[],[]) "hi there"]
,Para [Code ("",[],[]) "hi````there"]
-,Para [Str "`",Str "hi"]
-,Para [Str "there",Str "`"]
+,Para [Str "`hi"]
+,Para [Str "there`"]
,Header 2 [Str "Multilingual",Space,Str "URLs"]
-,Plain [RawInline "html" "<http://\27979.com?\27979=\27979>"]
+,Para [RawInline "html" "<http://\27979.com?\27979=\27979>"]
,Para [Link [Str "foo"] ("/bar/\27979?x=\27979","title")]
,Para [Link [Code ("",["url"],[]) "\27979@foo.\27979.baz"] ("mailto:\27979@foo.\27979.baz","")]
,Header 2 [Str "Numbered",Space,Str "examples"]
,OrderedList (1,Example,TwoParens)
- [[Plain [Str "First",Space,Str "example",Str "."]]
- ,[Plain [Str "Second",Space,Str "example",Str "."]]]
-,Para [Str "Explanation",Space,Str "of",Space,Str "examples",Space,Str "(",Str "2",Str ")",Space,Str "and",Space,Str "(",Str "3",Str ")",Str "."]
+ [[Plain [Str "First",Space,Str "example."]]
+ ,[Plain [Str "Second",Space,Str "example."]]]
+,Para [Str "Explanation",Space,Str "of",Space,Str "examples",Space,Str "(2)",Space,Str "and",Space,Str "(3)."]
,OrderedList (3,Example,TwoParens)
- [[Plain [Str "Third",Space,Str "example",Str "."]]]
+ [[Plain [Str "Third",Space,Str "example."]]]
,Header 2 [Str "Macros"]
,Para [Math InlineMath "\\langle x,y \\rangle"]
-,Header 2 [Str "Case",Str "-",Str "insensitive",Space,Str "references"]
+,Header 2 [Str "Case-insensitive",Space,Str "references"]
,Para [Link [Str "Fum"] ("/fum","")]
,Para [Link [Str "FUM"] ("/fum","")]
,Para [Link [Str "bat"] ("/bat","")]
diff --git a/tests/pipe-tables.native b/tests/pipe-tables.native
new file mode 100644
index 000000000..5420a7bd3
--- /dev/null
+++ b/tests/pipe-tables.native
@@ -0,0 +1,70 @@
+[Para [Str "Simplest",Space,Str "table",Space,Str "without",Space,Str "caption:"]
+,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
+ [[Plain [Str "Default1"]]
+ ,[Plain [Str "Default2"]]
+ ,[Plain [Str "Default3"]]]
+ [[[Plain [Str "12"]]
+ ,[Plain [Str "12"]]
+ ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+ ,[Plain [Str "123"]]
+ ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+ ,[Plain [Str "1"]]
+ ,[Plain [Str "1"]]]]
+,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."] [AlignRight,AlignLeft,AlignDefault,AlignCenter] [0.0,0.0,0.0,0.0]
+ [[Plain [Str "Right"]]
+ ,[Plain [Str "Left"]]
+ ,[Plain [Str "Default"]]
+ ,[Plain [Str "Center"]]]
+ [[[Plain [Str "12"]]
+ ,[Plain [Str "12"]]
+ ,[Plain [Str "12"]]
+ ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+ ,[Plain [Str "123"]]
+ ,[Plain [Str "123"]]
+ ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+ ,[Plain [Str "1"]]
+ ,[Plain [Str "1"]]
+ ,[Plain [Str "1"]]]]
+,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
+,Table [] [AlignRight,AlignLeft,AlignCenter] [0.0,0.0,0.0]
+ [[Plain [Str "Right"]]
+ ,[Plain [Str "Left"]]
+ ,[Plain [Str "Center"]]]
+ [[[Plain [Str "12"]]
+ ,[Plain [Str "12"]]
+ ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+ ,[Plain [Str "123"]]
+ ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+ ,[Plain [Str "1"]]
+ ,[Plain [Str "1"]]]]
+,Para [Str "Headerless",Space,Str "table",Space,Str "without",Space,Str "caption:"]
+,Table [] [AlignRight,AlignLeft,AlignCenter] [0.0,0.0,0.0]
+ [[]
+ ,[]
+ ,[]]
+ [[[Plain [Str "12"]]
+ ,[Plain [Str "12"]]
+ ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+ ,[Plain [Str "123"]]
+ ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+ ,[Plain [Str "1"]]
+ ,[Plain [Str "1"]]]]
+,Para [Str "Table",Space,Str "without",Space,Str "sides:"]
+,Table [] [AlignDefault,AlignRight] [0.0,0.0]
+ [[Plain [Str "Fruit"]]
+ ,[Plain [Str "Quantity"]]]
+ [[[Plain [Str "apple"]]
+ ,[Plain [Str "5"]]]
+ ,[[Plain [Str "orange"]]
+ ,[Plain [Str "17"]]]
+ ,[[Plain [Str "pear"]]
+ ,[Plain [Str "302"]]]]]
diff --git a/tests/pipe-tables.txt b/tests/pipe-tables.txt
new file mode 100644
index 000000000..929038ebb
--- /dev/null
+++ b/tests/pipe-tables.txt
@@ -0,0 +1,42 @@
+Simplest table without caption:
+
+| Default1 | Default2 | Default3 |
+|----------|----------|----------|
+|12|12|12|
+|123|123|123|
+|1|1|1|
+
+Simple table with caption:
+
+| Right | Left | Default | Center |
+|------:|:-----|---------|:------:|
+| 12 | 12 | 12 | 12 |
+| 123 | 123 | 123 | 123 |
+| 1 | 1 | 1 | 1 |
+
+ : Demonstration of simple table syntax.
+
+Simple table without caption:
+
+| Right | Left | Center |
+|------:|:-----|:------:|
+|12|12|12|
+|123|123|123|
+|1|1|1|
+
+
+Headerless table without caption:
+
+|------:|:-----|:------:|
+|12|12|12|
+|123|123|123|
+|1|1|1|
+
+Table without sides:
+
+Fruit |Quantity
+------|-------:
+apple | 5
+orange| 17
+pear | 302
+
diff --git a/tests/rst-reader.native b/tests/rst-reader.native
index bf794c849..c99e73f07 100644
--- a/tests/rst-reader.native
+++ b/tests/rst-reader.native
@@ -320,4 +320,6 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite",Str ":
,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",Str "-",Str "role",Space,Str "to",Space,Str "the",Space,Str "default",Space,Str "default",Str "."]
-,Para [Str "And",Space,Str "now",Space,Str "`",Str "some",Str "-",Str "invalid",Str "-",Str "string",Str "-",Str "3231231",Str "`",Space,Str "is",Space,Str "nonsense",Str "."]]
+,Para [Str "And",Space,Str "now",Space,Str "`",Str "some",Str "-",Str "invalid",Str "-",Str "string",Str "-",Str "3231231",Str "`",Space,Str "is",Space,Str "nonsense",Str "."]
+,Header 2 [Str "Literal",Space,Str "symbols"]
+,Para [Str "2",Str "*",Str "2",Space,Str "=",Space,Str "4",Str "*",Str "1"]]
diff --git a/tests/rst-reader.rst b/tests/rst-reader.rst
index abe6d4f69..4d81ccb85 100644
--- a/tests/rst-reader.rst
+++ b/tests/rst-reader.rst
@@ -593,3 +593,7 @@ Reset default-role to the default default.
And now `some-invalid-string-3231231` is nonsense.
+Literal symbols
+---------------
+
+2*2 = 4*1
diff --git a/tests/tables.fb2 b/tests/tables.fb2
new file mode 100644
index 000000000..f636e9fd4
--- /dev/null
+++ b/tests/tables.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><p>Simple table with caption:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis>Demonstration of simple table syntax.</emphasis></p><p>Simple table without caption:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis /></p><p>Simple table indented two spaces:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis>Demonstration of simple table syntax.</emphasis></p><p>Multiline table with caption:</p><table><tr><th align="center">Centered Header</th><th align="left">Left Aligned</th><th align="right">Right Aligned</th><th align="left">Default aligned</th></tr><tr><td align="center">First</td><td align="left">row</td><td align="right">12.0</td><td align="left">Example of a row that spans multiple lines.</td></tr><tr><td align="center">Second</td><td align="left">row</td><td align="right">5.0</td><td align="left">Here&#39;s another one. Note the blank line between rows.</td></tr></table><p><emphasis>Here&#39;s the caption. It may span multiple lines.</emphasis></p><p>Multiline table without caption:</p><table><tr><th align="center">Centered Header</th><th align="left">Left Aligned</th><th align="right">Right Aligned</th><th align="left">Default aligned</th></tr><tr><td align="center">First</td><td align="left">row</td><td align="right">12.0</td><td align="left">Example of a row that spans multiple lines.</td></tr><tr><td align="center">Second</td><td align="left">row</td><td align="right">5.0</td><td align="left">Here&#39;s another one. Note the blank line between rows.</td></tr></table><p><emphasis /></p><p>Table without column headers:</p><table><tr><th align="right" /><th align="left" /><th align="center" /><th align="right" /></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="right">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="right">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="right">1</td></tr></table><p><emphasis /></p><p>Multiline table without column headers:</p><table><tr><th align="center" /><th align="left" /><th align="right" /><th align="left" /></tr><tr><td align="center">First</td><td align="left">row</td><td align="right">12.0</td><td align="left">Example of a row that spans multiple lines.</td></tr><tr><td align="center">Second</td><td align="left">row</td><td align="right">5.0</td><td align="left">Here&#39;s another one. Note the blank line between rows.</td></tr></table><p><emphasis /></p></section></body></FictionBook> \ No newline at end of file
diff --git a/tests/tables.native b/tests/tables.native
index 1d714d730..00a7c5970 100644
--- a/tests/tables.native
+++ b/tests/tables.native
@@ -1,5 +1,5 @@
-[Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption",Str ":"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax",Str "."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
+[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."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
[[Plain [Str "Right"]]
,[Plain [Str "Left"]]
,[Plain [Str "Center"]]
@@ -16,7 +16,7 @@
,[Plain [Str "1"]]
,[Plain [Str "1"]]
,[Plain [Str "1"]]]]
-,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption",Str ":"]
+,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
,Table [] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
[[Plain [Str "Right"]]
,[Plain [Str "Left"]]
@@ -34,8 +34,8 @@
,[Plain [Str "1"]]
,[Plain [Str "1"]]
,[Plain [Str "1"]]]]
-,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces",Str ":"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax",Str "."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
+,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."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
[[Plain [Str "Right"]]
,[Plain [Str "Left"]]
,[Plain [Str "Center"]]
@@ -52,21 +52,21 @@
,[Plain [Str "1"]]
,[Plain [Str "1"]]
,[Plain [Str "1"]]]]
-,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption",Str ":"]
-,Table [Str "Here",Str "'",Str "s",Space,Str "the",Space,Str "caption",Str ".",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines",Str "."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375]
+,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"]
+,Table [Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375]
[[Plain [Str "Centered",Space,Str "Header"]]
,[Plain [Str "Left",Space,Str "Aligned"]]
,[Plain [Str "Right",Space,Str "Aligned"]]
,[Plain [Str "Default",Space,Str "aligned"]]]
[[[Plain [Str "First"]]
,[Plain [Str "row"]]
- ,[Plain [Str "12",Str ".",Str "0"]]
- ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines",Str "."]]]
+ ,[Plain [Str "12.0"]]
+ ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
,[[Plain [Str "Second"]]
,[Plain [Str "row"]]
- ,[Plain [Str "5",Str ".",Str "0"]]
- ,[Plain [Str "Here",Str "'",Str "s",Space,Str "another",Space,Str "one",Str ".",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows",Str "."]]]]
-,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption",Str ":"]
+ ,[Plain [Str "5.0"]]
+ ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]
+,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]
,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375]
[[Plain [Str "Centered",Space,Str "Header"]]
,[Plain [Str "Left",Space,Str "Aligned"]]
@@ -74,13 +74,13 @@
,[Plain [Str "Default",Space,Str "aligned"]]]
[[[Plain [Str "First"]]
,[Plain [Str "row"]]
- ,[Plain [Str "12",Str ".",Str "0"]]
- ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines",Str "."]]]
+ ,[Plain [Str "12.0"]]
+ ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
,[[Plain [Str "Second"]]
,[Plain [Str "row"]]
- ,[Plain [Str "5",Str ".",Str "0"]]
- ,[Plain [Str "Here",Str "'",Str "s",Space,Str "another",Space,Str "one",Str ".",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows",Str "."]]]]
-,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers",Str ":"]
+ ,[Plain [Str "5.0"]]
+ ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]
+,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]
[[]
,[]
@@ -98,7 +98,7 @@
,[Plain [Str "1"]]
,[Plain [Str "1"]]
,[Plain [Str "1"]]]]
-,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers",Str ":"]
+,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
,Table [] [AlignCenter,AlignLeft,AlignRight,AlignDefault] [0.15,0.1375,0.1625,0.3375]
[[]
,[]
@@ -106,9 +106,9 @@
,[]]
[[[Plain [Str "First"]]
,[Plain [Str "row"]]
- ,[Plain [Str "12",Str ".",Str "0"]]
- ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines",Str "."]]]
+ ,[Plain [Str "12.0"]]
+ ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
,[[Plain [Str "Second"]]
,[Plain [Str "row"]]
- ,[Plain [Str "5",Str ".",Str "0"]]
- ,[Plain [Str "Here",Str "'",Str "s",Space,Str "another",Space,Str "one",Str ".",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows",Str "."]]]]]
+ ,[Plain [Str "5.0"]]
+ ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]]
diff --git a/src/test-pandoc.hs b/tests/test-pandoc.hs
index 1a8c05e14..968f31df6 100644
--- a/src/test-pandoc.hs
+++ b/tests/test-pandoc.hs
@@ -14,6 +14,7 @@ import qualified Tests.Writers.HTML
import qualified Tests.Writers.Native
import qualified Tests.Writers.Markdown
import qualified Tests.Shared
+import Text.Pandoc.Shared (inDirectory)
tests :: [Test]
tests = [ testGroup "Old" Tests.Old.tests
@@ -33,4 +34,4 @@ tests = [ testGroup "Old" Tests.Old.tests
]
main :: IO ()
-main = defaultMain tests
+main = inDirectory "tests" $ defaultMain tests
diff --git a/tests/testsuite.native b/tests/testsuite.native
index 691c4959a..6393b89d6 100644
--- a/tests/testsuite.native
+++ b/tests/testsuite.native
@@ -1,5 +1,5 @@
-Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docAuthors = [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]], docDate = [Str "July",Space,Str "17",Str ",",Space,Str "2006"]})
-[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
+Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docAuthors = [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]], docDate = [Str "July",Space,Str "17,",Space,Str "2006"]})
+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
,HorizontalRule
,Header 1 [Str "Headers"]
,Header 2 [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embedded",Space,Str "link"] ("/url","")]
@@ -14,95 +14,95 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
,HorizontalRule
,Header 1 [Str "Paragraphs"]
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph",Str "."]
-,Para [Str "In",Space,Str "Markdown",Space,Str "1",Str ".",Str "0",Str ".",Str "0",Space,Str "and",Space,Str "earlier",Str ".",Space,Str "Version",Space,Str "8",Str ".",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item",Str ".",Space,Str "Because",Space,Str "a",Space,Str "hard",Str "-",Str "wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item",Str "."]
-,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet",Str ".",Space,Str "*",Space,Str "criminey",Str "."]
-,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here",Str "."]
+,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]
+,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."]
+,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."]
+,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here."]
,HorizontalRule
,Header 1 [Str "Block",Space,Str "Quotes"]
-,Para [Str "E",Str "-",Str "mail",Space,Str "style",Str ":"]
+,Para [Str "E-mail",Space,Str "style:"]
,BlockQuote
- [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote",Str ".",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short",Str "."]]
+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]]
,BlockQuote
- [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote",Str ":"]
+ [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"]
,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}"
- ,Para [Str "A",Space,Str "list",Str ":"]
+ ,Para [Str "A",Space,Str "list:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "item",Space,Str "one"]]
,[Plain [Str "item",Space,Str "two"]]]
- ,Para [Str "Nested",Space,Str "block",Space,Str "quotes",Str ":"]
+ ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"]
,BlockQuote
[Para [Str "nested"]]
,BlockQuote
[Para [Str "nested"]]]
-,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote",Str ":",Space,Str "2",Space,Str ">",Space,Str "1",Str "."]
-,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."]
+,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."]
+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]
,HorizontalRule
,Header 1 [Str "Code",Space,Str "Blocks"]
-,Para [Str "Code",Str ":"]
+,Para [Str "Code:"]
,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab"
-,Para [Str "And",Str ":"]
+,Para [Str "And:"]
,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{"
,HorizontalRule
,Header 1 [Str "Lists"]
,Header 2 [Str "Unordered"]
-,Para [Str "Asterisks",Space,Str "tight",Str ":"]
+,Para [Str "Asterisks",Space,Str "tight:"]
,BulletList
[[Plain [Str "asterisk",Space,Str "1"]]
,[Plain [Str "asterisk",Space,Str "2"]]
,[Plain [Str "asterisk",Space,Str "3"]]]
-,Para [Str "Asterisks",Space,Str "loose",Str ":"]
+,Para [Str "Asterisks",Space,Str "loose:"]
,BulletList
[[Para [Str "asterisk",Space,Str "1"]]
,[Para [Str "asterisk",Space,Str "2"]]
,[Para [Str "asterisk",Space,Str "3"]]]
-,Para [Str "Pluses",Space,Str "tight",Str ":"]
+,Para [Str "Pluses",Space,Str "tight:"]
,BulletList
[[Plain [Str "Plus",Space,Str "1"]]
,[Plain [Str "Plus",Space,Str "2"]]
,[Plain [Str "Plus",Space,Str "3"]]]
-,Para [Str "Pluses",Space,Str "loose",Str ":"]
+,Para [Str "Pluses",Space,Str "loose:"]
,BulletList
[[Para [Str "Plus",Space,Str "1"]]
,[Para [Str "Plus",Space,Str "2"]]
,[Para [Str "Plus",Space,Str "3"]]]
-,Para [Str "Minuses",Space,Str "tight",Str ":"]
+,Para [Str "Minuses",Space,Str "tight:"]
,BulletList
[[Plain [Str "Minus",Space,Str "1"]]
,[Plain [Str "Minus",Space,Str "2"]]
,[Plain [Str "Minus",Space,Str "3"]]]
-,Para [Str "Minuses",Space,Str "loose",Str ":"]
+,Para [Str "Minuses",Space,Str "loose:"]
,BulletList
[[Para [Str "Minus",Space,Str "1"]]
,[Para [Str "Minus",Space,Str "2"]]
,[Para [Str "Minus",Space,Str "3"]]]
,Header 2 [Str "Ordered"]
-,Para [Str "Tight",Str ":"]
+,Para [Str "Tight:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "First"]]
,[Plain [Str "Second"]]
,[Plain [Str "Third"]]]
-,Para [Str "and",Str ":"]
+,Para [Str "and:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "One"]]
,[Plain [Str "Two"]]
,[Plain [Str "Three"]]]
-,Para [Str "Loose",Space,Str "using",Space,Str "tabs",Str ":"]
+,Para [Str "Loose",Space,Str "using",Space,Str "tabs:"]
,OrderedList (1,Decimal,Period)
[[Para [Str "First"]]
,[Para [Str "Second"]]
,[Para [Str "Third"]]]
-,Para [Str "and",Space,Str "using",Space,Str "spaces",Str ":"]
+,Para [Str "and",Space,Str "using",Space,Str "spaces:"]
,OrderedList (1,Decimal,Period)
[[Para [Str "One"]]
,[Para [Str "Two"]]
,[Para [Str "Three"]]]
-,Para [Str "Multiple",Space,Str "paragraphs",Str ":"]
+,Para [Str "Multiple",Space,Str "paragraphs:"]
,OrderedList (1,Decimal,Period)
- [[Para [Str "Item",Space,Str "1",Str ",",Space,Str "graf",Space,Str "one",Str "."]
- ,Para [Str "Item",Space,Str "1",Str ".",Space,Str "graf",Space,Str "two",Str ".",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",Space,Str "back",Str "."]]
- ,[Para [Str "Item",Space,Str "2",Str "."]]
- ,[Para [Str "Item",Space,Str "3",Str "."]]]
+ [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."]
+ ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",Space,Str "back."]]
+ ,[Para [Str "Item",Space,Str "2."]]
+ ,[Para [Str "Item",Space,Str "3."]]]
,Header 2 [Str "Nested"]
,BulletList
[[Plain [Str "Tab"]
@@ -110,19 +110,19 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "Tab"]
,BulletList
[[Plain [Str "Tab"]]]]]]]
-,Para [Str "Here\8217s",Space,Str "another",Str ":"]
+,Para [Str "Here\8217s",Space,Str "another:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "First"]]
- ,[Plain [Str "Second",Str ":"]
+ ,[Plain [Str "Second:"]
,BulletList
[[Plain [Str "Fee"]]
,[Plain [Str "Fie"]]
,[Plain [Str "Foe"]]]]
,[Plain [Str "Third"]]]
-,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs",Str ":"]
+,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"]
,OrderedList (1,Decimal,Period)
[[Para [Str "First"]]
- ,[Para [Str "Second",Str ":"]
+ ,[Para [Str "Second:"]
,BulletList
[[Plain [Str "Fee"]]
,[Plain [Str "Fie"]]
@@ -141,32 +141,32 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,[Para [Str "and",Space,Str "now",Space,Str "3"]
,Para [Str "with",Space,Str "a",Space,Str "continuation"]
,OrderedList (4,LowerRoman,Period)
- [[Plain [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals",Str ",",Space,Str "starting",Space,Str "with",Space,Str "4"]]
+ [[Plain [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals,",Space,Str "starting",Space,Str "with",Space,Str "4"]]
,[Plain [Str "more",Space,Str "items"]
,OrderedList (1,UpperAlpha,TwoParens)
[[Plain [Str "a",Space,Str "subsublist"]]
,[Plain [Str "a",Space,Str "subsublist"]]]]]]]
-,Para [Str "Nesting",Str ":"]
+,Para [Str "Nesting:"]
,OrderedList (1,UpperAlpha,Period)
[[Plain [Str "Upper",Space,Str "Alpha"]
,OrderedList (1,UpperRoman,Period)
- [[Plain [Str "Upper",Space,Str "Roman",Str "."]
+ [[Plain [Str "Upper",Space,Str "Roman."]
,OrderedList (6,Decimal,TwoParens)
[[Plain [Str "Decimal",Space,Str "start",Space,Str "with",Space,Str "6"]
,OrderedList (3,LowerAlpha,OneParen)
[[Plain [Str "Lower",Space,Str "alpha",Space,Str "with",Space,Str "paren"]]]]]]]]]
-,Para [Str "Autonumbering",Str ":"]
+,Para [Str "Autonumbering:"]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "Autonumber",Str "."]]
- ,[Plain [Str "More",Str "."]
+ [[Plain [Str "Autonumber."]]
+ ,[Plain [Str "More."]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "Nested",Str "."]]]]]
-,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item",Str ":"]
-,Para [Str "M.A.\160",Str "2007"]
-,Para [Str "B",Str ".",Space,Str "Williams"]
+ [[Plain [Str "Nested."]]]]]
+,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item:"]
+,Para [Str "M.A.\160\&2007"]
+,Para [Str "B.",Space,Str "Williams"]
,HorizontalRule
,Header 1 [Str "Definition",Space,Str "Lists"]
-,Para [Str "Tight",Space,Str "using",Space,Str "spaces",Str ":"]
+,Para [Str "Tight",Space,Str "using",Space,Str "spaces:"]
,DefinitionList
[([Str "apple"],
[[Plain [Str "red",Space,Str "fruit"]]])
@@ -174,7 +174,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "orange",Space,Str "fruit"]]])
,([Str "banana"],
[[Plain [Str "yellow",Space,Str "fruit"]]])]
-,Para [Str "Tight",Space,Str "using",Space,Str "tabs",Str ":"]
+,Para [Str "Tight",Space,Str "using",Space,Str "tabs:"]
,DefinitionList
[([Str "apple"],
[[Plain [Str "red",Space,Str "fruit"]]])
@@ -182,7 +182,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "orange",Space,Str "fruit"]]])
,([Str "banana"],
[[Plain [Str "yellow",Space,Str "fruit"]]])]
-,Para [Str "Loose",Str ":"]
+,Para [Str "Loose:"]
,DefinitionList
[([Str "apple"],
[[Para [Str "red",Space,Str "fruit"]]])
@@ -190,17 +190,17 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Para [Str "orange",Space,Str "fruit"]]])
,([Str "banana"],
[[Para [Str "yellow",Space,Str "fruit"]]])]
-,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics",Str ":"]
+,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics:"]
,DefinitionList
[([Emph [Str "apple"]],
[[Para [Str "red",Space,Str "fruit"]
- ,Para [Str "contains",Space,Str "seeds",Str ",",Space,Str "crisp",Str ",",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]])
+ ,Para [Str "contains",Space,Str "seeds,",Space,Str "crisp,",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]])
,([Emph [Str "orange"]],
[[Para [Str "orange",Space,Str "fruit"]
,CodeBlock ("",[],[]) "{ orange code block }"
,BlockQuote
[Para [Str "orange",Space,Str "block",Space,Str "quote"]]]])]
-,Para [Str "Multiple",Space,Str "definitions",Str ",",Space,Str "tight",Str ":"]
+,Para [Str "Multiple",Space,Str "definitions,",Space,Str "tight:"]
,DefinitionList
[([Str "apple"],
[[Plain [Str "red",Space,Str "fruit"]]
@@ -208,7 +208,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,([Str "orange"],
[[Plain [Str "orange",Space,Str "fruit"]]
,[Plain [Str "bank"]]])]
-,Para [Str "Multiple",Space,Str "definitions",Str ",",Space,Str "loose",Str ":"]
+,Para [Str "Multiple",Space,Str "definitions,",Space,Str "loose:"]
,DefinitionList
[([Str "apple"],
[[Para [Str "red",Space,Str "fruit"]]
@@ -216,7 +216,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,([Str "orange"],
[[Para [Str "orange",Space,Str "fruit"]]
,[Para [Str "bank"]]])]
-,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term",Str ",",Space,Str "indented",Space,Str "marker",Str ",",Space,Str "alternate",Space,Str "markers",Str ":"]
+,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term,",Space,Str "indented",Space,Str "marker,",Space,Str "alternate",Space,Str "markers:"]
,DefinitionList
[([Str "apple"],
[[Para [Str "red",Space,Str "fruit"]]
@@ -227,70 +227,70 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "sublist"]]
,[Plain [Str "sublist"]]]]])]
,Header 1 [Str "HTML",Space,Str "Blocks"]
-,Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line",Str ":"]
+,Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line:"]
,RawBlock "html" "<div>"
,Plain [Str "foo"]
,RawBlock "html" "</div>\n"
-,Para [Str "And",Space,Str "nested",Space,Str "without",Space,Str "indentation",Str ":"]
+,Para [Str "And",Space,Str "nested",Space,Str "without",Space,Str "indentation:"]
,RawBlock "html" "<div>\n<div>\n<div>"
,Plain [Str "foo"]
,RawBlock "html" "</div>\n</div>\n<div>"
,Plain [Str "bar"]
,RawBlock "html" "</div>\n</div>\n"
-,Para [Str "Interpreted",Space,Str "markdown",Space,Str "in",Space,Str "a",Space,Str "table",Str ":"]
+,Para [Str "Interpreted",Space,Str "markdown",Space,Str "in",Space,Str "a",Space,Str "table:"]
,RawBlock "html" "<table>\n<tr>\n<td>"
,Plain [Str "This",Space,Str "is",Space,Emph [Str "emphasized"]]
,RawBlock "html" "</td>\n<td>"
,Plain [Str "And",Space,Str "this",Space,Str "is",Space,Strong [Str "strong"]]
,RawBlock "html" "</td>\n</tr>\n</table>\n\n<script type=\"text/javascript\">document.write('This *should not* be interpreted as markdown');</script>\n"
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "simple",Space,Str "block",Str ":"]
+,Para [Str "Here\8217s",Space,Str "a",Space,Str "simple",Space,Str "block:"]
,RawBlock "html" "<div>\n "
,Plain [Str "foo"]
,RawBlock "html" "</div>\n"
-,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "code",Space,Str "block",Str ",",Space,Str "though",Str ":"]
+,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "code",Space,Str "block,",Space,Str "though:"]
,CodeBlock ("",[],[]) "<div>\n foo\n</div>"
-,Para [Str "As",Space,Str "should",Space,Str "this",Str ":"]
+,Para [Str "As",Space,Str "should",Space,Str "this:"]
,CodeBlock ("",[],[]) "<div>foo</div>"
-,Para [Str "Now",Str ",",Space,Str "nested",Str ":"]
+,Para [Str "Now,",Space,Str "nested:"]
,RawBlock "html" "<div>\n <div>\n <div>\n "
,Plain [Str "foo"]
,RawBlock "html" "</div>\n </div>\n</div>\n"
-,Para [Str "This",Space,Str "should",Space,Str "just",Space,Str "be",Space,Str "an",Space,Str "HTML",Space,Str "comment",Str ":"]
+,Para [Str "This",Space,Str "should",Space,Str "just",Space,Str "be",Space,Str "an",Space,Str "HTML",Space,Str "comment:"]
,RawBlock "html" "<!-- Comment -->\n"
-,Para [Str "Multiline",Str ":"]
+,Para [Str "Multiline:"]
,RawBlock "html" "<!--\nBlah\nBlah\n-->\n\n<!--\n This is another comment.\n-->\n"
-,Para [Str "Code",Space,Str "block",Str ":"]
+,Para [Str "Code",Space,Str "block:"]
,CodeBlock ("",[],[]) "<!-- Comment -->"
-,Para [Str "Just",Space,Str "plain",Space,Str "comment",Str ",",Space,Str "with",Space,Str "trailing",Space,Str "spaces",Space,Str "on",Space,Str "the",Space,Str "line",Str ":"]
+,Para [Str "Just",Space,Str "plain",Space,Str "comment,",Space,Str "with",Space,Str "trailing",Space,Str "spaces",Space,Str "on",Space,Str "the",Space,Str "line:"]
,RawBlock "html" "<!-- foo --> \n"
-,Para [Str "Code",Str ":"]
+,Para [Str "Code:"]
,CodeBlock ("",[],[]) "<hr />"
-,Para [Str "Hr\8217s",Str ":"]
+,Para [Str "Hr\8217s:"]
,RawBlock "html" "<hr>\n\n<hr />\n\n<hr />\n\n<hr> \n\n<hr /> \n\n<hr /> \n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\">\n"
,HorizontalRule
,Header 1 [Str "Inline",Space,Str "Markup"]
,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str "."]
,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str "."]
,Para [Str "An",Space,Emph [Link [Str "emphasized",Space,Str "link"] ("/url","")],Str "."]
-,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]]]
-,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Str "."]
-,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]]]
-,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Str "."]
-,Para [Str "This",Space,Str "is",Space,Str "code",Str ":",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "<html>",Str "."]
+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
+,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "<html>",Str "."]
,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "strikeout"],Str "."]]
-,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Emph [Str "hello"]],Space,Str "a",Superscript [Str "hello",Str "\160",Str "there"],Str "."]
-,Para [Str "Subscripts",Str ":",Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Str "\160",Str "of",Str "\160",Str "them"],Str "O",Str "."]
-,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts",Str ",",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",Space,Str "spaces",Str ":",Space,Str "a",Str "^",Str "b",Space,Str "c",Str "^",Str "d",Str ",",Space,Str "a",Str "~",Str "b",Space,Str "c",Str "~",Str "d",Str "."]
+,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Emph [Str "hello"]],Space,Str "a",Superscript [Str "hello\160there"],Str "."]
+,Para [Str "Subscripts:",Space,Str "H",Subscript [Str "2"],Str "O,",Space,Str "H",Subscript [Str "23"],Str "O,",Space,Str "H",Subscript [Str "many\160of\160them"],Str "O."]
+,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts,",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",Space,Str "spaces:",Space,Str "a^b",Space,Str "c^d,",Space,Str "a~b",Space,Str "c~d."]
,HorizontalRule
-,Header 1 [Str "Smart",Space,Str "quotes",Str ",",Space,Str "ellipses",Str ",",Space,Str "dashes"]
-,Para [Quoted DoubleQuote [Str "Hello",Str ","],Space,Str "said",Space,Str "the",Space,Str "spider",Str ".",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",Space,Str "name",Str "."]]
-,Para [Quoted SingleQuote [Str "A"],Str ",",Space,Quoted SingleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted SingleQuote [Str "C"],Space,Str "are",Space,Str "letters",Str "."]
-,Para [Quoted SingleQuote [Str "Oak",Str ","],Space,Quoted SingleQuote [Str "elm",Str ","],Space,Str "and",Space,Quoted SingleQuote [Str "beech"],Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees",Str ".",Space,Str "So",Space,Str "is",Space,Quoted SingleQuote [Str "pine",Str "."]]
-,Para [Quoted SingleQuote [Str "He",Space,Str "said",Str ",",Space,Quoted DoubleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go",Str "."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70\8217s",Str "?"]
+,Header 1 [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]
+,Para [Quoted DoubleQuote [Str "Hello,"],Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",Space,Str "name."]]
+,Para [Quoted SingleQuote [Str "A"],Str ",",Space,Quoted SingleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted SingleQuote [Str "C"],Space,Str "are",Space,Str "letters."]
+,Para [Quoted SingleQuote [Str "Oak,"],Space,Quoted SingleQuote [Str "elm,"],Space,Str "and",Space,Quoted SingleQuote [Str "beech"],Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Quoted SingleQuote [Str "pine."]]
+,Para [Quoted SingleQuote [Str "He",Space,Str "said,",Space,Quoted DoubleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70\8217s?"]
,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Quoted SingleQuote [Code ("",[],[]) "code"],Space,Str "and",Space,Str "a",Space,Quoted DoubleQuote [Link [Str "quoted",Space,Str "link"] ("http://example.com/?foo=1&bar=2","")],Str "."]
-,Para [Str "Some",Space,Str "dashes",Str ":",Space,Str "one",Str "\8212",Str "two",Space,Str "\8212",Space,Str "three",Str "\8212",Str "four",Space,Str "\8212",Space,Str "five",Str "."]
-,Para [Str "Dashes",Space,Str "between",Space,Str "numbers",Str ":",Space,Str "5",Str "\8211",Str "7",Str ",",Space,Str "255",Str "\8211",Str "66",Str ",",Space,Str "1987",Str "\8211",Str "1999",Str "."]
-,Para [Str "Ellipses",Str "\8230",Str "and",Str "\8230",Str "and",Str "\8230",Str "."]
+,Para [Str "Some",Space,Str "dashes:",Space,Str "one\8212two",Space,Str "\8212",Space,Str "three\8212four",Space,Str "\8212",Space,Str "five."]
+,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5\8211\&7,",Space,Str "255\8211\&66,",Space,Str "1987\8211\&1999."]
+,Para [Str "Ellipses\8230and\8230and\8230."]
,HorizontalRule
,Header 1 [Str "LaTeX"]
,BulletList
@@ -299,47 +299,47 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,[Plain [Math InlineMath "x \\in y"]]
,[Plain [Math InlineMath "\\alpha \\wedge \\omega"]]
,[Plain [Math InlineMath "223"]]
- ,[Plain [Math InlineMath "p",Str "-",Str "Tree"]]
- ,[Plain [Str "Here\8217s",Space,Str "some",Space,Str "display",Space,Str "math",Str ":",Space,Math DisplayMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]]
- ,[Plain [Str "Here\8217s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it",Str ":",Space,Math InlineMath "\\alpha + \\omega \\times x^2",Str "."]]]
-,Para [Str "These",Space,Str "shouldn\8217t",Space,Str "be",Space,Str "math",Str ":"]
+ ,[Plain [Math InlineMath "p",Str "-Tree"]]
+ ,[Plain [Str "Here\8217s",Space,Str "some",Space,Str "display",Space,Str "math:",Space,Math DisplayMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]]
+ ,[Plain [Str "Here\8217s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math InlineMath "\\alpha + \\omega \\times x^2",Str "."]]]
+,Para [Str "These",Space,Str "shouldn\8217t",Space,Str "be",Space,Str "math:"]
,BulletList
- [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation",Str ",",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
- ,[Plain [Str "$",Str "22",Str ",",Str "000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$",Str "34",Str ",",Str "000",Str ".",Space,Str "(",Str "It",Space,Str "worked",Space,Str "if",Space,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]]
- ,[Plain [Str "Shoes",Space,Str "(",Str "$",Str "20",Str ")",Space,Str "and",Space,Str "socks",Space,Str "(",Str "$",Str "5",Str ")",Str "."]]
- ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$",Str "73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23",Str "$",Str "."]]]
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table",Str ":"]
+ [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
+ ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized.)"]]
+ ,[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 "latex" "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}"
,HorizontalRule
,Header 1 [Str "Special",Space,Str "Characters"]
-,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode",Str ":"]
+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
,BulletList
- [[Plain [Str "I",Space,Str "hat",Str ":",Space,Str "\206"]]
- ,[Plain [Str "o",Space,Str "umlaut",Str ":",Space,Str "\246"]]
- ,[Plain [Str "section",Str ":",Space,Str "\167"]]
- ,[Plain [Str "set",Space,Str "membership",Str ":",Space,Str "\8712"]]
- ,[Plain [Str "copyright",Str ":",Space,Str "\169"]]]
-,Para [Str "AT",Str "&",Str "T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
-,Para [Str "AT",Str "&",Str "T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
-,Para [Str "This",Space,Str "&",Space,Str "that",Str "."]
-,Para [Str "4",Space,Str "<",Space,Str "5",Str "."]
-,Para [Str "6",Space,Str ">",Space,Str "5",Str "."]
-,Para [Str "Backslash",Str ":",Space,Str "\\"]
-,Para [Str "Backtick",Str ":",Space,Str "`"]
-,Para [Str "Asterisk",Str ":",Space,Str "*"]
-,Para [Str "Underscore",Str ":",Space,Str "_"]
-,Para [Str "Left",Space,Str "brace",Str ":",Space,Str "{"]
-,Para [Str "Right",Space,Str "brace",Str ":",Space,Str "}"]
-,Para [Str "Left",Space,Str "bracket",Str ":",Space,Str "["]
-,Para [Str "Right",Space,Str "bracket",Str ":",Space,Str "]"]
-,Para [Str "Left",Space,Str "paren",Str ":",Space,Str "("]
-,Para [Str "Right",Space,Str "paren",Str ":",Space,Str ")"]
-,Para [Str "Greater",Str "-",Str "than",Str ":",Space,Str ">"]
-,Para [Str "Hash",Str ":",Space,Str "#"]
-,Para [Str "Period",Str ":",Space,Str "."]
-,Para [Str "Bang",Str ":",Space,Str "!"]
-,Para [Str "Plus",Str ":",Space,Str "+"]
-,Para [Str "Minus",Str ":",Space,Str "-"]
+ [[Plain [Str "I",Space,Str "hat:",Space,Str "\206"]]
+ ,[Plain [Str "o",Space,Str "umlaut:",Space,Str "\246"]]
+ ,[Plain [Str "section:",Space,Str "\167"]]
+ ,[Plain [Str "set",Space,Str "membership:",Space,Str "\8712"]]
+ ,[Plain [Str "copyright:",Space,Str "\169"]]]
+,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."]
+,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."]
+,Para [Str "This",Space,Str "&",Space,Str "that."]
+,Para [Str "4",Space,Str "<",Space,Str "5."]
+,Para [Str "6",Space,Str ">",Space,Str "5."]
+,Para [Str "Backslash:",Space,Str "\\"]
+,Para [Str "Backtick:",Space,Str "`"]
+,Para [Str "Asterisk:",Space,Str "*"]
+,Para [Str "Underscore:",Space,Str "_"]
+,Para [Str "Left",Space,Str "brace:",Space,Str "{"]
+,Para [Str "Right",Space,Str "brace:",Space,Str "}"]
+,Para [Str "Left",Space,Str "bracket:",Space,Str "["]
+,Para [Str "Right",Space,Str "bracket:",Space,Str "]"]
+,Para [Str "Left",Space,Str "paren:",Space,Str "("]
+,Para [Str "Right",Space,Str "paren:",Space,Str ")"]
+,Para [Str "Greater-than:",Space,Str ">"]
+,Para [Str "Hash:",Space,Str "#"]
+,Para [Str "Period:",Space,Str "."]
+,Para [Str "Bang:",Space,Str "!"]
+,Para [Str "Plus:",Space,Str "+"]
+,Para [Str "Minus:",Space,Str "-"]
,HorizontalRule
,Header 1 [Str "Links"]
,Header 2 [Str "Explicit"]
@@ -349,48 +349,48 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."]
,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")]
,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with single quotes")]
-,Para [Link [Str "with",Str "_",Str "underscore"] ("/url/with_underscore","")]
+,Para [Link [Str "with_underscore"] ("/url/with_underscore","")]
,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")]
,Para [Link [Str "Empty"] ("",""),Str "."]
,Header 2 [Str "Reference"]
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
-,Para [Str "With",Space,Link [Str "embedded",Space,Str "[",Str "brackets",Str "]"] ("/url/",""),Str "."]
-,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link",Str "."]
+,Para [Str "With",Space,Link [Str "embedded",Space,Str "[brackets]"] ("/url/",""),Str "."]
+,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."]
,Para [Str "Indented",Space,Link [Str "once"] ("/url",""),Str "."]
,Para [Str "Indented",Space,Link [Str "twice"] ("/url",""),Str "."]
,Para [Str "Indented",Space,Link [Str "thrice"] ("/url",""),Str "."]
-,Para [Str "This",Space,Str "should",Space,Str "[",Str "not",Str "]",Str "[",Str "]",Space,Str "be",Space,Str "a",Space,Str "link",Str "."]
+,Para [Str "This",Space,Str "should",Space,Str "[not][]",Space,Str "be",Space,Str "a",Space,Str "link."]
,CodeBlock ("",[],[]) "[not]: /url"
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."]
,Para [Str "Foo",Space,Link [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."]
,Header 2 [Str "With",Space,Str "ampersands"]
,Para [Str "Here\8217s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text",Str ":",Space,Link [Str "AT",Str "&",Str "T"] ("http://att.com/","AT&T"),Str "."]
+,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] ("http://att.com/","AT&T"),Str "."]
,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 [Str "Autolinks"]
-,Para [Str "With",Space,Str "an",Space,Str "ampersand",Str ":",Space,Link [Code ("",["url"],[]) "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 [Code ("",["url"],[]) "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
,BulletList
- [[Plain [Str "In",Space,Str "a",Space,Str "list",Str "?"]]
+ [[Plain [Str "In",Space,Str "a",Space,Str "list?"]]
,[Plain [Link [Code ("",["url"],[]) "http://example.com/"] ("http://example.com/","")]]
- ,[Plain [Str "It",Space,Str "should",Str "."]]]
-,Para [Str "An",Space,Str "e",Str "-",Str "mail",Space,Str "address",Str ":",Space,Link [Code ("",["url"],[]) "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
+ ,[Plain [Str "It",Space,Str "should."]]]
+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link [Code ("",["url"],[]) "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
,BlockQuote
- [Para [Str "Blockquoted",Str ":",Space,Link [Code ("",["url"],[]) "http://example.com/"] ("http://example.com/","")]]
-,Para [Str "Auto",Str "-",Str "links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here",Str ":",Space,Code ("",[],[]) "<http://example.com/>"]
+ [Para [Str "Blockquoted:",Space,Link [Code ("",["url"],[]) "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
,Header 1 [Str "Images"]
-,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(",Str "1902",Str ")",Str ":"]
+,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]
,Para [Image [Str "lalune"] ("lalune.jpg","Voyage dans la Lune")]
-,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon",Str "."]
+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon."]
,HorizontalRule
,Header 1 [Str "Footnotes"]
-,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference",Str ",",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote",Str ".",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference",Str ".",Space,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document",Str "."]],Space,Str "and",Space,Str "another",Str ".",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note",Str ".",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks",Str "."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",Space,Str "footnote",Space,Str "(",Str "as",Space,Str "with",Space,Str "list",Space,Str "items",Str ")",Str "."],CodeBlock ("",[],[]) " { <code> }",Para [Str "If",Space,Str "you",Space,Str "want",Str ",",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line",Str ",",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",Space,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block",Str "."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference",Str ",",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space",Str ".",Str "[",Str "^",Str "my",Space,Str "note",Str "]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note",Str ".",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type",Str ".",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",Space,Link [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",Space,Str "verbatim",Space,Str "characters",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[",Str "bracketed",Space,Str "text",Str "]",Str "."]]]
+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference.",Space,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document."]],Space,Str "and",Space,Str "another.",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "list",Space,Str "items)."],CodeBlock ("",[],[]) " { <code> }",Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line,",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",Space,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space.[^my",Space,Str "note]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note.",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type.",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",Space,Link [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",Space,Str "verbatim",Space,Str "characters,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[bracketed",Space,Str "text]."]]]
,BlockQuote
- [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes",Str ".",Note [Para [Str "In",Space,Str "quote",Str "."]]]]
+ [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes.",Note [Para [Str "In",Space,Str "quote."]]]]
,OrderedList (1,Decimal,Period)
- [[Plain [Str "And",Space,Str "in",Space,Str "list",Space,Str "items",Str ".",Note [Para [Str "In",Space,Str "list",Str "."]]]]]
-,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note",Str ",",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented",Str "."]]
+ [[Plain [Str "And",Space,Str "in",Space,Str "list",Space,Str "items.",Note [Para [Str "In",Space,Str "list."]]]]]
+,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented."]]
diff --git a/tests/textile-reader.native b/tests/textile-reader.native
index 39359d13a..f5ca5ae0f 100644
--- a/tests/textile-reader.native
+++ b/tests/textile-reader.native
@@ -83,6 +83,7 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")]
,Para [Str "Automatic",Space,Str "linking",Space,Str "to",Space,Link [Str "http://www.example.com"] ("http://www.example.com",""),Space,Str "and",Space,Link [Str "foobar@example.com"] ("mailto:foobar@example.com",""),Str "."]
,Para [Link [Str "Example"] ("http://www.example.com/",""),Str ":",Space,Str "Example",Space,Str "of",Space,Str "a",Space,Str "link",Space,Str "followed",Space,Str "by",Space,Str "a",Space,Str "colon",Str "."]
+,Para [Str "A",Space,Str "link",Link [Str "with",Space,Str "brackets"] ("http://www.example.com",""),Str "and",Space,Str "no",Space,Str "spaces",Str "."]
,Header 1 [Str "Tables"]
,Para [Str "Textile",Space,Str "allows",Space,Str "tables",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "headers",Space,Str ":"]
,Header 2 [Str "Without",Space,Str "headers"]
diff --git a/tests/textile-reader.textile b/tests/textile-reader.textile
index adfec90d3..f52212af3 100644
--- a/tests/textile-reader.textile
+++ b/tests/textile-reader.textile
@@ -155,6 +155,8 @@ Automatic linking to http://www.example.com and foobar@example.com.
"Example":http://www.example.com/: Example of a link followed by a colon.
+A link["with brackets":http://www.example.com]and no spaces.
+
h1. Tables
Textile allows tables with and without headers :
diff --git a/tests/writer.fb2 b/tests/writer.fb2
new file mode 100644
index 000000000..64275d03e
--- /dev/null
+++ b/tests/writer.fb2
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><book-title>Pandoc Test Suite</book-title><author><first-name>John</first-name><last-name>MacFarlane</last-name></author><author><nickname>Anonymous</nickname></author><date>July 17, 2006</date></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p>Pandoc Test Suite</p></title><annotation><p>John MacFarlane</p><p>Anonymous</p><p>July 17, 2006</p></annotation><section><p>This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Headers</p></title><section><title><p>Level 2 with an embedded link &lt;/url&gt;</p></title><section><title><p>Level 3 with emphasis</p></title><section><title><p>Level 4</p></title><section><title><p>Level 5</p></title></section></section></section></section></section><section><title><p>Level 1</p></title><section><title><p>Level 2 with emphasis</p></title><section><title><p>Level 3</p></title><p>with no blank line</p></section></section><section><title><p>Level 2</p></title><p>with no blank line</p><empty-line /><p>——————————</p><empty-line /></section></section><section><title><p>Paragraphs</p></title><p>Here’s a regular paragraph.</p><p>In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.</p><p>Here’s one with a bullet. * criminey.</p><p>There should be a hard line break<empty-line />here.</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Block Quotes</p></title><p>E-mail style:</p><cite><p>This is a block quote. It is pretty short.</p></cite><cite><p>Code in a block quote:</p><empty-line /><p><code>sub status {</code></p><p><code> print &quot;working&quot;;</code></p><p><code>}</code></p><empty-line /><p>A list:</p><p> 1. item one</p><p> 2. item two</p><p>Nested block quotes:</p><cite><p>nested</p></cite><cite><p>nested</p></cite></cite><p>This should not be a block quote: 2 &gt; 1.</p><p>And a following paragraph.</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Code Blocks</p></title><p>Code:</p><empty-line /><p><code>---- (should be four hyphens)</code></p><p><code></code></p><p><code>sub status {</code></p><p><code> print &quot;working&quot;;</code></p><p><code>}</code></p><p><code></code></p><p><code>this code block is indented by one tab</code></p><empty-line /><p>And:</p><empty-line /><p><code> this code block is indented by two tabs</code></p><p><code></code></p><p><code>These should not be escaped: \$ \\ \&gt; \[ \{</code></p><empty-line /><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Lists</p></title><section><title><p>Unordered</p></title><p>Asterisks tight:</p><p>• asterisk 1</p><p>• asterisk 2</p><p>• asterisk 3</p><p>Asterisks loose:</p><p>• asterisk 1<empty-line /></p><p>• asterisk 2<empty-line /></p><p>• asterisk 3<empty-line /></p><p>Pluses tight:</p><p>• Plus 1</p><p>• Plus 2</p><p>• Plus 3</p><p>Pluses loose:</p><p>• Plus 1<empty-line /></p><p>• Plus 2<empty-line /></p><p>• Plus 3<empty-line /></p><p>Minuses tight:</p><p>• Minus 1</p><p>• Minus 2</p><p>• Minus 3</p><p>Minuses loose:</p><p>• Minus 1<empty-line /></p><p>• Minus 2<empty-line /></p><p>• Minus 3<empty-line /></p></section><section><title><p>Ordered</p></title><p>Tight:</p><p> 1. First</p><p> 2. Second</p><p> 3. Third</p><p>and:</p><p> 1. One</p><p> 2. Two</p><p> 3. Three</p><p>Loose using tabs:</p><p> 1. First<empty-line /></p><p> 2. Second<empty-line /></p><p> 3. Third<empty-line /></p><p>and using spaces:</p><p> 1. One<empty-line /></p><p> 2. Two<empty-line /></p><p> 3. Three<empty-line /></p><p>Multiple paragraphs:</p><p> 1. Item 1, graf one.<empty-line />Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.<empty-line /></p><p> 2. Item 2.<empty-line /></p><p> 3. Item 3.<empty-line /></p></section><section><title><p>Nested</p></title><p>• Tab<p>◦ Tab<p>* Tab</p></p></p><p>Here’s another:</p><p> 1. First</p><p> 2. Second:<p>   • Fee</p><p>   • Fie</p><p>   • Foe</p></p><p> 3. Third</p><p>Same thing but with paragraphs:</p><p> 1. First<empty-line /></p><p> 2. Second:<empty-line /><p>   • Fee</p><p>   • Fie</p><p>   • Foe</p></p><p> 3. Third<empty-line /></p></section><section><title><p>Tabs and spaces</p></title><p>• this is a list item indented with tabs<empty-line /></p><p>• this is a list item indented with spaces<empty-line /><p>◦ this is an example list item indented with tabs<empty-line /></p><p>◦ this is an example list item indented with spaces<empty-line /></p></p></section><section><title><p>Fancy list markers</p></title><p> (2) begins with 2</p><p> (3) and now 3<empty-line />with a continuation<empty-line /><p> (3) iv. sublist with roman numerals, starting with 4</p><p> (3) v. more items<p> (3) v. (A) a subsublist</p><p> (3) v. (B) a subsublist</p></p></p><p>Nesting:</p><p> A. Upper Alpha<p> A. I. Upper Roman.<p> A. I. (6) Decimal start with 6<p> A. I. (6) c) Lower alpha with paren</p></p></p></p><p>Autonumbering:</p><p> 1. Autonumber.</p><p> 2. More.<p> 2. 1. Nested.</p></p><p>Should not be a list item:</p><p>M.A. 2007</p><p>B. Williams</p><empty-line /><p>——————————</p><empty-line /></section></section><section><title><p>Definition Lists</p></title><p>Tight using spaces:</p><p><strong>apple</strong></p><p>    red fruit<empty-line /></p><p><strong>orange</strong></p><p>    orange fruit<empty-line /></p><p><strong>banana</strong></p><p>    yellow fruit<empty-line /></p><p>Tight using tabs:</p><p><strong>apple</strong></p><p>    red fruit<empty-line /></p><p><strong>orange</strong></p><p>    orange fruit<empty-line /></p><p><strong>banana</strong></p><p>    yellow fruit<empty-line /></p><p>Loose:</p><p><strong>apple</strong></p><p>    red fruit<empty-line /></p><p><strong>orange</strong></p><p>    orange fruit<empty-line /></p><p><strong>banana</strong></p><p>    yellow fruit<empty-line /></p><p>Multiple blocks with italics:</p><p><strong><emphasis>apple</emphasis></strong></p><p>    red fruit<empty-line />    contains seeds, crisp, pleasant to taste<empty-line /></p><p><strong><emphasis>orange</emphasis></strong></p><p>    orange fruit<empty-line /><empty-line /><p><code>    { orange code block }</code></p><empty-line /><cite><p>    orange block quote</p></cite></p><p>Multiple definitions, tight:</p><p><strong>apple</strong></p><p>    red fruit<empty-line />    computer<empty-line /></p><p><strong>orange</strong></p><p>    orange fruit<empty-line />    bank<empty-line /></p><p>Multiple definitions, loose:</p><p><strong>apple</strong></p><p>    red fruit<empty-line />    computer<empty-line /></p><p><strong>orange</strong></p><p>    orange fruit<empty-line />    bank<empty-line /></p><p>Blank line after term, indented marker, alternate markers:</p><p><strong>apple</strong></p><p>    red fruit<empty-line />    computer<empty-line /></p><p><strong>orange</strong></p><p>    orange fruit<empty-line /><p> 1. sublist</p><p> 2. sublist</p></p></section><section><title><p>HTML Blocks</p></title><p>Simple block on one line:</p><empty-line /><p><code>&lt;div&gt;</code></p><empty-line />foo<empty-line /><p><code>&lt;/div&gt;</code></p><empty-line /><p>And nested without indentation:</p><empty-line /><p><code>&lt;div&gt;</code></p><p><code>&lt;div&gt;</code></p><p><code>&lt;div&gt;</code></p><empty-line />foo<empty-line /><p><code>&lt;/div&gt;</code></p><p><code>&lt;/div&gt;</code></p><p><code>&lt;div&gt;</code></p><empty-line />bar<empty-line /><p><code>&lt;/div&gt;</code></p><p><code>&lt;/div&gt;</code></p><empty-line /><p>Interpreted markdown in a table:</p><empty-line /><p><code>&lt;table&gt;</code></p><p><code>&lt;tr&gt;</code></p><p><code>&lt;td&gt;</code></p><empty-line />This is <emphasis>emphasized</emphasis><empty-line /><p><code>&lt;/td&gt;</code></p><p><code>&lt;td&gt;</code></p><empty-line />And this is <strong>strong</strong><empty-line /><p><code>&lt;/td&gt;</code></p><p><code>&lt;/tr&gt;</code></p><p><code>&lt;/table&gt;</code></p><p><code></code></p><p><code>&lt;script type=&quot;text/javascript&quot;&gt;document.write(&#39;This *should not* be interpreted as markdown&#39;);&lt;/script&gt;</code></p><empty-line /><p>Here’s a simple block:</p><empty-line /><p><code>&lt;div&gt;</code></p><p><code> </code></p><empty-line />foo<empty-line /><p><code>&lt;/div&gt;</code></p><empty-line /><p>This should be a code block, though:</p><empty-line /><p><code>&lt;div&gt;</code></p><p><code> foo</code></p><p><code>&lt;/div&gt;</code></p><empty-line /><p>As should this:</p><empty-line /><p><code>&lt;div&gt;foo&lt;/div&gt;</code></p><empty-line /><p>Now, nested:</p><empty-line /><p><code>&lt;div&gt;</code></p><p><code> &lt;div&gt;</code></p><p><code> &lt;div&gt;</code></p><p><code> </code></p><empty-line />foo<empty-line /><p><code>&lt;/div&gt;</code></p><p><code> &lt;/div&gt;</code></p><p><code>&lt;/div&gt;</code></p><empty-line /><p>This should just be an HTML comment:</p><empty-line /><p><code>&lt;!-- Comment --&gt;</code></p><empty-line /><p>Multiline:</p><empty-line /><p><code>&lt;!--</code></p><p><code>Blah</code></p><p><code>Blah</code></p><p><code>--&gt;</code></p><p><code></code></p><p><code>&lt;!--</code></p><p><code> This is another comment.</code></p><p><code>--&gt;</code></p><empty-line /><p>Code block:</p><empty-line /><p><code>&lt;!-- Comment --&gt;</code></p><empty-line /><p>Just plain comment, with trailing spaces on the line:</p><empty-line /><p><code>&lt;!-- foo --&gt; </code></p><empty-line /><p>Code:</p><empty-line /><p><code>&lt;hr /&gt;</code></p><empty-line /><p>Hr’s:</p><empty-line /><p><code>&lt;hr&gt;</code></p><p><code></code></p><p><code>&lt;hr /&gt;</code></p><p><code></code></p><p><code>&lt;hr /&gt;</code></p><p><code></code></p><p><code>&lt;hr&gt; </code></p><p><code></code></p><p><code>&lt;hr /&gt; </code></p><p><code></code></p><p><code>&lt;hr /&gt; </code></p><p><code></code></p><p><code>&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;</code></p><p><code></code></p><p><code>&lt;hr class=&quot;foo&quot; id=&quot;bar&quot; /&gt;</code></p><p><code></code></p><p><code>&lt;hr class=&quot;foo&quot; id=&quot;bar&quot;&gt;</code></p><empty-line /><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Inline Markup</p></title><p>This is <emphasis>emphasized</emphasis>, and so <emphasis>is this</emphasis>.</p><p>This is <strong>strong</strong>, and so <strong>is this</strong>.</p><p>An <emphasis>emphasized link<a l:href="#l1" type="note"><sup>[1]</sup></a></emphasis>.</p><p><strong><emphasis>This is strong and em.</emphasis></strong></p><p>So is <strong><emphasis>this</emphasis></strong> word.</p><p><strong><emphasis>This is strong and em.</emphasis></strong></p><p>So is <strong><emphasis>this</emphasis></strong> word.</p><p>This is code: <code>&gt;</code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code>&lt;html&gt;</code>.</p><p><strikethrough>This is <emphasis>strikeout</emphasis>.</strikethrough></p><p>Superscripts: a<sup>bc</sup>d a<sup><emphasis>hello</emphasis></sup> a<sup>hello there</sup>.</p><p>Subscripts: H<sub>2</sub>O, H<sub>23</sub>O, H<sub>many of them</sub>O.</p><p>These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Smart quotes, ellipses, dashes</p></title><p>“Hello,” said the spider. “‘Shelob’ is my name.”</p><p>‘A’, ‘B’, and ‘C’ are letters.</p><p>‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’</p><p>‘He said, “I want to go.”’ Were you alive in the 70’s?</p><p>Here is some quoted ‘<code>code</code>’ and a “quoted link<a l:href="#l2" type="note"><sup>[2]</sup></a>”.</p><p>Some dashes: one—two — three—four — five.</p><p>Dashes between numbers: 5–7, 255–66, 1987–1999.</p><p>Ellipses…and…and….</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>LaTeX</p></title><p>• </p><p>• <code>2+2=4</code></p><p>• <code>x \in y</code></p><p>• <code>\alpha \wedge \omega</code></p><p>• <code>223</code></p><p>• <code>p</code>-Tree</p><p>• Here’s some display math: <code>\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}</code></p><p>• Here’s one that has a line break in it: <code>\alpha + \omega \times x^2</code>.</p><p>These shouldn’t be math:</p><p>• To get the famous equation, write <code>$e = mc^2$</code>.</p><p>• $22,000 is a <emphasis>lot</emphasis> of money. So is $34,000. (It worked if “lot” is emphasized.)</p><p>• Shoes ($20) and socks ($5).</p><p>• Escaped <code>$</code>: $73 <emphasis>this should be emphasized</emphasis> 23$.</p><p>Here’s a LaTeX table:</p><empty-line /><p><code>\begin{tabular}{|l|l|}\hline</code></p><p><code>Animal &amp; Number \\ \hline</code></p><p><code>Dog &amp; 2 \\</code></p><p><code>Cat &amp; 1 \\ \hline</code></p><p><code>\end{tabular}</code></p><empty-line /><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Special Characters</p></title><p>Here is some unicode:</p><p>• I hat: Î</p><p>• o umlaut: ö</p><p>• section: §</p><p>• set membership: ∈</p><p>• copyright: ©</p><p>AT&amp;T has an ampersand in their name.</p><p>AT&amp;T is another way to write it.</p><p>This &amp; that.</p><p>4 &lt; 5.</p><p>6 &gt; 5.</p><p>Backslash: \</p><p>Backtick: `</p><p>Asterisk: *</p><p>Underscore: _</p><p>Left brace: {</p><p>Right brace: }</p><p>Left bracket: [</p><p>Right bracket: ]</p><p>Left paren: (</p><p>Right paren: )</p><p>Greater-than: &gt;</p><p>Hash: #</p><p>Period: .</p><p>Bang: !</p><p>Plus: +</p><p>Minus: -</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Links</p></title><section><title><p>Explicit</p></title><p>Just a URL<a l:href="#l3" type="note"><sup>[3]</sup></a>.</p><p>URL and title<a l:href="#l4" type="note"><sup>[4]</sup></a>.</p><p>URL and title<a l:href="#l5" type="note"><sup>[5]</sup></a>.</p><p>URL and title<a l:href="#l6" type="note"><sup>[6]</sup></a>.</p><p>URL and title<a l:href="#l7" type="note"><sup>[7]</sup></a></p><p>URL and title<a l:href="#l8" type="note"><sup>[8]</sup></a></p><p>with_underscore<a l:href="#l9" type="note"><sup>[9]</sup></a></p><p>Email link<a l:href="#l10" type="note"><sup>[10]</sup></a></p><p>Empty<a l:href="#l11" type="note"><sup>[11]</sup></a>.</p></section><section><title><p>Reference</p></title><p>Foo bar<a l:href="#l12" type="note"><sup>[12]</sup></a>.</p><p>Foo bar<a l:href="#l13" type="note"><sup>[13]</sup></a>.</p><p>Foo bar<a l:href="#l14" type="note"><sup>[14]</sup></a>.</p><p>With embedded [brackets]<a l:href="#l15" type="note"><sup>[15]</sup></a>.</p><p>b<a l:href="#l16" type="note"><sup>[16]</sup></a> by itself should be a link.</p><p>Indented once<a l:href="#l17" type="note"><sup>[17]</sup></a>.</p><p>Indented twice<a l:href="#l18" type="note"><sup>[18]</sup></a>.</p><p>Indented thrice<a l:href="#l19" type="note"><sup>[19]</sup></a>.</p><p>This should [not][] be a link.</p><empty-line /><p><code>[not]: /url</code></p><empty-line /><p>Foo bar<a l:href="#l20" type="note"><sup>[20]</sup></a>.</p><p>Foo biz<a l:href="#l21" type="note"><sup>[21]</sup></a>.</p></section><section><title><p>With ampersands</p></title><p>Here’s a link with an ampersand in the URL<a l:href="#l22" type="note"><sup>[22]</sup></a>.</p><p>Here’s a link with an amersand in the link text: AT&amp;T<a l:href="#l23" type="note"><sup>[23]</sup></a>.</p><p>Here’s an inline link<a l:href="#l24" type="note"><sup>[24]</sup></a>.</p><p>Here’s an inline link in pointy braces<a l:href="#l25" type="note"><sup>[25]</sup></a>.</p></section><section><title><p>Autolinks</p></title><p>With an ampersand: <code>http://example.com/?foo=1&amp;bar=2</code><a l:href="#l26" type="note"><sup>[26]</sup></a></p><p>• In a list?</p><p>• <code>http://example.com/</code><a l:href="#l27" type="note"><sup>[27]</sup></a></p><p>• It should.</p><p>An e-mail address: <code>nobody@nowhere.net</code><a l:href="#l28" type="note"><sup>[28]</sup></a></p><cite><p>Blockquoted: <code>http://example.com/</code><a l:href="#l29" type="note"><sup>[29]</sup></a></p></cite><p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p><empty-line /><p><code>or here: &lt;http://example.com/&gt;</code></p><empty-line /><empty-line /><p>——————————</p><empty-line /></section></section><section><title><p>Images</p></title><p>From “Voyage dans la Lune” by Georges Melies (1902):</p><image l:href="#image1" l:type="imageType" alt="lalune" title="Voyage dans la Lune" /><p>Here is a movie <image l:href="#image2" l:type="inlineImageType" alt="movie" /> icon.</p><empty-line /><p>——————————</p><empty-line /></section><section><title><p>Footnotes</p></title><p>Here is a footnote reference,<a l:href="#n30" type="note"><sup>[30]</sup></a> and another.<a l:href="#n31" type="note"><sup>[31]</sup></a> This should <emphasis>not</emphasis> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<a l:href="#n32" type="note"><sup>[32]</sup></a></p><cite><p>Notes can go in quotes.<a l:href="#n33" type="note"><sup>[33]</sup></a></p></cite><p> 1. And in list items.<a l:href="#n34" type="note"><sup>[34]</sup></a></p><p>This paragraph should not be part of the note, as it is not indented.</p></section></body><body name="notes"><section id="l1"><title><p>1</p></title><p><code>/url</code></p></section><section id="l2"><title><p>2</p></title><p><code>http://example.com/?foo=1&amp;bar=2</code></p></section><section id="l3"><title><p>3</p></title><p><code>/url/</code></p></section><section id="l4"><title><p>4</p></title><p>title: <code>/url/</code></p></section><section id="l5"><title><p>5</p></title><p>title preceded by two spaces: <code>/url/</code></p></section><section id="l6"><title><p>6</p></title><p>title preceded by a tab: <code>/url/</code></p></section><section id="l7"><title><p>7</p></title><p>title with &quot;quotes&quot; in it: <code>/url/</code></p></section><section id="l8"><title><p>8</p></title><p>title with single quotes: <code>/url/</code></p></section><section id="l9"><title><p>9</p></title><p><code>/url/with_underscore</code></p></section><section id="l10"><title><p>10</p></title><p><code>mailto:nobody@nowhere.net</code></p></section><section id="l11"><title><p>11</p></title><p><code></code></p></section><section id="l12"><title><p>12</p></title><p><code>/url/</code></p></section><section id="l13"><title><p>13</p></title><p><code>/url/</code></p></section><section id="l14"><title><p>14</p></title><p><code>/url/</code></p></section><section id="l15"><title><p>15</p></title><p><code>/url/</code></p></section><section id="l16"><title><p>16</p></title><p><code>/url/</code></p></section><section id="l17"><title><p>17</p></title><p><code>/url</code></p></section><section id="l18"><title><p>18</p></title><p><code>/url</code></p></section><section id="l19"><title><p>19</p></title><p><code>/url</code></p></section><section id="l20"><title><p>20</p></title><p>Title with &quot;quotes&quot; inside: <code>/url/</code></p></section><section id="l21"><title><p>21</p></title><p>Title with &quot;quote&quot; inside: <code>/url/</code></p></section><section id="l22"><title><p>22</p></title><p><code>http://example.com/?foo=1&amp;bar=2</code></p></section><section id="l23"><title><p>23</p></title><p>AT&amp;T: <code>http://att.com/</code></p></section><section id="l24"><title><p>24</p></title><p><code>/script?foo=1&amp;bar=2</code></p></section><section id="l25"><title><p>25</p></title><p><code>/script?foo=1&amp;bar=2</code></p></section><section id="l26"><title><p>26</p></title><p><code>http://example.com/?foo=1&amp;bar=2</code></p></section><section id="l27"><title><p>27</p></title><p><code>http://example.com/</code></p></section><section id="l28"><title><p>28</p></title><p><code>mailto:nobody@nowhere.net</code></p></section><section id="l29"><title><p>29</p></title><p><code>http://example.com/</code></p></section><section id="n30"><title><p>30</p></title><p>Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.</p></section><section id="n31"><title><p>31</p></title><p>Here’s the long note. This one contains multiple blocks.</p><p>Subsequent blocks are indented to show that they belong to the footnote (as with list items).</p><empty-line /><p><code> { &lt;code&gt; }</code></p><empty-line /><p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.</p></section><section id="n32"><title><p>32</p></title><p>This is <emphasis>easier</emphasis> to type. Inline notes may contain links<a l:href="#l32" type="note"><sup>[32]</sup></a> and <code>]</code> verbatim characters, as well as [bracketed text].</p></section><section id="n33"><title><p>33</p></title><p>In quote.</p></section><section id="n34"><title><p>34</p></title><p>In list.</p></section></body><binary id="image2" content-type="image/jpeg">/9j/4AAQSkZJRgABAQEASABIAAD//gBQVGhpcyBhcnQgaXMgaW4gdGhlIHB1YmxpYyBkb21haW4uIEtldmluIEh1Z2hlcywga2V2aW5oQGVpdC5jb20sIFNlcHRlbWJlciAxOTk1/9sAQwABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/9sAQwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/8AAEQgAFgAUAwEiAAIRAQMRAf/EABoAAQACAwEAAAAAAAAAAAAAAAAICQUGCgf/xAAjEAABBQEAAwABBQAAAAAAAAAGAwQFBwgCAAEJChEVOXa3/8QAFgEBAQEAAAAAAAAAAAAAAAAABggA/8QAJhEBAAECBQEJAAAAAAAAAAAAAQIAAwQFBhEhszE0NlFUcXR1tP/aAAwDAQACEQMRAD8AqQzziPNmpiqnIO1q4H+WkB84MdlzRSuM82/jVw/JCORtRmQz5d2VTy6WmS2eSYx3U/qkSRbgFsqRzH2Is4/mCluXc33vy8xTnJjTNqV/T8LKmkhr8Hq1da2aOvTfIh2CFeNt+GxFBP8AJFdFUbPWh+4FdXV7OtZOMR7mK9lBWNN+JBmMQ5cwmfH8DEFhTZUCRlE6CBq/ds/nBh9oYygeY1L9FnCUnBSN1t+w0l9bNomx1cllsOrL9OCTKtKOIqua6UVjP0dEvTyM7gp/3whbkAD0ScX3r6MLg+C2/XsMhCnJRn/5cVNHyJHiX6JKIFhhqnFeagm9BIgjfcJyNBTZiROBUk6Mp8CJRmT4NWU2MatV7n495DPk/wAbMJSRJOTBDItq0KR5s/nJN7LPW8AJWtYAoKQaDp+u4XShxgXhYcbHoxNTllCwETGQ8ag2jmDVsk8w/wCOp/C/hn+mWV/utpePH+D5wmF39NY6UakjUYR1Dn0YgRM5zQAAAMdfAA4AOAOArjkMNQ3vgm7UKtBR+m9QHFD5tpnDtpy+t2R20gK/OsmFtuDpaL5mVyiT5qdEVAvZci5ch5VoSGKbwlWTBr0RPoZT07av9lHfrXo6yLApWMugKpPM9SV1cDm65s/wkOHZBojoqiM+6GpMSj4FhtayNAUi5H3LfQBG2KWssFoSPuJdKyMLKtpuLi+e3jwFICUg7CSHsNVlYlKdizOTvKdq3KTsG8pQirsAG6vAB5FdhP490U4gfjxi+DedoqO4YftmKdKNulO26jiOv+2Ga/bftVNFXpHtVHrpLpRFJTpP3z77T469++fTx48e4LueE+NY6UKk7UniLP8A7rNf3X6//9k=</binary><binary id="image1" content-type="image/jpeg">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</binary></FictionBook> \ No newline at end of file
diff --git a/tests/writer.man b/tests/writer.man
index 28bc0feb5..f0a6f348a 100644
--- a/tests/writer.man
+++ b/tests/writer.man
@@ -26,7 +26,7 @@ Here's a regular paragraph.
In Markdown 1.0.0 and earlier.
Version 8.
This line turns into a list item.
-Because a hard-wrapped line in the middle of a paragraph looked like a list
+Because a hard\-wrapped line in the middle of a paragraph looked like a list
item.
.PP
Here's one with a bullet.
@@ -41,7 +41,7 @@ here.
* * * * *
.SH Block Quotes
.PP
-E-mail style:
+E\-mail style:
.RS
.PP
This is a block quote.
@@ -87,7 +87,7 @@ Code:
.IP
.nf
\f[C]
-----\ (should\ be\ four\ hyphens)
+\-\-\-\-\ (should\ be\ four\ hyphens)
sub\ status\ {
\ \ \ \ print\ "working";
@@ -489,7 +489,7 @@ Code block:
.IP
.nf
\f[C]
-<!--\ Comment\ -->
+<!\-\-\ Comment\ \-\->
\f[]
.fi
.PP
@@ -568,11 +568,11 @@ Ellipses\&...and\&...and\&....
.IP \[bu] 2
223
.IP \[bu] 2
-\f[I]p\f[]-Tree
+\f[I]p\f[]\-Tree
.IP \[bu] 2
Here's some display math:
.RS
-$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$
+$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)\-f(x)}{h}$
.RE
.IP \[bu] 2
Here's one that has a line break in it:
@@ -637,7 +637,7 @@ Left paren: (
.PP
Right paren: )
.PP
-Greater-than: >
+Greater\-than: >
.PP
Hash: #
.PP
@@ -647,7 +647,7 @@ Bang: !
.PP
Plus: +
.PP
-Minus: -
+Minus: \-
.PP
* * * * *
.SH Links
@@ -718,13 +718,13 @@ In a list?
.IP \[bu] 2
It should.
.PP
-An e-mail address: <nobody@nowhere.net>
+An e\-mail address: <nobody@nowhere.net>
.RS
.PP
Blockquoted: <http://example.com/>
.RE
.PP
-Auto-links should not occur here: \f[C]<http://example.com/>\f[]
+Auto\-links should not occur here: \f[C]<http://example.com/>\f[]
.IP
.nf
\f[C]
diff --git a/tests/writer.native b/tests/writer.native
index 691c4959a..6393b89d6 100644
--- a/tests/writer.native
+++ b/tests/writer.native
@@ -1,5 +1,5 @@
-Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docAuthors = [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]], docDate = [Str "July",Space,Str "17",Str ",",Space,Str "2006"]})
-[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
+Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docAuthors = [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]], docDate = [Str "July",Space,Str "17,",Space,Str "2006"]})
+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
,HorizontalRule
,Header 1 [Str "Headers"]
,Header 2 [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embedded",Space,Str "link"] ("/url","")]
@@ -14,95 +14,95 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
,HorizontalRule
,Header 1 [Str "Paragraphs"]
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph",Str "."]
-,Para [Str "In",Space,Str "Markdown",Space,Str "1",Str ".",Str "0",Str ".",Str "0",Space,Str "and",Space,Str "earlier",Str ".",Space,Str "Version",Space,Str "8",Str ".",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item",Str ".",Space,Str "Because",Space,Str "a",Space,Str "hard",Str "-",Str "wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item",Str "."]
-,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet",Str ".",Space,Str "*",Space,Str "criminey",Str "."]
-,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here",Str "."]
+,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]
+,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."]
+,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."]
+,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here."]
,HorizontalRule
,Header 1 [Str "Block",Space,Str "Quotes"]
-,Para [Str "E",Str "-",Str "mail",Space,Str "style",Str ":"]
+,Para [Str "E-mail",Space,Str "style:"]
,BlockQuote
- [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote",Str ".",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short",Str "."]]
+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]]
,BlockQuote
- [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote",Str ":"]
+ [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"]
,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}"
- ,Para [Str "A",Space,Str "list",Str ":"]
+ ,Para [Str "A",Space,Str "list:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "item",Space,Str "one"]]
,[Plain [Str "item",Space,Str "two"]]]
- ,Para [Str "Nested",Space,Str "block",Space,Str "quotes",Str ":"]
+ ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"]
,BlockQuote
[Para [Str "nested"]]
,BlockQuote
[Para [Str "nested"]]]
-,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote",Str ":",Space,Str "2",Space,Str ">",Space,Str "1",Str "."]
-,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."]
+,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."]
+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]
,HorizontalRule
,Header 1 [Str "Code",Space,Str "Blocks"]
-,Para [Str "Code",Str ":"]
+,Para [Str "Code:"]
,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab"
-,Para [Str "And",Str ":"]
+,Para [Str "And:"]
,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{"
,HorizontalRule
,Header 1 [Str "Lists"]
,Header 2 [Str "Unordered"]
-,Para [Str "Asterisks",Space,Str "tight",Str ":"]
+,Para [Str "Asterisks",Space,Str "tight:"]
,BulletList
[[Plain [Str "asterisk",Space,Str "1"]]
,[Plain [Str "asterisk",Space,Str "2"]]
,[Plain [Str "asterisk",Space,Str "3"]]]
-,Para [Str "Asterisks",Space,Str "loose",Str ":"]
+,Para [Str "Asterisks",Space,Str "loose:"]
,BulletList
[[Para [Str "asterisk",Space,Str "1"]]
,[Para [Str "asterisk",Space,Str "2"]]
,[Para [Str "asterisk",Space,Str "3"]]]
-,Para [Str "Pluses",Space,Str "tight",Str ":"]
+,Para [Str "Pluses",Space,Str "tight:"]
,BulletList
[[Plain [Str "Plus",Space,Str "1"]]
,[Plain [Str "Plus",Space,Str "2"]]
,[Plain [Str "Plus",Space,Str "3"]]]
-,Para [Str "Pluses",Space,Str "loose",Str ":"]
+,Para [Str "Pluses",Space,Str "loose:"]
,BulletList
[[Para [Str "Plus",Space,Str "1"]]
,[Para [Str "Plus",Space,Str "2"]]
,[Para [Str "Plus",Space,Str "3"]]]
-,Para [Str "Minuses",Space,Str "tight",Str ":"]
+,Para [Str "Minuses",Space,Str "tight:"]
,BulletList
[[Plain [Str "Minus",Space,Str "1"]]
,[Plain [Str "Minus",Space,Str "2"]]
,[Plain [Str "Minus",Space,Str "3"]]]
-,Para [Str "Minuses",Space,Str "loose",Str ":"]
+,Para [Str "Minuses",Space,Str "loose:"]
,BulletList
[[Para [Str "Minus",Space,Str "1"]]
,[Para [Str "Minus",Space,Str "2"]]
,[Para [Str "Minus",Space,Str "3"]]]
,Header 2 [Str "Ordered"]
-,Para [Str "Tight",Str ":"]
+,Para [Str "Tight:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "First"]]
,[Plain [Str "Second"]]
,[Plain [Str "Third"]]]
-,Para [Str "and",Str ":"]
+,Para [Str "and:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "One"]]
,[Plain [Str "Two"]]
,[Plain [Str "Three"]]]
-,Para [Str "Loose",Space,Str "using",Space,Str "tabs",Str ":"]
+,Para [Str "Loose",Space,Str "using",Space,Str "tabs:"]
,OrderedList (1,Decimal,Period)
[[Para [Str "First"]]
,[Para [Str "Second"]]
,[Para [Str "Third"]]]
-,Para [Str "and",Space,Str "using",Space,Str "spaces",Str ":"]
+,Para [Str "and",Space,Str "using",Space,Str "spaces:"]
,OrderedList (1,Decimal,Period)
[[Para [Str "One"]]
,[Para [Str "Two"]]
,[Para [Str "Three"]]]
-,Para [Str "Multiple",Space,Str "paragraphs",Str ":"]
+,Para [Str "Multiple",Space,Str "paragraphs:"]
,OrderedList (1,Decimal,Period)
- [[Para [Str "Item",Space,Str "1",Str ",",Space,Str "graf",Space,Str "one",Str "."]
- ,Para [Str "Item",Space,Str "1",Str ".",Space,Str "graf",Space,Str "two",Str ".",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",Space,Str "back",Str "."]]
- ,[Para [Str "Item",Space,Str "2",Str "."]]
- ,[Para [Str "Item",Space,Str "3",Str "."]]]
+ [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."]
+ ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",Space,Str "back."]]
+ ,[Para [Str "Item",Space,Str "2."]]
+ ,[Para [Str "Item",Space,Str "3."]]]
,Header 2 [Str "Nested"]
,BulletList
[[Plain [Str "Tab"]
@@ -110,19 +110,19 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "Tab"]
,BulletList
[[Plain [Str "Tab"]]]]]]]
-,Para [Str "Here\8217s",Space,Str "another",Str ":"]
+,Para [Str "Here\8217s",Space,Str "another:"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "First"]]
- ,[Plain [Str "Second",Str ":"]
+ ,[Plain [Str "Second:"]
,BulletList
[[Plain [Str "Fee"]]
,[Plain [Str "Fie"]]
,[Plain [Str "Foe"]]]]
,[Plain [Str "Third"]]]
-,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs",Str ":"]
+,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"]
,OrderedList (1,Decimal,Period)
[[Para [Str "First"]]
- ,[Para [Str "Second",Str ":"]
+ ,[Para [Str "Second:"]
,BulletList
[[Plain [Str "Fee"]]
,[Plain [Str "Fie"]]
@@ -141,32 +141,32 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,[Para [Str "and",Space,Str "now",Space,Str "3"]
,Para [Str "with",Space,Str "a",Space,Str "continuation"]
,OrderedList (4,LowerRoman,Period)
- [[Plain [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals",Str ",",Space,Str "starting",Space,Str "with",Space,Str "4"]]
+ [[Plain [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals,",Space,Str "starting",Space,Str "with",Space,Str "4"]]
,[Plain [Str "more",Space,Str "items"]
,OrderedList (1,UpperAlpha,TwoParens)
[[Plain [Str "a",Space,Str "subsublist"]]
,[Plain [Str "a",Space,Str "subsublist"]]]]]]]
-,Para [Str "Nesting",Str ":"]
+,Para [Str "Nesting:"]
,OrderedList (1,UpperAlpha,Period)
[[Plain [Str "Upper",Space,Str "Alpha"]
,OrderedList (1,UpperRoman,Period)
- [[Plain [Str "Upper",Space,Str "Roman",Str "."]
+ [[Plain [Str "Upper",Space,Str "Roman."]
,OrderedList (6,Decimal,TwoParens)
[[Plain [Str "Decimal",Space,Str "start",Space,Str "with",Space,Str "6"]
,OrderedList (3,LowerAlpha,OneParen)
[[Plain [Str "Lower",Space,Str "alpha",Space,Str "with",Space,Str "paren"]]]]]]]]]
-,Para [Str "Autonumbering",Str ":"]
+,Para [Str "Autonumbering:"]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "Autonumber",Str "."]]
- ,[Plain [Str "More",Str "."]
+ [[Plain [Str "Autonumber."]]
+ ,[Plain [Str "More."]
,OrderedList (1,DefaultStyle,DefaultDelim)
- [[Plain [Str "Nested",Str "."]]]]]
-,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item",Str ":"]
-,Para [Str "M.A.\160",Str "2007"]
-,Para [Str "B",Str ".",Space,Str "Williams"]
+ [[Plain [Str "Nested."]]]]]
+,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item:"]
+,Para [Str "M.A.\160\&2007"]
+,Para [Str "B.",Space,Str "Williams"]
,HorizontalRule
,Header 1 [Str "Definition",Space,Str "Lists"]
-,Para [Str "Tight",Space,Str "using",Space,Str "spaces",Str ":"]
+,Para [Str "Tight",Space,Str "using",Space,Str "spaces:"]
,DefinitionList
[([Str "apple"],
[[Plain [Str "red",Space,Str "fruit"]]])
@@ -174,7 +174,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "orange",Space,Str "fruit"]]])
,([Str "banana"],
[[Plain [Str "yellow",Space,Str "fruit"]]])]
-,Para [Str "Tight",Space,Str "using",Space,Str "tabs",Str ":"]
+,Para [Str "Tight",Space,Str "using",Space,Str "tabs:"]
,DefinitionList
[([Str "apple"],
[[Plain [Str "red",Space,Str "fruit"]]])
@@ -182,7 +182,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "orange",Space,Str "fruit"]]])
,([Str "banana"],
[[Plain [Str "yellow",Space,Str "fruit"]]])]
-,Para [Str "Loose",Str ":"]
+,Para [Str "Loose:"]
,DefinitionList
[([Str "apple"],
[[Para [Str "red",Space,Str "fruit"]]])
@@ -190,17 +190,17 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Para [Str "orange",Space,Str "fruit"]]])
,([Str "banana"],
[[Para [Str "yellow",Space,Str "fruit"]]])]
-,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics",Str ":"]
+,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics:"]
,DefinitionList
[([Emph [Str "apple"]],
[[Para [Str "red",Space,Str "fruit"]
- ,Para [Str "contains",Space,Str "seeds",Str ",",Space,Str "crisp",Str ",",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]])
+ ,Para [Str "contains",Space,Str "seeds,",Space,Str "crisp,",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]])
,([Emph [Str "orange"]],
[[Para [Str "orange",Space,Str "fruit"]
,CodeBlock ("",[],[]) "{ orange code block }"
,BlockQuote
[Para [Str "orange",Space,Str "block",Space,Str "quote"]]]])]
-,Para [Str "Multiple",Space,Str "definitions",Str ",",Space,Str "tight",Str ":"]
+,Para [Str "Multiple",Space,Str "definitions,",Space,Str "tight:"]
,DefinitionList
[([Str "apple"],
[[Plain [Str "red",Space,Str "fruit"]]
@@ -208,7 +208,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,([Str "orange"],
[[Plain [Str "orange",Space,Str "fruit"]]
,[Plain [Str "bank"]]])]
-,Para [Str "Multiple",Space,Str "definitions",Str ",",Space,Str "loose",Str ":"]
+,Para [Str "Multiple",Space,Str "definitions,",Space,Str "loose:"]
,DefinitionList
[([Str "apple"],
[[Para [Str "red",Space,Str "fruit"]]
@@ -216,7 +216,7 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,([Str "orange"],
[[Para [Str "orange",Space,Str "fruit"]]
,[Para [Str "bank"]]])]
-,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term",Str ",",Space,Str "indented",Space,Str "marker",Str ",",Space,Str "alternate",Space,Str "markers",Str ":"]
+,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term,",Space,Str "indented",Space,Str "marker,",Space,Str "alternate",Space,Str "markers:"]
,DefinitionList
[([Str "apple"],
[[Para [Str "red",Space,Str "fruit"]]
@@ -227,70 +227,70 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[[Plain [Str "sublist"]]
,[Plain [Str "sublist"]]]]])]
,Header 1 [Str "HTML",Space,Str "Blocks"]
-,Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line",Str ":"]
+,Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line:"]
,RawBlock "html" "<div>"
,Plain [Str "foo"]
,RawBlock "html" "</div>\n"
-,Para [Str "And",Space,Str "nested",Space,Str "without",Space,Str "indentation",Str ":"]
+,Para [Str "And",Space,Str "nested",Space,Str "without",Space,Str "indentation:"]
,RawBlock "html" "<div>\n<div>\n<div>"
,Plain [Str "foo"]
,RawBlock "html" "</div>\n</div>\n<div>"
,Plain [Str "bar"]
,RawBlock "html" "</div>\n</div>\n"
-,Para [Str "Interpreted",Space,Str "markdown",Space,Str "in",Space,Str "a",Space,Str "table",Str ":"]
+,Para [Str "Interpreted",Space,Str "markdown",Space,Str "in",Space,Str "a",Space,Str "table:"]
,RawBlock "html" "<table>\n<tr>\n<td>"
,Plain [Str "This",Space,Str "is",Space,Emph [Str "emphasized"]]
,RawBlock "html" "</td>\n<td>"
,Plain [Str "And",Space,Str "this",Space,Str "is",Space,Strong [Str "strong"]]
,RawBlock "html" "</td>\n</tr>\n</table>\n\n<script type=\"text/javascript\">document.write('This *should not* be interpreted as markdown');</script>\n"
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "simple",Space,Str "block",Str ":"]
+,Para [Str "Here\8217s",Space,Str "a",Space,Str "simple",Space,Str "block:"]
,RawBlock "html" "<div>\n "
,Plain [Str "foo"]
,RawBlock "html" "</div>\n"
-,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "code",Space,Str "block",Str ",",Space,Str "though",Str ":"]
+,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "code",Space,Str "block,",Space,Str "though:"]
,CodeBlock ("",[],[]) "<div>\n foo\n</div>"
-,Para [Str "As",Space,Str "should",Space,Str "this",Str ":"]
+,Para [Str "As",Space,Str "should",Space,Str "this:"]
,CodeBlock ("",[],[]) "<div>foo</div>"
-,Para [Str "Now",Str ",",Space,Str "nested",Str ":"]
+,Para [Str "Now,",Space,Str "nested:"]
,RawBlock "html" "<div>\n <div>\n <div>\n "
,Plain [Str "foo"]
,RawBlock "html" "</div>\n </div>\n</div>\n"
-,Para [Str "This",Space,Str "should",Space,Str "just",Space,Str "be",Space,Str "an",Space,Str "HTML",Space,Str "comment",Str ":"]
+,Para [Str "This",Space,Str "should",Space,Str "just",Space,Str "be",Space,Str "an",Space,Str "HTML",Space,Str "comment:"]
,RawBlock "html" "<!-- Comment -->\n"
-,Para [Str "Multiline",Str ":"]
+,Para [Str "Multiline:"]
,RawBlock "html" "<!--\nBlah\nBlah\n-->\n\n<!--\n This is another comment.\n-->\n"
-,Para [Str "Code",Space,Str "block",Str ":"]
+,Para [Str "Code",Space,Str "block:"]
,CodeBlock ("",[],[]) "<!-- Comment -->"
-,Para [Str "Just",Space,Str "plain",Space,Str "comment",Str ",",Space,Str "with",Space,Str "trailing",Space,Str "spaces",Space,Str "on",Space,Str "the",Space,Str "line",Str ":"]
+,Para [Str "Just",Space,Str "plain",Space,Str "comment,",Space,Str "with",Space,Str "trailing",Space,Str "spaces",Space,Str "on",Space,Str "the",Space,Str "line:"]
,RawBlock "html" "<!-- foo --> \n"
-,Para [Str "Code",Str ":"]
+,Para [Str "Code:"]
,CodeBlock ("",[],[]) "<hr />"
-,Para [Str "Hr\8217s",Str ":"]
+,Para [Str "Hr\8217s:"]
,RawBlock "html" "<hr>\n\n<hr />\n\n<hr />\n\n<hr> \n\n<hr /> \n\n<hr /> \n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\">\n"
,HorizontalRule
,Header 1 [Str "Inline",Space,Str "Markup"]
,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str "."]
,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str "."]
,Para [Str "An",Space,Emph [Link [Str "emphasized",Space,Str "link"] ("/url","")],Str "."]
-,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]]]
-,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Str "."]
-,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]]]
-,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Str "."]
-,Para [Str "This",Space,Str "is",Space,Str "code",Str ":",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "<html>",Str "."]
+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
+,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "<html>",Str "."]
,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "strikeout"],Str "."]]
-,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Emph [Str "hello"]],Space,Str "a",Superscript [Str "hello",Str "\160",Str "there"],Str "."]
-,Para [Str "Subscripts",Str ":",Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Str "\160",Str "of",Str "\160",Str "them"],Str "O",Str "."]
-,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts",Str ",",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",Space,Str "spaces",Str ":",Space,Str "a",Str "^",Str "b",Space,Str "c",Str "^",Str "d",Str ",",Space,Str "a",Str "~",Str "b",Space,Str "c",Str "~",Str "d",Str "."]
+,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Emph [Str "hello"]],Space,Str "a",Superscript [Str "hello\160there"],Str "."]
+,Para [Str "Subscripts:",Space,Str "H",Subscript [Str "2"],Str "O,",Space,Str "H",Subscript [Str "23"],Str "O,",Space,Str "H",Subscript [Str "many\160of\160them"],Str "O."]
+,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts,",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",Space,Str "spaces:",Space,Str "a^b",Space,Str "c^d,",Space,Str "a~b",Space,Str "c~d."]
,HorizontalRule
-,Header 1 [Str "Smart",Space,Str "quotes",Str ",",Space,Str "ellipses",Str ",",Space,Str "dashes"]
-,Para [Quoted DoubleQuote [Str "Hello",Str ","],Space,Str "said",Space,Str "the",Space,Str "spider",Str ".",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",Space,Str "name",Str "."]]
-,Para [Quoted SingleQuote [Str "A"],Str ",",Space,Quoted SingleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted SingleQuote [Str "C"],Space,Str "are",Space,Str "letters",Str "."]
-,Para [Quoted SingleQuote [Str "Oak",Str ","],Space,Quoted SingleQuote [Str "elm",Str ","],Space,Str "and",Space,Quoted SingleQuote [Str "beech"],Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees",Str ".",Space,Str "So",Space,Str "is",Space,Quoted SingleQuote [Str "pine",Str "."]]
-,Para [Quoted SingleQuote [Str "He",Space,Str "said",Str ",",Space,Quoted DoubleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go",Str "."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70\8217s",Str "?"]
+,Header 1 [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]
+,Para [Quoted DoubleQuote [Str "Hello,"],Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",Space,Str "name."]]
+,Para [Quoted SingleQuote [Str "A"],Str ",",Space,Quoted SingleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted SingleQuote [Str "C"],Space,Str "are",Space,Str "letters."]
+,Para [Quoted SingleQuote [Str "Oak,"],Space,Quoted SingleQuote [Str "elm,"],Space,Str "and",Space,Quoted SingleQuote [Str "beech"],Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Quoted SingleQuote [Str "pine."]]
+,Para [Quoted SingleQuote [Str "He",Space,Str "said,",Space,Quoted DoubleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70\8217s?"]
,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Quoted SingleQuote [Code ("",[],[]) "code"],Space,Str "and",Space,Str "a",Space,Quoted DoubleQuote [Link [Str "quoted",Space,Str "link"] ("http://example.com/?foo=1&bar=2","")],Str "."]
-,Para [Str "Some",Space,Str "dashes",Str ":",Space,Str "one",Str "\8212",Str "two",Space,Str "\8212",Space,Str "three",Str "\8212",Str "four",Space,Str "\8212",Space,Str "five",Str "."]
-,Para [Str "Dashes",Space,Str "between",Space,Str "numbers",Str ":",Space,Str "5",Str "\8211",Str "7",Str ",",Space,Str "255",Str "\8211",Str "66",Str ",",Space,Str "1987",Str "\8211",Str "1999",Str "."]
-,Para [Str "Ellipses",Str "\8230",Str "and",Str "\8230",Str "and",Str "\8230",Str "."]
+,Para [Str "Some",Space,Str "dashes:",Space,Str "one\8212two",Space,Str "\8212",Space,Str "three\8212four",Space,Str "\8212",Space,Str "five."]
+,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5\8211\&7,",Space,Str "255\8211\&66,",Space,Str "1987\8211\&1999."]
+,Para [Str "Ellipses\8230and\8230and\8230."]
,HorizontalRule
,Header 1 [Str "LaTeX"]
,BulletList
@@ -299,47 +299,47 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,[Plain [Math InlineMath "x \\in y"]]
,[Plain [Math InlineMath "\\alpha \\wedge \\omega"]]
,[Plain [Math InlineMath "223"]]
- ,[Plain [Math InlineMath "p",Str "-",Str "Tree"]]
- ,[Plain [Str "Here\8217s",Space,Str "some",Space,Str "display",Space,Str "math",Str ":",Space,Math DisplayMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]]
- ,[Plain [Str "Here\8217s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it",Str ":",Space,Math InlineMath "\\alpha + \\omega \\times x^2",Str "."]]]
-,Para [Str "These",Space,Str "shouldn\8217t",Space,Str "be",Space,Str "math",Str ":"]
+ ,[Plain [Math InlineMath "p",Str "-Tree"]]
+ ,[Plain [Str "Here\8217s",Space,Str "some",Space,Str "display",Space,Str "math:",Space,Math DisplayMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]]
+ ,[Plain [Str "Here\8217s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math InlineMath "\\alpha + \\omega \\times x^2",Str "."]]]
+,Para [Str "These",Space,Str "shouldn\8217t",Space,Str "be",Space,Str "math:"]
,BulletList
- [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation",Str ",",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
- ,[Plain [Str "$",Str "22",Str ",",Str "000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$",Str "34",Str ",",Str "000",Str ".",Space,Str "(",Str "It",Space,Str "worked",Space,Str "if",Space,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]]
- ,[Plain [Str "Shoes",Space,Str "(",Str "$",Str "20",Str ")",Space,Str "and",Space,Str "socks",Space,Str "(",Str "$",Str "5",Str ")",Str "."]]
- ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$",Str "73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23",Str "$",Str "."]]]
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table",Str ":"]
+ [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
+ ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized.)"]]
+ ,[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 "latex" "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}"
,HorizontalRule
,Header 1 [Str "Special",Space,Str "Characters"]
-,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode",Str ":"]
+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
,BulletList
- [[Plain [Str "I",Space,Str "hat",Str ":",Space,Str "\206"]]
- ,[Plain [Str "o",Space,Str "umlaut",Str ":",Space,Str "\246"]]
- ,[Plain [Str "section",Str ":",Space,Str "\167"]]
- ,[Plain [Str "set",Space,Str "membership",Str ":",Space,Str "\8712"]]
- ,[Plain [Str "copyright",Str ":",Space,Str "\169"]]]
-,Para [Str "AT",Str "&",Str "T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
-,Para [Str "AT",Str "&",Str "T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
-,Para [Str "This",Space,Str "&",Space,Str "that",Str "."]
-,Para [Str "4",Space,Str "<",Space,Str "5",Str "."]
-,Para [Str "6",Space,Str ">",Space,Str "5",Str "."]
-,Para [Str "Backslash",Str ":",Space,Str "\\"]
-,Para [Str "Backtick",Str ":",Space,Str "`"]
-,Para [Str "Asterisk",Str ":",Space,Str "*"]
-,Para [Str "Underscore",Str ":",Space,Str "_"]
-,Para [Str "Left",Space,Str "brace",Str ":",Space,Str "{"]
-,Para [Str "Right",Space,Str "brace",Str ":",Space,Str "}"]
-,Para [Str "Left",Space,Str "bracket",Str ":",Space,Str "["]
-,Para [Str "Right",Space,Str "bracket",Str ":",Space,Str "]"]
-,Para [Str "Left",Space,Str "paren",Str ":",Space,Str "("]
-,Para [Str "Right",Space,Str "paren",Str ":",Space,Str ")"]
-,Para [Str "Greater",Str "-",Str "than",Str ":",Space,Str ">"]
-,Para [Str "Hash",Str ":",Space,Str "#"]
-,Para [Str "Period",Str ":",Space,Str "."]
-,Para [Str "Bang",Str ":",Space,Str "!"]
-,Para [Str "Plus",Str ":",Space,Str "+"]
-,Para [Str "Minus",Str ":",Space,Str "-"]
+ [[Plain [Str "I",Space,Str "hat:",Space,Str "\206"]]
+ ,[Plain [Str "o",Space,Str "umlaut:",Space,Str "\246"]]
+ ,[Plain [Str "section:",Space,Str "\167"]]
+ ,[Plain [Str "set",Space,Str "membership:",Space,Str "\8712"]]
+ ,[Plain [Str "copyright:",Space,Str "\169"]]]
+,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."]
+,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."]
+,Para [Str "This",Space,Str "&",Space,Str "that."]
+,Para [Str "4",Space,Str "<",Space,Str "5."]
+,Para [Str "6",Space,Str ">",Space,Str "5."]
+,Para [Str "Backslash:",Space,Str "\\"]
+,Para [Str "Backtick:",Space,Str "`"]
+,Para [Str "Asterisk:",Space,Str "*"]
+,Para [Str "Underscore:",Space,Str "_"]
+,Para [Str "Left",Space,Str "brace:",Space,Str "{"]
+,Para [Str "Right",Space,Str "brace:",Space,Str "}"]
+,Para [Str "Left",Space,Str "bracket:",Space,Str "["]
+,Para [Str "Right",Space,Str "bracket:",Space,Str "]"]
+,Para [Str "Left",Space,Str "paren:",Space,Str "("]
+,Para [Str "Right",Space,Str "paren:",Space,Str ")"]
+,Para [Str "Greater-than:",Space,Str ">"]
+,Para [Str "Hash:",Space,Str "#"]
+,Para [Str "Period:",Space,Str "."]
+,Para [Str "Bang:",Space,Str "!"]
+,Para [Str "Plus:",Space,Str "+"]
+,Para [Str "Minus:",Space,Str "-"]
,HorizontalRule
,Header 1 [Str "Links"]
,Header 2 [Str "Explicit"]
@@ -349,48 +349,48 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."]
,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")]
,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with single quotes")]
-,Para [Link [Str "with",Str "_",Str "underscore"] ("/url/with_underscore","")]
+,Para [Link [Str "with_underscore"] ("/url/with_underscore","")]
,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")]
,Para [Link [Str "Empty"] ("",""),Str "."]
,Header 2 [Str "Reference"]
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
-,Para [Str "With",Space,Link [Str "embedded",Space,Str "[",Str "brackets",Str "]"] ("/url/",""),Str "."]
-,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link",Str "."]
+,Para [Str "With",Space,Link [Str "embedded",Space,Str "[brackets]"] ("/url/",""),Str "."]
+,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."]
,Para [Str "Indented",Space,Link [Str "once"] ("/url",""),Str "."]
,Para [Str "Indented",Space,Link [Str "twice"] ("/url",""),Str "."]
,Para [Str "Indented",Space,Link [Str "thrice"] ("/url",""),Str "."]
-,Para [Str "This",Space,Str "should",Space,Str "[",Str "not",Str "]",Str "[",Str "]",Space,Str "be",Space,Str "a",Space,Str "link",Str "."]
+,Para [Str "This",Space,Str "should",Space,Str "[not][]",Space,Str "be",Space,Str "a",Space,Str "link."]
,CodeBlock ("",[],[]) "[not]: /url"
,Para [Str "Foo",Space,Link [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."]
,Para [Str "Foo",Space,Link [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."]
,Header 2 [Str "With",Space,Str "ampersands"]
,Para [Str "Here\8217s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]
-,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text",Str ":",Space,Link [Str "AT",Str "&",Str "T"] ("http://att.com/","AT&T"),Str "."]
+,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] ("http://att.com/","AT&T"),Str "."]
,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 [Str "Autolinks"]
-,Para [Str "With",Space,Str "an",Space,Str "ampersand",Str ":",Space,Link [Code ("",["url"],[]) "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 [Code ("",["url"],[]) "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
,BulletList
- [[Plain [Str "In",Space,Str "a",Space,Str "list",Str "?"]]
+ [[Plain [Str "In",Space,Str "a",Space,Str "list?"]]
,[Plain [Link [Code ("",["url"],[]) "http://example.com/"] ("http://example.com/","")]]
- ,[Plain [Str "It",Space,Str "should",Str "."]]]
-,Para [Str "An",Space,Str "e",Str "-",Str "mail",Space,Str "address",Str ":",Space,Link [Code ("",["url"],[]) "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
+ ,[Plain [Str "It",Space,Str "should."]]]
+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link [Code ("",["url"],[]) "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]
,BlockQuote
- [Para [Str "Blockquoted",Str ":",Space,Link [Code ("",["url"],[]) "http://example.com/"] ("http://example.com/","")]]
-,Para [Str "Auto",Str "-",Str "links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here",Str ":",Space,Code ("",[],[]) "<http://example.com/>"]
+ [Para [Str "Blockquoted:",Space,Link [Code ("",["url"],[]) "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
,Header 1 [Str "Images"]
-,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(",Str "1902",Str ")",Str ":"]
+,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]
,Para [Image [Str "lalune"] ("lalune.jpg","Voyage dans la Lune")]
-,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon",Str "."]
+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon."]
,HorizontalRule
,Header 1 [Str "Footnotes"]
-,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference",Str ",",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote",Str ".",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference",Str ".",Space,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document",Str "."]],Space,Str "and",Space,Str "another",Str ".",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note",Str ".",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks",Str "."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",Space,Str "footnote",Space,Str "(",Str "as",Space,Str "with",Space,Str "list",Space,Str "items",Str ")",Str "."],CodeBlock ("",[],[]) " { <code> }",Para [Str "If",Space,Str "you",Space,Str "want",Str ",",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line",Str ",",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",Space,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block",Str "."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference",Str ",",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space",Str ".",Str "[",Str "^",Str "my",Space,Str "note",Str "]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note",Str ".",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type",Str ".",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",Space,Link [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",Space,Str "verbatim",Space,Str "characters",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[",Str "bracketed",Space,Str "text",Str "]",Str "."]]]
+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference.",Space,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document."]],Space,Str "and",Space,Str "another.",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "list",Space,Str "items)."],CodeBlock ("",[],[]) " { <code> }",Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line,",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",Space,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space.[^my",Space,Str "note]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note.",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type.",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",Space,Link [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",Space,Str "verbatim",Space,Str "characters,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[bracketed",Space,Str "text]."]]]
,BlockQuote
- [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes",Str ".",Note [Para [Str "In",Space,Str "quote",Str "."]]]]
+ [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes.",Note [Para [Str "In",Space,Str "quote."]]]]
,OrderedList (1,Decimal,Period)
- [[Plain [Str "And",Space,Str "in",Space,Str "list",Space,Str "items",Str ".",Note [Para [Str "In",Space,Str "list",Str "."]]]]]
-,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note",Str ",",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented",Str "."]]
+ [[Plain [Str "And",Space,Str "in",Space,Str "list",Space,Str "items.",Note [Para [Str "In",Space,Str "list."]]]]]
+,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented."]]
diff --git a/tests/writer.opendocument b/tests/writer.opendocument
index 587c16502..3ca4a3564 100644
--- a/tests/writer.opendocument
+++ b/tests/writer.opendocument
@@ -665,27 +665,27 @@
<style:style style:name="T35" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>
<style:style style:name="T36" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>
<style:style style:name="T37" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>
- <style:style style:name="T38" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>
- <style:style style:name="T39" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>
+ <style:style style:name="T38" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
+ <style:style style:name="T39" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
<style:style style:name="T40" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
<style:style style:name="T41" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
- <style:style style:name="T42" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
+ <style:style style:name="T42" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style>
<style:style style:name="T43" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
- <style:style style:name="T44" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style>
- <style:style style:name="T45" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>
+ <style:style style:name="T44" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
+ <style:style style:name="T45" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style>
<style:style style:name="T46" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
- <style:style style:name="T47" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style>
- <style:style style:name="T48" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
- <style:style style:name="T49" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
- <style:style style:name="T50" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
- <style:style style:name="T51" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T52" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T53" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T54" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T55" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T56" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T57" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T58" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T47" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
+ <style:style style:name="T48" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
+ <style:style style:name="T49" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
+ <style:style style:name="T50" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T51" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T52" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T53" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T54" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T55" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T56" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T57" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
+ <style:style style:name="T58" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
<style:style style:name="T59" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="T60" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="T61" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
@@ -693,17 +693,9 @@
<style:style style:name="T63" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="T64" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="T65" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T66" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
+ <style:style style:name="T66" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="T67" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="T68" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T69" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T70" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T71" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T72" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T73" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T74" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T75" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
- <style:style style:name="T76" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Quotations">
<style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />
</style:style>
@@ -1342,33 +1334,33 @@ Markup</text:h>
</text:span><text:span text:style-name="T20">is</text:span><text:span text:style-name="T21">
</text:span><text:span text:style-name="T22">strong</text:span><text:span text:style-name="T23">
</text:span><text:span text:style-name="T24">and</text:span><text:span text:style-name="T25">
-</text:span><text:span text:style-name="T26">em</text:span><text:span text:style-name="T27">.</text:span></text:p>
+</text:span><text:span text:style-name="T26">em.</text:span></text:p>
<text:p text:style-name="Text_20_body">So is
-<text:span text:style-name="T28">this</text:span> word.</text:p>
-<text:p text:style-name="Text_20_body"><text:span text:style-name="T29">This</text:span><text:span text:style-name="T30">
-</text:span><text:span text:style-name="T31">is</text:span><text:span text:style-name="T32">
-</text:span><text:span text:style-name="T33">strong</text:span><text:span text:style-name="T34">
-</text:span><text:span text:style-name="T35">and</text:span><text:span text:style-name="T36">
-</text:span><text:span text:style-name="T37">em</text:span><text:span text:style-name="T38">.</text:span></text:p>
+<text:span text:style-name="T27">this</text:span> word.</text:p>
+<text:p text:style-name="Text_20_body"><text:span text:style-name="T28">This</text:span><text:span text:style-name="T29">
+</text:span><text:span text:style-name="T30">is</text:span><text:span text:style-name="T31">
+</text:span><text:span text:style-name="T32">strong</text:span><text:span text:style-name="T33">
+</text:span><text:span text:style-name="T34">and</text:span><text:span text:style-name="T35">
+</text:span><text:span text:style-name="T36">em.</text:span></text:p>
<text:p text:style-name="Text_20_body">So is
-<text:span text:style-name="T39">this</text:span> word.</text:p>
+<text:span text:style-name="T37">this</text:span> word.</text:p>
<text:p text:style-name="Text_20_body">This is code:
<text:span text:style-name="Teletype">&gt;</text:span>,
<text:span text:style-name="Teletype">$</text:span>,
<text:span text:style-name="Teletype">\</text:span>,
<text:span text:style-name="Teletype">\$</text:span>,
<text:span text:style-name="Teletype">&lt;html&gt;</text:span>.</text:p>
-<text:p text:style-name="Text_20_body"><text:span text:style-name="T40">This</text:span><text:span text:style-name="T41">
-</text:span><text:span text:style-name="T42">is</text:span><text:span text:style-name="T43">
-</text:span><text:span text:style-name="T44">strikeout</text:span><text:span text:style-name="T45">.</text:span></text:p>
+<text:p text:style-name="Text_20_body"><text:span text:style-name="T38">This</text:span><text:span text:style-name="T39">
+</text:span><text:span text:style-name="T40">is</text:span><text:span text:style-name="T41">
+</text:span><text:span text:style-name="T42">strikeout</text:span><text:span text:style-name="T43">.</text:span></text:p>
<text:p text:style-name="Text_20_body">Superscripts:
-a<text:span text:style-name="T46">bc</text:span>d
-a<text:span text:style-name="T47">hello</text:span>
-a<text:span text:style-name="T48">hello</text:span><text:span text:style-name="T49"> </text:span><text:span text:style-name="T50">there</text:span>.</text:p>
+a<text:span text:style-name="T44">bc</text:span>d
+a<text:span text:style-name="T45">hello</text:span>
+a<text:span text:style-name="T46">hello there</text:span>.</text:p>
<text:p text:style-name="Text_20_body">Subscripts:
-H<text:span text:style-name="T51">2</text:span>O,
-H<text:span text:style-name="T52">23</text:span>O,
-H<text:span text:style-name="T53">many</text:span><text:span text:style-name="T54"> </text:span><text:span text:style-name="T55">of</text:span><text:span text:style-name="T56"> </text:span><text:span text:style-name="T57">them</text:span>O.</text:p>
+H<text:span text:style-name="T47">2</text:span>O,
+H<text:span text:style-name="T48">23</text:span>O,
+H<text:span text:style-name="T49">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" />
@@ -1400,16 +1392,16 @@ five.</text:p>
<text:p text:style-name="P51">2 + 2 = 4</text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51"><text:span text:style-name="T58">x</text:span> ∈ <text:span text:style-name="T59">y</text:span></text:p>
+ <text:p text:style-name="P51"><text:span text:style-name="T50">x</text:span> ∈ <text:span text:style-name="T51">y</text:span></text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51"><text:span text:style-name="T60">α</text:span> ∧ <text:span text:style-name="T61">ω</text:span></text:p>
+ <text:p text:style-name="P51"><text:span text:style-name="T52">α</text:span> ∧ <text:span text:style-name="T53">ω</text:span></text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="P51">223</text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51"><text:span text:style-name="T62">p</text:span>-Tree</text:p>
+ <text:p text:style-name="P51"><text:span text:style-name="T54">p</text:span>-Tree</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="P51">Here’s some display math:
@@ -1417,7 +1409,7 @@ five.</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="P51">Here’s one that has a line break in it:
- <text:span text:style-name="T63">α</text:span> + <text:span text:style-name="T64">ω</text:span> × <text:span text:style-name="T65">x</text:span><text:span text:style-name="T66">2</text:span>.</text:p>
+ <text:span text:style-name="T55">α</text:span> + <text:span text:style-name="T56">ω</text:span> × <text:span text:style-name="T57">x</text:span><text:span text:style-name="T58">2</text:span>.</text:p>
</text:list-item>
</text:list>
<text:p text:style-name="First_20_paragraph">These shouldn’t be math:</text:p>
@@ -1428,7 +1420,7 @@ five.</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="P52">$22,000 is a
- <text:span text:style-name="T67">lot</text:span> of money. So is $34,000.
+ <text:span text:style-name="T59">lot</text:span> of money. So is $34,000.
(It worked if “lot” is emphasized.)</text:p>
</text:list-item>
<text:list-item>
@@ -1437,10 +1429,10 @@ five.</text:p>
<text:list-item>
<text:p text:style-name="P52">Escaped
<text:span text:style-name="Teletype">$</text:span>: $73
- <text:span text:style-name="T68">this</text:span><text:span text:style-name="T69">
- </text:span><text:span text:style-name="T70">should</text:span><text:span text:style-name="T71">
- </text:span><text:span text:style-name="T72">be</text:span><text:span text:style-name="T73">
- </text:span><text:span text:style-name="T74">emphasized</text:span>
+ <text:span text:style-name="T60">this</text:span><text:span text:style-name="T61">
+ </text:span><text:span text:style-name="T62">should</text:span><text:span text:style-name="T63">
+ </text:span><text:span text:style-name="T64">be</text:span><text:span text:style-name="T65">
+ </text:span><text:span text:style-name="T66">emphasized</text:span>
23$.</text:p>
</text:list-item>
</text:list>
@@ -1589,10 +1581,10 @@ indented to show that they belong to the footnote (as with list
items).</text:p><text:p text:style-name="P58"><text:s text:c="2" />{ &lt;code&gt; }</text:p><text:p text:style-name="Footnote">If
you want, you can indent every line, but you can also be lazy and just indent
the first line of each block.</text:p></text:note-body></text:note> This
-should <text:span text:style-name="T75">not</text:span> be a footnote
+should <text:span text:style-name="T67">not</text:span> be a footnote
reference, because it contains a space.[^my note] Here is an inline
note.<text:note text:id="ftn2" text:note-class="footnote"><text:note-citation>3</text:note-citation><text:note-body><text:p text:style-name="Footnote">This
-is <text:span text:style-name="T76">easier</text:span> to type. Inline notes
+is <text:span text:style-name="T68">easier</text:span> to type. Inline notes
may contain
<text:a xlink:type="simple" xlink:href="http://google.com" office:name=""><text:span text:style-name="Definition">links</text:span></text:a>
and <text:span text:style-name="Teletype">]</text:span> verbatim characters,
diff --git a/windows/pandoc-setup.iss b/windows/pandoc-setup.iss
index 6ec6487e3..712cf4f0d 100644
--- a/windows/pandoc-setup.iss
+++ b/windows/pandoc-setup.iss
@@ -9,7 +9,7 @@ AppId={{3CEE7B38-B19D-4980-9CAD-DF53600BD4CA}
; Version 5.1 is XP
MinVersion=5.1,5.1
AppName=Pandoc
-AppVerName=Pandoc 1.9.4.2
+AppVerName=Pandoc 1.10
AppPublisher=John MacFarlane
AppPublisherURL=http://johnmacfarlane.net/pandoc/
AppSupportURL=http://johnmacfarlane.net/pandoc/