summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL13
-rw-r--r--README282
-rw-r--r--changelog166
-rw-r--r--epub.css11
-rw-r--r--man/man1/pandoc.1.md73
-rw-r--r--markdown2pdf136
-rw-r--r--pandoc.cabal106
-rw-r--r--slidy/slidy.min.css1
-rw-r--r--slidy/slidy.min.js1
-rw-r--r--src/Text/Pandoc.hs12
-rw-r--r--src/Text/Pandoc/Definition.hs19
-rw-r--r--src/Text/Pandoc/ODT.hs102
-rw-r--r--src/Text/Pandoc/Parsing.hs700
-rw-r--r--src/Text/Pandoc/Readers/HTML.hs84
-rw-r--r--src/Text/Pandoc/Readers/LaTeX.hs39
-rw-r--r--src/Text/Pandoc/Readers/Markdown.hs127
-rw-r--r--src/Text/Pandoc/Readers/RST.hs178
-rw-r--r--src/Text/Pandoc/Readers/TeXMath.hs253
-rw-r--r--src/Text/Pandoc/S5.hs57
-rw-r--r--src/Text/Pandoc/Shared.hs668
-rw-r--r--src/Text/Pandoc/Templates.hs3
-rw-r--r--src/Text/Pandoc/UTF8.hs72
-rw-r--r--src/Text/Pandoc/UUID.hs77
-rw-r--r--src/Text/Pandoc/Writers/ConTeXt.hs3
-rw-r--r--src/Text/Pandoc/Writers/Docbook.hs1
-rw-r--r--src/Text/Pandoc/Writers/EPUB.hs283
-rw-r--r--src/Text/Pandoc/Writers/HTML.hs84
-rw-r--r--src/Text/Pandoc/Writers/LaTeX.hs2
-rw-r--r--src/Text/Pandoc/Writers/Man.hs17
-rw-r--r--src/Text/Pandoc/Writers/Markdown.hs33
-rw-r--r--src/Text/Pandoc/Writers/Native.hs86
-rw-r--r--src/Text/Pandoc/Writers/ODT.hs83
-rw-r--r--src/Text/Pandoc/Writers/RST.hs32
-rw-r--r--src/Text/Pandoc/Writers/S5.hs136
-rw-r--r--src/Text/Pandoc/Writers/Texinfo.hs1
-rw-r--r--src/markdown2pdf.hs26
-rw-r--r--src/pandoc.hs210
-rw-r--r--templates/docbook.template1
-rw-r--r--templates/html.template29
-rw-r--r--templates/latex.template11
-rw-r--r--templates/s5.template69
-rw-r--r--templates/slidy.template66
-rw-r--r--tests/RunTests.hs15
-rw-r--r--tests/html-reader.native1
-rw-r--r--tests/latex-reader.native1
-rw-r--r--tests/lhs-test.fragment.html+lhs88
-rw-r--r--tests/lhs-test.html117
-rw-r--r--tests/lhs-test.html+lhs123
-rw-r--r--tests/lhs-test.latex3
-rw-r--r--tests/lhs-test.latex+lhs3
-rw-r--r--tests/lhs-test.markdown3
-rw-r--r--tests/lhs-test.markdown+lhs3
-rw-r--r--tests/lhs-test.native1
-rw-r--r--tests/lhs-test.rst2
-rw-r--r--tests/lhs-test.rst+lhs2
-rw-r--r--tests/markdown-reader-more.native11
-rw-r--r--tests/markdown-reader-more.txt9
-rw-r--r--tests/rst-reader.native1
-rw-r--r--tests/s5.basic.html314
-rw-r--r--tests/s5.fancy.html294
-rw-r--r--tests/s5.fragment.html60
-rw-r--r--tests/s5.inserts.html61
-rw-r--r--tests/tables-rstsubset.native1
-rw-r--r--tests/tables.docbook2
-rw-r--r--tests/tables.html2
-rw-r--r--tests/tables.latex1
-rw-r--r--tests/tables.markdown9
-rw-r--r--tests/tables.mediawiki1
-rw-r--r--tests/tables.native1
-rw-r--r--tests/tables.opendocument2
-rw-r--r--tests/tables.plain9
-rw-r--r--tests/tables.rst2
-rw-r--r--tests/tables.rtf1
-rw-r--r--tests/tables.texinfo1
-rw-r--r--tests/tables.txt8
-rw-r--r--tests/testsuite.native1
-rw-r--r--tests/writer.context1
-rw-r--r--tests/writer.docbook12
-rw-r--r--tests/writer.html2007
-rw-r--r--tests/writer.latex12
-rw-r--r--tests/writer.man142
-rw-r--r--tests/writer.markdown57
-rw-r--r--tests/writer.mediawiki1
-rw-r--r--tests/writer.native1
-rw-r--r--tests/writer.opendocument38
-rw-r--r--tests/writer.plain55
-rw-r--r--tests/writer.rst56
-rw-r--r--tests/writer.rtf11
-rw-r--r--tests/writer.texinfo1
89 files changed, 3988 insertions, 3912 deletions
diff --git a/INSTALL b/INSTALL
index 51b5e4c01..f405e2c4a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -68,19 +68,20 @@ you will need [zip-archive] and (if you want syntax highlighting)
preceded by a `-` (to force the flag to `false`), and separated
by spaces. Pandoc's flags include:
- - `library`: build the library (default yes)
- `executable`: build the pandoc executable (default yes)
- - `wrappers`: build the wrappers `markdown2pdf` and `hsmarkdown`
- (default yes)
+ - `library`: build the pandoc library (default yes)
+ - `wrappers`: build the wrapper `markdown2pdf` (default yes)
- `highlighting`: compile with syntax highlighting support (increases
the size of the executable) (default no)
+ - `citeproc`: compile with bibliographic support using `citeproc-hs`
+ (default no)
So, for example,
- --flags="-library highlighting"
+ --flags="-executable -wrappers highlighting"
- tells Cabal to build the executable but not the library, and to
- compile with syntax highlighting support.
+ tells Cabal to build the library but not the executables,
+ and to compile with syntax highlighting support.
3. Build:
diff --git a/README b/README
index 3040e2ddf..47f9456ea 100644
--- a/README
+++ b/README
@@ -7,7 +7,9 @@ another, and a command-line tool that uses this library. It can read
[markdown] and (subsets of) [reStructuredText], [HTML], and [LaTeX]; and
it can write plain text, [markdown], [reStructuredText], [HTML], [LaTeX],
[ConTeXt], [RTF], [DocBook XML], [OpenDocument XML], [ODT], [GNU Texinfo],
-[MediaWiki markup], [groff man] pages, and [S5] HTML slide shows.
+[MediaWiki markup], [EPUB], [groff man] pages, and [Slidy] or [S5]
+HTML slide shows.
+
Pandoc's enhanced version of markdown includes syntax for footnotes,
tables, flexible ordered lists, definition lists, delimited code blocks,
superscript, subscript, strikeout, title blocks, automatic tables of
@@ -25,6 +27,7 @@ or output format requires only adding a reader or writer.
[markdown]: http://daringfireball.net/projects/markdown/
[reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html
[S5]: http://meyerweb.com/eric/tools/s5/
+[Slidy]: http://www.w3.org/Talks/Tools/Slidy/
[HTML]: http://www.w3.org/TR/html40/
[LaTeX]: http://www.latex-project.org/
[ConTeXt]: http://www.pragma-ade.nl/
@@ -36,6 +39,7 @@ or output format requires only adding a reader or writer.
[groff man]: http://developer.apple.com/DOCUMENTATION/Darwin/Reference/ManPages/man7/groff_man.7.html
[Haskell]: http://www.haskell.org/
[GNU Texinfo]: http://www.gnu.org/software/texinfo/
+[EPUB]: http://www.idpf.org/
© 2006-2010 John MacFarlane (jgm at berkeley dot edu). Released under the
[GPL], version 2 or greater. This software carries no warranty of
@@ -56,8 +60,8 @@ If you want to write to a file, use the `-o` option:
pandoc -o hello.html hello.txt
-[^1]: The exception is for `odt`. Since this is a binary output format,
- an output file must be specified explicitly.
+[^1]: The exceptions are for `odt` and `epub`. Since these are
+ a binary output formats, an output file must be specified explicitly.
Note that you can specify multiple input files on the command line.
`pandoc` will concatenate them all (with blank lines between them)
@@ -90,8 +94,9 @@ Supported output formats include `markdown`, `latex`, `context`
(ConTeXt), `html`, `rtf` (rich text format), `rst`
(reStructuredText), `docbook` (DocBook XML), `opendocument`
(OpenDocument XML), `odt` (OpenOffice text document), `texinfo`, (GNU
-Texinfo), `mediawiki` (MediaWiki markup), `man` (groff man), and `s5`
-(which produces an HTML file that acts like powerpoint).
+Texinfo), `mediawiki` (MediaWiki markup), `epub` (EPUB ebook),
+`man` (groff man), `slidy` (slidy HTML and javascript slide show), or
+`s5` (S5 HTML and javascript slide show).
Supported input formats include `markdown`, `html`, `latex`, and `rst`.
Note that the `rst` reader only parses a subset of reStructuredText
@@ -116,9 +121,7 @@ Character encodings
-------------------
All input is assumed to be in the UTF-8 encoding, and all output
-is in UTF-8 (unless your version of pandoc was compiled using
-GHC 6.12 or higher, in which case the local encoding will be used).
-If your local character encoding is not UTF-8 and you use
+is in UTF-8. If your local character encoding is not UTF-8 and you use
accented or foreign characters, you should pipe the input and output
through [`iconv`]. For example,
@@ -191,7 +194,7 @@ For further documentation, see the `pandoc(1)` man page.
`-t`, `--to`, `-w`, or `--write` *format*
: specifies the output format -- the format Pandoc will
- be converting *to*. *format* can be `native`, `html`, `s5`,
+ be converting *to*. *format* can be `native`, `html`, `slidy`, `s5`,
`docbook`, `opendocument`, `latex`, `context`, `markdown`, `man`,
`plain`, `rst`, and `rtf`. (`+lhs` can be appended to indicate that
the output should be treated as literate Haskell source. See
@@ -204,8 +207,8 @@ For further documentation, see the `pandoc(1)` man page.
`-o` or `--output` *filename*
: sends output to *filename*. If this option is not specified,
or if its argument is `-`, output will be sent to stdout.
- (Exception: if the output format is `odt`, output to stdout
- is disabled.)
+ (Exception: if the output format is `odt` or `epub`, output to
+ stdout is disabled.)
`-p` or `--preserve-tabs`
: causes tabs in the source text to be preserved, rather than converted
@@ -228,11 +231,12 @@ For further documentation, see the `pandoc(1)` man page.
`-R` or `--parse-raw`
: causes the HTML and LaTeX readers to parse HTML codes and LaTeX
environments that it can't translate as raw HTML or LaTeX. Raw HTML can
- be printed in markdown, reStructuredText, HTML, and S5 output; raw LaTeX
- can be printed in markdown, reStructuredText, LaTeX, and ConTeXt output.
- The default is for the readers to omit untranslatable HTML codes and
- LaTeX environments. (The LaTeX reader does pass through untranslatable
- LaTeX *commands*, even if `-R` is not specified.)
+ be printed in markdown, reStructuredText, HTML, Slidy, and S5
+ output; raw LaTeX can be printed in markdown, reStructuredText,
+ LaTeX, and ConTeXt output. The default is for the readers to omit
+ untranslatable HTML codes and LaTeX environments. (The LaTeX reader
+ does pass through untranslatable LaTeX *commands*, even if `-R` is
+ not specified.)
`-C` or `--custom-header` *filename*
: can be used to specify a custom document header. Implies `--standalone`.
@@ -242,7 +246,7 @@ For further documentation, see the `pandoc(1)` man page.
: includes an automatically generated table of contents (or, in the
case of `latex`, `context`, and `rst`, an instruction to create
one) in the output document. This option has no effect with `man`,
- `docbook`, or `s5` output formats.
+ `docbook`, `slidy`, or `s5` output formats.
`--base-header-level` *level*
: specifies the base level for headers (defaults to 1).
@@ -263,9 +267,9 @@ For further documentation, see the `pandoc(1)` man page.
`-c` or `--css` *filename*
: allows the user to specify a custom stylesheet that will be linked to
- in HTML and S5 output. This option can be used repeatedly to include
- multiple stylesheets. They will be included in the order specified.
- Implies `--standalone`.
+ in HTML, Slidy, and S5 output. This option can be used repeatedly
+ to include multiple stylesheets. They will be included in the order
+ specified. Implies `--standalone`.
`-H` or `--include-in-header` *filename*
: includes the contents of *filename* (verbatim) at the end of the
@@ -299,6 +303,26 @@ For further documentation, see the `pandoc(1)` man page.
`--data-dir`, below). If it is not found there, sensible defaults
will be used.
+`--epub-stylesheet` *filename*
+: uses the specified CSS file to style the EPUB. If no stylesheet
+ is specified, pandoc will look for a file `epub.css` in the
+ user data directory (see `--data-dir`, below). If it is not
+ found there, sensible defaults will be used.
+
+`--epub-metadata` *filename*
+: looks in the specified XML file for metadata for the EPUB.
+ The file should contain a series of [Dublin Core elements],
+ for example:
+
+ <dc:rights>Creative Commons</dc:rights>
+ <dc:language>es-AR</dc:language>
+
+ By default, pandoc will include the following metadata elements:
+ `<dc:title>` (from the document title), `<dc:creator>` (from the
+ document authors), `<dc:language>` (from the locale), and
+ `<dc:identifier id="BookId">` (a randomly generated UUID). Any of
+ these may be overridden by elements in the metadata file.
+
`-D` or `--print-default-template` *format*
: prints the default template for an output *format*. (See `-t`
for a list of possible *format*s.)
@@ -320,15 +344,15 @@ For further documentation, see the `pandoc(1)` man page.
`-m`*[url]* or `--latexmathml`*[=url]*
: causes `pandoc` to use the [LaTeXMathML] script to display
- TeX math in HTML or S5. If a local copy of `LaTeXMathML.js` is
- available on the webserver where the page will be viewed, provide a
- *url* and a link will be inserted in the generated HTML or S5. If
+ TeX math in HTML, Slidy, or S5. If a local copy of `LaTeXMathML.js`
+ is available on the webserver where the page will be viewed, provide
+ a *url* and a link will be inserted in the generated HTML. If
no *url* is provided, the contents of the script will be inserted
directly; this provides portability at the price of efficiency. If
you plan to use math on several pages, it is much better to link to
- a copy of `LaTeXMathML.js`, which can be cached. (See `--jsmath`,
- `--gladtex`, and `--mimetex` for alternative ways of dealing with
- math in HTML.)
+ a copy of `LaTeXMathML.js`, which can be cached. (See `--jsmath`,
+ `--gladtex`, `--webtex`, and `--mimetex` for alternative ways of
+ dealing with math in HTML.)
`--mathml`
: causes `pandoc` to convert all TeX math to MathML.
@@ -337,29 +361,43 @@ For further documentation, see the `pandoc(1)` man page.
`--jsmath`*=[url]*
: causes `pandoc` to use the [jsMath] script to display
- TeX math in HTML or S5. The *url* should point to the jsMath load
- script (e.g. `jsMath/easy/load.js`). If it is provided, a link to it
- will be included in the header of standalone HTML documents.
- (See `--latexmathml`, `--mimetex`, and `--gladtex` for alternative
- ways of dealing with math in HTML.)
+ TeX math in HTML, Slidy, or S5. The *url* should point to the jsMath
+ load script (e.g. `jsMath/easy/load.js`). If it is provided, a link
+ to it will be included in the header of standalone HTML documents.
+ (See `--latexmathml`, `--mimetex`, `--webtex`, and `--gladtex` for
+ alternative ways of dealing with math in HTML.)
`--gladtex`*[=url]*
-: causes TeX formulas to be enclosed in `<eq>` tags in HTML or S5 output.
- This output can then be processed by [gladTeX] to produce links to
- images with the typeset formulas. (See `--latexmathml`, `--jsmath`, and
- `--mimetex` for alternative ways of dealing with math in HTML.)
+: causes TeX formulas to be enclosed in `<eq>` tags in HTML, Slidy, or
+ S5 output. This output can then be processed by [gladTeX] to produce
+ links to images with the typeset formulas. (See `--latexmathml`,
+ `--jsmath`, `--webtex`, and `--mimetex` for alternative ways of
+ dealing with math in HTML.)
`--mimetex`*[=url]*
: causes TeX formulas to be replaced by `<img>` tags linking to the
[mimeTeX] CGI script, which will produce images with the typeset
- formulas. (See `--latexmathml`, `--jsmath`, and `--gladtex` for alternative
- ways of dealing with math in HTML.)
+ formulas. (See `--latexmathml`, `--jsmath`, `--webtex`, and
+ `--gladtex` for alternative ways of dealing with math in HTML.)
+
+`--webtex`*[=url]*
+: causes TeX formulas to be replaced by `<img>` tags linking to an
+ external service that converts TeX formulas to images. The formula
+ will be concatenated with the URL provided. If no URL
+ is specified, the Google Chart API is used. (See `--latexmathml`,
+ `--jsmath`, `--mimetex`, and `--gladtex` for alternative ways of
+ dealing with math in HTML.)
`-i` or `--incremental`
-: causes all lists in S5 output to be displayed incrementally by
+: causes all lists in Slidy or S5 output to be displayed incrementally by
default (one item at a time). The normal default is for lists to be
displayed all at once.
+`--offline`
+: causes all the CSS and javascript needed for a Slidy or S5 slide show
+ to be included in the output, so that the slide show will work even
+ when no internet connection is available.
+
`--xetex`
: creates LaTeX outut suitable for processing by XeTeX.
@@ -367,6 +405,11 @@ For further documentation, see the `pandoc(1)` man page.
: causes sections to be numbered in LaTeX, ConTeXt, or HTML output.
By default, sections are not numbered.
+`--section-divs`
+: causes sections to be wrapped in `<div>` tags. In this case,
+ [section identifiers](#header-identifiers-in-html)
+ are attached to the enclosing `<div>` rather than the header itself.
+
`--no-wrap`
: disables text-wrapping in output. By default, text is wrapped
appropriately for the output format.
@@ -406,8 +449,9 @@ For further documentation, see the `pandoc(1)` man page.
C:\Documents And Settings\USERNAME\Application Data\pandoc
- in Windows. A reference ODT, `templates` directory, `s5` directory
- placed in this directory will override pandoc's normal defaults.
+ in Windows. A `reference.odt`, `epub.css`, `templates` directory,
+ or `s5` directory placed in this directory will override pandoc's
+ normal defaults.
`--dump-args`
: is intended to make it easier to create wrapper scripts that use
@@ -447,6 +491,7 @@ For further documentation, see the `pandoc(1)` man page.
[jsMath]: http://www.math.union.edu/~dpvc/jsmath/
[gladTeX]: http://www.math.uio.no/~martingu/gladtex/index.html
[mimeTeX]: http://www.forkosh.com/mimetex.html
+[Dublin Core elements]: http://dublincore.org/documents/dces/
Templates
=========
@@ -562,12 +607,12 @@ which allows only the following characters to be backslash-escaped:
\`*_{}[]()>#+-.!
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
-'`\&nbsp;`'.
+appear in TeX output as `~` and in HTML and XML as `\&#160;` or
+`\&nbsp;`.
A backslash-escaped newline (i.e. a backslash occurring at the end of
a line) is parsed as a hard line break. It will appear in TeX output as
-'`\\`' and in HTML as '`<br />`'. This is a nice alternative to
+`\\` and in HTML as `<br />`. This is a nice alternative to
markdown's "invisible" way of indicating hard line breaks using
two trailing spaces on a line.
@@ -645,7 +690,7 @@ capital letter with a period, by at least two spaces.[^2]
escape can be used:
(C\) 2007 Joe Smith
-
+
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
@@ -667,12 +712,38 @@ So, the following yields a list numbered sequentially starting from 2:
1. Four
* Five
-If default list markers are desired, use '`#.`':
+If default list markers are desired, use `#.`:
#. one
#. two
#. three
+Numbered examples
+-----------------
+
+The special list marker `@` can be used for sequentially numbered
+examples. The first list item with a `@` marker will be numbered '1',
+the next '2', and so on, throughout the document. The numbered examples
+need not occur in a single list; each new list using `@` will take up
+where the last stopped. So, for example:
+
+ (@) My first example will be numbered (1).
+ (@) My second example will be numbered (2).
+
+ Explanation of examples.
+
+ (@) My third example will be numbered (3).
+
+Numbered examples can be labeled and referred to elsewhere in the
+document:
+
+ (@good) This is a good example.
+
+ As (@good) illustrates, ...
+
+The label can be any string of alphanumeric characters, underscores,
+or hyphens.
+
Definition lists
----------------
@@ -771,10 +842,10 @@ Inline and regular footnotes may be mixed freely.
Tables
------
-Two kinds of tables may be used. Both kinds presuppose the use of
+Three kinds of tables may be used. All three kinds presuppose the use of
a fixed-width font, such as Courier.
-Simple tables look like this:
+**Simple tables** look like this:
Right Left Center Default
------- ------ ---------- -------
@@ -803,7 +874,8 @@ to the dashed line below it:[^4]
The table must end with a blank line, or a line of dashes followed by
a blank line. A caption may optionally be provided (as illustrated in
the example above). A caption is a paragraph beginning with the string
-`Table:`, which will be stripped off.
+`Table:` (or just `:`), which will be stripped off. It may appear either
+before or after the table.
The column headers may be omitted, provided a dashed line is used
to end the table. For example:
@@ -818,7 +890,7 @@ 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** allow headers and table rows to span multiple lines
of text. Here is an example:
-------------------------------------------------------------
@@ -859,12 +931,34 @@ Headers may be omitted in multiline tables as well as simple tables:
rows.
-------------------------------------------------------------
- Table: Here's a multiline table without headers.
+ : Here's a multiline table without headers.
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:
+
+ : Sample grid table.
+
+ +---------------+---------------+--------------------+
+ | Fruit | Price | Advantages |
+ +===============+===============+====================+
+ | Bananas | $1.34 | - built-in wrapper |
+ | | | - bright color |
+ +---------------+---------------+--------------------+
+ | Oranges | $2.10 | - cures scurvy |
+ | | | - tasty |
+ +---------------+---------------+--------------------+
+
+The row of `=`s separates the header from the table body, and can be
+omitted for a headerless table. The cells of grid tables may contain
+arbitrary block elements (multiple paragraphs, code blocks, lists,
+etc.). Alignments are not supported, nor are multi-column or multi-row
+cells. Grid tables can be created easily using [Emacs table mode].
+
+ [Emacs table mode]: http://table.sourceforge.net/
+
Delimited Code blocks
---------------------
@@ -1087,6 +1181,12 @@ another. A link to this section, for example, might look like this:
Note, however, that this method of providing links to sections works
only in HTML.
+If the `--section-divs` option is specified, then each section will
+be wrapped in a `div`, and the identifier will be attached to the
+enclosing `<div>` tag rather than the header itself. This allows entire
+sections to be manipulated using javascript or treated differently in
+CSS.
+
Blank lines before headers and blockquotes
------------------------------------------
@@ -1130,7 +1230,7 @@ Unknown commands and symbols, and commands that cannot be dealt with
this way (like `\frac`), will be rendered verbatim. So the results may
be a mix of raw TeX code and properly rendered unicode math.
-In HTML and S5 output, the way math is rendered will depend on the
+In HTML, Slidy, and S5 output, the way math is rendered will depend on the
command-line options selected:
1. The default is to render TeX math as far as possible using unicode
@@ -1166,6 +1266,12 @@ command-line options selected:
gladtex -d myfile-images myfile.htex
# produces myfile.html and images in myfile-images
+6. If the `--webtex` option is used, TeX formulas will be converted
+ to `<img>` tags that link to an external script that converts
+ formulas to images. The formula will be URL-encoded and concatenated
+ 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=`).
+
Inline TeX
----------
@@ -1190,14 +1296,12 @@ LaTeX, not as markdown.
Inline LaTeX is ignored in output formats other than Markdown, LaTeX,
and ConTeXt.
-Producing S5 with Pandoc
-========================
+Producing HTML slide shows with Pandoc
+======================================
-Producing an [S5] web-based slide show with Pandoc is easy. A title
-page is constructed automatically from the document's title block (see
-above). Each section (with a level-one header) produces a single slide.
-(Note that if the section is too big, the slide will not fit on the page;
-S5 is not smart enough to produce multiple pages.)
+You can use Pandoc to produce an HTML + javascript slide presentation
+that can be viewed via a web browser. There are two ways to do this,
+using [S5] or [Slidy].
Here's the markdown source for a simple slide show, `eating.txt`:
@@ -1215,18 +1319,45 @@ Here's the markdown source for a simple slide show, `eating.txt`:
- Eat spaghetti
- Drink wine
+ --------------------------
+
+ ![picture of spaghetti](images/spaghetti.jpg)
+
To produce the slide show, simply type
pandoc -w s5 -s eating.txt > eating.html
-and open up `eating.html` in a browser.
+for S5, or
+
+ pandoc -w slidy -s eating.txt > eating.html
+
+for Slidy.
-Note that by default, the S5 writer produces lists that display
-"all at once." If you want your lists to display incrementally
-(one item at a time), use the `-i` option. If you want a
-particular list to depart from the default (that is, to display
-incrementally without the `-i` option and all at once with the
-`-i` option), put it in a block quote:
+A title page is constructed automatically from the document's title
+block. Each level-one header and horizontal rule begins a new slide.
+
+The file produced by pandoc with the `-s/--standalone` option embeds a
+link to javascripts and CSS files, which are assumed to be available at
+the relative path `ui/default` (for S5) or at the Slidy website at
+`w3.org` (for Slidy). If the `--offline` option is specified, the
+scripts and CSS will be included directly in the generated file, so that
+it may be used offline.
+
+You can change the style of the slides by putting customized CSS files
+in `$DATADIR/s5/default` (for S5) or `$DATADIR/slidy` (for Slidy),
+where `$DATADIR` is the user data directory (see `--data-dir`, above).
+The originals may be found in pandoc's system data directory (generally
+`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any
+files it does not find in the user data directory.
+
+Incremental lists
+-----------------
+
+By default, these writers produces lists that display "all at once."
+If you want your lists to display incrementally (one item at a time),
+use the `-i` option. If you want a particular list to depart from the
+default (that is, to display incrementally without the `-i` option and
+all at once with the `-i` option), put it in a block quote:
> - Eat spaghetti
> - Drink wine
@@ -1234,27 +1365,6 @@ incrementally without the `-i` option and all at once with the
In this way incremental and nonincremental lists can be mixed in
a single document.
-Note: the S5 file produced by pandoc with the `-s/--standalone` option
-embeds the javascript and CSS required to show the slides. Thus it
-does not depend on any additional files: you can send the HTML file to
-others, and they will be able to view the slide show just by opening
-it. However, if you intend to produce several S5 slide shows, and you
-are displaying them on your own website, it is better to keep the S5
-javascript and CSS files separate from the slide shows themselves, so
-that they may be cached. The best approach in this case is to use pandoc
-without the `-s` option to produce the body of the S5 document, which
-can then be inserted into an HTML template that links to the javascript
-and CSS files required by S5. (See the instructions on the S5 website.)
-Alternatively, you may use `-s` together with the `--template`
-option to specify a custom template.
-
-You can change the style of the slides by putting customized CSS files
-in `$DATADIR/s5/default`, where `$DATADIR` is the user data directory
-(see `--data-dir`, above). The originals may be found in pandoc's system
-data directory (generally `$CABALDIR/pandoc-VERSION/s5/default`). Pandoc
-will look there for any files it does not find in the user data
-directory.
-
Literate Haskell support
========================
diff --git a/changelog b/changelog
index 6e47d24ae..ee7227ff1 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,160 @@
+pandoc (1.6)
+
+ [ John MacFarlane ]
+
+ * New EPUB and HTML Slidy writers. (Issue #122)
+
+ - EPUB is a standard ebook format, used in Apple's iBooks for
+ the iPad and iPhone, Barnes and Noble's nook reader, the Sony
+ reader, and many other devices.
+ - Slidy, like S5, is a system for producing HTML+javascript slide
+ shows.
+
+ * All input is assumed to be UTF-8, no matter what the locale and ghc
+ version, and all output is UTF-8. This reverts to pre-1.5 behavior.
+ Also, a BOM, if present, is stripped from the input.
+
+ * Markdown now supports grid tables, whose cells can contain
+ arbitrary block elements. (Issue #43)
+
+ * Sequentially numbered example lists in markdown with `@` marker.
+
+ * Markdown table captions can begin with a bare colon and no longer need
+ to include the English word "table." Also, a caption can now occur
+ either before or after the table. (Issue #227)
+
+ * New command-line options:
+
+ - `--epub-stylesheet` allows you to specify a CSS file that will
+ be used to style your ebook.
+ - `--epub-metadata` allows you to specify metadata for the ebook.
+ - `--offline` causes the generated HTML slideshow to include all
+ needed scripts and stylesheets.
+ - `--webtex` causes TeX math to be converted to images using the
+ Google Charts API (unless a different URL is specified).
+ - `--section-divs` causes div tags to be added around each section
+ in an HTML document. (Issue #230, 239)
+
+ * Default behavior of S5 writer in standalone mode has changed:
+ previously, it would include all needed scripts and stylesheets
+ in the generated HTML; now, only links are included unless
+ the `--offline` option is used.
+
+ * Default behavior of HTML writer has changed. Between 1.2 and 1.5,
+ pandoc would enclose sections in div tags with identifiers on the
+ div tags, so that the sections can be manipulated in javascript.
+ This caused undesirable interactions with raw HTML div tags. So,
+ starting with 1.6, the default is to put the identifiers directly
+ on the header tags, and not to include the divs. The `--section-divs`
+ option selects the 1.2-1.5 behavior.
+
+ * API changes:
+
+ - `HTMLMathMethod`: Added `WebTeX`, removed `MimeTeX`.
+ - `WriterOptions`: Added `writerUserDataDir`, `writerSourceDirectory`,
+ `writerEPUBMetadata` fields. Removed `writerIncludeBefore`,
+ `writerIncludeAfter`.
+ - Added `headerShift` to `Text.Pandoc.Shared`.
+ - Moved parsing code and `ParserState` from `Text.Pandoc.Shared`
+ to a new module, `Text.Pandoc.Parsing`.
+ - Added `stateHasChapters` to `ParserState`.
+ - Added `HTMLSlideVariant`.
+ - Made `KeyTable` a map instead of an association list.
+ - Added accessors for `Meta` fields (`docTitle`, `docAuthors`,
+ `docDate`).
+ - `Pandoc`, `Meta`, `Inline`, and `Block` have been given `Ord`
+ instances.
+ - Reference keys now have a type of their own (`Key`), with its
+ own `Ord` instance for case-insensitive comparison.
+ - Added `Text.Pandoc.Writers.EPUB`.
+ - Added `Text.Pandoc.UUID`.
+ - Removed `Text.Pandoc.ODT`, added `Text.Pandoc.Writers.ODT`.
+ Removed `saveOpenDocumentAsODT`, added `writeODT`.
+ - Added `Text.Pandoc.Writers.Native` and `writeNative`.
+ Removed `prettyPandoc`.
+ - Added `Text.Pandoc.UTF8` for portable UTF8 string IO.
+ - Removed `Text.Pandoc.Writers.S5` and the `writeS5` function.
+ Moved `s5Includes` to a new module, `Text.Pandoc.S5`.
+ To write S5, you now use `writeHtml` with `writerSlideVariant`
+ set to `S5Slides` or `SlidySlides`.
+
+ * Template changes. If you use custom templates, please update them,
+ particularly if you use syntax highlighting with pandoc. The old HTML
+ templates hardcoded highlighting CSS that will no longer work with
+ the most recent version of highlighting-kate.
+
+ - HTML template: avoid empty meta tag if no date.
+ - HTML template: Use default highlighting CSS from highlighting-kate
+ instead of hard-coding the CSS into the template.
+ - HTML template: insert-before text goes before the title, and
+ immediately after the <body> tag, as documented. (Issue #241)
+ - Added slidy and s5 templates.
+ - Added amssymb to preamble of latex template. (github Issue 1)
+
+ * Removed excess newlines at the end of output. Note: because output
+ will not contain an extra newline, you may need to make adjustments
+ if you are inserting pandoc's output into a template.
+
+ * In S5 and slidy, horizontal rules now cause a new slide, so you
+ are no longer limited to one slide per section.
+
+ * Improved handling of code in man writer. Inline code is now monospace,
+ not bold, and code blocks now use .nf (no fill) and .IP (indented para).
+
+ * HTML reader parses `<tt>` as Code. (Issue #247)
+
+ * html+lhs output now contains bird tracks, even when compiled without
+ highlighting support. (Issue #242)
+
+ * Colons are now no longer allowed in autogenerated XML/HTML identifiers,
+ since they have a special meaning in XML.
+
+ * Code improvements in ODT writer. Remote images are now replaced with
+ their alt text rather than a broken link.
+
+ * LaTeX reader improvements:
+
+ - Made latex `\section`, `\chapter` parsers more forgiving of
+ whitespace.
+ - Parse `\chapter{}` in latex.
+ - Changed `rawLaTeXInline` to accept `\section`, `\begin`, etc.
+ - Use new `rawLaTeXInline'` in LaTeX reader, and export `rawLaTeXInline`
+ for use in markdown reader.
+ - Fixes bug wherein `\section{foo}` was not recognized as raw TeX
+ in markdown document.
+
+ * LaTeX writer: images are automatically shrunk if they would extend
+ beyond the page margin.
+
+ * Plain, markdown, RST writers now use unicode for smart punctuation.
+
+ * Man writer converts math to unicode when possible, as in other writers.
+
+ * `markdown2pdf` can now recognize citeproc options.
+
+ * Command-line arguments are converted to UTF-8. (Issue #234)
+
+ * `Text.Pandoc.TeXMath` has been rewritten to use texmath's parser.
+ This allows it to handle a wider range of formulas. Also, if a formula
+ cannot be converted, it is left in raw TeX; formulas are no longer
+ partially converted.
+
+ * Unicode curly quotes are left alone when parsing smart quotes. (Issue
+ #143)
+
+ * Cabal file changes:
+
+ - Removed parsec < 3 restriction.
+ - Added 'threaded' flag for architectures where GHC lacks a threaded
+ runtime.
+ - Use 'threaded' only for markdown2pdf; it is not needed for pandoc.
+ - Require highlighting-kate 0.2.7.
+
+ * Use explicit imports from `Data.Generics`. Otherwise we have a
+ conflict with the 'empty' symbol, introduced in syb >= 0.2. (Issue #237)
+
+ * New data files: slidy/slidy.min.js, slidy/slidy.min.css, epub.css.
+
pandoc (1.5.1.1)
[ John MacFarlane ]
@@ -16,9 +173,9 @@ pandoc (1.5.1)
parsed text and the escaped URI (in the latter case, with
the mailto: prefix).
+ HTML reader: unsanitaryURI has been modified to allow unicode
- high characters in a URI.
+ high characters in a URI.
+ Readers: All link and image URIs are now escaped using
- escapeURI.
+ escapeURI.
+ Markdown and RST writers: unescapeURI is used so that URIs
in these formats are human-readable.
@@ -245,13 +402,14 @@ pandoc (1.5)
Resolves Issue #199.
* LaTeX writer:
- + If book, report, or memoir documentclass, use \chapter{}
+
+ + If book, report, or memoir documentclass, use \chapter{}
for first-level headers. Otherwise use \section{}.
+ Removed stLink, link template variable. Reason: we now always
include hyperref in the template.
* Latex template:
- + Only show \author if there are some.
+ + Only show \author if there are some.
+ Always include hyperref package. It is used not just for links but
for toc, section heading bookmarks, footnotes, etc. Also added
unicode=true on hyperref options.
diff --git a/epub.css b/epub.css
new file mode 100644
index 000000000..1774066cc
--- /dev/null
+++ b/epub.css
@@ -0,0 +1,11 @@
+/* This defines styles and classes used in the book */
+body { margin-left: 5%; margin-right: 5%; margin-top: 5%; margin-bottom: 5%; text-align: justify; font-size: medium; }
+code { font-family: monospace; }
+h1 { text-align: center; }
+h2 { text-align: center; }
+h3 { text-align: center; }
+h4 { text-align: center; }
+h5 { text-align: center; }
+h6 { text-align: center; }
+h1.title { }
+h2.author { }
diff --git a/man/man1/pandoc.1.md b/man/man1/pandoc.1.md
index a5fadb5c4..502b0b98d 100644
--- a/man/man1/pandoc.1.md
+++ b/man/man1/pandoc.1.md
@@ -16,13 +16,13 @@ Pandoc converts files from one markup format to another. It can
read markdown and (subsets of) reStructuredText, HTML, and LaTeX, and
it can write plain text, markdown, reStructuredText, HTML, LaTeX,
ConTeXt, Texinfo, groff man, MediaWiki markup, RTF, OpenDocument XML,
-ODT, DocBook XML, and S5 HTML slide shows.
+ODT, DocBook XML, EPUB, and Slidy or S5 HTML slide shows.
If no *input-file* is specified, input is read from *stdin*.
Otherwise, the *input-files* are concatenated (with a blank
line between each) and used as input. Output goes to *stdout* by
-default (though output to *stdout* is disabled for the `odt` output
-format). For output to a file, use the `-o` option:
+default (though output to *stdout* is disabled for the `odt` and
+`epub` output formats). For output to a file, use the `-o` option:
pandoc -o output.html input.txt
@@ -53,9 +53,8 @@ markdown: the differences are described in the *README* file in
the user documentation. If standard markdown syntax is desired, the
`--strict` option may be used.
-Pandoc uses the UTF-8 character encoding for both input and output
-(unless compiled with GHC 6.12 or higher, in which case it uses
-the local encoding). If your local character encoding is not UTF-8, you
+Pandoc uses the UTF-8 character encoding for both input and output.
+If your local character encoding is not UTF-8, you
should pipe input and output through `iconv`:
iconv -t utf-8 input.txt | pandoc | iconv -f utf-8
@@ -75,12 +74,13 @@ should pipe input and output through `iconv`:
`html` (HTML), `latex` (LaTeX), `context` (ConTeXt), `man` (groff man),
`mediawiki` (MediaWiki markup), `texinfo` (GNU Texinfo),
`docbook` (DocBook XML), `opendocument` (OpenDocument XML),
- `odt` (OpenOffice text document), `s5` (S5 HTML and javascript slide
- show), or `rtf` (rich text format). Note that `odt` 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`, or `html`, the output will be rendered as literate
- Haskell source.
+ `odt` (OpenOffice text document), `epub` (EPUB book),
+ `slidy` (Slidy HTML and 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`, or `html`,
+ the output will be rendered as literate Haskell source.
-s, \--standalone
: Produce output with an appropriate header and footer (e.g. a
@@ -136,8 +136,18 @@ should pipe input and output through `iconv`:
: Render TeX math using the mimeTeX CGI script. If *URL* is not specified,
it is assumed that the script is at `/cgi-bin/mimetex.cgi`.
+\--webtex=*URL*
+: Render TeX math using an external script. The formula will be
+ concatenated with the URL provided. If *URL* is not specified, the
+ Google Chart API will be used.
+
-i, \--incremental
-: Make list items in S5 display incrementally (one by one).
+: Make list items in Slidy or S5 display incrementally (one by one).
+
+\--offline
+: Include all the CSS and javascript needed for a Slidy or S5 slide
+ show in the output, so that the slide show will work even when no
+ internet connection is available.
\--xetex
: Create LaTeX outut suitable for processing by XeTeX.
@@ -146,6 +156,10 @@ should pipe input and output through `iconv`:
: Number section headings in LaTeX, ConTeXt, or HTML output.
(Default is not to number them.)
+\--section-divs
+: Wrap sections in `<div>` tags, and attach identifiers to the
+ enclosing `<div>` rather than the header itself.
+
\--no-wrap
: Disable text wrapping in output. (Default is to wrap text.)
@@ -176,7 +190,7 @@ should pipe input and output through `iconv`:
\--toc, \--table-of-contents
: Include an automatically generated table of contents (HTML, markdown,
RTF) or an instruction to create one (LaTeX, reStructuredText).
- This option has no effect on man, DocBook, or S5 output.
+ This option has no effect on man, DocBook, Slidy, or S5 output.
\--base-header-level=*LEVEL*
: Specify the base level for headers (defaults to 1).
@@ -222,6 +236,26 @@ should pipe input and output through `iconv`:
`--data-dir`). If this is not found either, sensible defaults will be
used.
+\--epub-stylesheet=*filename*
+: Use the specified CSS file to style the EPUB. If no stylesheet
+ is specified, pandoc will look for a file `epub.css` in the
+ user data directory (see `--data-dir`, below). If it is not
+ found there, sensible defaults will be used.
+
+\--epub-metadata=*filename*
+: Look in the specified XML file for metadata for the EPUB.
+ The file should contain a series of Dublin Core elements
+ (http://dublincore.org/documents/dces/), for example:
+
+ <dc:rights>Creative Commons</dc:rights>
+ <dc:language>es-AR</dc:language>
+
+ By default, pandoc will include the following metadata elements:
+ `<dc:title>` (from the document title), `<dc:creator>` (from the
+ document authors), `<dc:language>` (from the locale), and
+ `<dc:identifier id="BookId">` (a randomly generated UUID). Any of
+ these may be overridden by elements in the metadata file.
+
-D *FORMAT*, \--print-default-template=*FORMAT*
: Print the default template for an output *FORMAT*. (See `-t`
for a list of possible *FORMAT*s.)
@@ -240,8 +274,9 @@ should pipe input and output through `iconv`:
C:\Documents And Settings\USERNAME\Application Data\pandoc
- in Windows. A reference ODT, `templates` directory, `s5` directory
- placed in this directory will override pandoc's normal defaults.
+ in Windows. A `reference.odt`, `epub.css`, `templates` directory,
+ or `s5` directory placed in this directory will override pandoc's
+ normal defaults.
\--dump-args
: Print information about command-line arguments to *stdout*, then exit.
@@ -257,11 +292,11 @@ should pipe input and output through `iconv`:
: Ignore command-line arguments (for use in wrapper scripts).
Regular Pandoc options are not ignored. Thus, for example,
-: pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1
+ pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1
-: is equivalent to
+ is equivalent to
-: pandoc -o foo.html -s
+ pandoc -o foo.html -s
-v, \--version
: Print version.
diff --git a/markdown2pdf b/markdown2pdf
deleted file mode 100644
index 9470ae8e8..000000000
--- a/markdown2pdf
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/bin/sh -e
-
-latexprogram=pdflatex
-if (echo "$@" | grep -q xetex); then
- latexprogram=xelatex
-fi
-
-REQUIRED=$latexprogram
-SYNOPSIS="converts markdown-formatted text to PDF, using pdflatex."
-
-THIS=${0##*/}
-
-NEWLINE='
-'
-
-err () { echo "$*" | fold -s -w ${COLUMNS:-110} >&2; }
-errn () { printf "$*" | fold -s -w ${COLUMNS:-110} >&2; }
-
-usage () {
- err "$1 - $2" # short description
- err "Options:"
- pandoc -h | sed -ne '/--strict\|--preserve-tabs\|--tab-stop\|--parse-raw\|--toc\|--xetex\|--number-sections\|--include-in-header\|--include-before-body\|--include-after-body\|--custom-header\|--output\|--template\|--variable\|--help\|--version/p' >&2
-}
-
-# Portable which(1).
-pathfind () {
- oldifs="$IFS"; IFS=':'
- for _p in $PATH; do
- if [ -x "$_p/$*" ] && [ -f "$_p/$*" ]; then
- IFS="$oldifs"
- return 0
- fi
- done
- IFS="$oldifs"
- return 1
-}
-
-for p in pandoc $REQUIRED; do
- pathfind $p || {
- err "You need '$p' to use this program!"
- exit 1
- }
-done
-
-if (echo "$@" | grep -q -- "--help\|-h"); then
- usage "$THIS" "$SYNOPSIS"
- exit 0
-fi
-
-CONF=$(pandoc --dump-args "$@") || exit $?
-OUTPUT=$(echo "$CONF" | sed -ne '1p')
-ARGS=$(echo "$CONF" | sed -e '1d')
-
-# As a security measure refuse to proceed if mktemp is not available.
-pathfind mktemp || { err "Couldn't find 'mktemp'; aborting."; exit 1; }
-
-# Avoid issues with /tmp directory on Windows/Cygwin
-cygwin=
-cygwin=$(uname | sed -ne '/^CYGWIN/p')
-if [ -n "$cygwin" ]; then
- TMPDIR=.
- export TMPDIR
-fi
-
-THIS_TEMPDIR=
-THIS_TEMPDIR="$(mktemp -d -t $THIS.XXXXXXXX)" || exit 1
-readonly THIS_TEMPDIR
-
-trap 'exitcode=$?
- [ -z "$THIS_TEMPDIR" ] || rm -rf "$THIS_TEMPDIR"
- exit $exitcode' 0 1 2 3 13 15
-
-texname=output
-logfile=$THIS_TEMPDIR/log
-
-pandoc -s -r markdown -w latex "$@" -o $THIS_TEMPDIR/$texname.tex
-
-if [ "$OUTPUT" = "-" ]; then
- firstinfile="$(echo $ARGS | sed -ne '1p')"
- firstinfilebase="${firstinfile%.*}"
- destname="${firstinfilebase:-stdin}.pdf"
-else
- destname="$OUTPUT"
-fi
-
-(
- origdir=$(pwd)
- cd $THIS_TEMPDIR
- TEXINPUTS=$origdir:$TEXINPUTS:
- export TEXINPUTS
- finished=no
- runs=0
- while [ $finished = "no" ]; do
- $latexprogram -interaction=batchmode $texname.tex >/dev/null || {
- errcode=$?
- err "${THIS}: $latexprogram failed with error code $errcode"
- [ -f $texname.log ] && {
- err "${THIS}: error context:"
- sed -ne '/^!/,/^[[:space:]]*$/p' \
- -ne '/^[Ll]a[Tt]e[Xx] [Ww]arning/,/^[[:space:]]*$/p' \
- -ne '/^[Ee]rror/,/^[[:space:]]*$/p' $texname.log >&2
- if grep -q "File \`ucs.sty' not found" $texname.log; then
- err "${THIS}: Please install the 'unicode' package from CTAN:"
- err " http://www.ctan.org/tex-archive/macros/latex/contrib/unicode/"
- fi
- if grep -q "File \`ulem.sty' not found" $texname.log; then
- err "${THIS}: Please install the 'ulem' package from CTAN:"
- err " http://www.ctan.org/tex-archive/macros/latex/contrib/misc/ulem.sty"
- fi
- }
- exit $errcode
- }
- if [ $runs -lt 3 ] &&
- ((grep -q "Warning: There were undefined references." $texname.log) ||
- (echo "$@" | grep -q -- "--toc\|--table-of-contents")); then
- runs=$(($runs + 1))
- if grep -q "LaTeX Warning:.*[Cc]itation" $texname.log; then
- bibtex $texname 2>&1 >bibtex.err
- if [ $runs -gt 2 ]; then
- if grep -q "error message" bibtex.err ||
- grep -q "Warning" bibtex.err; then
- cat bibtex.err >&2
- fi
- fi
- fi
- elif [ $runs -gt 1 ]; then # always run at least twice for pdf bookmarks
- finished=yes
- else
- runs=$(($runs + 1))
- fi
- done
-) || exit $?
-
-mv -f $THIS_TEMPDIR/$texname.pdf "$destname"
-
-err "Created $destname"
diff --git a/pandoc.cabal b/pandoc.cabal
index e5995c23d..60e719d12 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,5 +1,5 @@
Name: pandoc
-Version: 1.5.1.1
+Version: 1.6
Cabal-Version: >= 1.2
Build-Type: Custom
License: GPL
@@ -11,15 +11,15 @@ Bug-Reports: http://code.google.com/p/pandoc/issues/list
Stability: alpha
Homepage: http://johnmacfarlane.net/pandoc
Category: Text
-Tested-With: GHC == 6.10.4, GHC == 6.12.1
+Tested-With: GHC == 6.12.1
Synopsis: Conversion between markup formats
Description: Pandoc is a Haskell library for converting from one markup
format to another, and a command-line tool that uses
this library. It can read markdown and (subsets of)
reStructuredText, HTML, and LaTeX, and it can write
markdown, reStructuredText, HTML, LaTeX, ConTeXt, Docbook,
- OpenDocument, ODT, RTF, MediaWiki, groff man pages, and
- S5 HTML slide shows.
+ OpenDocument, ODT, RTF, MediaWiki, groff man pages, EPUB,
+ and S5 and Slidy HTML slide shows.
.
Pandoc extends standard markdown syntax with footnotes,
embedded LaTeX, definition lists, tables, and other
@@ -42,8 +42,11 @@ Data-Files:
templates/man.template, templates/markdown.template,
templates/rst.template, templates/plain.template,
templates/mediawiki.template, templates/rtf.template,
+ templates/s5.template, templates/slidy.template,
-- data for ODT writer
reference.odt,
+ -- stylesheet for EPUB writer
+ epub.css,
-- data for LaTeXMathML writer
data/LaTeXMathML.js,
data/MathMLinHTML.js,
@@ -56,10 +59,11 @@ Data-Files:
s5/default/opera.css,
s5/default/outline.css,
s5/default/print.css,
+ -- data for slidy writer
+ slidy/slidy.min.css,
+ slidy/slidy.min.js,
-- documentation
- README, INSTALL, COPYRIGHT, BUGS, changelog,
- -- wrappers
- markdown2pdf
+ README, INSTALL, COPYRIGHT, BUGS, changelog
Extra-Source-Files:
-- sources for man pages
man/man1/pandoc.1.md, man/man1/markdown2pdf.1.md,
@@ -124,55 +128,69 @@ Extra-Source-Files:
tests/RunTests.hs
Extra-Tmp-Files: man/man1/pandoc.1, man/man1/markdown2pdf.1
+Flag threaded
+ Description: Compile markdown2pdf with -threaded option.
+ Default: True
Flag highlighting
Description: Compile in support for syntax highlighting of code blocks.
Default: False
Flag executable
Description: Build the pandoc executable.
Default: True
-Flag wrappers
- Description: Build the wrappers (markdown2pdf).
- Default: True
Flag library
Description: Build the pandoc library.
Default: True
+Flag wrappers
+ Description: Build the wrappers (markdown2pdf).
+ Default: True
Flag citeproc
Description: Compile in support for citeproc-hs bibliographic formatting.
Default: False
Library
+ -- Note: the following material must be in both Library and Executable stanzas.
+ -- It needs to be duplicated because of the library & executable flags.
+ -- BEGIN DUPLICATED SECTION
Build-Depends: pretty >= 1, containers >= 0.1,
- parsec >= 2.1 && < 3, xhtml >= 3000.0,
+ parsec >= 2.1, xhtml >= 3000.0,
mtl >= 1.1, network >= 2, filepath >= 1.1,
process >= 1, directory >= 1,
bytestring >= 0.9, zip-archive >= 0.1.1.4,
utf8-string >= 0.3, old-time >= 1,
- HTTP >= 4000.0.5, texmath, xml >= 1.3.5 && < 1.4,
- extensible-exceptions
+ HTTP >= 4000.0.5, texmath >= 0.3, xml >= 1.3.5 && < 1.4,
+ random, extensible-exceptions
if impl(ghc >= 6.10)
Build-depends: base >= 4 && < 5, syb
else
Build-depends: base >= 3 && < 4
if flag(highlighting)
- Build-depends: highlighting-kate >= 0.2.3
+ Build-depends: highlighting-kate >= 0.2.7.1
cpp-options: -D_HIGHLIGHTING
if flag(citeproc)
- Build-depends: citeproc-hs
- Exposed-Modules: Text.Pandoc.Biblio
+ Build-depends: citeproc-hs >= 0.2
cpp-options: -D_CITEPROC
+ if impl(ghc >= 6.12)
+ Ghc-Options: -O2 -Wall -fno-warn-unused-do-bind
+ else
+ Ghc-Options: -O2 -Wall
+ Ghc-Prof-Options: -auto-all -caf-all
+ Extensions: CPP
Hs-Source-Dirs: src
+ -- END DUPLICATED SECTION
+
Exposed-Modules: Text.Pandoc,
Text.Pandoc.Blocks,
Text.Pandoc.Definition,
Text.Pandoc.CharacterReferences,
Text.Pandoc.Shared,
- Text.Pandoc.ODT,
+ Text.Pandoc.Parsing,
Text.Pandoc.Highlighting,
Text.Pandoc.Readers.HTML,
Text.Pandoc.Readers.LaTeX,
Text.Pandoc.Readers.Markdown,
Text.Pandoc.Readers.RST,
Text.Pandoc.Readers.TeXMath,
+ Text.Pandoc.Writers.Native,
Text.Pandoc.Writers.Docbook,
Text.Pandoc.Writers.HTML,
Text.Pandoc.Writers.LaTeX,
@@ -184,38 +202,55 @@ Library
Text.Pandoc.Writers.RST,
Text.Pandoc.Writers.MediaWiki,
Text.Pandoc.Writers.RTF,
- Text.Pandoc.Writers.S5,
+ Text.Pandoc.Writers.ODT,
+ Text.Pandoc.Writers.EPUB,
+ Text.Pandoc.S5,
Text.Pandoc.Templates
Other-Modules: Text.Pandoc.XML,
+ Text.Pandoc.UTF8,
+ Text.Pandoc.UUID,
Paths_pandoc
- Extensions: CPP
- if impl(ghc >= 6.12)
- Ghc-Options: -O2 -Wall -fno-warn-unused-do-bind
- else
- Ghc-Options: -O2 -Wall
- Ghc-Prof-Options: -auto-all -caf-all
+ if flag(citeproc)
+ Exposed-Modules: Text.Pandoc.Biblio
if flag(library)
Buildable: True
else
Buildable: False
Executable pandoc
- Hs-Source-Dirs: src
- Main-Is: pandoc.hs
- if impl(ghc >= 6.12)
- Ghc-Options: -O2 -Wall -threaded -fno-warn-unused-do-bind
+ -- Note: the following material must be in both Library and Executable stanzas.
+ -- It needs to be duplicated because of the library & executable flags.
+ -- BEGIN DUPLICATED SECTION
+ Build-Depends: pretty >= 1, containers >= 0.1,
+ parsec >= 2.1, xhtml >= 3000.0,
+ mtl >= 1.1, network >= 2, filepath >= 1.1,
+ process >= 1, directory >= 1,
+ bytestring >= 0.9, zip-archive >= 0.1.1.4,
+ utf8-string >= 0.3, old-time >= 1,
+ HTTP >= 4000.0.5, texmath, xml >= 1.3.5 && < 1.4,
+ random, extensible-exceptions
+ if impl(ghc >= 6.10)
+ Build-depends: base >= 4 && < 5, syb
else
- Ghc-Options: -O2 -Wall -threaded
- Ghc-Prof-Options: -auto-all -caf-all
- Extensions: CPP
-
+ Build-depends: base >= 3 && < 4
if flag(highlighting)
+ Build-depends: highlighting-kate >= 0.2.7.1
cpp-options: -D_HIGHLIGHTING
if flag(citeproc)
Build-depends: citeproc-hs >= 0.2
cpp-options: -D_CITEPROC
- if flag(executable)
+ if impl(ghc >= 6.12)
+ Ghc-Options: -O2 -Wall -fno-warn-unused-do-bind
+ else
+ Ghc-Options: -O2 -Wall
+ Ghc-Prof-Options: -auto-all -caf-all
+ Extensions: CPP
+ Hs-Source-Dirs: src
+ -- END DUPLICATED SECTION
+
+ Main-Is: pandoc.hs
+ if flag(executable) || flag(wrappers)
Buildable: True
else
Buildable: False
@@ -223,7 +258,10 @@ Executable pandoc
Executable markdown2pdf
Hs-Source-Dirs: src
Main-Is: markdown2pdf.hs
- Ghc-Options: -Wall -threaded
+ if flag(threaded)
+ Ghc-Options: -Wall -threaded
+ else
+ Ghc-Options: -Wall
Ghc-Prof-Options: -auto-all
Extensions: CPP
if flag(wrappers)
diff --git a/slidy/slidy.min.css b/slidy/slidy.min.css
new file mode 100644
index 000000000..59e49495f
--- /dev/null
+++ b/slidy/slidy.min.css
@@ -0,0 +1 @@
+body{margin:0;padding:0;width:100%;height:100%;color:black;background-color:white;font-family:"Gill Sans MT","Gill Sans",GillSans,sans-serif;font-size:14pt;}.hidden{display:none;visibility:hidden;}div.toolbar{position:fixed;z-index:200;top:auto;bottom:0;left:0;right:0;height:1.2em;text-align:right;padding-left:1em;padding-right:1em;font-size:60%;color:red;background:#f0f0f0;}div.background{display:none;}div.handout{margin-left:20px;margin-right:20px;}div.slide.titlepage{text-align:center;}div.slide.titlepage.h1{padding-top:40%;}div.slide{z-index:20;margin:0;padding-top:0;padding-bottom:0;padding-left:20px;padding-right:20px;border-width:0;clear:both;top:0;bottom:0;left:0;right:0;line-height:120%;background-color:transparent;}div.slide+div[class].slide{page-break-before:always;}div.slide h1{padding-left:0;padding-right:20pt;padding-top:4pt;padding-bottom:4pt;margin-top:0;margin-left:0;margin-right:60pt;margin-bottom:.5em;display:block;font-size:160%;line-height:1.2em;background:transparent;}div.toc{position:absolute;top:auto;bottom:4em;left:4em;right:auto;width:60%;max-width:30em;height:30em;border:solid thin black;padding:1em;background:#f0f0f0;color:black;z-index:300;overflow:auto;display:block;visibility:visible;}div.toc-heading{width:100%;border-bottom:solid 1px #b4b4b4;margin-bottom:1em;text-align:center;}pre{font-size:80%;font-weight:bold;line-height:120%;padding-top:.2em;padding-bottom:.2em;padding-left:1em;padding-right:1em;border-style:solid;border-left-width:1em;border-top-width:thin;border-right-width:thin;border-bottom-width:thin;border-color:#95ABD0;color:#00428C;background-color:#E4E5E7;}li pre{margin-left:0;}@media print{div.slide{display:block;visibility:visible;position:relative;border-top-style:solid;border-top-width:thin;border-top-color:black;}div.slide pre{font-size:60%;padding-left:.5em;}div.handout{display:block;visibility:visible;}}blockquote{font-style:italic;}img{background-color:transparent;}p.copyright{font-size:smaller;}.center{text-align:center;}.footnote{font-size:smaller;margin-left:2em;}a img{border-width:0;border-style:none;}a:visited{color:navy;}a:link{color:navy;}a:hover{color:red;text-decoration:underline;}a:active{color:red;text-decoration:underline;}a{text-decoration:none;}.navbar a:link{color:white;}.navbar a:visited{color:yellow;}.navbar a:active{color:red;}.navbar a:hover{color:red;}ul{list-style-type:square;}ul ul{list-style-type:disc;}ul ul ul{list-style-type:circle;}ul ul ul ul{list-style-type:disc;}li{margin-left:.5em;margin-top:.5em;}li li{font-size:85%;font-style:italic;}li li li{font-size:85%;font-style:normal;}div dt{margin-left:0;margin-top:1em;margin-bottom:.5em;font-weight:bold;}div dd{margin-left:2em;margin-bottom:.5em;}p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table{margin-left:1em;margin-right:1em;}p.subhead{font-weight:bold;margin-top:2em;}.smaller{font-size:smaller;}.bigger{font-size:130%;}td,th{padding:.2em;}ul{margin:.5em 1.5em .5em 1.5em;padding:0;}ol{margin:.5em 1.5em .5em 1.5em;padding:0;}ul{list-style-type:square;}ul ul{list-style-type:disc;}ul ul ul{list-style-type:circle;}ul ul ul ul{list-style-type:disc;}ul li{list-style:square;margin:.1em 0 .6em 0;padding:0;line-height:140%;}ol li{margin:.1em 0 .6em 1.5em;padding:0;line-height:140%;list-style-type:decimal;}li ul li{font-size:85%;font-style:italic;list-style-type:disc;background:transparent;padding:0;}li li ul li{font-size:85%;font-style:normal;list-style-type:circle;background:transparent;padding:0;}li li li ul li{list-style-type:disc;background:transparent;padding:0;}li ol li{list-style-type:decimal;}li li ol li{list-style-type:decimal;}ol.outline li:hover{cursor:pointer;}ol.outline li.nofold:hover{cursor:default;}ul.outline li:hover{cursor:pointer;}ul.outline li.nofold:hover{cursor:default;}ol.outline{list-style:decimal;}ol.outline ol{list-style-type:lower-alpha;}ol.outline li.nofold{padding:0 0 0 20px;background:transparent url(nofold-dim.gif) no-repeat 0 .5em;}ol.outline li.unfolded{padding:0 0 0 20px;background:transparent url(fold-dim.gif) no-repeat 0 .5em;}ol.outline li.folded{padding:0 0 0 20px;background:transparent url(unfold-dim.gif) no-repeat 0 .5em;}ol.outline li.unfolded:hover{padding:0 0 0 20px;background:transparent url(fold.gif) no-repeat 0 .5em;}ol.outline li.folded:hover{padding:0 0 0 20px;background:transparent url(unfold.gif) no-repeat 0 .5em;}ul.outline li.nofold{padding:0 0 0 20px;background:transparent url(nofold-dim.gif) no-repeat 0 .5em;}ul.outline li.unfolded{padding:0 0 0 20px;background:transparent url(fold-dim.gif) no-repeat 0 .5em;}ul.outline li.folded{padding:0 0 0 20px;background:transparent url(unfold-dim.gif) no-repeat 0 .5em;}ul.outline li.unfolded:hover{padding:0 0 0 20px;background:transparent url(fold.gif) no-repeat 0 .5em;}ul.outline li.folded:hover{padding:0 0 0 20px;background:transparent url(unfold.gif) no-repeat 0 .5em;}a.titleslide{font-weight:bold;font-style:italic;} \ No newline at end of file
diff --git a/slidy/slidy.min.js b/slidy/slidy.min.js
new file mode 100644
index 000000000..990d7d50f
--- /dev/null
+++ b/slidy/slidy.min.js
@@ -0,0 +1 @@
+var ns_pos=(typeof window.pageYOffset!="undefined");var khtml=((navigator.userAgent).indexOf("KHTML")>=0?true:false);var opera=((navigator.userAgent).indexOf("Opera")>=0?true:false);var ie=(typeof document.all!="undefined"&&!opera);var ie7=(!ns_pos&&navigator.userAgent.indexOf("MSIE 7")!=-1);var ie8=(!ns_pos&&navigator.userAgent.indexOf("MSIE 8")!=-1);var slidy_started=false;if(ie&&!ie8){document.write("<iframe id='historyFrame' src='javascript:\"<html></html>\"' height='1' width='1' style='position:absolute;left:-800px'></iframe>")}if(typeof beforePrint!="undefined"){window.onbeforeprint=beforePrint;window.onafterprint=afterPrint}if(ie){setTimeout(ieSlidyInit,100)}else{if(document.addEventListener){document.addEventListener("DOMContentLoaded",startup,false)}}function ieSlidyInit(){if(document.readyState=="complete"||document.readyState=="loaded"){startup()}else{setTimeout(ieSlidyInit,100)}}setTimeout(hideSlides,50);function hideSlides(){if(document.body){document.body.style.visibility="hidden"}else{setTimeout(hideSlides,50)}}var slidenum=0;var slides;var slideNumElement;var notes;var backgrounds;var toolbar;var title;var lastShown=null;var eos=null;var toc=null;var outline=null;var selectedTextLen;var viewAll=0;var wantToolbar=1;var mouseClickEnabled=true;var scrollhack=0;var key_wanted=false;var helpAnchor;var helpPage="http://www.w3.org/Talks/Tools/Slidy/help.html";var helpText="Navigate with mouse click, space bar, Cursor Left/Right, or Pg Up and Pg Dn. Use S and B to change font size.";var sizeIndex=0;var sizeAdjustment=0;var sizes=new Array("10pt","12pt","14pt","16pt","18pt","20pt","22pt","24pt","26pt","28pt","30pt","32pt");var okayForIncremental=incrementalElementList();var lastWidth=0;var lastHeight=0;var objects;var lang="en";var strings_es={slide:"pág.","help?":"Ayuda","contents?":"Índice","table of contents":"tabla de contenidos","Table of Contents":"Tabla de Contenidos","restart presentation":"Reiniciar presentación","restart?":"Inicio"};strings_es[helpText]="Utilice el ratón, barra espaciadora, teclas Izda/Dcha, o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.";var strings_ca={slide:"pàg..","help?":"Ajuda","contents?":"Índex","table of contents":"taula de continguts","Table of Contents":"Taula de Continguts","restart presentation":"Reiniciar presentació","restart?":"Inici"};strings_ca[helpText]="Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. o Re pàg y Av pàg. Usi S i B per canviar grandària de font.";var strings_nl={slide:"pagina","help?":"Help?","contents?":"Inhoud?","table of contents":"inhoudsopgave","Table of Contents":"Inhoudsopgave","restart presentation":"herstart presentatie","restart?":"Herstart?"};strings_nl[helpText]="Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.";var strings_de={slide:"Seite","help?":"Hilfe","contents?":"Übersicht","table of contents":"Inhaltsverzeichnis","Table of Contents":"Inhaltsverzeichnis","restart presentation":"Präsentation neu starten","restart?":"Neustart"};strings_de[helpText]="Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.";var strings_pl={slide:"slajd","help?":"pomoc?","contents?":"spis treści?","table of contents":"spis treści","Table of Contents":"Spis Treści","restart presentation":"Restartuj prezentację","restart?":"restart?"};strings_pl[helpText]="Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawolub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.";var strings_fr={slide:"page","help?":"Aide","contents?":"Index","table of contents":"table des matières","Table of Contents":"Table des matières","restart presentation":"Recommencer l'exposé","restart?":"Début"};strings_fr[helpText]="Naviguez avec la souris, la barre d'espace, les flèches gauche/droite ou les touches Pg Up, Pg Dn. Utilisez les touches S et B pour modifier la taille de la police.";var strings_hu={slide:"oldal","help?":"segítség","contents?":"tartalom","table of contents":"tartalomjegyzék","Table of Contents":"Tartalomjegyzék","restart presentation":"bemutató újraindítása","restart?":"újraindítás"};strings_hu[helpText]="Az oldalak közti lépkedéshez kattintson az egérrel, vagy használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, Page Up billentyűket. Az S és a B billentyűkkel változtathatja a szöveg méretét.";var strings_it={slide:"pag.","help?":"Aiuto","contents?":"Indice","table of contents":"indice","Table of Contents":"Indice","restart presentation":"Ricominciare la presentazione","restart?":"Inizio"};strings_it[helpText]="Navigare con mouse, barra spazio, frecce sinistra/destra o PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.";var strings_el={slide:"σελίδα","help?":"βοήθεια;","contents?":"περιεχόμενα;","table of contents":"πίνακας περιεχομένων","Table of Contents":"Πίνακας Περιεχομένων","restart presentation":"επανεκκίνηση παρουσίασης","restart?":"επανεκκίνηση;"};strings_el[helpText]="Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε το μέγεθος της γραμματοσειράς.";var strings_ja={slide:"スライド","help?":"ヘルプ","contents?":"目次","table of contents":"目次を表示","Table of Contents":"目次","restart presentation":"最初から再生","restart?":"最初から"};strings_ja[helpText]="マウス左クリック ・ スペース ・ 左右キー または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更";var strings_zh={slide:"幻灯片","help?":"帮助?","contents?":"内容?","table of contents":"目录","Table of Contents":"目录","restart presentation":"重新启动展示","restart?":"重新启动?"};strings_zh[helpText]="用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. 用 S, B 改变字体大小.";var strings_ru={slide:"слайд","help?":"помощь?","contents?":"содержание?","table of contents":"оглавление","Table of Contents":"Оглавление","restart presentation":"перезапустить презентацию","restart?":"перезапуск?"};strings_ru[helpText]="Перемещайтесь кликая мышкой, используя клавишу пробел, стрелкивлево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.";var strings_sv={slide:"sida","help?":"hjälp","contents?":"innehåll","table of contents":"innehållsförteckning","Table of Contents":"Innehållsförteckning","restart presentation":"visa presentationen från början","restart?":"börja om"};strings_sv[helpText]="Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. Använd tangenterna S och B för att ändra textens storlek.";var localize={es:strings_es,ca:strings_ca,nl:strings_nl,de:strings_de,pl:strings_pl,fr:strings_fr,hu:strings_hu,it:strings_it,el:strings_el,jp:strings_ja,zh:strings_zh,ru:strings_ru,sv:strings_sv};function startup(){if(slidy_started){alert("already started");return}slidy_started=true;lang=document.body.parentNode.getAttribute("lang");if(!lang){lang=document.body.parentNode.getAttribute("xml:lang")}if(!lang){lang="en"}document.body.style.visibility="visible";title=document.title;toolbar=addToolbar();wrapImplicitSlides();slides=collectSlides();notes=collectNotes();objects=document.body.getElementsByTagName("object");backgrounds=collectBackgrounds();patchAnchors();slidenum=findSlideNumber(location.href);window.offscreenbuffering=true;sizeAdjustment=findSizeAdjust();hideImageToolbar();initOutliner();if(slides.length>0){var slide=slides[slidenum];slide.style.position="absolute";if(slidenum>0){setVisibilityAllIncremental("visible");lastShown=previousIncrementalItem(null);setEosStatus(true)}else{lastShown=null;setVisibilityAllIncremental("hidden");setEosStatus(!nextIncrementalItem(lastShown))}setLocation()}toc=tableOfContents();hideTableOfContents();document.onclick=mouseButtonClick;document.onmouseup=mouseButtonUp;document.onkeydown=keyDown;if(opera){document.onkeypress=keyPress}window.onresize=resized;window.onscroll=scrolled;window.onunload=unloaded;singleSlideView();setLocation();resized();if(ie7){setTimeout("ieHack()",100)}showToolbar();setInterval("checkLocation()",200)}String.prototype.localize=function(){if(this==""){return this}var s,lookup=localize[lang];if(lookup){s=lookup[this];if(s){return s}}var lg=lang.split("-");if(lg.length>1){lookup=localize[lg[0]];if(lookup){s=lookup[this];if(s){return s}}}return this};function hideImageToolbar(){if(!ns_pos){var images=document.getElementsByTagName("IMG");for(var i=0;i<images.length;++i){images[i].setAttribute("galleryimg","no")}}}function ieHack(){window.resizeBy(0,-1);window.resizeBy(0,1)}function unloaded(e){}function reload(e){if(!e){var e=window.event}hideBackgrounds();setTimeout("document.reload();",100);stopPropagation(e);e.cancel=true;e.returnValue=false;return false}function isKHTML(){var agent=navigator.userAgent;return(agent.indexOf("KHTML")>=0?true:false)}function resized(){var width=0;if(typeof(window.innerWidth)=="number"){width=window.innerWidth}else{if(document.documentElement&&document.documentElement.clientWidth){width=document.documentElement.clientWidth}else{if(document.body&&document.body.clientWidth){width=document.body.clientWidth}}}var height=0;if(typeof(window.innerHeight)=="number"){height=window.innerHeight}else{if(document.documentElement&&document.documentElement.clientHeight){height=document.documentElement.clientHeight}else{if(document.body&&document.body.clientHeight){height=document.body.clientHeight}}}if(height&&(width/height>1.05*1024/768)){width=height*1024/768}if(width!=lastWidth||height!=lastHeight){if(width>=1100){sizeIndex=5}else{if(width>=1000){sizeIndex=4}else{if(width>=800){sizeIndex=3}else{if(width>=600){sizeIndex=2}else{if(width){sizeIndex=0}}}}}if(0<=sizeIndex+sizeAdjustment&&sizeIndex+sizeAdjustment<sizes.length){sizeIndex=sizeIndex+sizeAdjustment}adjustObjectDimensions(width,height);document.body.style.fontSize=sizes[sizeIndex];lastWidth=width;lastHeight=height;var slide=slides[slidenum];hideSlide(slide);showSlide(slide);refreshToolbar(200)}}function scrolled(){if(toolbar&&!ns_pos&&!ie7){hackoffset=scrollXOffset();toolbar.style.display="none";if(scrollhack==0&&!viewAll){setTimeout(showToolbar,1000);scrollhack=1}}}function refreshToolbar(interval){if(!ns_pos&&!ie7){hideToolbar();setTimeout(showToolbar,interval)}}function showToolbar(){if(wantToolbar){if(!ns_pos){var xoffset=scrollXOffset();toolbar.style.left=xoffset;toolbar.style.right=xoffset;toolbar.style.bottom=0}toolbar.style.display="block";toolbar.style.visibility="visible"}scrollhack=0;try{if(!opera){helpAnchor.focus()}}catch(e){}}function hideToolbar(){toolbar.style.display="none";toolbar.style.visibility="hidden";window.focus()}function toggleToolbar(){if(!viewAll){if(toolbar.style.display=="none"){toolbar.style.display="block";toolbar.style.visibility="visible";wantToolbar=1}else{toolbar.style.display="none";toolbar.style.visibility="hidden";wantToolbar=0}}}function scrollXOffset(){if(window.pageXOffset){return self.pageXOffset}if(document.documentElement&&document.documentElement.scrollLeft){return document.documentElement.scrollLeft}if(document.body){return document.body.scrollLeft}return 0}function scrollYOffset(){if(window.pageYOffset){return self.pageYOffset}if(document.documentElement&&document.documentElement.scrollTop){return document.documentElement.scrollTop}if(document.body){return document.body.scrollTop}return 0}function optimizeFontSize(){var slide=slides[slidenum];var dh=slide.scrollHeight;var wh=getWindowHeight();var u=100*dh/wh;alert("window utilization = "+u+"% (doc "+dh+" win "+wh+")")}function getDocHeight(doc){if(!doc){doc=document}if(doc&&doc.body&&doc.body.offsetHeight){return doc.body.offsetHeight}if(doc&&doc.body&&doc.body.scrollHeight){return doc.body.scrollHeight}alert("couldn't determine document height")}function getWindowHeight(){if(typeof(window.innerHeight)=="number"){return window.innerHeight}if(document.documentElement&&document.documentElement.clientHeight){return document.documentElement.clientHeight}if(document.body&&document.body.clientHeight){return document.body.clientHeight}}function documentHeight(){var sh,oh;sh=document.body.scrollHeight;oh=document.body.offsetHeight;if(sh&&oh){return(sh>oh?sh:oh)}return 0}function smaller(){if(sizeIndex>0){--sizeIndex}toolbar.style.display="none";document.body.style.fontSize=sizes[sizeIndex];var slide=slides[slidenum];hideSlide(slide);showSlide(slide);setTimeout(showToolbar,300)}function bigger(){if(sizeIndex<sizes.length-1){++sizeIndex}toolbar.style.display="none";document.body.style.fontSize=sizes[sizeIndex];var slide=slides[slidenum];hideSlide(slide);showSlide(slide);setTimeout(showToolbar,300)}function adjustObjectDimensions(width,height){for(var i=0;i<objects.length;i++){var obj=objects[i];var mimeType=obj.getAttribute("type");if(mimeType=="image/svg+xml"||mimeType=="application/x-shockwave-flash"){if(!obj.initialWidth){obj.initialWidth=obj.getAttribute("width")}if(!obj.initialHeight){obj.initialHeight=obj.getAttribute("height")}if(obj.initialWidth&&obj.initialWidth.charAt(obj.initialWidth.length-1)=="%"){var w=parseInt(obj.initialWidth.slice(0,obj.initialWidth.length-1));var newW=width*(w/100);obj.setAttribute("width",newW)}if(obj.initialHeight&&obj.initialHeight.charAt(obj.initialHeight.length-1)=="%"){var h=parseInt(obj.initialHeight.slice(0,obj.initialHeight.length-1));var newH=height*(h/100);obj.setAttribute("height",newH)}}}}function cancel(event){if(event){event.cancel=true;event.returnValue=false;if(event.preventDefault){event.preventDefault()}}return false}function keyDown(event){var key;if(!event){var event=window.event}key_wanted=false;if(window.event){key=window.event.keyCode}else{if(event.which){key=event.which}else{return true}}if(!key){return true}if(event.ctrlKey||event.altKey||event.metaKey){return true}if(isShownToc()&&key!=9&&key!=16&&key!=38&&key!=40){hideTableOfContents();if(key==27||key==84||key==67){return cancel(event)}}key_wanted=true;if(key==34){if(viewAll){return true}nextSlide(false);return cancel(event)}else{if(key==33){if(viewAll){return true}previousSlide(false);return cancel(event)}else{if(key==32){nextSlide(true);return cancel(event)}else{if(key==37){previousSlide(!event.shiftKey);return cancel(event)}else{if(key==36){firstSlide();return cancel(event)}else{if(key==35){lastSlide();return cancel(event)}else{if(key==39){nextSlide(!event.shiftKey);return cancel(event)}else{if(key==13){if(outline){if(outline.visible){fold(outline)}else{unfold(outline)}return cancel(event)}}else{if(key==188){smaller();return cancel(event)}else{if(key==190){bigger();return cancel(event)}else{if(key==189||key==109){smaller();return cancel(event)}else{if(key==187||key==191||key==107){bigger();return cancel(event)}else{if(key==83){smaller();return cancel(event)}else{if(key==66){bigger();return cancel(event)}else{if(key==90){lastSlide();return cancel(event)}else{if(key==70){toggleToolbar();return cancel(event)}else{if(key==65){toggleView();return cancel(event)}else{if(key==75){mouseClickEnabled=!mouseClickEnabled;alert((mouseClickEnabled?"enabled":"disabled")+" mouse click advance");return cancel(event)}else{if(key==84||key==67){if(toc){showTableOfContents()}return cancel(event)}else{if(key==72){window.location=helpPage;return cancel(event)}}}}}}}}}}}}}}}}}}}}key_wanted=false;return true}function keyPress(event){if(!event){event=window.event}return key_wanted?cancel(event):true}function mouseButtonUp(e){selectedTextLen=getSelectedText().length}function mouseButtonClick(e){var rightclick=false;var leftclick=false;var middleclick=false;var target;if(!e){var e=window.event}if(e.target){target=e.target}else{if(e.srcElement){target=e.srcElement}}if(target.nodeType==3){target=target.parentNode}if(e.which){leftclick=(e.which==1);middleclick=(e.which==2);rightclick=(e.which==3)}else{if(e.button){if(e.button==4){middleclick=true}rightclick=(e.button==2)}else{leftclick=true}}if(selectedTextLen>0){stopPropagation(e);e.cancel=true;e.returnValue=false;return false}hideTableOfContents();if(mouseClickEnabled&&leftclick&&target.nodeName!="EMBED"&&target.nodeName!="OBJECT"&&target.nodeName!="VIDEO"&&target.nodeName!="INPUT"&&target.nodeName!="TEXTAREA"&&target.nodeName!="SELECT"&&target.nodeName!="OPTION"){nextSlide(true);stopPropagation(e);e.cancel=true;e.returnValue=false}}function previousSlide(incremental){if(!viewAll){var slide;if((incremental||slidenum==0)&&lastShown!=null){lastShown=hidePreviousItem(lastShown);setEosStatus(false)}else{if(slidenum>0){slide=slides[slidenum];hideSlide(slide);slidenum=slidenum-1;slide=slides[slidenum];setVisibilityAllIncremental("visible");lastShown=previousIncrementalItem(null);setEosStatus(true);showSlide(slide)}}setLocation();if(!ns_pos){refreshToolbar(200)}}}function nextSlide(incremental){if(!viewAll){var slide,last=lastShown;if(incremental||slidenum==slides.length-1){lastShown=revealNextItem(lastShown)}if((!incremental||lastShown==null)&&slidenum<slides.length-1){slide=slides[slidenum];hideSlide(slide);slidenum=slidenum+1;slide=slides[slidenum];lastShown=null;setVisibilityAllIncremental("hidden");showSlide(slide)}else{if(!lastShown){if(last&&incremental){lastShown=last}}}setLocation();setEosStatus(!nextIncrementalItem(lastShown));if(!ns_pos){refreshToolbar(200)}}}function firstSlide(){if(!viewAll){var slide;if(slidenum!=0){slide=slides[slidenum];hideSlide(slide);slidenum=0;slide=slides[slidenum];lastShown=null;setVisibilityAllIncremental("hidden");showSlide(slide)}setEosStatus(!nextIncrementalItem(lastShown));setLocation()}}function lastSlide(){if(!viewAll){var slide;lastShown=null;if(lastShown==null&&slidenum<slides.length-1){slide=slides[slidenum];hideSlide(slide);slidenum=slides.length-1;slide=slides[slidenum];setVisibilityAllIncremental("visible");lastShown=previousIncrementalItem(null);showSlide(slide)}else{setVisibilityAllIncremental("visible");lastShown=previousIncrementalItem(null)}setEosStatus(true);setLocation()}}function gotoSlide(num){var slide=slides[slidenum];hideSlide(slide);slidenum=num;slide=slides[slidenum];lastShown=null;setVisibilityAllIncremental("hidden");setEosStatus(!nextIncrementalItem(lastShown));document.title=title+" ("+(slidenum+1)+")";showSlide(slide);showSlideNumber()}function setEosStatus(state){if(eos){eos.style.color=(state?"rgb(240,240,240)":"red")}}function showSlide(slide){syncBackground(slide);window.scrollTo(0,0);slide.style.visibility="visible";slide.style.display="block"}function hideSlide(slide){slide.style.visibility="hidden";slide.style.display="none"}function beforePrint(){showAllSlides();hideToolbar()}function afterPrint(){if(!viewAll){singleSlideView();showToolbar()}}function printSlides(){beforePrint();window.print();afterPrint()}function toggleView(){if(viewAll){singleSlideView();showToolbar();viewAll=0}else{showAllSlides();hideToolbar();viewAll=1}}function showAllSlides(){var slide;for(var i=0;i<slides.length;++i){slide=slides[i];slide.style.position="relative";slide.style.borderTopStyle="solid";slide.style.borderTopWidth="thin";slide.style.borderTopColor="black";try{if(i==0){slide.style.pageBreakBefore="avoid"}else{slide.style.pageBreakBefore="always"}}catch(e){}setVisibilityAllIncremental("visible");showSlide(slide)}var note;for(var i=0;i<notes.length;++i){showSlide(notes[i])}hideBackgrounds()}function singleSlideView(){var slide;for(var i=0;i<slides.length;++i){slide=slides[i];slide.style.position="absolute";if(i==slidenum){slide.style.borderStyle="none";showSlide(slide)}else{slide.style.borderStyle="none";hideSlide(slide)}}setVisibilityAllIncremental("visible");lastShown=previousIncrementalItem(null);var note;for(var i=0;i<notes.length;++i){hideSlide(notes[i])}}function hasToken(str,token){if(str){var pattern=/\w+/g;var result=str.match(pattern);for(var i=0;i<result.length;i++){if(result[i]==token){return true}}}return false}function getClassList(element){if(typeof element.className!="undefined"){return element.className}var clsname=(ns_pos||ie8)?"class":"className";return element.getAttribute(clsname)}function hasClass(element,name){var regexp=new RegExp("(^| )"+name+"W*");if(typeof element.className!="undefined"){return regexp.test(element.className)}var clsname=(ns_pos||ie8)?"class":"className";return regexp.test(element.getAttribute(clsname))}function removeClass(element,name){var regexp=new RegExp("(^| )"+name+"W*");var clsval="";if(typeof element.className!="undefined"){clsval=element.className;if(clsval){clsval=clsval.replace(regexp,"");element.className=clsval}}else{var clsname=(ns_pos||ie8)?"class":"className";clsval=element.getAttribute(clsname);if(clsval){clsval=clsval.replace(regexp,"");element.setAttribute(clsname,clsval)}}}function addClass(element,name){if(!hasClass(element,name)){if(typeof element.className!="undefined"){element.className+=" "+name}else{var clsname=(ns_pos||ie8)?"class":"className";var clsval=element.getAttribute(clsname);clsval=clsval?clsval+" "+name:name;element.setAttribute(clsname,clsval)}}}function wrapImplicitSlides(){var i,heading,node,next,div;var headings=document.getElementsByTagName("h1");if(!headings){return}for(i=0;i<headings.length;++i){heading=headings[i];if(heading.parentNode!=document.body){continue}node=heading.nextSibling;div=document.createElement("div");addClass(div,"slide");document.body.replaceChild(div,heading);div.appendChild(heading);while(node){if(node.nodeType==1&&(node.nodeName=="H1"||node.nodeName=="h1"||node.nodeName=="DIV"||node.nodeName=="div")){break}next=node.nextSibling;node=document.body.removeChild(node);div.appendChild(node);node=next}}}function collectSlides(){var slides=new Array();var divs=document.body.getElementsByTagName("div");for(var i=0;i<divs.length;++i){div=divs.item(i);if(hasClass(div,"slide")){slides[slides.length]=div;div.style.display="none";div.style.visibility="hidden";var node1=document.createElement("br");div.appendChild(node1);var node2=document.createElement("br");div.appendChild(node2)}else{if(hasClass(div,"background")){div.style.display="block"}}}return slides}function collectNotes(){var notes=new Array();var divs=document.body.getElementsByTagName("div");for(var i=0;i<divs.length;++i){div=divs.item(i);if(hasClass(div,"handout")){notes[notes.length]=div;div.style.display="none";div.style.visibility="hidden"}}return notes}function collectBackgrounds(){var backgrounds=new Array();var divs=document.body.getElementsByTagName("div");for(var i=0;i<divs.length;++i){div=divs.item(i);if(hasClass(div,"background")){backgrounds[backgrounds.length]=div;if(getClassList(div)!="background"){div.style.display="none";div.style.visibility="hidden"}}}return backgrounds}function syncBackground(slide){var background;var bgColor;if(slide.currentStyle){bgColor=slide.currentStyle.backgroundColor}else{if(document.defaultView){var styles=document.defaultView.getComputedStyle(slide,null);if(styles){bgColor=styles.getPropertyValue("background-color")}else{bgColor="transparent"}}else{bgColor=="transparent"}}if(bgColor=="transparent"){var slideClass=getClassList(slide);for(var i=0;i<backgrounds.length;i++){background=backgrounds[i];var bgClass=getClassList(background);if(matchingBackground(slideClass,bgClass)){background.style.display="block";background.style.visibility="visible"}else{background.style.display="none";background.style.visibility="hidden"}}}else{hideBackgrounds()}}function hideBackgrounds(){for(var i=0;i<backgrounds.length;i++){background=backgrounds[i];background.style.display="none";background.style.visibility="hidden"}}function matchingBackground(slideClass,bgClass){if(bgClass=="background"){return true}var pattern=/\w+/g;var result=slideClass.match(pattern);for(var i=0;i<result.length;i++){if(hasToken(bgClass,result[i])){return true}}return false}function nextNode(root,node){if(node==null){return root.firstChild}if(node.firstChild){return node.firstChild}if(node.nextSibling){return node.nextSibling}for(;;){node=node.parentNode;if(!node||node==root){break}if(node&&node.nextSibling){return node.nextSibling}}return null}function previousNode(root,node){if(node==null){node=root.lastChild;if(node){while(node.lastChild){node=node.lastChild}}return node}if(node.previousSibling){node=node.previousSibling;while(node.lastChild){node=node.lastChild}return node}if(node.parentNode!=root){return node.parentNode}return null}function incrementalElementList(){var inclist=new Array();inclist.P=true;inclist.PRE=true;inclist.LI=true;inclist.BLOCKQUOTE=true;inclist.DT=true;inclist.DD=true;inclist.H2=true;inclist.H3=true;inclist.H4=true;inclist.H5=true;inclist.H6=true;inclist.SPAN=true;inclist.ADDRESS=true;inclist.TABLE=true;inclist.TR=true;inclist.TH=true;inclist.TD=true;inclist.IMG=true;inclist.OBJECT=true;return inclist}function nextIncrementalItem(node){var slide=slides[slidenum];for(;;){node=nextNode(slide,node);if(node==null||node.parentNode==null){break}if(node.nodeType==1){if(node.nodeName=="BR"){continue}if(hasClass(node,"incremental")&&okayForIncremental[node.nodeName]){return node}if(hasClass(node.parentNode,"incremental")&&!hasClass(node,"non-incremental")){return node}}}return node}function previousIncrementalItem(node){var slide=slides[slidenum];for(;;){node=previousNode(slide,node);if(node==null||node.parentNode==null){break}if(node.nodeType==1){if(node.nodeName=="BR"){continue}if(hasClass(node,"incremental")&&okayForIncremental[node.nodeName]){return node}if(hasClass(node.parentNode,"incremental")&&!hasClass(node,"non-incremental")){return node}}}return node}function setVisibilityAllIncremental(value){var node=nextIncrementalItem(null);while(node){node.style.visibility=value;node=nextIncrementalItem(node)}}function revealNextItem(node){node=nextIncrementalItem(node);if(node&&node.nodeType==1){node.style.visibility="visible"}return node}function hidePreviousItem(node){if(node&&node.nodeType==1){node.style.visibility="hidden"}return previousIncrementalItem(node)}function patchAnchors(){var anchors=document.body.getElementsByTagName("a");for(var i=0;i<anchors.length;++i){anchors[i].onclick=clickedAnchor}}function clickedAnchor(e){if(!e){var e=window.event}if(pageAddress(this.href)==pageAddress(location.href)){var newslidenum=findSlideNumber(this.href);if(newslidenum!=slidenum){slide=slides[slidenum];hideSlide(slide);slidenum=newslidenum;slide=slides[slidenum];showSlide(slide);setLocation()}}else{if(this.target==null){location.href=this.href}}this.blur();stopPropagation(e)}function pageAddress(uri){var i=uri.indexOf("#");if(i<0){i=uri.indexOf("%23")}if(i<0){return uri}return uri.substr(0,i)}function showSlideNumber(){slideNumElement.innerHTML="slide".localize()+" "+(slidenum+1)+"/"+slides.length}function checkLocation(){var hash=location.hash;if(slidenum>0&&(hash==""||hash=="#")){gotoSlide(0)}else{if(hash.length>2&&hash!="#("+(slidenum+1)+")"){var num=parseInt(location.hash.substr(2));if(!isNaN(num)){gotoSlide(num-1)}}}}function setLocation(){var uri=pageAddress(location.href);var hash="#("+(slidenum+1)+")";if(slidenum>=0){uri=uri+hash}if(ie&&!ie8){pushHash(hash)}if(uri!=location.href){location.href=uri}if(khtml){hash="("+(slidenum+1)+")"}if(!ie&&location.hash!=hash&&location.hash!=""){location.hash=hash}document.title=title+" ("+(slidenum+1)+")";showSlideNumber()}function onFrameLoaded(hash){location.hash=hash;var uri=pageAddress(location.href);location.href=uri+hash}function pushHash(hash){if(hash==""){hash="#(1)"}window.location.hash=hash;var doc=document.getElementById("historyFrame").contentWindow.document;doc.open("javascript:'<html></html>'");doc.write('<html><head><script type="text/javascript">parent.onFrameLoaded(\''+(hash)+"');<\/script></head><body>hello mum</body></html>");doc.close()}function findSlideNumber(uri){var i=uri.indexOf("#");if(i<0){return 0}var anchor=unescape(uri.substr(i+1));var target=document.getElementById(anchor);if(!target){var re=/\((\d)+\)/;if(anchor.match(re)){var num=parseInt(anchor.substring(1,anchor.length-1));if(num>slides.length){num=1}if(--num<0){num=0}return num}re=/\[(\d)+\]/;if(anchor.match(re)){var num=parseInt(anchor.substring(1,anchor.length-1));if(num>slides.length){num=1}if(--num<0){num=0}return num}return 0}while(true){if(target.nodeName.toLowerCase()=="div"&&hasClass(target,"slide")){break}target=target.parentNode;if(!target){return 0}}for(i=0;i<slides.length;++i){if(slides[i]==target){return i}}return 0}function slideName(index){var name=null;var slide=slides[index];var heading=findHeading(slide);if(heading){name=extractText(heading)}if(!name){name=title+"("+(index+1)+")"}name.replace(/\&/g,"&amp;");name.replace(/\</g,"&lt;");name.replace(/\>/g,"&gt;");return name}function findHeading(node){if(!node||node.nodeType!=1){return null}if(node.nodeName=="H1"||node.nodeName=="h1"){return node}var child=node.firstChild;while(child){node=findHeading(child);if(node){return node}child=child.nextSibling}return null}function extractText(node){if(!node){return""}if(node.nodeType==3){return node.nodeValue}if(node.nodeType==1){node=node.firstChild;var text="";while(node){text=text+extractText(node);node=node.nextSibling}return text}return""}function findCopyright(){var name,content;var meta=document.getElementsByTagName("meta");for(var i=0;i<meta.length;++i){name=meta[i].getAttribute("name");content=meta[i].getAttribute("content");if(name=="copyright"){return content}}return null}function findSizeAdjust(){var name,content,offset;var meta=document.getElementsByTagName("meta");for(var i=0;i<meta.length;++i){name=meta[i].getAttribute("name");content=meta[i].getAttribute("content");if(name=="font-size-adjustment"){return 1*content}}return 1}function addToolbar(){var slideCounter,page;var toolbar=createElement("div");toolbar.setAttribute("class","toolbar");if(ns_pos){var right=document.createElement("div");right.setAttribute("style","float: right; text-align: right");slideCounter=document.createElement("div");slideCounter.innerHTML="slide".localize()+" n/m";right.appendChild(slideCounter);toolbar.appendChild(right);var left=document.createElement("div");left.setAttribute("style","text-align: left");eos=document.createElement("span");eos.innerHTML="* ";left.appendChild(eos);var help=document.createElement("a");help.setAttribute("href",helpPage);help.setAttribute("title",helpText.localize());help.innerHTML="help?".localize();left.appendChild(help);helpAnchor=help;var gap1=document.createTextNode(" ");left.appendChild(gap1);var contents=document.createElement("a");contents.setAttribute("href","javascript:toggleTableOfContents()");contents.setAttribute("title","table of contents".localize());contents.innerHTML="contents?".localize();left.appendChild(contents);var gap2=document.createTextNode(" ");left.appendChild(gap2);var start=document.createElement("a");start.setAttribute("href","javascript:firstSlide()");start.setAttribute("title","restart presentation".localize());start.innerHTML="restart?".localize();left.appendChild(start);var copyright=findCopyright();if(copyright){var span=document.createElement("span");span.innerHTML=copyright;span.style.color="black";span.style.marginLeft="4em";left.appendChild(span)}toolbar.appendChild(left)}else{toolbar.style.position=(ie7?"fixed":"absolute");toolbar.style.zIndex="200";toolbar.style.width="99.9%";toolbar.style.height="1.2em";toolbar.style.top="auto";toolbar.style.bottom="0";toolbar.style.left="0";toolbar.style.right="0";toolbar.style.textAlign="left";toolbar.style.fontSize="60%";toolbar.style.color="red";toolbar.borderWidth=0;toolbar.className="toolbar";toolbar.style.background="rgb(240,240,240)";var sp=document.createElement("span");sp.innerHTML="&nbsp;&nbsp;*&nbsp;";toolbar.appendChild(sp);eos=sp;var help=document.createElement("a");help.setAttribute("href",helpPage);help.setAttribute("title",helpText.localize());help.innerHTML="help?".localize();toolbar.appendChild(help);helpAnchor=help;var gap1=document.createTextNode(" ");toolbar.appendChild(gap1);var contents=document.createElement("a");contents.setAttribute("href","javascript:toggleTableOfContents()");contents.setAttribute("title","table of contents".localize());contents.innerHTML="contents?".localize();toolbar.appendChild(contents);var gap2=document.createTextNode(" ");toolbar.appendChild(gap2);var start=document.createElement("a");start.setAttribute("href","javascript:firstSlide()");start.setAttribute("title","restart presentation".localize());start.innerHTML="restart?".localize();toolbar.appendChild(start);var copyright=findCopyright();if(copyright){var span=document.createElement("span");span.innerHTML=copyright;span.style.color="black";span.style.marginLeft="2em";toolbar.appendChild(span)}slideCounter=document.createElement("div");slideCounter.style.position="absolute";slideCounter.style.width="auto";slideCounter.style.height="1.2em";slideCounter.style.top="auto";slideCounter.style.bottom=0;slideCounter.style.right="0";slideCounter.style.textAlign="right";slideCounter.style.color="red";slideCounter.style.background="rgb(240,240,240)";slideCounter.innerHTML="slide".localize()+" n/m";toolbar.appendChild(slideCounter)}toolbar.onclick=stopPropagation;document.body.appendChild(toolbar);slideNumElement=slideCounter;setEosStatus(false);return toolbar}function isShownToc(){if(toc&&toc.style.visible=="visible"){return true}return false}function showTableOfContents(){if(toc){if(toc.style.visibility!="visible"){toc.style.visibility="visible";toc.style.display="block";toc.focus();if(ie7&&slidenum==0){setTimeout("ieHack()",100)}}else{hideTableOfContents()}}}function hideTableOfContents(){if(toc&&toc.style.visibility!="hidden"){toc.style.visibility="hidden";toc.style.display="none";try{if(!opera){helpAnchor.focus()}}catch(e){}}}function toggleTableOfContents(){if(toc){if(toc.style.visible!="visible"){showTableOfContents()}else{hideTableOfContents()}}}function gotoEntry(e){var target;if(!e){var e=window.event}if(e.target){target=e.target}else{if(e.srcElement){target=e.srcElement}}if(target.nodeType==3){target=target.parentNode}if(target&&target.nodeType==1){var uri=target.getAttribute("href");if(uri){var slide=slides[slidenum];hideSlide(slide);slidenum=findSlideNumber(uri);slide=slides[slidenum];lastShown=null;setLocation();setVisibilityAllIncremental("hidden");setEosStatus(!nextIncrementalItem(lastShown));showSlide(slide);try{if(!opera){helpAnchor.focus()}}catch(e){}}}hideTableOfContents(e);if(ie7){ieHack()}stopPropagation(e);return cancel(e)}function gotoTocEntry(event){var key;if(!event){var event=window.event}if(window.event){key=window.event.keyCode}else{if(event.which){key=event.which}else{return true}}if(!key){return true}if(event.ctrlKey||event.altKey){return true}if(key==13){var uri=this.getAttribute("href");if(uri){var slide=slides[slidenum];hideSlide(slide);slidenum=findSlideNumber(uri);slide=slides[slidenum];lastShown=null;setLocation();setVisibilityAllIncremental("hidden");setEosStatus(!nextIncrementalItem(lastShown));showSlide(slide);try{if(!opera){helpAnchor.focus()}}catch(e){}}hideTableOfContents();if(ie7){ieHack()}return cancel(event)}if(key==40&&this.next){this.next.focus();return cancel(event)}if(key==38&&this.previous){this.previous.focus();return cancel(event)}return true}function isTitleSlide(slide){return hasClass(slide,"title")}function tableOfContents(){var toc=document.createElement("div");addClass(toc,"toc");var heading=document.createElement("div");addClass(heading,"toc-heading");heading.innerHTML="Table of Contents".localize();heading.style.textAlign="center";heading.style.width="100%";heading.style.margin="0";heading.style.marginBottom="1em";heading.style.borderBottomStyle="solid";heading.style.borderBottomColor="rgb(180,180,180)";heading.style.borderBottomWidth="1px";toc.appendChild(heading);var previous=null;for(var i=0;i<slides.length;++i){var title=hasClass(slides[i],"title");var num=document.createTextNode((i+1)+". ");toc.appendChild(num);var a=document.createElement("a");a.setAttribute("href","#("+(i+1)+")");if(title){addClass(a,"titleslide")}var name=document.createTextNode(slideName(i));a.appendChild(name);a.onclick=gotoEntry;a.onkeydown=gotoTocEntry;a.previous=previous;if(previous){previous.next=a}toc.appendChild(a);if(i==0){toc.first=a}if(i<slides.length-1){var br=document.createElement("br");toc.appendChild(br)}previous=a}toc.focus=function(){if(this.first){this.first.focus()}};toc.onmouseup=mouseButtonUp;toc.onclick=function(e){e||(e=window.event);if(selectedTextLen<=0){hideTableOfContents()}stopPropagation(e);if(e.cancel!=undefined){e.cancel=true}if(e.returnValue!=undefined){e.returnValue=false}return false};toc.style.position="absolute";toc.style.zIndex="300";toc.style.width="60%";toc.style.maxWidth="30em";toc.style.height="30em";toc.style.overflow="auto";toc.style.top="auto";toc.style.right="auto";toc.style.left="4em";toc.style.bottom="4em";toc.style.padding="1em";toc.style.background="rgb(240,240,240)";toc.style.borderStyle="solid";toc.style.borderWidth="2px";toc.style.fontSize="60%";document.body.insertBefore(toc,document.body.firstChild);return toc}function replaceByNonBreakingSpace(str){for(var i=0;i<str.length;++i){str[i]=160}}function initOutliner(){var items=document.getElementsByTagName("LI");for(var i=0;i<items.length;++i){var target=items[i];if(!hasClass(target.parentNode,"outline")){continue}target.onclick=outlineClick;if(!ns_pos){target.onmouseover=hoverOutline;target.onmouseout=unhoverOutline}if(foldable(target)){target.foldable=true;target.onfocus=function(){outline=this};target.onblur=function(){outline=null};if(!target.getAttribute("tabindex")){target.setAttribute("tabindex","0")}if(hasClass(target,"expand")){unfold(target)}else{fold(target)}}else{addClass(target,"nofold");target.visible=true;target.foldable=false}}}function foldable(item){if(!item||item.nodeType!=1){return false}var node=item.firstChild;while(node){if(node.nodeType==1&&isBlock(node)){return true}node=node.nextSibling}return false}function fold(item){if(item){removeClass(item,"unfolded");addClass(item,"folded")}var node=item?item.firstChild:null;while(node){if(node.nodeType==1&&isBlock(node)){node.display=getElementStyle(node,"display","display");node.style.display="none";node.style.visibility="hidden"}node=node.nextSibling}item.visible=false}function unfold(item){if(item){addClass(item,"unfolded");removeClass(item,"folded")}var node=item?item.firstChild:null;while(node){if(node.nodeType==1&&isBlock(node)){node.style.display=(node.display?node.display:"block");node.style.visibility="visible"}node=node.nextSibling}item.visible=true}function outlineClick(e){var rightclick=false;var target;if(!e){var e=window.event}if(e.target){target=e.target}else{if(e.srcElement){target=e.srcElement}}if(target.nodeType==3){target=target.parentNode}while(target&&target.visible==undefined){target=target.parentNode}if(!target){return true}if(e.which){rightclick=(e.which==3)}else{if(e.button){rightclick=(e.button==2)}}if(!rightclick&&target.visible!=undefined){if(target.foldable){if(target.visible){fold(target)}else{unfold(target)}}stopPropagation(e);e.cancel=true;e.returnValue=false}return false}function hoverOutline(e){var target;if(!e){var e=window.event}if(e.target){target=e.target}else{if(e.srcElement){target=e.srcElement}}if(target.nodeType==3){target=target.parentNode}while(target&&target.visible==undefined){target=target.parentNode}if(target&&target.foldable){target.style.cursor="pointer"}return true}function unhoverOutline(e){var target;if(!e){var e=window.event}if(e.target){target=e.target}else{if(e.srcElement){target=e.srcElement}}if(target.nodeType==3){target=target.parentNode}while(target&&target.visible==undefined){target=target.parentNode}if(target){target.style.cursor="default"}return true}function stopPropagation(e){if(window.event){window.event.cancelBubble=true}else{if(e){e.cancelBubble=true;e.stopPropagation()}}}function isBlock(elem){var tag=elem.nodeName;return tag=="OL"||tag=="UL"||tag=="P"||tag=="LI"||tag=="TABLE"||tag=="PRE"||tag=="H1"||tag=="H2"||tag=="H3"||tag=="H4"||tag=="H5"||tag=="H6"||tag=="BLOCKQUOTE"||tag=="ADDRESS"}function getElementStyle(elem,IEStyleProp,CSSStyleProp){if(elem.currentStyle){return elem.currentStyle[IEStyleProp]}else{if(window.getComputedStyle){var compStyle=window.getComputedStyle(elem,"");return compStyle.getPropertyValue(CSSStyleProp)}}return""}function createElement(element){if(typeof document.createElementNS!="undefined"){return document.createElementNS("http://www.w3.org/1999/xhtml",element)}if(typeof document.createElement!="undefined"){return document.createElement(element)}return false}function getElementsByTagName(name){if(typeof document.getElementsByTagNameNS!="undefined"){return document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml",name)}if(typeof document.getElementsByTagName!="undefined"){return document.getElementsByTagName(name)}return null}function getSelectedText(){try{if(window.getSelection){return window.getSelection().toString()}if(document.getSelection){return document.getSelection().toString()}if(document.selection){return document.selection.createRange().text}}catch(e){return""}return""}; \ No newline at end of file
diff --git a/src/Text/Pandoc.hs b/src/Text/Pandoc.hs
index 9cad5fb34..ad429bc93 100644
--- a/src/Text/Pandoc.hs
+++ b/src/Text/Pandoc.hs
@@ -71,6 +71,7 @@ module Text.Pandoc
, NoteTable
, HeaderType (..)
-- * Writers: converting /from/ Pandoc format
+ , writeNative
, writeMarkdown
, writePlain
, writeRST
@@ -79,16 +80,16 @@ module Text.Pandoc
, writeTexinfo
, writeHtml
, writeHtmlString
- , writeS5
- , writeS5String
, writeDocbook
, writeOpenDocument
, writeMan
, writeMediaWiki
, writeRTF
- , prettyPandoc
+ , writeODT
+ , writeEPUB
-- * Writer options used in writers
, WriterOptions (..)
+ , HTMLSlideVariant (..)
, HTMLMathMethod (..)
, defaultWriterOptions
-- * Rendering templates and default templates
@@ -102,19 +103,22 @@ import Text.Pandoc.Readers.Markdown
import Text.Pandoc.Readers.RST
import Text.Pandoc.Readers.LaTeX
import Text.Pandoc.Readers.HTML
+import Text.Pandoc.Writers.Native
import Text.Pandoc.Writers.Markdown
import Text.Pandoc.Writers.RST
import Text.Pandoc.Writers.LaTeX
import Text.Pandoc.Writers.ConTeXt
import Text.Pandoc.Writers.Texinfo
import Text.Pandoc.Writers.HTML
-import Text.Pandoc.Writers.S5
+import Text.Pandoc.Writers.ODT
+import Text.Pandoc.Writers.EPUB
import Text.Pandoc.Writers.Docbook
import Text.Pandoc.Writers.OpenDocument
import Text.Pandoc.Writers.Man
import Text.Pandoc.Writers.RTF
import Text.Pandoc.Writers.MediaWiki
import Text.Pandoc.Templates
+import Text.Pandoc.Parsing
import Text.Pandoc.Shared
import Data.Version (showVersion)
import Paths_pandoc (version)
diff --git a/src/Text/Pandoc/Definition.hs b/src/Text/Pandoc/Definition.hs
index 169c4d1a6..fffca3b2e 100644
--- a/src/Text/Pandoc/Definition.hs
+++ b/src/Text/Pandoc/Definition.hs
@@ -33,36 +33,37 @@ module Text.Pandoc.Definition where
import Data.Generics
-data Pandoc = Pandoc Meta [Block] deriving (Eq, Read, Show, Typeable, Data)
+data Pandoc = Pandoc Meta [Block] deriving (Eq, Ord, Read, Show, Typeable, Data)
-- | Bibliographic information for the document: title, authors, date.
data Meta = Meta { docTitle :: [Inline]
, docAuthors :: [[Inline]]
, docDate :: [Inline] }
- deriving (Eq, Show, Read, Typeable, Data)
+ deriving (Eq, Ord, Show, Read, Typeable, Data)
-- | Alignment of a table column.
data Alignment = AlignLeft
| AlignRight
| AlignCenter
- | AlignDefault deriving (Eq, Show, Read, Typeable, Data)
+ | AlignDefault deriving (Eq, Ord, Show, Read, Typeable, Data)
-- | List attributes.
type ListAttributes = (Int, ListNumberStyle, ListNumberDelim)
-- | Style of list numbers.
data ListNumberStyle = DefaultStyle
+ | Example
| Decimal
| LowerRoman
| UpperRoman
| LowerAlpha
- | UpperAlpha deriving (Eq, Show, Read, Typeable, Data)
+ | UpperAlpha deriving (Eq, Ord, Show, Read, Typeable, Data)
-- | Delimiter of list numbers.
data ListNumberDelim = DefaultDelim
| Period
| OneParen
- | TwoParens deriving (Eq, Show, Read, Typeable, Data)
+ | TwoParens deriving (Eq, Ord, Show, Read, Typeable, Data)
-- | Attributes: identifier, classes, key-value pairs
type Attr = (String, [String], [(String, String)])
@@ -90,16 +91,16 @@ data Block
-- column headers (each a list of blocks), and
-- rows (each a list of lists of blocks)
| Null -- ^ Nothing
- deriving (Eq, Read, Show, Typeable, Data)
+ deriving (Eq, Ord, Read, Show, Typeable, Data)
-- | Type of quotation marks to use in Quoted inline.
-data QuoteType = SingleQuote | DoubleQuote deriving (Show, Eq, Read, Typeable, Data)
+data QuoteType = SingleQuote | DoubleQuote deriving (Show, Eq, Ord, Read, Typeable, Data)
-- | Link target (URL, title).
type Target = (String, String)
-- | Type of math element (display or inline).
-data MathType = DisplayMath | InlineMath deriving (Show, Eq, Read, Typeable, Data)
+data MathType = DisplayMath | InlineMath deriving (Show, Eq, Ord, Read, Typeable, Data)
-- | Inline elements.
data Inline
@@ -126,7 +127,7 @@ data Inline
| Image [Inline] Target -- ^ Image: alt text (list of inlines), target
-- and target
| Note [Block] -- ^ Footnote or endnote
- deriving (Show, Eq, Read, Typeable, Data)
+ deriving (Show, Eq, Ord, Read, Typeable, Data)
-- | Applies a transformation on @a@s to matching elements in a @b@.
processWith :: (Data a, Data b) => (a -> a) -> b -> b
diff --git a/src/Text/Pandoc/ODT.hs b/src/Text/Pandoc/ODT.hs
deleted file mode 100644
index d978c0cb4..000000000
--- a/src/Text/Pandoc/ODT.hs
+++ /dev/null
@@ -1,102 +0,0 @@
-{-
-Copyright (C) 2008-2010 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.ODT
- Copyright : Copyright (C) 2008-2010 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Functions for producing an ODT file from OpenDocument XML.
--}
-module Text.Pandoc.ODT ( saveOpenDocumentAsODT ) where
-import Data.List ( find )
-import System.FilePath ( (</>), takeFileName )
-import qualified Data.ByteString.Lazy as B
-import Data.ByteString.Lazy.UTF8 ( fromString )
-import Prelude hiding ( writeFile, readFile )
-import Codec.Archive.Zip
-import Control.Applicative ( (<$>) )
-import Text.ParserCombinators.Parsec
-import System.Time
-import Paths_pandoc ( getDataFileName )
-import System.Directory
-import Control.Monad (liftM)
-
--- | Produce an ODT file from OpenDocument XML.
-saveOpenDocumentAsODT :: Maybe FilePath -- ^ Path of user data directory
- -> FilePath -- ^ Pathname of ODT file to be produced
- -> FilePath -- ^ Relative directory of source file
- -> Maybe FilePath -- ^ Path specified by --reference-odt
- -> String -- ^ OpenDocument XML contents
- -> IO ()
-saveOpenDocumentAsODT datadir destinationODTPath sourceDirRelative mbRefOdt xml = do
- refArchive <- liftM toArchive $
- case mbRefOdt of
- Just f -> B.readFile f
- Nothing -> do
- let defaultODT = getDataFileName "reference.odt" >>= B.readFile
- case datadir of
- Nothing -> defaultODT
- Just d -> do
- exists <- doesFileExist (d </> "reference.odt")
- if exists
- then B.readFile (d </> "reference.odt")
- else defaultODT
- -- handle pictures
- let (newContents, pics) =
- case runParser pPictures [] "OpenDocument XML contents" xml of
- Left err -> error $ show err
- Right x -> x
- picEntries <- mapM (makePictureEntry sourceDirRelative) pics
- (TOD epochTime _) <- getClockTime
- let contentEntry = toEntry "content.xml" epochTime $ fromString newContents
- let archive = foldr addEntryToArchive refArchive (contentEntry : picEntries)
- B.writeFile destinationODTPath $ fromArchive archive
-
-makePictureEntry :: FilePath -- ^ Relative directory of source file
- -> (FilePath, String) -- ^ Path and new path of picture
- -> IO Entry
-makePictureEntry sourceDirRelative (path, newPath) = do
- entry <- readEntry [] $ sourceDirRelative </> path
- return (entry { eRelativePath = newPath })
-
-pPictures :: GenParser Char [(FilePath, String)] ([Char], [(FilePath, String)])
-pPictures = do
- contents <- concat <$> many (pPicture <|> many1 (noneOf "<") <|> string "<")
- pics <- getState
- return (contents, pics)
-
-pPicture :: GenParser Char [(FilePath, String)] [Char]
-pPicture = try $ do
- string "<draw:image xlink:href=\""
- path <- manyTill anyChar (char '"')
- let filename = takeFileName path
- pics <- getState
- newPath <- case find (\(o, _) -> o == path) pics of
- Just (_, new) -> return new
- Nothing -> do
- -- get a unique name
- let dups = length $ (filter (\(o, _) -> takeFileName o == filename)) pics
- let new = "Pictures/" ++ replicate dups '0' ++ filename
- updateState ((path, new) :)
- return new
- return $ "<draw:image xlink:href=\"" ++ newPath ++ "\""
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
new file mode 100644
index 000000000..3678fc22a
--- /dev/null
+++ b/src/Text/Pandoc/Parsing.hs
@@ -0,0 +1,700 @@
+{-
+Copyright (C) 2006-2010 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.Parsing
+ Copyright : Copyright (C) 2006-2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+A utility library with parsers used in pandoc readers.
+-}
+module Text.Pandoc.Parsing ( (>>~),
+ anyLine,
+ many1Till,
+ notFollowedBy',
+ oneOfStrings,
+ spaceChar,
+ skipSpaces,
+ blankline,
+ blanklines,
+ enclosed,
+ stringAnyCase,
+ parseFromString,
+ lineClump,
+ charsInBalanced,
+ charsInBalanced',
+ romanNumeral,
+ emailAddress,
+ uri,
+ withHorizDisplacement,
+ nullBlock,
+ failIfStrict,
+ failUnlessLHS,
+ escaped,
+ anyOrderedListMarker,
+ orderedListMarker,
+ charRef,
+ tableWith,
+ gridTableWith,
+ readWith,
+ testStringWith,
+ ParserState (..),
+ defaultParserState,
+ HeaderType (..),
+ ParserContext (..),
+ QuoteContext (..),
+ NoteTable,
+ KeyTable,
+ Key (..),
+ lookupKeySrc,
+ refsMatch )
+where
+
+import Text.Pandoc.Definition
+import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn)
+import Text.ParserCombinators.Parsec
+import Text.Pandoc.CharacterReferences ( characterReference )
+import Data.Char ( toLower, toUpper, ord, isAscii )
+import Data.List ( intercalate, transpose )
+import Network.URI ( parseURI, URI (..), isAllowedInURI )
+import Control.Monad ( join, liftM )
+import Text.Pandoc.Shared
+import qualified Data.Map as M
+
+-- | Like >>, but returns the operation on the left.
+-- (Suggested by Tillmann Rendel on Haskell-cafe list.)
+(>>~) :: (Monad m) => m a -> m b -> m a
+a >>~ b = a >>= \x -> b >> return x
+
+-- | Parse any line of text
+anyLine :: GenParser 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 p end = do
+ first <- p
+ rest <- manyTill p end
+ return (first:rest)
+
+-- | 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' 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 a space or tab.
+spaceChar :: CharParser st Char
+spaceChar = char ' ' <|> char '\t'
+
+-- | Skips zero or more spaces or tabs.
+skipSpaces :: GenParser Char st ()
+skipSpaces = skipMany spaceChar
+
+-- | Skips zero or more spaces or tabs, then reads a newline.
+blankline :: GenParser 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 = 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 $
+ start >> notFollowedBy space >> many1Till parser end
+
+-- | Parse string, case insensitive.
+stringAnyCase :: [Char] -> CharParser st String
+stringAnyCase [] = string ""
+stringAnyCase (x:xs) = do
+ firstChar <- char (toUpper x) <|> char (toLower x)
+ rest <- stringAnyCase xs
+ return (firstChar:rest)
+
+-- | Parse contents of 'str' using 'parser' and return result.
+parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a
+parseFromString parser str = do
+ oldPos <- getPosition
+ oldInput <- getInput
+ setInput str
+ result <- parser
+ setInput oldInput
+ setPosition oldPos
+ return result
+
+-- | Parse raw line block up to and including blank lines.
+lineClump :: GenParser Char st String
+lineClump = blanklines
+ <|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines)
+
+-- | Parse a string of characters between an open character
+-- and a close character, including text between balanced
+-- pairs of open and close, which must be different. For example,
+-- @charsInBalanced '(' ')'@ will parse "(hello (there))"
+-- and return "hello (there)". Stop if a blank line is
+-- encountered.
+charsInBalanced :: Char -> Char -> GenParser Char st String
+charsInBalanced open close = try $ do
+ char open
+ raw <- many $ (many1 (noneOf [open, close, '\n']))
+ <|> (do res <- charsInBalanced open close
+ return $ [open] ++ res ++ [close])
+ <|> try (string "\n" >>~ notFollowedBy' blanklines)
+ char close
+ return $ concat raw
+
+-- | Like @charsInBalanced@, but allow blank lines in the content.
+charsInBalanced' :: Char -> Char -> GenParser Char st String
+charsInBalanced' open close = try $ do
+ char open
+ raw <- many $ (many1 (noneOf [open, close]))
+ <|> (do res <- charsInBalanced' open close
+ return $ [open] ++ res ++ [close])
+ char close
+ return $ concat raw
+
+-- Auxiliary functions for romanNumeral:
+
+lowercaseRomanDigits :: [Char]
+lowercaseRomanDigits = ['i','v','x','l','c','d','m']
+
+uppercaseRomanDigits :: [Char]
+uppercaseRomanDigits = map toUpper lowercaseRomanDigits
+
+-- | Parses a roman numeral (uppercase or lowercase), returns number.
+romanNumeral :: Bool -- ^ Uppercase if true
+ -> GenParser Char st Int
+romanNumeral upperCase = do
+ let romanDigits = if upperCase
+ then uppercaseRomanDigits
+ else lowercaseRomanDigits
+ lookAhead $ oneOf romanDigits
+ let [one, five, ten, fifty, hundred, fivehundred, thousand] =
+ map char romanDigits
+ thousands <- many thousand >>= (return . (1000 *) . length)
+ ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900
+ fivehundreds <- many fivehundred >>= (return . (500 *) . length)
+ fourhundreds <- option 0 $ try $ hundred >> fivehundred >> return 400
+ hundreds <- many hundred >>= (return . (100 *) . length)
+ nineties <- option 0 $ try $ ten >> hundred >> return 90
+ fifties <- many fifty >>= (return . (50 *) . length)
+ forties <- option 0 $ try $ ten >> fifty >> return 40
+ tens <- many ten >>= (return . (10 *) . length)
+ nines <- option 0 $ try $ one >> ten >> return 9
+ fives <- many five >>= (return . (5 *) . length)
+ fours <- option 0 $ try $ one >> five >> return 4
+ ones <- many one >>= (return . length)
+ let total = thousands + ninehundreds + fivehundreds + fourhundreds +
+ hundreds + nineties + fifties + forties + tens + nines +
+ fives + fours + ones
+ if total == 0
+ then fail "not a roman numeral"
+ else return total
+
+-- Parsers for email addresses and URIs
+
+emailChar :: GenParser Char st Char
+emailChar = alphaNum <|> oneOf "-+_."
+
+domainChar :: GenParser Char st Char
+domainChar = alphaNum <|> char '-'
+
+domain :: GenParser Char st [Char]
+domain = do
+ first <- many1 domainChar
+ dom <- many1 $ try (char '.' >> many1 domainChar )
+ return $ intercalate "." (first:dom)
+
+-- | Parses an email address; returns original and corresponding
+-- escaped mailto: URI.
+emailAddress :: GenParser Char st (String, String)
+emailAddress = try $ do
+ firstLetter <- alphaNum
+ restAddr <- many emailChar
+ let addr = firstLetter:restAddr
+ char '@'
+ dom <- domain
+ let full = addr ++ '@':dom
+ return (full, escapeURI $ "mailto:" ++ full)
+
+-- | Parses a URI. Returns pair of original and URI-escaped version.
+uri :: GenParser Char st (String, String)
+uri = try $ do
+ let protocols = [ "http:", "https:", "ftp:", "file:", "mailto:",
+ "news:", "telnet:" ]
+ lookAhead $ oneOfStrings protocols
+ -- scan non-ascii characters and ascii characters allowed in a URI
+ str <- many1 $ satisfy (\c -> not (isAscii c) || isAllowedInURI c)
+ -- now see if they amount to an absolute URI
+ case parseURI (escapeURI str) of
+ Just uri' -> if uriScheme uri' `elem` protocols
+ then return (str, show uri')
+ else fail "not a URI"
+ Nothing -> fail "not a URI"
+
+-- | Applies a parser, returns tuple of its results and its horizontal
+-- 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 = do
+ pos1 <- getPosition
+ result <- parser
+ pos2 <- getPosition
+ return (result, sourceColumn pos2 - sourceColumn pos1)
+
+-- | Parses a character and returns 'Null' (so that the parser can move on
+-- if it gets stuck).
+nullBlock :: GenParser Char st Block
+nullBlock = anyChar >> return Null
+
+-- | Fail if reader is in strict markdown syntax mode.
+failIfStrict :: GenParser Char 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 = do
+ state <- getState
+ if stateLiterateHaskell state then return () else fail "Literate haskell feature"
+
+-- | Parses backslash, then applies character parser.
+escaped :: GenParser Char st Char -- ^ Parser for character to escape
+ -> GenParser Char st Inline
+escaped parser = try $ do
+ char '\\'
+ result <- parser
+ return (Str [result])
+
+-- | Parses an uppercase roman numeral and returns (UpperRoman, number).
+upperRoman :: GenParser 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 = do
+ num <- romanNumeral False
+ return (LowerRoman, num)
+
+-- | Parses a decimal numeral and returns (Decimal, number).
+decimal :: GenParser Char st (ListNumberStyle, Int)
+decimal = do
+ num <- many1 digit
+ return (Decimal, read num)
+
+-- | Parses a '@' and optional label and
+-- 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 = do
+ char '@'
+ lab <- many (alphaNum <|> oneOf "_-")
+ st <- getState
+ let num = stateNextExample st
+ let newlabels = if null lab
+ then stateExamples st
+ else M.insert lab num $ stateExamples st
+ updateState $ \s -> s{ stateNextExample = num + 1
+ , stateExamples = newlabels }
+ return (Example, num)
+
+-- | Parses a '#' returns (DefaultStyle, 1).
+defaultNum :: GenParser 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 = 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 = 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 = (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 $
+ [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 num = try $ do
+ (style, start) <- num
+ char '.'
+ let delim = if style == DefaultStyle
+ 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 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 num = try $ do
+ char '('
+ (style, start) <- num
+ char ')'
+ return (start, style, TwoParens)
+
+-- | Parses an ordered list marker with a given style and delimiter,
+-- returns number.
+orderedListMarker :: ListNumberStyle
+ -> ListNumberDelim
+ -> GenParser Char ParserState Int
+orderedListMarker style delim = do
+ let num = defaultNum <|> -- # can continue any kind of list
+ case style of
+ DefaultStyle -> decimal
+ Example -> exampleNum
+ Decimal -> decimal
+ UpperRoman -> upperRoman
+ LowerRoman -> lowerRoman
+ UpperAlpha -> upperAlpha
+ LowerAlpha -> lowerAlpha
+ let context = case delim of
+ DefaultDelim -> inPeriod
+ Period -> inPeriod
+ OneParen -> inOneParen
+ TwoParens -> inTwoParens
+ (start, _, _) <- context num
+ return start
+
+-- | Parses a character reference and returns a Str element.
+charRef :: GenParser 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
+ (heads, aligns, indices) <- headerParser
+ lines' <- rowParser indices `sepEndBy` 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'
+
+-- 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 =
+ let lengths' = zipWith (-) indices (0:indices)
+ lengths = reverse $
+ case reverse lengths' of
+ [] -> []
+ [x] -> [x]
+ -- compensate for the fact that intercolumn
+ -- spaces are counted in widths of all columns
+ -- but the last...
+ (x:y:zs) -> if x < y && y - x <= 2
+ then y:y:zs
+ else x:y:zs
+ totLength = sum lengths
+ quotient = if totLength > numColumns
+ then fromIntegral totLength
+ else fromIntegral numColumns
+ 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
+ -> Bool -- ^ Headerless table
+ -> GenParser Char ParserState Block
+gridTableWith block tableCaption headless =
+ tableWith (gridTableHeader headless block) (gridTableRow block) (gridTableSep '-') gridTableFooter tableCaption
+
+gridTableSplitLine :: [Int] -> String -> [String]
+gridTableSplitLine indices line =
+ map removeFinalBar $ tail $ splitByIndices (init indices) line
+
+gridPart :: Char -> GenParser 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 ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline
+
+removeFinalBar :: String -> String
+removeFinalBar = reverse . dropWhile (=='|') . dropWhile (`elem` " \t") .
+ reverse
+
+-- | Separator between rows of grid table.
+gridTableSep :: Char -> GenParser 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
+ 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 <- mapM (parseFromString $ many block) $
+ map removeLeadingTrailingSpace rawHeads
+ return (heads, aligns, indices)
+
+gridTableRawLine :: [Int] -> GenParser Char ParserState [String]
+gridTableRawLine indices = do
+ char '|'
+ line <- many1Till anyChar newline
+ return (gridTableSplitLine indices $ removeTrailingSpace line)
+
+-- | Parse row of grid table.
+gridTableRow :: GenParser Char ParserState Block
+ -> [Int]
+ -> GenParser Char ParserState [[Block]]
+gridTableRow block indices = do
+ colLines <- many1 (gridTableRawLine indices)
+ let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
+ transpose colLines
+ mapM (liftM compactifyCell . parseFromString (many block)) cols
+
+removeOneLeadingSpace :: [String] -> [String]
+removeOneLeadingSpace xs =
+ if all startsWithSpace xs
+ then map (drop 1) xs
+ else xs
+ where startsWithSpace "" = True
+ startsWithSpace (y:_) = y == ' '
+
+compactifyCell :: [Block] -> [Block]
+compactifyCell bs = head $ compactify [bs]
+
+-- | Parse footer for a grid table.
+gridTableFooter :: GenParser Char ParserState [Char]
+gridTableFooter = blanklines
+
+---
+
+-- | Parse a string with a given parser and state.
+readWith :: GenParser Char ParserState a -- ^ parser
+ -> ParserState -- ^ initial state
+ -> String -- ^ input string
+ -> a
+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
+ -> String
+ -> IO ()
+testStringWith parser str = UTF8.putStrLn $ show $
+ readWith parser defaultParserState str
+
+-- | Parsing options.
+data ParserState = ParserState
+ { stateParseRaw :: Bool, -- ^ Parse raw HTML and LaTeX?
+ stateParserContext :: ParserContext, -- ^ Inside list?
+ stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment?
+ stateSanitizeHTML :: Bool, -- ^ Sanitize HTML?
+ stateKeys :: KeyTable, -- ^ List of reference keys
+#ifdef _CITEPROC
+ stateCitations :: [String], -- ^ List of available citations
+#endif
+ stateNotes :: NoteTable, -- ^ List of notes
+ stateTabStop :: Int, -- ^ Tab stop
+ stateStandalone :: Bool, -- ^ Parse bibliographic info?
+ 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?
+ 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
+ stateHasChapters :: Bool -- ^ True if \chapter encountered
+ }
+ deriving Show
+
+defaultParserState :: ParserState
+defaultParserState =
+ ParserState { stateParseRaw = False,
+ stateParserContext = NullState,
+ stateQuoteContext = NoQuote,
+ stateSanitizeHTML = False,
+ stateKeys = M.empty,
+#ifdef _CITEPROC
+ stateCitations = [],
+#endif
+ stateNotes = [],
+ stateTabStop = 4,
+ stateStandalone = False,
+ stateTitle = [],
+ stateAuthors = [],
+ stateDate = [],
+ stateStrict = False,
+ stateSmart = False,
+ stateLiterateHaskell = False,
+ stateColumns = 80,
+ stateHeaderTable = [],
+ stateIndentedCodeClasses = [],
+ stateNextExample = 1,
+ stateExamples = M.empty,
+ stateHasChapters = False }
+
+data HeaderType
+ = SingleHeader Char -- ^ Single line of characters underneath
+ | DoubleHeader Char -- ^ Lines of characters above and below
+ deriving (Eq, Show)
+
+data ParserContext
+ = ListItemState -- ^ Used when running parser on list item contents
+ | NullState -- ^ Default state
+ deriving (Eq, Show)
+
+data QuoteContext
+ = InSingleQuote -- ^ Used when parsing inside single quotes
+ | InDoubleQuote -- ^ Used when parsing inside double quotes
+ | NoQuote -- ^ Used when not parsing inside quotes
+ deriving (Eq, Show)
+
+type NoteTable = [(String, String)]
+
+newtype Key = Key [Inline] deriving (Show, Read)
+
+instance Eq Key where
+ Key a == Key b = refsMatch a b
+
+instance Ord Key where
+ compare (Key a) (Key b) = if a == b then EQ else compare a b
+
+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
+
+-- | Returns @True@ if keys match (case insensitive).
+refsMatch :: [Inline] -> [Inline] -> Bool
+refsMatch ((Str x):restx) ((Str y):resty) =
+ ((map toLower x) == (map toLower y)) && refsMatch restx resty
+refsMatch ((Emph x):restx) ((Emph y):resty) =
+ refsMatch x y && refsMatch restx resty
+refsMatch ((Strong x):restx) ((Strong y):resty) =
+ refsMatch x y && refsMatch restx resty
+refsMatch ((Strikeout x):restx) ((Strikeout y):resty) =
+ refsMatch x y && refsMatch restx resty
+refsMatch ((Superscript x):restx) ((Superscript y):resty) =
+ refsMatch x y && refsMatch restx resty
+refsMatch ((Subscript x):restx) ((Subscript y):resty) =
+ refsMatch x y && refsMatch restx resty
+refsMatch ((SmallCaps x):restx) ((SmallCaps y):resty) =
+ refsMatch x y && refsMatch restx resty
+refsMatch ((Quoted t x):restx) ((Quoted u y):resty) =
+ t == u && refsMatch x y && refsMatch restx resty
+refsMatch ((Code x):restx) ((Code y):resty) =
+ ((map toLower x) == (map toLower y)) && refsMatch restx resty
+refsMatch ((Math t x):restx) ((Math u y):resty) =
+ ((map toLower x) == (map toLower y)) && t == u && refsMatch restx resty
+refsMatch ((TeX x):restx) ((TeX y):resty) =
+ ((map toLower x) == (map toLower y)) && refsMatch restx resty
+refsMatch ((HtmlInline x):restx) ((HtmlInline y):resty) =
+ ((map toLower x) == (map toLower y)) && refsMatch restx resty
+refsMatch (x:restx) (y:resty) = (x == y) && refsMatch restx resty
+refsMatch [] x = null x
+refsMatch x [] = null x
+
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
index 5c188e3d9..f47309d3f 100644
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -44,13 +44,14 @@ module Text.Pandoc.Readers.HTML (
import Text.ParserCombinators.Parsec
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Shared
+import Text.Pandoc.Parsing
import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )
import Data.Maybe ( fromMaybe )
import Data.List ( isPrefixOf, isSuffixOf, intercalate )
import Data.Char ( toLower, isAlphaNum )
import Network.URI ( parseURIReference, URI (..) )
-import Control.Monad ( liftM )
+import Control.Monad ( liftM, when )
-- | Convert HTML-formatted string to 'Pandoc' document.
readHtml :: ParserState -- ^ Parser state
@@ -198,11 +199,11 @@ inlinesTilEnd tag = manyTill inline (htmlEndTag tag)
-- | Parse blocks between open and close tag.
blocksIn :: String -> GenParser Char ParserState [Block]
-blocksIn tag = try $ htmlTag tag >> spaces >> blocksTilEnd tag
+blocksIn tag = try $ htmlOpenTag tag >> spaces >> blocksTilEnd tag
-- | Parse inlines between open and close tag.
inlinesIn :: String -> GenParser Char ParserState [Inline]
-inlinesIn tag = try $ htmlTag tag >> spaces >> inlinesTilEnd tag
+inlinesIn tag = try $ htmlOpenTag tag >> spaces >> inlinesTilEnd tag
-- | Extract type from a tag: e.g. @br@ from @\<br\>@
extractTagType :: String -> String
@@ -258,18 +259,33 @@ anyHtmlEndTag = try $ do
then return $ "<!-- unsafe HTML removed -->"
else return result
-htmlTag :: String -> GenParser Char ParserState (String, [(String, String)])
-htmlTag tag = try $ do
+htmlTag :: Bool
+ -> String
+ -> GenParser Char ParserState (String, [(String, String)])
+htmlTag selfClosing tag = try $ do
char '<'
spaces
stringAnyCase tag
attribs <- many htmlAttribute
spaces
- optional (string "/")
- spaces
+ -- note: we want to handle both HTML and XHTML,
+ -- so we don't require the /
+ when selfClosing $ optional $ char '/' >> spaces
char '>'
return (tag, (map (\(name, content, _) -> (name, content)) attribs))
+htmlOpenTag :: String
+ -> GenParser Char ParserState (String, [(String, String)])
+htmlOpenTag = htmlTag False
+
+htmlCloseTag :: String
+ -> GenParser Char ParserState (String, [(String, String)])
+htmlCloseTag = htmlTag False . ('/':)
+
+htmlSelfClosingTag :: String
+ -> GenParser Char ParserState (String, [(String, String)])
+htmlSelfClosingTag = htmlTag True
+
-- parses a quoted html attribute value
quoted :: Char -> GenParser Char st (String, String)
quoted quoteChar = do
@@ -344,7 +360,7 @@ anyHtmlInlineTag = try $ do
-- Scripts must be treated differently, because they can contain '<>' etc.
htmlScript :: GenParser Char ParserState [Char]
htmlScript = try $ do
- lookAhead $ htmlTag "script"
+ lookAhead $ htmlOpenTag "script"
open <- anyHtmlTag
rest <- liftM concat $ manyTill scriptChunk (htmlEndTag "script")
st <- getState
@@ -379,7 +395,7 @@ scriptChunk = jsComment <|> jsString <|> jsChars
-- Style tags must be treated differently, because they can contain CSS
htmlStyle :: GenParser Char ParserState [Char]
htmlStyle = try $ do
- lookAhead $ htmlTag "style"
+ lookAhead $ htmlOpenTag "style"
open <- anyHtmlTag
rest <- manyTill anyChar (htmlEndTag "style")
st <- getState
@@ -411,7 +427,8 @@ rawVerbatimBlock = try $ do
-- We don't want to parse </body> or </html> as raw HTML, since these
-- are handled in parseHtml.
rawHtmlBlock' :: GenParser Char ParserState Block
-rawHtmlBlock' = do notFollowedBy' (htmlTag "/body" <|> htmlTag "/html")
+rawHtmlBlock' = do notFollowedBy' (htmlCloseTag "body" <|>
+ htmlCloseTag "html")
rawHtmlBlock
-- | Parses an HTML comment.
@@ -441,13 +458,13 @@ definition = try $ do
nonTitleNonHead :: GenParser Char ParserState Char
nonTitleNonHead = try $ do
- notFollowedBy $ (htmlTag "title" >> return ' ') <|>
+ notFollowedBy $ (htmlOpenTag "title" >> return ' ') <|>
(htmlEndTag "head" >> return ' ')
(rawHtmlBlock >> return ' ') <|> anyChar
parseTitle :: GenParser Char ParserState [Inline]
parseTitle = try $ do
- (tag, _) <- htmlTag "title"
+ (tag, _) <- htmlOpenTag "title"
contents <- inlinesTilEnd tag
spaces
return contents
@@ -455,7 +472,7 @@ parseTitle = try $ do
-- parse header and return meta-information (for now, just title)
parseHead :: GenParser Char ParserState Meta
parseHead = try $ do
- htmlTag "head"
+ htmlOpenTag "head"
spaces
skipMany nonTitleNonHead
contents <- option [] parseTitle
@@ -463,13 +480,10 @@ parseHead = try $ do
htmlEndTag "head"
return $ Meta contents [] []
-skipHtmlTag :: String -> GenParser Char ParserState ()
-skipHtmlTag tag = optional (htmlTag tag)
-
-- h1 class="title" representation of title in body
bodyTitle :: GenParser Char ParserState [Inline]
bodyTitle = try $ do
- (_, attribs) <- htmlTag "h1"
+ (_, attribs) <- htmlOpenTag "h1"
case (extractAttribute "class" attribs) of
Just "title" -> return ""
_ -> fail "not title"
@@ -487,11 +501,11 @@ parseHtml :: GenParser Char ParserState Pandoc
parseHtml = do
sepEndBy (choice [xmlDec, definition, htmlComment]) spaces
spaces
- skipHtmlTag "html"
+ optional $ htmlOpenTag "html"
spaces
meta <- option (Meta [] [] []) parseHead
spaces
- skipHtmlTag "body"
+ optional $ htmlOpenTag "body"
spaces
optional bodyTitle -- skip title in body, because it's represented in meta
blocks <- parseBlocks
@@ -527,7 +541,7 @@ header = choice (map headerLevel (enumFromTo 1 5)) <?> "header"
headerLevel :: Int -> GenParser Char ParserState Block
headerLevel n = try $ do
let level = "h" ++ show n
- htmlTag level
+ htmlOpenTag level
contents <- inlinesTilEnd level
return $ Header n (normalizeSpaces contents)
@@ -537,7 +551,7 @@ headerLevel n = try $ do
hrule :: GenParser Char ParserState Block
hrule = try $ do
- (_, attribs) <- htmlTag "hr"
+ (_, attribs) <- htmlSelfClosingTag "hr"
state <- getState
if not (null attribs) && stateParseRaw state
then unexpected "attributes in hr" -- parse as raw in this case
@@ -551,7 +565,7 @@ hrule = try $ do
-- skipped, because they are not portable to output formats other than HTML.
codeBlock :: GenParser Char ParserState Block
codeBlock = try $ do
- htmlTag "pre"
+ htmlOpenTag "pre"
result <- manyTill
(many1 (satisfy (/= '<')) <|>
((anyHtmlTag <|> anyHtmlEndTag) >> return ""))
@@ -572,7 +586,7 @@ codeBlock = try $ do
--
blockQuote :: GenParser Char ParserState Block
-blockQuote = try $ htmlTag "blockquote" >> spaces >>
+blockQuote = try $ htmlOpenTag "blockquote" >> spaces >>
blocksTilEnd "blockquote" >>= (return . BlockQuote)
--
@@ -584,7 +598,7 @@ list = choice [ bulletList, orderedList, definitionList ] <?> "list"
orderedList :: GenParser Char ParserState Block
orderedList = try $ do
- (_, attribs) <- htmlTag "ol"
+ (_, attribs) <- htmlOpenTag "ol"
(start, style) <- option (1, DefaultStyle) $
do failIfStrict
let sta = fromMaybe "1" $
@@ -609,7 +623,7 @@ orderedList = try $ do
bulletList :: GenParser Char ParserState Block
bulletList = try $ do
- htmlTag "ul"
+ htmlOpenTag "ul"
spaces
-- note: if they have an <ol> or <ul> not in scope of a <li>,
-- treat it as a list item, though it's not valid xhtml...
@@ -620,7 +634,7 @@ bulletList = try $ do
definitionList :: GenParser Char ParserState Block
definitionList = try $ do
failIfStrict -- def lists not part of standard markdown
- htmlTag "dl"
+ htmlOpenTag "dl"
spaces
items <- sepEndBy1 definitionListItem spaces
htmlEndTag "dl"
@@ -638,7 +652,7 @@ definitionListItem = try $ do
--
para :: GenParser Char ParserState Block
-para = try $ htmlTag "p" >> inlinesTilEnd "p" >>=
+para = try $ htmlOpenTag "p" >> inlinesTilEnd "p" >>=
return . Para . normalizeSpaces
--
@@ -672,8 +686,8 @@ inline = choice [ charRef
code :: GenParser Char ParserState Inline
code = try $ do
- htmlTag "code"
- result <- manyTill anyChar (htmlEndTag "code")
+ result <- (htmlOpenTag "code" >> manyTill anyChar (htmlEndTag "code"))
+ <|> (htmlOpenTag "tt" >> manyTill anyChar (htmlEndTag "tt"))
-- remove internal line breaks, leading and trailing space,
-- and decode character references
return $ Code $ decodeCharacterReferences $ removeLeadingTrailingSpace $
@@ -686,7 +700,7 @@ rawHtmlInline = do
if stateParseRaw state then return (HtmlInline result) else return (Str "")
betweenTags :: [Char] -> GenParser Char ParserState [Inline]
-betweenTags tag = try $ htmlTag tag >> inlinesTilEnd tag >>=
+betweenTags tag = try $ htmlOpenTag tag >> inlinesTilEnd tag >>=
return . normalizeSpaces
emph :: GenParser Char ParserState Inline
@@ -708,7 +722,7 @@ strikeout = failIfStrict >> (betweenTags "s" <|> betweenTags "strike") >>=
spanStrikeout :: GenParser Char ParserState Inline
spanStrikeout = try $ do
failIfStrict -- strict markdown has no strikeout, so treat as raw HTML
- (_, attributes) <- htmlTag "span"
+ (_, attributes) <- htmlOpenTag "span"
result <- case (extractAttribute "class" attributes) of
Just "strikeout" -> inlinesTilEnd "span"
_ -> fail "not a strikeout"
@@ -719,7 +733,7 @@ whitespace = many1 space >> return Space
-- hard line break
linebreak :: GenParser Char ParserState Inline
-linebreak = htmlTag "br" >> optional newline >> return LineBreak
+linebreak = htmlSelfClosingTag "br" >> optional newline >> return LineBreak
str :: GenParser Char st Inline
str = many1 (noneOf "< \t\n&") >>= return . Str
@@ -740,7 +754,7 @@ extractAttribute name ((attrName, contents):rest) =
link :: GenParser Char ParserState Inline
link = try $ do
- (_, attributes) <- htmlTag "a"
+ (_, attributes) <- htmlOpenTag "a"
url <- case (extractAttribute "href" attributes) of
Just url -> return url
Nothing -> fail "no href"
@@ -750,7 +764,7 @@ link = try $ do
image :: GenParser Char ParserState Inline
image = try $ do
- (_, attributes) <- htmlTag "img"
+ (_, attributes) <- htmlSelfClosingTag "img"
url <- case (extractAttribute "src" attributes) of
Just url -> return url
Nothing -> fail "no src"
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
index 36940fab0..406809dfc 100644
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -35,7 +35,8 @@ module Text.Pandoc.Readers.LaTeX (
import Text.ParserCombinators.Parsec
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Shared
+import Text.Pandoc.Parsing
import Data.Maybe ( fromMaybe )
import Data.Char ( chr )
import Data.List ( isPrefixOf, isSuffixOf )
@@ -167,16 +168,37 @@ block = choice [ hrule
--
header :: GenParser Char ParserState Block
-header = try $ do
+header = section <|> chapter
+
+chapter :: GenParser Char ParserState Block
+chapter = try $ do
+ string "\\chapter"
+ result <- headerWithLevel 1
+ updateState $ \s -> s{ stateHasChapters = True }
+ return result
+
+section :: GenParser Char ParserState Block
+section = try $ do
char '\\'
subs <- many (try (string "sub"))
base <- try (string "section" >> return 1) <|> (string "paragraph" >> return 4)
+ st <- getState
+ let lev = if stateHasChapters st
+ then length subs + base + 1
+ else length subs + base
+ headerWithLevel lev
+
+headerWithLevel :: Int -> GenParser Char ParserState Block
+headerWithLevel lev = try $ do
+ spaces
optional (char '*')
+ spaces
optional $ bracketedText '[' ']' -- alt title
+ spaces
char '{'
title' <- manyTill inline (char '}')
spaces
- return $ Header (length subs + base) (normalizeSpaces title')
+ return $ Header lev (normalizeSpaces title')
--
-- hrule block
@@ -453,7 +475,7 @@ inline = choice [ str
, accentedChar
, nonbreakingSpace
, specialChar
- , rawLaTeXInline
+ , rawLaTeXInline'
, escapedChar
, unescapedChar
] <?> "inline"
@@ -771,11 +793,16 @@ footnote = try $ do
setInput rest
return $ Note blocks
+-- | Parse any LaTeX inline command and return it in a raw TeX inline element.
+rawLaTeXInline' :: GenParser Char ParserState Inline
+rawLaTeXInline' = do
+ notFollowedBy' $ oneOfStrings ["\\begin", "\\end", "\\item", "\\ignore",
+ "\\section"]
+ rawLaTeXInline
+
-- | Parse any LaTeX command and return it in a raw TeX inline element.
rawLaTeXInline :: GenParser Char ParserState Inline
rawLaTeXInline = try $ do
- notFollowedBy' $ oneOfStrings ["\\begin", "\\end", "\\item", "\\ignore",
- "\\section"]
state <- getState
if stateParseRaw state
then do
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 13edd0586..33fb3d8e6 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -32,11 +32,13 @@ module Text.Pandoc.Readers.Markdown (
) where
import Data.List ( transpose, isSuffixOf, sortBy, findIndex, intercalate )
+import qualified Data.Map as M
import Data.Ord ( comparing )
import Data.Char ( isAlphaNum )
import Data.Maybe
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Shared
+import Text.Pandoc.Parsing
import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXEnvironment' )
import Text.Pandoc.Readers.HTML ( rawHtmlBlock, anyHtmlBlockTag,
anyHtmlInlineTag, anyHtmlTag,
@@ -67,7 +69,7 @@ setextHChars = "=-"
-- treat these as potentially non-text when parsing inline:
specialChars :: [Char]
-specialChars = "\\[]*_~`<>$!^-.&'\"\8216\8217\8220\8221;"
+specialChars = "\\[]*_~`<>$!^-.&@'\";"
--
-- auxiliary functions
@@ -183,7 +185,18 @@ parseMarkdown = do
-- now parse it for real...
(title, author, date) <- option ([],[],[]) titleBlock
blocks <- parseBlocks
- return $ Pandoc (Meta title author date) $ filter (/= Null) blocks
+ 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 $ processWith handleExampleRef doc
--
-- initial pass for references and notes
@@ -202,10 +215,10 @@ referenceKey = try $ do
tit <- option "" referenceTitle
blanklines
endPos <- getPosition
- let newkey = (lab, (escapeURI $ removeTrailingSpace src, tit))
+ let target = (escapeURI $ removeTrailingSpace src, tit)
st <- getState
let oldkeys = stateKeys st
- updateState $ \s -> s { stateKeys = newkey : oldkeys }
+ updateState $ \s -> s { stateKeys = M.insert (Key lab) target oldkeys }
-- return blanks so line count isn't affected
return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
@@ -715,7 +728,7 @@ dashedLine ch = do
-- Parse a table header with dashed lines of '-' preceded by
-- one (or zero) line of text.
simpleTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([[Char]], [Alignment], [Int])
+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
simpleTableHeader headless = try $ do
rawContent <- if headless
then return ""
@@ -734,7 +747,9 @@ simpleTableHeader headless = try $ do
let rawHeads' = if headless
then replicate (length dashes) ""
else rawHeads
- return (rawHeads', aligns, indices)
+ heads <- mapM (parseFromString (many plain)) $
+ map removeLeadingTrailingSpace rawHeads'
+ return (heads, aligns, indices)
-- Parse a table footer - dashed lines followed by blank line.
tableFooter :: GenParser Char ParserState [Char]
@@ -763,65 +778,27 @@ multilineRow :: [Int]
-> GenParser Char ParserState [[Block]]
multilineRow indices = do
colLines <- many1 (rawTableLine indices)
- optional blanklines
let cols = map unlines $ transpose colLines
mapM (parseFromString (many plain)) cols
--- 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 =
- let lengths' = zipWith (-) indices (0:indices)
- lengths = reverse $
- case reverse lengths' of
- [] -> []
- [x] -> [x]
- -- compensate for the fact that intercolumn
- -- spaces are counted in widths of all columns
- -- but the last...
- (x:y:zs) -> if x < y && y - x <= 2
- then y:y:zs
- else x:y:zs
- totLength = sum lengths
- quotient = if totLength > numColumns
- then fromIntegral totLength
- else fromIntegral numColumns
- fracs = map (\l -> (fromIntegral l) / quotient) lengths in
- tail fracs
-
-- Parses a table caption: inlines beginning with 'Table:'
-- and followed by blank lines.
tableCaption :: GenParser Char ParserState [Inline]
tableCaption = try $ do
skipNonindentSpaces
- string "Table:"
+ string ":" <|> string "Table:"
result <- many1 inline
blanklines
return $ normalizeSpaces result
--- Parse a table using 'headerParser', 'lineParser', and 'footerParser'.
-tableWith :: GenParser Char ParserState ([[Char]], [Alignment], [Int])
- -> ([Int] -> GenParser Char ParserState [[Block]])
- -> GenParser Char ParserState end
- -> GenParser Char ParserState Block
-tableWith headerParser lineParser footerParser = try $ do
- (rawHeads, aligns, indices) <- headerParser
- lines' <- many1Till (lineParser indices) footerParser
- caption <- option [] tableCaption
- heads <- mapM (parseFromString (many plain)) rawHeads
- state <- getState
- let numColumns = stateColumns state
- let widths = widthsFromIndices numColumns indices
- return $ Table caption aligns widths heads lines'
-
-- Parse a simple table with '---' header and one line per row.
simpleTable :: Bool -- ^ Headerless table
-> GenParser Char ParserState Block
simpleTable headless = do
Table c a _w h l <- tableWith (simpleTableHeader headless) tableLine
- (if headless then tableFooter else tableFooter <|> blanklines)
+ (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
@@ -832,10 +809,10 @@ simpleTable headless = do
multilineTable :: Bool -- ^ Headerless table
-> GenParser Char ParserState Block
multilineTable headless =
- tableWith (multilineTableHeader headless) multilineRow tableFooter
+ tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter tableCaption
multilineTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([String], [Alignment], [Int])
+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
multilineTableHeader headless = try $ do
if headless
then return '\n'
@@ -859,7 +836,9 @@ multilineTableHeader headless = try $ do
let rawHeads = if headless
then replicate (length dashes) ""
else map (intercalate " ") rawHeadsList
- return ((map removeLeadingTrailingSpace rawHeads), aligns, indices)
+ heads <- mapM (parseFromString (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
@@ -879,9 +858,14 @@ alignType strLst len =
(True, True) -> AlignCenter
(False, False) -> AlignDefault
+gridTable :: Bool -- ^ Headerless table
+ -> GenParser Char ParserState Block
+gridTable = gridTableWith block tableCaption
+
table :: GenParser Char ParserState Block
table = multilineTable False <|> simpleTable True <|>
- simpleTable False <|> multilineTable True <?> "table"
+ simpleTable False <|> multilineTable True <|>
+ gridTable False <|> gridTable True <?> "table"
--
-- inline
@@ -915,6 +899,7 @@ inlineParsers = [ str
, rawHtmlInline'
, rawLaTeXInline'
, escapedChar
+ , exampleRef
, symbol
, ltSign ]
@@ -950,6 +935,14 @@ ltSign = do
specialCharsMinusLt :: [Char]
specialCharsMinusLt = filter (/= '<') specialChars
+exampleRef :: GenParser Char ParserState Inline
+exampleRef = try $ do
+ 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
result <- oneOf specialCharsMinusLt
@@ -1070,30 +1063,28 @@ failIfInQuoteContext context = do
singleQuoteStart :: GenParser Char ParserState Char
singleQuoteStart = do
failIfInQuoteContext InSingleQuote
- char '\8216' <|>
- (try $ do char '\''
- notFollowedBy (oneOf ")!],.;:-? \t\n")
- notFollowedBy (try (oneOfStrings ["s","t","m","ve","ll","re"] >>
- satisfy (not . isAlphaNum)))
- -- possess/contraction
- return '\'')
+ try $ do char '\''
+ notFollowedBy (oneOf ")!],.;:-? \t\n")
+ notFollowedBy (try (oneOfStrings ["s","t","m","ve","ll","re"] >>
+ satisfy (not . isAlphaNum)))
+ -- possess/contraction
+ return '\''
singleQuoteEnd :: GenParser Char st Char
singleQuoteEnd = try $ do
- char '\8217' <|> char '\''
+ char '\''
notFollowedBy alphaNum
return '\''
doubleQuoteStart :: GenParser Char ParserState Char
doubleQuoteStart = do
failIfInQuoteContext InDoubleQuote
- char '\8220' <|>
- (try $ do char '"'
- notFollowedBy (oneOf " \t\n")
- return '"')
+ try $ do char '"'
+ notFollowedBy (oneOf " \t\n")
+ return '"'
doubleQuoteEnd :: GenParser Char st Char
-doubleQuoteEnd = char '\8221' <|> char '"'
+doubleQuoteEnd = char '"'
ellipses :: GenParser Char st Inline
ellipses = oneOfStrings ["...", " . . . ", ". . .", " . . ."] >> return Ellipses
@@ -1218,7 +1209,7 @@ referenceLink lab = do
optional (newline >> skipSpaces) >> reference))
let ref' = if null ref then lab else ref
state <- getState
- case lookupKeySrc (stateKeys state) ref' of
+ case lookupKeySrc (stateKeys state) (Key ref') of
Nothing -> fail "no corresponding key"
Just target -> return target
@@ -1303,7 +1294,7 @@ inlineCitation = try $ do
chkCit :: Target -> GenParser Char ParserState (Maybe Target)
chkCit t = do
st <- getState
- case lookupKeySrc (stateKeys st) [Str $ fst t] of
+ case lookupKeySrc (stateKeys st) (Key [Str $ fst t]) of
Just _ -> fail "This is a link"
Nothing -> if elem (fst t) $ stateCitations st
then return $ Just t
diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs
index 5e7ea512e..13afe5053 100644
--- a/src/Text/Pandoc/Readers/RST.hs
+++ b/src/Text/Pandoc/Readers/RST.hs
@@ -31,10 +31,13 @@ module Text.Pandoc.Readers.RST (
readRST
) where
import Text.Pandoc.Definition
-import Text.Pandoc.Shared
+import Text.Pandoc.Shared
+import Text.Pandoc.Parsing
import Text.ParserCombinators.Parsec
-import Control.Monad ( when, unless, liftM )
-import Data.List ( findIndex, delete, intercalate, transpose )
+import Control.Monad ( when, unless )
+import Data.List ( findIndex, intercalate, transpose, sort )
+import qualified Data.Map as M
+import Text.Printf ( printf )
-- | Parse reStructuredText string and return Pandoc document.
readRST :: ParserState -- ^ Parser state, including options for parser
@@ -93,9 +96,6 @@ parseRST = do
docMinusKeys <- manyTill (referenceKey <|> lineClump) eof >>= return . concat
setInput docMinusKeys
setPosition startPos
- st <- getState
- let reversedKeys = stateKeys st
- updateState $ \s -> s { stateKeys = reverse reversedKeys }
-- now parse it for real...
blocks <- parseBlocks
let blocks' = filter (/= Null) blocks
@@ -425,7 +425,7 @@ bulletListStart = try $ do
-- parses ordered list start and returns its length (inc following whitespace)
orderedListStart :: ListNumberStyle
-> ListNumberDelim
- -> GenParser Char st Int
+ -> GenParser Char ParserState Int
orderedListStart style delim = try $ do
(_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)
white <- many1 spaceChar
@@ -540,10 +540,10 @@ referenceName = quotedReferenceName <|>
referenceKey :: GenParser Char ParserState [Char]
referenceKey = do
startPos <- getPosition
- key <- choice [imageKey, anonymousKey, regularKey]
+ (key, target) <- choice [imageKey, anonymousKey, regularKey]
st <- getState
let oldkeys = stateKeys st
- updateState $ \s -> s { stateKeys = key : oldkeys }
+ updateState $ \s -> s { stateKeys = M.insert key target oldkeys }
optional blanklines
endPos <- getPosition
-- return enough blanks to replace key
@@ -558,28 +558,29 @@ targetURI = do
blanklines
return $ escapeURI $ removeLeadingTrailingSpace $ contents
-imageKey :: GenParser Char ParserState ([Inline], (String, [Char]))
+imageKey :: GenParser Char ParserState (Key, Target)
imageKey = try $ do
string ".. |"
ref <- manyTill inline (char '|')
skipSpaces
string "image::"
src <- targetURI
- return (normalizeSpaces ref, (src, ""))
+ return (Key (normalizeSpaces ref), (src, ""))
-anonymousKey :: GenParser Char st ([Inline], (String, [Char]))
+anonymousKey :: GenParser Char st (Key, Target)
anonymousKey = try $ do
oneOfStrings [".. __:", "__"]
src <- targetURI
- return ([Str "_"], (src, ""))
+ pos <- getPosition
+ return (Key [Str $ "_" ++ printf "%09d" (sourceLine pos)], (src, ""))
-regularKey :: GenParser Char ParserState ([Inline], (String, [Char]))
+regularKey :: GenParser Char ParserState (Key, Target)
regularKey = try $ do
string ".. _"
ref <- referenceName
char ':'
src <- targetURI
- return (normalizeSpaces ref, (src, ""))
+ return (Key (normalizeSpaces ref), (src, ""))
--
-- tables
@@ -607,41 +608,20 @@ dashedLine ch = do
simpleDashedLines :: Char -> GenParser Char st [(Int,Int)]
simpleDashedLines ch = try $ many1 (dashedLine ch)
-gridPart :: Char -> GenParser 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 ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline
-
-- Parse a table row separator
simpleTableSep :: Char -> GenParser Char ParserState Char
simpleTableSep ch = try $ simpleDashedLines ch >> newline
-gridTableSep :: Char -> GenParser Char ParserState Char
-gridTableSep ch = try $ gridDashedLines ch >> return '\n'
-
-- Parse a table footer
simpleTableFooter :: GenParser Char ParserState [Char]
simpleTableFooter = try $ simpleTableSep '=' >> blanklines
-gridTableFooter :: GenParser Char ParserState [Char]
-gridTableFooter = blanklines
-
-- Parse a raw line and split it into chunks by indices.
simpleTableRawLine :: [Int] -> GenParser Char ParserState [String]
simpleTableRawLine indices = do
line <- many1Till anyChar newline
return (simpleTableSplitLine indices line)
-gridTableRawLine :: [Int] -> GenParser Char ParserState [String]
-gridTableRawLine indices = do
- char '|'
- line <- many1Till anyChar newline
- return (gridTableSplitLine indices $ removeTrailingSpace line)
-
-- Parse a table row and return a list of blocks (columns).
simpleTableRow :: [Int] -> GenParser Char ParserState [[Block]]
simpleTableRow indices = do
@@ -651,64 +631,13 @@ simpleTableRow indices = do
let cols = map unlines . transpose $ firstLine : colLines
mapM (parseFromString (many plain)) cols
-gridTableRow :: [Int]
- -> GenParser Char ParserState [[Block]]
-gridTableRow indices = do
- colLines <- many1 (gridTableRawLine indices)
- let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
- transpose colLines
- mapM (liftM compactifyCell . parseFromString (many block)) cols
-
-compactifyCell :: [Block] -> [Block]
-compactifyCell bs = head $ compactify [bs]
-
simpleTableSplitLine :: [Int] -> String -> [String]
simpleTableSplitLine indices line =
map removeLeadingTrailingSpace
$ tail $ splitByIndices (init indices) line
-gridTableSplitLine :: [Int] -> String -> [String]
-gridTableSplitLine indices line =
- map removeFinalBar $ tail $ splitByIndices (init indices) line
-
-removeFinalBar :: String -> String
-removeFinalBar = reverse . dropWhile (=='|') . dropWhile (`elem` " \t") .
- reverse
-
-removeOneLeadingSpace :: [String] -> [String]
-removeOneLeadingSpace xs =
- if all startsWithSpace xs
- then map (drop 1) xs
- else xs
- where startsWithSpace "" = True
- startsWithSpace (y:_) = y == ' '
-
--- 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 =
- let lengths' = zipWith (-) indices (0:indices)
- lengths = reverse $
- case reverse lengths' of
- [] -> []
- [x] -> [x]
- -- compensate for the fact that intercolumn
- -- spaces are counted in widths of all columns
- -- but the last...
- (x:y:zs) -> if x < y && y - x <= 2
- then y:y:zs
- else x:y:zs
- totLength = sum lengths
- quotient = if totLength > numColumns
- then fromIntegral totLength
- else fromIntegral numColumns
- fracs = map (\l -> (fromIntegral l) / quotient) lengths in
- tail fracs
-
simpleTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([[Char]], [Alignment], [Int])
+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
simpleTableHeader headless = try $ do
optional blanklines
rawContent <- if headless
@@ -722,64 +651,23 @@ simpleTableHeader headless = try $ do
let rawHeads = if headless
then replicate (length dashes) ""
else simpleTableSplitLine indices rawContent
- return (rawHeads, aligns, indices)
+ heads <- mapM (parseFromString (many plain)) $
+ map removeLeadingTrailingSpace rawHeads
+ return (heads, aligns, indices)
-gridTableHeader :: Bool -- ^ Headerless table
- -> GenParser Char ParserState ([String], [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
- return (rawHeads, aligns, indices)
-
--- Parse a table using 'headerParser', 'lineParser', and 'footerParser'.
-tableWith :: GenParser Char ParserState ([[Char]], [Alignment], [Int])
- -> ([Int] -> GenParser Char ParserState [[Block]])
- -> GenParser Char ParserState sep
- -> GenParser Char ParserState end
- -> GenParser Char ParserState Block
-tableWith headerParser rowParser lineParser footerParser = try $ do
- (rawHeads, aligns, indices) <- headerParser
- lines' <- rowParser indices `sepEndBy` lineParser
- footerParser
- heads <- mapM (parseFromString (many plain)) rawHeads
- state <- getState
- let captions = [] -- no notion of captions in RST
- let numColumns = stateColumns state
- let widths = widthsFromIndices numColumns indices
- return $ Table captions aligns widths heads lines'
-
--- Parse a simple table with '---' header and one line per row.
+-- Parse a simple table.
simpleTable :: Bool -- ^ Headerless table
-> GenParser Char ParserState Block
simpleTable headless = do
- Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter
+ Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter (return [])
-- 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 '-')
--- 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 headless =
- tableWith (gridTableHeader headless) gridTableRow (gridTableSep '-') gridTableFooter
+ -> GenParser Char ParserState Block
+gridTable = gridTableWith block (return [])
table :: GenParser Char ParserState Block
table = gridTable False <|> simpleTable False <|>
@@ -889,17 +777,21 @@ explicitLink = try $ do
referenceLink :: GenParser Char ParserState Inline
referenceLink = try $ do
label' <- (quotedReferenceName <|> simpleReferenceName) >>~ char '_'
- key <- option label' (do{char '_'; return [Str "_"]}) -- anonymous link
state <- getState
let keyTable = stateKeys state
+ let isAnonKey (Key [Str ('_':_)]) = True
+ isAnonKey _ = False
+ key <- option (Key label') $
+ do char '_'
+ let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
+ if null anonKeys
+ then pzero
+ else return (head anonKeys)
(src,tit) <- case lookupKeySrc keyTable key of
Nothing -> fail "no corresponding key"
Just target -> return target
- -- if anonymous link, remove first anon key so it won't be used again
- let keyTable' = if (key == [Str "_"]) -- anonymous link?
- then delete ([Str "_"], (src,tit)) keyTable -- remove first anon key
- else keyTable
- setState $ state { stateKeys = keyTable' }
+ -- 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)
autoURI :: GenParser Char ParserState Inline
@@ -922,7 +814,7 @@ image = try $ do
ref <- manyTill inline (char '|')
state <- getState
let keyTable = stateKeys state
- (src,tit) <- case lookupKeySrc keyTable ref of
+ (src,tit) <- case lookupKeySrc keyTable (Key ref) of
Nothing -> fail "no corresponding key"
Just target -> return target
return $ Image (normalizeSpaces ref) (src, tit)
diff --git a/src/Text/Pandoc/Readers/TeXMath.hs b/src/Text/Pandoc/Readers/TeXMath.hs
index 080354be1..b0c6e86d4 100644
--- a/src/Text/Pandoc/Readers/TeXMath.hs
+++ b/src/Text/Pandoc/Readers/TeXMath.hs
@@ -28,208 +28,67 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Conversion of TeX math to a list of 'Pandoc' inline elements.
-}
module Text.Pandoc.Readers.TeXMath (
- readTeXMath
+ readTeXMath
) where
import Text.ParserCombinators.Parsec
import Text.Pandoc.Definition
+import Text.TeXMath.Parser
--- | Converts a string of raw TeX math to a list of 'Pandoc' inlines.
+-- | Converts a raw TeX math formula to a list of 'Pandoc' inlines.
+-- Defaults to raw formula between @$@ characters if entire formula
+-- can't be converted.
readTeXMath :: String -- ^ String to parse (assumes @'\n'@ line endings)
-> [Inline]
-readTeXMath inp = case parse teXMath ("formula: " ++ inp) inp of
- Left _ -> [Str inp] -- if unparseable, just include original
- Right res -> res
-
-teXMath :: GenParser Char st [Inline]
-teXMath = manyTill mathPart eof >>= return . concat
-
-mathPart :: GenParser Char st [Inline]
-mathPart = whitespace <|> superscript <|> subscript <|> symbol <|>
- argument <|> digits <|> letters <|> misc
-
-whitespace :: GenParser Char st [Inline]
-whitespace = many1 space >> return []
-
-symbol :: GenParser Char st [Inline]
-symbol = try $ do
- char '\\'
- res <- many1 letter
- case lookup res teXsymbols of
- Just m -> return [Str m]
- Nothing -> return [Str $ "\\" ++ res]
-
-argument :: GenParser Char st [Inline]
-argument = try $ do
- char '{'
- res <- many mathPart
- char '}'
- return $ if null res
- then [Str " "]
- else [Str "{"] ++ concat res ++ [Str "}"]
-
-digits :: GenParser Char st [Inline]
-digits = do
- res <- many1 digit
- return [Str res]
-
-letters :: GenParser Char st [Inline]
-letters = do
- res <- many1 letter
- return [Emph [Str res]]
-
-misc :: GenParser Char st [Inline]
-misc = do
- res <- noneOf "}"
- return [Str [res]]
-
-scriptArg :: GenParser Char st [Inline]
-scriptArg = try $ do
- (try (do{char '{'; r <- many mathPart; char '}'; return $ concat r}))
- <|> symbol
- <|> (do{c <- (letter <|> digit); return [Str [c]]})
-
-superscript :: GenParser Char st [Inline]
-superscript = try $ do
- char '^'
- arg <- scriptArg
- return [Superscript arg]
-
-subscript :: GenParser Char st [Inline]
-subscript = try $ do
- char '_'
- arg <- scriptArg
- return [Subscript arg]
-
-withThinSpace :: String -> String
-withThinSpace str = "\x2009" ++ str ++ "\x2009"
-
-teXsymbols :: [(String, String)]
-teXsymbols =
- [("alpha","\x3B1")
- ,("beta", "\x3B2")
- ,("chi", "\x3C7")
- ,("delta", "\x3B4")
- ,("Delta", "\x394")
- ,("epsilon", "\x3B5")
- ,("varepsilon", "\x25B")
- ,("eta", "\x3B7")
- ,("gamma", "\x3B3")
- ,("Gamma", "\x393")
- ,("iota", "\x3B9")
- ,("kappa", "\x3BA")
- ,("lambda", "\x3BB")
- ,("Lambda", "\x39B")
- ,("mu", "\x3BC")
- ,("nu", "\x3BD")
- ,("omega", "\x3C9")
- ,("Omega", "\x3A9")
- ,("phi", "\x3C6")
- ,("varphi", "\x3D5")
- ,("Phi", "\x3A6")
- ,("pi", "\x3C0")
- ,("Pi", "\x3A0")
- ,("psi", "\x3C8")
- ,("Psi", "\x3A8")
- ,("rho", "\x3C1")
- ,("sigma", "\x3C3")
- ,("Sigma", "\x3A3")
- ,("tau", "\x3C4")
- ,("theta", "\x3B8")
- ,("vartheta", "\x3D1")
- ,("Theta", "\x398")
- ,("upsilon", "\x3C5")
- ,("xi", "\x3BE")
- ,("Xi", "\x39E")
- ,("zeta", "\x3B6")
- ,("ne", "\x2260")
- ,("lt", withThinSpace "<")
- ,("le", withThinSpace "\x2264")
- ,("leq", withThinSpace "\x2264")
- ,("ge", withThinSpace "\x2265")
- ,("geq", withThinSpace "\x2265")
- ,("prec", withThinSpace "\x227A")
- ,("succ", withThinSpace "\x227B")
- ,("preceq", withThinSpace "\x2AAF")
- ,("succeq", withThinSpace "\x2AB0")
- ,("in", withThinSpace "\x2208")
- ,("notin", withThinSpace "\x2209")
- ,("subset", withThinSpace "\x2282")
- ,("supset", withThinSpace "\x2283")
- ,("subseteq", withThinSpace "\x2286")
- ,("supseteq", withThinSpace "\x2287")
- ,("equiv", withThinSpace "\x2261")
- ,("cong", withThinSpace "\x2245")
- ,("approx", withThinSpace "\x2248")
- ,("propto", withThinSpace "\x221D")
- ,("cdot", withThinSpace "\x22C5")
- ,("star", withThinSpace "\x22C6")
- ,("backslash", "\\")
- ,("times", withThinSpace "\x00D7")
- ,("divide", withThinSpace "\x00F7")
- ,("circ", withThinSpace "\x2218")
- ,("oplus", withThinSpace "\x2295")
- ,("otimes", withThinSpace "\x2297")
- ,("odot", withThinSpace "\x2299")
- ,("sum", "\x2211")
- ,("prod", "\x220F")
- ,("wedge", withThinSpace "\x2227")
- ,("bigwedge", withThinSpace "\x22C0")
- ,("vee", withThinSpace "\x2228")
- ,("bigvee", withThinSpace "\x22C1")
- ,("cap", withThinSpace "\x2229")
- ,("bigcap", withThinSpace "\x22C2")
- ,("cup", withThinSpace "\x222A")
- ,("bigcup", withThinSpace "\x22C3")
- ,("neg", "\x00AC")
- ,("implies", withThinSpace "\x21D2")
- ,("iff", withThinSpace "\x21D4")
- ,("forall", "\x2200")
- ,("exists", "\x2203")
- ,("bot", "\x22A5")
- ,("top", "\x22A4")
- ,("vdash", "\x22A2")
- ,("models", withThinSpace "\x22A8")
- ,("uparrow", "\x2191")
- ,("downarrow", "\x2193")
- ,("rightarrow", withThinSpace "\x2192")
- ,("to", withThinSpace "\x2192")
- ,("rightarrowtail", "\x21A3")
- ,("twoheadrightarrow", withThinSpace "\x21A0")
- ,("twoheadrightarrowtail", withThinSpace "\x2916")
- ,("mapsto", withThinSpace "\x21A6")
- ,("leftarrow", withThinSpace "\x2190")
- ,("leftrightarrow", withThinSpace "\x2194")
- ,("Rightarrow", withThinSpace "\x21D2")
- ,("Leftarrow", withThinSpace "\x21D0")
- ,("Leftrightarrow", withThinSpace "\x21D4")
- ,("partial", "\x2202")
- ,("nabla", "\x2207")
- ,("pm", "\x00B1")
- ,("emptyset", "\x2205")
- ,("infty", "\x221E")
- ,("aleph", "\x2135")
- ,("ldots", "...")
- ,("therefore", "\x2234")
- ,("angle", "\x2220")
- ,("quad", "\x00A0\x00A0")
- ,("cdots", "\x22EF")
- ,("vdots", "\x22EE")
- ,("ddots", "\x22F1")
- ,("diamond", "\x22C4")
- ,("Box", "\x25A1")
- ,("lfloor", "\x230A")
- ,("rfloor", "\x230B")
- ,("lceiling", "\x2308")
- ,("rceiling", "\x2309")
- ,("langle", "\x2329")
- ,("rangle", "\x232A")
- ,("int", "\8747")
- ,("{", "{")
- ,("}", "}")
- ,("[", "[")
- ,("]", "]")
- ,("|", "|")
- ,("||", "||")
- ]
+readTeXMath inp = case readTeXMath' inp of
+ Nothing -> [Str ("$" ++ inp ++ "$")]
+ Just res -> res
+
+-- | Like 'readTeXMath', but without the default.
+readTeXMath' :: String -- ^ String to parse (assumes @'\n'@ line endings)
+ -> Maybe [Inline]
+readTeXMath' inp = case parse formula "formula" inp of
+ Left _ -> Just [Str inp]
+ Right exps -> expsToInlines exps
+
+expsToInlines :: [Exp] -> Maybe [Inline]
+expsToInlines xs = do
+ res <- mapM expToInlines xs
+ return (concat res)
+
+expToInlines :: Exp -> Maybe [Inline]
+expToInlines (ENumber s) = Just [Str s]
+expToInlines (EIdentifier s) = Just [Emph [Str s]]
+expToInlines (EMathOperator s) = Just [Str s]
+expToInlines (ESymbol t s) = Just $ addSpace t (Str s)
+ where addSpace Op x = [x, thinspace]
+ addSpace Bin x = [medspace, x, medspace]
+ addSpace Rel x = [widespace, x, widespace]
+ addSpace Pun x = [x, thinspace]
+ addSpace _ x = [x]
+ thinspace = Str "\x2006"
+ medspace = Str "\x2005"
+ widespace = Str "\x2004"
+expToInlines (EStretchy x) = expToInlines x
+expToInlines (EGrouped xs) = expsToInlines xs
+expToInlines (ESpace _) = Just [Str " "] -- variable widths not supported
+expToInlines (EBinary _ _ _) = Nothing
+expToInlines (ESub x y) = do
+ x' <- expToInlines x
+ y' <- expToInlines y
+ return $ x' ++ [Subscript y']
+expToInlines (ESuper x y) = do
+ x' <- expToInlines x
+ y' <- expToInlines y
+ return $ x' ++ [Superscript y']
+expToInlines (ESubsup x y z) = do
+ x' <- expToInlines x
+ y' <- expToInlines y
+ z' <- expToInlines z
+ return $ x' ++ [Subscript y'] ++ [Superscript z']
+expToInlines (EDown x y) = expToInlines (ESub x y)
+expToInlines (EUp x y) = expToInlines (ESuper x y)
+expToInlines (EDownup x y z) = expToInlines (ESubsup x y z)
+expToInlines (EText _ x) = Just [Emph [Str x]]
+expToInlines _ = Nothing
diff --git a/src/Text/Pandoc/S5.hs b/src/Text/Pandoc/S5.hs
new file mode 100644
index 000000000..1567a3ede
--- /dev/null
+++ b/src/Text/Pandoc/S5.hs
@@ -0,0 +1,57 @@
+{-
+Copyright (C) 2006-2010 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.S5
+ Copyright : Copyright (C) 2006-2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+Definitions for creation of S5 powerpoint-like HTML.
+(See <http://meyerweb.com/eric/tools/s5/>.)
+-}
+module Text.Pandoc.S5 ( s5HeaderIncludes) where
+import Text.Pandoc.Shared ( readDataFile )
+import System.FilePath ( (</>) )
+
+s5HeaderIncludes :: Maybe FilePath -> IO String
+s5HeaderIncludes datadir = do
+ c <- s5CSS datadir
+ j <- s5Javascript datadir
+ return $ c ++ j
+
+s5Javascript :: Maybe FilePath -> IO String
+s5Javascript datadir = do
+ jsCom <- readDataFile datadir $ "s5" </> "default" </> "slides.js.comment"
+ jsPacked <- readDataFile datadir $ "s5" </> "default" </> "slides.js.packed"
+ return $ "<script type=\"text/javascript\">\n" ++ jsCom ++ jsPacked ++
+ "</script>\n"
+
+s5CSS :: Maybe FilePath -> IO String
+s5CSS datadir = do
+ s5CoreCSS <- readDataFile datadir $ "s5" </> "default" </> "s5-core.css"
+ s5FramingCSS <- readDataFile datadir $ "s5" </> "default" </> "framing.css"
+ s5PrettyCSS <- readDataFile datadir $ "s5" </> "default" </> "pretty.css"
+ s5OperaCSS <- readDataFile datadir $ "s5" </> "default" </> "opera.css"
+ s5OutlineCSS <- readDataFile datadir $ "s5" </> "default" </> "outline.css"
+ s5PrintCSS <- readDataFile datadir $ "s5" </> "default" </> "print.css"
+ return $ "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"
+
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index 26aff4250..633708046 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -45,54 +45,15 @@ module Text.Pandoc.Shared (
toRomanNumeral,
escapeURI,
unescapeURI,
+ tabFilter,
+ -- * Prettyprinting
wrapped,
wrapIfNeeded,
wrappedTeX,
wrapTeXIfNeeded,
BlockWrapper (..),
wrappedBlocksToDoc,
- tabFilter,
- -- * Parsing
- (>>~),
- anyLine,
- many1Till,
- notFollowedBy',
- oneOfStrings,
- spaceChar,
- skipSpaces,
- blankline,
- blanklines,
- enclosed,
- stringAnyCase,
- parseFromString,
- lineClump,
- charsInBalanced,
- charsInBalanced',
- romanNumeral,
- emailAddress,
- uri,
- withHorizDisplacement,
- nullBlock,
- failIfStrict,
- failUnlessLHS,
- escaped,
- anyOrderedListMarker,
- orderedListMarker,
- charRef,
- readWith,
- testStringWith,
- ParserState (..),
- defaultParserState,
- HeaderType (..),
- ParserContext (..),
- QuoteContext (..),
- NoteTable,
- KeyTable,
- lookupKeySrc,
- refsMatch,
- -- * Prettyprinting
hang',
- prettyPandoc,
-- * Pandoc block and inline list processing
orderedListMarkers,
normalizeSpaces,
@@ -101,9 +62,11 @@ module Text.Pandoc.Shared (
hierarchicalize,
uniqueIdent,
isHeaderBlock,
+ headerShift,
-- * Writer options
HTMLMathMethod (..),
ObfuscationMethod (..),
+ HTMLSlideVariant (..),
WriterOptions (..),
defaultWriterOptions,
-- * File handling
@@ -112,27 +75,18 @@ module Text.Pandoc.Shared (
) where
import Text.Pandoc.Definition
-import Text.ParserCombinators.Parsec
+import qualified Text.Pandoc.UTF8 as UTF8 (readFile)
import Text.PrettyPrint.HughesPJ ( Doc, fsep, ($$), (<>), empty, isEmpty, text, nest )
import qualified Text.PrettyPrint.HughesPJ as PP
-import Text.Pandoc.CharacterReferences ( characterReference )
-import Data.Char ( toLower, toUpper, ord, isLower, isUpper, isAlpha, isAscii,
+import Data.Char ( toLower, isLower, isUpper, isAlpha, isAscii,
isLetter, isDigit )
import Data.List ( find, isPrefixOf, intercalate )
-import Network.URI ( parseURI, URI (..), isAllowedInURI, escapeURIString, unEscapeString )
+import Network.URI ( isAllowedInURI, escapeURIString, unEscapeString )
import Codec.Binary.UTF8.String ( encodeString, decodeString )
import System.Directory
import System.FilePath ( (</>) )
--- Note: ghc >= 6.12 (base >=4.2) supports unicode through iconv
--- So we use System.IO.UTF8 only if we have an earlier version
-#if MIN_VERSION_base(4,2,0)
-#else
-import Prelude hiding ( putStr, putStrLn, writeFile, readFile, getContents )
-import System.IO.UTF8
-#endif
-import Data.Generics
+import Data.Generics (Typeable, Data)
import qualified Control.Monad.State as S
-import Control.Monad (join)
import Paths_pandoc (getDataFileName)
--
@@ -157,11 +111,11 @@ splitByIndices (x:xs) lst =
-- | Replace each occurrence of one sublist in a list with another.
substitute :: (Eq a) => [a] -> [a] -> [a] -> [a]
substitute _ _ [] = []
-substitute [] _ lst = lst
-substitute target replacement lst =
+substitute [] _ xs = xs
+substitute target replacement lst@(x:xs) =
if target `isPrefixOf` lst
- then replacement ++ (substitute target replacement $ drop (length target) lst)
- else (head lst):(substitute target replacement $ tail lst)
+ then replacement ++ substitute target replacement (drop (length target) lst)
+ else x : substitute target replacement xs
--
-- Text processing
@@ -243,6 +197,30 @@ unescapeURI :: String -> String
unescapeURI = escapeURIString (\c -> isAllowedInURI c || not (isAscii c)) .
decodeString . unEscapeString
+-- | Convert tabs to spaces and filter out DOS line endings.
+-- Tabs will be preserved if tab stop is set to 0.
+tabFilter :: Int -- ^ Tab stop
+ -> String -- ^ Input
+ -> String
+tabFilter tabStop =
+ let go _ [] = ""
+ go _ ('\n':xs) = '\n' : go tabStop xs
+ go _ ('\r':'\n':xs) = '\n' : go tabStop xs
+ go _ ('\r':xs) = '\n' : go tabStop xs
+ go spsToNextStop ('\t':xs) =
+ if tabStop == 0
+ then '\t' : go tabStop xs
+ else replicate spsToNextStop ' ' ++ go tabStop xs
+ go 1 (x:xs) =
+ x : go tabStop xs
+ go spsToNextStop (x:xs) =
+ x : go (spsToNextStop - 1) xs
+ in go tabStop
+
+--
+-- Prettyprinting
+--
+
-- | Wrap inlines to line length.
wrapped :: Monad m => ([Inline] -> m Doc) -> [Inline] -> m Doc
wrapped listWriter sect = (mapM listWriter $ splitBy Space sect) >>=
@@ -312,538 +290,10 @@ wrappedBlocksToDoc = foldr addBlock empty
addBlock (Pad d) accum = d $$ text "" $$ accum
addBlock (Reg d) accum = d $$ accum
--- | Convert tabs to spaces and filter out DOS line endings.
--- Tabs will be preserved if tab stop is set to 0.
-tabFilter :: Int -- ^ Tab stop
- -> String -- ^ Input
- -> String
-tabFilter tabStop =
- let go _ [] = ""
- go _ ('\n':xs) = '\n' : go tabStop xs
- go _ ('\r':'\n':xs) = '\n' : go tabStop xs
- go _ ('\r':xs) = '\n' : go tabStop xs
- go spsToNextStop ('\t':xs) =
- if tabStop == 0
- then '\t' : go tabStop xs
- else replicate spsToNextStop ' ' ++ go tabStop xs
- go 1 (x:xs) =
- x : go tabStop xs
- go spsToNextStop (x:xs) =
- x : go (spsToNextStop - 1) xs
- in go tabStop
-
---
--- Parsing
---
-
--- | Like >>, but returns the operation on the left.
--- (Suggested by Tillmann Rendel on Haskell-cafe list.)
-(>>~) :: (Monad m) => m a -> m b -> m a
-a >>~ b = a >>= \x -> b >> return x
-
--- | Parse any line of text
-anyLine :: GenParser 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 p end = do
- first <- p
- rest <- manyTill p end
- return (first:rest)
-
--- | 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' 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 a space or tab.
-spaceChar :: CharParser st Char
-spaceChar = char ' ' <|> char '\t'
-
--- | Skips zero or more spaces or tabs.
-skipSpaces :: GenParser Char st ()
-skipSpaces = skipMany spaceChar
-
--- | Skips zero or more spaces or tabs, then reads a newline.
-blankline :: GenParser 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 = 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 $
- start >> notFollowedBy space >> many1Till parser end
-
--- | Parse string, case insensitive.
-stringAnyCase :: [Char] -> CharParser st String
-stringAnyCase [] = string ""
-stringAnyCase (x:xs) = do
- firstChar <- char (toUpper x) <|> char (toLower x)
- rest <- stringAnyCase xs
- return (firstChar:rest)
-
--- | Parse contents of 'str' using 'parser' and return result.
-parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a
-parseFromString parser str = do
- oldPos <- getPosition
- oldInput <- getInput
- setInput str
- result <- parser
- setInput oldInput
- setPosition oldPos
- return result
-
--- | Parse raw line block up to and including blank lines.
-lineClump :: GenParser Char st String
-lineClump = blanklines
- <|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines)
-
--- | Parse a string of characters between an open character
--- and a close character, including text between balanced
--- pairs of open and close, which must be different. For example,
--- @charsInBalanced '(' ')'@ will parse "(hello (there))"
--- and return "hello (there)". Stop if a blank line is
--- encountered.
-charsInBalanced :: Char -> Char -> GenParser Char st String
-charsInBalanced open close = try $ do
- char open
- raw <- many $ (many1 (noneOf [open, close, '\n']))
- <|> (do res <- charsInBalanced open close
- return $ [open] ++ res ++ [close])
- <|> try (string "\n" >>~ notFollowedBy' blanklines)
- char close
- return $ concat raw
-
--- | Like @charsInBalanced@, but allow blank lines in the content.
-charsInBalanced' :: Char -> Char -> GenParser Char st String
-charsInBalanced' open close = try $ do
- char open
- raw <- many $ (many1 (noneOf [open, close]))
- <|> (do res <- charsInBalanced' open close
- return $ [open] ++ res ++ [close])
- char close
- return $ concat raw
-
--- Auxiliary functions for romanNumeral:
-
-lowercaseRomanDigits :: [Char]
-lowercaseRomanDigits = ['i','v','x','l','c','d','m']
-
-uppercaseRomanDigits :: [Char]
-uppercaseRomanDigits = map toUpper lowercaseRomanDigits
-
--- | Parses a roman numeral (uppercase or lowercase), returns number.
-romanNumeral :: Bool -- ^ Uppercase if true
- -> GenParser Char st Int
-romanNumeral upperCase = do
- let romanDigits = if upperCase
- then uppercaseRomanDigits
- else lowercaseRomanDigits
- lookAhead $ oneOf romanDigits
- let [one, five, ten, fifty, hundred, fivehundred, thousand] =
- map char romanDigits
- thousands <- many thousand >>= (return . (1000 *) . length)
- ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900
- fivehundreds <- many fivehundred >>= (return . (500 *) . length)
- fourhundreds <- option 0 $ try $ hundred >> fivehundred >> return 400
- hundreds <- many hundred >>= (return . (100 *) . length)
- nineties <- option 0 $ try $ ten >> hundred >> return 90
- fifties <- many fifty >>= (return . (50 *) . length)
- forties <- option 0 $ try $ ten >> fifty >> return 40
- tens <- many ten >>= (return . (10 *) . length)
- nines <- option 0 $ try $ one >> ten >> return 9
- fives <- many five >>= (return . (5 *) . length)
- fours <- option 0 $ try $ one >> five >> return 4
- ones <- many one >>= (return . length)
- let total = thousands + ninehundreds + fivehundreds + fourhundreds +
- hundreds + nineties + fifties + forties + tens + nines +
- fives + fours + ones
- if total == 0
- then fail "not a roman numeral"
- else return total
-
--- Parsers for email addresses and URIs
-
-emailChar :: GenParser Char st Char
-emailChar = alphaNum <|> oneOf "-+_."
-
-domainChar :: GenParser Char st Char
-domainChar = alphaNum <|> char '-'
-
-domain :: GenParser Char st [Char]
-domain = do
- first <- many1 domainChar
- dom <- many1 $ try (char '.' >> many1 domainChar )
- return $ intercalate "." (first:dom)
-
--- | Parses an email address; returns original and corresponding
--- escaped mailto: URI.
-emailAddress :: GenParser Char st (String, String)
-emailAddress = try $ do
- firstLetter <- alphaNum
- restAddr <- many emailChar
- let addr = firstLetter:restAddr
- char '@'
- dom <- domain
- let full = addr ++ '@':dom
- return (full, escapeURI $ "mailto:" ++ full)
-
--- | Parses a URI. Returns pair of original and URI-escaped version.
-uri :: GenParser Char st (String, String)
-uri = try $ do
- let protocols = [ "http:", "https:", "ftp:", "file:", "mailto:",
- "news:", "telnet:" ]
- lookAhead $ oneOfStrings protocols
- -- scan non-ascii characters and ascii characters allowed in a URI
- str <- many1 $ satisfy (\c -> not (isAscii c) || isAllowedInURI c)
- -- now see if they amount to an absolute URI
- case parseURI (escapeURI str) of
- Just uri' -> if uriScheme uri' `elem` protocols
- then return (str, show uri')
- else fail "not a URI"
- Nothing -> fail "not a URI"
-
--- | Applies a parser, returns tuple of its results and its horizontal
--- 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 = do
- pos1 <- getPosition
- result <- parser
- pos2 <- getPosition
- return (result, sourceColumn pos2 - sourceColumn pos1)
-
--- | Parses a character and returns 'Null' (so that the parser can move on
--- if it gets stuck).
-nullBlock :: GenParser Char st Block
-nullBlock = anyChar >> return Null
-
--- | Fail if reader is in strict markdown syntax mode.
-failIfStrict :: GenParser Char 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 = do
- state <- getState
- if stateLiterateHaskell state then return () else fail "Literate haskell feature"
-
--- | Parses backslash, then applies character parser.
-escaped :: GenParser Char st Char -- ^ Parser for character to escape
- -> GenParser Char st Inline
-escaped parser = try $ do
- char '\\'
- result <- parser
- return (Str [result])
-
--- | Parses an uppercase roman numeral and returns (UpperRoman, number).
-upperRoman :: GenParser 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 = do
- num <- romanNumeral False
- return (LowerRoman, num)
-
--- | Parses a decimal numeral and returns (Decimal, number).
-decimal :: GenParser Char st (ListNumberStyle, Int)
-decimal = do
- num <- many1 digit
- return (Decimal, read num)
-
--- | Parses a '#' returns (DefaultStyle, 1).
-defaultNum :: GenParser 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 = 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 = 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 = (char 'i' >> return (LowerRoman, 1)) <|>
- (char 'I' >> return (UpperRoman, 1))
-
--- | Parses an ordered list marker and returns list attributes.
-anyOrderedListMarker :: GenParser Char st ListAttributes
-anyOrderedListMarker = choice $
- [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens],
- numParser <- [decimal, 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 num = try $ do
- (style, start) <- num
- char '.'
- let delim = if style == DefaultStyle
- 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 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 num = try $ do
- char '('
- (style, start) <- num
- char ')'
- return (start, style, TwoParens)
-
--- | Parses an ordered list marker with a given style and delimiter,
--- returns number.
-orderedListMarker :: ListNumberStyle
- -> ListNumberDelim
- -> GenParser Char st Int
-orderedListMarker style delim = do
- let num = defaultNum <|> -- # can continue any kind of list
- case style of
- DefaultStyle -> decimal
- Decimal -> decimal
- UpperRoman -> upperRoman
- LowerRoman -> lowerRoman
- UpperAlpha -> upperAlpha
- LowerAlpha -> lowerAlpha
- let context = case delim of
- DefaultDelim -> inPeriod
- Period -> inPeriod
- OneParen -> inOneParen
- TwoParens -> inTwoParens
- (start, _, _) <- context num
- return start
-
--- | Parses a character reference and returns a Str element.
-charRef :: GenParser Char st Inline
-charRef = do
- c <- characterReference
- return $ Str [c]
-
--- | Parse a string with a given parser and state.
-readWith :: GenParser Char ParserState a -- ^ parser
- -> ParserState -- ^ initial state
- -> String -- ^ input string
- -> a
-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
- -> String
- -> IO ()
-testStringWith parser str = putStrLn $ show $
- readWith parser defaultParserState str
-
--- | Parsing options.
-data ParserState = ParserState
- { stateParseRaw :: Bool, -- ^ Parse raw HTML and LaTeX?
- stateParserContext :: ParserContext, -- ^ Inside list?
- stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment?
- stateSanitizeHTML :: Bool, -- ^ Sanitize HTML?
- stateKeys :: KeyTable, -- ^ List of reference keys
-#ifdef _CITEPROC
- stateCitations :: [String], -- ^ List of available citations
-#endif
- stateNotes :: NoteTable, -- ^ List of notes
- stateTabStop :: Int, -- ^ Tab stop
- stateStandalone :: Bool, -- ^ Parse bibliographic info?
- 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?
- 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
- }
- deriving Show
-
-defaultParserState :: ParserState
-defaultParserState =
- ParserState { stateParseRaw = False,
- stateParserContext = NullState,
- stateQuoteContext = NoQuote,
- stateSanitizeHTML = False,
- stateKeys = [],
-#ifdef _CITEPROC
- stateCitations = [],
-#endif
- stateNotes = [],
- stateTabStop = 4,
- stateStandalone = False,
- stateTitle = [],
- stateAuthors = [],
- stateDate = [],
- stateStrict = False,
- stateSmart = False,
- stateLiterateHaskell = False,
- stateColumns = 80,
- stateHeaderTable = [],
- stateIndentedCodeClasses = [] }
-
-data HeaderType
- = SingleHeader Char -- ^ Single line of characters underneath
- | DoubleHeader Char -- ^ Lines of characters above and below
- deriving (Eq, Show)
-
-data ParserContext
- = ListItemState -- ^ Used when running parser on list item contents
- | NullState -- ^ Default state
- deriving (Eq, Show)
-
-data QuoteContext
- = InSingleQuote -- ^ Used when parsing inside single quotes
- | InDoubleQuote -- ^ Used when parsing inside double quotes
- | NoQuote -- ^ Used when not parsing inside quotes
- deriving (Eq, Show)
-
-type NoteTable = [(String, String)]
-
-type KeyTable = [([Inline], Target)]
-
--- | Look up key in key table and return target object.
-lookupKeySrc :: KeyTable -- ^ Key table
- -> [Inline] -- ^ Key
- -> Maybe Target
-lookupKeySrc table key = case find (refsMatch key . fst) table of
- Nothing -> Nothing
- Just (_, src) -> Just src
-
--- | Returns @True@ if keys match (case insensitive).
-refsMatch :: [Inline] -> [Inline] -> Bool
-refsMatch ((Str x):restx) ((Str y):resty) =
- ((map toLower x) == (map toLower y)) && refsMatch restx resty
-refsMatch ((Emph x):restx) ((Emph y):resty) =
- refsMatch x y && refsMatch restx resty
-refsMatch ((Strong x):restx) ((Strong y):resty) =
- refsMatch x y && refsMatch restx resty
-refsMatch ((Strikeout x):restx) ((Strikeout y):resty) =
- refsMatch x y && refsMatch restx resty
-refsMatch ((Superscript x):restx) ((Superscript y):resty) =
- refsMatch x y && refsMatch restx resty
-refsMatch ((Subscript x):restx) ((Subscript y):resty) =
- refsMatch x y && refsMatch restx resty
-refsMatch ((SmallCaps x):restx) ((SmallCaps y):resty) =
- refsMatch x y && refsMatch restx resty
-refsMatch ((Quoted t x):restx) ((Quoted u y):resty) =
- t == u && refsMatch x y && refsMatch restx resty
-refsMatch ((Code x):restx) ((Code y):resty) =
- ((map toLower x) == (map toLower y)) && refsMatch restx resty
-refsMatch ((Math t x):restx) ((Math u y):resty) =
- ((map toLower x) == (map toLower y)) && t == u && refsMatch restx resty
-refsMatch ((TeX x):restx) ((TeX y):resty) =
- ((map toLower x) == (map toLower y)) && refsMatch restx resty
-refsMatch ((HtmlInline x):restx) ((HtmlInline y):resty) =
- ((map toLower x) == (map toLower y)) && refsMatch restx resty
-refsMatch (x:restx) (y:resty) = (x == y) && refsMatch restx resty
-refsMatch [] x = null x
-refsMatch x [] = null x
-
---
--- Prettyprinting
---
-
-- | A version of hang that works like the version in pretty-1.0.0.0
hang' :: Doc -> Int -> Doc -> Doc
hang' d1 n d2 = d1 $$ (nest n d2)
--- | Indent string as a block.
-indentBy :: Int -- ^ Number of spaces to indent the block
- -> Int -- ^ Number of spaces (rel to block) to indent first line
- -> String -- ^ Contents of block to indent
- -> String
-indentBy _ _ [] = ""
-indentBy num first str =
- let (firstLine:restLines) = lines str
- firstLineIndent = num + first
- in (replicate firstLineIndent ' ') ++ firstLine ++ "\n" ++
- (intercalate "\n" $ map ((replicate num ' ') ++ ) restLines)
-
--- | Prettyprint list of Pandoc blocks elements.
-prettyBlockList :: Int -- ^ Number of spaces to indent list of blocks
- -> [Block] -- ^ List of blocks
- -> String
-prettyBlockList indent [] = indentBy indent 0 "[]"
-prettyBlockList indent blocks = indentBy indent (-2) $ "[ " ++
- (intercalate "\n, " (map prettyBlock blocks)) ++ " ]"
-
--- | Prettyprint Pandoc block element.
-prettyBlock :: Block -> String
-prettyBlock (BlockQuote blocks) = "BlockQuote\n " ++
- (prettyBlockList 2 blocks)
-prettyBlock (OrderedList attribs blockLists) =
- "OrderedList " ++ show attribs ++ "\n" ++ indentBy 2 0 ("[ " ++
- (intercalate ", " $ map (\blocks -> prettyBlockList 2 blocks)
- blockLists)) ++ " ]"
-prettyBlock (BulletList blockLists) = "BulletList\n" ++
- indentBy 2 0 ("[ " ++ (intercalate ", "
- (map (\blocks -> prettyBlockList 2 blocks) blockLists))) ++ " ]"
-prettyBlock (DefinitionList items) = "DefinitionList\n" ++
- indentBy 2 0 ("[ " ++ (intercalate "\n, "
- (map (\(term, defs) -> "(" ++ show term ++ ",\n" ++
- indentBy 3 0 ("[ " ++ (intercalate ", "
- (map (\blocks -> prettyBlockList 2 blocks) defs)) ++ "]") ++
- ")") items))) ++ " ]"
-prettyBlock (Table caption aligns widths header rows) =
- "Table " ++ show caption ++ " " ++ show aligns ++ " " ++
- show widths ++ "\n" ++ prettyRow header ++ " [\n" ++
- (intercalate ",\n" (map prettyRow rows)) ++ " ]"
- where prettyRow cols = indentBy 2 0 ("[ " ++ (intercalate ", "
- (map (\blocks -> prettyBlockList 2 blocks)
- cols))) ++ " ]"
-prettyBlock block = show block
-
--- | Prettyprint Pandoc document.
-prettyPandoc :: Pandoc -> String
-prettyPandoc (Pandoc meta blocks) = "Pandoc " ++ "(" ++ show meta ++
- ")\n" ++ (prettyBlockList 0 blocks) ++ "\n"
-
--
-- Pandoc block and inline list processing
--
@@ -855,6 +305,7 @@ 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 $
map singleton ['A'..'Z']
@@ -916,11 +367,11 @@ data Element = Blk Block
-- | Convert Pandoc inline list to plain text identifier. HTML
-- identifiers must start with a letter, and may contain only
--- letters, digits, and the characters _-:.
+-- letters, digits, and the characters _-.
inlineListToIdentifier :: [Inline] -> String
inlineListToIdentifier =
dropWhile (not . isAlpha) . intercalate "-" . words . map toLower .
- filter (\c -> isLetter c || isDigit c || c `elem` "_-:. ") .
+ filter (\c -> isLetter c || isDigit c || c `elem` "_-. ") .
concatMap extractText
where extractText x = case x of
Str s -> s
@@ -991,6 +442,13 @@ isHeaderBlock :: Block -> Bool
isHeaderBlock (Header _ _) = True
isHeaderBlock _ = False
+-- | Shift header levels up or down.
+headerShift :: Int -> Pandoc -> Pandoc
+headerShift n = processWith shift
+ where shift :: Block -> Block
+ shift (Header level inner) = Header (level + n) inner
+ shift x = x
+
--
-- Writer options
--
@@ -999,7 +457,7 @@ data HTMLMathMethod = PlainMath
| LaTeXMathML (Maybe String) -- url of LaTeXMathML.js
| JsMath (Maybe String) -- url of jsMath load script
| GladTeX
- | MimeTeX String -- url of mimetex.cgi
+ | WebTeX String -- url of TeX->image script.
| MathML (Maybe String) -- url of MathMLinHTML.js
deriving (Show, Read, Eq)
@@ -1009,27 +467,35 @@ data ObfuscationMethod = NoObfuscation
| JavascriptObfuscation
deriving (Show, Read, Eq)
+-- | Varieties of HTML slide shows.
+data HTMLSlideVariant = S5Slides
+ | SlidySlides
+ | 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
- , writerIncludeBefore :: String -- ^ Text to include before the body
- , writerIncludeAfter :: String -- ^ Text to include after the body
+ , writerEPUBMetadata :: String -- ^ Metadata to include in EPUB
, writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs
, writerTableOfContents :: Bool -- ^ Include table of contents
- , writerS5 :: Bool -- ^ We're writing S5
+ , writerSlideVariant :: HTMLSlideVariant -- ^ Are we writing S5 or Slidy?
+ , 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)
- , writerIncremental :: Bool -- ^ Incremental S5 lists
, 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
, 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
} deriving Show
-- | Default writer options.
@@ -1038,22 +504,24 @@ defaultWriterOptions =
WriterOptions { writerStandalone = False
, writerTemplate = ""
, writerVariables = []
- , writerIncludeBefore = ""
- , writerIncludeAfter = ""
+ , writerEPUBMetadata = ""
, writerTabStop = 4
, writerTableOfContents = False
- , writerS5 = False
+ , writerSlideVariant = NoSlides
+ , writerIncremental = False
, writerXeTeX = False
, writerHTMLMathMethod = PlainMath
, writerIgnoreNotes = False
- , writerIncremental = False
, writerNumberSections = False
+ , writerSectionDivs = True
, writerStrictMarkdown = False
, writerReferenceLinks = False
, writerWrapText = True
, writerLiterateHaskell = False
, writerEmailObfuscation = JavascriptObfuscation
, writerIdentifierPrefix = ""
+ , writerSourceDirectory = "."
+ , writerUserDataDir = Nothing
}
--
@@ -1074,6 +542,6 @@ inDirectory path action = do
readDataFile :: Maybe FilePath -> FilePath -> IO String
readDataFile userDir fname =
case userDir of
- Nothing -> getDataFileName fname >>= readFile
- Just u -> catch (readFile $ u </> fname)
- (\_ -> getDataFileName fname >>= readFile)
+ Nothing -> getDataFileName fname >>= UTF8.readFile
+ Just u -> catch (UTF8.readFile $ u </> fname)
+ (\_ -> getDataFileName fname >>= UTF8.readFile)
diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs
index 2238f4da8..c8ddc3abf 100644
--- a/src/Text/Pandoc/Templates.hs
+++ b/src/Text/Pandoc/Templates.hs
@@ -83,7 +83,6 @@ getDefaultTemplate :: (Maybe FilePath) -- ^ User data directory to search first
-> String -- ^ Name of writer
-> IO (Either E.IOException String)
getDefaultTemplate _ "native" = return $ Right ""
-getDefaultTemplate user "s5" = getDefaultTemplate user "html"
getDefaultTemplate user "odt" = getDefaultTemplate user "opendocument"
getDefaultTemplate user writer = do
let format = takeWhile (/='+') writer -- strip off "+lhs" if present
@@ -173,7 +172,7 @@ for = try $ do
string "$for("
id' <- ident
string ")$"
- -- if newline after the "if", then a newline after "endif" will be swallowed
+ -- 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 indent = replicate pos ' '
diff --git a/src/Text/Pandoc/UTF8.hs b/src/Text/Pandoc/UTF8.hs
new file mode 100644
index 000000000..96d6e6218
--- /dev/null
+++ b/src/Text/Pandoc/UTF8.hs
@@ -0,0 +1,72 @@
+{-
+Copyright (C) 2010 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.UTF8
+ Copyright : Copyright (C) 2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+UTF-8 aware string IO functions that will work with GHC 6.10 or 6.12.
+-}
+module Text.Pandoc.UTF8 ( readFile
+ , writeFile
+ , getContents
+ , putStr
+ , putStrLn
+ , hPutStr
+ , hPutStrLn
+ )
+
+where
+import qualified Data.ByteString as B
+import Data.ByteString.UTF8 (toString, fromString)
+import Prelude hiding (readFile, writeFile, getContents, putStr, putStrLn)
+import System.IO (Handle)
+import Control.Monad (liftM)
+
+bom :: B.ByteString
+bom = B.pack [0xEF, 0xBB, 0xBF]
+
+stripBOM :: B.ByteString -> B.ByteString
+stripBOM s | bom `B.isPrefixOf` s = B.drop 3 s
+stripBOM s = s
+
+readFile :: FilePath -> IO String
+readFile = liftM (toString . stripBOM) . B.readFile
+
+writeFile :: FilePath -> String -> IO ()
+writeFile f = B.writeFile f . fromString
+
+getContents :: IO String
+getContents = liftM (toString . stripBOM) B.getContents
+
+putStr :: String -> IO ()
+putStr = B.putStr . fromString
+
+putStrLn :: String -> IO ()
+putStrLn = B.putStrLn . fromString
+
+hPutStr :: Handle -> String -> IO ()
+hPutStr h = B.hPutStr h . fromString
+
+hPutStrLn :: Handle -> String -> IO ()
+hPutStrLn h s = hPutStr h (s ++ "\n")
diff --git a/src/Text/Pandoc/UUID.hs b/src/Text/Pandoc/UUID.hs
new file mode 100644
index 000000000..082644eea
--- /dev/null
+++ b/src/Text/Pandoc/UUID.hs
@@ -0,0 +1,77 @@
+{-
+Copyright (C) 2010 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.UUID
+ Copyright : Copyright (C) 2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+UUID generation using Version 4 (random method) described
+in RFC4122. See http://tools.ietf.org/html/rfc4122
+-}
+
+module Text.Pandoc.UUID ( UUID, getRandomUUID ) where
+
+import Text.Printf ( printf )
+import System.Random ( randomIO )
+import Data.Word
+import Data.Bits ( setBit, clearBit )
+import Control.Monad ( liftM )
+
+data UUID = UUID Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8
+ Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8
+
+instance Show UUID where
+ show (UUID a b c d e f g h i j k l m n o p) =
+ "urn:uuid:" ++
+ printf "%02x" a ++
+ printf "%02x" b ++
+ printf "%02x" c ++
+ printf "%02x" d ++
+ "-" ++
+ printf "%02x" e ++
+ printf "%02x" f ++
+ "-" ++
+ printf "%02x" g ++
+ printf "%02x" h ++
+ "-" ++
+ printf "%02x" i ++
+ printf "%02x" j ++
+ "-" ++
+ printf "%02x" k ++
+ printf "%02x" l ++
+ printf "%02x" m ++
+ printf "%02x" n ++
+ printf "%02x" o ++
+ printf "%02x" p
+
+getRandomUUID :: IO UUID
+getRandomUUID = do
+ let getRN :: a -> IO Word8
+ getRN _ = liftM fromIntegral (randomIO :: IO Int)
+ [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] <- mapM getRN ([1..16] :: [Int])
+ -- set variant
+ let i' = i `setBit` 7 `clearBit` 6
+ -- set version (0100 for random)
+ let g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4
+ return $ UUID a b c d e f g' h i' j k l m n o p
+
diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs
index 32948e292..395bc2d30 100644
--- a/src/Text/Pandoc/Writers/ConTeXt.hs
+++ b/src/Text/Pandoc/Writers/ConTeXt.hs
@@ -64,7 +64,7 @@ pandocToConTeXt options (Pandoc (Meta title authors date) blocks) = do
then return ""
else liftM render $ inlineListToConTeXt date
body <- blockListToConTeXt blocks
- let main = render body
+ let main = render $ body $$ text ""
let context = writerVariables options ++
[ ("toc", if writerTableOfContents options then "yes" else "")
, ("body", main)
@@ -153,6 +153,7 @@ blockToConTeXt (OrderedList (start, style', delim) lst) = do
let style'' = case style' of
DefaultStyle -> orderedListStyles !! level
Decimal -> "[n]"
+ Example -> "[n]"
LowerRoman -> "[r]"
UpperRoman -> "[R]"
LowerAlpha -> "[a]"
diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs
index 3abed1610..5223259eb 100644
--- a/src/Text/Pandoc/Writers/Docbook.hs
+++ b/src/Text/Pandoc/Writers/Docbook.hs
@@ -154,6 +154,7 @@ blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) =
let attribs = case numstyle of
DefaultStyle -> []
Decimal -> [("numeration", "arabic")]
+ Example -> [("numeration", "arabic")]
UpperAlpha -> [("numeration", "upperalpha")]
LowerAlpha -> [("numeration", "loweralpha")]
UpperRoman -> [("numeration", "upperroman")]
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
new file mode 100644
index 000000000..deaa2fe33
--- /dev/null
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -0,0 +1,283 @@
+{-
+Copyright (C) 2010 John MacFarlane <jgm@berkeley.edu>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-}
+
+{- |
+ Module : Text.Pandoc.Writers.EPUB
+ Copyright : Copyright (C) 2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+Conversion of 'Pandoc' documents to EPUB.
+-}
+module Text.Pandoc.Writers.EPUB ( writeEPUB ) where
+import Data.IORef
+import Data.Maybe ( fromMaybe, isNothing )
+import Data.List ( findIndices, isPrefixOf )
+import System.Environment ( getEnv )
+import System.FilePath ( (</>), takeBaseName, takeExtension )
+import qualified Data.ByteString.Lazy as B
+import Data.ByteString.Lazy.UTF8 ( fromString )
+import Codec.Archive.Zip
+import System.Time
+import Text.Pandoc.Shared hiding ( Element )
+import Text.Pandoc.Definition
+import Control.Monad (liftM)
+import Text.XML.Light hiding (ppTopElement)
+import Text.Pandoc.UUID
+import Text.Pandoc.Writers.HTML
+import Text.Pandoc.Writers.Markdown ( writePlain )
+import Data.Char ( toLower )
+
+-- | Produce an EPUB file from a Pandoc document.
+writeEPUB :: Maybe String -- ^ EPUB stylesheet specified at command line
+ -> WriterOptions -- ^ Writer options
+ -> Pandoc -- ^ Document to convert
+ -> IO B.ByteString
+writeEPUB mbStylesheet opts doc@(Pandoc meta _) = do
+ (TOD epochtime _) <- getClockTime
+ let mkEntry path content = toEntry path epochtime content
+ let opts' = opts{ writerEmailObfuscation = NoObfuscation
+ , writerStandalone = True
+ , writerWrapText = False }
+ let sourceDir = writerSourceDirectory opts'
+
+ -- title page
+ let vars = writerVariables opts'
+ let tpContent = fromString $ writeHtmlString
+ opts'{writerTemplate = pageTemplate
+ ,writerVariables = ("titlepage","yes"):vars}
+ (Pandoc meta [])
+ let tpEntry = mkEntry "title_page.xhtml" tpContent
+
+ -- handle pictures
+ picsRef <- newIORef []
+ Pandoc _ blocks <- liftM (processWith transformBlock) $ processWithM
+ (transformInlines (writerHTMLMathMethod opts) sourceDir picsRef) doc
+ pics <- readIORef picsRef
+ let readPicEntry (oldsrc, newsrc) = readEntry [] oldsrc >>= \e ->
+ return e{ eRelativePath = newsrc }
+ picEntries <- mapM readPicEntry pics
+
+ -- body pages
+ let isH1 (Header 1 _) = True
+ isH1 _ = False
+ let h1Indices = dropWhile (== 0) $ findIndices isH1 blocks
+ let chunks = splitByIndices h1Indices blocks
+ let titleize (Header 1 xs : ys) = Pandoc meta{docTitle = xs} ys
+ titleize xs = Pandoc meta xs
+ let chapToHtml = writeHtmlString opts'{ writerTemplate = pageTemplate
+ , writerHTMLMathMethod = PlainMath }
+ let chapters = map titleize chunks
+ let chapterToEntry :: Int -> Pandoc -> Entry
+ chapterToEntry num chap = mkEntry ("ch" ++ show num ++ ".xhtml") $
+ fromString $ chapToHtml chap
+ let chapterEntries = zipWith chapterToEntry [1..] chapters
+
+ -- contents.opf
+ lang <- catch (liftM (takeWhile (/='.')) $ getEnv "lang")
+ (\_ -> return "en-US")
+ uuid <- getRandomUUID
+ let chapterNode ent = unode "item" !
+ [("id", takeBaseName $ eRelativePath ent),
+ ("href", eRelativePath ent),
+ ("media-type", "application/xhtml+xml")] $ ()
+ let chapterRefNode ent = unode "itemref" !
+ [("idref", takeBaseName $ eRelativePath ent)] $ ()
+ let pictureNode ent = unode "item" !
+ [("id", takeBaseName $ eRelativePath ent),
+ ("href", eRelativePath ent),
+ ("media-type", fromMaybe "application/octet-stream"
+ $ imageTypeOf $ eRelativePath ent)] $ ()
+ let plainify t = removeTrailingSpace $
+ writePlain opts'{ writerStandalone = False } $
+ Pandoc meta [Plain t]
+ let plainTitle = plainify $ docTitle meta
+ let plainAuthors = map plainify $ docAuthors meta
+ let contentsData = fromString $ ppTopElement $
+ unode "package" ! [("version","2.0")
+ ,("xmlns","http://www.idpf.org/2007/opf")
+ ,("unique-identifier","BookId")] $
+ [ metadataElement (writerEPUBMetadata opts')
+ uuid lang plainTitle plainAuthors
+ , unode "manifest" $
+ [ unode "item" ! [("id","ncx"), ("href","toc.ncx")
+ ,("media-type","application/x-dtbncx+xml")] $ ()
+ , unode "item" ! [("id","style"), ("href","stylesheet.css")
+ ,("media-type","text/css")] $ ()
+ ] ++
+ map chapterNode (tpEntry : chapterEntries) ++
+ map pictureNode picEntries
+ , unode "spine" ! [("toc","ncx")] $
+ map chapterRefNode (tpEntry : chapterEntries)
+ ]
+ let contentsEntry = mkEntry "content.opf" contentsData
+
+ -- toc.ncx
+ let navPointNode ent n tit = unode "navPoint" !
+ [("id", "navPoint-" ++ show n)
+ ,("playOrder", show n)] $
+ [ unode "navLabel" $ unode "text" tit
+ , unode "content" ! [("src",
+ eRelativePath ent)] $ ()
+ ]
+ let tocData = fromString $ ppTopElement $
+ unode "ncx" ! [("version","2005-1")
+ ,("xmlns","http://www.daisy.org/z3986/2005/ncx/")] $
+ [ unode "head"
+ [ unode "meta" ! [("name","dtb:uid")
+ ,("content", show uuid)] $ ()
+ , unode "meta" ! [("name","dtb:depth")
+ ,("content", "1")] $ ()
+ , unode "meta" ! [("name","dtb:totalPageCount")
+ ,("content", "0")] $ ()
+ , unode "meta" ! [("name","dtb:maxPageNumber")
+ ,("content", "0")] $ ()
+ ]
+ , unode "docTitle" $ unode "text" $ plainTitle
+ , unode "navMap" $ zipWith3 navPointNode (tpEntry : chapterEntries)
+ [1..(length chapterEntries + 1)]
+ ("Title Page" : map (\(Pandoc m _) ->
+ plainify $ docTitle m) chapters)
+ ]
+ let tocEntry = mkEntry "toc.ncx" tocData
+
+ -- mimetype
+ let mimetypeEntry = mkEntry "mimetype" $ fromString "application/epub+zip"
+
+ -- container.xml
+ let containerData = fromString $ ppTopElement $
+ unode "container" ! [("version","1.0")
+ ,("xmlns","urn:oasis:names:tc:opendocument:xmlns:container")] $
+ unode "rootfiles" $
+ unode "rootfile" ! [("full-path","content.opf")
+ ,("media-type","application/oebps-package+xml")] $ ()
+ let containerEntry = mkEntry "META-INF/container.xml" containerData
+
+ -- stylesheet
+ stylesheet <- case mbStylesheet of
+ Just s -> return s
+ Nothing -> readDataFile (writerUserDataDir opts) "epub.css"
+ let stylesheetEntry = mkEntry "stylesheet.css" $ fromString stylesheet
+
+ -- construct archive
+ let archive = foldr addEntryToArchive emptyArchive
+ (mimetypeEntry : containerEntry : stylesheetEntry : tpEntry :
+ contentsEntry : tocEntry : (picEntries ++ chapterEntries) )
+ return $ fromArchive archive
+
+metadataElement :: String -> UUID -> String -> String -> [String] -> Element
+metadataElement metadataXML uuid lang title authors =
+ 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
+ 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
+ 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") ] ++
+ [ unode "dc:identifier" ! [("id","BookId")] $ show uuid |
+ not (elt `contains` "identifier") ] ++
+ [ unode "dc:creator" ! [("opf:role","aut")] $ a | a <- authors ]
+ in elt{ elContent = elContent elt ++ map Elem newNodes }
+
+transformInlines :: HTMLMathMethod
+ -> FilePath
+ -> IORef [(FilePath, FilePath)] -- ^ (oldpath, newpath) images
+ -> [Inline]
+ -> IO [Inline]
+transformInlines _ _ _ (Image lab (src,_) : xs) | isNothing (imageTypeOf src) =
+ return $ Emph lab : xs
+transformInlines _ sourceDir picsRef (Image lab (src,tit) : xs) = do
+ pics <- readIORef picsRef
+ let oldsrc = sourceDir </> src
+ let ext = takeExtension src
+ newsrc <- case lookup oldsrc pics of
+ Just n -> return n
+ Nothing -> do
+ let new = "images/img" ++ show (length pics) ++ ext
+ modifyIORef picsRef ( (oldsrc, new): )
+ return new
+ return $ Image lab (newsrc, tit) : xs
+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
+ 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>" ++
+ "</ops:switch>"
+ result = if "<math" `isPrefixOf` mathml then inOps else mathml
+ return $ HtmlInline result : xs
+transformInlines _ _ _ (HtmlInline _ : xs) = return $ Str "" : xs
+transformInlines _ _ _ (Link lab (_,_) : xs) = return $ lab ++ xs
+transformInlines _ _ _ xs = return xs
+
+transformBlock :: Block -> Block
+transformBlock (RawHtml _) = Null
+transformBlock x = x
+
+(!) :: Node t => (t -> Element) -> [(String, String)] -> t -> Element
+(!) f attrs n = add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) (f n)
+
+-- | Version of 'ppTopElement' that specifies UTF-8 encoding.
+ppTopElement :: Element -> String
+ppTopElement = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++) . ppElement
+
+imageTypeOf :: FilePath -> Maybe String
+imageTypeOf x = case drop 1 (map toLower (takeExtension x)) of
+ "jpg" -> Just "image/jpeg"
+ "jpeg" -> Just "image/jpeg"
+ "jfif" -> Just "image/jpeg"
+ "png" -> Just "image/png"
+ "gif" -> Just "image/gif"
+ "svg" -> Just "image/svg+xml"
+ _ -> Nothing
+
+pageTemplate :: String
+pageTemplate = unlines
+ [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ , "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"
+ , "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ , "<head>"
+ , "<title>$title$</title>"
+ , "<link href=\"stylesheet.css\" type=\"text/css\" rel=\"stylesheet\" />"
+ , "</head>"
+ , "<body>"
+ , "$if(titlepage)$"
+ , "<h1 class=\"title\">$title$</h1>"
+ , "$for(author)$"
+ , "<h2 class=\"author\">$author$</h2>"
+ , "$endfor$"
+ , "$else$"
+ , "<h1>$title$</h1>"
+ , "$body$"
+ , "$endif$"
+ , "</body>"
+ , "</html>"
+ ]
+
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
index 299471328..d2a400c5c 100644
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -34,8 +34,9 @@ import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )
import Text.Pandoc.Shared
import Text.Pandoc.Templates
import Text.Pandoc.Readers.TeXMath
-import Text.Pandoc.Highlighting ( highlightHtml )
+import Text.Pandoc.Highlighting ( highlightHtml, defaultHighlightingCss )
import Text.Pandoc.XML (stripTags, escapeStringForXML)
+import Network.HTTP ( urlEncode )
import Numeric ( showHex )
import Data.Char ( ord, toLower )
import Data.List ( isPrefixOf, intersperse )
@@ -104,7 +105,24 @@ pandocToHtml opts (Pandoc (Meta title' authors' date') blocks) = do
toc <- if writerTableOfContents opts
then tableOfContents opts sects
else return Nothing
- blocks' <- liftM toHtmlFromList $ mapM (elementToHtml opts) sects
+ let startSlide = RawHtml "<div class=\"slide\">\n"
+ endSlide = RawHtml "</div>\n"
+ let cutUp (HorizontalRule : Header 1 ys : xs) = cutUp (Header 1 ys : xs)
+ cutUp (HorizontalRule : xs) = [endSlide, startSlide] ++ cutUp xs
+ cutUp (Header 1 ys : xs) = [endSlide, startSlide] ++
+ (Header 1 ys : cutUp xs)
+ cutUp (x:xs) = x : cutUp xs
+ cutUp [] = []
+ let slides = case blocks of
+ (HorizontalRule : xs) -> [startSlide] ++ cutUp xs ++ [endSlide]
+ (Header 1 ys : xs) -> [startSlide, Header 1 ys] ++
+ cutUp xs ++ [endSlide]
+ _ -> [startSlide] ++ cutUp blocks ++
+ [endSlide]
+ blocks' <- liftM toHtmlFromList $
+ if writerSlideVariant opts `elem` [SlidySlides, S5Slides]
+ then mapM (blockToHtml opts) slides
+ else mapM (elementToHtml opts) sects
st <- get
let notes = reverse (stNotes st)
let thebody = blocks' +++ footnoteSection notes
@@ -125,7 +143,8 @@ pandocToHtml opts (Pandoc (Meta title' authors' date') blocks) = do
primHtml s
Nothing -> noHtml
else noHtml
- let newvars = [("highlighting","yes") | stHighlighting st] ++
+ let newvars = [("highlighting-css", defaultHighlightingCss) |
+ stHighlighting st] ++
[("math", renderHtmlFragment math) | stMath st]
return (tit, auths, date, toc, thebody, newvars)
@@ -197,10 +216,16 @@ elementToHtml opts (Sec level num id' title' elements) = do
innerContents <- mapM (elementToHtml opts) elements
modify $ \st -> st{stSecNum = num} -- update section number
header' <- blockToHtml opts (Header level title')
- return $ if writerS5 opts || (writerStrictMarkdown opts && not (writerTableOfContents opts))
- -- S5 gets confused by the extra divs around sections
- then toHtmlFromList (header' : innerContents)
- else thediv ! [prefixedId opts id'] << (header' : innerContents)
+ let slides = writerSlideVariant opts `elem` [SlidySlides, S5Slides]
+ let header'' = header' ! [prefixedId opts id' |
+ not (writerStrictMarkdown opts ||
+ writerSectionDivs opts || slides)]
+ let stuff = header'' : innerContents
+ return $ if slides -- S5 gets confused by the extra divs around sections
+ then toHtmlFromList stuff
+ else if writerSectionDivs opts
+ then thediv ! [prefixedId opts id'] << stuff
+ else toHtmlFromList stuff
-- | Convert list of Note blocks to a footnote <div>.
-- Assumes notes are sorted.
@@ -285,15 +310,18 @@ blockToHtml opts (CodeBlock (id',classes,keyvals) rawCode) = do
attrs = [theclass (unwords classes') | not (null classes')] ++
[prefixedId opts id' | not (null id')] ++
map (\(x,y) -> strAttr x y) keyvals
+ addBird = if "literate" `elem` classes'
+ then unlines . map ("> " ++) . lines
+ else unlines . lines
in return $ pre ! attrs $ thecode <<
(replicate (length leadingBreaks) br +++
- [stringToHtml $ rawCode' ++ "\n"])
+ [stringToHtml $ addBird rawCode'])
Right h -> modify (\st -> st{ stHighlighting = True }) >> return h
blockToHtml opts (BlockQuote blocks) =
-- in S5, treat list in blockquote specially
-- if default is incremental, make it nonincremental;
-- otherwise incremental
- if writerS5 opts
+ if writerSlideVariant opts /= NoSlides
then let inc = not (writerIncremental opts) in
case blocks of
[BulletList lst] -> blockToHtml (opts {writerIncremental = inc})
@@ -444,16 +472,20 @@ inlineToHtml opts inline =
-- non-math elements on the page from being treated as math by
-- the javascript
return $ thespan ! [theclass "LaTeX"] $
- if t == InlineMath
- then primHtml ("$" ++ str ++ "$")
- else primHtml ("$$" ++ str ++ "$$")
- JsMath _ ->
- return $ if t == InlineMath
- then thespan ! [theclass "math"] $ primHtml str
- else thediv ! [theclass "math"] $ primHtml str
- MimeTeX url ->
- return $ image ! [src (url ++ "?" ++ str),
- alt str, title str]
+ case t of
+ InlineMath -> primHtml ("$" ++ str ++ "$")
+ DisplayMath -> primHtml ("$$" ++ str ++ "$$")
+ JsMath _ -> do
+ let m = primHtml str
+ return $ case t of
+ InlineMath -> thespan ! [theclass "math"] $ m
+ DisplayMath -> thediv ! [theclass "math"] $ m
+ WebTeX url -> do
+ let m = image ! [src (url ++ urlEncode str),
+ alt str, title str]
+ return $ case t of
+ InlineMath -> m
+ DisplayMath -> br +++ m +++ br
GladTeX ->
return $ primHtml $ "<EQ>" ++ str ++ "</EQ>"
MathML _ -> do
@@ -466,12 +498,14 @@ inlineToHtml opts inline =
Right r -> return $ primHtml $
ppcElement conf r
Left _ -> inlineListToHtml opts
- (readTeXMath str) >>=
- return . (thespan !
- [theclass "math"])
- PlainMath ->
- inlineListToHtml opts (readTeXMath str) >>=
- return . (thespan ! [theclass "math"]) )
+ (readTeXMath str) >>= return .
+ (thespan ! [theclass "math"])
+ PlainMath -> do
+ x <- inlineListToHtml opts (readTeXMath str)
+ let m = thespan ! [theclass "math"] $ x
+ return $ case t of
+ InlineMath -> m
+ DisplayMath -> br +++ m +++ br )
(TeX str) -> case writerHTMLMathMethod opts of
LaTeXMathML _ -> do modify (\st -> st {stMath = True})
return $ primHtml str
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
index 8aa028bd7..720c00ac8 100644
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -338,7 +338,7 @@ inlineToLaTeX (Link txt (src, _)) =
char '}'
inlineToLaTeX (Image _ (source, _)) = do
modify $ \s -> s{ stGraphics = True }
- return $ text $ "\\includegraphics{" ++ source ++ "}"
+ return $ text $ "\\includegraphics{" ++ source ++ "}"
inlineToLaTeX (Note contents) = do
st <- get
put (st {stInNote = True})
diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs
index 77dead196..a46a18893 100644
--- a/src/Text/Pandoc/Writers/Man.hs
+++ b/src/Text/Pandoc/Writers/Man.hs
@@ -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.Readers.TeXMath
import Text.Printf ( printf )
import Data.List ( isPrefixOf, intersperse, intercalate )
import Text.PrettyPrint.HughesPJ hiding ( Str )
@@ -62,7 +63,7 @@ pandocToMan opts (Pandoc (Meta title authors date) blocks) = do
body <- blockListToMan opts blocks
notes <- liftM stNotes get
notes' <- notesToMan opts (reverse notes)
- let main = render $ body $$ notes'
+ let main = render $ body $$ notes' $$ text ""
hasTables <- liftM stHasTables get
let context = writerVariables opts ++
[ ("body", main)
@@ -150,8 +151,12 @@ blockToMan opts (Header level inlines) = do
_ -> ".SS "
return $ text heading <> contents
blockToMan _ (CodeBlock _ str) = return $
- text ".PP" $$ text "\\f[CR]" $$
- text ((unlines . map (" " ++) . lines) (escapeCode str)) <> text "\\f[]"
+ text ".IP" $$
+ text ".nf" $$
+ text "\\f[C]" $$
+ text (escapeCode str) $$
+ text "\\f[]" $$
+ text ".fi"
blockToMan opts (BlockQuote blocks) = do
contents <- blockListToMan opts blocks
return $ text ".RS" $$ contents $$ text ".RE"
@@ -299,11 +304,11 @@ inlineToMan _ EnDash = return $ text "\\[en]"
inlineToMan _ Apostrophe = return $ char '\''
inlineToMan _ Ellipses = return $ text "\\&..."
inlineToMan _ (Code str) =
- return $ text $ "\\f[B]" ++ escapeCode str ++ "\\f[]"
+ return $ text $ "\\f[C]" ++ escapeCode str ++ "\\f[]"
inlineToMan _ (Str str) = return $ text $ escapeString str
-inlineToMan opts (Math InlineMath str) = inlineToMan opts (Code str)
+inlineToMan opts (Math InlineMath str) = inlineListToMan opts $ readTeXMath str
inlineToMan opts (Math DisplayMath str) = do
- contents <- inlineToMan opts (Code str)
+ contents <- inlineListToMan opts $ readTeXMath str
return $ text ".RS" $$ contents $$ text ".RE"
inlineToMan _ (TeX _) = return empty
inlineToMan _ (HtmlInline _) = return empty
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
index fe8e0c2de..1b612006b 100644
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -32,15 +32,16 @@ Markdown: <http://daringfireball.net/projects/markdown/>
module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where
import Text.Pandoc.Definition
import Text.Pandoc.Templates (renderTemplate)
-import Text.Pandoc.Shared
+import Text.Pandoc.Shared
+import Text.Pandoc.Parsing
import Text.Pandoc.Blocks
-import Text.ParserCombinators.Parsec ( parse, GenParser )
+import Text.ParserCombinators.Parsec ( runParser, GenParser )
import Data.List ( group, isPrefixOf, find, intersperse, transpose )
import Text.PrettyPrint.HughesPJ hiding ( Str )
import Control.Monad.State
type Notes = [[Block]]
-type Refs = KeyTable
+type Refs = [([Inline], Target)]
data WriterState = WriterState { stNotes :: Notes
, stRefs :: Refs
, stPlain :: Bool }
@@ -94,8 +95,8 @@ pandocToMarkdown opts (Pandoc (Meta title authors date) blocks) = do
st <- get
notes' <- notesToMarkdown opts (reverse $ stNotes st)
st' <- get -- note that the notes may contain refs
- refs' <- keyTableToMarkdown opts (reverse $ stRefs st')
- let main = render $ body $+$ text "" $+$ notes' $+$ text "" $+$ refs'
+ refs' <- refsToMarkdown opts (reverse $ stRefs st')
+ let main = render $ foldl ($+$) empty $ [body, notes', refs']
let context = writerVariables opts ++
[ ("toc", render toc)
, ("body", main)
@@ -109,8 +110,8 @@ pandocToMarkdown opts (Pandoc (Meta title authors date) blocks) = do
else return main
-- | Return markdown representation of reference key table.
-keyTableToMarkdown :: WriterOptions -> KeyTable -> State WriterState Doc
-keyTableToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat
+refsToMarkdown :: WriterOptions -> Refs -> State WriterState Doc
+refsToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat
-- | Return markdown representation of a reference key.
keyToMarkdown :: WriterOptions
@@ -158,7 +159,7 @@ elementToListItem (Sec _ _ _ headerText subsecs) = [Plain headerText] ++
else [BulletList $ map elementToListItem subsecs]
-- | Ordered list start parser for use in Para below.
-olMarker :: GenParser Char st Char
+olMarker :: GenParser Char ParserState Char
olMarker = do (start, style', delim) <- anyOrderedListMarker
if delim == Period &&
(style' == UpperAlpha || (style' == UpperRoman &&
@@ -169,7 +170,7 @@ olMarker = do (start, style', delim) <- anyOrderedListMarker
-- | True if string begins with an ordered list marker
beginsWithOrderedListMarker :: String -> Bool
beginsWithOrderedListMarker str =
- case parse olMarker "para start" str of
+ case runParser olMarker defaultParserState "para start" str of
Left _ -> False
Right _ -> True
@@ -238,7 +239,7 @@ blockToMarkdown opts (Table caption aligns widths headers rows) = do
caption' <- inlineListToMarkdown opts caption
let caption'' = if null caption
then empty
- else text "" $+$ (text "Table: " <> caption')
+ else text "" $+$ (text ": " <> caption')
headers' <- mapM (blockListToMarkdown opts) headers
let alignHeader alignment = case alignment of
AlignLeft -> leftAlignBlock
@@ -372,14 +373,14 @@ inlineToMarkdown opts (Subscript lst) = do
inlineToMarkdown opts (SmallCaps lst) = inlineListToMarkdown opts lst
inlineToMarkdown opts (Quoted SingleQuote lst) = do
contents <- inlineListToMarkdown opts lst
- return $ char '\'' <> contents <> char '\''
+ return $ char '‘' <> contents <> char '’'
inlineToMarkdown opts (Quoted DoubleQuote lst) = do
contents <- inlineListToMarkdown opts lst
- return $ char '"' <> contents <> char '"'
-inlineToMarkdown _ EmDash = return $ text "--"
-inlineToMarkdown _ EnDash = return $ char '-'
-inlineToMarkdown _ Apostrophe = return $ char '\''
-inlineToMarkdown _ Ellipses = return $ text "..."
+ return $ char '“' <> contents <> char '”'
+inlineToMarkdown _ EmDash = return $ char '\8212'
+inlineToMarkdown _ EnDash = return $ char '\8211'
+inlineToMarkdown _ Apostrophe = return $ char '\8217'
+inlineToMarkdown _ Ellipses = return $ char '\8230'
inlineToMarkdown _ (Code str) =
let tickGroups = filter (\s -> '`' `elem` s) $ group str
longest = if null tickGroups
diff --git a/src/Text/Pandoc/Writers/Native.hs b/src/Text/Pandoc/Writers/Native.hs
new file mode 100644
index 000000000..3b5ea7481
--- /dev/null
+++ b/src/Text/Pandoc/Writers/Native.hs
@@ -0,0 +1,86 @@
+{-
+Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-}
+
+{- |
+ Module : Text.Pandoc.Writers.Native
+ Copyright : Copyright (C) 2006-2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+Utility functions and definitions used by the various Pandoc modules.
+-}
+module Text.Pandoc.Writers.Native ( writeNative )
+where
+import Text.Pandoc.Shared ( WriterOptions )
+import Data.List ( intercalate )
+import Text.Pandoc.Definition
+
+-- | Indent string as a block.
+indentBy :: Int -- ^ Number of spaces to indent the block
+ -> Int -- ^ Number of spaces (rel to block) to indent first line
+ -> String -- ^ Contents of block to indent
+ -> String
+indentBy _ _ [] = ""
+indentBy num first str =
+ let (firstLine:restLines) = lines str
+ firstLineIndent = num + first
+ in (replicate firstLineIndent ' ') ++ firstLine ++ "\n" ++
+ (intercalate "\n" $ map ((replicate num ' ') ++ ) restLines)
+
+-- | Prettyprint list of Pandoc blocks elements.
+prettyBlockList :: Int -- ^ Number of spaces to indent list of blocks
+ -> [Block] -- ^ List of blocks
+ -> String
+prettyBlockList indent [] = indentBy indent 0 "[]"
+prettyBlockList indent blocks = indentBy indent (-2) $ "[ " ++
+ (intercalate "\n, " (map prettyBlock blocks)) ++ " ]"
+
+-- | Prettyprint Pandoc block element.
+prettyBlock :: Block -> String
+prettyBlock (BlockQuote blocks) = "BlockQuote\n " ++
+ (prettyBlockList 2 blocks)
+prettyBlock (OrderedList attribs blockLists) =
+ "OrderedList " ++ show attribs ++ "\n" ++ indentBy 2 0 ("[ " ++
+ (intercalate ", " $ map (\blocks -> prettyBlockList 2 blocks)
+ blockLists)) ++ " ]"
+prettyBlock (BulletList blockLists) = "BulletList\n" ++
+ indentBy 2 0 ("[ " ++ (intercalate ", "
+ (map (\blocks -> prettyBlockList 2 blocks) blockLists))) ++ " ]"
+prettyBlock (DefinitionList items) = "DefinitionList\n" ++
+ indentBy 2 0 ("[ " ++ (intercalate "\n, "
+ (map (\(term, defs) -> "(" ++ show term ++ ",\n" ++
+ indentBy 3 0 ("[ " ++ (intercalate ", "
+ (map (\blocks -> prettyBlockList 2 blocks) defs)) ++ "]") ++
+ ")") items))) ++ " ]"
+prettyBlock (Table caption aligns widths header rows) =
+ "Table " ++ show caption ++ " " ++ show aligns ++ " " ++
+ show widths ++ "\n" ++ prettyRow header ++ " [\n" ++
+ (intercalate ",\n" (map prettyRow rows)) ++ " ]"
+ where prettyRow cols = indentBy 2 0 ("[ " ++ (intercalate ", "
+ (map (\blocks -> prettyBlockList 2 blocks)
+ cols))) ++ " ]"
+prettyBlock block = show block
+
+-- | Prettyprint Pandoc document.
+writeNative :: WriterOptions -> Pandoc -> String
+writeNative _ (Pandoc meta blocks) = "Pandoc " ++ "(" ++ show meta ++
+ ")\n" ++ (prettyBlockList 0 blocks) ++ "\n"
+
diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs
new file mode 100644
index 000000000..5aa0fd310
--- /dev/null
+++ b/src/Text/Pandoc/Writers/ODT.hs
@@ -0,0 +1,83 @@
+{-
+Copyright (C) 2008-2010 John MacFarlane <jgm@berkeley.edu>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-}
+
+{- |
+ Module : Text.Pandoc.Writers.ODT
+ Copyright : Copyright (C) 2008-2010 John MacFarlane
+ License : GNU GPL, version 2 or above
+
+ Maintainer : John MacFarlane <jgm@berkeley.edu>
+ Stability : alpha
+ Portability : portable
+
+Conversion of 'Pandoc' documents to ODT.
+-}
+module Text.Pandoc.Writers.ODT ( writeODT ) where
+import Data.IORef
+import System.FilePath ( (</>), takeExtension )
+import qualified Data.ByteString.Lazy as B
+import Data.ByteString.Lazy.UTF8 ( fromString )
+import Codec.Archive.Zip
+import System.Time
+import Paths_pandoc ( getDataFileName )
+import Text.Pandoc.Shared ( WriterOptions(..) )
+import Text.Pandoc.Definition
+import Text.Pandoc.Writers.OpenDocument ( writeOpenDocument )
+import System.Directory
+import Control.Monad (liftM)
+
+-- | Produce an ODT file from a Pandoc document.
+writeODT :: Maybe FilePath -- ^ Path specified by --reference-odt
+ -> WriterOptions -- ^ Writer options
+ -> Pandoc -- ^ Document to convert
+ -> IO B.ByteString
+writeODT mbRefOdt opts doc = do
+ let datadir = writerUserDataDir opts
+ refArchive <- liftM toArchive $
+ case mbRefOdt of
+ Just f -> B.readFile f
+ Nothing -> do
+ let defaultODT = getDataFileName "reference.odt" >>= B.readFile
+ case datadir of
+ Nothing -> defaultODT
+ Just d -> do
+ exists <- doesFileExist (d </> "reference.odt")
+ if exists
+ then B.readFile (d </> "reference.odt")
+ else defaultODT
+ -- handle pictures
+ picEntriesRef <- newIORef ([] :: [Entry])
+ let sourceDir = writerSourceDirectory opts
+ doc' <- processWithM (transformPic sourceDir picEntriesRef) doc
+ let newContents = writeOpenDocument opts doc'
+ (TOD epochtime _) <- getClockTime
+ let contentEntry = toEntry "content.xml" epochtime $ fromString newContents
+ picEntries <- readIORef picEntriesRef
+ let archive = foldr addEntryToArchive refArchive (contentEntry : picEntries)
+ return $ fromArchive archive
+
+transformPic :: FilePath -> IORef [Entry] -> Inline -> IO Inline
+transformPic sourceDir entriesRef (Image lab (src,tit)) = do
+ 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))
+transformPic _ _ x = return x
+
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
index f4dfb2aa6..e79f97b33 100644
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -39,10 +39,12 @@ import Text.PrettyPrint.HughesPJ hiding ( Str )
import Control.Monad.State
import Control.Applicative ( (<$>) )
+type Refs = [([Inline], Target)]
+
data WriterState =
WriterState { stNotes :: [[Block]]
- , stLinks :: KeyTable
- , stImages :: KeyTable
+ , stLinks :: Refs
+ , stImages :: Refs
, stHasMath :: Bool
, stOptions :: WriterOptions
}
@@ -65,10 +67,10 @@ pandocToRST (Pandoc (Meta tit auth dat) blocks) = do
body <- blockListToRST blocks
notes <- liftM (reverse . stNotes) get >>= notesToRST
-- note that the notes may contain refs, so we do them first
- refs <- liftM (reverse . stLinks) get >>= keyTableToRST
- pics <- liftM (reverse . stImages) get >>= pictTableToRST
+ refs <- liftM (reverse . stLinks) get >>= refsToRST
+ pics <- liftM (reverse . stImages) get >>= pictRefsToRST
hasMath <- liftM stHasMath get
- let main = render $ body $+$ notes $+$ text "" $+$ refs $+$ pics
+ let main = render $ foldl ($+$) empty $ [body, notes, refs, pics]
let context = writerVariables opts ++
[ ("body", main)
, ("title", render title)
@@ -80,8 +82,8 @@ pandocToRST (Pandoc (Meta tit auth dat) blocks) = do
else return main
-- | Return RST representation of reference key table.
-keyTableToRST :: KeyTable -> State WriterState Doc
-keyTableToRST refs = mapM keyToRST refs >>= return . vcat
+refsToRST :: Refs -> State WriterState Doc
+refsToRST refs = mapM keyToRST refs >>= return . vcat
-- | Return RST representation of a reference key.
keyToRST :: ([Inline], (String, String))
@@ -107,8 +109,8 @@ noteToRST num note = do
return $ marker $$ nest 3 contents
-- | Return RST representation of picture reference table.
-pictTableToRST :: KeyTable -> State WriterState Doc
-pictTableToRST refs = mapM pictToRST refs >>= return . vcat
+pictRefsToRST :: Refs -> State WriterState Doc
+pictRefsToRST refs = mapM pictToRST refs >>= return . vcat
-- | Return RST representation of a picture substitution reference.
pictToRST :: ([Inline], (String, String))
@@ -280,16 +282,16 @@ inlineToRST (Subscript lst) = do
inlineToRST (SmallCaps lst) = inlineListToRST lst
inlineToRST (Quoted SingleQuote lst) = do
contents <- inlineListToRST lst
- return $ char '\'' <> contents <> char '\''
+ return $ char '‘' <> contents <> char '’'
inlineToRST (Quoted DoubleQuote lst) = do
contents <- inlineListToRST lst
- return $ char '"' <> contents <> char '"'
+ return $ char '“' <> contents <> char '”'
inlineToRST (Cite _ lst) =
inlineListToRST lst
-inlineToRST EmDash = return $ text "--"
-inlineToRST EnDash = return $ char '-'
-inlineToRST Apostrophe = return $ char '\''
-inlineToRST Ellipses = return $ text "..."
+inlineToRST EmDash = return $ char '\8212'
+inlineToRST EnDash = return $ char '\8211'
+inlineToRST Apostrophe = return $ char '\8217'
+inlineToRST Ellipses = return $ char '\8230'
inlineToRST (Code str) = return $ text $ "``" ++ str ++ "``"
inlineToRST (Str str) = return $ text $ escapeString str
inlineToRST (Math t str) = do
diff --git a/src/Text/Pandoc/Writers/S5.hs b/src/Text/Pandoc/Writers/S5.hs
deleted file mode 100644
index 1a2639a50..000000000
--- a/src/Text/Pandoc/Writers/S5.hs
+++ /dev/null
@@ -1,136 +0,0 @@
-{-
-Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.S5
- Copyright : Copyright (C) 2006-2010 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Definitions for creation of S5 powerpoint-like HTML.
-(See <http://meyerweb.com/eric/tools/s5/>.)
--}
-module Text.Pandoc.Writers.S5 (
- -- * Header includes
- s5HeaderIncludes,
- s5Links,
- -- * Functions
- writeS5,
- writeS5String,
- insertS5Structure
- ) where
-import Text.Pandoc.Shared ( WriterOptions, readDataFile )
-import Text.Pandoc.Writers.HTML ( writeHtml, writeHtmlString )
-import Text.Pandoc.Definition
-import Text.XHtml.Strict
-import System.FilePath ( (</>) )
-import Data.List ( intercalate )
-
-s5HeaderIncludes :: Maybe FilePath -> IO String
-s5HeaderIncludes datadir = do
- c <- s5CSS datadir
- j <- s5Javascript datadir
- return $ s5Meta ++ c ++ j
-
-s5Meta :: String
-s5Meta = "<!-- configuration parameters -->\n<meta name=\"defaultView\" content=\"slideshow\" />\n<meta name=\"controlVis\" content=\"hidden\" />\n"
-
-s5Javascript :: Maybe FilePath -> IO String
-s5Javascript datadir = do
- jsCom <- readDataFile datadir $ "s5" </> "default" </> "slides.js.comment"
- jsPacked <- readDataFile datadir $ "s5" </> "default" </> "slides.js.packed"
- return $ "<script type=\"text/javascript\">\n" ++ jsCom ++ jsPacked ++
- "</script>\n"
-
-s5CSS :: Maybe FilePath -> IO String
-s5CSS datadir = do
- s5CoreCSS <- readDataFile datadir $ "s5" </> "default" </> "s5-core.css"
- s5FramingCSS <- readDataFile datadir $ "s5" </> "default" </> "framing.css"
- s5PrettyCSS <- readDataFile datadir $ "s5" </> "default" </> "pretty.css"
- s5OperaCSS <- readDataFile datadir $ "s5" </> "default" </> "opera.css"
- s5OutlineCSS <- readDataFile datadir $ "s5" </> "default" </> "outline.css"
- s5PrintCSS <- readDataFile datadir $ "s5" </> "default" </> "print.css"
- return $ "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"
-
-s5Links :: String
-s5Links = "<!-- style sheet links -->\n<link rel=\"stylesheet\" href=\"ui/default/slides.css\" type=\"text/css\" media=\"projection\" id=\"slideProj\" />\n<link rel=\"stylesheet\" href=\"ui/default/outline.css\" type=\"text/css\" media=\"screen\" id=\"outlineStyle\" />\n<link rel=\"stylesheet\" href=\"ui/default/print.css\" type=\"text/css\" media=\"print\" id=\"slidePrint\" />\n<link rel=\"stylesheet\" href=\"ui/default/opera.css\" type=\"text/css\" media=\"projection\" id=\"operaFix\" />\n<!-- S5 JS -->\n<script src=\"ui/default/slides.js\" type=\"text/javascript\"></script>\n"
-
--- | Converts Pandoc document to an S5 HTML presentation (Html structure).
-writeS5 :: WriterOptions -> Pandoc -> Html
-writeS5 options = (writeHtml options) . insertS5Structure
-
--- | Converts Pandoc document to an S5 HTML presentation (string).
-writeS5String :: WriterOptions -> Pandoc -> String
-writeS5String options = (writeHtmlString options) . insertS5Structure
-
--- | Inserts HTML needed for an S5 presentation (e.g. around slides).
-layoutDiv :: [Inline] -- ^ Title of document (for header or footer)
- -> [Inline] -- ^ Date of document (for header or footer)
- -> [Block] -- ^ List of block elements returned
-layoutDiv title' date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 date), (Header 2 title'), (RawHtml "</div>\n</div>\n")]
-
-presentationStart :: Block
-presentationStart = RawHtml "<div class=\"presentation\">\n\n"
-
-presentationEnd :: Block
-presentationEnd = RawHtml "</div>\n"
-
-slideStart :: Block
-slideStart = RawHtml "<div class=\"slide\">\n"
-
-slideEnd :: Block
-slideEnd = RawHtml "</div>\n"
-
--- | Returns 'True' if block is a Header 1.
-isH1 :: Block -> Bool
-isH1 (Header 1 _) = True
-isH1 _ = False
-
--- | Insert HTML around sections to make individual slides.
-insertSlides :: Bool -> [Block] -> [Block]
-insertSlides beginning blocks =
- let (beforeHead, rest) = break isH1 blocks in
- if (null rest) then
- if beginning then
- beforeHead
- else
- beforeHead ++ [slideEnd]
- else
- if beginning then
- beforeHead ++
- slideStart:(head rest):(insertSlides False (tail rest))
- else
- beforeHead ++
- slideEnd:slideStart:(head rest):(insertSlides False (tail rest))
-
--- | Insert blocks into 'Pandoc' for slide structure.
-insertS5Structure :: Pandoc -> Pandoc
-insertS5Structure (Pandoc meta' []) = Pandoc meta' []
-insertS5Structure (Pandoc (Meta title' authors date) blocks) =
- let slides = insertSlides True blocks
- firstSlide = if not (null title')
- then [slideStart, (Header 1 title'),
- (Header 3 (intercalate [LineBreak] authors)),
- (Header 4 date), slideEnd]
- else []
- newBlocks = (layoutDiv title' date) ++ presentationStart:firstSlide ++
- slides ++ [presentationEnd]
- in Pandoc (Meta title' authors date) newBlocks
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
index 503222754..65e053827 100644
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -144,6 +144,7 @@ blockToTexinfo (OrderedList (start, numstyle, _) lst) = do
exemplar = case numstyle of
DefaultStyle -> decimal
Decimal -> decimal
+ Example -> decimal
UpperRoman -> decimal -- Roman numerals not supported
LowerRoman -> decimal
UpperAlpha -> upperAlpha
diff --git a/src/markdown2pdf.hs b/src/markdown2pdf.hs
index d713ae263..cc6a034c0 100644
--- a/src/markdown2pdf.hs
+++ b/src/markdown2pdf.hs
@@ -9,14 +9,7 @@ import Control.Exception (tryJust, bracket)
import System.IO (stderr)
import System.IO.Error (isDoesNotExistError)
import System.Environment ( getArgs, getProgName )
--- Note: ghc >= 6.12 (base >=4.2) supports unicode through iconv
--- So we use System.IO.UTF8 only if we have an earlier version
-#if MIN_VERSION_base(4,2,0)
-import System.IO (hPutStrLn)
-#else
-import Prelude hiding ( putStr, putStrLn, writeFile, readFile, getContents )
-import System.IO.UTF8
-#endif
+import qualified Text.Pandoc.UTF8 as UTF8
import System.Exit (ExitCode (..), exitWith)
import System.FilePath
import System.Directory
@@ -57,7 +50,7 @@ runLatexRaw latexProgram file = do
takeDirectory file, dropExtension file] >> return ()
let pdfFile = replaceExtension file "pdf"
let logFile = replaceExtension file "log"
- txt <- tryJust (guard . isDoesNotExistError) (readFile logFile)
+ txt <- tryJust (guard . isDoesNotExistError) (UTF8.readFile logFile)
let checks = checkLatex $ either (const "") id txt
case checks of
-- err , bib , ref , msg
@@ -122,13 +115,13 @@ runBibtex file = do
exit :: String -> IO a
exit x = do
progName <- getProgName
- hPutStrLn stderr $ progName ++ ": " ++ x
+ UTF8.hPutStrLn stderr $ progName ++ ": " ++ x
exitWith $ ExitFailure 1
saveStdin :: FilePath -> IO (Either String FilePath)
saveStdin file = do
- text <- getContents
- writeFile file text
+ text <- UTF8.getContents
+ UTF8.writeFile file text
fileExist <- doesFileExist file
case fileExist of
False -> return $ Left $! "Could not create " ++ file
@@ -137,7 +130,7 @@ saveStdin file = do
saveOutput :: FilePath -> FilePath -> IO ()
saveOutput input output = do
copyFile input output
- hPutStrLn stderr $! "Created " ++ output
+ UTF8.hPutStrLn stderr $! "Created " ++ output
main :: IO ()
main = bracket
@@ -161,7 +154,8 @@ main = bracket
"--number-sections","--include-in-header",
"--include-before-body","--include-after-body",
"--custom-header","--output",
- "--template", "--variable"]
+ "--template", "--variable",
+ "--csl", "--biblio", "--biblio-format"]
let isOpt ('-':_) = True
isOpt _ = False
let opts = filter isOpt args
@@ -170,8 +164,8 @@ main = bracket
any (\o -> (o ++ "=") `isPrefixOf` x) goodoptslong
unless (all isGoodopt opts) $ do
(code, out, _err) <- readProcessWithExitCode "pandoc" ["--help"] ""
- putStrLn "markdown2pdf [OPTIONS] [FILES]\nOptions:"
- putStr $ unlines $
+ UTF8.putStrLn "markdown2pdf [OPTIONS] [FILES]\nOptions:"
+ UTF8.putStr $ unlines $
filter (\l -> any (`isInfixOf` l) goodoptslong) $ lines out
exitWith code
diff --git a/src/pandoc.hs b/src/pandoc.hs
index 0560efc0a..ef38c0332 100644
--- a/src/pandoc.hs
+++ b/src/pandoc.hs
@@ -30,9 +30,9 @@ writers.
-}
module Main where
import Text.Pandoc
-import Text.Pandoc.ODT
-import Text.Pandoc.Writers.S5 (s5HeaderIncludes)
-import Text.Pandoc.Shared ( tabFilter, ObfuscationMethod (..), readDataFile )
+import Text.Pandoc.S5 (s5HeaderIncludes)
+import Text.Pandoc.Shared ( tabFilter, ObfuscationMethod (..), readDataFile,
+ headerShift )
#ifdef _HIGHLIGHTING
import Text.Pandoc.Highlighting ( languages )
#endif
@@ -40,19 +40,11 @@ import System.Environment ( getArgs, getProgName, getEnvironment )
import System.Exit ( exitWith, ExitCode (..) )
import System.FilePath
import System.Console.GetOpt
-import Data.Maybe ( fromMaybe )
import Data.Char ( toLower, isDigit )
import Data.List ( intercalate, isSuffixOf )
import System.Directory ( getAppUserDataDirectory )
import System.IO ( stdout, stderr )
--- Note: ghc >= 6.12 (base >=4.2) supports unicode through iconv
--- So we use System.IO.UTF8 only if we have an earlier version
-#if MIN_VERSION_base(4,2,0)
-import System.IO ( hPutStr, hPutStrLn )
-#else
-import Prelude hiding ( putStr, putStrLn, writeFile, readFile, getContents )
-import System.IO.UTF8
-#endif
+import qualified Text.Pandoc.UTF8 as UTF8
#ifdef _CITEPROC
import Text.CSL
import Text.Pandoc.Biblio
@@ -60,7 +52,9 @@ import Text.Pandoc.Biblio
import Control.Monad (when, unless, liftM)
import Network.HTTP (simpleHTTP, mkRequest, getResponseBody, RequestMethod(..))
import Network.URI (parseURI, isURI)
-import Data.ByteString.Lazy.UTF8 (toString)
+import qualified Data.ByteString.Lazy as B
+import Data.ByteString.Lazy.UTF8 (toString, fromString)
+import Codec.Binary.UTF8.String (decodeString)
copyrightMessage :: String
copyrightMessage = "\nCopyright (C) 2006-2010 John MacFarlane\n" ++
@@ -108,13 +102,15 @@ readPandoc _ = read
-- | Association list of formats and writers.
writers :: [ ( String, WriterOptions -> Pandoc -> String ) ]
-writers = [("native" , writeDoc)
+writers = [("native" , writeNative)
,("html" , writeHtmlString)
,("html+lhs" , writeHtmlString)
- ,("s5" , writeS5String)
+ ,("s5" , writeHtmlString)
+ ,("slidy" , writeHtmlString)
,("docbook" , writeDocbook)
,("opendocument" , writeOpenDocument)
- ,("odt" , writeOpenDocument)
+ ,("odt" , \_ _ -> "")
+ ,("epub" , \_ _ -> "")
,("latex" , writeLaTeX)
,("latex+lhs" , writeLaTeX)
,("context" , writeConTeXt)
@@ -130,17 +126,7 @@ writers = [("native" , writeDoc)
]
isNonTextOutput :: String -> Bool
-isNonTextOutput = (`elem` ["odt"])
-
--- | Writer for Pandoc native format.
-writeDoc :: WriterOptions -> Pandoc -> String
-writeDoc _ = prettyPandoc
-
-headerShift :: Int -> Pandoc -> Pandoc
-headerShift n = processWith shift
- where shift :: Block -> Block
- shift (Header level inner) = Header (level + n) inner
- shift x = x
+isNonTextOutput = (`elem` ["odt","epub"])
-- | Data structure for command line options.
data Opt = Opt
@@ -154,15 +140,17 @@ data Opt = Opt
, optTransforms :: [Pandoc -> Pandoc] -- ^ Doc transforms to apply
, optTemplate :: String -- ^ Custom template
, optVariables :: [(String,String)] -- ^ Template variables to set
- , optBefore :: [String] -- ^ Texts to include before body
- , optAfter :: [String] -- ^ Texts to include after body
, optOutputFile :: String -- ^ Name of output file
, optNumberSections :: Bool -- ^ Number sections in LaTeX
- , optIncremental :: Bool -- ^ Use incremental lists in S5
+ , optSectionDivs :: Bool -- ^ Put sections in div tags in HTML
+ , optIncremental :: Bool -- ^ Use incremental lists in Slidy/S5
+ , optOffline :: Bool -- ^ Make slideshow accessible offline
, optXeTeX :: Bool -- ^ Format latex for xetex
, optSmart :: Bool -- ^ Use smart typography
, optHTMLMathMethod :: HTMLMathMethod -- ^ Method to print HTML math
, optReferenceODT :: Maybe FilePath -- ^ Path of reference.odt
+ , optEPUBStylesheet :: Maybe String -- ^ EPUB stylesheet
+ , optEPUBMetadata :: String -- ^ EPUB metadata
, optDumpArgs :: Bool -- ^ Output command-line arguments
, optIgnoreArgs :: Bool -- ^ Ignore command-line arguments
, optStrict :: Bool -- ^ Use strict markdown syntax
@@ -194,15 +182,17 @@ defaultOpts = Opt
, optTransforms = []
, optTemplate = ""
, optVariables = []
- , optBefore = []
- , optAfter = []
, optOutputFile = "-" -- "-" means stdout
, optNumberSections = False
+ , optSectionDivs = False
, optIncremental = False
+ , optOffline = False
, optXeTeX = False
, optSmart = False
, optHTMLMathMethod = PlainMath
, optReferenceODT = Nothing
+ , optEPUBStylesheet = Nothing
+ , optEPUBMetadata = ""
, optDumpArgs = False
, optIgnoreArgs = False
, optStrict = False
@@ -295,11 +285,24 @@ options =
, Option "" ["mimetex"]
(OptArg
- (\arg opt -> return opt { optHTMLMathMethod = MimeTeX
- (fromMaybe "/cgi-bin/mimetex.cgi" arg)})
+ (\arg opt -> do
+ let url' = case arg of
+ Just u -> u ++ "?"
+ Nothing -> "/cgi-bin/mimetex.cgi?"
+ return opt { optHTMLMathMethod = WebTeX url' })
"URL")
"" -- "Use mimetex for HTML math"
+ , Option "" ["webtex"]
+ (OptArg
+ (\arg opt -> do
+ let url' = case arg of
+ Just u -> u
+ Nothing -> "http://chart.apis.google.com/chart?cht=tx&chl="
+ return opt { optHTMLMathMethod = WebTeX url' })
+ "URL")
+ "" -- "Use web service for HTML math"
+
, Option "" ["jsmath"]
(OptArg
(\arg opt -> return opt { optHTMLMathMethod = JsMath arg})
@@ -314,7 +317,13 @@ options =
, Option "i" ["incremental"]
(NoArg
(\opt -> return opt { optIncremental = True }))
- "" -- "Make list items display incrementally in S5"
+ "" -- "Make list items display incrementally in Slidy/S5"
+
+ , Option "" ["offline"]
+ (NoArg
+ (\opt -> return opt { optOffline = True,
+ optStandalone = True }))
+ "" -- "Make slide shows include all the needed js and css"
, Option "" ["xetex"]
(NoArg
@@ -326,6 +335,11 @@ options =
(\opt -> return opt { optNumberSections = True }))
"" -- "Number sections in LaTeX"
+ , Option "" ["section-divs"]
+ (NoArg
+ (\opt -> return opt { optSectionDivs = True }))
+ "" -- "Put sections in div tags in HTML"
+
, Option "" ["no-wrap"]
(NoArg
(\opt -> return opt { optWrapText = False }))
@@ -343,7 +357,7 @@ options =
"references" -> return ReferenceObfuscation
"javascript" -> return JavascriptObfuscation
"none" -> return NoObfuscation
- _ -> hPutStrLn stderr ("Error: Unknown obfuscation method: " ++ arg) >>
+ _ -> UTF8.hPutStrLn stderr ("Error: Unknown obfuscation method: " ++ arg) >>
exitWith (ExitFailure 6)
return opt { optEmailObfuscation = method })
"none|javascript|references")
@@ -377,7 +391,7 @@ options =
return opt{ optTransforms =
headerShift shift : oldTransforms }
else do
- hPutStrLn stderr $ "base-header-level must be a number >= 1"
+ UTF8.hPutStrLn stderr $ "base-header-level must be a number >= 1"
exitWith $ ExitFailure 19)
"LEVEL")
"" -- "Headers base level"
@@ -385,7 +399,7 @@ options =
, Option "" ["template"]
(ReqArg
(\arg opt -> do
- text <- readFile arg
+ text <- UTF8.readFile arg
return opt{ optTemplate = text,
optStandalone = True })
"FILENAME")
@@ -399,7 +413,7 @@ options =
let newvars = optVariables opt ++ [(k,v)]
return opt{ optVariables = newvars }
_ -> do
- hPutStrLn stderr $ "Could not parse `" ++ arg ++ "' as a key/value pair (k=v or k:v)"
+ UTF8.hPutStrLn stderr $ "Could not parse `" ++ arg ++ "' as a key/value pair (k=v or k:v)"
exitWith $ ExitFailure 17)
"FILENAME")
"" -- "Use custom template"
@@ -417,7 +431,7 @@ options =
, Option "H" ["include-in-header"]
(ReqArg
(\arg opt -> do
- text <- readFile arg
+ text <- UTF8.readFile arg
-- add new ones to end, so they're included in order specified
let newvars = optVariables opt ++ [("header-includes",text)]
return opt { optVariables = newvars,
@@ -428,7 +442,7 @@ options =
, Option "B" ["include-before-body"]
(ReqArg
(\arg opt -> do
- text <- readFile arg
+ text <- UTF8.readFile arg
-- add new ones to end, so they're included in order specified
let newvars = optVariables opt ++ [("include-before",text)]
return opt { optVariables = newvars,
@@ -439,7 +453,7 @@ options =
, Option "A" ["include-after-body"]
(ReqArg
(\arg opt -> do
- text <- readFile arg
+ text <- UTF8.readFile arg
-- add new ones to end, so they're included in order specified
let newvars = optVariables opt ++ [("include-after",text)]
return opt { optVariables = newvars,
@@ -450,7 +464,7 @@ options =
, Option "C" ["custom-header"]
(ReqArg
(\arg opt -> do
- text <- readFile arg
+ text <- UTF8.readFile arg
let newVars = ("legacy-header", text) : optVariables opt
return opt { optVariables = newVars
, optStandalone = True })
@@ -473,12 +487,28 @@ options =
"FILENAME")
"" -- "Path of custom reference.odt"
+ , Option "" ["epub-stylesheet"]
+ (ReqArg
+ (\arg opt -> do
+ text <- UTF8.readFile arg
+ return opt { optEPUBStylesheet = Just text })
+ "FILENAME")
+ "" -- "Path of epub.css"
+
+ , Option "" ["epub-metadata"]
+ (ReqArg
+ (\arg opt -> do
+ text <- UTF8.readFile arg
+ return opt { optEPUBMetadata = text })
+ "FILENAME")
+ "" -- "Path of epub metadata file"
+
, Option "D" ["print-default-template"]
(ReqArg
(\arg _ -> do
templ <- getDefaultTemplate Nothing arg
case templ of
- Right t -> hPutStr stdout t
+ Right t -> UTF8.hPutStr stdout t
Left e -> error $ show e
exitWith ExitSuccess)
"FORMAT")
@@ -520,7 +550,7 @@ options =
(NoArg
(\_ -> do
prg <- getProgName
- hPutStrLn stdout (prg ++ " " ++ pandocVersion ++ compileInfo ++
+ UTF8.hPutStrLn stdout (prg ++ " " ++ pandocVersion ++ compileInfo ++
copyrightMessage)
exitWith ExitSuccess ))
"" -- "Print version"
@@ -529,7 +559,7 @@ options =
(NoArg
(\_ -> do
prg <- getProgName
- hPutStr stdout (usageMessage prg options)
+ UTF8.hPutStr stdout (usageMessage prg options)
exitWith ExitSuccess ))
"" -- "Show help"
]
@@ -586,13 +616,14 @@ defaultWriterName x =
".texinfo" -> "texinfo"
".db" -> "docbook"
".odt" -> "odt"
+ ".epub" -> "epub"
['.',y] | y `elem` ['1'..'9'] -> "man"
_ -> "html"
main :: IO ()
main = do
- rawArgs <- getArgs
+ rawArgs <- liftM (map decodeString) getArgs
prg <- getProgName
let compatMode = (prg == "hsmarkdown")
@@ -602,8 +633,8 @@ main = do
unless (null errors) $
do name <- getProgName
- mapM_ (\e -> hPutStr stderr (name ++ ": ") >> hPutStr stderr e) errors
- hPutStrLn stderr $ "Try " ++ name ++ " --help for more information."
+ mapM_ (\e -> UTF8.hPutStr stderr (name ++ ": ") >> UTF8.hPutStr stderr e) errors
+ UTF8.hPutStrLn stderr $ "Try " ++ name ++ " --help for more information."
exitWith $ ExitFailure 2
let defaultOpts' = if compatMode
@@ -622,18 +653,20 @@ main = do
, optWriter = writerName
, optParseRaw = parseRaw
, optVariables = variables
- , optBefore = befores
- , optAfter = afters
, optTableOfContents = toc
, optTransforms = transforms
, optTemplate = template
, optOutputFile = outputFile
, optNumberSections = numberSections
+ , optSectionDivs = sectionDivs
, optIncremental = incremental
+ , optOffline = offline
, optXeTeX = xetex
, optSmart = smart
, optHTMLMathMethod = mathMethod
, optReferenceODT = referenceODT
+ , optEPUBStylesheet = epubStylesheet
+ , optEPUBMetadata = epubMetadata
, optDumpArgs = dumpArgs
, optIgnoreArgs = ignoreArgs
, optStrict = strict
@@ -652,13 +685,13 @@ main = do
} = opts
when dumpArgs $
- do hPutStrLn stdout outputFile
- mapM_ (\arg -> hPutStrLn stdout arg) args
+ do UTF8.hPutStrLn stdout outputFile
+ mapM_ (\arg -> UTF8.hPutStrLn stdout arg) args
exitWith ExitSuccess
-- warn about deprecated options
case lookup "legacy-header" variables of
- Just _ -> hPutStrLn stderr $
+ Just _ -> UTF8.hPutStrLn stderr $
"Warning: The -C/--custom-header is deprecated.\n" ++
"Please transition to using --template instead."
Nothing -> return ()
@@ -687,9 +720,13 @@ main = do
Just r -> return r
Nothing -> error ("Unknown reader: " ++ readerName')
- writer <- case (lookup writerName' writers) of
- Just r -> return r
- Nothing -> error ("Unknown writer: " ++ writerName')
+ let writer = case lookup writerName' writers of
+ Just _ | writerName' == "epub" -> writeEPUB epubStylesheet
+ Just _ | writerName' == "odt" -> writeODT referenceODT
+ Just r -> \o ->
+ return . fromString . r o
+ Nothing -> error $ "Unknown writer: " ++
+ writerName'
templ <- getDefaultTemplate datadir writerName'
let defaultTemplate = case templ of
@@ -707,11 +744,18 @@ main = do
refs <- if null biblioFile then return [] else readBiblioFile biblioFile biblioFormat
#endif
- variables' <- if writerName' == "s5" && standalone'
- then do
- inc <- s5HeaderIncludes datadir
- return $ ("header-includes", inc) : variables
- else return variables
+ variables' <- case (writerName', standalone', offline) of
+ ("s5", True, True) -> do
+ inc <- s5HeaderIncludes datadir
+ return $ ("s5includes", inc) : variables
+ ("slidy", True, True) -> do
+ slidyJs <- readDataFile datadir $
+ "slidy" </> "slidy.min.js"
+ slidyCss <- readDataFile datadir $
+ "slidy" </> "slidy.min.css"
+ return $ ("slidy-js", slidyJs) :
+ ("slidy-css", slidyCss) : variables
+ _ -> return variables
variables'' <- case mathMethod of
LaTeXMathML Nothing -> do
@@ -722,6 +766,15 @@ main = do
return $ ("mathml-script", s) : variables'
_ -> return variables'
+ let sourceDir = if null sources
+ then "."
+ else takeDirectory (head sources)
+
+ let slideVariant = case writerName' of
+ "s5" -> S5Slides
+ "slidy" -> SlidySlides
+ _ -> NoSlides
+
let startParserState =
defaultParserState { stateParseRaw = parseRaw,
stateTabStop = tabStop,
@@ -737,22 +790,23 @@ main = do
stateColumns = columns,
stateStrict = strict,
stateIndentedCodeClasses = codeBlockClasses }
+
let writerOptions = WriterOptions { writerStandalone = standalone',
writerTemplate = if null template
then defaultTemplate
else template,
writerVariables = variables'',
- writerIncludeBefore = concat befores,
- writerIncludeAfter = concat afters,
+ writerEPUBMetadata = epubMetadata,
writerTabStop = tabStop,
writerTableOfContents = toc &&
writerName' /= "s5",
writerHTMLMathMethod = mathMethod,
- writerS5 = (writerName' == "s5"),
+ writerSlideVariant = slideVariant,
+ writerIncremental = incremental,
writerXeTeX = xetex,
writerIgnoreNotes = False,
- writerIncremental = incremental,
writerNumberSections = numberSections,
+ writerSectionDivs = sectionDivs,
writerStrictMarkdown = strict,
writerReferenceLinks = referenceLinks,
writerWrapText = wrap,
@@ -761,23 +815,21 @@ main = do
writerEmailObfuscation = if strict
then ReferenceObfuscation
else obfuscationMethod,
- writerIdentifierPrefix = idPrefix }
+ writerIdentifierPrefix = idPrefix,
+ writerSourceDirectory = sourceDir,
+ writerUserDataDir = datadir }
when (isNonTextOutput writerName' && outputFile == "-") $
- do hPutStrLn stderr ("Error: Cannot write " ++ writerName ++ " output to stdout.\n" ++
+ do UTF8.hPutStrLn stderr ("Error: Cannot write " ++ writerName ++ " output to stdout.\n" ++
"Specify an output file using the -o option.")
exitWith $ ExitFailure 5
- let sourceDirRelative = if null sources
- then ""
- else takeDirectory (head sources)
-
let readSources [] = mapM readSource ["-"]
readSources srcs = mapM readSource srcs
- readSource "-" = getContents
+ readSource "-" = UTF8.getContents
readSource src = case parseURI src of
Just u -> readURI u
- Nothing -> readFile src
+ Nothing -> UTF8.readFile src
readURI uri = simpleHTTP (mkRequest GET uri) >>= getResponseBody >>=
return . toString -- treat all as UTF8
@@ -794,10 +846,8 @@ main = do
return doc'
#endif
- let writerOutput = writer writerOptions doc'' ++ "\n"
+ writerOutput <- writer writerOptions doc''
- case writerName' of
- "odt" -> saveOpenDocumentAsODT datadir outputFile sourceDirRelative referenceODT writerOutput
- _ -> if outputFile == "-"
- then putStr writerOutput
- else writeFile outputFile writerOutput
+ if outputFile == "-"
+ then B.putStr writerOutput
+ else B.writeFile outputFile writerOutput
diff --git a/templates/docbook.template b/templates/docbook.template
index 374a8fbf2..cd9ec59ca 100644
--- a/templates/docbook.template
+++ b/templates/docbook.template
@@ -25,4 +25,3 @@ $for(include-after)$
$include-after$
$endfor$
</article>
-
diff --git a/templates/html.template b/templates/html.template
index 820279939..bd1864ff0 100644
--- a/templates/html.template
+++ b/templates/html.template
@@ -7,27 +7,12 @@
$for(author)$
<meta name="author" content="$author$" />
$endfor$
+$if(date)$
<meta name="date" content="$date$" />
-$if(highlighting)$
+$endif$
+$if(highlighting-css)$
<style type="text/css">
- table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
- td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
- td.sourceCode { padding-left: 5px; }
- pre.sourceCode { }
- pre.sourceCode span.Normal { }
- pre.sourceCode span.Keyword { color: #007020; font-weight: bold; }
- pre.sourceCode span.DataType { color: #902000; }
- pre.sourceCode span.DecVal { color: #40a070; }
- pre.sourceCode span.BaseN { color: #40a070; }
- pre.sourceCode span.Float { color: #40a070; }
- pre.sourceCode span.Char { color: #4070a0; }
- pre.sourceCode span.String { color: #4070a0; }
- pre.sourceCode span.Comment { color: #60a0b0; font-style: italic; }
- pre.sourceCode span.Others { color: #007020; }
- pre.sourceCode span.Alert { color: red; font-weight: bold; }
- pre.sourceCode span.Function { color: #06287e; }
- pre.sourceCode span.RegionMarker { }
- pre.sourceCode span.Error { color: red; font-weight: bold; }
+$highlighting-css$
</style>
$endif$
$for(css)$
@@ -41,12 +26,12 @@ $for(header-includes)$
$endfor$
</head>
<body>
-$if(title)$
-<h1 class="title">$title$</h1>
-$endif$
$for(include-before)$
$include-before$
$endfor$
+$if(title)$
+<h1 class="title">$title$</h1>
+$endif$
$if(toc)$
$toc$
$endif$
diff --git a/templates/latex.template b/templates/latex.template
index 02e570a76..4eb92e2c1 100644
--- a/templates/latex.template
+++ b/templates/latex.template
@@ -2,7 +2,7 @@ $if(legacy-header)$
$legacy-header$
$else$
\documentclass{article}
-\usepackage{amsmath}
+\usepackage{amssymb,amsmath}
$if(xetex)$
\usepackage{ifxetex}
\ifxetex
@@ -50,6 +50,15 @@ $if(url)$
$endif$
$if(graphics)$
\usepackage{graphicx}
+% We will generate all images so they have a width \maxwidth. This means
+% that they will get their normal width if they fit onto the page, but
+% are scaled down if they would overflow the margins.
+\makeatletter
+\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth
+\else\Gin@nat@width\fi}
+\makeatother
+\let\Oldincludegraphics\includegraphics
+\renewcommand{\includegraphics}[1]{\Oldincludegraphics[width=\maxwidth]{#1}}
$endif$
\usepackage[breaklinks=true,unicode=true]{hyperref}
\setlength{\parindent}{0pt}
diff --git a/templates/s5.template b/templates/s5.template
new file mode 100644
index 000000000..480c1e435
--- /dev/null
+++ b/templates/s5.template
@@ -0,0 +1,69 @@
+<!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>
+ <title>$if(title-prefix)$$title-prefix$ - $endif$$if(pagetitle)$$pagetitle$$endif$</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="generator" content="pandoc" />
+$for(author)$
+ <meta name="author" content="$author$" />
+$endfor$
+$if(date)$
+ <meta name="date" content="$date$" />
+$endif$
+ <!-- configuration parameters -->
+ <meta name="defaultView" content="slideshow" />
+ <meta name="controlVis" content="hidden" />
+$if(highlighting-css)$
+ <style type="text/css">
+$highlighting-css$
+ </style>
+$endif$
+$for(css)$
+ <link rel="stylesheet" href="$css$" type="text/css" />
+$endfor$
+$if(s5includes)$
+$s5includes$
+$else$
+ <!-- style sheet links -->
+ <link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
+ <link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
+ <link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
+ <link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
+ <!-- S5 JS -->
+ <script src="ui/default/slides.js" type="text/javascript"></script>
+$endif$
+$if(math)$
+ $math$
+$endif$
+$for(header-includes)$
+ $header-includes$
+$endfor$
+</head>
+<body>
+$for(include-before)$
+$include-before$
+$endfor$
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header"></div>
+<div id="footer">
+ <h1>$date$</h1>
+ <h2>$title$</h2>
+</div>
+</div>
+<div class="presentation">
+$if(title)$
+<div class="slide">
+ <h1>$title$</h1>
+ <h3>$for(author)$$author$$sep$<br/>$endfor$</h3>
+ <h4>$date$</h4>
+</div>
+$endif$
+$body$
+$for(include-after)$
+$include-after$
+$endfor$
+</div>
+</body>
+</html>
diff --git a/templates/slidy.template b/templates/slidy.template
new file mode 100644
index 000000000..f625c36e2
--- /dev/null
+++ b/templates/slidy.template
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <title>$if(title-prefix)$$title-prefix$ - $endif$$if(pagetitle)$$pagetitle$$endif$</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="generator" content="pandoc" />
+$for(author)$
+ <meta name="author" content="$author$" />
+$endfor$
+$if(date)$
+ <meta name="date" content="$date$" />
+$endif$
+$if(highlighting-css)$
+ <style type="text/css">
+$highlighting-css$
+ </style>
+$endif$
+$for(css)$
+ <link rel="stylesheet" href="$css$" type="text/css" />
+$endfor$
+$if(slidy-css)$
+ <style type="text/css">
+$slidy-css$
+ </style>
+$else$
+ <link rel="stylesheet" type="text/css" media="screen, projection, print"
+ href="http://www.w3.org/Talks/Tools/Slidy/slidy.css" />
+$endif$
+$if(math)$
+ $math$
+$endif$
+$for(header-includes)$
+ $header-includes$
+$endfor$
+$if(slidy-js)$
+ <script type="text/javascript" charset="utf-8">
+$slidy-js$
+ </script>
+$else$
+ <script src="http://www.w3.org/Talks/Tools/Slidy/slidy.js.gz"
+ charset="utf-8" type="text/javascript"></script>
+$endif$
+</head>
+<body>
+$for(include-before)$
+$include-before$
+$endfor$
+$if(title)$
+<div class="slide cover title">
+ <h1 class="title">$title$</h1>
+ <p class="author">
+$for(author)$$author$$sep$<br/>$endfor$
+ </p>
+$if(date)$
+ <p class="date">$date$</p>
+$endif$
+</div>
+$endif$
+$body$
+$for(include-after)$
+$include-after$
+$endfor$
+</body>
+</html>
diff --git a/tests/RunTests.hs b/tests/RunTests.hs
index 0b5555ed1..1715400fd 100644
--- a/tests/RunTests.hs
+++ b/tests/RunTests.hs
@@ -13,9 +13,7 @@
-- cabal install Diff
module Main where
-import System.IO.UTF8
import System.IO ( openTempFile, stderr, stdout, hFlush )
-import Prelude hiding ( putStrLn, putStr, readFile )
import System.Process ( runProcess, waitForProcess )
import System.FilePath ( (</>), (<.>) )
import System.Directory
@@ -23,6 +21,12 @@ import System.Environment
import System.Exit
import Text.Printf
import Data.Algorithm.Diff
+import Prelude hiding ( readFile )
+import qualified Data.ByteString.Lazy as B
+import Data.ByteString.Lazy.UTF8 (toString, fromString)
+
+readFileUTF8 :: FilePath -> IO String
+readFileUTF8 f = B.readFile f >>= return . toString
pandocPath :: FilePath
pandocPath = ".." </> "dist" </> "build" </> "pandoc" </> "pandoc"
@@ -127,7 +131,7 @@ main = do
-- makes sure file is fully closed after reading
readFile' :: FilePath -> IO String
-readFile' f = do s <- readFile f
+readFile' f = do s <- readFileUTF8 f
return $! (length s `seq` s)
runLhsWriterTest :: String -> IO Bool
@@ -161,8 +165,7 @@ runTest testname opts inp norm = do
let normPath = norm
hFlush stdout
-- Note: COLUMNS must be set for markdown table reader
- -- and we need LANG set for ghc 6.12
- ph <- runProcess pandocPath (opts ++ [inpPath] ++ ["--data-dir", ".."]) Nothing (Just [("COLUMNS", "80"),("LANG","en_US.UTF-8")]) Nothing (Just hOut) (Just stderr)
+ ph <- runProcess pandocPath (opts ++ [inpPath] ++ ["--data-dir", ".."]) Nothing (Just [("COLUMNS", "80")]) Nothing (Just hOut) (Just stderr)
ec <- waitForProcess ph
result <- if ec == ExitSuccess
then do
@@ -174,5 +177,5 @@ runTest testname opts inp norm = do
else return $ TestFailed $ getDiff (lines outputContents) (lines normContents)
else return $ TestError ec
removeFile outputPath
- putStrLn (show result)
+ B.putStrLn (fromString $ show result)
return (result == TestPassed)
diff --git a/tests/html-reader.native b/tests/html-reader.native
index 5eb74768c..ee419d3ac 100644
--- a/tests/html-reader.native
+++ b/tests/html-reader.native
@@ -344,4 +344,3 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
, Para [Str "Caret",Space,Str "characters",Space,Str "are",Space,Str "used",Space,Str "to",Space,Str "indicate",Space,Str "that",Space,Str "the",Space,Str "blocks",Space,Str "all",Space,Str "belong",Space,Str "to",Space,Str "a",Space,Str "single",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "block",Space,Str "quotes)."]
, CodeBlock ("",[],[]) " { <code> }"
, Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "use",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "every",Space,Str "line,",Space,Str "as",Space,Str "with",Space,Str "blockquotes,",Space,Str "but",Space,Str "all",Space,Str "that",Space,Str "you",Space,Str "need",Space,Str "is",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "the",Space,Str "block",Space,Str "and",Space,Str "any",Space,Str "preceding",Space,Str "blank",Space,Str "lines."] ]
-
diff --git a/tests/latex-reader.native b/tests/latex-reader.native
index 76e5daf08..921bf9d77 100644
--- a/tests/latex-reader.native
+++ b/tests/latex-reader.native
@@ -375,4 +375,3 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[ [ Para [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/lhs-test.fragment.html+lhs b/tests/lhs-test.fragment.html+lhs
index fec6bb750..74180d5c1 100644
--- a/tests/lhs-test.fragment.html+lhs
+++ b/tests/lhs-test.fragment.html+lhs
@@ -1,51 +1,39 @@
-<div id="lhs-test"
-><h1
- >lhs test</h1
- ><p
- ><code
- >unsplit</code
- > is an arrow that takes a pair of values and combines them to return a single value:</p
- ><pre class="sourceCode haskell"
- ><code
- ><span class="Special"
- >&gt; </span
- ><span class="Function FunctionDefinition"
- >unsplit ::</span
- ><span class="Normal NormalText"
- > (Arrow a) =&gt; (b -&gt; c -&gt; d) -&gt; a (b, c) d</span
- ><br
- /><span class="Special"
- >&gt; </span
- ><span class="Normal NormalText"
- >unsplit = arr . </span
- ><span class="Function"
- >uncurry</span
- ><span class="Normal NormalText"
- > </span
- ><br
- /><span class="Special"
- >&gt; </span
- ><span class="Normal NormalText"
- > </span
- ><span class="Comment"
- >-- arr (\op (x,y) -&gt; x `op` y) </span
- ><br
- /></code
- ></pre
- ><p
- ><code
- >(***)</code
- > combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).</p
- ><pre
- ><code
- >f *** g = first f &gt;&gt;&gt; second g
+<h1 id="lhs-test"
+>lhs test</h1
+><p
+><code
+ >unsplit</code
+ > is an arrow that takes a pair of values and combines them to return a single value:</p
+><pre class="sourceCode haskell"
+><code
+ >&gt; unsplit :: (<span class="dt"
+ >Arrow</span
+ > a) =&gt; (b -&gt; c -&gt; d) -&gt; a (b, c) d<br
+ />&gt; unsplit <span class="fu"
+ >=</span
+ > arr <span class="fu"
+ >.</span
+ > <span class="fu"
+ >uncurry</span
+ > <br
+ />&gt; <span class="co"
+ >-- arr (\op (x,y) -&gt; x `op` y) </span
+ ><br
+ /></code
+ ></pre
+><p
+><code
+ >(***)</code
+ > combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).</p
+><pre
+><code
+ >f *** g = first f &gt;&gt;&gt; second g
</code
- ></pre
- ><p
- >Block quote:</p
- ><blockquote
- ><p
- >foo bar</p
- ></blockquote
- ></div
->
+ ></pre
+><p
+>Block quote:</p
+><blockquote
+><p
+ >foo bar</p
+ ></blockquote
+> \ No newline at end of file
diff --git a/tests/lhs-test.html b/tests/lhs-test.html
index 5f015db0f..1cfcb199a 100644
--- a/tests/lhs-test.html
+++ b/tests/lhs-test.html
@@ -4,74 +4,65 @@
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
- <meta name="date" content="" />
<style type="text/css">
- table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
- td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
- td.sourceCode { padding-left: 5px; }
- pre.sourceCode { }
- pre.sourceCode span.Normal { }
- pre.sourceCode span.Keyword { color: #007020; font-weight: bold; }
- pre.sourceCode span.DataType { color: #902000; }
- pre.sourceCode span.DecVal { color: #40a070; }
- pre.sourceCode span.BaseN { color: #40a070; }
- pre.sourceCode span.Float { color: #40a070; }
- pre.sourceCode span.Char { color: #4070a0; }
- pre.sourceCode span.String { color: #4070a0; }
- pre.sourceCode span.Comment { color: #60a0b0; font-style: italic; }
- pre.sourceCode span.Others { color: #007020; }
- pre.sourceCode span.Alert { color: red; font-weight: bold; }
- pre.sourceCode span.Function { color: #06287e; }
- pre.sourceCode span.RegionMarker { }
- pre.sourceCode span.Error { color: red; font-weight: bold; }
+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre
+ { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
+td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
+td.sourceCode { padding-left: 5px; }
+pre.sourceCode span.kw { color: #007020; font-weight: bold; }
+pre.sourceCode span.dt { color: #902000; }
+pre.sourceCode span.dv { color: #40a070; }
+pre.sourceCode span.bn { color: #40a070; }
+pre.sourceCode span.fl { color: #40a070; }
+pre.sourceCode span.ch { color: #4070a0; }
+pre.sourceCode span.st { color: #4070a0; }
+pre.sourceCode span.co { color: #60a0b0; font-style: italic; }
+pre.sourceCode span.ot { color: #007020; }
+pre.sourceCode span.al { color: red; font-weight: bold; }
+pre.sourceCode span.fu { color: #06287e; }
+pre.sourceCode span.re { }
+pre.sourceCode span.er { color: red; font-weight: bold; }
</style>
</head>
<body>
-<div id="lhs-test"
-><h1
- >lhs test</h1
- ><p
- ><code
- >unsplit</code
- > is an arrow that takes a pair of values and combines them to return a single value:</p
- ><pre class="sourceCode haskell"
- ><code
- ><span class="Function FunctionDefinition"
- >unsplit ::</span
- ><span class="Normal NormalText"
- > (Arrow a) =&gt; (b -&gt; c -&gt; d) -&gt; a (b, c) d</span
- ><br
- /><span class="Normal NormalText"
- >unsplit = arr . </span
- ><span class="Function"
- >uncurry</span
- ><span class="Normal NormalText"
- > </span
- ><br
- /><span class="Normal NormalText"
- > </span
- ><span class="Comment"
- >-- arr (\op (x,y) -&gt; x `op` y) </span
- ><br
- /></code
- ></pre
- ><p
- ><code
- >(***)</code
- > combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).</p
- ><pre
- ><code
- >f *** g = first f &gt;&gt;&gt; second g
+<h1 id="lhs-test"
+>lhs test</h1
+><p
+><code
+ >unsplit</code
+ > is an arrow that takes a pair of values and combines them to return a single value:</p
+><pre class="sourceCode haskell"
+><code
+ >unsplit :: (<span class="dt"
+ >Arrow</span
+ > a) =&gt; (b -&gt; c -&gt; d) -&gt; a (b, c) d<br
+ />unsplit <span class="fu"
+ >=</span
+ > arr <span class="fu"
+ >.</span
+ > <span class="fu"
+ >uncurry</span
+ > <br
+ /> <span class="co"
+ >-- arr (\op (x,y) -&gt; x `op` y) </span
+ ><br
+ /></code
+ ></pre
+><p
+><code
+ >(***)</code
+ > combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).</p
+><pre
+><code
+ >f *** g = first f &gt;&gt;&gt; second g
</code
- ></pre
- ><p
- >Block quote:</p
- ><blockquote
- ><p
- >foo bar</p
- ></blockquote
- ></div
+ ></pre
+><p
+>Block quote:</p
+><blockquote
+><p
+ >foo bar</p
+ ></blockquote
>
</body>
</html>
-
diff --git a/tests/lhs-test.html+lhs b/tests/lhs-test.html+lhs
index 210054bf6..a33bf83ce 100644
--- a/tests/lhs-test.html+lhs
+++ b/tests/lhs-test.html+lhs
@@ -4,80 +4,65 @@
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
- <meta name="date" content="" />
<style type="text/css">
- table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
- td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
- td.sourceCode { padding-left: 5px; }
- pre.sourceCode { }
- pre.sourceCode span.Normal { }
- pre.sourceCode span.Keyword { color: #007020; font-weight: bold; }
- pre.sourceCode span.DataType { color: #902000; }
- pre.sourceCode span.DecVal { color: #40a070; }
- pre.sourceCode span.BaseN { color: #40a070; }
- pre.sourceCode span.Float { color: #40a070; }
- pre.sourceCode span.Char { color: #4070a0; }
- pre.sourceCode span.String { color: #4070a0; }
- pre.sourceCode span.Comment { color: #60a0b0; font-style: italic; }
- pre.sourceCode span.Others { color: #007020; }
- pre.sourceCode span.Alert { color: red; font-weight: bold; }
- pre.sourceCode span.Function { color: #06287e; }
- pre.sourceCode span.RegionMarker { }
- pre.sourceCode span.Error { color: red; font-weight: bold; }
+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre
+ { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
+td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
+td.sourceCode { padding-left: 5px; }
+pre.sourceCode span.kw { color: #007020; font-weight: bold; }
+pre.sourceCode span.dt { color: #902000; }
+pre.sourceCode span.dv { color: #40a070; }
+pre.sourceCode span.bn { color: #40a070; }
+pre.sourceCode span.fl { color: #40a070; }
+pre.sourceCode span.ch { color: #4070a0; }
+pre.sourceCode span.st { color: #4070a0; }
+pre.sourceCode span.co { color: #60a0b0; font-style: italic; }
+pre.sourceCode span.ot { color: #007020; }
+pre.sourceCode span.al { color: red; font-weight: bold; }
+pre.sourceCode span.fu { color: #06287e; }
+pre.sourceCode span.re { }
+pre.sourceCode span.er { color: red; font-weight: bold; }
</style>
</head>
<body>
-<div id="lhs-test"
-><h1
- >lhs test</h1
- ><p
- ><code
- >unsplit</code
- > is an arrow that takes a pair of values and combines them to return a single value:</p
- ><pre class="sourceCode haskell"
- ><code
- ><span class="Special"
- >&gt; </span
- ><span class="Function FunctionDefinition"
- >unsplit ::</span
- ><span class="Normal NormalText"
- > (Arrow a) =&gt; (b -&gt; c -&gt; d) -&gt; a (b, c) d</span
- ><br
- /><span class="Special"
- >&gt; </span
- ><span class="Normal NormalText"
- >unsplit = arr . </span
- ><span class="Function"
- >uncurry</span
- ><span class="Normal NormalText"
- > </span
- ><br
- /><span class="Special"
- >&gt; </span
- ><span class="Normal NormalText"
- > </span
- ><span class="Comment"
- >-- arr (\op (x,y) -&gt; x `op` y) </span
- ><br
- /></code
- ></pre
- ><p
- ><code
- >(***)</code
- > combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).</p
- ><pre
- ><code
- >f *** g = first f &gt;&gt;&gt; second g
+<h1 id="lhs-test"
+>lhs test</h1
+><p
+><code
+ >unsplit</code
+ > is an arrow that takes a pair of values and combines them to return a single value:</p
+><pre class="sourceCode haskell"
+><code
+ >&gt; unsplit :: (<span class="dt"
+ >Arrow</span
+ > a) =&gt; (b -&gt; c -&gt; d) -&gt; a (b, c) d<br
+ />&gt; unsplit <span class="fu"
+ >=</span
+ > arr <span class="fu"
+ >.</span
+ > <span class="fu"
+ >uncurry</span
+ > <br
+ />&gt; <span class="co"
+ >-- arr (\op (x,y) -&gt; x `op` y) </span
+ ><br
+ /></code
+ ></pre
+><p
+><code
+ >(***)</code
+ > combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).</p
+><pre
+><code
+ >f *** g = first f &gt;&gt;&gt; second g
</code
- ></pre
- ><p
- >Block quote:</p
- ><blockquote
- ><p
- >foo bar</p
- ></blockquote
- ></div
+ ></pre
+><p
+>Block quote:</p
+><blockquote
+><p
+ >foo bar</p
+ ></blockquote
>
</body>
</html>
-
diff --git a/tests/lhs-test.latex b/tests/lhs-test.latex
index ee078546b..331f429ef 100644
--- a/tests/lhs-test.latex
+++ b/tests/lhs-test.latex
@@ -1,5 +1,5 @@
\documentclass{article}
-\usepackage{amsmath}
+\usepackage{amssymb,amsmath}
\usepackage[mathletters]{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[breaklinks=true,unicode=true]{hyperref}
@@ -35,4 +35,3 @@ foo bar
\end{quote}
\end{document}
-
diff --git a/tests/lhs-test.latex+lhs b/tests/lhs-test.latex+lhs
index e4041a3af..a6270afcf 100644
--- a/tests/lhs-test.latex+lhs
+++ b/tests/lhs-test.latex+lhs
@@ -1,5 +1,5 @@
\documentclass{article}
-\usepackage{amsmath}
+\usepackage{amssymb,amsmath}
\usepackage[mathletters]{ucs}
\usepackage[utf8x]{inputenc}
\usepackage{listings}
@@ -37,4 +37,3 @@ foo bar
\end{quote}
\end{document}
-
diff --git a/tests/lhs-test.markdown b/tests/lhs-test.markdown
index 5b7c6465a..834d642d8 100644
--- a/tests/lhs-test.markdown
+++ b/tests/lhs-test.markdown
@@ -16,6 +16,3 @@ and one arrow on the second item of the pair).
Block quote:
> foo bar
-
-
-
diff --git a/tests/lhs-test.markdown+lhs b/tests/lhs-test.markdown+lhs
index fa8564a98..187fa630f 100644
--- a/tests/lhs-test.markdown+lhs
+++ b/tests/lhs-test.markdown+lhs
@@ -17,6 +17,3 @@ and one arrow on the second item of the pair).
Block quote:
> foo bar
-
-
-
diff --git a/tests/lhs-test.native b/tests/lhs-test.native
index 51274399b..94150f069 100644
--- a/tests/lhs-test.native
+++ b/tests/lhs-test.native
@@ -8,4 +8,3 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
, BlockQuote
[ Para [Str "foo",Space,Str "bar"] ]
]
-
diff --git a/tests/lhs-test.rst b/tests/lhs-test.rst
index c567fb4ed..67f7b3984 100644
--- a/tests/lhs-test.rst
+++ b/tests/lhs-test.rst
@@ -22,5 +22,3 @@ Block quote:
foo bar
-
-
diff --git a/tests/lhs-test.rst+lhs b/tests/lhs-test.rst+lhs
index 7feeea2dc..22d54e85e 100644
--- a/tests/lhs-test.rst+lhs
+++ b/tests/lhs-test.rst+lhs
@@ -20,5 +20,3 @@ Block quote:
foo bar
-
-
diff --git a/tests/markdown-reader-more.native b/tests/markdown-reader-more.native
index 9ce783fb8..104baeaa6 100644
--- a/tests/markdown-reader-more.native
+++ b/tests/markdown-reader-more.native
@@ -31,5 +31,12 @@ Pandoc (Meta {docTitle = [Str "Title",Space,Str "spanning",Space,Str "multiple",
, Header 2 [Str "Multilingual",Space,Str "URLs"]
, Para [Link [Code "http://\27979.com?\27979=\27979"] ("http://%E6%B5%8B.com?%E6%B5%8B=%E6%B5%8B","")]
, Para [Link [Str "foo"] ("/bar/%E6%B5%8B?x=%E6%B5%8B","title")]
-, Para [Link [Code "\27979@foo.\27979.baz"] ("mailto:%E6%B5%8B@foo.%E6%B5%8B.baz","")] ]
-
+, Para [Link [Code "\27979@foo.\27979.baz"] ("mailto:%E6%B5%8B@foo.%E6%B5%8B.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 "."]
+, OrderedList (3,Example,TwoParens)
+ [ [ Plain [Str "Third",Space,Str "example",Str "."] ]
+ ] ]
diff --git a/tests/markdown-reader-more.txt b/tests/markdown-reader-more.txt
index 1feb1e5d4..29e210088 100644
--- a/tests/markdown-reader-more.txt
+++ b/tests/markdown-reader-more.txt
@@ -91,3 +91,12 @@ there`
<测@foo.测.baz>
+## Numbered examples
+
+(@) First example.
+(@foo) Second example.
+
+Explanation of examples (@foo) and (@bar).
+
+(@bar) Third example.
+
diff --git a/tests/rst-reader.native b/tests/rst-reader.native
index eddeb6e8d..b79d35bd9 100644
--- a/tests/rst-reader.native
+++ b/tests/rst-reader.native
@@ -309,4 +309,3 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite",Str ":
[ [ Plain [Str "b"] ]
, [ Plain [Str "b",Space,Str "2"] ]
, [ Plain [Str "b",Space,Str "2"] ] ] ], [ Plain [Str "c",Space,Str "c",Space,Str "2",Space,Str "c",Space,Str "2"] ] ] ] ]
-
diff --git a/tests/s5.basic.html b/tests/s5.basic.html
index 253bcab2f..825d05868 100644
--- a/tests/s5.basic.html
+++ b/tests/s5.basic.html
@@ -10,289 +10,30 @@
<!-- configuration parameters -->
<meta name="defaultView" content="slideshow" />
<meta name="controlVis" content="hidden" />
- <style type="text/css" media="projection" id="slideProj">
- /* Do not edit or override these styles! The system will likely break if you do. */
-
- div#header, div#footer, div#controls, .slide {position: absolute;}
- html>body div#header, html>body div#footer,
- html>body div#controls, html>body .slide {position: fixed;}
- .handout {display: none;}
- .layout {display: block;}
- .slide, .hideme, .incremental {visibility: hidden;}
- #slide0 {visibility: visible;}
-
- /* The following styles size, place, and layer the slide components.
- Edit these if you want to change the overall slide layout.
- The commented lines can be uncommented (and modified, if necessary)
- to help you with the rearrangement process. */
-
- /* target = 1024x768 */
-
- div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
- div#header {top: 0; height: 3em; z-index: 1;}
- div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}
- .slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}
- div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
- div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
- margin: 0;}
- #currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}
- html>body #currentSlide {position: fixed;}
-
- /*
- div#header {background: #FCC;}
- div#footer {background: #CCF;}
- div#controls {background: #BBD;}
- div#currentSlide {background: #FFC;}
- */
-
- /* Following are the presentation styles -- edit away! */
-
- body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}
- :link, :visited {text-decoration: none; color: #00C;}
- #controls :active {color: #88A !important;}
- #controls :focus {outline: 1px dotted #227;}
- h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
- ul, pre {margin: 0; line-height: 1em;}
- html, body {margin: 0; padding: 0;}
-
- blockquote, q {font-style: italic;}
- blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}
- blockquote p {margin: 0;}
- blockquote i {font-style: normal;}
- blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}
- blockquote b i {font-style: italic;}
-
- kbd {font-weight: bold; font-size: 1em;}
- sup {font-size: smaller; line-height: 1px;}
-
- .slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}
- .slide code.bad, code del {color: red;}
- .slide code.old {color: silver;}
- .slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}
- .slide pre code {display: block;}
- .slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}
- .slide li {margin-top: 0.75em; margin-right: 0;}
- .slide ul ul {line-height: 1;}
- .slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}
- .slide img.leader {display: block; margin: 0 auto;}
-
- div#header, div#footer {background: #005; color: #AAB;
- font-family: Verdana, Helvetica, sans-serif;}
- div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;
- line-height: 1px;}
- div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}
- #footer h1, #footer h2 {display: block; padding: 0 1em;}
- #footer h2 {font-style: italic;}
-
- div.long {font-size: 0.75em;}
- .slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;
- margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;
- font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;
- color: #DDE; background: #005;}
- .slide h3 {font-size: 130%;}
- h1 abbr {font-variant: small-caps;}
-
- div#controls {position: absolute; left: 50%; bottom: 0;
- width: 50%;
- text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}
- html>body div#controls {position: fixed; padding: 0 0 1em 0;
- top: auto;}
- div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
- margin: 0; padding: 0;}
- #controls #navLinks a {padding: 0; margin: 0 0.5em;
- background: #005; border: none; color: #779;
- cursor: pointer;}
- #controls #navList {height: 1em;}
- #controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}
-
- #currentSlide {text-align: center; font-size: 0.5em; color: #449;}
-
- #slide0 {padding-top: 3.5em; font-size: 90%;}
- #slide0 h1 {position: static; margin: 1em 0 0; padding: 0;
- font: bold 2em Helvetica, sans-serif; white-space: normal;
- color: #000; background: transparent;}
- #slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}
- #slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
- #slide0 h4 {margin-top: 0; font-size: 1em;}
-
- ul.urls {list-style: none; display: inline; margin: 0;}
- .urls li {display: inline; margin: 0;}
- .note {display: none;}
- .external {border-bottom: 1px dotted gray;}
- html>body .external {border-bottom: none;}
- .external:after {content: " \274F"; font-size: smaller; color: #77B;}
-
- .incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}
- img.incremental {visibility: hidden;}
- .slide .current {color: #B02;}
-
-
- /* diagnostics
-
- li:after {content: " [" attr(class) "]"; color: #F88;}
- */
-
- </style>
- <style type="text/css" media="projection" id="operaFix">
- /* DO NOT CHANGE THESE unless you really want to break Opera Show */
- .slide {
- visibility: visible !important;
- position: static !important;
- page-break-before: always;
- }
- #slide0 {page-break-before: avoid;}
-
- </style>
- <style type="text/css" media="screen" id="outlineStyle">
- /* don't change this unless you want the layout stuff to show up in the outline view! */
-
- .layout div, #footer *, #controlForm * {display: none;}
- #footer, #controls, #controlForm, #navLinks, #toggle {
- display: block; visibility: visible; margin: 0; padding: 0;}
- #toggle {float: right; padding: 0.5em;}
- html>body #toggle {position: fixed; top: 0; right: 0;}
-
- /* making the outline look pretty-ish */
-
- #slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}
- #slide0 h1 {padding-top: 1.5em;}
- .slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;
- border-top: 1px solid #888; border-bottom: 1px solid #AAA;}
- #toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
-
- </style>
- <style type="text/css" media="print" id="slidePrint">
- /* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */
- .slide, ul {page-break-inside: avoid; visibility: visible !important;}
- h1 {page-break-after: avoid;}
-
- body {font-size: 12pt; background: white;}
- * {color: black;}
-
- #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}
- #slide0 h3 {margin: 0; padding: 0;}
- #slide0 h4 {margin: 0 0 0.5em; padding: 0;}
- #slide0 {margin-bottom: 3em;}
-
- h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}
- .extra {background: transparent !important;}
- div.extra, pre.extra, .example {font-size: 10pt; color: #333;}
- ul.extra a {font-weight: bold;}
- p.example {display: none;}
-
- #header {display: none;}
- #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}
- #footer h2, #controls {display: none;}
-
- /* The following rule keeps the layout stuff out of print. Remove at your own risk! */
- .layout, .layout * {display: none !important;}
-
- </style>
- <script type="text/javascript">
- // S5 v1.1 slides.js -- released into the Public Domain
- //
- // Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information
- // about all the wonderful and talented contributors to this code!
- var undef;var slideCSS='';var snum=0;var smax=1;var incpos=0;var number=undef;var s5mode=true;var defaultView='slideshow';var controlVis='visible';var isIE=navigator.appName=='Microsoft Internet Explorer'&&navigator.userAgent.indexOf('Opera')<1?1:0;var isOp=navigator.userAgent.indexOf('Opera')>-1?1:0;var isGe=navigator.userAgent.indexOf('Gecko')>-1&&navigator.userAgent.indexOf('Safari')<1?1:0;function hasClass(object,className){if(!object.className)return false;return(object.className.search('(^|\\s)'+className+'(\\s|$)')!=-1);}
- function hasValue(object,value){if(!object)return false;return(object.search('(^|\\s)'+value+'(\\s|$)')!=-1);}
- function removeClass(object,className){if(!object)return;object.className=object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'),RegExp.$1+RegExp.$2);}
- function addClass(object,className){if(!object||hasClass(object,className))return;if(object.className){object.className+=' '+className;}else{object.className=className;}}
- function GetElementsWithClassName(elementName,className){var allElements=document.getElementsByTagName(elementName);var elemColl=new Array();for(var i=0;i<allElements.length;i++){if(hasClass(allElements[i],className)){elemColl[elemColl.length]=allElements[i];}}
- return elemColl;}
- function isParentOrSelf(element,id){if(element==null||element.nodeName=='BODY')return false;else if(element.id==id)return true;else return isParentOrSelf(element.parentNode,id);}
- function nodeValue(node){var result="";if(node.nodeType==1){var children=node.childNodes;for(var i=0;i<children.length;++i){result+=nodeValue(children[i]);}}
- else if(node.nodeType==3){result=node.nodeValue;}
- return(result);}
- function slideLabel(){var slideColl=GetElementsWithClassName('*','slide');var list=document.getElementById('jumplist');smax=slideColl.length;for(var n=0;n<smax;n++){var obj=slideColl[n];var did='slide'+n.toString();obj.setAttribute('id',did);if(isOp)continue;var otext='';var menu=obj.firstChild;if(!menu)continue;while(menu&&menu.nodeType==3){menu=menu.nextSibling;}
- if(!menu)continue;var menunodes=menu.childNodes;for(var o=0;o<menunodes.length;o++){otext+=nodeValue(menunodes[o]);}
- list.options[list.length]=new Option(n+' : '+otext,n);}}
- function currentSlide(){var cs;if(document.getElementById){cs=document.getElementById('currentSlide');}else{cs=document.currentSlide;}
- cs.innerHTML='<span id="csHere">'+snum+'<\/span> '+'<span id="csSep">\/<\/span> '+'<span id="csTotal">'+(smax-1)+'<\/span>';if(snum==0){cs.style.visibility='hidden';}else{cs.style.visibility='visible';}}
- function go(step){if(document.getElementById('slideProj').disabled||step==0)return;var jl=document.getElementById('jumplist');var cid='slide'+snum;var ce=document.getElementById(cid);if(incrementals[snum].length>0){for(var i=0;i<incrementals[snum].length;i++){removeClass(incrementals[snum][i],'current');removeClass(incrementals[snum][i],'incremental');}}
- if(step!='j'){snum+=step;lmax=smax-1;if(snum>lmax)snum=lmax;if(snum<0)snum=0;}else
- snum=parseInt(jl.value);var nid='slide'+snum;var ne=document.getElementById(nid);if(!ne){ne=document.getElementById('slide0');snum=0;}
- if(step<0){incpos=incrementals[snum].length}else{incpos=0;}
- if(incrementals[snum].length>0&&incpos==0){for(var i=0;i<incrementals[snum].length;i++){if(hasClass(incrementals[snum][i],'current'))
- incpos=i+1;else
- addClass(incrementals[snum][i],'incremental');}}
- if(incrementals[snum].length>0&&incpos>0)
- addClass(incrementals[snum][incpos-1],'current');ce.style.visibility='hidden';ne.style.visibility='visible';jl.selectedIndex=snum;currentSlide();number=0;}
- function goTo(target){if(target>=smax||target==snum)return;go(target-snum);}
- function subgo(step){if(step>0){removeClass(incrementals[snum][incpos-1],'current');removeClass(incrementals[snum][incpos],'incremental');addClass(incrementals[snum][incpos],'current');incpos++;}else{incpos--;removeClass(incrementals[snum][incpos],'current');addClass(incrementals[snum][incpos],'incremental');addClass(incrementals[snum][incpos-1],'current');}}
- function toggle(){var slideColl=GetElementsWithClassName('*','slide');var slides=document.getElementById('slideProj');var outline=document.getElementById('outlineStyle');if(!slides.disabled){slides.disabled=true;outline.disabled=false;s5mode=false;fontSize('1em');for(var n=0;n<smax;n++){var slide=slideColl[n];slide.style.visibility='visible';}}else{slides.disabled=false;outline.disabled=true;s5mode=true;fontScale();for(var n=0;n<smax;n++){var slide=slideColl[n];slide.style.visibility='hidden';}
- slideColl[snum].style.visibility='visible';}}
- function showHide(action){var obj=GetElementsWithClassName('*','hideme')[0];switch(action){case's':obj.style.visibility='visible';break;case'h':obj.style.visibility='hidden';break;case'k':if(obj.style.visibility!='visible'){obj.style.visibility='visible';}else{obj.style.visibility='hidden';}
- break;}}
- function keys(key){if(!key){key=event;key.which=key.keyCode;}
- if(key.which==84){toggle();return;}
- if(s5mode){switch(key.which){case 10:case 13:if(window.event&&isParentOrSelf(window.event.srcElement,'controls'))return;if(key.target&&isParentOrSelf(key.target,'controls'))return;if(number!=undef){goTo(number);break;}
- case 32:case 34:case 39:case 40:if(number!=undef){go(number);}else if(!incrementals[snum]||incpos>=incrementals[snum].length){go(1);}else{subgo(1);}
- break;case 33:case 37:case 38:if(number!=undef){go(-1*number);}else if(!incrementals[snum]||incpos<=0){go(-1);}else{subgo(-1);}
- break;case 36:goTo(0);break;case 35:goTo(smax-1);break;case 67:showHide('k');break;}
- if(key.which<48||key.which>57){number=undef;}else{if(window.event&&isParentOrSelf(window.event.srcElement,'controls'))return;if(key.target&&isParentOrSelf(key.target,'controls'))return;number=(((number!=undef)?number:0)*10)+(key.which-48);}}
- return false;}
- function clicker(e){number=undef;var target;if(window.event){target=window.event.srcElement;e=window.event;}else target=e.target;if(target.getAttribute('href')!=null||hasValue(target.rel,'external')||isParentOrSelf(target,'controls')||isParentOrSelf(target,'embed')||isParentOrSelf(target,'object'))return true;if(!e.which||e.which==1){if(!incrementals[snum]||incpos>=incrementals[snum].length){go(1);}else{subgo(1);}}}
- function findSlide(hash){var target=null;var slides=GetElementsWithClassName('*','slide');for(var i=0;i<slides.length;i++){var targetSlide=slides[i];if((targetSlide.name&&targetSlide.name==hash)||(targetSlide.id&&targetSlide.id==hash)){target=targetSlide;break;}}
- while(target!=null&&target.nodeName!='BODY'){if(hasClass(target,'slide')){return parseInt(target.id.slice(5));}
- target=target.parentNode;}
- return null;}
- function slideJump(){if(window.location.hash==null)return;var sregex=/^#slide(\d+)$/;var matches=sregex.exec(window.location.hash);var dest=null;if(matches!=null){dest=parseInt(matches[1]);}else{dest=findSlide(window.location.hash.slice(1));}
- if(dest!=null)
- go(dest-snum);}
- function fixLinks(){var thisUri=window.location.href;thisUri=thisUri.slice(0,thisUri.length-window.location.hash.length);var aelements=document.getElementsByTagName('A');for(var i=0;i<aelements.length;i++){var a=aelements[i].href;var slideID=a.match('\#slide[0-9]{1,2}');if((slideID)&&(slideID[0].slice(0,1)=='#')){var dest=findSlide(slideID[0].slice(1));if(dest!=null){if(aelements[i].addEventListener){aelements[i].addEventListener("click",new Function("e","if (document.getElementById('slideProj').disabled) return;"+"go("+dest+" - snum); "+"if (e.preventDefault) e.preventDefault();"),true);}else if(aelements[i].attachEvent){aelements[i].attachEvent("onclick",new Function("","if (document.getElementById('slideProj').disabled) return;"+"go("+dest+" - snum); "+"event.returnValue = false;"));}}}}}
- function externalLinks(){if(!document.getElementsByTagName)return;var anchors=document.getElementsByTagName('a');for(var i=0;i<anchors.length;i++){var anchor=anchors[i];if(anchor.getAttribute('href')&&hasValue(anchor.rel,'external')){anchor.target='_blank';addClass(anchor,'external');}}}
- function createControls(){var controlsDiv=document.getElementById("controls");if(!controlsDiv)return;var hider=' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"';var hideDiv,hideList='';if(controlVis=='hidden'){hideDiv=hider;}else{hideList=hider;}
- controlsDiv.innerHTML='<form action="#" id="controlForm"'+hideDiv+'>'+'<div id="navLinks">'+'<a accesskey="t" id="toggle" href="javascript:toggle();">&#216;<\/a>'+'<a accesskey="z" id="prev" href="javascript:go(-1);">&laquo;<\/a>'+'<a accesskey="x" id="next" href="javascript:go(1);">&raquo;<\/a>'+'<div id="navList"'+hideList+'><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>'+'<\/div><\/form>';if(controlVis=='hidden'){var hidden=document.getElementById('navLinks');}else{var hidden=document.getElementById('jumplist');}
- addClass(hidden,'hideme');}
- function fontScale(){if(!s5mode)return false;var vScale=22;var hScale=32;if(window.innerHeight){var vSize=window.innerHeight;var hSize=window.innerWidth;}else if(document.documentElement.clientHeight){var vSize=document.documentElement.clientHeight;var hSize=document.documentElement.clientWidth;}else if(document.body.clientHeight){var vSize=document.body.clientHeight;var hSize=document.body.clientWidth;}else{var vSize=700;var hSize=1024;}
- var newSize=Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));fontSize(newSize+'px');if(isGe){var obj=document.getElementsByTagName('body')[0];obj.style.display='none';obj.style.display='block';}}
- function fontSize(value){if(!(s5ss=document.getElementById('s5ss'))){if(!isIE){document.getElementsByTagName('head')[0].appendChild(s5ss=document.createElement('style'));s5ss.setAttribute('media','screen, projection');s5ss.setAttribute('id','s5ss');}else{document.createStyleSheet();document.s5ss=document.styleSheets[document.styleSheets.length-1];}}
- if(!isIE){while(s5ss.lastChild)s5ss.removeChild(s5ss.lastChild);s5ss.appendChild(document.createTextNode('body {font-size: '+value+' !important;}'));}else{document.s5ss.addRule('body','font-size: '+value+' !important;');}}
- function notOperaFix(){slideCSS=document.getElementById('slideProj').href;var slides=document.getElementById('slideProj');var outline=document.getElementById('outlineStyle');slides.setAttribute('media','screen');outline.disabled=true;if(isGe){slides.setAttribute('href','null');slides.setAttribute('href',slideCSS);}
- if(isIE&&document.styleSheets&&document.styleSheets[0]){document.styleSheets[0].addRule('img','behavior: url(ui/default/iepngfix.htc)');document.styleSheets[0].addRule('div','behavior: url(ui/default/iepngfix.htc)');document.styleSheets[0].addRule('.slide','behavior: url(ui/default/iepngfix.htc)');}}
- function getIncrementals(obj){var incrementals=new Array();if(!obj)
- return incrementals;var children=obj.childNodes;for(var i=0;i<children.length;i++){var child=children[i];if(hasClass(child,'incremental')){if(child.nodeName=='OL'||child.nodeName=='UL'){removeClass(child,'incremental');for(var j=0;j<child.childNodes.length;j++){if(child.childNodes[j].nodeType==1){addClass(child.childNodes[j],'incremental');}}}else{incrementals[incrementals.length]=child;removeClass(child,'incremental');}}
- if(hasClass(child,'show-first')){if(child.nodeName=='OL'||child.nodeName=='UL'){removeClass(child,'show-first');if(child.childNodes[isGe].nodeType==1){removeClass(child.childNodes[isGe],'incremental');}}else{incrementals[incrementals.length]=child;}}
- incrementals=incrementals.concat(getIncrementals(child));}
- return incrementals;}
- function createIncrementals(){var incrementals=new Array();for(var i=0;i<smax;i++){incrementals[i]=getIncrementals(document.getElementById('slide'+i));}
- return incrementals;}
- function defaultCheck(){var allMetas=document.getElementsByTagName('meta');for(var i=0;i<allMetas.length;i++){if(allMetas[i].name=='defaultView'){defaultView=allMetas[i].content;}
- if(allMetas[i].name=='controlVis'){controlVis=allMetas[i].content;}}}
- function trap(e){if(!e){e=event;e.which=e.keyCode;}
- try{modifierKey=e.ctrlKey||e.altKey||e.metaKey;}
- catch(e){modifierKey=false;}
- return modifierKey||e.which==0;}
- function startup(){defaultCheck();if(!isOp)
- createControls();slideLabel();fixLinks();externalLinks();fontScale();if(!isOp){notOperaFix();incrementals=createIncrementals();slideJump();if(defaultView=='outline'){toggle();}
- document.onkeyup=keys;document.onkeypress=trap;document.onclick=clicker;}}
- window.onload=startup;window.onresize=function(){setTimeout('fontScale()',50);}
- </script>
+ <!-- style sheet links -->
+ <link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
+ <link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
+ <link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
+ <link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
+ <!-- S5 JS -->
+ <script src="ui/default/slides.js" type="text/javascript"></script>
</head>
<body>
-<h1 class="title">My S5 Document</h1>
<div class="layout">
<div id="controls"></div>
<div id="currentSlide"></div>
<div id="header"></div>
<div id="footer">
-<h1
->July 15, 2006</h1
-><h2
->My S5 Document</h2
-></div>
+ <h1>July 15, 2006</h1>
+ <h2>My S5 Document</h2>
+</div>
</div>
<div class="presentation">
-
<div class="slide">
-<h1
->My S5 Document</h1
-><h3
->Sam Smith<br
- />Jen Jones</h3
-><h4
->July 15, 2006</h4
-></div>
+ <h1>My S5 Document</h1>
+ <h3>Sam Smith<br/>Jen Jones</h3>
+ <h4>July 15, 2006</h4>
+</div>
<div class="slide">
<h1
>First slide</h1
@@ -309,35 +50,10 @@
><ul
><li
><span class="math"
- >\frac{<em
- >d</em
- >}{<em
- >dx</em
- >}<em
- >f</em
- >(<em
- >x</em
- >)=\lim<sub
- ><em
- >h</em
- > → 0</sub
- >\frac{<em
- >f</em
- >(<em
- >x</em
- >+<em
- >h</em
- >)-<em
- >f</em
- >(<em
- >x</em
- >)}{<em
- >h</em
- >}</span
+ >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</span
></li
></ul
></div>
</div>
</body>
</html>
-
diff --git a/tests/s5.fancy.html b/tests/s5.fancy.html
index 1379c3e2e..f4f2e7815 100644
--- a/tests/s5.fancy.html
+++ b/tests/s5.fancy.html
@@ -7,6 +7,16 @@
<meta name="author" content="Sam Smith" />
<meta name="author" content="Jen Jones" />
<meta name="date" content="July 15, 2006" />
+ <!-- configuration parameters -->
+ <meta name="defaultView" content="slideshow" />
+ <meta name="controlVis" content="hidden" />
+ <!-- style sheet links -->
+ <link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
+ <link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
+ <link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
+ <link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
+ <!-- S5 JS -->
+ <script src="ui/default/slides.js" type="text/javascript"></script>
<script type="text/javascript"
>/*
LaTeXMathML.js from http://math.etsu.edu/LaTeXMathML/
@@ -208,292 +218,23 @@
{window.onload=generic;}}
</script
>
- <!-- configuration parameters -->
- <meta name="defaultView" content="slideshow" />
- <meta name="controlVis" content="hidden" />
- <style type="text/css" media="projection" id="slideProj">
- /* Do not edit or override these styles! The system will likely break if you do. */
-
- div#header, div#footer, div#controls, .slide {position: absolute;}
- html>body div#header, html>body div#footer,
- html>body div#controls, html>body .slide {position: fixed;}
- .handout {display: none;}
- .layout {display: block;}
- .slide, .hideme, .incremental {visibility: hidden;}
- #slide0 {visibility: visible;}
-
- /* The following styles size, place, and layer the slide components.
- Edit these if you want to change the overall slide layout.
- The commented lines can be uncommented (and modified, if necessary)
- to help you with the rearrangement process. */
-
- /* target = 1024x768 */
-
- div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
- div#header {top: 0; height: 3em; z-index: 1;}
- div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}
- .slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}
- div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
- div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
- margin: 0;}
- #currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}
- html>body #currentSlide {position: fixed;}
-
- /*
- div#header {background: #FCC;}
- div#footer {background: #CCF;}
- div#controls {background: #BBD;}
- div#currentSlide {background: #FFC;}
- */
-
- /* Following are the presentation styles -- edit away! */
-
- body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}
- :link, :visited {text-decoration: none; color: #00C;}
- #controls :active {color: #88A !important;}
- #controls :focus {outline: 1px dotted #227;}
- h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
- ul, pre {margin: 0; line-height: 1em;}
- html, body {margin: 0; padding: 0;}
-
- blockquote, q {font-style: italic;}
- blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}
- blockquote p {margin: 0;}
- blockquote i {font-style: normal;}
- blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}
- blockquote b i {font-style: italic;}
-
- kbd {font-weight: bold; font-size: 1em;}
- sup {font-size: smaller; line-height: 1px;}
-
- .slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}
- .slide code.bad, code del {color: red;}
- .slide code.old {color: silver;}
- .slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}
- .slide pre code {display: block;}
- .slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}
- .slide li {margin-top: 0.75em; margin-right: 0;}
- .slide ul ul {line-height: 1;}
- .slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}
- .slide img.leader {display: block; margin: 0 auto;}
-
- div#header, div#footer {background: #005; color: #AAB;
- font-family: Verdana, Helvetica, sans-serif;}
- div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;
- line-height: 1px;}
- div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}
- #footer h1, #footer h2 {display: block; padding: 0 1em;}
- #footer h2 {font-style: italic;}
-
- div.long {font-size: 0.75em;}
- .slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;
- margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;
- font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;
- color: #DDE; background: #005;}
- .slide h3 {font-size: 130%;}
- h1 abbr {font-variant: small-caps;}
-
- div#controls {position: absolute; left: 50%; bottom: 0;
- width: 50%;
- text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}
- html>body div#controls {position: fixed; padding: 0 0 1em 0;
- top: auto;}
- div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
- margin: 0; padding: 0;}
- #controls #navLinks a {padding: 0; margin: 0 0.5em;
- background: #005; border: none; color: #779;
- cursor: pointer;}
- #controls #navList {height: 1em;}
- #controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}
-
- #currentSlide {text-align: center; font-size: 0.5em; color: #449;}
-
- #slide0 {padding-top: 3.5em; font-size: 90%;}
- #slide0 h1 {position: static; margin: 1em 0 0; padding: 0;
- font: bold 2em Helvetica, sans-serif; white-space: normal;
- color: #000; background: transparent;}
- #slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}
- #slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
- #slide0 h4 {margin-top: 0; font-size: 1em;}
-
- ul.urls {list-style: none; display: inline; margin: 0;}
- .urls li {display: inline; margin: 0;}
- .note {display: none;}
- .external {border-bottom: 1px dotted gray;}
- html>body .external {border-bottom: none;}
- .external:after {content: " \274F"; font-size: smaller; color: #77B;}
-
- .incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}
- img.incremental {visibility: hidden;}
- .slide .current {color: #B02;}
-
-
- /* diagnostics
-
- li:after {content: " [" attr(class) "]"; color: #F88;}
- */
-
- </style>
- <style type="text/css" media="projection" id="operaFix">
- /* DO NOT CHANGE THESE unless you really want to break Opera Show */
- .slide {
- visibility: visible !important;
- position: static !important;
- page-break-before: always;
- }
- #slide0 {page-break-before: avoid;}
-
- </style>
- <style type="text/css" media="screen" id="outlineStyle">
- /* don't change this unless you want the layout stuff to show up in the outline view! */
-
- .layout div, #footer *, #controlForm * {display: none;}
- #footer, #controls, #controlForm, #navLinks, #toggle {
- display: block; visibility: visible; margin: 0; padding: 0;}
- #toggle {float: right; padding: 0.5em;}
- html>body #toggle {position: fixed; top: 0; right: 0;}
-
- /* making the outline look pretty-ish */
-
- #slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}
- #slide0 h1 {padding-top: 1.5em;}
- .slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;
- border-top: 1px solid #888; border-bottom: 1px solid #AAA;}
- #toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
-
- </style>
- <style type="text/css" media="print" id="slidePrint">
- /* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */
- .slide, ul {page-break-inside: avoid; visibility: visible !important;}
- h1 {page-break-after: avoid;}
-
- body {font-size: 12pt; background: white;}
- * {color: black;}
-
- #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}
- #slide0 h3 {margin: 0; padding: 0;}
- #slide0 h4 {margin: 0 0 0.5em; padding: 0;}
- #slide0 {margin-bottom: 3em;}
-
- h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}
- .extra {background: transparent !important;}
- div.extra, pre.extra, .example {font-size: 10pt; color: #333;}
- ul.extra a {font-weight: bold;}
- p.example {display: none;}
-
- #header {display: none;}
- #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}
- #footer h2, #controls {display: none;}
-
- /* The following rule keeps the layout stuff out of print. Remove at your own risk! */
- .layout, .layout * {display: none !important;}
-
- </style>
- <script type="text/javascript">
- // S5 v1.1 slides.js -- released into the Public Domain
- //
- // Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information
- // about all the wonderful and talented contributors to this code!
- var undef;var slideCSS='';var snum=0;var smax=1;var incpos=0;var number=undef;var s5mode=true;var defaultView='slideshow';var controlVis='visible';var isIE=navigator.appName=='Microsoft Internet Explorer'&&navigator.userAgent.indexOf('Opera')<1?1:0;var isOp=navigator.userAgent.indexOf('Opera')>-1?1:0;var isGe=navigator.userAgent.indexOf('Gecko')>-1&&navigator.userAgent.indexOf('Safari')<1?1:0;function hasClass(object,className){if(!object.className)return false;return(object.className.search('(^|\\s)'+className+'(\\s|$)')!=-1);}
- function hasValue(object,value){if(!object)return false;return(object.search('(^|\\s)'+value+'(\\s|$)')!=-1);}
- function removeClass(object,className){if(!object)return;object.className=object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'),RegExp.$1+RegExp.$2);}
- function addClass(object,className){if(!object||hasClass(object,className))return;if(object.className){object.className+=' '+className;}else{object.className=className;}}
- function GetElementsWithClassName(elementName,className){var allElements=document.getElementsByTagName(elementName);var elemColl=new Array();for(var i=0;i<allElements.length;i++){if(hasClass(allElements[i],className)){elemColl[elemColl.length]=allElements[i];}}
- return elemColl;}
- function isParentOrSelf(element,id){if(element==null||element.nodeName=='BODY')return false;else if(element.id==id)return true;else return isParentOrSelf(element.parentNode,id);}
- function nodeValue(node){var result="";if(node.nodeType==1){var children=node.childNodes;for(var i=0;i<children.length;++i){result+=nodeValue(children[i]);}}
- else if(node.nodeType==3){result=node.nodeValue;}
- return(result);}
- function slideLabel(){var slideColl=GetElementsWithClassName('*','slide');var list=document.getElementById('jumplist');smax=slideColl.length;for(var n=0;n<smax;n++){var obj=slideColl[n];var did='slide'+n.toString();obj.setAttribute('id',did);if(isOp)continue;var otext='';var menu=obj.firstChild;if(!menu)continue;while(menu&&menu.nodeType==3){menu=menu.nextSibling;}
- if(!menu)continue;var menunodes=menu.childNodes;for(var o=0;o<menunodes.length;o++){otext+=nodeValue(menunodes[o]);}
- list.options[list.length]=new Option(n+' : '+otext,n);}}
- function currentSlide(){var cs;if(document.getElementById){cs=document.getElementById('currentSlide');}else{cs=document.currentSlide;}
- cs.innerHTML='<span id="csHere">'+snum+'<\/span> '+'<span id="csSep">\/<\/span> '+'<span id="csTotal">'+(smax-1)+'<\/span>';if(snum==0){cs.style.visibility='hidden';}else{cs.style.visibility='visible';}}
- function go(step){if(document.getElementById('slideProj').disabled||step==0)return;var jl=document.getElementById('jumplist');var cid='slide'+snum;var ce=document.getElementById(cid);if(incrementals[snum].length>0){for(var i=0;i<incrementals[snum].length;i++){removeClass(incrementals[snum][i],'current');removeClass(incrementals[snum][i],'incremental');}}
- if(step!='j'){snum+=step;lmax=smax-1;if(snum>lmax)snum=lmax;if(snum<0)snum=0;}else
- snum=parseInt(jl.value);var nid='slide'+snum;var ne=document.getElementById(nid);if(!ne){ne=document.getElementById('slide0');snum=0;}
- if(step<0){incpos=incrementals[snum].length}else{incpos=0;}
- if(incrementals[snum].length>0&&incpos==0){for(var i=0;i<incrementals[snum].length;i++){if(hasClass(incrementals[snum][i],'current'))
- incpos=i+1;else
- addClass(incrementals[snum][i],'incremental');}}
- if(incrementals[snum].length>0&&incpos>0)
- addClass(incrementals[snum][incpos-1],'current');ce.style.visibility='hidden';ne.style.visibility='visible';jl.selectedIndex=snum;currentSlide();number=0;}
- function goTo(target){if(target>=smax||target==snum)return;go(target-snum);}
- function subgo(step){if(step>0){removeClass(incrementals[snum][incpos-1],'current');removeClass(incrementals[snum][incpos],'incremental');addClass(incrementals[snum][incpos],'current');incpos++;}else{incpos--;removeClass(incrementals[snum][incpos],'current');addClass(incrementals[snum][incpos],'incremental');addClass(incrementals[snum][incpos-1],'current');}}
- function toggle(){var slideColl=GetElementsWithClassName('*','slide');var slides=document.getElementById('slideProj');var outline=document.getElementById('outlineStyle');if(!slides.disabled){slides.disabled=true;outline.disabled=false;s5mode=false;fontSize('1em');for(var n=0;n<smax;n++){var slide=slideColl[n];slide.style.visibility='visible';}}else{slides.disabled=false;outline.disabled=true;s5mode=true;fontScale();for(var n=0;n<smax;n++){var slide=slideColl[n];slide.style.visibility='hidden';}
- slideColl[snum].style.visibility='visible';}}
- function showHide(action){var obj=GetElementsWithClassName('*','hideme')[0];switch(action){case's':obj.style.visibility='visible';break;case'h':obj.style.visibility='hidden';break;case'k':if(obj.style.visibility!='visible'){obj.style.visibility='visible';}else{obj.style.visibility='hidden';}
- break;}}
- function keys(key){if(!key){key=event;key.which=key.keyCode;}
- if(key.which==84){toggle();return;}
- if(s5mode){switch(key.which){case 10:case 13:if(window.event&&isParentOrSelf(window.event.srcElement,'controls'))return;if(key.target&&isParentOrSelf(key.target,'controls'))return;if(number!=undef){goTo(number);break;}
- case 32:case 34:case 39:case 40:if(number!=undef){go(number);}else if(!incrementals[snum]||incpos>=incrementals[snum].length){go(1);}else{subgo(1);}
- break;case 33:case 37:case 38:if(number!=undef){go(-1*number);}else if(!incrementals[snum]||incpos<=0){go(-1);}else{subgo(-1);}
- break;case 36:goTo(0);break;case 35:goTo(smax-1);break;case 67:showHide('k');break;}
- if(key.which<48||key.which>57){number=undef;}else{if(window.event&&isParentOrSelf(window.event.srcElement,'controls'))return;if(key.target&&isParentOrSelf(key.target,'controls'))return;number=(((number!=undef)?number:0)*10)+(key.which-48);}}
- return false;}
- function clicker(e){number=undef;var target;if(window.event){target=window.event.srcElement;e=window.event;}else target=e.target;if(target.getAttribute('href')!=null||hasValue(target.rel,'external')||isParentOrSelf(target,'controls')||isParentOrSelf(target,'embed')||isParentOrSelf(target,'object'))return true;if(!e.which||e.which==1){if(!incrementals[snum]||incpos>=incrementals[snum].length){go(1);}else{subgo(1);}}}
- function findSlide(hash){var target=null;var slides=GetElementsWithClassName('*','slide');for(var i=0;i<slides.length;i++){var targetSlide=slides[i];if((targetSlide.name&&targetSlide.name==hash)||(targetSlide.id&&targetSlide.id==hash)){target=targetSlide;break;}}
- while(target!=null&&target.nodeName!='BODY'){if(hasClass(target,'slide')){return parseInt(target.id.slice(5));}
- target=target.parentNode;}
- return null;}
- function slideJump(){if(window.location.hash==null)return;var sregex=/^#slide(\d+)$/;var matches=sregex.exec(window.location.hash);var dest=null;if(matches!=null){dest=parseInt(matches[1]);}else{dest=findSlide(window.location.hash.slice(1));}
- if(dest!=null)
- go(dest-snum);}
- function fixLinks(){var thisUri=window.location.href;thisUri=thisUri.slice(0,thisUri.length-window.location.hash.length);var aelements=document.getElementsByTagName('A');for(var i=0;i<aelements.length;i++){var a=aelements[i].href;var slideID=a.match('\#slide[0-9]{1,2}');if((slideID)&&(slideID[0].slice(0,1)=='#')){var dest=findSlide(slideID[0].slice(1));if(dest!=null){if(aelements[i].addEventListener){aelements[i].addEventListener("click",new Function("e","if (document.getElementById('slideProj').disabled) return;"+"go("+dest+" - snum); "+"if (e.preventDefault) e.preventDefault();"),true);}else if(aelements[i].attachEvent){aelements[i].attachEvent("onclick",new Function("","if (document.getElementById('slideProj').disabled) return;"+"go("+dest+" - snum); "+"event.returnValue = false;"));}}}}}
- function externalLinks(){if(!document.getElementsByTagName)return;var anchors=document.getElementsByTagName('a');for(var i=0;i<anchors.length;i++){var anchor=anchors[i];if(anchor.getAttribute('href')&&hasValue(anchor.rel,'external')){anchor.target='_blank';addClass(anchor,'external');}}}
- function createControls(){var controlsDiv=document.getElementById("controls");if(!controlsDiv)return;var hider=' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"';var hideDiv,hideList='';if(controlVis=='hidden'){hideDiv=hider;}else{hideList=hider;}
- controlsDiv.innerHTML='<form action="#" id="controlForm"'+hideDiv+'>'+'<div id="navLinks">'+'<a accesskey="t" id="toggle" href="javascript:toggle();">&#216;<\/a>'+'<a accesskey="z" id="prev" href="javascript:go(-1);">&laquo;<\/a>'+'<a accesskey="x" id="next" href="javascript:go(1);">&raquo;<\/a>'+'<div id="navList"'+hideList+'><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>'+'<\/div><\/form>';if(controlVis=='hidden'){var hidden=document.getElementById('navLinks');}else{var hidden=document.getElementById('jumplist');}
- addClass(hidden,'hideme');}
- function fontScale(){if(!s5mode)return false;var vScale=22;var hScale=32;if(window.innerHeight){var vSize=window.innerHeight;var hSize=window.innerWidth;}else if(document.documentElement.clientHeight){var vSize=document.documentElement.clientHeight;var hSize=document.documentElement.clientWidth;}else if(document.body.clientHeight){var vSize=document.body.clientHeight;var hSize=document.body.clientWidth;}else{var vSize=700;var hSize=1024;}
- var newSize=Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));fontSize(newSize+'px');if(isGe){var obj=document.getElementsByTagName('body')[0];obj.style.display='none';obj.style.display='block';}}
- function fontSize(value){if(!(s5ss=document.getElementById('s5ss'))){if(!isIE){document.getElementsByTagName('head')[0].appendChild(s5ss=document.createElement('style'));s5ss.setAttribute('media','screen, projection');s5ss.setAttribute('id','s5ss');}else{document.createStyleSheet();document.s5ss=document.styleSheets[document.styleSheets.length-1];}}
- if(!isIE){while(s5ss.lastChild)s5ss.removeChild(s5ss.lastChild);s5ss.appendChild(document.createTextNode('body {font-size: '+value+' !important;}'));}else{document.s5ss.addRule('body','font-size: '+value+' !important;');}}
- function notOperaFix(){slideCSS=document.getElementById('slideProj').href;var slides=document.getElementById('slideProj');var outline=document.getElementById('outlineStyle');slides.setAttribute('media','screen');outline.disabled=true;if(isGe){slides.setAttribute('href','null');slides.setAttribute('href',slideCSS);}
- if(isIE&&document.styleSheets&&document.styleSheets[0]){document.styleSheets[0].addRule('img','behavior: url(ui/default/iepngfix.htc)');document.styleSheets[0].addRule('div','behavior: url(ui/default/iepngfix.htc)');document.styleSheets[0].addRule('.slide','behavior: url(ui/default/iepngfix.htc)');}}
- function getIncrementals(obj){var incrementals=new Array();if(!obj)
- return incrementals;var children=obj.childNodes;for(var i=0;i<children.length;i++){var child=children[i];if(hasClass(child,'incremental')){if(child.nodeName=='OL'||child.nodeName=='UL'){removeClass(child,'incremental');for(var j=0;j<child.childNodes.length;j++){if(child.childNodes[j].nodeType==1){addClass(child.childNodes[j],'incremental');}}}else{incrementals[incrementals.length]=child;removeClass(child,'incremental');}}
- if(hasClass(child,'show-first')){if(child.nodeName=='OL'||child.nodeName=='UL'){removeClass(child,'show-first');if(child.childNodes[isGe].nodeType==1){removeClass(child.childNodes[isGe],'incremental');}}else{incrementals[incrementals.length]=child;}}
- incrementals=incrementals.concat(getIncrementals(child));}
- return incrementals;}
- function createIncrementals(){var incrementals=new Array();for(var i=0;i<smax;i++){incrementals[i]=getIncrementals(document.getElementById('slide'+i));}
- return incrementals;}
- function defaultCheck(){var allMetas=document.getElementsByTagName('meta');for(var i=0;i<allMetas.length;i++){if(allMetas[i].name=='defaultView'){defaultView=allMetas[i].content;}
- if(allMetas[i].name=='controlVis'){controlVis=allMetas[i].content;}}}
- function trap(e){if(!e){e=event;e.which=e.keyCode;}
- try{modifierKey=e.ctrlKey||e.altKey||e.metaKey;}
- catch(e){modifierKey=false;}
- return modifierKey||e.which==0;}
- function startup(){defaultCheck();if(!isOp)
- createControls();slideLabel();fixLinks();externalLinks();fontScale();if(!isOp){notOperaFix();incrementals=createIncrementals();slideJump();if(defaultView=='outline'){toggle();}
- document.onkeyup=keys;document.onkeypress=trap;document.onclick=clicker;}}
- window.onload=startup;window.onresize=function(){setTimeout('fontScale()',50);}
- </script>
</head>
<body>
-<h1 class="title">My S5 Document</h1>
<div class="layout">
<div id="controls"></div>
<div id="currentSlide"></div>
<div id="header"></div>
<div id="footer">
-<h1
->July 15, 2006</h1
-><h2
->My S5 Document</h2
-></div>
+ <h1>July 15, 2006</h1>
+ <h2>My S5 Document</h2>
+</div>
</div>
<div class="presentation">
-
<div class="slide">
-<h1
->My S5 Document</h1
-><h3
->Sam Smith<br
- />Jen Jones</h3
-><h4
->July 15, 2006</h4
-></div>
+ <h1>My S5 Document</h1>
+ <h3>Sam Smith<br/>Jen Jones</h3>
+ <h4>July 15, 2006</h4>
+</div>
<div class="slide">
<h1
>First slide</h1
@@ -517,4 +258,3 @@
</div>
</body>
</html>
-
diff --git a/tests/s5.fragment.html b/tests/s5.fragment.html
index 6ab704d41..cc111566a 100644
--- a/tests/s5.fragment.html
+++ b/tests/s5.fragment.html
@@ -1,45 +1,17 @@
-<div id="first-slide"
-><h1
- >First slide</h1
- ><ul
+<h1 id="first-slide"
+>First slide</h1
+><ul
+><li
+ >first bullet</li
><li
- >first bullet</li
- ><li
- >second bullet</li
- ></ul
- ></div
-><div id="math"
-><h1
- >Math</h1
- ><ul
- ><li
- ><span class="math"
- >\frac{<em
- >d</em
- >}{<em
- >dx</em
- >}<em
- >f</em
- >(<em
- >x</em
- >)=\lim<sub
- ><em
- >h</em
- > → 0</sub
- >\frac{<em
- >f</em
- >(<em
- >x</em
- >+<em
- >h</em
- >)-<em
- >f</em
- >(<em
- >x</em
- >)}{<em
- >h</em
- >}</span
- ></li
- ></ul
- ></div
->
+ >second bullet</li
+ ></ul
+><h1 id="math"
+>Math</h1
+><ul
+><li
+ ><span class="math"
+ >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</span
+ ></li
+ ></ul
+> \ No newline at end of file
diff --git a/tests/s5.inserts.html b/tests/s5.inserts.html
index efce03868..90014f2e6 100644
--- a/tests/s5.inserts.html
+++ b/tests/s5.inserts.html
@@ -11,54 +11,25 @@
STUFF INSERTED
</head>
<body>
-<h1 class="title">My S5 Document</h1>
STUFF INSERTED
-<div id="first-slide"
-><h1
- >First slide</h1
- ><ul
- ><li
- >first bullet</li
- ><li
- >second bullet</li
- ></ul
- ></div
-><div id="math"
-><h1
- >Math</h1
- ><ul
+<h1 class="title">My S5 Document</h1>
+<h1 id="first-slide"
+>First slide</h1
+><ul
+><li
+ >first bullet</li
><li
- ><span class="math"
- >\frac{<em
- >d</em
- >}{<em
- >dx</em
- >}<em
- >f</em
- >(<em
- >x</em
- >)=\lim<sub
- ><em
- >h</em
- > → 0</sub
- >\frac{<em
- >f</em
- >(<em
- >x</em
- >+<em
- >h</em
- >)-<em
- >f</em
- >(<em
- >x</em
- >)}{<em
- >h</em
- >}</span
- ></li
- ></ul
- ></div
+ >second bullet</li
+ ></ul
+><h1 id="math"
+>Math</h1
+><ul
+><li
+ ><span class="math"
+ >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</span
+ ></li
+ ></ul
>
STUFF INSERTED
</body>
</html>
-
diff --git a/tests/tables-rstsubset.native b/tests/tables-rstsubset.native
index f26e46e90..7941772b5 100644
--- a/tests/tables-rstsubset.native
+++ b/tests/tables-rstsubset.native
@@ -116,4 +116,3 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
, [ Plain [Str "row"] ]
, [ 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/tests/tables.docbook b/tests/tables.docbook
index 6483a97c0..a24964600 100644
--- a/tests/tables.docbook
+++ b/tests/tables.docbook
@@ -399,4 +399,4 @@
</td>
</tr>
</tbody>
-</informaltable>
+</informaltable> \ No newline at end of file
diff --git a/tests/tables.html b/tests/tables.html
index e4dd6be58..93944828c 100644
--- a/tests/tables.html
+++ b/tests/tables.html
@@ -298,4 +298,4 @@
></tr
></tbody
></table
->
+> \ No newline at end of file
diff --git a/tests/tables.latex b/tests/tables.latex
index 7f29b72c3..5dac8e2a0 100644
--- a/tests/tables.latex
+++ b/tests/tables.latex
@@ -175,4 +175,3 @@ Second
\\
\end{tabular}
\end{center}
-
diff --git a/tests/tables.markdown b/tests/tables.markdown
index a605137d1..95bcc667e 100644
--- a/tests/tables.markdown
+++ b/tests/tables.markdown
@@ -6,7 +6,7 @@ Simple table with caption:
123 123 123 123
1 1 1 1
- Table: Demonstration of simple table syntax.
+ : Demonstration of simple table syntax.
Simple table without caption:
@@ -24,7 +24,7 @@ Simple table indented two spaces:
123 123 123 123
1 1 1 1
- Table: Demonstration of simple table syntax.
+ : Demonstration of simple table syntax.
Multiline table with caption:
@@ -40,7 +40,7 @@ Multiline table with caption:
rows.
--------------------------------------------------------------
- Table: Here's the caption. It may span multiple lines.
+ : Here's the caption. It may span multiple lines.
Multiline table without caption:
@@ -74,6 +74,3 @@ Multiline table without column headers:
the blank line between
rows.
----------- ---------- ------------ --------------------------
-
-
-
diff --git a/tests/tables.mediawiki b/tests/tables.mediawiki
index 4836ecd79..d0e5c7b9e 100644
--- a/tests/tables.mediawiki
+++ b/tests/tables.mediawiki
@@ -209,4 +209,3 @@ Multiline table without column headers:
</tr>
</tbody>
</table>
-
diff --git a/tests/tables.native b/tests/tables.native
index 11304795c..8592831fe 100644
--- a/tests/tables.native
+++ b/tests/tables.native
@@ -113,4 +113,3 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
, [ 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 "."] ] ] ] ]
-
diff --git a/tests/tables.opendocument b/tests/tables.opendocument
index 6cbfa00eb..c071e526d 100644
--- a/tests/tables.opendocument
+++ b/tests/tables.opendocument
@@ -381,4 +381,4 @@
<text:p text:style-name="Table_20_Contents">Here's another one. Note the blank line between rows.</text:p>
</table:table-cell>
</table:table-row>
-</table:table>
+</table:table> \ No newline at end of file
diff --git a/tests/tables.plain b/tests/tables.plain
index a605137d1..95bcc667e 100644
--- a/tests/tables.plain
+++ b/tests/tables.plain
@@ -6,7 +6,7 @@ Simple table with caption:
123 123 123 123
1 1 1 1
- Table: Demonstration of simple table syntax.
+ : Demonstration of simple table syntax.
Simple table without caption:
@@ -24,7 +24,7 @@ Simple table indented two spaces:
123 123 123 123
1 1 1 1
- Table: Demonstration of simple table syntax.
+ : Demonstration of simple table syntax.
Multiline table with caption:
@@ -40,7 +40,7 @@ Multiline table with caption:
rows.
--------------------------------------------------------------
- Table: Here's the caption. It may span multiple lines.
+ : Here's the caption. It may span multiple lines.
Multiline table without caption:
@@ -74,6 +74,3 @@ Multiline table without column headers:
the blank line between
rows.
----------- ---------- ------------ --------------------------
-
-
-
diff --git a/tests/tables.rst b/tests/tables.rst
index c7c0c954d..25d5932ea 100644
--- a/tests/tables.rst
+++ b/tests/tables.rst
@@ -88,5 +88,3 @@ Multiline table without column headers:
| | | | the blank line between |
| | | | rows. |
+-------------+------------+--------------+----------------------------+
-
-
diff --git a/tests/tables.rtf b/tests/tables.rtf
index e7c1e9f60..011724967 100644
--- a/tests/tables.rtf
+++ b/tests/tables.rtf
@@ -357,4 +357,3 @@
}
\intbl\row}
{\pard \ql \f0 \sa180 \li0 \fi0 \par}
-
diff --git a/tests/tables.texinfo b/tests/tables.texinfo
index f18de7012..b82006f1a 100644
--- a/tests/tables.texinfo
+++ b/tests/tables.texinfo
@@ -156,4 +156,3 @@ Second
@tab 5.0
@tab Here's another one. Note the blank line between rows.
@end multitable
-
diff --git a/tests/tables.txt b/tests/tables.txt
index 62d431597..d70492262 100644
--- a/tests/tables.txt
+++ b/tests/tables.txt
@@ -24,10 +24,13 @@ Simple table indented two spaces:
123 123 123 123
1 1 1 1
- Table: Demonstration of simple table syntax.
+ : Demonstration of simple table syntax.
Multiline table with caption:
+: Here's the caption.
+It may span multiple lines.
+
---------------------------------------------------------------
Centered Left Right
Header Aligned Aligned Default aligned
@@ -39,9 +42,6 @@ Multiline table with caption:
the blank line between rows.
---------------------------------------------------------------
-Table: Here's the caption.
-It may span multiple lines.
-
Multiline table without caption:
---------------------------------------------------------------
diff --git a/tests/testsuite.native b/tests/testsuite.native
index 7560317c5..ced38537c 100644
--- a/tests/testsuite.native
+++ b/tests/testsuite.native
@@ -415,4 +415,3 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[ [ 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,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented",Str "."] ]
-
diff --git a/tests/writer.context b/tests/writer.context
index 288d6970c..2c53fde5c 100644
--- a/tests/writer.context
+++ b/tests/writer.context
@@ -906,4 +906,3 @@ This paragraph should not be part of the note, as it is not
indented.
\stoptext
-
diff --git a/tests/writer.docbook b/tests/writer.docbook
index f771bf4af..c17513cf9 100644
--- a/tests/writer.docbook
+++ b/tests/writer.docbook
@@ -1077,17 +1077,17 @@ Blah
</listitem>
<listitem>
<para>
- 2+2=4
+ 2 + 2 = 4
</para>
</listitem>
<listitem>
<para>
- <emphasis>x</emphasis> ∈ <emphasis>y</emphasis>
+ <emphasis>x</emphasis> ∈ <emphasis>y</emphasis>
</para>
</listitem>
<listitem>
<para>
- α ∧ ω
+ α ∧ ω
</para>
</listitem>
<listitem>
@@ -1103,13 +1103,13 @@ Blah
<listitem>
<para>
Here's some display math:
- \frac{<emphasis>d</emphasis>}{<emphasis>dx</emphasis>}<emphasis>f</emphasis>(<emphasis>x</emphasis>)=\lim<subscript><emphasis>h</emphasis> → 0</subscript>\frac{<emphasis>f</emphasis>(<emphasis>x</emphasis>+<emphasis>h</emphasis>)-<emphasis>f</emphasis>(<emphasis>x</emphasis>)}{<emphasis>h</emphasis>}
+ $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
</para>
</listitem>
<listitem>
<para>
Here's one that has a line break in it:
- α+ω × <emphasis>x</emphasis><superscript>2</superscript>.
+ α + ω × <emphasis>x</emphasis><superscript>2</superscript>.
</para>
</listitem>
</itemizedlist>
@@ -1462,5 +1462,3 @@ or here: &lt;http://example.com/&gt;
</para>
</section>
</article>
-
-
diff --git a/tests/writer.html b/tests/writer.html
index f41a8e60a..39ae2ebb7 100644
--- a/tests/writer.html
+++ b/tests/writer.html
@@ -13,119 +13,96 @@
<p
>This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.</p
><hr
- /><div id="headers"
-><h1
- >Headers</h1
- ><div id="level-2-with-an-embedded-link"
- ><h2
- >Level 2 with an <a href="/url"
- >embedded link</a
- ></h2
- ><div id="level-3-with-emphasis"
- ><h3
- >Level 3 with <em
- >emphasis</em
- ></h3
- ><div id="level-4"
- ><h4
- >Level 4</h4
- ><div id="level-5"
- ><h5
- >Level 5</h5
- ></div
- ></div
- ></div
- ></div
- ></div
-><div id="level-1"
-><h1
- >Level 1</h1
- ><div id="level-2-with-emphasis"
- ><h2
- >Level 2 with <em
- >emphasis</em
- ></h2
- ><div id="level-3"
- ><h3
- >Level 3</h3
- ><p
- >with no blank line</p
- ></div
- ></div
- ><div id="level-2"
- ><h2
- >Level 2</h2
- ><p
- >with no blank line</p
- ><hr
- /></div
- ></div
-><div id="paragraphs"
-><h1
- >Paragraphs</h1
- ><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
+ /><h1 id="headers"
+>Headers</h1
+><h2 id="level-2-with-an-embedded-link"
+>Level 2 with an <a href="/url"
+ >embedded link</a
+ ></h2
+><h3 id="level-3-with-emphasis"
+>Level 3 with <em
+ >emphasis</em
+ ></h3
+><h4 id="level-4"
+>Level 4</h4
+><h5 id="level-5"
+>Level 5</h5
+><h1 id="level-1"
+>Level 1</h1
+><h2 id="level-2-with-emphasis"
+>Level 2 with <em
+ >emphasis</em
+ ></h2
+><h3 id="level-3"
+>Level 3</h3
+><p
+>with no blank line</p
+><h2 id="level-2"
+>Level 2</h2
+><p
+>with no blank line</p
+><hr
+ /><h1 id="paragraphs"
+>Paragraphs</h1
+><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<br
+ />here.</p
+><hr
+ /><h1 id="block-quotes"
+>Block Quotes</h1
+><p
+>E-mail style:</p
+><blockquote
+><p
+ >This is a block quote. It is pretty short.</p
+ ></blockquote
+><blockquote
+><p
+ >Code in a block quote:</p
+ ><pre
+ ><code
+ >sub status {
+ print &quot;working&quot;;
+}
+</code
+ ></pre
><p
- >There should be a hard line break<br
- />here.</p
- ><hr
- /></div
-><div id="block-quotes"
-><h1
- >Block Quotes</h1
+ >A list:</p
+ ><ol style="list-style-type: decimal;"
+ ><li
+ >item one</li
+ ><li
+ >item two</li
+ ></ol
><p
- >E-mail style:</p
+ >Nested block quotes:</p
><blockquote
><p
- >This is a block quote. It is pretty short.</p
+ >nested</p
></blockquote
><blockquote
><p
- >Code in a block quote:</p
- ><pre
- ><code
- >sub status {
- print &quot;working&quot;;
-}
-</code
- ></pre
- ><p
- >A list:</p
- ><ol style="list-style-type: decimal;"
- ><li
- >item one</li
- ><li
- >item two</li
- ></ol
- ><p
- >Nested block quotes:</p
- ><blockquote
- ><p
- >nested</p
- ></blockquote
- ><blockquote
- ><p
- >nested</p
- ></blockquote
+ >nested</p
></blockquote
- ><p
- >This should not be a block quote: 2 &gt; 1.</p
- ><p
- >And a following paragraph.</p
- ><hr
- /></div
-><div id="code-blocks"
-><h1
- >Code Blocks</h1
- ><p
- >Code:</p
- ><pre
- ><code
- >---- (should be four hyphens)
+ ></blockquote
+><p
+>This should not be a block quote: 2 &gt; 1.</p
+><p
+>And a following paragraph.</p
+><hr
+ /><h1 id="code-blocks"
+>Code Blocks</h1
+><p
+>Code:</p
+><pre
+><code
+ >---- (should be four hyphens)
sub status {
print &quot;working&quot;;
@@ -133,540 +110,524 @@ sub status {
this code block is indented by one tab
</code
- ></pre
- ><p
- >And:</p
- ><pre
- ><code
- > this code block is indented by two tabs
+ ></pre
+><p
+>And:</p
+><pre
+><code
+ > this code block is indented by two tabs
These should not be escaped: \$ \\ \&gt; \[ \{
</code
- ></pre
- ><hr
- /></div
-><div id="lists"
-><h1
- >Lists</h1
- ><div id="unordered"
- ><h2
- >Unordered</h2
- ><p
- >Asterisks tight:</p
- ><ul
- ><li
- >asterisk 1</li
- ><li
- >asterisk 2</li
- ><li
- >asterisk 3</li
- ></ul
+ ></pre
+><hr
+ /><h1 id="lists"
+>Lists</h1
+><h2 id="unordered"
+>Unordered</h2
+><p
+>Asterisks tight:</p
+><ul
+><li
+ >asterisk 1</li
+ ><li
+ >asterisk 2</li
+ ><li
+ >asterisk 3</li
+ ></ul
+><p
+>Asterisks loose:</p
+><ul
+><li
+ ><p
+ >asterisk 1</p
+ ></li
+ ><li
+ ><p
+ >asterisk 2</p
+ ></li
+ ><li
+ ><p
+ >asterisk 3</p
+ ></li
+ ></ul
+><p
+>Pluses tight:</p
+><ul
+><li
+ >Plus 1</li
+ ><li
+ >Plus 2</li
+ ><li
+ >Plus 3</li
+ ></ul
+><p
+>Pluses loose:</p
+><ul
+><li
+ ><p
+ >Plus 1</p
+ ></li
+ ><li
+ ><p
+ >Plus 2</p
+ ></li
+ ><li
+ ><p
+ >Plus 3</p
+ ></li
+ ></ul
+><p
+>Minuses tight:</p
+><ul
+><li
+ >Minus 1</li
+ ><li
+ >Minus 2</li
+ ><li
+ >Minus 3</li
+ ></ul
+><p
+>Minuses loose:</p
+><ul
+><li
+ ><p
+ >Minus 1</p
+ ></li
+ ><li
+ ><p
+ >Minus 2</p
+ ></li
+ ><li
+ ><p
+ >Minus 3</p
+ ></li
+ ></ul
+><h2 id="ordered"
+>Ordered</h2
+><p
+>Tight:</p
+><ol style="list-style-type: decimal;"
+><li
+ >First</li
+ ><li
+ >Second</li
+ ><li
+ >Third</li
+ ></ol
+><p
+>and:</p
+><ol style="list-style-type: decimal;"
+><li
+ >One</li
+ ><li
+ >Two</li
+ ><li
+ >Three</li
+ ></ol
+><p
+>Loose using tabs:</p
+><ol style="list-style-type: decimal;"
+><li
+ ><p
+ >First</p
+ ></li
+ ><li
+ ><p
+ >Second</p
+ ></li
+ ><li
+ ><p
+ >Third</p
+ ></li
+ ></ol
+><p
+>and using spaces:</p
+><ol style="list-style-type: decimal;"
+><li
+ ><p
+ >One</p
+ ></li
+ ><li
+ ><p
+ >Two</p
+ ></li
+ ><li
+ ><p
+ >Three</p
+ ></li
+ ></ol
+><p
+>Multiple paragraphs:</p
+><ol style="list-style-type: decimal;"
+><li
+ ><p
+ >Item 1, graf one.</p
><p
- >Asterisks loose:</p
- ><ul
+ >Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.</p
+ ></li
+ ><li
+ ><p
+ >Item 2.</p
+ ></li
+ ><li
+ ><p
+ >Item 3.</p
+ ></li
+ ></ol
+><h2 id="nested"
+>Nested</h2
+><ul
+><li
+ >Tab<ul
><li
- ><p
- >asterisk 1</p
- ></li
- ><li
- ><p
- >asterisk 2</p
- ></li
- ><li
- ><p
- >asterisk 3</p
+ >Tab<ul
+ ><li
+ >Tab</li
+ ></ul
></li
></ul
- ><p
- >Pluses tight:</p
- ><ul
- ><li
- >Plus 1</li
- ><li
- >Plus 2</li
- ><li
- >Plus 3</li
- ></ul
- ><p
- >Pluses loose:</p
- ><ul
+ ></li
+ ></ul
+><p
+>Here’s another:</p
+><ol style="list-style-type: decimal;"
+><li
+ >First</li
+ ><li
+ >Second:<ul
><li
- ><p
- >Plus 1</p
- ></li
+ >Fee</li
><li
- ><p
- >Plus 2</p
- ></li
+ >Fie</li
><li
- ><p
- >Plus 3</p
- ></li
+ >Foe</li
></ul
- ><p
- >Minuses tight:</p
+ ></li
+ ><li
+ >Third</li
+ ></ol
+><p
+>Same thing but with paragraphs:</p
+><ol style="list-style-type: decimal;"
+><li
+ ><p
+ >First</p
+ ></li
+ ><li
+ ><p
+ >Second:</p
><ul
><li
- >Minus 1</li
+ >Fee</li
><li
- >Minus 2</li
+ >Fie</li
><li
- >Minus 3</li
+ >Foe</li
></ul
- ><p
- >Minuses loose:</p
+ ></li
+ ><li
+ ><p
+ >Third</p
+ ></li
+ ></ol
+><h2 id="tabs-and-spaces"
+>Tabs and spaces</h2
+><ul
+><li
+ ><p
+ >this is a list item indented with tabs</p
+ ></li
+ ><li
+ ><p
+ >this is a list item indented with spaces</p
><ul
><li
><p
- >Minus 1</p
- ></li
- ><li
- ><p
- >Minus 2</p
- ></li
- ><li
- ><p
- >Minus 3</p
- ></li
- ></ul
- ></div
- ><div id="ordered"
- ><h2
- >Ordered</h2
- ><p
- >Tight:</p
- ><ol style="list-style-type: decimal;"
- ><li
- >First</li
- ><li
- >Second</li
- ><li
- >Third</li
- ></ol
- ><p
- >and:</p
- ><ol style="list-style-type: decimal;"
- ><li
- >One</li
- ><li
- >Two</li
- ><li
- >Three</li
- ></ol
- ><p
- >Loose using tabs:</p
- ><ol style="list-style-type: decimal;"
- ><li
- ><p
- >First</p
- ></li
- ><li
- ><p
- >Second</p
- ></li
- ><li
- ><p
- >Third</p
- ></li
- ></ol
- ><p
- >and using spaces:</p
- ><ol style="list-style-type: decimal;"
- ><li
- ><p
- >One</p
- ></li
- ><li
- ><p
- >Two</p
- ></li
- ><li
- ><p
- >Three</p
- ></li
- ></ol
- ><p
- >Multiple paragraphs:</p
- ><ol style="list-style-type: decimal;"
- ><li
- ><p
- >Item 1, graf one.</p
- ><p
- >Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.</p
- ></li
- ><li
- ><p
- >Item 2.</p
+ >this is an example list item indented with tabs</p
></li
><li
><p
- >Item 3.</p
- ></li
- ></ol
- ></div
- ><div id="nested"
- ><h2
- >Nested</h2
- ><ul
- ><li
- >Tab<ul
- ><li
- >Tab<ul
- ><li
- >Tab</li
- ></ul
- ></li
- ></ul
+ >this is an example list item indented with spaces</p
></li
></ul
+ ></li
+ ></ul
+><h2 id="fancy-list-markers"
+>Fancy list markers</h2
+><ol start="2" style="list-style-type: decimal;"
+><li
+ >begins with 2</li
+ ><li
+ ><p
+ >and now 3</p
><p
- >Here’s another:</p
- ><ol style="list-style-type: decimal;"
- ><li
- >First</li
- ><li
- >Second:<ul
- ><li
- >Fee</li
- ><li
- >Fie</li
- ><li
- >Foe</li
- ></ul
- ></li
- ><li
- >Third</li
- ></ol
- ><p
- >Same thing but with paragraphs:</p
- ><ol style="list-style-type: decimal;"
- ><li
- ><p
- >First</p
- ></li
- ><li
- ><p
- >Second:</p
- ><ul
- ><li
- >Fee</li
- ><li
- >Fie</li
- ><li
- >Foe</li
- ></ul
- ></li
- ><li
- ><p
- >Third</p
- ></li
- ></ol
- ></div
- ><div id="tabs-and-spaces"
- ><h2
- >Tabs and spaces</h2
- ><ul
- ><li
- ><p
- >this is a list item indented with tabs</p
- ></li
- ><li
- ><p
- >this is a list item indented with spaces</p
- ><ul
- ><li
- ><p
- >this is an example list item indented with tabs</p
- ></li
- ><li
- ><p
- >this is an example list item indented with spaces</p
- ></li
- ></ul
- ></li
- ></ul
- ></div
- ><div id="fancy-list-markers"
- ><h2
- >Fancy list markers</h2
- ><ol start="2" style="list-style-type: decimal;"
+ >with a continuation</p
+ ><ol start="4" style="list-style-type: lower-roman;"
><li
- >begins with 2</li
+ >sublist with roman numerals, starting with 4</li
><li
- ><p
- >and now 3</p
- ><p
- >with a continuation</p
- ><ol start="4" style="list-style-type: lower-roman;"
+ >more items<ol style="list-style-type: upper-alpha;"
><li
- >sublist with roman numerals, starting with 4</li
+ >a subsublist</li
><li
- >more items<ol style="list-style-type: upper-alpha;"
- ><li
- >a subsublist</li
- ><li
- >a subsublist</li
- ></ol
- ></li
+ >a subsublist</li
></ol
></li
></ol
- ><p
- >Nesting:</p
- ><ol style="list-style-type: upper-alpha;"
+ ></li
+ ></ol
+><p
+>Nesting:</p
+><ol style="list-style-type: upper-alpha;"
+><li
+ >Upper Alpha<ol style="list-style-type: upper-roman;"
><li
- >Upper Alpha<ol style="list-style-type: upper-roman;"
+ >Upper Roman.<ol start="6" style="list-style-type: decimal;"
><li
- >Upper Roman.<ol start="6" style="list-style-type: decimal;"
+ >Decimal start with 6<ol start="3" style="list-style-type: lower-alpha;"
><li
- >Decimal start with 6<ol start="3" style="list-style-type: lower-alpha;"
- ><li
- >Lower alpha with paren</li
- ></ol
- ></li
+ >Lower alpha with paren</li
></ol
></li
></ol
></li
></ol
- ><p
- >Autonumbering:</p
- ><ol
+ ></li
+ ></ol
+><p
+>Autonumbering:</p
+><ol
+><li
+ >Autonumber.</li
+ ><li
+ >More.<ol
><li
- >Autonumber.</li
- ><li
- >More.<ol
- ><li
- >Nested.</li
- ></ol
- ></li
+ >Nested.</li
></ol
- ><p
- >Should not be a list item:</p
- ><p
- >M.A. 2007</p
- ><p
- >B. Williams</p
- ><hr
- /></div
- ></div
-><div id="definition-lists"
-><h1
- >Definition Lists</h1
- ><p
- >Tight using spaces:</p
- ><dl
+ ></li
+ ></ol
+><p
+>Should not be a list item:</p
+><p
+>M.A. 2007</p
+><p
+>B. Williams</p
+><hr
+ /><h1 id="definition-lists"
+>Definition Lists</h1
+><p
+>Tight using spaces:</p
+><dl
+><dt
+ >apple</dt
+ ><dd
+ >red fruit</dd
><dt
- >apple</dt
- ><dd
- >red fruit</dd
- ><dt
- >orange</dt
- ><dd
- >orange fruit</dd
- ><dt
- >banana</dt
- ><dd
- >yellow fruit</dd
- ></dl
- ><p
- >Tight using tabs:</p
- ><dl
+ >orange</dt
+ ><dd
+ >orange fruit</dd
><dt
- >apple</dt
- ><dd
- >red fruit</dd
- ><dt
- >orange</dt
- ><dd
- >orange fruit</dd
- ><dt
- >banana</dt
- ><dd
- >yellow fruit</dd
- ></dl
- ><p
- >Loose:</p
- ><dl
+ >banana</dt
+ ><dd
+ >yellow fruit</dd
+ ></dl
+><p
+>Tight using tabs:</p
+><dl
+><dt
+ >apple</dt
+ ><dd
+ >red fruit</dd
><dt
- >apple</dt
- ><dd
- ><p
- >red fruit</p
- ></dd
- ><dt
- >orange</dt
- ><dd
- ><p
- >orange fruit</p
- ></dd
- ><dt
- >banana</dt
- ><dd
- ><p
- >yellow fruit</p
- ></dd
- ></dl
- ><p
- >Multiple blocks with italics:</p
- ><dl
+ >orange</dt
+ ><dd
+ >orange fruit</dd
><dt
- ><em
- >apple</em
- ></dt
- ><dd
- ><p
- >red fruit</p
- ><p
- >contains seeds, crisp, pleasant to taste</p
- ></dd
- ><dt
- ><em
- >orange</em
- ></dt
- ><dd
- ><p
- >orange fruit</p
- ><pre
- ><code
- >{ orange code block }
-</code
- ></pre
- ><blockquote
- ><p
- >orange block quote</p
- ></blockquote
- ></dd
- ></dl
- ><p
- >Multiple definitions, tight:</p
- ><dl
+ >banana</dt
+ ><dd
+ >yellow fruit</dd
+ ></dl
+><p
+>Loose:</p
+><dl
+><dt
+ >apple</dt
+ ><dd
+ ><p
+ >red fruit</p
+ ></dd
><dt
- >apple</dt
- ><dd
- >red fruit</dd
- ><dd
- >computer</dd
- ><dt
- >orange</dt
- ><dd
- >orange fruit</dd
- ><dd
- >bank</dd
- ></dl
+ >orange</dt
+ ><dd
><p
- >Multiple definitions, loose:</p
- ><dl
+ >orange fruit</p
+ ></dd
><dt
- >apple</dt
- ><dd
- ><p
- >red fruit</p
- ></dd
- ><dd
- ><p
- >computer</p
- ></dd
- ><dt
- >orange</dt
- ><dd
- ><p
- >orange fruit</p
- ></dd
- ><dd
- ><p
- >bank</p
- ></dd
- ></dl
- ><p
- >Blank line after term, indented marker, alternate markers:</p
- ><dl
+ >banana</dt
+ ><dd
+ ><p
+ >yellow fruit</p
+ ></dd
+ ></dl
+><p
+>Multiple blocks with italics:</p
+><dl
+><dt
+ ><em
+ >apple</em
+ ></dt
+ ><dd
+ ><p
+ >red fruit</p
+ ><p
+ >contains seeds, crisp, pleasant to taste</p
+ ></dd
><dt
- >apple</dt
- ><dd
- ><p
- >red fruit</p
- ></dd
- ><dd
- ><p
- >computer</p
- ></dd
- ><dt
- >orange</dt
- ><dd
+ ><em
+ >orange</em
+ ></dt
+ ><dd
+ ><p
+ >orange fruit</p
+ ><pre
+ ><code
+ >{ orange code block }
+</code
+ ></pre
+ ><blockquote
><p
- >orange fruit</p
- ><ol style="list-style-type: decimal;"
- ><li
- >sublist</li
- ><li
- >sublist</li
- ></ol
- ></dd
- ></dl
- ></div
-><div id="html-blocks"
-><h1
- >HTML Blocks</h1
+ >orange block quote</p
+ ></blockquote
+ ></dd
+ ></dl
+><p
+>Multiple definitions, tight:</p
+><dl
+><dt
+ >apple</dt
+ ><dd
+ >red fruit</dd
+ ><dd
+ >computer</dd
+ ><dt
+ >orange</dt
+ ><dd
+ >orange fruit</dd
+ ><dd
+ >bank</dd
+ ></dl
+><p
+>Multiple definitions, loose:</p
+><dl
+><dt
+ >apple</dt
+ ><dd
+ ><p
+ >red fruit</p
+ ></dd
+ ><dd
+ ><p
+ >computer</p
+ ></dd
+ ><dt
+ >orange</dt
+ ><dd
+ ><p
+ >orange fruit</p
+ ></dd
+ ><dd
+ ><p
+ >bank</p
+ ></dd
+ ></dl
+><p
+>Blank line after term, indented marker, alternate markers:</p
+><dl
+><dt
+ >apple</dt
+ ><dd
+ ><p
+ >red fruit</p
+ ></dd
+ ><dd
+ ><p
+ >computer</p
+ ></dd
+ ><dt
+ >orange</dt
+ ><dd
><p
- >Simple block on one line:</p
- ><div>foo</div>
+ >orange fruit</p
+ ><ol style="list-style-type: decimal;"
+ ><li
+ >sublist</li
+ ><li
+ >sublist</li
+ ></ol
+ ></dd
+ ></dl
+><h1 id="html-blocks"
+>HTML Blocks</h1
+><p
+>Simple block on one line:</p
+><div>foo</div>
<p
- >And nested without indentation:</p
- ><div>
+>And nested without indentation:</p
+><div>
<div>
<div>foo</div>
</div>
<div>bar</div>
</div>
<p
- >Interpreted markdown in a table:</p
- ><table>
+>Interpreted markdown in a table:</p
+><table>
<tr>
<td>This is <em
- >emphasized</em
- ></td>
+>emphasized</em
+></td>
<td>And this is <strong
- >strong</strong
- ></td>
+>strong</strong
+></td>
</tr>
</table>
<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>
<p
- >Here’s a simple block:</p
- ><div>
+>Here’s a simple block:</p
+><div>
foo</div>
<p
- >This should be a code block, though:</p
- ><pre
- ><code
- >&lt;div&gt;
+>This should be a code block, though:</p
+><pre
+><code
+ >&lt;div&gt;
foo
&lt;/div&gt;
</code
- ></pre
- ><p
- >As should this:</p
- ><pre
- ><code
- >&lt;div&gt;foo&lt;/div&gt;
+ ></pre
+><p
+>As should this:</p
+><pre
+><code
+ >&lt;div&gt;foo&lt;/div&gt;
</code
- ></pre
- ><p
- >Now, nested:</p
- ><div>
+ ></pre
+><p
+>Now, nested:</p
+><div>
<div>
<div>
foo</div>
</div>
</div>
<p
- >This should just be an HTML comment:</p
- ><!-- Comment -->
+>This should just be an HTML comment:</p
+><!-- Comment -->
<p
- >Multiline:</p
- ><!--
+>Multiline:</p
+><!--
Blah
Blah
-->
@@ -675,25 +636,25 @@ Blah
This is another comment.
-->
<p
- >Code block:</p
- ><pre
- ><code
- >&lt;!-- Comment --&gt;
+>Code block:</p
+><pre
+><code
+ >&lt;!-- Comment --&gt;
</code
- ></pre
- ><p
- >Just plain comment, with trailing spaces on the line:</p
- ><!-- foo -->
+ ></pre
+><p
+>Just plain comment, with trailing spaces on the line:</p
+><!-- foo -->
<p
- >Code:</p
- ><pre
- ><code
- >&lt;hr /&gt;
+>Code:</p
+><pre
+><code
+ >&lt;hr /&gt;
</code
- ></pre
- ><p
- >Hr’s:</p
- ><hr>
+ ></pre
+><p
+>Hr’s:</p
+><hr>
<hr />
@@ -711,499 +672,454 @@ Blah
<hr class="foo" id="bar">
<hr
- /></div
-><div id="inline-markup"
-><h1
- >Inline Markup</h1
- ><p
+ /><h1 id="inline-markup"
+>Inline Markup</h1
+><p
+>This is <em
+ >emphasized</em
+ >, and so <em
+ >is this</em
+ >.</p
+><p
+>This is <strong
+ >strong</strong
+ >, and so <strong
+ >is this</strong
+ >.</p
+><p
+>An <em
+ ><a href="/url"
+ >emphasized link</a
+ ></em
+ >.</p
+><p
+><strong
+ ><em
+ >This is strong and em.</em
+ ></strong
+ ></p
+><p
+>So is <strong
+ ><em
+ >this</em
+ ></strong
+ > word.</p
+><p
+><strong
+ ><em
+ >This is strong and em.</em
+ ></strong
+ ></p
+><p
+>So is <strong
+ ><em
+ >this</em
+ ></strong
+ > word.</p
+><p
+>This is code: <code
+ >&gt;</code
+ >, <code
+ >$</code
+ >, <code
+ >\</code
+ >, <code
+ >\$</code
+ >, <code
+ >&lt;html&gt;</code
+ >.</p
+><p
+><span style="text-decoration: line-through;"
>This is <em
- >emphasized</em
- >, and so <em
- >is this</em
- >.</p
- ><p
- >This is <strong
- >strong</strong
- >, and so <strong
- >is this</strong
- >.</p
- ><p
- >An <em
- ><a href="/url"
- >emphasized link</a
- ></em
- >.</p
- ><p
- ><strong
- ><em
- >This is strong and em.</em
- ></strong
- ></p
- ><p
- >So is <strong
- ><em
- >this</em
- ></strong
- > word.</p
- ><p
- ><strong
+ >strikeout</em
+ >.</span
+ ></p
+><p
+>Superscripts: a<sup
+ >bc</sup
+ >d a<sup
+ ><em
+ >hello</em
+ ></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
+><hr
+ /><h1 id="smart-quotes-ellipses-dashes"
+>Smart quotes, ellipses, dashes</h1
+><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 “<a href="http://example.com/?foo=1&amp;bar=2"
+ >quoted link</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
+><hr
+ /><h1 id="latex"
+>LaTeX</h1
+><ul
+><li
+ ></li
+ ><li
+ ><span class="math"
+ >2 + 2 = 4</span
+ ></li
+ ><li
+ ><span class="math"
><em
- >This is strong and em.</em
- ></strong
- ></p
- ><p
- >So is <strong
+ >x</em
+ > ∈ <em
+ >y</em
+ ></span
+ ></li
+ ><li
+ ><span class="math"
+ >α ∧ ω</span
+ ></li
+ ><li
+ ><span class="math"
+ >223</span
+ ></li
+ ><li
+ ><span class="math"
><em
- >this</em
- ></strong
- > word.</p
- ><p
- >This is code: <code
- >&gt;</code
- >, <code
+ >p</em
+ ></span
+ >-Tree</li
+ ><li
+ >Here’s some display math: <br
+ /><span class="math"
+ >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</span
+ ><br
+ /></li
+ ><li
+ >Here’s one that has a line break in it: <span class="math"
+ >α + ω × <em
+ >x</em
+ ><sup
+ >2</sup
+ ></span
+ >.</li
+ ></ul
+><p
+>These shouldn’t be math:</p
+><ul
+><li
+ >To get the famous equation, write <code
+ >$e = mc^2$</code
+ >.</li
+ ><li
+ >$22,000 is a <em
+ >lot</em
+ > of money. So is $34,000. (It worked if “lot” is emphasized.)</li
+ ><li
+ >Shoes ($20) and socks ($5).</li
+ ><li
+ >Escaped <code
>$</code
- >, <code
- >\</code
- >, <code
- >\$</code
- >, <code
- >&lt;html&gt;</code
- >.</p
- ><p
- ><span style="text-decoration: line-through;"
- >This is <em
- >strikeout</em
- >.</span
- ></p
- ><p
- >Superscripts: a<sup
- >bc</sup
- >d a<sup
- ><em
- >hello</em
- ></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
- ><hr
- /></div
-><div id="smart-quotes-ellipses-dashes"
-><h1
- >Smart quotes, ellipses, dashes</h1
- ><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 “<a href="http://example.com/?foo=1&amp;bar=2"
- >quoted link</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
- ><hr
- /></div
-><div id="latex"
-><h1
- >LaTeX</h1
- ><ul
+ >: $73 <em
+ >this should be emphasized</em
+ > 23$.</li
+ ></ul
+><p
+>Here’s a LaTeX table:</p
+><p
+></p
+><hr
+ /><h1 id="special-characters"
+>Special Characters</h1
+><p
+>Here is some unicode:</p
+><ul
+><li
+ >I hat: Î</li
><li
- ></li
- ><li
- ><span class="math"
- >2+2=4</span
- ></li
- ><li
- ><span class="math"
- ><em
- >x</em
- > ∈ <em
- >y</em
- ></span
- ></li
- ><li
- ><span class="math"
- >α ∧ ω</span
- ></li
- ><li
- ><span class="math"
- >223</span
- ></li
- ><li
- ><span class="math"
- ><em
- >p</em
- ></span
- >-Tree</li
- ><li
- >Here’s some display math: <span class="math"
- >\frac{<em
- >d</em
- >}{<em
- >dx</em
- >}<em
- >f</em
- >(<em
- >x</em
- >)=\lim<sub
- ><em
- >h</em
- > → 0</sub
- >\frac{<em
- >f</em
- >(<em
- >x</em
- >+<em
- >h</em
- >)-<em
- >f</em
- >(<em
- >x</em
- >)}{<em
- >h</em
- >}</span
- ></li
- ><li
- >Here’s one that has a line break in it: <span class="math"
- >α+ω × <em
- >x</em
- ><sup
- >2</sup
- ></span
- >.</li
- ></ul
- ><p
- >These shouldn’t be math:</p
- ><ul
+ >o umlaut: ö</li
><li
- >To get the famous equation, write <code
- >$e = mc^2$</code
- >.</li
- ><li
- >$22,000 is a <em
- >lot</em
- > of money. So is $34,000. (It worked if “lot” is emphasized.)</li
- ><li
- >Shoes ($20) and socks ($5).</li
- ><li
- >Escaped <code
- >$</code
- >: $73 <em
- >this should be emphasized</em
- > 23$.</li
- ></ul
- ><p
- >Here’s a LaTeX table:</p
- ><p
- ></p
- ><hr
- /></div
-><div id="special-characters"
-><h1
- >Special Characters</h1
- ><p
- >Here is some unicode:</p
- ><ul
+ >section: §</li
><li
- >I hat: Î</li
- ><li
- >o umlaut: ö</li
- ><li
- >section: §</li
- ><li
- >set membership: ∈</li
- ><li
- >copyright: ©</li
- ></ul
- ><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
- ><hr
- /></div
-><div id="links"
-><h1
- >Links</h1
- ><div id="explicit"
- ><h2
- >Explicit</h2
- ><p
- >Just a <a href="/url/"
- >URL</a
- >.</p
- ><p
- ><a href="/url/" title="title"
- >URL and title</a
- >.</p
- ><p
- ><a href="/url/" title="title preceded by two spaces"
- >URL and title</a
- >.</p
- ><p
- ><a href="/url/" title="title preceded by a tab"
- >URL and title</a
- >.</p
- ><p
- ><a href="/url/" title="title with &quot;quotes&quot; in it"
- >URL and title</a
- ></p
- ><p
- ><a href="/url/" title="title with single quotes"
- >URL and title</a
- ></p
- ><p
- ><a href="/url/with_underscore"
- >with_underscore</a
- ></p
- ><p
- ><script type="text/javascript"
- >
+ >set membership: ∈</li
+ ><li
+ >copyright: ©</li
+ ></ul
+><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
+><hr
+ /><h1 id="links"
+>Links</h1
+><h2 id="explicit"
+>Explicit</h2
+><p
+>Just a <a href="/url/"
+ >URL</a
+ >.</p
+><p
+><a href="/url/" title="title"
+ >URL and title</a
+ >.</p
+><p
+><a href="/url/" title="title preceded by two spaces"
+ >URL and title</a
+ >.</p
+><p
+><a href="/url/" title="title preceded by a tab"
+ >URL and title</a
+ >.</p
+><p
+><a href="/url/" title="title with &quot;quotes&quot; in it"
+ >URL and title</a
+ ></p
+><p
+><a href="/url/" title="title with single quotes"
+ >URL and title</a
+ ></p
+><p
+><a href="/url/with_underscore"
+ >with_underscore</a
+ ></p
+><p
+><script type="text/javascript"
+ >
<!--
h='&#110;&#x6f;&#x77;&#104;&#x65;&#114;&#x65;&#46;&#110;&#x65;&#116;';a='&#64;';n='&#110;&#x6f;&#98;&#x6f;&#100;&#x79;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+'Email link'+'<\/'+'a'+'>');
// -->
</script
- ><noscript
- >&#x45;&#x6d;&#x61;&#x69;&#108;&#32;&#108;&#x69;&#110;&#x6b;&#32;&#40;&#110;&#x6f;&#98;&#x6f;&#100;&#x79;&#32;&#x61;&#116;&#32;&#110;&#x6f;&#x77;&#104;&#x65;&#114;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#110;&#x65;&#116;&#x29;</noscript
- ></p
- ><p
- ><a href=""
- >Empty</a
- >.</p
- ></div
- ><div id="reference"
- ><h2
- >Reference</h2
- ><p
- >Foo <a href="/url/"
- >bar</a
- >.</p
- ><p
- >Foo <a href="/url/"
- >bar</a
- >.</p
- ><p
- >Foo <a href="/url/"
- >bar</a
- >.</p
- ><p
- >With <a href="/url/"
- >embedded [brackets]</a
- >.</p
- ><p
- ><a href="/url/"
- >b</a
- > by itself should be a link.</p
- ><p
- >Indented <a href="/url"
- >once</a
- >.</p
- ><p
- >Indented <a href="/url"
- >twice</a
- >.</p
- ><p
- >Indented <a href="/url"
- >thrice</a
- >.</p
- ><p
- >This should [not][] be a link.</p
- ><pre
- ><code
- >[not]: /url
+ ><noscript
+ >&#x45;&#x6d;&#x61;&#x69;&#108;&#32;&#108;&#x69;&#110;&#x6b;&#32;&#40;&#110;&#x6f;&#98;&#x6f;&#100;&#x79;&#32;&#x61;&#116;&#32;&#110;&#x6f;&#x77;&#104;&#x65;&#114;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#110;&#x65;&#116;&#x29;</noscript
+ ></p
+><p
+><a href=""
+ >Empty</a
+ >.</p
+><h2 id="reference"
+>Reference</h2
+><p
+>Foo <a href="/url/"
+ >bar</a
+ >.</p
+><p
+>Foo <a href="/url/"
+ >bar</a
+ >.</p
+><p
+>Foo <a href="/url/"
+ >bar</a
+ >.</p
+><p
+>With <a href="/url/"
+ >embedded [brackets]</a
+ >.</p
+><p
+><a href="/url/"
+ >b</a
+ > by itself should be a link.</p
+><p
+>Indented <a href="/url"
+ >once</a
+ >.</p
+><p
+>Indented <a href="/url"
+ >twice</a
+ >.</p
+><p
+>Indented <a href="/url"
+ >thrice</a
+ >.</p
+><p
+>This should [not][] be a link.</p
+><pre
+><code
+ >[not]: /url
</code
- ></pre
- ><p
- >Foo <a href="/url/" title="Title with &quot;quotes&quot; inside"
- >bar</a
- >.</p
- ><p
- >Foo <a href="/url/" title="Title with &quot;quote&quot; inside"
- >biz</a
- >.</p
- ></div
- ><div id="with-ampersands"
- ><h2
- >With ampersands</h2
- ><p
- >Here’s a <a href="http://example.com/?foo=1&amp;bar=2"
- >link with an ampersand in the URL</a
- >.</p
- ><p
- >Here’s a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T"
- >AT&amp;T</a
- >.</p
- ><p
- >Here’s an <a href="/script?foo=1&amp;bar=2"
- >inline link</a
- >.</p
- ><p
- >Here’s an <a href="/script?foo=1&amp;bar=2"
- >inline link in pointy braces</a
- >.</p
- ></div
- ><div id="autolinks"
- ><h2
- >Autolinks</h2
- ><p
- >With an ampersand: <a href="http://example.com/?foo=1&amp;bar=2"
- ><code
- >http://example.com/?foo=1&amp;bar=2</code
- ></a
- ></p
- ><ul
- ><li
- >In a list?</li
- ><li
- ><a href="http://example.com/"
- ><code
- >http://example.com/</code
- ></a
- ></li
- ><li
- >It should.</li
- ></ul
- ><p
- >An e-mail address: <script type="text/javascript"
- >
+ ></pre
+><p
+>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside"
+ >bar</a
+ >.</p
+><p
+>Foo <a href="/url/" title="Title with &quot;quote&quot; inside"
+ >biz</a
+ >.</p
+><h2 id="with-ampersands"
+>With ampersands</h2
+><p
+>Here’s a <a href="http://example.com/?foo=1&amp;bar=2"
+ >link with an ampersand in the URL</a
+ >.</p
+><p
+>Here’s a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T"
+ >AT&amp;T</a
+ >.</p
+><p
+>Here’s an <a href="/script?foo=1&amp;bar=2"
+ >inline link</a
+ >.</p
+><p
+>Here’s an <a href="/script?foo=1&amp;bar=2"
+ >inline link in pointy braces</a
+ >.</p
+><h2 id="autolinks"
+>Autolinks</h2
+><p
+>With an ampersand: <a href="http://example.com/?foo=1&amp;bar=2"
+ ><code
+ >http://example.com/?foo=1&amp;bar=2</code
+ ></a
+ ></p
+><ul
+><li
+ >In a list?</li
+ ><li
+ ><a href="http://example.com/"
+ ><code
+ >http://example.com/</code
+ ></a
+ ></li
+ ><li
+ >It should.</li
+ ></ul
+><p
+>An e-mail address: <script type="text/javascript"
+ >
<!--
h='&#110;&#x6f;&#x77;&#104;&#x65;&#114;&#x65;&#46;&#110;&#x65;&#116;';a='&#64;';n='&#110;&#x6f;&#98;&#x6f;&#100;&#x79;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+'<code>'+e+'</code>'+'<\/'+'a'+'>');
// -->
</script
- ><noscript
- >&#110;&#x6f;&#98;&#x6f;&#100;&#x79;&#32;&#x61;&#116;&#32;&#110;&#x6f;&#x77;&#104;&#x65;&#114;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#110;&#x65;&#116;</noscript
- ></p
- ><blockquote
- ><p
- >Blockquoted: <a href="http://example.com/"
- ><code
- >http://example.com/</code
- ></a
- ></p
- ></blockquote
- ><p
- >Auto-links should not occur here: <code
- >&lt;http://example.com/&gt;</code
- ></p
- ><pre
+ ><noscript
+ >&#110;&#x6f;&#98;&#x6f;&#100;&#x79;&#32;&#x61;&#116;&#32;&#110;&#x6f;&#x77;&#104;&#x65;&#114;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#110;&#x65;&#116;</noscript
+ ></p
+><blockquote
+><p
+ >Blockquoted: <a href="http://example.com/"
><code
- >or here: &lt;http://example.com/&gt;
+ >http://example.com/</code
+ ></a
+ ></p
+ ></blockquote
+><p
+>Auto-links should not occur here: <code
+ >&lt;http://example.com/&gt;</code
+ ></p
+><pre
+><code
+ >or here: &lt;http://example.com/&gt;
</code
- ></pre
- ><hr
- /></div
+ ></pre
+><hr
+ /><h1 id="images"
+>Images</h1
+><p
+>From “Voyage dans la Lune” by Georges Melies (1902):</p
+><div class="figure"
+><img src="lalune.jpg" title="Voyage dans la Lune" alt="lalune"
+ /><p class="caption"
+ >lalune</p
></div
-><div id="images"
-><h1
- >Images</h1
- ><p
- >From “Voyage dans la Lune” by Georges Melies (1902):</p
- ><div class="figure"
- ><img src="lalune.jpg" title="Voyage dans la Lune" alt="lalune"
- /><p class="caption"
- >lalune</p
- ></div
- ><p
- >Here is a movie <img src="movie.jpg" alt="movie"
- /> icon.</p
- ><hr
- /></div
-><div id="footnotes"
-><h1
- >Footnotes</h1
- ><p
- >Here is a footnote reference,<sup
- ><a href="#fn1" class="footnoteRef" id="fnref1"
- >1</a
- ></sup
- > and another.<sup
- ><a href="#fn2" class="footnoteRef" id="fnref2"
- >2</a
- ></sup
- > This should <em
- >not</em
- > be a footnote reference, because it contains a space.[^my note] Here is an inline note.<sup
- ><a href="#fn3" class="footnoteRef" id="fnref3"
- >3</a
+><p
+>Here is a movie <img src="movie.jpg" alt="movie"
+ /> icon.</p
+><hr
+ /><h1 id="footnotes"
+>Footnotes</h1
+><p
+>Here is a footnote reference,<sup
+ ><a href="#fn1" class="footnoteRef" id="fnref1"
+ >1</a
+ ></sup
+ > and another.<sup
+ ><a href="#fn2" class="footnoteRef" id="fnref2"
+ >2</a
+ ></sup
+ > This should <em
+ >not</em
+ > be a footnote reference, because it contains a space.[^my note] Here is an inline note.<sup
+ ><a href="#fn3" class="footnoteRef" id="fnref3"
+ >3</a
+ ></sup
+ ></p
+><blockquote
+><p
+ >Notes can go in quotes.<sup
+ ><a href="#fn4" class="footnoteRef" id="fnref4"
+ >4</a
></sup
></p
- ><blockquote
- ><p
- >Notes can go in quotes.<sup
- ><a href="#fn4" class="footnoteRef" id="fnref4"
- >4</a
- ></sup
- ></p
- ></blockquote
- ><ol style="list-style-type: decimal;"
- ><li
- >And in list items.<sup
- ><a href="#fn5" class="footnoteRef" id="fnref5"
- >5</a
- ></sup
- ></li
- ></ol
- ><p
- >This paragraph should not be part of the note, as it is not indented.</p
- ></div
+ ></blockquote
+><ol style="list-style-type: decimal;"
+><li
+ >And in list items.<sup
+ ><a href="#fn5" class="footnoteRef" id="fnref5"
+ >5</a
+ ></sup
+ ></li
+ ></ol
+><p
+>This paragraph should not be part of the note, as it is not indented.</p
><div class="footnotes"
><hr
/><ol
@@ -1247,4 +1163,3 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+'<code>'+e+'</code>'+'<\/'+
>
</body>
</html>
-
diff --git a/tests/writer.latex b/tests/writer.latex
index dbefdb8fd..1621a4844 100644
--- a/tests/writer.latex
+++ b/tests/writer.latex
@@ -1,5 +1,5 @@
\documentclass{article}
-\usepackage{amsmath}
+\usepackage{amssymb,amsmath}
\usepackage[mathletters]{ucs}
\usepackage[utf8x]{inputenc}
\usepackage{fancyvrb}
@@ -14,6 +14,15 @@
\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
\usepackage{url}
\usepackage{graphicx}
+% We will generate all images so they have a width \maxwidth. This means
+% that they will get their normal width if they fit onto the page, but
+% are scaled down if they would overflow the margins.
+\makeatletter
+\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth
+\else\Gin@nat@width\fi}
+\makeatother
+\let\Oldincludegraphics\includegraphics
+\renewcommand{\includegraphics}[1]{\Oldincludegraphics[width=\maxwidth]{#1}}
\usepackage[breaklinks=true,unicode=true]{hyperref}
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
@@ -855,4 +864,3 @@ This paragraph should not be part of the note, as it is not
indented.
\end{document}
-
diff --git a/tests/writer.man b/tests/writer.man
index 1048bc701..e4dc0c7de 100644
--- a/tests/writer.man
+++ b/tests/writer.man
@@ -50,12 +50,14 @@ It is pretty short.
.RS
.PP
Code in a block quote:
-.PP
-\f[CR]
- sub\ status\ {
- \ \ \ \ print\ "working";
- }
+.IP
+.nf
+\f[C]
+sub\ status\ {
+\ \ \ \ print\ "working";
+}
\f[]
+.fi
.PP
A list:
.IP "1." 3
@@ -82,24 +84,28 @@ And a following paragraph.
.SH Code Blocks
.PP
Code:
-.PP
-\f[CR]
- ----\ (should\ be\ four\ hyphens)
-
- sub\ status\ {
- \ \ \ \ print\ "working";
- }
-
- this\ code\ block\ is\ indented\ by\ one\ tab
+.IP
+.nf
+\f[C]
+----\ (should\ be\ four\ hyphens)
+
+sub\ status\ {
+\ \ \ \ print\ "working";
+}
+
+this\ code\ block\ is\ indented\ by\ one\ tab
\f[]
+.fi
.PP
And:
-.PP
-\f[CR]
- \ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
-
- These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{
+.IP
+.nf
+\f[C]
+\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
+
+These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{
\f[]
+.fi
.PP
* * * * *
.SH Lists
@@ -372,10 +378,12 @@ contains seeds, crisp, pleasant to taste
.B \f[I]orange\f[]
orange fruit
.RS
-.PP
-\f[CR]
- {\ orange\ code\ block\ }
+.IP
+.nf
+\f[C]
+{\ orange\ code\ block\ }
\f[]
+.fi
.RS
.PP
orange block quote
@@ -453,18 +461,22 @@ Here's a simple block:
foo
.PP
This should be a code block, though:
-.PP
-\f[CR]
- <div>
- \ \ \ \ foo
- </div>
+.IP
+.nf
+\f[C]
+<div>
+\ \ \ \ foo
+</div>
\f[]
+.fi
.PP
As should this:
-.PP
-\f[CR]
- <div>foo</div>
+.IP
+.nf
+\f[C]
+<div>foo</div>
\f[]
+.fi
.PP
Now, nested:
foo
@@ -474,18 +486,22 @@ This should just be an HTML comment:
Multiline:
.PP
Code block:
-.PP
-\f[CR]
- <!--\ Comment\ -->
+.IP
+.nf
+\f[C]
+<!--\ Comment\ -->
\f[]
+.fi
.PP
Just plain comment, with trailing spaces on the line:
.PP
Code:
-.PP
-\f[CR]
- <hr\ />
+.IP
+.nf
+\f[C]
+<hr\ />
\f[]
+.fi
.PP
Hr's:
.PP
@@ -506,8 +522,8 @@ So is \f[B]\f[I]this\f[]\f[] word.
.PP
So is \f[B]\f[I]this\f[]\f[] word.
.PP
-This is code: \f[B]>\f[], \f[B]$\f[], \f[B]\\\f[], \f[B]\\$\f[],
-\f[B]<html>\f[].
+This is code: \f[C]>\f[], \f[C]$\f[], \f[C]\\\f[], \f[C]\\$\f[],
+\f[C]<html>\f[].
.PP
[STRIKEOUT:This is \f[I]strikeout\f[].]
.PP
@@ -531,7 +547,7 @@ So is `pine.'
.PP
`He said, \[lq]I want to go.\[rq]' Were you alive in the 70's?
.PP
-Here is some quoted `\f[B]code\f[]' and a
+Here is some quoted `\f[C]code\f[]' and a
\[lq]quoted link (http://example.com/?foo=1&bar=2)\[rq].
.PP
Some dashes: one\[em]two \[em] three\[em]four \[em] five.
@@ -544,27 +560,26 @@ Ellipses\&...and\&...and\&....
.SH LaTeX
.IP \[bu] 2
.IP \[bu] 2
-\f[B]2+2=4\f[]
+2 + 2 = 4
.IP \[bu] 2
-\f[B]x\ \\in\ y\f[]
+\f[I]x\f[] ∈ \f[I]y\f[]
.IP \[bu] 2
-\f[B]\\alpha\ \\wedge\ \\omega\f[]
+α ∧ ω
.IP \[bu] 2
-\f[B]223\f[]
+223
.IP \[bu] 2
-\f[B]p\f[]-Tree
+\f[I]p\f[]-Tree
.IP \[bu] 2
Here's some display math:
.RS
-\f[B]\\frac{d}{dx}f(x)=\\lim_{h\\to\ 0}\\frac{f(x+h)-f(x)}{h}\f[]
+$\\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:
-\f[B]\\alpha\ +\ \\omega\ \\times\ x^2\f[].
+Here's one that has a line break in it: α + ω × \f[I]x\f[]^2^.
.PP
These shouldn't be math:
.IP \[bu] 2
-To get the famous equation, write \f[B]$e\ =\ mc^2$\f[].
+To get the famous equation, write \f[C]$e\ =\ mc^2$\f[].
.IP \[bu] 2
$22,000 is a \f[I]lot\f[] of money.
So is $34,000.
@@ -572,7 +587,7 @@ So is $34,000.
.IP \[bu] 2
Shoes ($20) and socks ($5).
.IP \[bu] 2
-Escaped \f[B]$\f[]: $73 \f[I]this should be emphasized\f[] 23$.
+Escaped \f[C]$\f[]: $73 \f[I]this should be emphasized\f[] 23$.
.PP
Here's a LaTeX table:
.PP
@@ -674,10 +689,12 @@ Indented twice (/url).
Indented thrice (/url).
.PP
This should [not][] be a link.
-.PP
-\f[CR]
- [not]:\ /url
+.IP
+.nf
+\f[C]
+[not]:\ /url
\f[]
+.fi
.PP
Foo bar (/url/).
.PP
@@ -709,11 +726,13 @@ An e-mail address: <nobody@nowhere.net>
Blockquoted: <http://example.com/>
.RE
.PP
-Auto-links should not occur here: \f[B]<http://example.com/>\f[]
-.PP
-\f[CR]
- or\ here:\ <http://example.com/>
+Auto-links should not occur here: \f[C]<http://example.com/>\f[]
+.IP
+.nf
+\f[C]
+or\ here:\ <http://example.com/>
\f[]
+.fi
.PP
* * * * *
.SH Images
@@ -754,10 +773,12 @@ This one contains multiple blocks.
.PP
Subsequent blocks are indented to show that they belong to the
footnote (as with list items).
-.PP
-\f[CR]
- \ \ {\ <code>\ }
+.IP
+.nf
+\f[C]
+\ \ {\ <code>\ }
\f[]
+.fi
.PP
If you want, you can indent every line, but you can also be lazy
and just indent the first line of each block.
@@ -765,7 +786,7 @@ and just indent the first line of each block.
.SS [3]
.PP
This is \f[I]easier\f[] to type.
-Inline notes may contain links (http://google.com) and \f[B]]\f[]
+Inline notes may contain links (http://google.com) and \f[C]]\f[]
verbatim characters, as well as [bracketed text].
.SS [4]
@@ -777,4 +798,3 @@ In quote.
In list.
.SH AUTHORS
John MacFarlane; Anonymous.
-
diff --git a/tests/writer.markdown b/tests/writer.markdown
index 1bc9b76f0..b417a8fee 100644
--- a/tests/writer.markdown
+++ b/tests/writer.markdown
@@ -3,7 +3,7 @@
% July 17, 2006
This is a set of tests for pandoc. Most of them are adapted from
-John Gruber's markdown test suite.
+John Gruber’s markdown test suite.
* * * * *
@@ -35,13 +35,13 @@ with no blank line
# Paragraphs
-Here's a regular paragraph.
+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 item.
-Here's one with a bullet. \* criminey.
+Here’s one with a bullet. \* criminey.
There should be a hard line break
here.
@@ -185,7 +185,7 @@ Multiple paragraphs:
1. Item 1, graf one.
- Item 1. graf two. The quick brown fox jumped over the lazy dog's
+ Item 1. graf two. The quick brown fox jumped over the lazy dog’s
back.
2. Item 2.
@@ -201,7 +201,7 @@ Multiple paragraphs:
-Here's another:
+Here’s another:
1. First
2. Second:
@@ -395,7 +395,7 @@ And this is **strong**
<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>
-Here's a simple block:
+Here’s a simple block:
<div>
@@ -450,7 +450,7 @@ Code:
<hr />
-Hr's:
+Hr’s:
<hr>
@@ -505,22 +505,22 @@ unescaped spaces: a\^b c\^d, a\~b c\~d.
# Smart quotes, ellipses, dashes
-"Hello," said the spider. "'Shelob' is my name."
+“Hello,” said the spider. “‘Shelob’ is my name.”
-'A', 'B', and 'C' are letters.
+‘A’, ‘B’, and ‘C’ are letters.
-'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
+‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’
-'He said, "I want to go."' Were you alive in the 70's?
+‘He said, “I want to go.”’ Were you alive in the 70’s?
-Here is some quoted '`code`' and a
-"[quoted link](http://example.com/?foo=1&bar=2)".
+Here is some quoted ‘`code`’ and a
+“[quoted link](http://example.com/?foo=1&bar=2)”.
-Some dashes: one--two -- three--four -- five.
+Some dashes: one—two — three—four — five.
-Dashes between numbers: 5-7, 255-66, 1987-1999.
+Dashes between numbers: 5–7, 255–66, 1987–1999.
-Ellipses...and...and....
+Ellipses…and…and….
* * * * *
@@ -533,20 +533,20 @@ Ellipses...and...and....
- $\alpha \wedge \omega$
- $223$
- $p$-Tree
-- Here's some display math:
+- Here’s some display math:
$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$
-- Here's one that has a line break in it:
+- Here’s one that has a line break in it:
$\alpha + \omega \times x^2$.
-These shouldn't be math:
+These shouldn’t be math:
- To get the famous equation, write `$e = mc^2$`.
-- $22,000 is a *lot* of money. So is $34,000. (It worked if "lot"
+- $22,000 is a *lot* of money. So is $34,000. (It worked if “lot”
is emphasized.)
- Shoes ($20) and socks ($5).
- Escaped `$`: $73 *this should be emphasized* 23$.
-Here's a LaTeX table:
+Here’s a LaTeX table:
\begin{tabular}{|l|l|}\hline
Animal & Number \\ \hline
@@ -662,15 +662,15 @@ Foo [biz](/url/ "Title with "quote" inside").
## With ampersands
-Here's a
+Here’s a
[link with an ampersand in the URL](http://example.com/?foo=1&bar=2).
-Here's a link with an amersand in the link text:
+Here’s a link with an amersand in the link text:
[AT&T](http://att.com/ "AT&T").
-Here's an [inline link](/script?foo=1&bar=2).
+Here’s an [inline link](/script?foo=1&bar=2).
-Here's an [inline link in pointy braces](/script?foo=1&bar=2).
+Here’s an [inline link in pointy braces](/script?foo=1&bar=2).
## Autolinks
@@ -693,7 +693,7 @@ Auto-links should not occur here: `<http://example.com/>`
# Images
-From "Voyage dans la Lune" by Georges Melies (1902):
+From “Voyage dans la Lune” by Georges Melies (1902):
![lalune](lalune.jpg "Voyage dans la Lune")
@@ -715,13 +715,12 @@ note] Here is an inline note.[^3]
This paragraph should not be part of the note, as it is not
indented.
-
[^1]:
Here is the footnote. It can go anywhere after the footnote
reference. It need not be placed at the end of the document.
[^2]:
- Here's the long note. This one contains multiple blocks.
+ Here’s the long note. This one contains multiple blocks.
Subsequent blocks are indented to show that they belong to the
footnote (as with list items).
@@ -741,5 +740,3 @@ indented.
[^5]:
In list.
-
-
diff --git a/tests/writer.mediawiki b/tests/writer.mediawiki
index 5873ea831..557396bfb 100644
--- a/tests/writer.mediawiki
+++ b/tests/writer.mediawiki
@@ -660,4 +660,3 @@ If you want, you can indent every line, but you can also be lazy and just indent
This paragraph should not be part of the note, as it is not indented.
<references />
-
diff --git a/tests/writer.native b/tests/writer.native
index 7560317c5..ced38537c 100644
--- a/tests/writer.native
+++ b/tests/writer.native
@@ -415,4 +415,3 @@ Pandoc (Meta {docTitle = [Str "Pandoc",Space,Str "Test",Space,Str "Suite"], docA
[ [ 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,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented",Str "."] ]
-
diff --git a/tests/writer.opendocument b/tests/writer.opendocument
index b10c5bef1..a08e5cf0a 100644
--- a/tests/writer.opendocument
+++ b/tests/writer.opendocument
@@ -689,30 +689,17 @@
<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>
- <style:style style:name="T62" 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="T62" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>
<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:text-position="sub 58%" /></style:style>
- <style:style style:name="T66" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>
- <style:style style:name="T67" style:family="text"><style:text-properties style:text-position="sub 58%" /></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 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 style:text-position="super 58%" /></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="T77" 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="T78" 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="T79" 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="T80" 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="T81" 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="T82" 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="T83" 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="T84" 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="T85" 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>
@@ -1317,13 +1304,13 @@
<text:p text:style-name="P51"><text:span text:style-name="Teletype">\cite[22-23]{smith.1899}</text:span></text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51">2+2=4</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="T58">x</text:span> ∈ <text:span text:style-name="T59">y</text:span></text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51">α ∧ ω</text:p>
+ <text:p text:style-name="P51">α ∧ ω</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="P51">223</text:p>
@@ -1332,10 +1319,10 @@
<text:p text:style-name="P51"><text:span text:style-name="T60">p</text:span>-Tree</text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51">Here&#8217;s some display math: \frac{<text:span text:style-name="T61">d</text:span>}{<text:span text:style-name="T62">dx</text:span>}<text:span text:style-name="T63">f</text:span>(<text:span text:style-name="T64">x</text:span>)=\lim<text:span text:style-name="T65">h</text:span><text:span text:style-name="T66"> → </text:span><text:span text:style-name="T67">0</text:span>\frac{<text:span text:style-name="T68">f</text:span>(<text:span text:style-name="T69">x</text:span>+<text:span text:style-name="T70">h</text:span>)-<text:span text:style-name="T71">f</text:span>(<text:span text:style-name="T72">x</text:span>)}{<text:span text:style-name="T73">h</text:span>}</text:p>
+ <text:p text:style-name="P51">Here&#8217;s some display math: $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P51">Here&#8217;s one that has a line break in it: α+ω × <text:span text:style-name="T74">x</text:span><text:span text:style-name="T75">2</text:span>.</text:p>
+ <text:p text:style-name="P51">Here&#8217;s one that has a line break in it: α + ω × <text:span text:style-name="T61">x</text:span><text:span text:style-name="T62">2</text:span>.</text:p>
</text:list-item>
</text:list>
<text:p text:style-name="Text_20_body">These shouldn&#8217;t be math:</text:p>
@@ -1344,13 +1331,13 @@
<text:p text:style-name="P52">To get the famous equation, write <text:span text:style-name="Teletype">$e = mc^2$</text:span>.</text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P52">$22,000 is a <text:span text:style-name="T76">lot</text:span> of money. So is $34,000. (It worked if &#8220;lot&#8221; is emphasized.)</text:p>
+ <text:p text:style-name="P52">$22,000 is a <text:span text:style-name="T63">lot</text:span> of money. So is $34,000. (It worked if &#8220;lot&#8221; is emphasized.)</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="P52">Shoes ($20) and socks ($5).</text:p>
</text:list-item>
<text:list-item>
- <text:p text:style-name="P52">Escaped <text:span text:style-name="Teletype">$</text:span>: $73 <text:span text:style-name="T77">this</text:span><text:span text:style-name="T78"> </text:span><text:span text:style-name="T79">should</text:span><text:span text:style-name="T80"> </text:span><text:span text:style-name="T81">be</text:span><text:span text:style-name="T82"> </text:span><text:span text:style-name="T83">emphasized</text:span> 23$.</text:p>
+ <text:p text:style-name="P52">Escaped <text:span text:style-name="Teletype">$</text:span>: $73 <text:span text:style-name="T64">this</text:span><text:span text:style-name="T65"> </text:span><text:span text:style-name="T66">should</text:span><text:span text:style-name="T67"> </text:span><text:span text:style-name="T68">be</text:span><text:span text:style-name="T69"> </text:span><text:span text:style-name="T70">emphasized</text:span> 23$.</text:p>
</text:list-item>
</text:list>
<text:p text:style-name="Text_20_body">Here&#8217;s a LaTeX table:</text:p>
@@ -1454,7 +1441,7 @@ Cat <text:s text:c="3" />&amp; 1 <text:s text:c="5" />\\ \hline
<text:p text:style-name="Text_20_body">Here is a movie <draw:frame><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame> icon.</text:p>
<text:p text:style-name="Horizontal_20_Line" />
<text:h text:style-name="Heading_20_1" text:outline-level="1">Footnotes</text:h>
-<text:p text:style-name="Text_20_body">Here is a footnote reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.</text:p></text:note-body></text:note> and another.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>2</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here&#8217;s the long note. This one contains multiple blocks.</text:p><text:p text:style-name="Footnote">Subsequent blocks are 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="T84">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="T85">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, as well as [bracketed text].</text:p></text:note-body></text:note></text:p>
+<text:p text:style-name="Text_20_body">Here is a footnote reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.</text:p></text:note-body></text:note> and another.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>2</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here&#8217;s the long note. This one contains multiple blocks.</text:p><text:p text:style-name="Footnote">Subsequent blocks are 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="T71">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="T72">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, as well as [bracketed text].</text:p></text:note-body></text:note></text:p>
<text:p text:style-name="P59">Notes can go in quotes.<text:note text:id="ftn3" text:note-class="footnote"><text:note-citation>4</text:note-citation><text:note-body><text:p text:style-name="Footnote">In quote.</text:p></text:note-body></text:note></text:p>
<text:list text:style-name="L30">
<text:list-item>
@@ -1465,4 +1452,3 @@ Cat <text:s text:c="3" />&amp; 1 <text:s text:c="5" />\\ \hline
</office:text>
</office:body>
</office:document-content>
-
diff --git a/tests/writer.plain b/tests/writer.plain
index 27ed0add9..bc6d25467 100644
--- a/tests/writer.plain
+++ b/tests/writer.plain
@@ -3,7 +3,7 @@ John MacFarlane; Anonymous
July 17, 2006
This is a set of tests for pandoc. Most of them are adapted from
-John Gruber's markdown test suite.
+John Gruber’s markdown test suite.
* * * * *
@@ -41,13 +41,13 @@ with no blank line
Paragraphs
==========
-Here's a regular paragraph.
+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 item.
-Here's one with a bullet. * criminey.
+Here’s one with a bullet. * criminey.
There should be a hard line break
here.
@@ -196,7 +196,7 @@ Multiple paragraphs:
1. Item 1, graf one.
- Item 1. graf two. The quick brown fox jumped over the lazy dog's
+ Item 1. graf two. The quick brown fox jumped over the lazy dog’s
back.
2. Item 2.
@@ -213,7 +213,7 @@ Nested
-Here's another:
+Here’s another:
1. First
2. Second:
@@ -388,7 +388,7 @@ Interpreted markdown in a table:
This is emphasized
And this is strong
-Here's a simple block:
+Here’s a simple block:
foo
This should be a code block, though:
@@ -418,7 +418,7 @@ Code:
<hr />
-Hr's:
+Hr’s:
* * * * *
@@ -457,21 +457,21 @@ unescaped spaces: a^b c^d, a~b c~d.
Smart quotes, ellipses, dashes
==============================
-"Hello," said the spider. "'Shelob' is my name."
+“Hello,” said the spider. “‘Shelob’ is my name.”
-'A', 'B', and 'C' are letters.
+‘A’, ‘B’, and ‘C’ are letters.
-'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
+‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’
-'He said, "I want to go."' Were you alive in the 70's?
+‘He said, “I want to go.”’ Were you alive in the 70’s?
-Here is some quoted 'code' and a "quoted link".
+Here is some quoted ‘code’ and a “quoted link”.
-Some dashes: one--two -- three--four -- five.
+Some dashes: one—two — three—four — five.
-Dashes between numbers: 5-7, 255-66, 1987-1999.
+Dashes between numbers: 5–7, 255–66, 1987–1999.
-Ellipses...and...and....
+Ellipses…and…and….
* * * * *
@@ -485,20 +485,20 @@ LaTeX
- \alpha \wedge \omega
- 223
- p-Tree
-- Here's some display math:
+- Here’s some display math:
\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}
-- Here's one that has a line break in it:
+- Here’s one that has a line break in it:
\alpha + \omega \times x^2.
-These shouldn't be math:
+These shouldn’t be math:
- To get the famous equation, write $e = mc^2$.
-- $22,000 is a lot of money. So is $34,000. (It worked if "lot"
+- $22,000 is a lot of money. So is $34,000. (It worked if “lot”
is emphasized.)
- Shoes ($20) and socks ($5).
- Escaped $: $73 this should be emphasized 23$.
-Here's a LaTeX table:
+Here’s a LaTeX table:
@@ -615,13 +615,13 @@ Foo biz.
With ampersands
---------------
-Here's a link with an ampersand in the URL.
+Here’s a link with an ampersand in the URL.
-Here's a link with an amersand in the link text: AT&T.
+Here’s a link with an amersand in the link text: AT&T.
-Here's an inline link.
+Here’s an inline link.
-Here's an inline link in pointy braces.
+Here’s an inline link in pointy braces.
Autolinks
---------
@@ -646,7 +646,7 @@ Auto-links should not occur here: <http://example.com/>
Images
======
-From "Voyage dans la Lune" by Georges Melies (1902):
+From “Voyage dans la Lune” by Georges Melies (1902):
@@ -669,13 +669,12 @@ Here is an inline note.[^3]
This paragraph should not be part of the note, as it is not
indented.
-
[^1]:
Here is the footnote. It can go anywhere after the footnote
reference. It need not be placed at the end of the document.
[^2]:
- Here's the long note. This one contains multiple blocks.
+ Here’s the long note. This one contains multiple blocks.
Subsequent blocks are indented to show that they belong to the
footnote (as with list items).
@@ -694,5 +693,3 @@ indented.
[^5]:
In list.
-
-
diff --git a/tests/writer.rst b/tests/writer.rst
index e68343b01..dff04bc81 100644
--- a/tests/writer.rst
+++ b/tests/writer.rst
@@ -10,7 +10,7 @@ Pandoc Test Suite
:format: html latex
This is a set of tests for pandoc. Most of them are adapted from
-John Gruber's markdown test suite.
+John Gruber’s markdown test suite.
--------------
@@ -50,13 +50,13 @@ with no blank line
Paragraphs
==========
-Here's a regular paragraph.
+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 item.
-Here's one with a bullet. \* criminey.
+Here’s one with a bullet. \* criminey.
There should be a hard line break
here.
@@ -224,7 +224,7 @@ Multiple paragraphs:
1. Item 1, graf one.
- Item 1. graf two. The quick brown fox jumped over the lazy dog's
+ Item 1. graf two. The quick brown fox jumped over the lazy dog’s
back.
2. Item 2.
@@ -244,7 +244,7 @@ Nested
-Here's another:
+Here’s another:
1. First
@@ -489,7 +489,7 @@ And this is **strong**
<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>
-Here's a simple block:
+Here’s a simple block:
.. raw:: html
@@ -575,7 +575,7 @@ Code:
<hr />
-Hr's:
+Hr’s:
.. raw:: html
@@ -635,22 +635,22 @@ unescaped spaces: a^b c^d, a~b c~d.
Smart quotes, ellipses, dashes
==============================
-"Hello," said the spider. "'Shelob' is my name."
+“Hello,” said the spider. “‘Shelob’ is my name.”
-'A', 'B', and 'C' are letters.
+‘A’, ‘B’, and ‘C’ are letters.
-'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
+‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’
-'He said, "I want to go."' Were you alive in the 70's?
+‘He said, “I want to go.”’ Were you alive in the 70’s?
-Here is some quoted '``code``' and a
-"`quoted link <http://example.com/?foo=1&bar=2>`_".
+Here is some quoted ‘``code``’ and a
+“`quoted link <http://example.com/?foo=1&bar=2>`_”.
-Some dashes: one--two -- three--four -- five.
+Some dashes: one—two — three—four — five.
-Dashes between numbers: 5-7, 255-66, 1987-1999.
+Dashes between numbers: 5–7, 255–66, 1987–1999.
-Ellipses...and...and....
+Ellipses…and…and….
--------------
@@ -664,21 +664,21 @@ LaTeX
- :math:`$\alpha \wedge \omega$`
- :math:`$223$`
- :math:`$p$`-Tree
-- Here's some display math:
+- Here’s some display math:
:math:`$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$`
-- Here's one that has a line break in it:
+- Here’s one that has a line break in it:
:math:`$\alpha + \omega \times x^2$`.
-These shouldn't be math:
+These shouldn’t be math:
- To get the famous equation, write ``$e = mc^2$``.
-- $22,000 is a *lot* of money. So is $34,000. (It worked if "lot"
+- $22,000 is a *lot* of money. So is $34,000. (It worked if “lot”
is emphasized.)
- Shoes ($20) and socks ($5).
- Escaped ``$``: $73 *this should be emphasized* 23$.
-Here's a LaTeX table:
+Here’s a LaTeX table:
@@ -796,15 +796,15 @@ Foo `biz </url/>`_.
With ampersands
---------------
-Here's a
+Here’s a
`link with an ampersand in the URL <http://example.com/?foo=1&bar=2>`_.
-Here's a link with an amersand in the link text:
+Here’s a link with an amersand in the link text:
`AT&T <http://att.com/>`_.
-Here's an `inline link </script?foo=1&bar=2>`_.
+Here’s an `inline link </script?foo=1&bar=2>`_.
-Here's an `inline link in pointy braces </script?foo=1&bar=2>`_.
+Here’s an `inline link in pointy braces </script?foo=1&bar=2>`_.
Autolinks
---------
@@ -832,7 +832,7 @@ Auto-links should not occur here: ``<http://example.com/>``
Images
======
-From "Voyage dans la Lune" by Georges Melies (1902):
+From “Voyage dans la Lune” by Georges Melies (1902):
.. figure:: lalune.jpg
:align: center
@@ -865,7 +865,7 @@ indented.
reference. It need not be placed at the end of the document.
.. [2]
- Here's the long note. This one contains multiple blocks.
+ Here’s the long note. This one contains multiple blocks.
Subsequent blocks are indented to show that they belong to the
footnote (as with list items).
@@ -888,6 +888,4 @@ indented.
.. [5]
In list.
-
.. |movie| image:: movie.jpg
-
diff --git a/tests/writer.rtf b/tests/writer.rtf
index ae3776261..3cb1d2996 100644
--- a/tests/writer.rtf
+++ b/tests/writer.rtf
@@ -264,13 +264,13 @@ quoted link
{\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par}
{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 LaTeX\par}
{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 2+2=4\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i x}\u8201?\u8712?\u8201?{\i y}\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \u945?\u8201?\u8743?\u8201?\u969?\par}
+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 2\u8197?+\u8197?2\u8196?=\u8196?4\par}
+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i x}\u8196?\u8712?\u8196?{\i y}\par}
+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \u945?\u8197?\u8743?\u8197?\u969?\par}
{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 223\par}
{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i p}-Tree\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's some display math: \\frac\{{\i d}\}\{{\i dx}\}{\i f}({\i x})=\\lim{\sub {\i h}\u8201?\u8594?\u8201?0}\\frac\{{\i f}({\i x}+{\i h})-{\i f}({\i x})\}\{{\i h}\}\par}
-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's one that has a line break in it: \u945?+\u969?\u8201?\u215?\u8201?{\i x}{\super 2}.\sa180\par}
+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's some display math: $\\frac\{d\}\{dx\}f(x)=\\lim_\{h\\to 0\}\\frac\{f(x+h)-f(x)\}\{h\}$\par}
+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's one that has a line break in it: \u945?\u8197?+\u8197?\u969?\u8197?\u215?\u8197?{\i x}{\super 2}.\sa180\par}
{\pard \ql \f0 \sa180 \li0 \fi0 These shouldn\u8217't be math:\par}
{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab To get the famous equation, write {\f1 $e = mc^2$}.\par}
{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab $22,000 is a {\i lot} of money. So is $34,000. (It worked if \u8220"lot\u8221" is emphasized.)\par}
@@ -450,4 +450,3 @@ links
}\sa180\par}
{\pard \ql \f0 \sa180 \li0 \fi0 This paragraph should not be part of the note, as it is not indented.\par}
}
-
diff --git a/tests/writer.texinfo b/tests/writer.texinfo
index 149b5a737..3344845b0 100644
--- a/tests/writer.texinfo
+++ b/tests/writer.texinfo
@@ -1014,4 +1014,3 @@ And in list items.@footnote{In list.}
This paragraph should not be part of the note@comma{} as it is not indented.
@bye
-