diff options
141 files changed, 3096 insertions, 9726 deletions
@@ -59,6 +59,22 @@ Quick install cabal install pandoc-citeproc + By default `pandoc-citeproc` uses the "i;unicode-casemap" method + to sort bibliography entries (RFC 5051). If you would like to + use the locale-sensitive unicode collation algorithm instead, + specify the `unicode_collation` flag: + + cabal install pandoc-citeproc -funicode_collation + + Note that this requires the `text-icu` library, which in turn + depends on the C library `icu4c`. Installation directions + vary by platform. Here is how it might work on OSX with homebrew: + + brew install icu4c + cabal install --extra-lib-dirs=/usr/local/Cellar/icu4c/51.1/lib \ + --extra-include-dirs=/usr/local/Cellar/icu4c/51.1/include \ + -funicode_collation text-icu pandoc-citeproc + [GHC]: http://www.haskell.org/ghc/ [Haskell platform]: http://hackage.haskell.org/platform/ [cabal-install]: http://hackage.haskell.org/trac/hackage/wiki/CabalInstall diff --git a/Interact.hs b/Interact.hs index 80b5a34f5..4d24904c5 100644 --- a/Interact.hs +++ b/Interact.hs @@ -9,6 +9,10 @@ -- You must have first done a 'cabal configure' or 'cabal install' +-- Note: Interact.hs doesn't work with Cabal >= 1.18. I recommend +-- using cabal sandboxes and the new 'cabal repl' command if you are +-- using a recent version. + import System.Process import Distribution.Simple.LocalBuildInfo import Distribution.Package @@ -108,7 +108,7 @@ to PDF: Production of a PDF requires that a LaTeX engine be installed (see `--latex-engine`, below), and assumes that the following LaTeX packages are available: `amssymb`, `amsmath`, `ifxetex`, `ifluatex`, `listings` (if the -`--listings` option is used), `fancyvrb`, `longtable`, `url`, +`--listings` option is used), `fancyvrb`, `longtable`, `booktabs`, `url`, `graphicx`, `hyperref`, `ulem`, `babel` (if the `lang` variable is set), `fontspec` (if `xelatex` or `lualatex` is used as the LaTeX engine), `xltxtra` and `xunicode` (if `xelatex` is used). @@ -278,17 +278,22 @@ Reader options Filters may be written in any language. `Text.Pandoc.JSON` exports `toJSONFilter` to facilitate writing filters in Haskell. Those who would prefer to write filters in python can use the - module `pandoc.py`: see <http://github.com/jgm/pandoc-filters-python> - for the module and several examples. Note that the *EXECUTABLE* - will be sought in the user's `PATH`, and not in the working directory, - if no directory is provided. If you want to run a script in the - working directory, preface the filename with `./`. + module `pandocfilters`, installable from PyPI. See + <http://github.com/jgm/pandocfilters> for the module and several + examples. Note that the *EXECUTABLE* will be sought in the user's + `PATH`, and not in the working directory, if no directory is + provided. If you want to run a script in the working directory, + preface the filename with `./`. `-M` *KEY[=VAL]*, `--metadata=`*KEY[:VAL]* -: Set the metadata field *KEY* to the value *VAL* after - parsing. A value specified on the command line overrides a value - specified in the document. Values will be interpreted as raw strings. - If no value is specified, the value will be treated as Boolean true. +: Set the metadata field *KEY* to the value *VAL*. A value specified + on the command line overrides a value specified in the document. + Values will be parsed as YAML boolean or string values. If no value is + specified, the value will be treated as Boolean true. Like + `--variable`, `--metadata` causes template variables to be set. + But unlike `--variable`, `--metadata` affects the metadata of the + underlying document (which is accessible from filters and may be + printed in some output formats). `--normalize` : Normalize the document after reading: merge adjacent @@ -429,8 +434,8 @@ Options affecting specific writers `--chapters` : Treat top-level headers as chapters in LaTeX, ConTeXt, and DocBook output. When the LaTeX template uses the report, book, or - memoir class, this option is implied. If `--beamer` is used, - top-level headers will become `\part{..}`. + memoir class, this option is implied. If `beamer` is the output + format, top-level headers will become `\part{..}`. `-N`, `--number-sections` : Number section headings in LaTeX, ConTeXt, HTML, or EPUB output. @@ -536,7 +541,9 @@ Options affecting specific writers `--epub-cover-image=`*FILE* : Use the specified image as the EPUB cover. It is recommended - that the image be less than 1000px in width and height. + that the image be less than 1000px in width and height. Note that + in a markdown source document you can also specify `cover-image` + in a YAML metadata block (see [EPUB Metadata], below). `--epub-metadata=`*FILE* : Look in the specified XML file for metadata for the EPUB. @@ -555,6 +562,10 @@ Options affecting specific writers id="BookId">` (a randomly generated UUID). Any of these may be overridden by elements in the metadata file. + Note: if the source document is markdown, a YAML metadata block + in the document can be used instead. See below under + [EPUB Metadata]. + `--epub-embed-font=`*FILE* : Embed the specified font in the EPUB. This option can be repeated to embed multiple fonts. To use embedded fonts, you @@ -606,10 +617,9 @@ Citation rendering `--bibliography=`*FILE* : Set the `bibliography` field in the document's metadata to *FILE*, - overriding any value set in the metadata, and tell pandoc to - use the `pandoc-citeproc` filter. (This is equivalent to the - combination `--metadata bibliography=FILE --filter pandoc-citeproc`.) - Note that an error will result unless `pandoc-citeproc` is installed. + overriding any value set in the metadata, and process citations + using `pandoc-citeproc`. (This is equivalent to + `--metadata bibliography=FILE --filter pandoc-citeproc`.) `--csl=`*FILE* : Set the `csl` field in the document's metadata to *FILE*, @@ -791,6 +801,8 @@ as `title`, `author`, and `date`) as well as the following: : causes links to be printed as footnotes in LaTeX documents `biblio-style` : bibliography style in LaTeX, when used with `--natbib` +`biblio-files` +: bibliography files to use in LaTeX, with `--natbib` or `--biblatex` `section` : section number in man pages `header` @@ -884,6 +896,9 @@ If you need a hard line break, put two or more spaces at the end of a line. **Extension: `escaped_line_breaks`** A backslash followed by a newline is also a hard line break. +Note: in multiline and grid table cells, this is the only way +to create a hard line break, since trailing spaces in the cells +are ignored. Headers ------- @@ -1267,7 +1282,7 @@ one tab: + pears + peaches * vegetables - + brocolli + + broccoli + chard As noted above, markdown allows you to write list items "lazily," instead of @@ -1833,6 +1848,18 @@ equivalent of the markdown in the `abstract` field: <p>This is the abstract.</p> <p>It consists of two paragraphs.</p> +Note: The `author` variable in the default templates expects a simple list or +string. To use the structured authors in the example, you would need a +custom template. For example: + + $for(author)$ + $if(author.name)$ + $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$ + $else$ + $author$ + $endif$ + $endfor$ + Backslash escapes ----------------- @@ -2081,7 +2108,7 @@ Raw HTML Markdown allows you to insert raw HTML (or DocBook) anywhere in a document (except verbatim contexts, where `<`, `>`, and `&` are interpreted -literally). (Techncially this is not an extension, since standard +literally). (Technically this is not an extension, since standard markdown allows it, but it has been made an extension so that it can be disabled if desired.) @@ -2454,6 +2481,10 @@ in pandoc, but may be enabled by adding `+EXTENSION` to the format name, where `EXTENSION` is the name of the extension. Thus, for example, `markdown+hard_line_breaks` is markdown with hard line breaks. +**Extension: `lists_without_preceding_blankline`**\ +Allow a list to occur right after a paragraph, with no intervening +blank space. + **Extension: `hard_line_breaks`**\ Causes all newlines within a paragraph to be interpreted as hard line breaks instead of spaces. @@ -2490,10 +2521,9 @@ the document, for example: Comment: This is a sample mmd title block, with a field spanning multiple lines. -See the MultiMarkdown documentation for details. Note that only title, -author, and date are recognized; other fields are simply ignored by -pandoc. If `pandoc_title_block` or `yaml_metadata_block` is enabled, -it will take precedence over `mmd_title_block`. +See the MultiMarkdown documentation for details. If `pandoc_title_block` or +`yaml_metadata_block` is enabled, it will take precedence over +`mmd_title_block`. [MultiMarkdown]: http://fletcherpenney.net/multimarkdown/ @@ -2551,6 +2581,20 @@ variants are supported: `markdown_strict` (Markdown.pl) : `raw_html` +Extensions with formats other than markdown +------------------------------------------- + +Some of the extensions discussed above can be used with formats +other than markdown: + +* `auto_identifiers` can be used with `latex`, `rst`, `mediawiki`, + and `textile` input (and is used by default). + +* `tex_math_dollars`, `tex_math_single_backslash`, and + `tex_math_double_backslash` can be used with `html` input. + (This is handy for reading web pages formatted using MathJax, + for example.) + Producing slide shows with Pandoc ================================= @@ -2676,9 +2720,8 @@ a single document. Inserting pauses ---------------- -In reveal.js and beamer slide shows, you can add "pauses" within -a slide by including a paragraph containing three dots, separated -by spaces: +You can add "pauses" within a slide by including a paragraph containing +three dots, separated by spaces: # Slide with a pause @@ -2724,11 +2767,99 @@ bibliographies: # References {.allowframebreaks} +Speaker notes +------------- + +reveal.js has good support for speaker notes. You can add notes to your +markdown document thus: + + <div class="notes"> + This is my note. + + - It can contain markdown + - like this list + + </div> + +To show the notes window, press `s` while viewing the presentation. +Notes are not yet supported for other slide formats, but the notes +will not appear on the slides themselves. + +EPUB Metadata +============= + +EPUB metadata may be specified using the `--epub-metadata` option, but +if the source document is markdown, it is better to use a YAML metadata +block. Here is an example: + + --- + title: + - type: main + text: My Book + - type: subtitle + text: An investigation of metadata + creator: + - role: author + text: John Smith + - role: editor + text: Sarah Jones + identifier: + - scheme: DOI + text: doi:10.234234.234/33 + publisher: My Press + rights: (c) 2007 John Smith, CC BY-NC + ... + +The following fields are recognized: + +`identifier` + ~ Either a string value or an object with fields `text` and + `scheme`. Valid values for `scheme` are `ISBN-10`, + `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`, + `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`, + `ISMN-13`, `ISBN-A`, `JP`, `OLCC`. +`title` + ~ Either a string value, or an object with fields `file-as` and + `type`, or a list of such objects. Valid values for `type` are + `main`, `subtitle`, `short`, `collection`, `edition`, `extended`. +`creator` + ~ Either a string value, or an object with fields `role`, `file-as`, + and `text`, or a list of such objects. Valid values for `role` are + [marc relators](http://www.loc.gov/marc/relators/relaterm.html), but + pandoc will attempt to translate the human-readable versions + (like "author" and "editor") to the appropriate marc relators. +`contributor` + ~ Same format as `creator`. +`date` + ~ A string value in `YYYY-MM-DD` format. (Only the year is necessary.) + Pandoc will attempt to convert other common date formats. +`language` + ~ A string value in [RFC5646] format. Pandoc will default to the local + language if nothing is specified. +`subject` + ~ A string value or a list of such values. +`description` + ~ A string value. +`type` + ~ A string value. +`format` + ~ A string value. +`relation` + ~ A string value. +`coverage` + ~ A string value. +`rights` + ~ A string value. +`cover-image` + ~ A string value (path to cover image). +`stylesheet` + ~ A string value (path to CSS stylesheet). + Literate Haskell support ======================== If you append `+lhs` (or `+literate_haskell`) to an appropriate input or output -format (`markdown`, `mardkown_strict`, `rst`, or `latex` for input or output; +format (`markdown`, `markdown_strict`, `rst`, or `latex` for input or output; `beamer`, `html` or `html5` for output only), pandoc will treat the document as literate Haskell source. This means that @@ -2834,5 +2965,6 @@ Jamie F. Olson. [PDF]: http://www.adobe.com/pdf/ [reveal.js]: http://lab.hakim.se/reveal-js/ [FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1 -[lua]: TODO - +[lua]: http://www.lua.org +[marc relators]: http://www.loc.gov/marc/relators/relaterm.html +[RFC5646]: http://tools.ietf.org/html/rfc5646 diff --git a/RELEASE-CHECKLIST b/RELEASE-CHECKLIST index 80a6738a5..af0102622 100644 --- a/RELEASE-CHECKLIST +++ b/RELEASE-CHECKLIST @@ -16,6 +16,8 @@ _ Upload to Google Code (googlecode-upload.sh) _ Go to Google code and deprecate the old versions +- Add release on github (and upload files) + _ Upload to HackageDB _ Update website, including short description of changes @@ -3,13 +3,15 @@ import Distribution.Simple import Distribution.Simple.PreProcess import Distribution.Simple.Setup - (copyDest, copyVerbosity, fromFlag, installVerbosity, BuildFlags(..)) + (copyDest, copyVerbosity, fromFlag, installVerbosity, BuildFlags(..), + TestFlags(..)) import Distribution.PackageDescription (PackageDescription(..), Executable(..)) import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..), absoluteInstallDirs) import Distribution.Verbosity ( Verbosity, silent ) -import Distribution.Simple.InstallDirs (mandir, CopyDest (NoCopyDest)) +import Distribution.Simple.InstallDirs (mandir, CopyDest (NoCopyDest), toPathTemplate) import Distribution.Simple.Utils (installOrdinaryFiles, info) +import Distribution.Simple.Test (test) import Prelude hiding (catch) import System.Process ( rawSystem ) import System.FilePath ( (</>) ) @@ -20,6 +22,10 @@ main :: IO () main = do defaultMainWithHooks $ simpleUserHooks { postBuild = makeManPages + , testHook = \pkg lbi _ flags -> + -- pass build directory as first argument to test program + test pkg lbi flags{ testOptions = + toPathTemplate (buildDir lbi) : testOptions flags } , postCopy = \ _ flags pkg lbi -> installManpages pkg lbi (fromFlag $ copyVerbosity flags) (fromFlag $ copyDest flags) diff --git a/benchmark/benchmark-pandoc.hs b/benchmark/benchmark-pandoc.hs index 60b543e1a..2eaaf91a1 100644 --- a/benchmark/benchmark-pandoc.hs +++ b/benchmark/benchmark-pandoc.hs @@ -31,7 +31,8 @@ main = do inp2 <- readFile "tests/testsuite.txt" let opts = def{ readerSmart = True } let doc = readMarkdown opts $ inp ++ unlines (drop 3 $ lines inp2) - let readerBs = map (readerBench doc) readers + let readerBs = map (readerBench doc) + $ filter (\(n,_) -> n /="haddock") readers let writers' = [(n,w) | (n, PureStringWriter w) <- writers] defaultMainWith conf (return ()) $ map (writerBench doc) writers' ++ readerBs @@ -1,18 +1,476 @@ -[pending release 1.12] +pandoc (1.12.3.1) + + * Relaxed version constraint on binary, allowing the use of binary 0.5. + +pandoc (1.12.3) + + * The `--bibliography` option now sets the `biblio-files` variable. + So, if you're using `--natbib` or `--biblatex`, you can just use + `--bibliography=foo.bib` instead of `-V bibliofiles=foo`. + + * Don't run pandoc-citeproc filter if `--bibliography` is + used together with `--natbib` or `--biblatex` (Florian Eitel). + + * Template changes: + + + Updated beamer template to include booktabs. + + Added `abstract` variable to LaTeX template. + + Put `header-includes` after `title` in LaTeX template (#908). + + Allow use of `\includegraphics[size]` in beamer. + This just required porting a macro definition from the default + LaTeX template to the default beamer template. + + * `reference.docx`: Include `FootnoteText` style. + Otherwise Word ignores the style, even when specified in the `pPr`. + (#901) + + * `reference.odt`: Tidied `styles.xml`. + + * Relaxed version bounds for dependencies. + + * Added `withSocketsDo` around http conduit code in `openURL`, + so it works on Windows (#1080). + + * Added `Cite` function to `sample.lua`. + + * Markdown reader: + + + Fixed regression in title blocks (#1089). + If author field was empty, date was being ignored. + + Allow backslash-newline hard line breaks in grid and + multiline table cells. + + Citation keys may now start with underscores, and may contain + underscores adjacent to internal punctuation. + + * LaTeX reader: + + + Add support for `Verb` macro (jrnold) (#1090). + + Support babel-style quoting: `` "`..."' ``. + + * Properly handle script blocks in strict mode. (That is, + `markdown-markdown_in_html_blocks`.) Previously a spurious + `<p>` tag was being added (#1093). + + * Docbook reader: Avoid failure if `tbody` contains no `tr` or `row` + elements. + + * LaTeX writer: + + + Factored out function for table cell creation. + + Better treatment of footnotes in tables. + Notes now appear in the regular sequence, rather than in the + table cell. (This was a regression in 1.10.) + + * HTML reader: Parse name/content pairs from meta tags as metadata. + Closes #1106. + + * Moved `fixDisplayMath` from Docx writer to `Writer.Shared`. + + * OpenDocument writer: Fixed `RawInline`, `RawBlock` so they don't escape. + + * ODT writer: Use mathml for proper rendering of formulas. + Note: LibreOffice's support for this seems a bit buggy. But + it should be better than what we had before. + + * RST writer: Ensure no blank line after def in definition list (#992). + + * Markdown writer: Don't use tilde code blocks with braced attributes in + `markdown_github` output. A consequence of this change is that the + backtick form will be preferred in general if both are enabled. That + is good, as it is much more widespread than the tilde form. (#1084) + + * Docx writer: Fixed problem with some modified reference docx files. + Include `word/_rels/settings.xml.rels` if it exists, as well as other + `rels` files besides the ones pandoc generates explicitly. + + * HTML writer: + + + With `--toc`, headers no longer link to themselves (#1081). + + Omit footnotes from TOC entries. Otherwise we get doubled + footnotes when headers have notes! + + * EPUB writer: + + + Avoid duplicate notes when headings contain notes. + This arose because the headings are copied into the metadata + "title" field, and the note gets rendered twice. We strip the + note now before putting the heading in "title". + + Strip out footnotes from toc entries. + + Fixed bug with `--epub-stylesheet`. Now the contents of + `writerEpubStylesheet` (set by `--epub-stylesheet`) + should again work, and take precedence over a stylesheet specified + in the metadata. + + * `Text.Pandoc.Pretty`: Added `nestle`. API change. + + * `Text.Pandoc.MIME`: Added `wmf`, `emf`. + + * `Text.Pandoc.Shared`: `fetchItem` now handles image URLs beginning + with `//`. + + * `Text.Pandoc.ImageSize`: Parse EXIF format JPEGs. Previously + we could only get size information for JFIF format, which led + to squished images in Word documents. Closes #976. + + * Removed old `MarkdownTest_1.0.3` directory (#1104). + +pandoc (1.12.2.1) + + * Markdown reader: Fixed regression in list parser, involving + continuation lines containing raw HTML (or even verbatim raw HTML). + +pandoc (1.12.2) + + * Metadata may now be included in YAML blocks in a markdown document. + For example, + + --- + title: + - type: main + text: My Book + - type: subtitle + text: An investigation of metadata + creator: + - role: author + text: John Smith + - role: editor + text: Sarah Jones + identifier: + - scheme: DOI + text: doi:10.234234.234/33 + publisher: My Press + rights: (c) 2007 John Smith, CC BY-NC + cover-image: img/mypic.jpg + ... + + Metadata may still be provided using `--epub-metadata`; it will + be merged with the metadata in YAML blocks. + + * EPUB writer: + + + `meta` tags are now used instead of `opf` attributes for EPUB3. + + Insert "svg" property as needed in opf (EPUB 3). + + Simplify `imageTypeOf` using `getMimeType`. + + Add properties attribute to `cover-image` item for EPUB 3. + + Don't include node for `cover.xhtml` if no cover! + + Ensure that same identifier is used throughout (#1044). + If an identifier is given in metadata, we use that; otherwise + we generate a random uuid. + + Add cover reference to guide element (EPUB 2) (Shaun Attfield). + Fixes an issue with Calibre putting the cover at the end of the book + if the spine has `linear="no"`. Apparently this is best practice + for other converters as well: + <http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6>. + + Allow `stylesheet` in metadata. The value is a path to the stylesheet. + + Allow partial dates: `YYYY`, `YYYY-MM`. + + * Markdown writer: Fix rendering of tight sublists (#1050). + Previously a spurious blank line was included after a tight sublist. + + * ODT writer: Add `draw:name` attribute to `draw:frame` elements (#1069). + This is reported to be necessary to avoid an error from recent + versions of Libre Office when files contain more than one image + Thanks to wmanley for reporting and diagnosing the problem. + + * ConTeXt writer: Don't hardcode figure/table placement and numbering. + Instead, let this be set in the template, using `\setupfloat`. + Thanks to on4aa and Aditya Mahajan for the suggestion (#1067). + + * Implemented CSL flipflopping spans in DOCX, LaTeX, and HTML writers. + + * Fixed bug with markdown intraword emphasis. Closes #1066. + + * Docbook writer: Hierarchicalize block content in metadata. + Previously headers just disappeared from block-level metadata + when it was used in templates. Now we apply the 'hierarchicalize' + transformation. Note that a block headed by a level-2 header will + turn into a `<sect1>` element. + + * OpenDocument writer: Skip raw HTML (#1035). + Previously it was erroneously included as verbatim text. + + * HTML/EPUB writer, footnotes: Put `<sup>` tag inside `<a>` tags. + This allows better control of formatting, since the `<a>` + tags have a distinguishing class (#1049). + + * Docx writer: + + + Use mime type info returned by fetchItem. + + Fixed core metadata (#1046). + Don't create empty date nodes if no date given. + Don't create multiple `dc:creator` nodes; instead separate by + semicolons. + + Fix URL for core-properties in `_rels/.rels` (#1046). + + * Plain writer: don't print `<span>` tags. + + * LaTeX writer: + + + Fix definition lists with internal links in terms (#1032). + This fix puts braces around a term that contains an internal + link, to avoid problems with square brackets. + + Properly escape pdftitle, pdfauthor (#1059). + + Use booktabs package for tables (thanks to Jose Luis Duran). + + * Updated beamer template. Now references should work properly + (in a slide) when `--biblatex` or `--natbib` is used. + + * LaTeX reader: + + + Parse contents of curly quotes or matched `"` as quotes. + + Support `\textnormal` as span with class `nodecor`. + This is needed for pandoc-citeproc. + + Improved citation parsing. This fixes a run-time error that occured + with `\citet{}` (empty list of keys). It also ensures that empty keys + don't get produced. + + * MediaWiki reader: Add automatic header identifiers. + + * HTML reader: + + + Use pandoc `Div` and `Span` for raw `<div>`, `<span>` when + `--parse-raw`. + + Recognize `svg` tags as block level content (thanks to MinRK). + + Parse LaTeX math if appropriate options are set. + + * Markdown reader: + + + Yaml block must start immediately after `---`. If there's a blank + line after `---`, we interpreted it as a horizontal rule. + + Correctly handle empty bullet list items. + + Stop parsing "list lines" when we hit a block tag. + This fixes exponential slowdown in certain input, e.g. + a series of lists followed by `</div>`. + + * Slides: Preserve `<div class="references">` in references slide. + + * `Text.Pandoc.Writer.Shared`: + + + Fixed bug in `tagWithAttrs`. A space was omitted before key-value + attributes, leading to invalid HTML. + + `normalizeDate`: Allow dates with year only (thanks to Shaun Attfield). + + Fixed bug in `openURL` with `data:` URIs. Previously the base-64 + encoded bytestring was returned. We now decode it so it's a proper + image! + + * DocBook reader: Handle numerical attributes starting with decimal. + Also use `safeRead` instead of `read`. + + * `Text.Pandoc.Parsing`: + + + Generalized type of `registerHeader`, using new type classes + `HasReadeOptions`, `HasIdentifierList`, `HasHeaderMap`. + These allow certain common functions to be reused + even in parsers that use custom state (instead of `ParserState`), + such as the MediaWiki reader. + + Moved inlineMath, displayMath from Markdown reader to Parsing. + Generalize their types and export them from Parsing. (API change.) + + * `Text.Pandoc.Readers.TexMath`: Export `readTeXMath'`, which attends + to display/inline. Deprecate `readTeXMath`, and use `readTeXMath'` + in all the writers. Require `texmath >= 0.6.5.2`. + + * `Text.Pandoc.MIME`: + + + Add entry for `jfif`. + + In looking up extensions, drop the encoding info. + E.g. for 'image/jpg;base64' we should lookup 'image/jpg'. + + * Templates: Changed how array variables are resolved. Previously if + `foo` is an array (which might be because multiple values were set on + the command line), `$foo$` would resolve to the concatenation of the + elements of foo. This is rarely useful behavior. It has been changed + so that the first value is rendered. Of course, you can still iterate + over the values using `$for(foo)$`. This has the result that you can + override earlier settings using `-V` by putting new values later on the + command line, which is useful for many purposes. + + * `Text.Pandoc`: Don't default to `pandocExtensions` for all writers. + + * Allow "epub2" as synonym for "epub", "html4" for "html". + + * Don't look for slidy files in data files with `--self-contained`. + + * Allow `https:` command line arguments to be downloaded. + + * Fixed `make_osx_package.sh` so data files embedded in `pandoc-citeproc`. + +pandoc (1.12.1) + + * `Text.Pandoc.Definition`: Changed default JSON serialization format. + Instead of `{"Str": "foo"}`, for example, we now have `{"t": "Str", + "c": "foo"}`. This new format is easier to work with outside of Haskell. + Incidentally, "t" stands for "tag", "c" for "contents". + + * MediaWiki reader: Trim contents of `<math>` tags, to avoid problems + when converting to markdown (#1027). + + * LaTeX reader: + + + Ensure that preamble doesn't contribute to the text of + the document. + + Fixed character escaping in \url{}. Previously `\~` wasn't handled + properly, among others. + + Parse `{groups}` as `Span`. This is needed for accurate conversion of + bibtex titles, since we need to know what was protected from + titlecase conversions. + + * LaTeX writer: + + + Specially escape non-ascii characters in labels. + Otherwise we can get compile errors and other bugs when + compiled with pdflatex (#1007). Thanks to begemotv2718 for the fix. + + Add link anchors for code blocks with identifiers (#1025). + + * Throughout the code, use `isURI` instead of `isAbsoluteURI`. + It allows fragments identifiers. + + * Slide formats: + + + A Div element with class "notes" is treated as speaker + notes. Currently beamer goes to `\note{}`, revealjs to + `<aside class="notes">`, and the notes are simply suppressed in + other formats (#925). + + Fixed `. . .` (pause) on HTML slide formats. Closes #1029. + The old version caused a pause to be inserted before the first + material on a slide. This has been fixed. + + Removed data files for s5, slideous, slidy. + Users of s5 and slideous will have to download the needed + files, as has been documented for some time in the README. + By default, slidy code will be sought on the web, as before. + + * HTML writer: Insert command to typeset mathjax only in slideous output + (#966, #1012). + + * RST writer: Skip spaces after display math. Otherwise we get indentation + problems, and part of the next paragraph may be rendered as part of the + math. + + * OpenDocument writer: Fix formatting of strikeout code (#995), + thanks to wilx. don't use `font-face-decls` variable. + + * Fixed test suite so it works with cabal sandboxes. + +pandoc (1.12.0.2) + + * Removed `stringable` dependency. + +pandoc (1.12.0.1) + + * Allow `--metadata` to be repeated for the same key to form a list. + This also has the effect that `--bibliography` can be repeated, + as before. + + * Handle boolean values in `--metadata`. Note that anything not parseable + as a YAML boolean or string is treated as a literal string. + You can get a string value with "yes", or any of the strings interpretable + as booleans, by quoting it: + + -M boolvalue=yes -M stringvalue='"yes"' + + * LaTeX writer: Don't print references if `--natbib` or `--biblatex` + option used. + + * DOCX writer: Add `settings.xml` to the zip container. Fixes a bug + in which docx files could not be read by some versions of Word + and LibreOffice (#990). + + * Fixed a regression involving slide shows with bibliographies. + The Div container around references messed up the procedure for carving + a document into slides. So we now remove the surrounding Div in + `prepSlides`. + + * More informative error message when a filter is not found in path. + + * Depend on pandoc-types 1.12.1. This provide `ToJSONFilter` + instances for `Data a => a -> [a]` and `Data a => a -> IO [a]`. + + * Don't use unicode_collation in building OSX package: + it adds something like 50MB of dependencies to the package. + + * Declare alex and happy as build-tools (#986). + +pandoc (1.12) + + [new features] + + * Much more flexible metadata, including arbitrary fields and structured + values. Metadata can be specified flexibly in pandoc markdown using + YAML metadata blocks, which may occur anywhere in the document: + + --- + title: Here is my title. + abstract: | + This is the abstract. + + 1. It can contain + 2. block content + and *inline markup* + + tags: [cat, dog, animal] + ... + + Metadata fields automatically populate template variables. + + * Added `opml` (OPML) as input and output format. The `_note` attribute, + used in OmniOutliner and supported by multimarkdown, is supported. + We treat the contents as markdown blocks under a section header. + + * Added `haddock` (Haddock markup) as input format (David Lazar). + + * Added `revealjs` output format, for reveal.js HTML 5 slide shows. + (Thanks to Jamie F. Olson for the initial patch.) + Nested vertical stacks are used for hierarchical structure. + Results for more than one level of nesting may be odd. + + * Custom writers can now be written in lua. + + pandoc -t data/sample.lua + + will load the script sample.lua and use it as a custom writer. + (For a sample, do `pandoc --print-default-data-file sample.lua`.) + Note that pandoc embeds a lua interpreter, so lua need not be + installed separately. * New `--filter/-F` option to make it easier to run "filters" (Pandoc AST transformations that operate on JSON serializations). Filters are always passed the name of the output format, so their behavior can be tailored to it. The repository - <https://github.com/jgm/pandoc-filters-python> contains + <https://github.com/jgm/pandocfilters> contains a python module for writing pandoc filters in python, with a number of examples. + * Added `--metadata/-M` option. + This is like `--variable/-V`, but actually adds to metadata, not + just variables. + * Added `--print-default-data-file` option, which allows printing of any of pandoc's data files. (For example, `pandoc --print-default-data-file reference.odt` will print `reference.odt`.) + * Added syntax for "pauses" in slide shows: + + This gives + + . . . + + me pause. + + * New markdown extensions: + + + `ignore_line_breaks`: causes intra-paragraph line breaks to be ignored, + rather than being treated as hard line breaks or spaces. This is useful + for some East Asian languages, where spaces aren't used between words, + but text is separated into lines for readability. + + `yaml_metadata_block`: Parse YAML metadata blocks. (Default.) + + `ascii_identifiers`: This will force `auto_identifiers` to use ASCII + only. (Default for `markdown_github`.) (#807) + + `lists_without_preceding_blankline`: Allow lists to start without + preceding blank space. (Default for `markdown_github`.) (#972) + + [behavior changes] + * `--toc-level` no longer implies `--toc`. Reason: EPUB users who don't want a visible TOC may still want to set the TOC level for in the book navigation. @@ -24,265 +482,244 @@ which URLs it is fetching, but not giving the full header). In addition, there are better error messages when fetching a URL fails. - * citeproc support has been removed from core pandoc (API changes). - - + The `--bibliography`, `--csl`, and `--citation-abbreviation` - options have been removed. - + Markdown and LaTeX citations as still parsed, but an external - filter, `pandoc-citeproc`, is now needed to process - them against a bibliography and CSL stylesheet. The bibliography - and stylesheet should be specified in the document's YAML metadata - (`bibliography` and `csl` fields), and the filter called with - `pandoc --filter pandoc-citeproc`. - + The `Text.Pandoc.Biblio` module has been removed, and the Markdown - and LaTeX readers no longer process citations. Users of the - pandoc library who want citation support will need to use - `Text.CSL.Pandoc` from `pandoc-citations`. - + All bibliography-related fields have been removed from - `ReaderOptions` and `WriterOptions`: `writerBiblioFiles`, - `readerReferences`, `readerCitationStyle`. - + Note that a Cite element is now created in parsing markdown whether - or not there is a matching reference (indeed, pandoc has no way of - knowing, since the `--bibliography` option has been removed). - By default citations will print as `???`. - + The `pandoc-citeproc` script will put the bibliography at the - end of the document, as before. However, it will be put inside a Div - element with class "references", allowing users some control - over the styling of references. A final header, if any, will - be included in the Div. - * The markdown writer will not print a bibliography if the - `citations` extension is enabled. (If the citations are formatted - as markdown citations, it is redundant to have a bibliography, - since one will be generated automatically.) - - * All slide formats: Support incremental slide view for definition lists. - - * Added syntax for "pauses" in beamer or reaveljs slide shows. + * Citation support is no longer baked in to core pandoc. Users who + need citations will need to install and use a separate filter + (`--filter pandoc-citeproc`). This filter will take `bibliography`, + `csl`, and `citation-abbreviations` from the metadata, though it + may still be specified on the command line as before. + + * A `Cite` element is now created in parsing markdown whether or not + there is a matching reference. + + * The `pandoc-citeproc` script will put the bibliography at the + end of the document, as before. However, it will be put inside a `Div` + element with class "references", allowing users some control + over the styling of references. A final header, if any, will + be included in the `Div`. + + * The markdown writer will not print a bibliography if the + `citations` extension is enabled. (If the citations are formatted + as markdown citations, it is redundant to have a bibliography, + since one will be generated automatically.) + + * Previously we used to store the directory of the first input file, + even if it was local, and used this as a base directory for finding + images in ODT, EPUB, Docx, and PDF. This has been confusing to many + users. So we now look for images relative to the current + working directory, even if the first file argument is in another + directory. Note that this change may break some existing workflows. + If you have been assuming that relative links will be interpreted + relative to the directory of the first file argument, you'll need + to make that the current directory before running pandoc. (#942) + + * Better error reporting in some readers, due to changes in `readWith`: + the line in which the error occured is printed, with a caret pointing + to the column. + + * All slide formats now support incremental slide view for definition lists. + + * Parse `\(..\)` and `\[..\]` as math in MediaWiki reader. + Parse `:<math>...</math>` as display math. These notations are used with + the MathJax MediaWiki extension. + + * All writers: template variables are set automatically from metadata + fields. However, variables specified on the command line with + `--variable` will completely shadow metadata fields. + + * If `--variable` is used to set many variables with the same name, + a list is created. + + * Man writer: The `title`, `section`, `header`, and `footer` can now + all be set individually in metadata. The `description` variable has been + removed. Quotes have been added so that spaces are allowed in the + title. If you have a title that begins - This gives + COMMAND(1) footer here | header here - . . . + pandoc will still parse it into a title, section, header, and + footer. But you can also specify these elements explicitly (#885). - a pause. + * Markdown reader - [note - no longer seems to work in recente revealjs - perhaps - this should be reverted] + + Added support for YAML metadata blocks, which can come anywhere + in the document (not just at the beginning). A document can contain + multiple YAML metadata blocks. + + HTML span and div tags are parsed as pandoc Span and Div elements. - * Slidy: Use slidy.js rather than slidy.js.gz. - Reason: some browsers have trouble with the gzipped js file, - at least on the local file system (#795). + * Markdown writer - * Added `revealjs` output format, for reveal.js HTML 5 slide shows. - Thanks to Jamie F. Olson for the initial patch. - Nested vertical stacks are used for hierarchical structure. - Results for more than one level of nesting may be odd. + + Allow simple tables to be printed as grid tables, + if other table options are disabled. This means you can do + `pandoc -t markdown-pipe_tables-simple_tables-multiline_tables` + and all tables will render as grid tables. + + Support YAML title block (render fields in alphabetical order + to make output predictable). - * Use new flexible metadata type. + [API changes] - + Depend on `pandoc-types` 1.12. This changes the type of - `Meta` to allow structured metadata. (API change: existing - code that pattern-matches on `Meta` will have to be revised.) - + Revised readers and writers to use the new `Meta` type. - + Variables completely shadow metadata. - If many variables with the same name are set, a list is created. + * `Meta` in `Text.Pandoc.Definition` has been changed to allow + structured metadata. (Note: existing code that pattern-matches + on `Meta` will have to be revised.) Metadata can now contain + indefinitely many fields, with content that can be a string, + a Boolean, a list of `Inline` elements, a list of `Block` + elements, or a map or list of these. + + * A new generic block container (`Div`) has been added to `Block`, + and a generic inline container (`Span`) has been added to `Inline`. + These can take attributes. They will render in HTML, Textile, + MediaWiki, Org, RST and and Markdown (with `markdown_in_html` + extension) as HTML `<div>` and `<span>` elements; in other formats + they will simply pass through their contents. But they can be + targeted by scripts. * `Format` is now a newtype, not an alias for String. Equality comparisons are case-insensitive. - * New generic block container (`Div`) and inline container - (`Span`) elements have been added. These can take attributes. - They will render in HTML, Textile, MediaWiki, Org, RST and - and Markdown (with `markdown_in_html` extension) as HTML `<div>` - and `<span>` elements; in other formats they will simply pass through - their contents. But they can be targeted by scripts. + * Added `Text.Pandoc.Walk`, which exports hand-written tree-walking + functions that are much faster than the SYB functions from + `Text.Pandoc.Generic`. These functions are now used where possible + in pandoc's code. (`Tests.Walk` verifies that `walk` and `query` + match the generic traversals `bottomUp` and `queryWith`.) + + * Added `Text.Pandoc.JSON`, which provides `ToJSON` and `FromJSON` + instances for the basic pandoc types. They use GHC generics and + should be faster than the old JSON serialization using + `Data.Aeson.Generic`. + + * Added `Text.Pandoc.Process`, exporting `pipeProcess`. + This is a souped-up version of `readProcessWithErrorcode` that + uses lazy bytestrings instead of strings and allows setting + environment variables. (Used in `Text.Pandoc.PDF`.) + + * New module `Text.Pandoc.Readers.OPML`. + + * New module `Text.Pandoc.Writers.OPML`. + + * New module `Text.Pandoc.Readers.Haddock` (David Lazar). + This is based on Haddock's own lexer/parser. + + * New module `Text.Pandoc.Writers.Custom`. + + * In `Text.Pandoc.Shared`, `openURL` and `fetchItem` now return an + Either, for better error handling. - * `Text.Pandoc` + * Made `stringify` polymorphic in `Text.Pandoc.Shared`. - + Make `toJsonFilter` an alias for `toJSONFilter` from `Text.Pandoc.JSON`. + * Removed `stripTags` from `Text.Pandoc.XML`. + + * `Text.Pandoc.Templates`: + + + Simplified `Template` type to a newtype. + + Removed `Empty`. + + Changed type of `renderTemplate`: it now takes a JSON context + and a compiled template. + + Export `compileTemplate`. + + Export `renderTemplate'` that takes a string instead of a compiled + template. + + Export `varListToJSON`. + + * `Text.Pandoc.PDF` exports `makePDF` instead of `tex2pdf`. + + * `Text.Pandoc`: + + + Made `toJsonFilter` an alias for `toJSONFilter` from `Text.Pandoc.JSON`. + Removed `ToJsonFilter` typeclass. `ToJSONFilter` from `Text.Pandoc.JSON` should be used instead. (Compiling against pandoc-types instead of pandoc will also produce smaller executables.) * Removed the deprecated `jsonFilter` function. + Added `readJSON`, `writeJSON` to the API (#817). - * Most of `Text.Pandoc.Readers.TeXMath` has been moved to the - `texmath` module (0.6.4). (This allows `pandoc-citeproc` to - handle simple math in bibliography fields.) - - [ TODO - systematic documentation of pandoc-types API changes, - including .JSON, .Walk and changes to .Definition, .Builder. - Include the new Format newtype, and the new Span and Div - elements.] - - * Added `Text.Pandoc.Walk` (in `pandoc-types`), which exports - hand-written tree-walking functions that are orders of magnitude - faster than the SYB functions from `Text.Pandoc.Generic`. - These functions are now used where possible in pandoc's code. - Added `Tests.Walk` to verify that `walk` and `query` match - the generic traversals `bottomUp` and `queryWith`. - (API change.) + * `Text.Pandoc.Options`: - * Added `Text.Pandoc.Process`, exporting `pipeProcess`. - This is a souped-up version of `readProcessWithErrorcode` that - uses lazy bytestrings instead of strings and allows setting - environment variables. (Used in `Text.Pandoc.PDF`.) + + Added `Ext_lists_without_preceding_blankline`, + `Ext_ascii_identifiers`, `Ext_ignore_line_breaks`, + `Ext_yaml_metadataBlock` to `Extension`. + + Changed `writerSourceDirectory` to `writerSourceURL` and changed the + type to a `Maybe`. `writerSourceURL` is set to 'Just url' when the + first command-line argument is an absolute URL. (So, relative links + will be resolved in relation to the first page.) Otherwise, 'Nothing'. + + All bibliography-related fields have been removed from + `ReaderOptions` and `WriterOptions`: `writerBiblioFiles`, + `readerReferences`, `readerCitationStyle`. - * Added `Text.Pandoc.Compat.Monoid`. - This allows pandoc to compile with `base` < 4.5, where `Data.Monoid` - doesn't export `<>`. Thanks to Dirk Ullirch for the patch. + * The `Text.Pandoc.Biblio` module has been removed. Users of the + pandoc library who want citation support will need to use + `Text.CSL.Pandoc` from `pandoc-citeproc`. + - * Added `Text.Pandoc.Compat.TagSoupEntity`. - This allows pandoc to compile with `tagsoup` 0.13.x. - Thanks to Dirk Ullrich for the patch. + [bug fixes] + + * In markdown, don't autolink a bare URI that is followed by `</a>` + (#937). * `Text.Pandoc.Shared` - + `openURL` now follows redirects (#701). - + `openURL` and `fetchItem` now return an Either, for - better error handling. (API change.) - + `readDefaultDataFile`: normalize the paths. - This fixes bugs in `--self-contained` on pandoc compiled with - `embed_data_files` (#833). + + `openURL` now follows redirects (#701), properly handles `data:` + URIs, and prints diagnostic output to stderr rather than stdout. + + `readDefaultDataFile`: normalize the paths. This fixes bugs in + `--self-contained` on pandoc compiled with `embed_data_files` (#833). + Fixed `readDefaultDataFile` so it works on Windows. + Better error messages for `readDefaultDataFile`. Instead of listing the last path tried, which can confuse people who are using `--self-contained`, so now we just list the data file name. - + URL-escape pipe characters. - Even though these are legal, `Network.URI` doesn't regard them - as legal in URLs. So we escape them first (#535). - + `openURL`: Print diagnostic output to stderr, not stdout. - + `openURL`: Properly handle `data:` URIs. - + `stringify`: Generalized type. - - * `Text.Pandoc.Biblio` - - + Override citeproc-hs's `endWithPunct`. - The new version correctly sees a sentence ending in '.)' as ending - with punctuation. This fixes a bug which led such sentences to receive - an extra period at the end: '.).'. Thanks to Steve Petersen for - reporting. - + Don't interfere with Notes that aren't citation notes. - This fixes a bug in which notes not generated from citations were - being altered (e.g. first letter capitalized) (#898). - + Only capitalize footnote citations when they have a prefix. - + Changes in suffix parsing. A suffix beginning with a digit gets 'p' - inserted before it before passing to citeproc-hs, so that bare numbers - are treated as page numbers by default. A suffix not beginning with - punctuation has a space added at the beginning (rather than a comma and - space, as was done before for not-author-in-text citations). - The result of these changes (and the last commit) is that - `\citep[23]{item1}` in LaTeX will be interpreted properly, - with '23' treated as a locator of type 'page'. - - * New module `Text.Pandoc.JSON` in pandoc-types. - - + This provides `ToJSON` and `FromJSON` instances for the basic - pandoc types. They use GHC generics and should be faster than the - old JSON serialization using `Data.Aeson.Generic`. + + URL-escape pipe characters. Even though these are legal, `Network.URI` + doesn't regard them as legal in URLs. So we escape them first (#535). - * New module `Text.Pandoc.Writers.Shared` for shared functions used - only in writers. + * Mathjax in HTML slide shows: include explicit "Typeset" call. + This seems to be needed for some formats (e.g. slideous) and won't + hurt in others (#966). - + Added `metaToJSON`. This is used in writers to create a - JSON object for use in the templates from the pandoc metadata - and variables. - + Added `getField`, `setField`, `defField` for working with JSON - template contexts. + * `Text.Pandoc.PDF` - * Added `Text.Pandoc.Asciify` utility module. - This exports functions to create ASCII-only versions of identifiers. - - * `Text.Pandoc.ImageSize`: Handle EPS (#903). This change will make - EPS images properly sized on conversion to Word. + + On Windows, create temdir in working directory, since the system + temp directory path may contain tildes, which can cause + problems in LaTeX (#777). + + Put temporary output directory in `TEXINPUTS` (see #917). + + `makePDF` tries to download images that are not found locally, + if the first argument is a URL (#917). + + If compiling with `pdflatex` yields an encoding error, offer + the suggestion to use `--latex-engine=xelatex`. - * `Text.Pandoc.SelfContained` + * Produce automatic header identifiers in parsing textile, RST, + and LaTeX, unless `auto_identifiers` extension is disabled (#967). - + Strip off fragment, query of relative URL before treating as - a filename. This fixes `--self-contained` when used with CSS - files that include web fonts using the method described here: + * `Text.Pandoc.SelfContained`: Strip off fragment, query of relative URL + before treating as a filename. This fixes `--self-contained` when used + with CSS files that include web fonts using the method described here: <http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/> - (#739). - + Handle `src` in `embed`, `audio`, `source`, `input` tags. - - * Added `Text.Pandoc.Writers.Custom` and custom output formats. + (#739). Handle `src` in `embed`, `audio`, `source`, `input` tags. - pandoc -t data/sample.lua + * `Text.Pandoc.Parsing`: `uri` parser no longer treats punctuation before + percent-encoding, or a `+` character, as final punctuation. - will load the script sample.lua and use it as a custom writer. - `data/sample.lua` is provided as an example. (This can be printed - with `pandoc --print-default-data-file sample.lua`.) - - * Added OPML reader and writer. - - + New module `Text.Pandoc.Readers.OPML`. - The `_note` attribute is supported. This is unofficial, but - used e.g. in OmniOutliner and supported by multimarkdown. - We treat the contents as markdown blocks under a section - header. - + New module `Text.Pandoc.Writers.OPML`. - - * Added Haddock reader. + * `Text.Pandoc.ImageSize`: Handle EPS (#903). This change will make + EPS images properly sized on conversion to Word. - + New module `Text.Pandoc.Readers.Haddock` (David Lazar). - This is based on Haddock's own lexer/parser. + * Slidy: Use slidy.js rather than slidy.js.gz. + Reason: some browsers have trouble with the gzipped js file, + at least on the local file system (#795). * Markdown reader - + Added `ignore_line_breaks` markdown extension. - This causes intra-paragraph line breaks to be ignored, - rather than being treated as hard line breaks or spaces. - This is useful for some East Asian languages, where spaces - aren't used between words, but text is separated into lines - for readability. + Properly handle blank line at beginning of input (#882). + Fixed bug in unmatched reference links. The input `[*infile*] [*outfile*]` was getting improperly parsed: "infile" was emphasized, but "*outfile*" was literal (#883). - + Check for blank lines first in blocks. (And skip them. This - might speed things up in some cases.) - + Implemented `Ext_ascii_identifiers` (#807). + Allow internal `+` in citation identifiers (#856). - + Added support for YAML metadata blocks, which can come anywhere - in the document (not just at the beginning). A document can contain - multiple YAML metadata blocks. - + Improved strong/emph parsing, using the strategy of - <https://github.com/jgm/Markdown>. The new parsing algorithm requires - no backtracking, and no keeping track of nesting levels. - It will give different results in some edge cases, but these should - not affect normal uses. + Allow `.` or `)` after `#` in ATX headers if no `fancy_lists`. + Do not generate blank title, author, or date metadata elements. Leave these out entirely if they aren't present. - + HTML span and div tags are parsed as pandoc Span and Div elements. + + Allow backtick code blocks not to be preceded by blank line (#975). - * RST reader - - + Don't insert paragraphs where docutils doesn't. - `rst2html` doesn't add `<p>` tags to list items (even when they are - separated by blank lines) unless there are multiple paragraphs in the - list. This commit changes the RST reader to conform more closely to - what docutils does (#880). - + Improved metadata. Treat initial field list as metadata when - standalone specified. Previously ALL fields "title", "author", - "date" in field lists were treated as metadata, even if not at - the beginning. Use `subtitle` metadata field for subtitle. - + Fixed 'authors' metadata parsing in reST. Semicolons separate - different authors. - - * Textile reader + * Textile reader: + Correctly handle entities. - + Improved handling of `<pre>` blocks. - + Fixed a bug in which `<pre>` in certain contexts was - not recognized as a code block (#927). - + Remove internal HTML tags in code blocks, rather than printing - them verbatim. - * Parse attributes on `<pre>` tag for code blocks. - - * HTML reader + + Improved handling of `<pre>` blocks (#927). Remove internal HTML tags + in code blocks, rather than printing them verbatim. Parse attributes + on `<pre>` tag for code blocks. - + Handle non-simple tables (#893). Column widths are read from - `col` tags if present, otherwise divided equally. + * HTML reader: Handle non-simple tables (#893). Column widths are read from + `col` tags if present, otherwise divided equally. * LaTeX reader @@ -292,11 +729,25 @@ + Skip positional options after `\begin{figure}`. + Support `\v{}` for hacek (#926). + Don't add spurious ", " to citation suffixes. - This is added when needed in `Text.Pandoc.Biblio` anyway. + This is added when needed in pandoc-citeproc. + Allow spaces in alignment spec in tables, e.g. `{ l r c }`. + Improved support for accented characters (thanks to Scott Morrison). + Parse label after section command and set id (#951). + * RST reader: + + + Don't insert paragraphs where docutils doesn't. + `rst2html` doesn't add `<p>` tags to list items (even when they are + separated by blank lines) unless there are multiple paragraphs in the + list. This commit changes the RST reader to conform more closely to + what docutils does (#880). + + Improved metadata. Treat initial field list as metadata when + standalone specified. Previously ALL fields "title", "author", + "date" in field lists were treated as metadata, even if not at + the beginning. Use `subtitle` metadata field for subtitle. + + Fixed 'authors' metadata parsing in reST. Semicolons separate + different authors. + * MediaWiki reader + Allow space before table rows. @@ -309,6 +760,8 @@ + Skip attributes on table rows. Previously we just crashed if rows had attributes, now we ignore them. + Ignore attributes on headers. + + Allow `Image:` for images (#971). + + Parse an image with caption in a paragraph by itself as a figure. * LaTeX writer @@ -326,51 +779,33 @@ + Scale LaTeX tables so they don't exceed columnwidth. + Avoid problem with footnotes in unnumbered headers (#940). - * Beamer writer - - + When creating beamer slides, add `allowframebreaks` option - to the slide if it is one of the header classes. It's recommended + * Beamer writer: when creating beamer slides, add `allowframebreaks` option + to the slide if it is one of the header classes. It is recommended that your bibliography slide have this attribute: - + # References {.allowframebreaks} - + This causes multiple slides to be created if necessary, depending on the length of the bibliography. - * ConTeXt writer - - + Properly handle tables without captions. The old output only - worked in MkII. This should work in MkIV as well (#837). + * ConTeXt writer: Properly handle tables without captions. The old output + only worked in MkII. This should work in MkIV as well (#837). - * MediaWiki writer + * MediaWiki writer: Use native mediawiki tables instead of HTML (#720). - + Use native mediawiki tables instead of HTML (#720). - - * HTML writer + * HTML writer: + Fixed `--no-highlight` (Alexander Kondratskiy). + Don't convert to lowercase in email obfuscation (#839). + + Ensure proper escaping in `<title>` and `<meta>` fields. - * Man writer - - + Offer more fine-grained control in template. - Now the `title`, `section`, `header`, and `footer` can all be set - individually in metadata. The `description` variable has been - removed. Quotes have been added so that spaces are allowed in the title. - If you have a title that begins - - COMMAND(1) footer here | header here - - pandoc will parse it as before into a title, section, header, and - footer. But you can also specify these elements explicitly (#885). - - * AsciiDoc writer + * AsciiDoc writer: + Support `--atx-headers` (Max Rydahl Andersen). + Don't print empty identifier blocks `([[]])` on headers (Max Rydahl Andersen). - * ODT writer + * ODT writer: + Fixing wrong numbered-list indentation in open document format (Alexander Kondratskiy) (#369). @@ -379,7 +814,7 @@ nonconforming `contextual-spacing` attribute, which is provided by LibreOffice itself and seems well supported. - * Docx writer + * Docx writer: + Fixed rendering of display math in lists. In 1.11 and 1.11.1, display math in lists rendered as a new list @@ -388,8 +823,8 @@ containing list item is (#784). + Use `w:br` with `w:type` `textWrapping` for linebreaks. Previously we used `w:cr` (#873). - + Use Compact style for Plain block elements. - This differentiates between tight and loose lists (#775). + + Use Compact style for Plain block elements, to + differentiate between tight and loose lists (#775). + Ignore most components of `reference.docx`. We take the `word/styles.xml`, `docProps/app.xml`, `word/theme/theme1.xml`, and `word/fontTable.xml` from @@ -413,124 +848,128 @@ margin fields. + If resource not found, skip it, as in Docx writer (#916). - * Markdown writer + * RTF writer: + + + Properly handle characters above the 0000-FFFF range. + Uses surrogate pairs. Thanks to Hiromi Ishii for the patch. + + Fixed regression with RTF table of contents. + + Only autolink absolute URIs. This fixes a regression, #830. + + * Markdown writer: - + Allow simple tables to be printed as grid tables, - if other table options are disabled. This means you can do - `pandoc -t markdown-pipe_tables-simple_tables-multiline_tables` - and all tables will render as grid tables. - + Put multiple authors on separate lines in pandoc titleblock. - Also, don't wrap long author entries, as new lines get treated - as new authors. + Only autolink absolute URIs. This fixes a regression, #830. + Don't wrap attributes in fenced code blocks. - + Support YAML title block (render fields in alphabetical order - to make output predictable). + Write full metadata in MMD style title blocks. + + Put multiple authors on separate lines in pandoc titleblock. + Also, don't wrap long author entries, as new lines get treated + as new authors. - * RTF writer + * `Text.Pandoc.Templates`: - + Properly handle characters above the 0000-FFFF range. - Uses surrogate pairs. Thanks to Hiromi Ishii for the patch. - + Fixed regression with RTF table of contents. - + Only autolink absolute URIs. This fixes a regression, #830. + + Fixed bug retrieving default template for markdown variants. + + Templates can now contain "record lookups" in variables; + for example, `author.institution` will retrieve the `institution` + field of the `author` variable. + + More consistent behavior of `$for$`. When `foo` is not a list, + `$for(foo)$...$endfor$` should behave like $if(foo)$...$endif$. + So if `foo` resolves to "", no output should be produced. + See pandoc-templates#39. - * `Text.Pandoc.PDF` + * Citation processing improvements (now part of pandoc-citeproc): - + On Windows, create temdir in working directory. - Reason: the path to the system temp directory may contain tildes, - which causes problems in LaTeX when the username is more than - eight characters (#777). - + Put temporary output directory in `TEXINPUTS`. - This will help later when we try to download external resources. - We can put them in the temp directory (see #917). - + `Text.Pandoc.PDF` exports `makePDF` instead of `tex2pdf`. - (API change.) - + `makePDF` walks the pandoc AST and checks for the existence of - images in the local directory. If they are not found, it attempts - to find them, either in the directory containing the first source - file, or at an absolute URL, or at a URL relative to the base URL - of the first command line argument (#917). - + If compiling with `pdflatex` yields an encoding error, offer - the suggestion to use `--latex-engine=xelatex`. + + Fixed `endWithPunct` The new version correctly sees a sentence + ending in '.)' as ending with punctuation. This fixes a bug which + led such sentences to receive an extra period at the end: '.).'. + Thanks to Steve Petersen for reporting. + + Don't interfere with Notes that aren't citation notes. + This fixes a bug in which notes not generated from citations were + being altered (e.g. first letter capitalized) (#898). + + Only capitalize footnote citations when they have a prefix. + + Changes in suffix parsing. A suffix beginning with a digit gets 'p' + inserted before it before passing to citeproc-hs, so that bare numbers + are treated as page numbers by default. A suffix not beginning with + punctuation has a space added at the beginning (rather than a comma and + space, as was done before for not-author-in-text citations). + The result is that `\citep[23]{item1}` in LaTeX will be interpreted + properly, with '23' treated as a locator of type 'page'. + + Many improvements to citation rendering, due to fixes in citeproc-hs + (thanks to Andrea Rossato). + + Warnings are issued for undefined citations, which are rendered + as `???`. + + Fixed hanging behavior when locale files cannot be found. + + [template changes] + + * DocBook: Use DocBook 4.5 doctype. + + * Org: '#+TITLE:' is inserted before the title. + Previously the writer did this. + + * LaTeX: Changes to make mathfont work with xelatex. + We need the mathspec library, not just fontspec, for this. + We also need to set options for setmathfont (#734). - * `Text.Pandoc.UTF8` + * LaTeX: Use `tex-ansi` mapping for `monofont`. + This ensures that straight quotes appear as straight, rather than + being treated as curly. See #889. - + Use strict bytestrings in reading. The use of lazy bytestrings seemed - to cause problems using pandoc on 64-bit Windows 7/8 (#874). + * Made `\includegraphics` more flexible in LaTeX template. + Now it can be used with options, if needed. Thanks to Bernhard Weichel. + + * LaTeX/Beamer: Added `classoption` variable. + This is intended for class options like `oneside`; it may + be repeated with different options. (Thanks to Oliver Matthews.) + + * Beamer: Added `fonttheme` variable. (Thanks to Luis Osa.) + + * LaTeX: Added `biblio-style` variable (#920). + + * DZSlides: title attribute on title section. + + * HTML5: add meta tag to allow scaling by user (Erik Evenson) + + [under-the-hood improvements] + + * Markdown reader:Improved strong/emph parsing, using the strategy of + <https://github.com/jgm/Markdown>. The new parsing algorithm requires + no backtracking, and no keeping track of nesting levels. It will give + different results in some edge cases, but these should not affect normal + uses. + + * Added `Text.Pandoc.Compat.Monoid`. + This allows pandoc to compile with `base` < 4.5, where `Data.Monoid` + doesn't export `<>`. Thanks to Dirk Ullirch for the patch. + + * Added `Text.Pandoc.Compat.TagSoupEntity`. + This allows pandoc to compile with `tagsoup` 0.13.x. + Thanks to Dirk Ullrich for the patch. + + * Most of `Text.Pandoc.Readers.TeXMath` has been moved to the + `texmath` module (0.6.4). (This allows `pandoc-citeproc` to + handle simple math in bibliography fields.) + + * Added `Text.Pandoc.Writers.Shared` for shared functions used + only in writers. `metaToJSON` is used in writers to create a + JSON object for use in the templates from the pandoc metadata + and variables. `getField`, `setField`, and `defField` are + for working with JSON template contexts. + + * Added `Text.Pandoc.Asciify` utility module. + This exports functions to create ASCII-only versions of identifiers. * `Text.Pandoc.Parsing` - + Further improvements to URI parser. - Don't treat punctuation before percent-encoding as final punctuation. - Don't treat '+' as final punctuation. + Generalized state type on `readWith` (API change). - + Specialize readWith to `String` input. - + Better error reporting in `readWith`: On error have it print the line - in which the error occurred, with a caret pointing to the column. + + Specialize readWith to `String` input. (API change). + In `ParserState`, replace `stateTitle`, `stateAuthors`, `stateDate` with `stateMeta` and `stateMeta'`. - * `Text.Pandoc.XML` - - + Removed `stripTags`. (API change.) - - * `Text.Pandoc.Options` - - + Added `Ext_yaml_metadata_block`. (API change.) - + Added `Ext_ascii_identifiers`. (API change.) - This will force `Ext_auto_identifiers` to use ASCII only. - Set as default for github markdown. - + Changed `writerSourceDir` to `writerSourceURL` and changed - the type to a `Maybe`. Previously we used to store the directory - of the first input file, even if it was local, and used this as a - base directory for finding images in ODT, EPUB, Docx, and PDF. - This has been confusing to many users. It seems better to look for - images relative to the current working directory, even if the first - file argument is in another directory. `writerSourceURL` is set - to 'Just url' when the first command-line argument is an absolute - URL. (So, relative links will be resolved in relation to the first - page.) Otherwise, 'Nothing'. The ODT, EPUB, Docx, and PDF - writers have been modified accordingly. Note that this change may - break some existing workflows. If you have been assuming that - relative links will be interpreted relative to the directory of - the first file argument, you'll need to make that the current - directory before running pandoc. API change (#942). - - * `Text.Pandoc.Templates` - - + Changed type of `renderTemplate`: it now takes a JSON context - and a compiled template. (API change.) - + Export `compileTemplate`. (API change.) - + Export `renderTemplate'` that takes a string instead of a compiled - template. (API change.) - + Export `varListToJSON`. (API change.) - + Removed `Empty`. - + Simplified `Template` type to a newtype. - + Templates can now contain "record lookups" in variables; - for example, `author.institution` will retrieve the `institution` - field of the `author` variable. - + Fixed bug retrieving default template for markdown variants. + * `Text.Pandoc.UTF8`: use strict bytestrings in reading. The use of lazy + bytestrings seemed to cause problems using pandoc on 64-bit Windows + 7/8 (#874). - * Default template changes - - + DocBook: Use DocBook 4.5 doctype. - + Org: '#+TITLE:' is inserted before the title. - Previously the writer did this. - + LaTeX: Changes to make mathfont work with xelatex. - We need the mathspec library, not just fontspec, for this. - We also need to set options for setmathfont (#734). - + LaTeX: Use `tex-ansi` mapping for `monofont`. - This ensures that straight quotes appear as straight, rather than - being treated as curly. See #889. - + Made `\includegraphics` more flexible in LaTeX template. - Now it can be used with options, if needed. Thanks to Bernhard Weichel. - + LaTeX/Beamer: Added `classoption` variable. - This is intended for class options like `oneside`; it may - be repeated with different options. (Thanks to Oliver Matthews.) - + Beamer: Added `fonttheme` variable. (Thanks to Luis Osa.) - + LaTeX: Added `biblio-style` variable (#920). - + DZSlides: title attribute on title section. + * Factored out `registerHeader` from markdown reader, added to + `Text.Pandoc.Parsing`. * Removed `blaze_html_0_5` flag, require `blaze-html` >= 0.5. Reason: < 0.5 does not provide a monoid instance for Attribute, @@ -554,12 +993,13 @@ * Various small documentation improvements. Thanks to achalddave and drothlis for patches. - + * Removed comment that chokes recent versions of CPP (#933). - + * Removed support for GHC version < 7.2, since pandoc-types now requires at least GHC 7.2 for GHC generics. + pandoc (1.11.1) * Markdown reader: @@ -572,7 +1012,7 @@ pandoc (1.11.1) paragraphs. The unmatched quotes now get turned into literal left double quotes. (No `Quoted` inline is generated, however.) Closes #99 (again). - + * HTML writer: Fixed numbering mismatch between TOC and sections. `--number-offset` now affects TOC numbering as well as section numbering, as it should have all along. Closes #789. @@ -607,7 +1047,7 @@ pandoc (1.11) * Added `--number-offset` option. (See README for description.) * Added `--default-image-extension` option. (See README for description.) - + * `--number-sections` behavior change: headers with class `unnumbered` will not be numbered. @@ -658,7 +1098,7 @@ pandoc (1.11) + Better support for Verbatim and minted environments. Closes #763. * Markdown reader: - + + `-` in an attribute context = `.unnumbered`. The point of this is to provide a way to specify unnumbered headers in non-English documents. @@ -684,7 +1124,7 @@ pandoc (1.11) Closes #723. * Textile reader: - + + Handle attributes on headers. * LaTeX reader: @@ -717,7 +1157,7 @@ pandoc (1.11) `unnumbered` class. * Textile writer: - + + Support header attributes. * Markdown writer: @@ -731,11 +1171,11 @@ pandoc (1.11) use `pandoc -t markdown-citations`. * RST writer: - + + Support `:number-lines:` in code blocks. * Docx writer: - + + Better treatment of display math. Display math inside a paragraph is now put in a separate paragraph, so it will render properly (centered and without extra blank lines around it). @@ -753,7 +1193,7 @@ pandoc (1.11) edited. Closes #414. * EPUB writer: - + + Fix section numbering. Previously the numbering restarted from 1 in each chapter (with `--number-sections`), though the numbers in the table of contents were correct. @@ -776,7 +1216,7 @@ pandoc (1.11) section number. * `Text.Pandoc.Pretty`: - + + Fixed `chomp` so it works inside `Prefixed` elements. + Changed `Show` instance so it is better for debugging. @@ -846,7 +1286,7 @@ pandoc (1.10.1) Thanks to Nick Bart for the suggestion of using @{}. * `Text.Pandoc.Parsing`: - + + More efficient version of `anyLine`. + Type of `macro` has changed; the parser now returns `Blocks` instead of `Block`. @@ -869,7 +1309,7 @@ pandoc (1.10.0.5) Thanks to Andrew Lee for pointing out the bug. * Markdown reader: Fixed regressions in fenced code blocks. Closes #722. - + + Tilde code fences can again take a bare language string (`~~~ haskell`), not just curly-bracketed attributes (`~~~ {.haskell}`). @@ -900,7 +1340,7 @@ pandoc (1.10.0.5) `hsb2hs`. * Changes to `make-windows-installer.bat`. - + + Exit batch file if any of the cabal-dev installs fail. + There's no longer any need to reinstall `highlighting-kate`. + Don't start with a `cabal update`; leave that to the user. @@ -1652,19 +2092,19 @@ pandoc (1.9.4.2) checks for the base version that intelligibly enable encoding/decoding when needed. Fixes a bug with multilingual filenames when pandoc was compiled with ghc 7.4 (#540). - + * Don't generate an empty H1 after hrule slide breaks. We now use a slide-level header with contents `[Str "\0"]` to mark an hrule break. This avoids creation of an empty H1 in these contexts. Closes #484. - + * Docbook reader: Added support for "bold" emphasis. Thanks to mb21. - + * In make_osx_package.sh, ensure citeproc-hs is built with the embed_data_files flag. - + * MediaWiki writer: Avoid extra blank lines after sublists (Gavin Beatty). - + * ConTeXt writer: Don't escape `&`, `^`, `<`, `>`, `_`, simplified escapes for `}` and `{` to `\{` and `\}` (Aditya Mahajan). @@ -1675,7 +2115,7 @@ pandoc (1.9.4.2) * Added some missing exports and tests to the cabal file (Alexander V Vershilov). - + * Compile with `-rtsopts` and `-threaded` by default. pandoc (1.9.4.1) @@ -1693,7 +2133,7 @@ pandoc (1.9.4.1) + Use microtype if available. * Biblio: - + + Add comma to beginning of bare suffix, e.g. `@item1 [50]`. Motivation: `@item1 [50]` should be as close as possible to `[@item1, 50]`. @@ -1997,12 +2437,12 @@ pandoc (1.9.1.1) pandoc (1.9.1) * LaTeX reader: - + + Fixed regression in 1.9; properly handle escaped $ in latex math. + Put LaTeX verse environments in blockquotes. * Markdown reader: - + + Limit nesting of strong/emph. This avoids exponential lookahead in parasitic cases, like `a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**`. + Improved attributes syntax (inn code blocks/spans): @@ -2221,7 +2661,7 @@ pandoc (1.9) </sidebar> will not be wrapped in `<para>` tags. - + * The LaTeX parser has been completely rewritten; it is now much more accurate, robust, and extensible. However, there are two important changes in how it treats unknown LaTeX. (1) Previously, unknown @@ -3397,7 +3837,7 @@ pandoc (1.5.1.1) [ John MacFarlane ] - * Fixed uniqueIdent in Shared so that header identifiers work as + * Fixed uniqueIdent in Shared so that header identifiers work as advertized in the README and are are valid XHTML names. pandoc (1.5.1) @@ -4639,7 +5079,7 @@ pandoc (0.46) unstable; urgency=low HTML reader now uses rawHtmlBlock', which excludes </html> and </body>, since these are handled in parseHtml. (Resolves Issue #38.) - + Fixed bug (emph parser was looking for <IT> tag, not <I>). + + Fixed bug (emph parser was looking for `<IT>` tag, not `<I>`). + Don't interpret contents of style tags as markdown. (Resolves Issue #40.) @@ -4724,15 +5164,15 @@ pandoc (0.45) unstable; urgency=low + readTeXMath is now used for default HTML output in HTML, S5, RTF, and Docbook, if no other method for displaying math in HTML is specified. Enclosing $'s are no longer printed by default. - + By default, math is put inside <span class="math">. This way it can be + + By default, math is put inside `<span class="math">`. This way it can be distinguished from the surrounding text, e.g. put in a different font. * New --gladtex and --mimetex options for display of math in HTML: - + If --gladtex is specified, math is output between <eq> tags, so + + If --gladtex is specified, math is output between `<eq>` tags, so it can be processed by gladTeX. - + If --mimetex is specified, math is put in <img> tags with a link + + If --mimetex is specified, math is put in `<img>` tags with a link to the mimetex CGI script (or any other script that takes TeX math as input and outputs an image). The URL of the script may be specified, but defaults to /cgi-bin/mimetex.cgi. @@ -4746,13 +5186,13 @@ pandoc (0.45) unstable; urgency=low + Fixed bug: parser for minimized attributes should not swallow trailing spaces. + Simplified HTML attribute parsing. - + Changed parsing of code blocks in HTML reader: <code> tag is no - longer needed. <pre> suffices. All HTML tags in the code block + + Changed parsing of code blocks in HTML reader: `<code>` tag is no + longer needed. `<pre>` suffices. All HTML tags in the code block (e.g. for syntax highlighting) are skipped, because they are not - portable to other output formats. A <code>...</code> block not - surrounded by <pre> now counts as inline HTML, not a code block. + portable to other output formats. A `<code>...</code>` block not + surrounded by `<pre>` now counts as inline HTML, not a code block. + Remove just one leading and one trailing newline from contents of - <pre>...</pre> in codeBlock parser. + `<pre>...</pre>` in codeBlock parser. * Markdown reader: @@ -5074,8 +5514,8 @@ pandoc (0.43) unstable; urgency=low end code block with a nonindented line.) + Changed definition of 'emph': italics with '_' must not be followed by an alphanumeric character. This is to help - prevent interpretation of e.g. [LC_TYPE]: my_type as - '[LC<em>TYPE]:my</em>type'. + prevent interpretation of e.g. `[LC_TYPE]: my_type` as + `[LC<em>TYPE]:my</em>type`. + Improved Markdown.pl-compatibility in referenceLink: the two parts of a reference-style link may be separated by one space, but not more... [a] [link], [not] [a link]. @@ -5083,7 +5523,7 @@ pandoc (0.43) unstable; urgency=low Markdown.pl: the marker for the end of the code section is a clump of the same number of `'s with which the section began, followed by a non-` character. So, for example, - ` h ``` i ` -> <code>h ``` i</code>. + ` h ``` i ` -> `<code>h ``` i</code>`. + Split 'title' into 'linkTitle' and 'referenceTitle', since the rules are slightly different. + Rewrote 'para' for greater efficiency. @@ -5190,7 +5630,7 @@ pandoc (0.41) unstable; urgency=low [ John MacFarlane ] * Fixed bugs in HTML reader: - + Skip material at end *only if* </html> is present (previously, + + Skip material at end *only if* `</html>` is present (previously, only part of the document would be parsed if an error was found; now a proper error message is given). + Added new constant eitherBlockOrInline with elements that may @@ -5399,9 +5839,9 @@ pandoc (0.4) unstable; urgency=low may cause documents to be parsed differently. Users should take care in upgrading. + Changed autoLink parsing to conform better to Markdown.pl's - behavior. <google.com> is not treated as a link, but - <http://google.com>, <ftp://google.com>, and <mailto:google@google.com> - are. + behavior. `<google.com>` is not treated as a link, but + `<http://google.com>`, `<ftp://google.com>`, and + `<mailto:google@google.com>` are. + Cleaned up handling of embedded quotes in link titles. Now these are stored as a '"' character, not as '"'. + Use lookAhead parser for the 'first pass' (looking for reference keys), @@ -5465,7 +5905,7 @@ pandoc (0.4) unstable; urgency=low been removed, since they are written programatically. This change introduces a new dependency on the xhtml package. + Fixed two bugs in email obfuscation involving improper escaping - of '&' in the <noscript> section and in --strict mode. Resolves + of '&' in the `<noscript>` section and in `--strict` mode. Resolves Issue #9. + Fixed another bug in email obfuscation: If the text to be obfuscated contains an entity, this needs to be decoded before obfuscation. @@ -5497,8 +5937,8 @@ pandoc (0.4) unstable; urgency=low + Links in markdown output are now printed as inline links by default, rather than reference links. A --reference-links option has been added that forces links to be printed as reference links. Resolves Issue #4. - + Use autolinks when possible. Instead of [site.com](site.com), - use <site.com>. + + Use autolinks when possible. Instead of `[site.com](site.com)`, + use `<site.com>`. * LaTeX writer: @@ -5714,7 +6154,7 @@ pandoc (0.3) unstable; urgency=low only non-alphanumeric characters can be escaped. Strict mode follows Markdown.pl in only allowing a select group of punctuation characters to be escaped. - + Modified HTML reader to skip a newline following a <br> tag. + + Modified HTML reader to skip a newline following a `<br>` tag. Otherwise the newline will be treated as a space at the beginning of the next line. @@ -5744,7 +6184,7 @@ pandoc (0.3) unstable; urgency=low * Moved handling of "smart typography" from the writers to the Markdown and LaTeX readers. This allows great simplification of the writers and more accurate smart quotes, dashes, and ellipses. DocBook can - now use '<quote>'. The '--smart' option now toggles an option in + now use `<quote>`. The '--smart' option now toggles an option in the parser state rather than a writer option. Several new kinds of inline elements have been added: Quoted, Ellipses, Apostrophe, EmDash, EnDash. diff --git a/data/reference.docx b/data/reference.docx Binary files differindex 42c14a906..a9c268b9f 100644 --- a/data/reference.docx +++ b/data/reference.docx diff --git a/data/reference.odt b/data/reference.odt Binary files differindex 08385dd4c..c01345612 100644 --- a/data/reference.odt +++ b/data/reference.odt diff --git a/data/s5/default/blank.gif b/data/s5/default/blank.gif Binary files differdeleted file mode 100644 index 75b945d25..000000000 --- a/data/s5/default/blank.gif +++ /dev/null diff --git a/data/s5/default/bodybg.gif b/data/s5/default/bodybg.gif Binary files differdeleted file mode 100644 index 5f448a16f..000000000 --- a/data/s5/default/bodybg.gif +++ /dev/null diff --git a/data/s5/default/framing.css b/data/s5/default/framing.css deleted file mode 100644 index 14d8509e9..000000000 --- a/data/s5/default/framing.css +++ /dev/null @@ -1,23 +0,0 @@ -/* 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;} -*/ diff --git a/data/s5/default/iepngfix.htc b/data/s5/default/iepngfix.htc deleted file mode 100644 index bba2db756..000000000 --- a/data/s5/default/iepngfix.htc +++ /dev/null @@ -1,42 +0,0 @@ -<public:component>
-<public:attach event="onpropertychange" onevent="doFix()" />
-
-<script>
-
-// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
-// Free usage permitted as long as this notice remains intact.
-
-// This must be a path to a blank image. That's all the configuration you need here.
-var blankImg = 'ui/default/blank.gif';
-
-var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
-
-function filt(s, m) {
- if (filters[f]) {
- filters[f].enabled = s ? true : false;
- if (s) with (filters[f]) { src = s; sizingMethod = m }
- } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
-}
-
-function doFix() {
- if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
- (event && !/(background|src)/.test(event.propertyName))) return;
-
- if (tagName == 'IMG') {
- if ((/\.png$/i).test(src)) {
- filt(src, 'image'); // was 'scale'
- src = blankImg;
- } else if (src.indexOf(blankImg) < 0) filt();
- } else if (style.backgroundImage) {
- if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
- var s = RegExp.$1;
- style.backgroundImage = '';
- filt(s, 'crop');
- } else filt();
- }
-}
-
-doFix();
-
-</script>
-</public:component>
\ No newline at end of file diff --git a/data/s5/default/opera.css b/data/s5/default/opera.css deleted file mode 100644 index 9e9d2a3c5..000000000 --- a/data/s5/default/opera.css +++ /dev/null @@ -1,7 +0,0 @@ -/* 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;} diff --git a/data/s5/default/outline.css b/data/s5/default/outline.css deleted file mode 100644 index 62db519ed..000000000 --- a/data/s5/default/outline.css +++ /dev/null @@ -1,15 +0,0 @@ -/* 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;} diff --git a/data/s5/default/pretty.css b/data/s5/default/pretty.css deleted file mode 100644 index a87b24375..000000000 --- a/data/s5/default/pretty.css +++ /dev/null @@ -1,86 +0,0 @@ -/* 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;} -*/ diff --git a/data/s5/default/print.css b/data/s5/default/print.css deleted file mode 100644 index 4a3554ddd..000000000 --- a/data/s5/default/print.css +++ /dev/null @@ -1,24 +0,0 @@ -/* 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;} diff --git a/data/s5/default/s5-core.css b/data/s5/default/s5-core.css deleted file mode 100644 index 86444e041..000000000 --- a/data/s5/default/s5-core.css +++ /dev/null @@ -1,9 +0,0 @@ -/* 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;} diff --git a/data/s5/default/slides.css b/data/s5/default/slides.css deleted file mode 100644 index 0786d7dbd..000000000 --- a/data/s5/default/slides.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url(s5-core.css); /* required to make the slide show run at all */ -@import url(framing.css); /* sets basic placement and size of slide components */ -@import url(pretty.css); /* stuff that makes the slides look better than blah */
\ No newline at end of file diff --git a/data/s5/default/slides.js b/data/s5/default/slides.js deleted file mode 100644 index 38fe8531c..000000000 --- a/data/s5/default/slides.js +++ /dev/null @@ -1,553 +0,0 @@ -// 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; // to cope with empty slides - while (menu && menu.nodeType == 3) { - menu = menu.nextSibling; - } - if (!menu) continue; // to cope with slides with only text nodes - - 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; - } -} - -// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) -function keys(key) { - if (!key) { - key = event; - key.which = key.keyCode; - } - if (key.which == 84) { - toggle(); - return; - } - if (s5mode) { - switch (key.which) { - case 10: // return - case 13: // enter - 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: // spacebar - case 34: // page down - case 39: // rightkey - case 40: // downkey - if(number != undef) { - go(number); - } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { - go(1); - } else { - subgo(1); - } - break; - case 33: // page up - case 37: // leftkey - case 38: // upkey - if(number != undef) { - go(-1 * number); - } else if (!incrementals[snum] || incpos <= 0) { - go(-1); - } else { - subgo(-1); - } - break; - case 36: // home - goTo(0); - break; - case 35: // end - goTo(smax-1); - break; - case 67: // c - 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();">Ø<\/a>' + - '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + - '<a accesskey="x" id="next" href="javascript:go(1);">»<\/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() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers - if (!s5mode) return false; - var vScale = 22; // both yield 32 (after rounding) at 1024x768 - var hScale = 32; // perhaps should auto-calculate based on theme's declared value? - 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; // assuming 1024x768, minus chrome and such - var hSize = 1024; // these do not account for kiosk mode or Opera Show - } - var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); - fontSize(newSize + 'px'); - if (isGe) { // hack to counter incremental reflow bugs - 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'); // Gecko fix - slides.setAttribute('href',slideCSS); // Gecko fix - } - 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; - } - } -} - -// Key trap fix, new function body for trap() -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);}
\ No newline at end of file diff --git a/data/sample.lua b/data/sample.lua index a7e9d6337..a0c3c29a2 100644 --- a/data/sample.lua +++ b/data/sample.lua @@ -181,6 +181,10 @@ function Span(s, attr) return "<span" .. attributes(attr) .. ">" .. s .. "</span>" end +function Cite(s) + return "<span class=\"cite\">" .. s .. "</span>" +end + function Plain(s) return s end diff --git a/data/slideous/slideous.css b/data/slideous/slideous.css deleted file mode 100644 index 7d6057069..000000000 --- a/data/slideous/slideous.css +++ /dev/null @@ -1,95 +0,0 @@ -/* This work is licensed under Creative Commons GNU LGPL License. - - License: http://creativecommons.org/licenses/LGPL/2.1/ - Version: 1.0 - - Author: Stefan Goessner/2005 - Web: http://goessner.net/ -*/ -@media screen, projection { -body { - background-color: #e3eee7; - padding: 0; - margin: 0; - color: #132; - border-color: #678; - font-size: 125%; -} -#statusbar { - display: none; - position: absolute; z-index: 10; - top: auto; bottom: 0; left: 0; right: 0; - height: 2em; - background-color: #f0fff8; - color: #132; - font-size: 75%; - padding: 0.5em 0.5em 0 2px; - border-top: solid 1px #000; -} -#statusbar button, #tocbox { - cursor: pointer; - color: #031; - background-color: #e0eee7; - margin: 1px; - padding: 0 0.5em; - border: inset 1px black; -} -#statusbar button:hover, #tocbox:hover { - color: #031; - background-color: #c0ccc6; - border: outset 1px black; -} -#tocbox { - width: 15em; -} -#eos { - visibility: hidden; - color: #021; - background-color: #fffafa; - border: inset 1px black; - font-size: 120%; -} -div.slide { - display: block; - margin: 0 0 2em 0; - padding: 0 150px; -} - -div.slide h1 { - background: #a0aaa4; - color: #f0fff8; - padding: 0 0.5em 0 0.5em; - margin: 0 -150px; - font-size: 120%; - border-bottom: solid 1px black; -} - -div.slide h1:before { content: "# "; } -div.handout { display: block; } - -body>#statusbar { /* ie6 hack for fixing the statusbar - in quirks mode */ - position: fixed; /* thanks to Anne van Kesteren and Arthur Steiner */ -} /* see http://limpid.nl/lab/css/fixed/footer */ -* html body { - overflow: hidden; -} -* html div.slide { - height: 100%; - padding-bottom: 2em; - overflow: auto; -} /* end ie6-hack */ - -} /* @media screen, projection */ - -@media print { -body { - color: black; - font-family: sans-serif; - font-size: 11pt; -} - -#statusbar { display: none; } -div.slide { page-break-after: always; } -div.handout { display: block; } - -} /* @media print */ diff --git a/data/slideous/slideous.js b/data/slideous/slideous.js deleted file mode 100644 index 3e7a63d4a..000000000 --- a/data/slideous/slideous.js +++ /dev/null @@ -1,321 +0,0 @@ -/* This work is licensed under Creative Commons GNU LGPL License. - - License: http://creativecommons.org/licenses/LGPL/2.1/ - - Author: Stefan Goessner/2005-2006 - Web: http://goessner.net/ -*/ -var Slideous = { - version: 1.0, - // == user customisable === - clickables: { a: true, button: true, img: true, input: true, object: true, textarea: true, select: true, option: true }, - incrementables: { blockquote: { filter: "self, parent" }, - dd: { filter: "self, parent" }, - dt: { filter: "self, parent" }, - h2: { filter: "self, parent" }, - h3: { filter: "self, parent" }, - h4: { filter: "self, parent" }, - h5: { filter: "self, parent" }, - h6: { filter: "self, parent" }, - li: { filter: "self, parent" }, - p: { filter: "self" }, - pre: { filter: "self" }, - img: { filter: "self, parent" }, - object: { filter: "self, parent" }, - table: { filter: "self, parent" }, - td: { filter: "self, parent" }, - th: { filter: "self, parent" }, - tr: { filter: "parent, grandparent" } - }, - autoincrementables: { ol: true, ul: true, dl: true }, - autoincrement: false, - statusbar: true, - navbuttons: { incfontbutton: function(){Slideous.changefontsize(+Slideous.fontdelta);}, - decfontbutton: function(){Slideous.changefontsize(-Slideous.fontdelta);}, - contentbutton: function(){Slideous.gotoslide(Slideous.tocidx(), true, true);}, - homebutton: function(){Slideous.gotoslide(1, true, true);}, - prevslidebutton: function(){Slideous.previous(false);}, - previtembutton: function(){Slideous.previous(true);}, - nextitembutton: function(){Slideous.next(true);}, - nextslidebutton: function(){Slideous.next(false);}, - endbutton: function(){Slideous.gotoslide(Slideous.count,true,true);} }, - fontsize: 125, // in percent, corresponding to body.font-size in css file - fontdelta: 5, // increase/decrease fontsize by this value - mousesensitive: true, - tocidx: 0, - tocitems: { toc: "<li><a href=\"#s{\$slideidx}\">{\$slidetitle}</a></li>", - tocbox: "<option value=\"#s{\$slideidx}\" title=\"{\$slidetitle}\">{\$slidetitle}</option>" }, - keydown: function(evt) { - evt = evt || window.event; - var key = evt.keyCode || evt.which; - if (key && !evt.ctrlKey && !evt.altKey) { - switch (key) { - case 33: // page up ... previous slide - Slideous.previous(false); evt.cancel = !Slideous.showall; break; - case 37: // left arrow ... previous item - Slideous.previous(true); evt.cancel = !Slideous.showall; break; - case 32: // space bar - case 39: // right arrow - Slideous.next(true); evt.cancel = !Slideous.showall; break; - case 13: // carriage return ... next slide - case 34: // page down - Slideous.next(false); evt.cancel = !Slideous.showall; break; - case 35: // end ... last slide (not recognised by opera) - Slideous.gotoslide(Slideous.count, true, true); evt.cancel = !Slideous.showall; break; - case 36: // home ... first slide (not recognised by opera) - Slideous.gotoslide(1, true, true); evt.cancel = !Slideous.showall; break; - case 65: // A ... show All - case 80: // P ... Print mode - Slideous.toggleshowall(!Slideous.showall); evt.cancel = true; break; - case 67: // C ... goto contents - Slideous.gotoslide(Slideous.tocidx, true, true); evt.cancel = true; break; - case 77: // M ... toggle mouse sensitivity - Slideous.mousenavigation(Slideous.mousesensitive = !Slideous.mousesensitive); evt.cancel = true; break; - case 83: // S ... toggle statusbar - Slideous.togglestatusbar(); evt.cancel = true; break; - case 61: // + ... increase fontsize - case 107: - Slideous.changefontsize(+Slideous.fontdelta); evt.cancel = true; break; - case 109: // - ... decrease fontsize - Slideous.changefontsize(-Slideous.fontdelta); evt.cancel = true; break; - default: break; - } - if (evt.cancel) evt.returnValue = false; - } - return !evt.cancel; - }, - - // == program logic === - count: 0, // # of slides .. - curidx: 0, // current slide index .. - mousedownpos: null, // last mouse down position .. - contentselected: false, // indicates content selection .. - showall: true, - init: function() { - Slideous.curidx = 1; - Slideous.importproperties(); - Slideous.registerslides(); - document.body.innerHTML = Slideous.injectproperties(document.body.innerHTML); - Slideous.buildtocs(); - Slideous.registeranchors(); - Slideous.toggleshowall(false); - Slideous.updatestatus(); - document.body.style.fontSize = Slideous.fontsize+"%"; - document.getElementById("s1").style.display = "block"; - document.onkeydown = Slideous.keydown; - Slideous.mousenavigation(Slideous.mousesensitive); - Slideous.registerbuttons(); - if (window.location.hash) - Slideous.gotoslide(window.location.hash.substr(2), true, true); - }, - registerslides: function() { - var div = document.getElementsByTagName("div"); - Slideous.count = 0; - for (var i in div) - if (Slideous.hasclass(div[i], "slide")) - div[i].setAttribute("id", "s"+(++Slideous.count)); - }, - registeranchors: function() { - var a = document.getElementsByTagName("a"), - loc = (window.location.hostname+window.location.pathname).replace(/\\/g, "/"); - for (var i in a) { - if (a[i].href && a[i].href.indexOf(loc) >= 0 && a[i].href.lastIndexOf("#") >= 0) { - a[i].href = "javascript:Slideous.gotoslide(" + a[i].href.substr(a[i].href.lastIndexOf("#")+2)+",true,true)"; - } - } - }, - registerbuttons: function() { - var button; - for (var b in Slideous.navbuttons) - if (button = document.getElementById(b)) - button.onclick = Slideous.navbuttons[b]; - }, - importproperties: function() { // from html meta section .. - var meta = document.getElementsByTagName("meta"), elem; - for (var i in meta) - if (meta[i].attributes && meta[i].attributes["name"] && meta[i].attributes["name"].value in Slideous) - switch (typeof(Slideous[meta[i].attributes["name"].value])) { - case "number": Slideous[meta[i].attributes["name"].value] = parseInt(meta[i].attributes["content"].value); break; - case "boolean": Slideous[meta[i].attributes["name"].value] = meta[i].attributes["content"].value == "true" ? true : false; break; - default: Slideous[meta[i].attributes["name"].value] = meta[i].attributes["content"].value; break; - } - }, - injectproperties: function(str) { - var meta = document.getElementsByTagName("meta"), elem; - for (var i in meta) { - if (meta[i].attributes && meta[i].attributes["name"]) - str = str.replace(new RegExp("{\\$"+meta[i].attributes["name"].value+"}","g"), meta[i].attributes["content"].value); - } - return str = str.replace(/{\$generator}/g, "Slideous") - .replace(/{\$version}/g, Slideous.version) - .replace(/{\$title}/g, document.title) - .replace(/{\$slidecount}/g, Slideous.count); - }, - buildtocs: function() { - var toc = document.getElementById("toc"), list = "", - tocbox = document.getElementById("tocbox"); - if (toc) { - for (var i=0; i<Slideous.count; i++) - list += Slideous.tocitems.toc.replace(/{\$slideidx}/g, i+1).replace(/{\$slidetitle}/, document.getElementById("s"+(i+1)).getElementsByTagName("h1")[0].innerHTML); - toc.innerHTML = list; - while (toc && !Slideous.hasclass(toc, "slide")) toc = toc.parentNode; - if (toc) Slideous.tocidx = toc.getAttribute("id").substr(1); - } - if (tocbox) { - tocbox.innerHTML = ""; - for (var i=0; i<Slideous.count; i++) - tocbox.options[tocbox.length] = new Option((i+1)+". "+document.getElementById("s"+(i+1)).getElementsByTagName("h1")[0].innerHTML, "#s"+(i+1)); - tocbox.onchange = function() { Slideous.gotoslide(this.selectedIndex+1, true, true); }; - } - }, - next: function(deep) { - if (!Slideous.showall) { - var slide = document.getElementById("s"+Slideous.curidx), - item = Slideous.firstitem(slide, Slideous.isitemhidden); - if (deep) { // next item - if (item) - Slideous.displayitem(item, true); - else - Slideous.gotoslide(Slideous.curidx+1, false, false); - } - else if (item) // complete slide .. - while (item = Slideous.firstitem(slide, Slideous.isitemhidden)) - Slideous.displayitem(item, true); - else // next slide - Slideous.gotoslide(Slideous.curidx+1, true, false); - Slideous.updatestatus(); - } - }, - previous: function(deep) { - if (!Slideous.showall) { - var slide = document.getElementById("s"+Slideous.curidx); - if (deep) { - var item = Slideous.lastitem(slide, Slideous.isitemvisible); - if (item) - Slideous.displayitem(item, false); - else - Slideous.gotoslide(Slideous.curidx-1, true, false); - } - else - Slideous.gotoslide(Slideous.curidx-1, true, false); - Slideous.updatestatus(); - } - }, - gotoslide: function(i, showitems, updatestatus) { - if (!Slideous.showall && i > 0 && i <= Slideous.count && i != Slideous.curidx) { - document.getElementById("s"+Slideous.curidx).style.display = "none"; - var slide = document.getElementById("s"+(Slideous.curidx=i)), item; - while (item = Slideous.firstitem(slide, showitems ? Slideous.isitemhidden : Slideous.isitemvisible)) - Slideous.displayitem(item, showitems); - slide.style.display = "block"; - if (updatestatus) - Slideous.updatestatus(); - } - }, - firstitem: function(root, filter) { - var found = filter(root); - for (var node=root.firstChild; node!=null && !found; node = node.nextSibling) - found = Slideous.firstitem(node, filter); - return found; - }, - lastitem: function(root, filter) { - var found = null; - for (var node=root.lastChild; node!=null && !found; node = node.previousSibling) - found = Slideous.lastitem(node, filter); - return found || filter(root); - }, - isitem: function(node, visible) { - var nodename; - return node && node.nodeType == 1 // elements only .. - && (nodename=node.nodeName.toLowerCase()) in Slideous.incrementables - && ( Slideous.incrementables[nodename].filter.match("\\bself\\b") && (Slideous.hasclass(node, "incremental") || (Slideous.autoincrement && nodename in Slideous.autoincrementables)) - || Slideous.incrementables[nodename].filter.match("\\bparent\\b") && (Slideous.hasclass(node.parentNode, "incremental") || (Slideous.autoincrement && node.parentNode.nodeName.toLowerCase() in Slideous.autoincrementables)) - || Slideous.incrementables[nodename].filter.match("\\bgrandparent\\b") && (Slideous.hasclass(node.parentNode.parentNode, "incremental") || (Slideous.autoincrement && node.parentNode.parentNode.nodeName.toLowerCase() in Slideous.autoincrementables)) - ) - && (visible ? (node.style.visibility != "hidden") - : (node.style.visibility == "hidden")) - ? node : null; - }, - isitemvisible: function(node) { return Slideous.isitem(node, true); }, - isitemhidden: function(node) { return Slideous.isitem(node, false); }, - displayitem: function(item, show) { - if (item) item.style.visibility = (show ? "visible" : "hidden"); - }, - updatestatus: function() { - if (Slideous.statusbar) { - var eos = document.getElementById("eos"), - idx = document.getElementById("slideidx"), - tocbox = document.getElementById("tocbox"); - if (eos) - eos.style.visibility = Slideous.firstitem(document.getElementById("s"+Slideous.curidx), Slideous.isitemhidden) != null - ? "visible" : "hidden"; - if (idx) - idx.innerHTML = Slideous.curidx; - if (tocbox) - tocbox.selectedIndex = Slideous.curidx-1; - } - }, - changefontsize: function(delta) { - document.body.style.fontSize = (Slideous.fontsize+=delta)+"%"; - }, - togglestatusbar: function() { - document.getElementById("statusbar").style.display = (Slideous.statusbar = !Slideous.statusbar) ? "block" : "none"; - }, - toggleshowall: function(showall) { - var slide, item; - for (var i=0; i<Slideous.count; i++) { - slide = document.getElementById("s"+(i+1)); - slide.style.display = showall ? "block" : "none"; - while (item = Slideous.firstitem(slide, showall ? Slideous.isitemhidden : Slideous.isitemvisible)) - Slideous.displayitem(item, showall); - var divs = slide.getElementsByTagName("div"); - for (var j in divs) - if (Slideous.hasclass(divs[j], "handout")) - divs[j].style.display = showall ? "block" : "none"; - } - if (!showall) - document.getElementById("s"+Slideous.curidx).style.display = "block"; - if (Slideous.statusbar) - document.getElementById("statusbar").style.display = showall ? "none" : "block"; - Slideous.showall = showall; - }, - hasclass: function(elem, classname) { - var classattr = null; - return (classattr=(elem.attributes && elem.attributes["class"])) - && classattr.nodeValue.match("\\b"+classname+"\\b"); - }, - selectedcontent: function() { - return window.getSelection ? window.getSelection().toString() - : document.getSelection ? document.getSelection() - : document.selection ? document.selection.createRange().text - : ""; - }, - mousenavigation: function(on) { - if (on) { - document.onmousedown = Slideous.mousedown; - document.onmouseup = Slideous.mouseup; - } - else - document.onmousedown = document.onmouseup = null; - }, - mousepos: function(e) { - return e.pageX ? {x: e.pageX, y: e.pageY} - : {x: e.x+document.body.scrollLeft, y: e.y+document.body.scrollTop}; - }, - mousedown: function(evt) { - evt = evt||window.event; - Slideous.mousedownpos = Slideous.mousepos(evt); - Slideous.contentselected = !!Slideous.selectedcontent() || ((evt.target || evt.srcElement).nodeName.toLowerCase() in Slideous.clickables); - return true; - }, - mouseup: function(evt) { - evt = evt||window.event; - var pos = Slideous.mousepos(evt); - if (pos.x == Slideous.mousedownpos.x && pos.y == Slideous.mousedownpos.y && !Slideous.contentselected) { - Slideous.next(true); - return evt.returnValue = !(evt.cancel = true); - } - return false; - } -}; -window.onload = Slideous.init; diff --git a/data/slidy/graphics/fold-dim.gif b/data/slidy/graphics/fold-dim.gif Binary files differdeleted file mode 100644 index 346fcbf3e..000000000 --- a/data/slidy/graphics/fold-dim.gif +++ /dev/null diff --git a/data/slidy/graphics/fold.gif b/data/slidy/graphics/fold.gif Binary files differdeleted file mode 100644 index 133e594fd..000000000 --- a/data/slidy/graphics/fold.gif +++ /dev/null diff --git a/data/slidy/graphics/nofold-dim.gif b/data/slidy/graphics/nofold-dim.gif Binary files differdeleted file mode 100644 index 996fb5eda..000000000 --- a/data/slidy/graphics/nofold-dim.gif +++ /dev/null diff --git a/data/slidy/graphics/unfold-dim.gif b/data/slidy/graphics/unfold-dim.gif Binary files differdeleted file mode 100644 index bee567117..000000000 --- a/data/slidy/graphics/unfold-dim.gif +++ /dev/null diff --git a/data/slidy/graphics/unfold.gif b/data/slidy/graphics/unfold.gif Binary files differdeleted file mode 100644 index 0753ae4d2..000000000 --- a/data/slidy/graphics/unfold.gif +++ /dev/null diff --git a/data/slidy/scripts/slidy.js b/data/slidy/scripts/slidy.js deleted file mode 100644 index a4101fe2c..000000000 --- a/data/slidy/scripts/slidy.js +++ /dev/null @@ -1,3016 +0,0 @@ -/* slidy.js - - Copyright (c) 2005-2011 W3C (MIT, ERCIM, Keio), All Rights Reserved. - W3C liability, trademark, document use and software licensing - rules apply, see: - - http://www.w3.org/Consortium/Legal/copyright-documents - http://www.w3.org/Consortium/Legal/copyright-software - - Defines single name "w3c_slidy" in global namespace - Adds event handlers without trampling on any others -*/ - -// the slidy object implementation -var w3c_slidy = { - // classify which kind of browser we're running under - ns_pos: (typeof window.pageYOffset!='undefined'), - khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false), - opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false), - ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false), - iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false), - android: ((navigator.userAgent).indexOf("Android") >= 0 ? true : false), - ie: (typeof document.all != "undefined" && !this.opera), - ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1), - ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1), - ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1), - ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1), - - // data for swipe and double tap detection on touch screens - last_tap: 0, - prev_tap: 0, - start_x: 0, - start_y: 0, - delta_x: 0, - delta_y: 0, - - // are we running as XHTML? (doesn't work on Opera) - is_xhtml: /xml/.test(document.contentType), - - slide_number: 0, // integer slide count: 0, 1, 2, ... - slide_number_element: null, // element containing slide number - slides: [], // set to array of slide div's - notes: [], // set to array of handout div's - backgrounds: [], // set to array of background div's - toolbar: null, // element containing toolbar - title: null, // document title - last_shown: null, // last incrementally shown item - eos: null, // span element for end of slide indicator - toc: null, // table of contents - outline: null, // outline element with the focus - selected_text_len: 0, // length of drag selection on document - view_all: 0, // 1 to view all slides + handouts - want_toolbar: true, // user preference to show/hide toolbar - mouse_click_enabled: true, // enables left click for next slide - scroll_hack: 0, // IE work around for position: fixed - disable_slide_click: false, // used by clicked anchors - - lang: "en", // updated to language specified by html file - - help_anchor: null, // used for keyboard focus hack in showToolbar() - help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html", - help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " + - "or Pg Up and Pg Dn. Use S and B to change font size.", - - size_index: 0, - size_adjustment: 0, - sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt", - "22pt", "24pt", "26pt", "28pt", "30pt", "32pt"), - - // needed for efficient resizing - last_width: 0, - last_height: 0, - - - // Needed for cross browser support for relative width/height on - // object elements. The work around is to save width/height attributes - // and then to recompute absolute width/height dimensions on resizing - objects: [], - - // attach initialiation event handlers - set_up: function () { - var init = function() { w3c_slidy.init(); }; - if (typeof window.addEventListener != "undefined") - window.addEventListener("load", init, false); - else - window.attachEvent("onload", init); - }, - - hide_slides: function () { - if (document.body && !w3c_slidy.initialized) - document.body.style.visibility = "hidden"; - else - setTimeout(w3c_slidy.hide_slides, 50); - }, - - // hack to persuade IE to compute correct document height - // as needed for simulating fixed positioning of toolbar - ie_hack: function () { - window.resizeBy(0,-1); - window.resizeBy(0, 1); - }, - - init: function () { - //alert("slidy starting test 10"); - document.body.style.visibility = "visible"; - this.init_localization(); - this.add_toolbar(); - this.wrap_implicit_slides(); - this.collect_slides(); - this.collect_notes(); - this.collect_backgrounds(); - this.objects = document.body.getElementsByTagName("object"); - this.patch_anchors(); - this.slide_number = this.find_slide_number(location.href); - window.offscreenbuffering = true; - this.size_adjustment = this.find_size_adjust(); - this.time_left = this.find_duration(); - this.hide_image_toolbar(); // suppress IE image toolbar popup - this.init_outliner(); // activate fold/unfold support - this.title = document.title; - this.keyboardless = (this.ipad||this.iphone||this.android); - - if (this.keyboardless) - { - w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden") - this.want_toolbar = 0; - } - - // work around for opera bug - this.is_xhtml = (document.body.tagName == "BODY" ? false : true); - - if (this.slides.length > 0) - { - var slide = this.slides[this.slide_number]; - - if (this.slide_number > 0) - { - this.set_visibility_all_incremental("visible"); - this.last_shown = this.previous_incremental_item(null); - this.set_eos_status(true); - } - else - { - this.last_shown = null; - this.set_visibility_all_incremental("hidden"); - this.set_eos_status(!this.next_incremental_item(this.last_shown)); - } - - this.set_location(); - this.add_class(this.slides[0], "first-slide"); - w3c_slidy.show_slide(slide); - } - - this.toc = this.table_of_contents(); - - this.add_initial_prompt(); - - // bind event handlers without interfering with custom page scripts - // Tap events behave too weirdly to support clicks reliably on - // iPhone and iPad, so exclude these from click handler - - if (!this.keyboardless) - { - this.add_listener(document.body, "click", this.mouse_button_click); - this.add_listener(document.body, "mousedown", this.mouse_button_down); - } - - this.add_listener(document, "keydown", this.key_down); - this.add_listener(document, "keypress", this.key_press); - this.add_listener(window, "resize", this.resized); - this.add_listener(window, "scroll", this.scrolled); - this.add_listener(window, "unload", this.unloaded); - - //this.add_listener(document.body, "touchstart", this.touchstart); - //this.add_listener(document.body, "touchmove", this.touchmove); - //this.add_listener(document.body, "touchend", this.touchend); - - this.add_listener(document, "gesturechange", function () - { - return false; - }); - - this.attach_touch_handers(this.slides); - - // this seems to be a debugging hack - //if (!document.body.onclick) - // document.body.onclick = function () { }; - - this.single_slide_view(); - - //this.set_location(); - - this.resized(); - - if (this.ie7) - setTimeout(w3c_slidy.ie_hack, 100); - - this.show_toolbar(); - - // for back button detection - setInterval(function () { w3c_slidy.check_location(); }, 200); - w3c_slidy.initialized = true; - }, - - // create div element with links to each slide - table_of_contents: function () { - var toc = this.create_element("div"); - this.add_class(toc, "slidy_toc hidden"); - //toc.setAttribute("tabindex", "0"); - - var heading = this.create_element("div"); - this.add_class(heading, "toc-heading"); - heading.innerHTML = this.localize("Table of Contents"); - - toc.appendChild(heading); - var previous = null; - - for (var i = 0; i < this.slides.length; ++i) - { - var title = this.has_class(this.slides[i], "title"); - var num = document.createTextNode((i + 1) + ". "); - - toc.appendChild(num); - - var a = this.create_element("a"); - a.setAttribute("href", "#(" + (i+1) + ")"); - - if (title) - this.add_class(a, "titleslide"); - - var name = document.createTextNode(this.slide_name(i)); - a.appendChild(name); - a.onclick = w3c_slidy.toc_click; - a.onkeydown = w3c_slidy.toc_key_down; - a.previous = previous; - - if (previous) - previous.next = a; - - toc.appendChild(a); - - if (i == 0) - toc.first = a; - - if (i < this.slides.length - 1) - { - var br = this.create_element("br"); - toc.appendChild(br); - } - - previous = a; - } - - toc.focus = function () { - if (this.first) - this.first.focus(); - } - - toc.onmouseup = w3c_slidy.mouse_button_up; - - toc.onclick = function (e) { - e||(e=window.event); - - if (w3c_slidy.selected_text_len <= 0) - w3c_slidy.hide_table_of_contents(true); - - w3c_slidy.stop_propagation(e); - - if (e.cancel != undefined) - e.cancel = true; - - if (e.returnValue != undefined) - e.returnValue = false; - - return false; - }; - - document.body.insertBefore(toc, document.body.firstChild); - return toc; - }, - - is_shown_toc: function () { - return !w3c_slidy.has_class(w3c_slidy.toc, "hidden"); - }, - - show_table_of_contents: function () { - w3c_slidy.remove_class(w3c_slidy.toc, "hidden"); - var toc = w3c_slidy.toc; - toc.focus(); - - if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0) - setTimeout(w3c_slidy.ie_hack, 100); - }, - - hide_table_of_contents: function (focus) { - w3c_slidy.add_class(w3c_slidy.toc, "hidden"); - - if (focus && !w3c_slidy.opera && - !w3c_slidy.has_class(w3c_slidy.toc, "hidden")) - w3c_slidy.help_anchor.focus(); - }, - - toggle_table_of_contents: function () { - if (w3c_slidy.is_shown_toc()) - w3c_slidy.hide_table_of_contents(true); - else - w3c_slidy.show_table_of_contents(); - }, - - // called on clicking toc entry - toc_click: function (e) { - if (!e) - e = window.event; - - var target = w3c_slidy.get_target(e); - - if (target && target.nodeType == 1) - { - var uri = target.getAttribute("href"); - - if (uri) - { - //alert("going to " + uri); - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri); - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.last_shown = null; - w3c_slidy.set_location(); - w3c_slidy.set_visibility_all_incremental("hidden"); - w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); - w3c_slidy.show_slide(slide); - //target.focus(); - - try - { - if (!w3c_slidy.opera) - w3c_slidy.help_anchor.focus(); - } - catch (e) - { - } - } - } - - w3c_slidy.hide_table_of_contents(true); - if (w3c_slidy.ie7) w3c_slidy.ie_hack(); - w3c_slidy.stop_propagation(e); - return w3c_slidy.cancel(e); - }, - - // called onkeydown for toc entry - toc_key_down: function (event) { - var key; - - if (!event) - var event = window.event; - - // kludge around NS/IE differences - if (window.event) - key = window.event.keyCode; - else if (event.which) - key = event.which; - else - return true; // Yikes! unknown browser - - // ignore event if key value is zero - // as for alt on Opera and Konqueror - if (!key) - return true; - - // check for concurrent control/command/alt key - // but are these only present on mouse events? - - if (event.ctrlKey || event.altKey) - return true; - - if (key == 13) - { - var uri = this.getAttribute("href"); - - if (uri) - { - //alert("going to " + uri); - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri); - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.last_shown = null; - w3c_slidy.set_location(); - w3c_slidy.set_visibility_all_incremental("hidden"); - w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); - w3c_slidy.show_slide(slide); - //target.focus(); - - try - { - if (!w3c_slidy.opera) - w3c_slidy.help_anchor.focus(); - } - catch (e) - { - } - } - - w3c_slidy.hide_table_of_contents(true); - - if (self.ie7) - w3c_slidy.ie_hack(); - - return w3c_slidy.cancel(event); - } - - if (key == 40 && this.next) - { - this.next.focus(); - return w3c_slidy.cancel(event); - } - - if (key == 38 && this.previous) - { - this.previous.focus(); - return w3c_slidy.cancel(event); - } - - return true; - }, - - touchstart: function (e) - { - //e.preventDefault(); - this.prev_tap = this.last_tap; - this.last_tap = (new Date).getTime(); - - var tap_delay = this.last_tap - this.prev_tap; - - if (tap_delay <= 200) - { - // double tap - } - - var touch = e.touches[0]; - - this.start_x = touch.pageX; - this.start_y = touch.pageY; - this.delta_x = this.delta_y = 0; - }, - - touchmove: function (e) - { - //e.preventDefault(); - var touch = e.touches[0]; - this.delta_x = touch.pageX - this.start_x; - this.delta_y = touch.pageY - this.start_y; - }, - - touchend: function (e) - { - //e.preventDefault(); - var delay = (new Date).getTime() - this.last_tap; - var dx = this.delta_x; - var dy = this.delta_y; - var abs_dx = Math.abs(dx); - var abs_dy = Math.abs(dy); - - if (delay < 500 && (abs_dx > 100 || abs_dy > 100)) - { - if (abs_dx > 0.5 * abs_dy) - { - if (dx < 0) - w3c_slidy.next_slide(true); - else - w3c_slidy.previous_slide(true); - } - else if (abs_dy > 2 * abs_dx) - { - w3c_slidy.toggle_table_of_contents(); - } - } - }, - - // ### OBSOLETE ### - before_print: function () { - this.show_all_slides(); - this.hide_toolbar(); - alert("before print"); - }, - - // ### OBSOLETE ### - after_print: function () { - if (!this.view_all) - { - this.single_slide_view(); - this.show_toolbar(); - } - alert("after print"); - }, - - // ### OBSOLETE ### - print_slides: function () { - this.before_print(); - window.print(); - this.after_print(); - }, - - // ### OBSOLETE ?? ### - toggle_view: function () { - if (this.view_all) - { - this.single_slide_view(); - this.show_toolbar(); - this.view_all = 0; - } - else - { - this.show_all_slides(); - this.hide_toolbar(); - this.view_all = 1; - } - }, - - // prepare for printing ### OBSOLETE ### - show_all_slides: function () { - this.remove_class(document.body, "single_slide"); - this.set_visibility_all_incremental("visible"); - }, - - // restore after printing ### OBSOLETE ### - single_slide_view: function () { - this.add_class(document.body, "single_slide"); - this.set_visibility_all_incremental("visible"); - this.last_shown = this.previous_incremental_item(null); - }, - - // suppress IE's image toolbar pop up - hide_image_toolbar: function () { - if (!this.ns_pos) - { - var images = document.getElementsByTagName("IMG"); - - for (var i = 0; i < images.length; ++i) - images[i].setAttribute("galleryimg", "no"); - } - }, - - unloaded: function (e) { - //alert("unloaded"); - }, - - // Safari and Konqueror don't yet support getComputedStyle() - // and they always reload page when location.href is updated - is_KHTML: function () { - var agent = navigator.userAgent; - return (agent.indexOf("KHTML") >= 0 ? true : false); - }, - - // find slide name from first h1 element - // default to document title + slide number - slide_name: function (index) { - var name = null; - var slide = this.slides[index]; - - var heading = this.find_heading(slide); - - if (heading) - name = this.extract_text(heading); - - if (!name) - name = this.title + "(" + (index + 1) + ")"; - - name.replace(/\&/g, "&"); - name.replace(/\</g, "<"); - name.replace(/\>/g, ">"); - - return name; - }, - - // find first h1 element in DOM tree - find_heading: function (node) { - if (!node || node.nodeType != 1) - return null; - - if (node.nodeName == "H1" || node.nodeName == "h1") - return node; - - var child = node.firstChild; - - while (child) - { - node = this.find_heading(child); - - if (node) - return node; - - child = child.nextSibling; - } - - return null; - }, - - // recursively extract text from DOM tree - extract_text: function (node) { - if (!node) - return ""; - - // text nodes - if (node.nodeType == 3) - return node.nodeValue; - - // elements - if (node.nodeType == 1) - { - node = node.firstChild; - var text = ""; - - while (node) - { - text = text + this.extract_text(node); - node = node.nextSibling; - } - - return text; - } - - return ""; - }, - - // find copyright text from meta element - find_copyright: function () { - 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; - }, - - find_size_adjust: function () { - 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; - }, - - // <meta name="duration" content="20" /> for 20 minutes - find_duration: function () { - 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 == "duration") - return 60000 * content; - } - - return null; - }, - - replace_by_non_breaking_space: function (str) { - for (var i = 0; i < str.length; ++i) - str[i] = 160; - }, - - // ### CHECK ME ### is use of "li" okay for text/html? - // for XHTML do we also need to specify namespace? - init_outliner: function () { - var items = document.getElementsByTagName("li"); - - for (var i = 0; i < items.length; ++i) - { - var target = items[i]; - - if (!this.has_class(target.parentNode, "outline")) - continue; - - target.onclick = this.outline_click; -/* ### more work needed for IE6 - if (!this.ns_pos) - { - target.onmouseover = this.hover_outline; - target.onmouseout = this.unhover_outline; - } -*/ - if (this.foldable(target)) - { - target.foldable = true; - target.onfocus = function () {w3c_slidy.outline = this;}; - target.onblur = function () {w3c_slidy.outline = null;}; - - if (!target.getAttribute("tabindex")) - target.setAttribute("tabindex", "0"); - - if (this.has_class(target, "expand")) - this.unfold(target); - else - this.fold(target); - } - else - { - this.add_class(target, "nofold"); - target.visible = true; - target.foldable = false; - } - } - }, - - foldable: function (item) { - if (!item || item.nodeType != 1) - return false; - - var node = item.firstChild; - - while (node) - { - if (node.nodeType == 1 && this.is_block(node)) - return true; - - node = node.nextSibling; - } - - return false; - }, - - // ### CHECK ME ### switch to add/remove "hidden" class - fold: function (item) { - if (item) - { - this.remove_class(item, "unfolded"); - this.add_class(item, "folded"); - } - - var node = item ? item.firstChild : null; - - while (node) - { - if (node.nodeType == 1 && this.is_block(node)) // element - { - w3c_slidy.add_class(node, "hidden"); - } - - node = node.nextSibling; - } - - item.visible = false; - }, - - // ### CHECK ME ### switch to add/remove "hidden" class - unfold: function (item) { - if (item) - { - this.add_class(item, "unfolded"); - this.remove_class(item, "folded"); - } - - var node = item ? item.firstChild : null; - - while (node) - { - if (node.nodeType == 1 && this.is_block(node)) // element - { - w3c_slidy.remove_class(node, "hidden"); - } - - node = node.nextSibling; - } - - item.visible = true; - }, - - outline_click: function (e) { - if (!e) - e = window.event; - - var rightclick = false; - var target = w3c_slidy.get_target(e); - - 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) - w3c_slidy.fold(target); - else - w3c_slidy.unfold(target); - } - - w3c_slidy.stop_propagation(e); - e.cancel = true; - e.returnValue = false; - } - - return false; - }, - - add_initial_prompt: function () { - var prompt = this.create_element("div"); - prompt.setAttribute("class", "initial_prompt"); - - var p1 = this.create_element("p"); - prompt.appendChild(p1); - p1.setAttribute("class", "help"); - - if (this.keyboardless) - p1.innerHTML = "swipe left to move to next slide"; - else - p1.innerHTML = "Space, Right Arrow or swipe left to move to " + - "next slide, click help below for more details"; - - this.add_listener(prompt, "click", function (e) { - document.body.removeChild(prompt); - w3c_slidy.stop_propagation(e); - - if (e.cancel != undefined) - e.cancel = true; - - if (e.returnValue != undefined) - e.returnValue = false; - - return false; - }); - - document.body.appendChild(prompt); - this.initial_prompt = prompt; - setTimeout(function() {document.body.removeChild(prompt);}, 5000); - }, - - add_toolbar: function () { - var counter, page; - - this.toolbar = this.create_element("div"); - this.toolbar.setAttribute("class", "toolbar"); - - // a reasonably behaved browser - if (this.ns_pos || !this.ie6) - { - var right = this.create_element("div"); - right.setAttribute("style", "float: right; text-align: right"); - - counter = this.create_element("span") - counter.innerHTML = this.localize("slide") + " n/m"; - right.appendChild(counter); - this.toolbar.appendChild(right); - - var left = this.create_element("div"); - left.setAttribute("style", "text-align: left"); - - // global end of slide indicator - this.eos = this.create_element("span"); - this.eos.innerHTML = "* "; - left.appendChild(this.eos); - - var help = this.create_element("a"); - help.setAttribute("href", this.help_page); - help.setAttribute("title", this.localize(this.help_text)); - help.innerHTML = this.localize("help?"); - left.appendChild(help); - this.help_anchor = help; // save for focus hack - - var gap1 = document.createTextNode(" "); - left.appendChild(gap1); - - var contents = this.create_element("a"); - contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()"); - contents.setAttribute("title", this.localize("table of contents")); - contents.innerHTML = this.localize("contents?"); - left.appendChild(contents); - - var gap2 = document.createTextNode(" "); - left.appendChild(gap2); - - var copyright = this.find_copyright(); - - if (copyright) - { - var span = this.create_element("span"); - span.className = "copyright"; - span.innerHTML = copyright; - left.appendChild(span); - } - - this.toolbar.setAttribute("tabindex", "0"); - this.toolbar.appendChild(left); - } - else // IE6 so need to work around its poor CSS support - { - this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute"); - this.toolbar.style.zIndex = "200"; - this.toolbar.style.width = "99.9%"; - this.toolbar.style.height = "1.2em"; - this.toolbar.style.top = "auto"; - this.toolbar.style.bottom = "0"; - this.toolbar.style.left = "0"; - this.toolbar.style.right = "0"; - this.toolbar.style.textAlign = "left"; - this.toolbar.style.fontSize = "60%"; - this.toolbar.style.color = "red"; - this.toolbar.borderWidth = 0; - this.toolbar.className = "toolbar"; - this.toolbar.style.background = "rgb(240,240,240)"; - - // would like to have help text left aligned - // and page counter right aligned, floating - // div's don't work, so instead use nested - // absolutely positioned div's. - - var sp = this.create_element("span"); - sp.innerHTML = " * "; - this.toolbar.appendChild(sp); - this.eos = sp; // end of slide indicator - - var help = this.create_element("a"); - help.setAttribute("href", this.help_page); - help.setAttribute("title", this.localize(this.help_text)); - help.innerHTML = this.localize("help?"); - this.toolbar.appendChild(help); - this.help_anchor = help; // save for focus hack - - var gap1 = document.createTextNode(" "); - this.toolbar.appendChild(gap1); - - var contents = this.create_element("a"); - contents.setAttribute("href", "javascript:toggleTableOfContents()"); - contents.setAttribute("title", this.localize("table of contents".localize)); - contents.innerHTML = this.localize("contents?"); - this.toolbar.appendChild(contents); - - var gap2 = document.createTextNode(" "); - this.toolbar.appendChild(gap2); - - var copyright = this.find_copyright(); - - if (copyright) - { - var span = this.create_element("span"); - span.innerHTML = copyright; - span.style.color = "black"; - span.style.marginLeft = "0.5em"; - this.toolbar.appendChild(span); - } - - counter = this.create_element("div") - counter.style.position = "absolute"; - counter.style.width = "auto"; //"20%"; - counter.style.height = "1.2em"; - counter.style.top = "auto"; - counter.style.bottom = 0; - counter.style.right = "0"; - counter.style.textAlign = "right"; - counter.style.color = "red"; - counter.style.background = "rgb(240,240,240)"; - - counter.innerHTML = this.localize("slide") + " n/m"; - this.toolbar.appendChild(counter); - } - - // ensure that click isn't passed through to the page - this.toolbar.onclick = - function (e) { - if (!e) - e = window.event; - - var target = e.target; - - if (!target && e.srcElement) - target = e.srcElement; - - // work around Safari bug - if (target && target.nodeType == 3) - target = target.parentNode; - - w3c_slidy.stop_propagation(e); - - if (target && target.nodeName.toLowerCase() != "a") - w3c_slidy.mouse_button_click(e); - }; - - this.slide_number_element = counter; - this.set_eos_status(false); - document.body.appendChild(this.toolbar); - }, - - // wysiwyg editors make it hard to use div elements - // e.g. amaya loses the div when you copy and paste - // this function wraps div elements around implicit - // slides which start with an h1 element and continue - // up to the next heading or div element - wrap_implicit_slides: function () { - 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"); - this.add_class(div, "slide"); - document.body.replaceChild(div, heading); - div.appendChild(heading); - - while (node) - { - if (node.nodeType == 1) // an element - { - if (node.nodeName == "H1" || node.nodeName == "h1") - break; - - if (node.nodeName == "DIV" || node.nodeName == "div") - { - if (this.has_class(node, "slide")) - break; - - if (this.has_class(node, "handout")) - break; - } - } - - next = node.nextSibling; - node = document.body.removeChild(node); - div.appendChild(node); - node = next; - } - } - }, - - attach_touch_handers: function(slides) - { - var i, slide; - - for (i = 0; i < slides.length; ++i) - { - slide = slides[i]; - this.add_listener(slide, "touchstart", this.touchstart); - this.add_listener(slide, "touchmove", this.touchmove); - this.add_listener(slide, "touchend", this.touchend); - } - }, - -// return new array of all slides - collect_slides: function () { - var slides = new Array(); - var divs = document.body.getElementsByTagName("div"); - - for (var i = 0; i < divs.length; ++i) - { - div = divs.item(i); - - if (this.has_class(div, "slide")) - { - // add slide to collection - slides[slides.length] = div; - - // hide each slide as it is found - this.add_class(div, "hidden"); - - // add dummy <br/> at end for scrolling hack - var node1 = document.createElement("br"); - div.appendChild(node1); - var node2 = document.createElement("br"); - div.appendChild(node2); - } - else if (this.has_class(div, "background")) - { // work around for Firefox SVG reload bug - // which otherwise replaces 1st SVG graphic with 2nd - div.style.display = "block"; - } - } - - this.slides = slides; - }, - - // return new array of all <div class="handout"> - collect_notes: function () { - var notes = new Array(); - var divs = document.body.getElementsByTagName("div"); - - for (var i = 0; i < divs.length; ++i) - { - div = divs.item(i); - - if (this.has_class(div, "handout")) - { - // add note to collection - notes[notes.length] = div; - - // and hide it - this.add_class(div, "hidden"); - } - } - - this.notes = notes; - }, - - // return new array of all <div class="background"> - // including named backgrounds e.g. class="background titlepage" - collect_backgrounds: function () { - var backgrounds = new Array(); - var divs = document.body.getElementsByTagName("div"); - - for (var i = 0; i < divs.length; ++i) - { - div = divs.item(i); - - if (this.has_class(div, "background")) - { - // add background to collection - backgrounds[backgrounds.length] = div; - - // and hide it - this.add_class(div, "hidden"); - } - } - - this.backgrounds = backgrounds; - }, - - // set click handlers on all anchors - patch_anchors: function () { - var self = w3c_slidy; - var handler = function (event) { - // compare this.href with location.href - // for link to another slide in this doc - - if (self.page_address(this.href) == self.page_address(location.href)) - { - // yes, so find new slide number - var newslidenum = self.find_slide_number(this.href); - - if (newslidenum != self.slide_number) - { - var slide = self.slides[self.slide_number]; - self.hide_slide(slide); - self.slide_number = newslidenum; - slide = self.slides[self.slide_number]; - self.show_slide(slide); - self.set_location(); - } - } - else - w3c_slidy.stop_propagation(event); - -// else if (this.target == null) -// location.href = this.href; - - this.blur(); - self.disable_slide_click = true; - }; - - var anchors = document.body.getElementsByTagName("a"); - - for (var i = 0; i < anchors.length; ++i) - { - if (window.addEventListener) - anchors[i].addEventListener("click", handler, false); - else - anchors[i].attachEvent("onclick", handler); - } - }, - - // ### CHECK ME ### see which functions are invoked via setTimeout - // either directly or indirectly for use of w3c_slidy vs this - show_slide_number: function () { - var timer = w3c_slidy.get_timer(); - w3c_slidy.slide_number_element.innerHTML = timer + w3c_slidy.localize("slide") + " " + - (w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length; - }, - - // every 200mS check if the location has been changed as a - // result of the user activating the Back button/menu item - // doesn't work for Opera < 9.5 - check_location: function () { - var hash = location.hash; - - if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#")) - w3c_slidy.goto_slide(0); - else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")") - { - var num = parseInt(location.hash.substr(2)); - - if (!isNaN(num)) - w3c_slidy.goto_slide(num-1); - } - - if (w3c_slidy.time_left && w3c_slidy.slide_number > 0) - { - w3c_slidy.show_slide_number(); - - if (w3c_slidy.time_left > 0) - w3c_slidy.time_left -= 200; - } - }, - - get_timer: function () { - var timer = ""; - if (w3c_slidy.time_left) - { - var mins, secs; - secs = Math.floor(w3c_slidy.time_left/1000); - mins = Math.floor(secs / 60); - secs = secs % 60; - timer = (mins ? mins+"m" : "") + secs + "s "; - } - - return timer; - }, - - // this doesn't push location onto history stack for IE - // for which a hidden iframe hack is needed: load page into - // the iframe with script that set's parent's location.hash - // but that won't work for standalone use unless we can - // create the page dynamically via a javascript: URL - // ### use history.pushState if available - set_location: function () { - var uri = w3c_slidy.page_address(location.href); - var hash = "#(" + (w3c_slidy.slide_number+1) + ")"; - - if (w3c_slidy.slide_number >= 0) - uri = uri + hash; - - if (typeof(history.pushState) != "undefined") - { - document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")"; - history.pushState(0, document.title, hash); - w3c_slidy.show_slide_number(); - return; - } - - if (w3c_slidy.ie && (w3c_slidy.ie6 || w3c_slidy.ie7)) - w3c_slidy.push_hash(hash); - - if (uri != location.href) // && !khtml - location.href = uri; - - if (this.khtml) - hash = "(" + (w3c_slidy.slide_number+1) + ")"; - - if (!this.ie && location.hash != hash && location.hash != "") - location.hash = hash; - - document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")"; - w3c_slidy.show_slide_number(); - }, - - page_address: function (uri) { - var i = uri.indexOf("#"); - - if (i < 0) - i = uri.indexOf("%23"); - - // check if anchor is entire page - - if (i < 0) - return uri; // yes - - return uri.substr(0, i); - }, - - // only used for IE6 and IE7 - on_frame_loaded: function (hash) { - location.hash = hash; - var uri = w3c_slidy.page_address(location.href); - location.href = uri + hash; - }, - - // history hack with thanks to Bertrand Le Roy - push_hash: function (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\">window.parent.w3c_slidy.on_frame_loaded('"+ - (hash) + "');</script></head><body>hello mum</body></html>"); - doc.close(); - }, - - // find current slide based upon location - // first find target anchor and then look - // for associated div element enclosing it - // finally map that to slide number - find_slide_number: function (uri) { - // first get anchor from page location - - var i = uri.indexOf("#"); - - // check if anchor is entire page - if (i < 0) - return 0; // yes - - var anchor = unescape(uri.substr(i+1)); - - // now use anchor as XML ID to find target - var target = document.getElementById(anchor); - - if (!target) - { - // does anchor look like "(2)" for slide 2 ?? - // where first slide is (1) - var re = /\((\d)+\)/; - - if (anchor.match(re)) - { - var num = parseInt(anchor.substring(1, anchor.length-1)); - - if (num > this.slides.length) - num = 1; - - if (--num < 0) - num = 0; - - return num; - } - - // accept [2] for backwards compatibility - re = /\[(\d)+\]/; - - if (anchor.match(re)) - { - var num = parseInt(anchor.substring(1, anchor.length-1)); - - if (num > this.slides.length) - num = 1; - - if (--num < 0) - num = 0; - - return num; - } - - // oh dear unknown anchor - return 0; - } - - // search for enclosing slide - - while (true) - { - // browser coerces html elements to uppercase! - if (target.nodeName.toLowerCase() == "div" && - this.has_class(target, "slide")) - { - // found the slide element - break; - } - - // otherwise try parent element if any - - target = target.parentNode; - - if (!target) - { - return 0; // no luck! - } - }; - - for (i = 0; i < slides.length; ++i) - { - if (slides[i] == target) - return i; // success - } - - // oh dear still no luck - return 0; - }, - - previous_slide: function (incremental) { - if (!w3c_slidy.view_all) - { - var slide; - - if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null) - { - w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown); - w3c_slidy.set_eos_status(false); - } - else if (w3c_slidy.slide_number > 0) - { - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - - w3c_slidy.slide_number = w3c_slidy.slide_number - 1; - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.set_visibility_all_incremental("visible"); - w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null); - w3c_slidy.set_eos_status(true); - w3c_slidy.show_slide(slide); - } - - w3c_slidy.set_location(); - - if (!w3c_slidy.ns_pos) - w3c_slidy.refresh_toolbar(200); - } - }, - - next_slide: function (incremental) { - if (!w3c_slidy.view_all) - { - var slide, last = w3c_slidy.last_shown; - - if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1) - w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown); - - if ((!incremental || w3c_slidy.last_shown == null) && - w3c_slidy.slide_number < w3c_slidy.slides.length - 1) - { - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - - w3c_slidy.slide_number = w3c_slidy.slide_number + 1; - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.last_shown = null; - w3c_slidy.set_visibility_all_incremental("hidden"); - w3c_slidy.show_slide(slide); - } - else if (!w3c_slidy.last_shown) - { - if (last && incremental) - w3c_slidy.last_shown = last; - } - - w3c_slidy.set_location(); - - w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); - - if (!w3c_slidy.ns_pos) - w3c_slidy.refresh_toolbar(200); - } - }, - - // to first slide with nothing revealed - // i.e. state at start of presentation - first_slide: function () { - if (!w3c_slidy.view_all) - { - var slide; - - if (w3c_slidy.slide_number != 0) - { - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - - w3c_slidy.slide_number = 0; - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.last_shown = null; - w3c_slidy.set_visibility_all_incremental("hidden"); - w3c_slidy.show_slide(slide); - } - - w3c_slidy.set_eos_status( - !w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); - w3c_slidy.set_location(); - } - }, - - // goto last slide with everything revealed - // i.e. state at end of presentation - last_slide: function () { - if (!w3c_slidy.view_all) - { - var slide; - - w3c_slidy.last_shown = null; //revealNextItem(lastShown); - - if (w3c_slidy.last_shown == null && - w3c_slidy.slide_number < w3c_slidy.slides.length - 1) - { - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.slide_number = w3c_slidy.slides.length - 1; - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.set_visibility_all_incremental("visible"); - w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null); - - w3c_slidy.show_slide(slide); - } - else - { - w3c_slidy.set_visibility_all_incremental("visible"); - w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null); - } - - w3c_slidy.set_eos_status(true); - w3c_slidy.set_location(); - } - }, - - - // ### check this and consider add/remove class - set_eos_status: function (state) { - if (this.eos) - this.eos.style.color = (state ? "rgb(240,240,240)" : "red"); - }, - - // first slide is 0 - goto_slide: function (num) { - //alert("going to slide " + (num+1)); - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.slide_number = num; - slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.last_shown = null; - w3c_slidy.set_visibility_all_incremental("hidden"); - w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); - document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")"; - w3c_slidy.show_slide(slide); - w3c_slidy.show_slide_number(); - }, - - - show_slide: function (slide) { - this.sync_background(slide); - this.remove_class(slide, "hidden"); - - // work around IE9 object rendering bug - setTimeout("window.scrollTo(0,0);", 1); - }, - - hide_slide: function (slide) { - this.add_class(slide, "hidden"); - }, - - // show just the backgrounds pertinent to this slide - // when slide background-color is transparent - // this should now work with rgba color values - sync_background: function (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 // broken implementation probably due Safari or Konqueror - { - //alert("defective implementation of getComputedStyle()"); - bgColor = "transparent"; - } - } - else - bgColor == "transparent"; - - if (bgColor == "transparent" || - bgColor.indexOf("rgba") >= 0 || - bgColor.indexOf("opacity") >= 0) - { - var slideClass = this.get_class_list(slide); - - for (var i = 0; i < this.backgrounds.length; i++) - { - background = this.backgrounds[i]; - - var bgClass = this.get_class_list(background); - - if (this.matching_background(slideClass, bgClass)) - this.remove_class(background, "hidden"); - else - this.add_class(background, "hidden"); - } - } - else // forcibly hide all backgrounds - this.hide_backgrounds(); - }, - - hide_backgrounds: function () { - for (var i = 0; i < this.backgrounds.length; i++) - { - background = this.backgrounds[i]; - this.add_class(background, "hidden"); - } - }, - - // compare classes for slide and background - matching_background: function (slideClass, bgClass) { - var i, count, pattern, result; - - // define pattern as regular expression - pattern = /\w+/g; - - // check background class names - result = bgClass.match(pattern); - - for (i = count = 0; i < result.length; i++) - { - if (result[i] == "hidden") - continue; - - if (result[i] == "background") - continue; - - ++count; - } - - if (count == 0) // default match - return true; - - // check for matches and place result in array - result = slideClass.match(pattern); - - // now check if desired name is present for background - for (i = count = 0; i < result.length; i++) - { - if (result[i] == "hidden") - continue; - - if (this.has_token(bgClass, result[i])) - return true; - } - - return false; - }, - - resized: function () { - var width = 0; - - if ( typeof( window.innerWidth ) == 'number' ) - width = window.innerWidth; // Non IE browser - else if (document.documentElement && document.documentElement.clientWidth) - width = document.documentElement.clientWidth; // IE6 - else if (document.body && document.body.clientWidth) - width = document.body.clientWidth; // IE4 - - var height = 0; - - if ( typeof( window.innerHeight ) == 'number' ) - height = window.innerHeight; // Non IE browser - else if (document.documentElement && document.documentElement.clientHeight) - height = document.documentElement.clientHeight; // IE6 - else if (document.body && document.body.clientHeight) - height = document.body.clientHeight; // IE4 - - if (height && (width/height > 1.05*1024/768)) - { - width = height * 1024.0/768; - } - - // IE fires onresize even when only font size is changed! - // so we do a check to avoid blocking < and > actions - if (width != w3c_slidy.last_width || height != w3c_slidy.last_height) - { - if (width >= 1100) - w3c_slidy.size_index = 5; // 4 - else if (width >= 1000) - w3c_slidy.size_index = 4; // 3 - else if (width >= 800) - w3c_slidy.size_index = 3; // 2 - else if (width >= 600) - w3c_slidy.size_index = 2; // 1 - else if (width) - w3c_slidy.size_index = 0; - - // add in font size adjustment from meta element e.g. - // <meta name="font-size-adjustment" content="-2" /> - // useful when slides have too much content ;-) - - if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment && - w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length) - w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment; - - // enables cross browser use of relative width/height - // on object elements for use with SVG and Flash media - w3c_slidy.adjust_object_dimensions(width, height); - - if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index]) - { - document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index]; - } - - w3c_slidy.last_width = width; - w3c_slidy.last_height = height; - - // force reflow to work around Mozilla bug - if (w3c_slidy.ns_pos) - { - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.show_slide(slide); - } - - // force correct positioning of toolbar - w3c_slidy.refresh_toolbar(200); - } - }, - - scrolled: function () { - if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7) - { - w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset(); - // hide toolbar - w3c_slidy.toolbar.style.display = "none"; - - // make it reappear later - if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all) - { - setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000); - w3c_slidy.scrollhack = 1; - } - } - }, - - hide_toolbar: function () { - w3c_slidy.add_class(w3c_slidy.toolbar, "hidden"); - window.focus(); - }, - - // used to ensure IE refreshes toolbar in correct position - refresh_toolbar: function (interval) { - if (!w3c_slidy.ns_pos && !w3c_slidy.ie7) - { - w3c_slidy.hide_toolbar(); - setTimeout(function () {w3c_slidy.show_toolbar();}, interval); - } - }, - - // restores toolbar after short delay - show_toolbar: function () { - if (w3c_slidy.want_toolbar) - { - w3c_slidy.toolbar.style.display = "block"; - - if (!w3c_slidy.ns_pos) - { - // adjust position to allow for scrolling - var xoffset = w3c_slidy.scroll_x_offset(); - w3c_slidy.toolbar.style.left = xoffset; - w3c_slidy.toolbar.style.right = xoffset; - - // determine vertical scroll offset - //var yoffset = scrollYOffset(); - - // bottom is doc height - window height - scroll offset - //var bottom = documentHeight() - lastHeight - yoffset - - //if (yoffset > 0 || documentHeight() > lastHeight) - // bottom += 16; // allow for height of scrollbar - - w3c_slidy.toolbar.style.bottom = 0; //bottom; - } - - w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden"); - } - - w3c_slidy.scrollhack = 0; - - - // set the keyboard focus to the help link on the - // toolbar to ensure that document has the focus - // IE doesn't always work with window.focus() - // and this hack has benefit of Enter for help - - try - { - if (!w3c_slidy.opera) - w3c_slidy.help_anchor.focus(); - } - catch (e) - { - } - }, - -// invoked via F key - toggle_toolbar: function () { - if (!w3c_slidy.view_all) - { - if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden")) - { - w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden") - w3c_slidy.want_toolbar = 1; - } - else - { - w3c_slidy.add_class(w3c_slidy.toolbar, "hidden") - w3c_slidy.want_toolbar = 0; - } - } - }, - - scroll_x_offset: function () { - 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; - }, - - scroll_y_offset: function () { - 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; - }, - - // looking for a way to determine height of slide content - // the slide itself is set to the height of the window - optimize_font_size: function () { - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - - //var dh = documentHeight(); //getDocHeight(document); - var dh = slide.scrollHeight; - var wh = getWindowHeight(); - var u = 100 * dh / wh; - - alert("window utilization = " + u + "% (doc " - + dh + " win " + wh + ")"); - }, - - // from document object - get_doc_height: function (doc) { - if (!doc) - doc = document; - - if (doc && doc.body && doc.body.offsetHeight) - return doc.body.offsetHeight; // ns/gecko syntax - - if (doc && doc.body && doc.body.scrollHeight) - return doc.body.scrollHeight; - - alert("couldn't determine document height"); - }, - - get_window_height: function () { - if ( typeof( window.innerHeight ) == 'number' ) - return window.innerHeight; // Non IE browser - - if (document.documentElement && document.documentElement.clientHeight) - return document.documentElement.clientHeight; // IE6 - - if (document.body && document.body.clientHeight) - return document.body.clientHeight; // IE4 - }, - - document_height: function () { - var sh, oh; - - sh = document.body.scrollHeight; - oh = document.body.offsetHeight; - - if (sh && oh) - { - return (sh > oh ? sh : oh); - } - - // no idea! - return 0; - }, - - smaller: function () { - if (w3c_slidy.size_index > 0) - { - --w3c_slidy.size_index; - } - - w3c_slidy.toolbar.style.display = "none"; - document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index]; - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.show_slide(slide); - setTimeout(function () {w3c_slidy.show_toolbar(); }, 50); - }, - - bigger: function () { - if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1) - { - ++w3c_slidy.size_index; - } - - w3c_slidy.toolbar.style.display = "none"; - document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index]; - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - w3c_slidy.hide_slide(slide); - w3c_slidy.show_slide(slide); - setTimeout(function () {w3c_slidy.show_toolbar(); }, 50); - }, - - // enables cross browser use of relative width/height - // on object elements for use with SVG and Flash media - // with thanks to Ivan Herman for the suggestion - adjust_object_dimensions: function (width, height) { - for( var i = 0; i < w3c_slidy.objects.length; i++ ) - { - var obj = this.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.0); - 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.0); - obj.setAttribute("height", newH); - } - } - } - }, - - // needed for Opera to inhibit default behavior - // since Opera delivers keyPress even if keyDown - // was cancelled - key_press: function (event) { - if (!event) - event = window.event; - - if (!w3c_slidy.key_wanted) - return w3c_slidy.cancel(event); - - return true; - }, - - // See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes - key_down: function (event) { - var key, target, tag; - - w3c_slidy.key_wanted = true; - - if (!event) - event = window.event; - - // kludge around NS/IE differences - if (window.event) - { - key = window.event.keyCode; - target = window.event.srcElement; - } - else if (event.which) - { - key = event.which; - target = event.target; - } - else - return true; // Yikes! unknown browser - - // ignore event if key value is zero - // as for alt on Opera and Konqueror - if (!key) - return true; - - // avoid interfering with keystroke - // behavior for non-slidy chrome elements - if (!w3c_slidy.slidy_chrome(target) && - w3c_slidy.special_element(target)) - return true; - - // check for concurrent control/command/alt key - // but are these only present on mouse events? - - if (event.ctrlKey || event.altKey || event.metaKey) - return true; - - // dismiss table of contents if visible - if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40) - { - w3c_slidy.hide_table_of_contents(true); - - if (key == 27 || key == 84 || key == 67) - return w3c_slidy.cancel(event); - } - - if (key == 34) // Page Down - { - if (w3c_slidy.view_all) - return true; - - w3c_slidy.next_slide(false); - return w3c_slidy.cancel(event); - } - else if (key == 33) // Page Up - { - if (w3c_slidy.view_all) - return true; - - w3c_slidy.previous_slide(false); - return w3c_slidy.cancel(event); - } - else if (key == 32) // space bar - { - w3c_slidy.next_slide(true); - return w3c_slidy.cancel(event); - } - else if (key == 37) // Left arrow - { - w3c_slidy.previous_slide(!event.shiftKey); - return w3c_slidy.cancel(event); - } - else if (key == 36) // Home - { - w3c_slidy.first_slide(); - return w3c_slidy.cancel(event); - } - else if (key == 35) // End - { - w3c_slidy.last_slide(); - return w3c_slidy.cancel(event); - } - else if (key == 39) // Right arrow - { - w3c_slidy.next_slide(!event.shiftKey); - return w3c_slidy.cancel(event); - } - else if (key == 13) // Enter - { - if (w3c_slidy.outline) - { - if (w3c_slidy.outline.visible) - w3c_slidy.fold(w3c_slidy.outline); - else - w3c_slidy.unfold(w3c_slidy.outline); - - return w3c_slidy.cancel(event); - } - } - else if (key == 188) // < for smaller fonts - { - w3c_slidy.smaller(); - return w3c_slidy.cancel(event); - } - else if (key == 190) // > for larger fonts - { - w3c_slidy.bigger(); - return w3c_slidy.cancel(event); - } - else if (key == 189 || key == 109) // - for smaller fonts - { - w3c_slidy.smaller(); - return w3c_slidy.cancel(event); - } - else if (key == 187 || key == 191 || key == 107) // = + for larger fonts - { - w3c_slidy.bigger(); - return w3c_slidy.cancel(event); - } - else if (key == 83) // S for smaller fonts - { - w3c_slidy.smaller(); - return w3c_slidy.cancel(event); - } - else if (key == 66) // B for larger fonts - { - w3c_slidy.bigger(); - return w3c_slidy.cancel(event); - } - else if (key == 90) // Z for last slide - { - w3c_slidy.last_slide(); - return w3c_slidy.cancel(event); - } - else if (key == 70) // F for toggle toolbar - { - w3c_slidy.toggle_toolbar(); - return w3c_slidy.cancel(event); - } - else if (key == 65) // A for toggle view single/all slides - { - w3c_slidy.toggle_view(); - return w3c_slidy.cancel(event); - } - else if (key == 75) // toggle action of left click for next page - { - w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled; - var alert_msg = (w3c_slidy.mouse_click_enabled ? - "enabled" : "disabled") + " mouse click advance"; - - alert(w3c_slidy.localize(alert_msg)); - return w3c_slidy.cancel(event); - } - else if (key == 84 || key == 67) // T or C for table of contents - { - if (w3c_slidy.toc) - w3c_slidy.toggle_table_of_contents(); - - return w3c_slidy.cancel(event); - } - else if (key == 72) // H for help - { - window.location = w3c_slidy.help_page; - return w3c_slidy.cancel(event); - } - //else alert("key code is "+ key); - - return true; - }, - - // safe for both text/html and application/xhtml+xml - create_element: function (name) { - if (this.xhtml && (typeof document.createElementNS != 'undefined')) - return document.createElementNS("http://www.w3.org/1999/xhtml", name) - - return document.createElement(name); - }, - - get_element_style: function (elem, IEStyleProp, CSSStyleProp) { - if (elem.currentStyle) - { - return elem.currentStyle[IEStyleProp]; - } - else if (window.getComputedStyle) - { - var compStyle = window.getComputedStyle(elem, ""); - return compStyle.getPropertyValue(CSSStyleProp); - } - return ""; - }, - - // the string str is a whitespace separated list of tokens - // test if str contains a particular token, e.g. "slide" - has_token: function (str, token) { - if (str) - { - // define pattern as regular expression - var pattern = /\w+/g; - - // check for matches - // place result in array - var result = str.match(pattern); - - // now check if desired token is present - for (var i = 0; i < result.length; i++) - { - if (result[i] == token) - return true; - } - } - - return false; - }, - - get_class_list: function (element) { - if (typeof element.className != 'undefined') - return element.className; - - return element.getAttribute("class"); - }, - - has_class: function (element, name) { - if (element.nodeType != 1) - return false; - - var regexp = new RegExp("(^| )" + name + "\W*"); - - if (typeof element.className != 'undefined') - return regexp.test(element.className); - - return regexp.test(element.getAttribute("class")); - }, - - remove_class: function (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 - { - clsval = element.getAttribute("class"); - - if (clsval) - { - clsval = clsval.replace(regexp, ""); - element.setAttribute("class", clsval); - } - } - }, - - add_class: function (element, name) { - if (!this.has_class(element, name)) - { - if (typeof element.className != 'undefined') - element.className += " " + name; - else - { - var clsval = element.getAttribute("class"); - clsval = clsval ? clsval + " " + name : name; - element.setAttribute("class", clsval); - } - } - }, - - // HTML elements that can be used with class="incremental" - // note that you can also put the class on containers like - // up, ol, dl, and div to make their contents appear - // incrementally. Upper case is used since this is what - // browsers report for HTML node names (text/html). - incremental_elements: null, - okay_for_incremental: function (name) { - if (!this.incremental_elements) - { - 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; - this.incremental_elements = inclist; - } - return this.incremental_elements[name.toLowerCase()]; - }, - - next_incremental_item: function (node) { - var br = this.is_xhtml ? "br" : "BR"; - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - - for (;;) - { - node = w3c_slidy.next_node(slide, node); - - if (node == null || node.parentNode == null) - break; - - if (node.nodeType == 1) // ELEMENT - { - if (node.nodeName == br) - continue; - - if (w3c_slidy.has_class(node, "incremental") - && w3c_slidy.okay_for_incremental(node.nodeName)) - return node; - - if (w3c_slidy.has_class(node.parentNode, "incremental") - && !w3c_slidy.has_class(node, "non-incremental")) - return node; - } - } - - return node; - }, - - previous_incremental_item: function (node) { - var br = this.is_xhtml ? "br" : "BR"; - var slide = w3c_slidy.slides[w3c_slidy.slide_number]; - - for (;;) - { - node = w3c_slidy.previous_node(slide, node); - - if (node == null || node.parentNode == null) - break; - - if (node.nodeType == 1) - { - if (node.nodeName == br) - continue; - - if (w3c_slidy.has_class(node, "incremental") - && w3c_slidy.okay_for_incremental(node.nodeName)) - return node; - - if (w3c_slidy.has_class(node.parentNode, "incremental") - && !w3c_slidy.has_class(node, "non-incremental")) - return node; - } - } - - return node; - }, - - // set visibility for all elements on current slide with - // a parent element with attribute class="incremental" - set_visibility_all_incremental: function (value) { - var node = this.next_incremental_item(null); - - if (value == "hidden") - { - while (node) - { - w3c_slidy.add_class(node, "invisible"); - node = w3c_slidy.next_incremental_item(node); - } - } - else // value == "visible" - { - while (node) - { - w3c_slidy.remove_class(node, "invisible"); - node = w3c_slidy.next_incremental_item(node); - } - } - }, - - // reveal the next hidden item on the slide - // node is null or the node that was last revealed - reveal_next_item: function (node) { - node = w3c_slidy.next_incremental_item(node); - - if (node && node.nodeType == 1) // an element - w3c_slidy.remove_class(node, "invisible"); - - return node; - }, - - // exact inverse of revealNextItem(node) - hide_previous_item: function (node) { - if (node && node.nodeType == 1) // an element - w3c_slidy.add_class(node, "invisible"); - - return this.previous_incremental_item(node); - }, - - // left to right traversal of root's content - next_node: function (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; - }, - - // right to left traversal of root's content - previous_node: function (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; - }, - - previous_sibling_element: function (el) { - el = el.previousSibling; - - while (el && el.nodeType != 1) - el = el.previousSibling; - - return el; - }, - - next_sibling_element: function (el) { - el = el.nextSibling; - - while (el && el.nodeType != 1) - el = el.nextSibling; - - return el; - }, - - first_child_element: function (el) { - var node; - - for (node = el.firstChild; node; node = node.nextSibling) - { - if (node.nodeType == 1) - break; - } - - return node; - }, - - first_tag: function (element, tag) { - var node; - - if (!this.is_xhtml) - tag = tag.toUpperCase(); - - for (node = element.firstChild; node; node = node.nextSibling) - { - if (node.nodeType == 1 && node.nodeName == tag) - break; - } - - return node; - }, - - hide_selection: function () { - if (window.getSelection) // Firefox, Chromium, Safari, Opera - { - var selection = window.getSelection(); - - if (selection.rangeCount > 0) - { - var range = selection.getRangeAt(0); - range.collapse (false); - } - } - else // Internet Explorer - { - var textRange = document.selection.createRange (); - textRange.collapse (false); - } - }, - - get_selected_text: function () { - 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 ""; - }, - - // make note of length of selected text - // as this evaluates to zero in click event - mouse_button_up: function (e) { - w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length; - }, - - mouse_button_down: function (e) { - w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length; - w3c_slidy.mouse_x = e.clientX; - w3c_slidy.mouse_y = e.clientY; - }, - - // right mouse button click is reserved for context menus - // it is more reliable to detect rightclick than leftclick - mouse_button_click: function (e) { - if (!e) - var e = window.event; - - if (Math.abs(e.clientX -w3c_slidy.mouse_x) + - Math.abs(e.clientY -w3c_slidy.mouse_y) > 10) - return true; - - if (w3c_slidy.selected_text_len > 0) - return true; - - 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; - - // work around Safari bug - if (target.nodeType == 3) - target = target.parentNode; - - if (e.which) // all browsers except IE - { - leftclick = (e.which == 1); - middleclick = (e.which == 2); - rightclick = (e.which == 3); - } - else if (e.button) - { - // Konqueror gives 1 for left, 4 for middle - // IE6 gives 0 for left and not 1 as I expected - - if (e.button == 4) - middleclick = true; - - // all browsers agree on 2 for right button - rightclick = (e.button == 2); - } - else - leftclick = true; - - if (w3c_slidy.selected_text_len > 0) - { - w3c_slidy.stop_propagation(e); - e.cancel = true; - e.returnValue = false; - return false; - } - - // dismiss table of contents - w3c_slidy.hide_table_of_contents(false); - - // check if target is something that probably want's clicks - // e.g. a, embed, object, input, textarea, select, option - var tag = target.nodeName.toLowerCase(); - - if (w3c_slidy.mouse_click_enabled && leftclick && - !w3c_slidy.special_element(target) && - !target.onclick) - { - w3c_slidy.next_slide(true); - w3c_slidy.stop_propagation(e); - e.cancel = true; - e.returnValue = false; - return false; - } - - return true; - }, - - special_element: function (element) { - if (this.has_class(element, "non-interactive")) - return false; - - var tag = element.nodeName.toLowerCase(); - - return element.onkeydown || - element.onclick || - tag == "a" || - tag == "embed" || - tag == "object" || - tag == "video" || - tag == "audio" || - tag == "svg" || - tag == "canvas" || - tag == "input" || - tag == "textarea" || - tag == "select" || - tag == "option"; - }, - - slidy_chrome: function (el) { - while (el) - { - if (el == w3c_slidy.toc || - el == w3c_slidy.toolbar || - w3c_slidy.has_class(el, "outline")) - return true; - - el = el.parentNode; - } - - return false; - }, - - get_key: function (e) - { - var key; - - // kludge around NS/IE differences - if (typeof window.event != "undefined") - key = window.event.keyCode; - else if (e.which) - key = e.which; - - return key; - }, - - get_target: function (e) { - var target; - - if (!e) - e = window.event; - - if (e.target) - target = e.target; - else if (e.srcElement) - target = e.srcElement; - - if (target.nodeType != 1) - target = target.parentNode; - - return target; - }, - - // does display property provide correct defaults? - is_block: function (elem) { - var tag = elem.nodeName.toLowerCase(); - - 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"; - }, - - add_listener: function (element, event, handler) { - if (window.addEventListener) - element.addEventListener(event, handler, false); - else - element.attachEvent("on"+event, handler); - }, - - // used to prevent event propagation from field controls - stop_propagation: function (event) { - event = event ? event : window.event; - event.cancelBubble = true; // for IE - - if (event.stopPropagation) - event.stopPropagation(); - - return true; - }, - - cancel: function (event) { - if (event) - { - event.cancel = true; - event.returnValue = false; - - if (event.preventDefault) - event.preventDefault(); - } - - w3c_slidy.key_wanted = false; - return false; - }, - -// for each language define an associative array -// and also the help text which is longer - - 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" - }, - help_es: - "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.", - - 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" - }, - help_ca: - "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.", - - strings_cs: { - "slide":"snímek", - "help?":"nápověda", - "contents?":"obsah", - "table of contents":"obsah prezentace", - "Table of Contents":"Obsah prezentace", - "restart presentation":"znovu spustit prezentaci", - "restart?":"restart" - }, - help_cs: - "Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " + - "šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " + - "dá zvětšit a zmenšit pomocí kláves B a S.", - - strings_nl: { - "slide":"pagina", - "help?":"Help?", - "contents?":"Inhoud?", - "table of contents":"inhoudsopgave", - "Table of Contents":"Inhoudsopgave", - "restart presentation":"herstart presentatie", - "restart?":"Herstart?" - }, - help_nl: - "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " + - "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.", - - strings_de: { - "slide":"Seite", - "help?":"Hilfe", - "contents?":"Übersicht", - "table of contents":"Inhaltsverzeichnis", - "Table of Contents":"Inhaltsverzeichnis", - "restart presentation":"Präsentation neu starten", - "restart?":"Neustart" - }, - help_de: - "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.", - - 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?" - }, - help_pl: - "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" + - "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.", - - 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" - }, - help_fr: - "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.", - - 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" - }, - help_hu: - "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.", - - strings_it: { - "slide":"pag.", - "help?":"Aiuto", - "contents?":"Indice", - "table of contents":"indice", - "Table of Contents":"Indice", - "restart presentation":"Ricominciare la presentazione", - "restart?":"Inizio" - }, - help_it: - "Navigare con mouse, barra spazio, frecce sinistra/destra o " + - "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.", - - strings_el: { - "slide":"σελίδα", - "help?":"βοήθεια;", - "contents?":"περιεχόμενα;", - "table of contents":"πίνακας περιεχομένων", - "Table of Contents":"Πίνακας Περιεχομένων", - "restart presentation":"επανεκκίνηση παρουσίασης", - "restart?":"επανεκκίνηση;" - }, - help_el: - "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " + - "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " + - "το μέγεθος της γραμματοσειράς.", - - strings_ja: { - "slide":"スライド", - "help?":"ヘルプ", - "contents?":"目次", - "table of contents":"目次を表示", - "Table of Contents":"目次", - "restart presentation":"最初から再生", - "restart?":"最初から" - }, - help_ja: - "マウス左クリック ・ スペース ・ 左右キー " + - "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更", - - strings_zh: { - "slide":"幻灯片", - "help?":"帮助?", - "contents?":"内容?", - "table of contents":"目录", - "Table of Contents":"目录", - "restart presentation":"重新启动展示", - "restart?":"重新启动?" - }, - help_zh: - "用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " + - "用 S, B 改变字体大小.", - - strings_ru: { - "slide":"слайд", - "help?":"помощь?", - "contents?":"содержание?", - "table of contents":"оглавление", - "Table of Contents":"Оглавление", - "restart presentation":"перезапустить презентацию", - "restart?":"перезапуск?" - }, - help_ru: - "Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" + - "влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.", - - 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" - }, - help_sv: - "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.", - - strings: { }, - - localize: function (src) { - if (src == "") - return src; - - // try full language code, e.g. en-US - var s, lookup = w3c_slidy.strings[w3c_slidy.lang]; - - if (lookup) - { - s = lookup[src]; - - if (s) - return s; - } - - // strip country code suffix, e.g. - // try en if undefined for en-US - var lg = w3c_slidy.lang.split("-"); - - if (lg.length > 1) - { - lookup = w3c_slidy.strings[lg[0]]; - - if (lookup) - { - s = lookup[src]; - - if (s) - return s; - } - } - - // otherwise string as is - return src; - }, - - init_localization: function () { - var i18n = w3c_slidy; - var help_text = w3c_slidy.help_text; - - // each such language array is declared in the localize array - // this is used as in w3c_slidy.localize("foo"); - this.strings = { - "es":this.strings_es, - "ca":this.strings_ca, - "cs":this.strings_cs, - "nl":this.strings_nl, - "de":this.strings_de, - "pl":this.strings_pl, - "fr":this.strings_fr, - "hu":this.strings_hu, - "it":this.strings_it, - "el":this.strings_el, - "jp":this.strings_ja, - "zh":this.strings_zh, - "ru":this.strings_ru, - "sv":this.strings_sv - }, - - i18n.strings_es[help_text] = i18n.help_es; - i18n.strings_ca[help_text] = i18n.help_ca; - i18n.strings_cs[help_text] = i18n.help_cs; - i18n.strings_nl[help_text] = i18n.help_nl; - i18n.strings_de[help_text] = i18n.help_de; - i18n.strings_pl[help_text] = i18n.help_pl; - i18n.strings_fr[help_text] = i18n.help_fr; - i18n.strings_hu[help_text] = i18n.help_hu; - i18n.strings_it[help_text] = i18n.help_it; - i18n.strings_el[help_text] = i18n.help_el; - i18n.strings_ja[help_text] = i18n.help_ja; - i18n.strings_zh[help_text] = i18n.help_zh; - i18n.strings_ru[help_text] = i18n.help_ru; - i18n.strings_sv[help_text] = i18n.help_sv; - - w3c_slidy.lang = document.body.parentNode.getAttribute("lang"); - - if (!w3c_slidy.lang) - w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang"); - - if (!w3c_slidy.lang) - w3c_slidy.lang = "en"; - } -}; - -// hack for back button behavior -if (w3c_slidy.ie6 || w3c_slidy.ie7) -{ - document.write("<iframe id='historyFrame' " + - "src='javascript:\"<html"+"></"+"html>\"' " + - "height='1' width='1' " + - "style='position:absolute;left:-800px'></iframe>"); -} - -// attach event listeners for initialization -w3c_slidy.set_up(); - -// hide the slides as soon as body element is available -// to reduce annoying screen mess before the onload event -setTimeout(w3c_slidy.hide_slides, 50); - diff --git a/data/slidy/styles/slidy.css b/data/slidy/styles/slidy.css deleted file mode 100644 index 0197e64d0..000000000 --- a/data/slidy/styles/slidy.css +++ /dev/null @@ -1,405 +0,0 @@ -/* slidy.css - - Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved. - W3C liability, trademark, document use and software licensing - rules apply, see: - - http://www.w3.org/Consortium/Legal/copyright-documents - http://www.w3.org/Consortium/Legal/copyright-software -*/ -body -{ - margin: 0 0 0 0; - padding: 0 0 0 0; - width: 100%; - height: 100%; - color: black; - background-color: white; - font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif; - font-size: 14pt; -} - -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-color: rgb(240,240,240); - border-top: solid 1px rgb(180,180,180); -} - -div.toolbar span.copyright { - color: black; - margin-left: 0.5em; -} - -div.initial_prompt { - position: absolute; - z-index: 1000; - bottom: 1.2em; - width: 100%; - background-color: rgb(200,200,200); - opacity: 0.35; - background-color: rgb(200,200,200, 0.35); - cursor: pointer; -} - -div.initial_prompt p.help { - text-align: center; -} - -div.initial_prompt p.close { - text-align: right; - font-style: italic; -} - -div.slidy_toc { - position: absolute; - z-index: 300; - width: 60%; - max-width: 30em; - height: 30em; - overflow: auto; - top: auto; - right: auto; - left: 4em; - bottom: 4em; - padding: 1em; - background: rgb(240,240,240); - border-style: solid; - border-width: 2px; - font-size: 60%; -} - -div.slidy_toc .toc_heading { - text-align: center; - width: 100%; - margin: 0; - margin-bottom: 1em; - border-bottom-style: solid; - border-bottom-color: rgb(180,180,180); - border-bottom-width: 1px; -} - -div.slide { - z-index: 20; - margin: 0 0 0 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.background { - display: none; -} - -div.handout { - margin-left: 20px; - margin-right: 20px; -} - -div.slide.titlepage { - text-align: center; -} - -div.slide.titlepage h1 { - padding-top: 10%; - margin-right: 0; -} - -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: 0.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: rgb(240,240,240); - color: black; - z-index: 300; - overflow: auto; - display: block; - visibility: visible; -} - -div.toc-heading { - width: 100%; - border-bottom: solid 1px rgb(180,180,180); - margin-bottom: 1em; - text-align: center; -} - -img { - image-rendering: optimize-quality; -} - -pre { - font-size: 80%; - font-weight: bold; - line-height: 120%; - padding-top: 0.2em; - padding-bottom: 0.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; } - -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: 0.5em; margin-top: 0.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: 0.5em; - font-weight: bold; -} -div dd -{ - margin-left: 2em; - margin-bottom: 0.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: 0.2em } - -ul { - margin: 0.5em 1.5em 0.5em 1.5em; - padding: 0; -} - -ol { - margin: 0.5em 1.5em 0.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: 0.1em 0em 0.6em 0; - padding: 0 0 0 0; - line-height: 140%; -} - -ol li { - margin: 0.1em 0em 0.6em 1.5em; - padding: 0 0 0 0px; - line-height: 140%; - list-style-type: decimal; -} - -li ul li { - font-size: 85%; - font-style: italic; - list-style-type: disc; - background: transparent; - padding: 0 0 0 0; -} -li li ul li { - font-size: 85%; - font-style: normal; - list-style-type: circle; - background: transparent; - padding: 0 0 0 0; -} -li li li ul li { - list-style-type: disc; - background: transparent; - padding: 0 0 0 0; -} - -li ol li { - list-style-type: decimal; -} - - -li li ol li { - list-style-type: decimal; -} - -/* - setting class="outline on ol or ul makes it behave as an - ouline list where blocklevel content in li elements is - hidden by default and can be expanded or collapsed with - mouse click. Set class="expand" on li to override default -*/ - -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(../graphics/nofold-dim.gif) no-repeat 0px 0.5em; -} -ol.outline li.unfolded { - padding: 0 0 0 20px; - background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em; -} -ol.outline li.folded { - padding: 0 0 0 20px; - background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em; -} -ol.outline li.unfolded:hover { - padding: 0 0 0 20px; - background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em; -} -ol.outline li.folded:hover { - padding: 0 0 0 20px; - background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em; -} - -ul.outline li.nofold { - padding: 0 0 0 20px; - background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em; -} -ul.outline li.unfolded { - padding: 0 0 0 20px; - background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em; -} -ul.outline li.folded { - padding: 0 0 0 20px; - background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em; -} -ul.outline li.unfolded:hover { - padding: 0 0 0 20px; - background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em; -} -ul.outline li.folded:hover { - padding: 0 0 0 20px; - background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em; -} - -/* for slides with class "title" in table of contents */ -a.titleslide { font-weight: bold; font-style: italic } - -/* - hide images for work around for save as bug - where browsers fail to save images used by CSS -*/ -img.hidden { display: none; visibility: hidden } -div.initial_prompt { display: none; visibility: hidden } - - div.slide { - visibility: visible; - position: inherit; - } - div.handout { - border-top-style: solid; - border-top-width: thin; - border-top-color: black; - } - -@media screen { - .hidden { display: none; visibility: visible } - - div.slide.hidden { display: block; visibility: visible } - div.handout.hidden { display: block; visibility: visible } - div.background { display: none; visibility: hidden } - body.single_slide div.initial_prompt { display: block; visibility: visible } - body.single_slide div.background { display: block; visibility: visible } - body.single_slide div.background.hidden { display: none; visibility: hidden } - body.single_slide .invisible { visibility: hidden } - body.single_slide .hidden { display: none; visibility: hidden } - body.single_slide div.slide { position: absolute } - body.single_slide div.handout { display: none; visibility: hidden } -} - -@media print { - .hidden { display: block; visibility: visible } - - div.slide pre { font-size: 60%; padding-left: 0.5em; } - div.toolbar { display: none; visibility: hidden; } - div.slidy_toc { display: none; visibility: hidden; } - div.background { display: none; visibility: hidden; } - div.slide { page-break-before: always } - /* :first-child isn't reliable for print media */ - div.slide.first-slide { page-break-before: avoid } -} - diff --git a/data/templates b/data/templates -Subproject 0cb55f2289148b106ab78ce8f15efc8d0b8acda +Subproject 50ca8c85d9abfb7918cb78015bcc6d6fec02ce7 diff --git a/github-upload.sh b/github-upload.sh new file mode 100755 index 000000000..875d51831 --- /dev/null +++ b/github-upload.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +VERSION=$1 +FULLNAME=pandoc-$VERSION +read -s -p "Token (https://github.com/settings/applications): " TOKEN + +curl -H "Authorization: token $TOKEN" \ + -H "Accept: application/vnd.github.manifold-preview" \ + -H "Content-Type: application/x-apple-diskimage" \ + --data-binary @$FULLNAME.pkg.zip \ + "https://uploads.github.com/repos/jgm/pandoc/releases/$VERSION/assets?name=$FULLNAME.pkg.zip" + +curl -H "Authorization: token $TOKEN" \ + -H "Accept: application/vnd.github.manifold-preview" \ + -H "Content-Type: application/x-msi" \ + --data-binary @$FULLNAME.msi \ + "https://uploads.github.com/repos/jgm/pandoc/releases/$VERSION/assets?name=$FULLNAME.msi" + diff --git a/googlecode-upload.sh b/googlecode-upload.sh index 19975ca91..40fba78e2 100755 --- a/googlecode-upload.sh +++ b/googlecode-upload.sh @@ -2,4 +2,4 @@ VERSION=$1 googlecode_upload.py -s "Source tarball" -p pandoc -u fiddlosopher --labels=Featured,Type-Source,OpSys-All dist/pandoc-$VERSION.tar.gz googlecode_upload.py -s "Windows installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-Windows pandoc-$VERSION.msi -googlecode_upload.py -s "Mac OS X installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-OSX pandoc-$VERSION.dmg +googlecode_upload.py -s "Mac OS X installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-OSX pandoc-$VERSION.pkg.zip diff --git a/make_osx_package.sh b/make_osx_package.sh index 0c84951c2..6c943c84a 100755 --- a/make_osx_package.sh +++ b/make_osx_package.sh @@ -1,49 +1,60 @@ -#!/bin/sh -e +#!/bin/bash -e DIST=`pwd`/osx_package +SANDBOX=`pwd`/.cabal-sandbox VERSION=$(grep -e '^Version' pandoc.cabal | awk '{print $2}') RESOURCES=$DIST/Resources ROOT=$DIST/pandoc +DEST=$ROOT/usr/local SCRIPTS=osx-resources BASE=pandoc-$VERSION -ICU=/usr/local/Cellar/icu4c/51.1 -ME=jgm +ME=$(whoami) CODESIGNID="Developer ID Application: John Macfarlane" PACKAGEMAKER=/Applications/PackageMaker.app/Contents/MacOS/PackageMaker +EXES="pandoc pandoc-citeproc" + +read -s -p "sudo password: " PASSWORD +echo $PASSWORD | sudo -S echo "Password valid, continuing." echo Removing old files... rm -rf $DIST mkdir -p $RESOURCES -# echo Updating database -# cabal update +echo Updating database +cabal update echo Building pandoc... -cabal-dev install hsb2hs - -cabal-dev install --reinstall -v1 --prefix $ROOT/tmp --flags="embed_data_files unicode_collation" --extra-lib-dirs=$ICU/lib --extra-include-dirs=$ICU/include pandoc-citeproc -cabal-dev install -v1 --prefix $ROOT/tmp --flags="embed_data_files" - -mkdir -p $ROOT/usr/local/share -cp -r $ROOT/tmp/bin $ROOT/usr/local/ -cp -r $ROOT/tmp/share/man $ROOT/usr/local/share/ -rm -rf $ROOT/tmp +cabal sandbox init +cabal clean +cabal install --reinstall --flags="embed_data_files" +cabal install --reinstall --flags="embed_data_files" pandoc-citeproc + +mkdir -p $DEST/bin +mkdir -p $DEST/share/man/man1 +mkdir -p $DEST/share/man/man5 +for f in $EXES; do + cp $SANDBOX/bin/$f $DEST/bin/; + cp $SANDBOX/share/man/man1/$f.1 $DEST/share/man/man1/ +done +cp $SANDBOX/share/man/man5/pandoc_markdown.5 $DEST/share/man/man5/ chown -R $ME:staff $DIST -# gzip $ROOT/usr/local/share/man/man?/*.* +# gzip $DEST/share/man/man?/*.* # cabal gives man pages the wrong permissions -chmod +r $ROOT/usr/local/share/man/man?/*.* +chmod +r $DEST/share/man/man?/*.* echo Copying license... -dist/build/pandoc/pandoc --data data -t rtf -s COPYING -o $RESOURCES/License.rtf +$SANDBOX/bin/pandoc --data data -t rtf -s COPYING -o $RESOURCES/License.rtf echo Signing pandoc executable... -codesign --force --sign "$CODESIGNID" $ROOT/usr/local/bin/pandoc +codesign --force --sign "$CODESIGNID" $DEST/bin/pandoc # make sure it's valid... returns nonzero exit code if it isn't: -spctl --assess --type execute $ROOT/usr/local/bin/pandoc +spctl --assess --type execute $DEST/bin/pandoc echo Creating OSX package... +# remove old package first +echo $PASSWORD | sudo -S rm -rf $BASE.pkg $BASE.dmg sudo $PACKAGEMAKER \ --root $ROOT \ @@ -61,11 +72,13 @@ sudo codesign --force --sign "$CODESIGNID" $BASE.pkg # make sure it's valid... spctl --assess --type install $BASE.pkg -echo Creating disk image... +echo Creating zip... +zip -9 -r $BASE.pkg.zip $BASE.pkg -sudo hdiutil create "$BASE.dmg" \ - -format UDZO -ov \ - -volname "pandoc $VERSION" \ - -srcfolder $BASE.pkg -sudo hdiutil internet-enable "$BASE.dmg" +# echo Creating disk image... +# sudo hdiutil create "$BASE.dmg" \ +# -format UDZO -ov \ +# -volname "pandoc $VERSION" \ +# -srcfolder $BASE.pkg +# sudo hdiutil internet-enable "$BASE.dmg" diff --git a/pandoc.cabal b/pandoc.cabal index e5deb0896..0199996be 100644 --- a/pandoc.cabal +++ b/pandoc.cabal @@ -1,5 +1,5 @@ Name: pandoc -Version: 1.12 +Version: 1.12.3.1 Cabal-Version: >= 1.10 Build-Type: Custom License: GPL @@ -74,29 +74,6 @@ Data-Files: -- data for LaTeXMathML writer data/LaTeXMathML.js, data/MathMLinHTML.js, - -- data for S5 writer - data/s5/default/slides.js, - data/s5/default/s5-core.css, - data/s5/default/framing.css, - data/s5/default/pretty.css, - data/s5/default/opera.css, - data/s5/default/outline.css, - data/s5/default/print.css, - data/s5/default/slides.css, - data/s5/default/iepngfix.htc, - data/s5/default/blank.gif, - data/s5/default/bodybg.gif, - -- data for slidy writer - data/slidy/styles/slidy.css, - data/slidy/scripts/slidy.js, - data/slidy/graphics/fold.gif, - data/slidy/graphics/unfold.gif, - data/slidy/graphics/nofold-dim.gif, - data/slidy/graphics/unfold-dim.gif, - data/slidy/graphics/fold-dim.gif, - -- data for slideous writer - data/slideous/slideous.css, - data/slideous/slideous.js, -- data for dzslides writer data/dzslides/template.html, -- sample lua custom writer @@ -116,9 +93,9 @@ Extra-Source-Files: tests/docbook-reader.native tests/html-reader.html, tests/html-reader.native, - tests/opml-reader.html, + tests/opml-reader.opml, tests/opml-reader.native, - tests/haddock-reader.html, + tests/haddock-reader.haddock, tests/haddock-reader.native, tests/insert, tests/lalune.jpg, @@ -225,45 +202,46 @@ Library syb >= 0.1 && < 0.5, containers >= 0.1 && < 0.6, unordered-containers >= 0.2 && < 0.3, - array >= 0.3 && < 0.5, + array >= 0.3 && < 0.6, parsec >= 3.1 && < 3.2, mtl >= 1.1 && < 2.2, network >= 2 && < 2.5, filepath >= 1.1 && < 1.4, - process >= 1 && < 1.2, + process >= 1 && < 1.3, directory >= 1 && < 1.3, bytestring >= 0.9 && < 0.11, - text >= 0.11 && < 0.12, - zip-archive >= 0.1.3.3 && < 0.2, + text >= 0.11 && < 1.2, + zip-archive >= 0.1.3.3 && < 0.3, old-locale >= 1 && < 1.1, time >= 1.2 && < 1.5, HTTP >= 4000.0.5 && < 4000.3, - texmath >= 0.6.4 && < 0.7, + texmath >= 0.6.6 && < 0.7, xml >= 1.3.12 && < 1.4, random >= 1 && < 1.1, extensible-exceptions >= 0.1 && < 0.2, - pandoc-types >= 1.12 && < 1.13, - aeson >= 0.6 && < 0.7, + pandoc-types >= 1.12.3 && < 1.13, + aeson >= 0.6 && < 0.8, tagsoup >= 0.12.5 && < 0.14, base64-bytestring >= 0.1 && < 1.1, zlib >= 0.5 && < 0.6, - highlighting-kate >= 0.5.5 && < 0.6, + highlighting-kate >= 0.5.6 && < 0.6, data-default >= 0.4 && < 0.6, - temporary >= 1.1 && < 1.2, + temporary >= 1.1 && < 1.3, blaze-html >= 0.5 && < 0.7, blaze-markup >= 0.5.1 && < 0.6, - attoparsec >= 0.10 && < 0.11, - stringable >= 0.1 && < 0.2, + attoparsec >= 0.10 && < 0.12, yaml >= 0.8.3 && < 0.9, vector >= 0.10 && < 0.11, - hslua >= 0.3 && < 0.4 + hslua >= 0.3 && < 0.4, + binary >= 0.5 && < 0.8 + Build-Tools: alex, happy if flag(http-conduit) - Build-Depends: http-conduit >= 1.9 && < 1.10, + Build-Depends: http-conduit >= 1.9 && < 2.1, http-types >= 0.8 && < 0.9 cpp-options: -DHTTP_CONDUIT if flag(embed_data_files) cpp-options: -DEMBED_DATA_FILES - -- build-tools: hsb2hs + -- Build-Tools: hsb2hs -- not yet recognized by cabal other-modules: Text.Pandoc.Data Ghc-Options: -rtsopts -Wall -fno-warn-unused-do-bind Ghc-Prof-Options: -auto-all -caf-all -rtsopts @@ -334,16 +312,18 @@ Library Executable pandoc Build-Depends: pandoc, - pandoc-types >= 1.12 && < 1.13, + pandoc-types >= 1.12.3 && < 1.13, base >= 4.2 && <5, directory >= 1 && < 1.3, filepath >= 1.1 && < 1.4, network >= 2 && < 2.5, - text >= 0.11 && < 0.12, + text >= 0.11 && < 1.2, bytestring >= 0.9 && < 0.11, extensible-exceptions >= 0.1 && < 0.2, - highlighting-kate >= 0.5.5 && < 0.6, - aeson >= 0.6 && < 0.7, + highlighting-kate >= 0.5.6 && < 0.6, + aeson >= 0.6 && < 0.8, + yaml >= 0.8.3 && < 0.9, + containers >= 0.1 && < 0.6, HTTP >= 4000.0.5 && < 4000.3 Ghc-Options: -rtsopts -with-rtsopts=-K16m -Wall -fno-warn-unused-do-bind Ghc-Prof-Options: -auto-all -caf-all -rtsopts -with-rtsopts=-K16m @@ -377,13 +357,13 @@ Test-Suite test-pandoc Build-Depends: base >= 4.2 && < 5, syb >= 0.1 && < 0.5, pandoc, - pandoc-types >= 1.12 && < 1.13, + pandoc-types >= 1.12.3 && < 1.13, bytestring >= 0.9 && < 0.11, - text >= 0.11 && < 0.12, + text >= 0.11 && < 1.2, directory >= 1 && < 1.3, filepath >= 1.1 && < 1.4, - process >= 1 && < 1.2, - highlighting-kate >= 0.5.5 && < 0.6, + process >= 1 && < 1.3, + highlighting-kate >= 0.5.6 && < 0.6, Diff >= 0.2 && < 0.4, test-framework >= 0.3 && < 0.9, test-framework-hunit >= 0.2 && < 0.4, @@ -35,7 +35,8 @@ import Text.Pandoc.Builder (setMeta) import Text.Pandoc.PDF (makePDF) import Text.Pandoc.Readers.LaTeX (handleIncludes) import Text.Pandoc.Shared ( tabFilter, readDataFileUTF8, readDataFile, - safeRead, headerShift, normalize, err, warn ) + safeRead, headerShift, normalize, err, warn, + openURL ) import Text.Pandoc.XML ( toEntities ) import Text.Pandoc.SelfContained ( makeSelfContained ) import Text.Pandoc.Process (pipeProcess) @@ -55,11 +56,16 @@ import Control.Exception.Extensible ( throwIO ) import qualified Text.Pandoc.UTF8 as UTF8 import Control.Monad (when, unless, liftM) import Data.Foldable (foldrM) -import Network.HTTP (simpleHTTP, mkRequest, getResponseBody, RequestMethod(..)) import Network.URI (parseURI, isURI, URI(..)) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString as BS import Data.Aeson (eitherDecode', encode) +import qualified Data.Map as M +import System.IO.Error(ioeGetErrorType) +import GHC.IO.Exception (IOErrorType(ResourceVanished)) +import Data.Yaml (decode) +import qualified Data.Yaml as Yaml +import qualified Data.Text as T copyrightMessage :: String copyrightMessage = "\nCopyright (C) 2006-2013 John MacFarlane\n" ++ @@ -98,8 +104,11 @@ externalFilter f args' d = do ExitSuccess -> return $ either error id $ eitherDecode' outbs ExitFailure _ -> err 83 $ "Error running filter " ++ f where filterException :: E.SomeException -> IO a - filterException e = err 83 $ "Error running filter " ++ f ++ - "\n" ++ show e + filterException e = err 83 $ "Error running filter " ++ f ++ "\n" ++ + if ioeGetErrorType `fmap` E.fromException e == + Just ResourceVanished + then f ++ " not found in path" + else show e -- | Data structure for command line options. data Opt = Opt @@ -113,7 +122,7 @@ data Opt = Opt , optTransforms :: [Pandoc -> Pandoc] -- ^ Doc transforms to apply , optTemplate :: Maybe FilePath -- ^ Custom template , optVariables :: [(String,String)] -- ^ Template variables to set - , optMetadata :: [(String,MetaValue)] -- ^ Metadata fields to set + , optMetadata :: M.Map String MetaValue -- ^ Metadata fields to set , optOutputFile :: String -- ^ Name of output file , optNumberSections :: Bool -- ^ Number sections in LaTeX , optNumberOffset :: [Int] -- ^ Starting number for sections @@ -140,7 +149,7 @@ data Opt = Opt , optReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst , optWrapText :: Bool -- ^ Wrap text , optColumns :: Int -- ^ Line length in characters - , optPlugins :: [[String] -> Pandoc -> IO Pandoc] -- ^ Plugins to apply + , optFilters :: [FilePath] -- ^ Filters to apply , optEmailObfuscation :: ObfuscationMethod , optIdentifierPrefix :: String , optIndentedCodeClasses :: [String] -- ^ Default classes for indented code blocks @@ -168,7 +177,7 @@ defaultOpts = Opt , optTransforms = [] , optTemplate = Nothing , optVariables = [] - , optMetadata = [] + , optMetadata = M.empty , optOutputFile = "-" -- "-" means stdout , optNumberSections = False , optNumberOffset = [0,0,0,0,0,0] @@ -195,7 +204,7 @@ defaultOpts = Opt , optReferenceLinks = False , optWrapText = True , optColumns = 72 - , optPlugins = [] + , optFilters = [] , optEmailObfuscation = JavascriptObfuscation , optIdentifierPrefix = "" , optIndentedCodeClasses = [] @@ -285,8 +294,7 @@ options = , Option "F" ["filter"] (ReqArg - (\arg opt -> return opt { optPlugins = externalFilter arg : - optPlugins opt }) + (\arg opt -> return opt { optFilters = arg : optFilters opt }) "PROGRAM") "" -- "External JSON filter" @@ -328,9 +336,10 @@ options = (ReqArg (\arg opt -> do let (key,val) = case break (`elem` ":=") arg of - (k,_:v) -> (k, MetaString v) + (k,_:v) -> (k, readMetaValue v) (k,_) -> (k, MetaBool True) - return opt{ optMetadata = (key,val) : optMetadata opt }) + return opt{ optMetadata = addMetadata key val + $ optMetadata opt }) "KEY[:VALUE]") "" @@ -452,8 +461,6 @@ options = , Option "" ["self-contained"] (NoArg (\opt -> return opt { optSelfContained = True, - optVariables = ("slidy-url","slidy") : - optVariables opt, optStandalone = True })) "" -- "Make slide shows include all the needed js and css" @@ -649,7 +656,7 @@ options = (ReqArg (\arg opt -> do let b = takeBaseName arg - if (b == "pdflatex" || b == "lualatex" || b == "xelatex") + if b `elem` ["pdflatex", "lualatex", "xelatex"] then return opt { optLaTeXEngine = arg } else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.") "PROGRAM") @@ -657,29 +664,32 @@ options = , Option "" ["bibliography"] (ReqArg - (\arg opt -> - return opt{ optMetadata = ("bibliography",MetaString arg) : - optMetadata opt - , optPlugins = externalFilter "pandoc-citeproc" - : optPlugins opt - }) + (\arg opt -> return opt{ optMetadata = addMetadata + "bibliography" (readMetaValue arg) + $ optMetadata opt + , optVariables = + ("biblio-files", dropExtension arg) : + optVariables opt + }) "FILE") "" , Option "" ["csl"] (ReqArg (\arg opt -> - return opt{ optMetadata = ("csl", MetaString arg) : - optMetadata opt }) + return opt{ optMetadata = addMetadata "csl" + (readMetaValue arg) + $ optMetadata opt }) "FILE") "" , Option "" ["citation-abbreviations"] (ReqArg (\arg opt -> - return opt{ optMetadata = ("citation-abbreviations", - MetaString arg) : - optMetadata opt }) + return opt{ optMetadata = addMetadata + "citation-abbreviations" + (readMetaValue arg) + $ optMetadata opt }) "FILE") "" @@ -779,6 +789,20 @@ options = ] +addMetadata :: String -> MetaValue -> M.Map String MetaValue + -> M.Map String MetaValue +addMetadata k v m = case M.lookup k m of + Nothing -> M.insert k v m + Just (MetaList xs) -> M.insert k + (MetaList (xs ++ [v])) m + Just x -> M.insert k (MetaList [v, x]) m + +readMetaValue :: String -> MetaValue +readMetaValue s = case decode (UTF8.fromString s) of + Just (Yaml.String t) -> MetaString $ T.unpack t + Just (Yaml.Bool b) -> MetaBool b + _ -> MetaString s + -- Returns usage message usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String usageMessage programName = usageInfo @@ -915,7 +939,7 @@ main = do , optReferenceLinks = referenceLinks , optWrapText = wrap , optColumns = columns - , optPlugins = plugins + , optFilters = filters , optEmailObfuscation = obfuscationMethod , optIdentifierPrefix = idPrefix , optIndentedCodeClasses = codeBlockClasses @@ -935,6 +959,15 @@ main = do mapM_ (\arg -> UTF8.hPutStrLn stdout arg) args exitWith ExitSuccess + -- --bibliography implies -F pandoc-citeproc for backwards compatibility: + let filters' = case M.lookup "bibliography" metadata of + Just _ | optCiteMethod opts /= Natbib && + optCiteMethod opts /= Biblatex && + all (\f -> takeBaseName f /= "pandoc-citeproc") + filters -> "pandoc-citeproc" : filters + _ -> filters + let plugins = map externalFilter filters' + let sources = if ignoreArgs then [] else args datadir <- case mbDataDir of @@ -954,7 +987,10 @@ main = do let writerName' = if null writerName then defaultWriterName outputFile - else writerName + else case writerName of + "epub2" -> "epub" + "html4" -> "html" + x -> x let pdfOutput = map toLower (takeExtension outputFile) == ".pdf" @@ -1003,12 +1039,10 @@ main = do variables' <- case mathMethod of LaTeXMathML Nothing -> do - s <- readDataFileUTF8 datadir - ("LaTeXMathML.js") + s <- readDataFileUTF8 datadir "LaTeXMathML.js" return $ ("mathml-script", s) : variables MathML Nothing -> do - s <- readDataFileUTF8 datadir - ("MathMLinHTML.js") + s <- readDataFileUTF8 datadir "MathMLinHTML.js" return $ ("mathml-script", s) : variables _ -> return variables @@ -1089,10 +1123,13 @@ main = do readSource "-" = UTF8.getContents readSource src = case parseURI src of Just u | uriScheme u `elem` ["http:","https:"] -> - readURI u + readURI src _ -> UTF8.readFile src - readURI uri = simpleHTTP (mkRequest GET uri) >>= getResponseBody >>= - return . UTF8.toStringLazy -- treat all as UTF8 + readURI src = do + res <- openURL src + case res of + Left e -> throwIO e + Right (bs,_) -> return $ UTF8.toString bs let convertTabs = tabFilter (if preserveTabs then 0 else tabStop) @@ -1105,7 +1142,7 @@ main = do reader readerOpts - let doc0 = foldr (\(k,v) -> setMeta k v) doc metadata + let doc0 = M.foldWithKey setMeta doc metadata let doc1 = foldr ($) doc0 transforms doc2 <- foldrM ($) doc1 $ map ($ [writerName']) plugins diff --git a/src/Text/Pandoc.hs b/src/Text/Pandoc.hs index 703bb876a..3ae81db00 100644 --- a/src/Text/Pandoc.hs +++ b/src/Text/Pandoc.hs @@ -267,7 +267,10 @@ getDefaultExtensions "markdown_strict" = strictExtensions getDefaultExtensions "markdown_phpextra" = phpMarkdownExtraExtensions getDefaultExtensions "markdown_mmd" = multimarkdownExtensions getDefaultExtensions "markdown_github" = githubMarkdownExtensions -getDefaultExtensions _ = pandocExtensions +getDefaultExtensions "markdown" = pandocExtensions +getDefaultExtensions "plain" = pandocExtensions +getDefaultExtensions "textile" = Set.fromList [Ext_auto_identifiers, Ext_raw_tex] +getDefaultExtensions _ = Set.fromList [Ext_auto_identifiers] -- | Retrieve reader based on formatSpec (format+extensions). getReader :: String -> Either String (ReaderOptions -> String -> IO Pandoc) diff --git a/src/Text/Pandoc/ImageSize.hs b/src/Text/Pandoc/ImageSize.hs index 9b0850efb..14575244d 100644 --- a/src/Text/Pandoc/ImageSize.hs +++ b/src/Text/Pandoc/ImageSize.hs @@ -32,9 +32,14 @@ module Text.Pandoc.ImageSize ( ImageType(..), imageType, imageSize, sizeInPixels, sizeInPoints ) where import Data.ByteString (ByteString, unpack) import qualified Data.ByteString.Char8 as B +import qualified Data.ByteString.Lazy as BL +import Control.Applicative import Control.Monad import Data.Bits +import Data.Binary +import Data.Binary.Get import Text.Pandoc.Shared (safeRead) +import qualified Data.Map as M -- quick and dirty functions to get image sizes -- algorithms borrowed from wwwis.pl @@ -53,7 +58,8 @@ imageType :: ByteString -> Maybe ImageType imageType img = case B.take 4 img of "\x89\x50\x4e\x47" -> return Png "\x47\x49\x46\x38" -> return Gif - "\xff\xd8\xff\xe0" -> return Jpeg + "\xff\xd8\xff\xe0" -> return Jpeg -- JFIF + "\xff\xd8\xff\xe1" -> return Jpeg -- Exif "%PDF" -> return Pdf "%!PS" | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF" @@ -139,8 +145,14 @@ gifSize img = do jpegSize :: ByteString -> Maybe ImageSize jpegSize img = do let (hdr, rest) = B.splitAt 4 img - guard $ hdr == "\xff\xd8\xff\xe0" guard $ B.length rest >= 14 + case hdr of + "\xff\xd8\xff\xe0" -> jfifSize rest + "\xff\xd8\xff\xe1" -> exifSize $ B.takeWhile (/= '\xff') rest + _ -> mzero + +jfifSize :: ByteString -> Maybe ImageSize +jfifSize rest = do let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral $ unpack $ B.take 5 $ B.drop 9 $ rest let factor = case dpiDensity of @@ -149,11 +161,11 @@ jpegSize img = do _ -> const 72 let dpix = factor (shift dpix1 8 + dpix2) let dpiy = factor (shift dpiy1 8 + dpiy2) - (w,h) <- findJpegSize rest + (w,h) <- findJfifSize rest return $ ImageSize { pxX = w, pxY = h, dpiX = dpix, dpiY = dpiy } -findJpegSize :: ByteString -> Maybe (Integer,Integer) -findJpegSize bs = do +findJfifSize :: ByteString -> Maybe (Integer,Integer) +findJfifSize bs = do let bs' = B.dropWhile (=='\xff') $ B.dropWhile (/='\xff') bs case B.uncons bs' of Just (c,bs'') | c >= '\xc0' && c <= '\xc3' -> do @@ -165,8 +177,216 @@ findJpegSize bs = do [c1,c2] -> do let len = shift c1 8 + c2 -- skip variables - findJpegSize $ B.drop len bs'' + findJfifSize $ B.drop len bs'' _ -> fail "JPEG parse error" Nothing -> fail "Did not find length record" +exifSize :: ByteString -> Maybe ImageSize +exifSize = runGet (Just <$> exifHeader) . BL.fromChunks . (:[]) +-- NOTE: It would be nicer to do +-- runGet ((Just <$> exifHeader) <|> return Nothing) +-- which would prevent pandoc from raising an error when an exif header can't +-- be parsed. But we only get an Alternative instance for Get in binary 0.6, +-- and binary 0.5 ships with ghc 7.6. + +exifHeader :: Get ImageSize +exifHeader = do + _app1DataSize <- getWord16be + exifHdr <- getWord32be + unless (exifHdr == 0x45786966) $ fail "Did not find exif header" + zeros <- getWord16be + unless (zeros == 0) $ fail "Expected zeros after exif header" + -- beginning of tiff header -- we read whole thing to use + -- in getting data from offsets: + tiffHeader <- lookAhead getRemainingLazyByteString + byteAlign <- getWord16be + let bigEndian = byteAlign == 0x4d4d + let (getWord16, getWord32, getWord64) = + if bigEndian + then (getWord16be, getWord32be, getWord64be) + else (getWord16le, getWord32le, getWord64le) + let getRational = do + num <- getWord32 + den <- getWord32 + return $ fromIntegral num / fromIntegral den + tagmark <- getWord16 + unless (tagmark == 0x002a) $ fail "Failed alignment sanity check" + ifdOffset <- getWord32 + skip (fromIntegral ifdOffset - 8) -- skip to IDF + numentries <- getWord16 + let ifdEntry = do + tag <- getWord16 >>= \t -> + maybe (fail $ "Unknown tag type " ++ show t) return + (M.lookup t tagTypeTable) + dataFormat <- getWord16 + numComponents <- getWord32 + (fmt, bytesPerComponent) <- + case dataFormat of + 1 -> return (UnsignedByte . runGet getWord8, 1) + 2 -> return (AsciiString, 1) + 3 -> return (UnsignedShort . runGet getWord16, 2) + 4 -> return (UnsignedLong . runGet getWord32, 4) + 5 -> return (UnsignedRational . runGet getRational, 8) + 6 -> return (SignedByte . runGet getWord8, 1) + 7 -> return (Undefined . runGet getWord8, 1) + 8 -> return (SignedShort . runGet getWord16, 2) + 9 -> return (SignedLong . runGet getWord32, 4) + 10 -> return (SignedRational . runGet getRational, 8) + 11 -> return (SingleFloat . runGet getWord32 {- TODO -}, 4) + 12 -> return (DoubleFloat . runGet getWord64 {- TODO -}, 8) + _ -> fail $ "Unknown data format " ++ show dataFormat + let totalBytes = fromIntegral $ numComponents * bytesPerComponent + payload <- if totalBytes <= 4 -- data is right here + then fmt <$> + (getLazyByteString (fromIntegral totalBytes) <* + skip (4 - totalBytes)) + else do -- get data from offset + offs <- getWord32 + return $ fmt $ BL.take (fromIntegral totalBytes) $ + BL.drop (fromIntegral offs) tiffHeader + return (tag, payload) + entries <- sequence $ replicate (fromIntegral numentries) ifdEntry + subentries <- case lookup ExifOffset entries of + Just (UnsignedLong offset) -> do + pos <- bytesRead + skip (fromIntegral offset - (fromIntegral pos - 8)) + numsubentries <- getWord16 + sequence $ + replicate (fromIntegral numsubentries) ifdEntry + _ -> return [] + let allentries = entries ++ subentries + (width, height) <- case (lookup ExifImageWidth allentries, + lookup ExifImageHeight allentries) of + (Just (UnsignedLong w), Just (UnsignedLong h)) -> + return (fromIntegral w, fromIntegral h) + _ -> fail "Could not determine image width, height" + let resfactor = case lookup ResolutionUnit allentries of + Just (UnsignedShort 1) -> (100 / 254) + _ -> 1 + let xres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor) + $ lookup XResolution allentries + let yres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor) + $ lookup YResolution allentries + return $ ImageSize{ + pxX = width + , pxY = height + , dpiX = xres + , dpiY = yres } + +data DataFormat = UnsignedByte Word8 + | AsciiString BL.ByteString + | UnsignedShort Word16 + | UnsignedLong Word32 + | UnsignedRational Rational + | SignedByte Word8 + | Undefined Word8 + | SignedShort Word16 + | SignedLong Word32 + | SignedRational Rational + | SingleFloat Word32 + | DoubleFloat Word64 + deriving (Show) + +data TagType = ImageDescription + | Make + | Model + | Orientation + | XResolution + | YResolution + | ResolutionUnit + | Software + | DateTime + | WhitePoint + | PrimaryChromaticities + | YCbCrCoefficients + | YCbCrPositioning + | ReferenceBlackWhite + | Copyright + | ExifOffset + | ExposureTime + | FNumber + | ExposureProgram + | ISOSpeedRatings + | ExifVersion + | DateTimeOriginal + | DateTimeDigitized + | ComponentConfiguration + | CompressedBitsPerPixel + | ShutterSpeedValue + | ApertureValue + | BrightnessValue + | ExposureBiasValue + | MaxApertureValue + | SubjectDistance + | MeteringMode + | LightSource + | Flash + | FocalLength + | MakerNote + | UserComment + | FlashPixVersion + | ColorSpace + | ExifImageWidth + | ExifImageHeight + | RelatedSoundFile + | ExifInteroperabilityOffset + | FocalPlaneXResolution + | FocalPlaneYResolution + | FocalPlaneResolutionUnit + | SensingMethod + | FileSource + | SceneType + deriving (Show, Eq, Ord) +tagTypeTable :: M.Map Word16 TagType +tagTypeTable = M.fromList + [ (0x010e, ImageDescription) + , (0x010f, Make) + , (0x0110, Model) + , (0x0112, Orientation) + , (0x011a, XResolution) + , (0x011b, YResolution) + , (0x0128, ResolutionUnit) + , (0x0131, Software) + , (0x0132, DateTime) + , (0x013e, WhitePoint) + , (0x013f, PrimaryChromaticities) + , (0x0211, YCbCrCoefficients) + , (0x0213, YCbCrPositioning) + , (0x0214, ReferenceBlackWhite) + , (0x8298, Copyright) + , (0x8769, ExifOffset) + , (0x829a, ExposureTime) + , (0x829d, FNumber) + , (0x8822, ExposureProgram) + , (0x8827, ISOSpeedRatings) + , (0x9000, ExifVersion) + , (0x9003, DateTimeOriginal) + , (0x9004, DateTimeDigitized) + , (0x9101, ComponentConfiguration) + , (0x9102, CompressedBitsPerPixel) + , (0x9201, ShutterSpeedValue) + , (0x9202, ApertureValue) + , (0x9203, BrightnessValue) + , (0x9204, ExposureBiasValue) + , (0x9205, MaxApertureValue) + , (0x9206, SubjectDistance) + , (0x9207, MeteringMode) + , (0x9208, LightSource) + , (0x9209, Flash) + , (0x920a, FocalLength) + , (0x927c, MakerNote) + , (0x9286, UserComment) + , (0xa000, FlashPixVersion) + , (0xa001, ColorSpace) + , (0xa002, ExifImageWidth) + , (0xa003, ExifImageHeight) + , (0xa004, RelatedSoundFile) + , (0xa005, ExifInteroperabilityOffset) + , (0xa20e, FocalPlaneXResolution) + , (0xa20f, FocalPlaneYResolution) + , (0xa210, FocalPlaneResolutionUnit) + , (0xa217, SensingMethod) + , (0xa300, FileSource) + , (0xa301, SceneType) + ] diff --git a/src/Text/Pandoc/MIME.hs b/src/Text/Pandoc/MIME.hs index d9cb94a33..44989ee94 100644 --- a/src/Text/Pandoc/MIME.hs +++ b/src/Text/Pandoc/MIME.hs @@ -40,7 +40,8 @@ getMimeType f = M.lookup (map toLower $ drop 1 $ takeExtension f) mimeTypes where mimeTypes = M.fromList mimeTypesList extensionFromMimeType :: String -> Maybe String -extensionFromMimeType mimetype = M.lookup mimetype reverseMimeTypes +extensionFromMimeType mimetype = M.lookup (takeWhile (/=';') mimetype) reverseMimeTypes + -- note: we just look up the basic mime type, dropping the content-encoding etc. where reverseMimeTypes = M.fromList $ map (\(k,v) -> (v,k)) mimeTypesList mimeTypesList :: [(String, String)] @@ -146,6 +147,7 @@ mimeTypesList = -- List borrowed from happstack-server. ,("dxr","application/x-director") ,("emb","chemical/x-embl-dl-nucleotide") ,("embl","chemical/x-embl-dl-nucleotide") + ,("emf","image/x-emf") ,("eml","message/rfc822") ,("ent","chemical/x-ncbi-asn1-ascii") ,("eot","application/vnd.ms-fontobject") @@ -219,6 +221,7 @@ mimeTypesList = -- List borrowed from happstack-server. ,("jnlp","application/x-java-jnlp-file") ,("jpe","image/jpeg") ,("jpeg","image/jpeg") + ,("jfif","image/jpeg") ,("jpg","image/jpeg") ,("js","application/x-javascript") ,("kar","audio/midi") @@ -463,6 +466,7 @@ mimeTypesList = -- List borrowed from happstack-server. ,("wm","video/x-ms-wm") ,("wma","audio/x-ms-wma") ,("wmd","application/x-ms-wmd") + ,("wmf","image/x-wmf") ,("wml","text/vnd.wap.wml") ,("wmlc","application/vnd.wap.wmlc") ,("wmls","text/vnd.wap.wmlscript") diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs index 48e418ab2..5f65abdde 100644 --- a/src/Text/Pandoc/Options.hs +++ b/src/Text/Pandoc/Options.hs @@ -80,6 +80,7 @@ data Extension = | Ext_link_attributes -- ^ MMD style reference link attributes | Ext_autolink_bare_uris -- ^ Make all absolute URIs into links | Ext_fancy_lists -- ^ Enable fancy list numbers and delimiters + | Ext_lists_without_preceding_blankline -- ^ Allow lists without preceding blank | Ext_startnum -- ^ Make start number of ordered list significant | Ext_definition_lists -- ^ Definition lists as in pandoc, mmd, php | Ext_example_lists -- ^ Markdown-style numbered examples @@ -169,6 +170,7 @@ githubMarkdownExtensions = Set.fromList , Ext_intraword_underscores , Ext_strikeout , Ext_hard_line_breaks + , Ext_lists_without_preceding_blankline ] multimarkdownExtensions :: Set Extension diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs index a445e2991..360338f8f 100644 --- a/src/Text/Pandoc/PDF.hs +++ b/src/Text/Pandoc/PDF.hs @@ -41,6 +41,7 @@ import System.Directory import System.Environment import Control.Monad (unless) import Data.List (isInfixOf) +import Data.Maybe (fromMaybe) import qualified Data.ByteString.Base64 as B64 import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Definition @@ -87,7 +88,7 @@ handleImage' baseURL tmpdir (Image ils (src,tit)) = do res <- fetchItem baseURL src case res of Right (contents, Just mime) -> do - let ext = maybe (takeExtension src) id $ + let ext = fromMaybe (takeExtension src) $ extensionFromMimeType mime let basename = UTF8.toString $ B64.encode $ UTF8.fromString src let fname = tmpdir </> basename <.> ext @@ -107,7 +108,7 @@ tex2pdf' tmpDir program source = do then 3 -- to get page numbers else 2 -- 1 run won't give you PDF bookmarks (exit, log', mbPdf) <- runTeXProgram program numruns tmpDir source - let msg = "Error producing PDF from TeX source." + let msg = "Error producing PDF from TeX source.\n" case (exit, mbPdf) of (ExitFailure _, _) -> do let logmsg = extractMsg log' @@ -116,7 +117,7 @@ tex2pdf' tmpDir program source = do x | "! Package inputenc Error" `BC.isPrefixOf` x -> "\nTry running pandoc with --latex-engine=xelatex." _ -> "" - return $ Left $ msg <> "\n" <> extractMsg log' <> extramsg + return $ Left $ msg <> logmsg <> extramsg (ExitSuccess, Nothing) -> return $ Left msg (ExitSuccess, Just pdf) -> return $ Right pdf diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs index 701b2ef84..2f21e1253 100644 --- a/src/Text/Pandoc/Parsing.hs +++ b/src/Text/Pandoc/Parsing.hs @@ -1,4 +1,5 @@ -{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances, + FlexibleInstances#-} {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> @@ -47,6 +48,8 @@ module Text.Pandoc.Parsing ( (>>~), romanNumeral, emailAddress, uri, + mathInline, + mathDisplay, withHorizDisplacement, withRaw, escaped, @@ -65,6 +68,9 @@ module Text.Pandoc.Parsing ( (>>~), guardEnabled, guardDisabled, ParserState (..), + HasReaderOptions (..), + HasHeaderMap (..), + HasIdentifierList (..), defaultParserState, HeaderType (..), ParserContext (..), @@ -265,7 +271,7 @@ spaceChar = satisfy $ \c -> c == ' ' || c == '\t' -- | Parses a nonspace, nonnewline character. nonspaceChar :: Parser [Char] st Char -nonspaceChar = satisfy $ \x -> x /= '\t' && x /= '\n' && x /= ' ' && x /= '\r' +nonspaceChar = satisfy $ flip notElem ['\t', '\n', ' ', '\r'] -- | Skips zero or more spaces or tabs. skipSpaces :: Parser [Char] st () @@ -451,6 +457,39 @@ uri = try $ do let uri' = scheme ++ ":" ++ fromEntities str' return (uri', escapeURI uri') +mathInlineWith :: String -> String -> Parser [Char] st String +mathInlineWith op cl = try $ do + string op + notFollowedBy space + words' <- many1Till (count 1 (noneOf "\n\\") + <|> (char '\\' >> anyChar >>= \c -> return ['\\',c]) + <|> count 1 newline <* notFollowedBy' blankline + *> return " ") + (try $ string cl) + notFollowedBy digit -- to prevent capture of $5 + return $ concat words' + +mathDisplayWith :: String -> String -> Parser [Char] st String +mathDisplayWith op cl = try $ do + string op + many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl) + +mathDisplay :: Parser [Char] ParserState String +mathDisplay = + (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$") + <|> (guardEnabled Ext_tex_math_single_backslash >> + mathDisplayWith "\\[" "\\]") + <|> (guardEnabled Ext_tex_math_double_backslash >> + mathDisplayWith "\\\\[" "\\\\]") + +mathInline :: Parser [Char] ParserState String +mathInline = + (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$") + <|> (guardEnabled Ext_tex_math_single_backslash >> + mathInlineWith "\\(" "\\)") + <|> (guardEnabled Ext_tex_math_double_backslash >> + mathInlineWith "\\\\(" "\\\\)") + -- | 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 @@ -826,6 +865,34 @@ instance HasMeta ParserState where deleteMeta field st = st{ stateMeta = deleteMeta field $ stateMeta st } +class Monad m => HasReaderOptions m where + askReaderOption :: (ReaderOptions -> b) -> m b + +class Monad m => HasHeaderMap m where + getHeaderMap :: m (M.Map Inlines String) + putHeaderMap :: M.Map Inlines String -> m () + modifyHeaderMap :: (M.Map Inlines String -> M.Map Inlines String) -> m () + -- default + modifyHeaderMap f = getHeaderMap >>= putHeaderMap . f + +class Monad m => HasIdentifierList m where + getIdentifierList :: m [String] + putIdentifierList :: [String] -> m () + modifyIdentifierList :: ([String] -> [String]) -> m () + -- default + modifyIdentifierList f = getIdentifierList >>= putIdentifierList . f + +instance HasReaderOptions (Parser s ParserState) where + askReaderOption = getOption + +instance HasHeaderMap (Parser s ParserState) where + getHeaderMap = fmap stateHeaders getState + putHeaderMap hm = updateState $ \st -> st{ stateHeaders = hm } + +instance HasIdentifierList (Parser s ParserState) where + getIdentifierList = fmap stateIdentifiers getState + putIdentifierList l = updateState $ \st -> st{ stateIdentifiers = l } + defaultParserState :: ParserState defaultParserState = ParserState { stateOptions = def, @@ -895,10 +962,11 @@ type SubstTable = M.Map Key Inlines -- and the auto_identifers extension is set, generate a new -- unique identifier, and update the list of identifiers -- in state. -registerHeader :: Attr -> Inlines -> Parser s ParserState Attr +registerHeader :: (HasReaderOptions m, HasHeaderMap m, HasIdentifierList m) + => Attr -> Inlines -> m Attr registerHeader (ident,classes,kvs) header' = do - ids <- stateIdentifiers `fmap` getState - exts <- getOption readerExtensions + ids <- getIdentifierList + exts <- askReaderOption readerExtensions let insert' = M.insertWith (\_new old -> old) if null ident && Ext_auto_identifiers `Set.member` exts then do @@ -906,16 +974,13 @@ registerHeader (ident,classes,kvs) header' = do let id'' = if Ext_ascii_identifiers `Set.member` exts then catMaybes $ map toAsciiChar id' else id' - updateState $ \st -> st{ - stateIdentifiers = if id' == id'' - then id' : ids - else id' : id'' : ids, - stateHeaders = insert' header' id' $ stateHeaders st } + putIdentifierList $ if id' == id'' + then id' : ids + else id' : id'' : ids + modifyHeaderMap $ insert' header' id' return (id'',classes,kvs) else do - unless (null ident) $ - updateState $ \st -> st{ - stateHeaders = insert' header' ident $ stateHeaders st } + unless (null ident) $ modifyHeaderMap $ insert' header' ident return (ident,classes,kvs) -- | Fail unless we're in "smart typography" mode. @@ -997,7 +1062,7 @@ doubleQuoteStart :: Parser [Char] ParserState () doubleQuoteStart = do failIfInQuoteContext InDoubleQuote try $ do charOrRef "\"\8220\147" - notFollowedBy (satisfy (\c -> c == ' ' || c == '\t' || c == '\n')) + notFollowedBy . satisfy $ flip elem [' ', '\t', '\n'] doubleQuoteEnd :: Parser [Char] st () doubleQuoteEnd = do diff --git a/src/Text/Pandoc/Pretty.hs b/src/Text/Pandoc/Pretty.hs index faf2a6797..033511832 100644 --- a/src/Text/Pandoc/Pretty.hs +++ b/src/Text/Pandoc/Pretty.hs @@ -60,6 +60,7 @@ module Text.Pandoc.Pretty ( , hsep , vcat , vsep + , nestle , chomp , inside , braces @@ -72,7 +73,7 @@ module Text.Pandoc.Pretty ( ) where -import Data.Sequence (Seq, fromList, (<|), singleton, mapWithIndex) +import Data.Sequence (Seq, fromList, (<|), singleton, mapWithIndex, viewl, ViewL(..)) import Data.Foldable (toList) import Data.List (intercalate) import Data.Monoid @@ -186,6 +187,14 @@ vcat = foldr ($$) empty vsep :: [Doc] -> Doc vsep = foldr ($+$) empty +-- | Removes leading blank lines from a 'Doc'. +nestle :: Doc -> Doc +nestle (Doc d) = Doc $ go d + where go x = case viewl x of + (BlankLine :< rest) -> go rest + (NewLine :< rest) -> go rest + _ -> x + -- | Chomps trailing blank space off of a 'Doc'. chomp :: Doc -> Doc chomp d = Doc (fromList dl') diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs index 6a799e270..56cb16b20 100644 --- a/src/Text/Pandoc/Readers/DocBook.hs +++ b/src/Text/Pandoc/Readers/DocBook.hs @@ -1,5 +1,6 @@ module Text.Pandoc.Readers.DocBook ( readDocBook ) where -import Data.Char (toUpper, isDigit) +import Data.Char (toUpper) +import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Builder @@ -11,6 +12,7 @@ import Data.Char (isSpace) import Control.Monad.State import Control.Applicative ((<$>)) import Data.List (intersperse) +import Data.Maybe (fromMaybe) {- @@ -682,10 +684,9 @@ parseBlock (Elem e) = "lowerroman" -> LowerRoman "upperroman" -> UpperRoman _ -> Decimal - let start = case attrValue "override" <$> - filterElement (named "listitem") e of - Just x@(_:_) | all isDigit x -> read x - _ -> 1 + let start = fromMaybe 1 $ + (attrValue "override" <$> filterElement (named "listitem") e) + >>= safeRead orderedListWith (start,listStyle,DefaultDelim) <$> listitems "variablelist" -> definitionList <$> deflistitems @@ -779,7 +780,7 @@ parseBlock (Elem e) = caption <- case filterChild isCaption e of Just t -> getInlines t Nothing -> return mempty - let e' = maybe e id $ filterChild (named "tgroup") e + let e' = fromMaybe e $ filterChild (named "tgroup") e let isColspec x = named "colspec" x || named "col" x let colspecs = case filterChild (named "colgroup") e' of Just c -> filterChildren isColspec c @@ -801,11 +802,14 @@ parseBlock (Elem e) = Just "center" -> AlignCenter _ -> AlignDefault let toWidth c = case findAttr (unqual "colwidth") c of - Just w -> read $ filter (\x -> + Just w -> fromMaybe 0 + $ safeRead $ '0': filter (\x -> (x >= '0' && x <= '9') || x == '.') w Nothing -> 0 :: Double - let numrows = maximum $ map length bodyrows + let numrows = case bodyrows of + [] -> 0 + xs -> maximum $ map length xs let aligns = case colspecs of [] -> replicate numrows AlignDefault cs -> map toAlignment cs diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs index 7ca554fa3..506fe7770 100644 --- a/src/Text/Pandoc/Readers/HTML.hs +++ b/src/Text/Pandoc/Readers/HTML.hs @@ -76,9 +76,18 @@ pBody :: TagParser [Block] pBody = pInTags "body" block pHead :: TagParser [Block] -pHead = pInTags "head" $ pTitle <|> ([] <$ pAnyTag) +pHead = pInTags "head" $ pTitle <|> pMetaTag <|> ([] <$ pAnyTag) where pTitle = pInTags "title" inline >>= setTitle . normalizeSpaces setTitle t = [] <$ (updateState $ B.setMeta "title" (B.fromList t)) + pMetaTag = do + mt <- pSatisfy (~== TagOpen "meta" []) + let name = fromAttrib "name" mt + if null name + then return [] + else do + let content = fromAttrib "content" mt + updateState $ B.setMeta name (B.text content) + return [] block :: TagParser [Block] block = choice @@ -92,6 +101,7 @@ block = choice , pHead , pBody , pPlain + , pDiv , pRawHtmlBlock ] @@ -177,6 +187,13 @@ pRawTag = do then return [] else return $ renderTags' [tag] +pDiv :: TagParser [Block] +pDiv = try $ do + getOption readerParseRaw >>= guard + TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="div") (const True) + contents <- pInTags "div" block + return [Div (mkAttr attr) contents] + pRawHtmlBlock :: TagParser [Block] pRawHtmlBlock = do raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag @@ -199,7 +216,7 @@ pHeader = try $ do let bodyTitle = TagOpen tagtype attr ~== TagOpen "h1" [("class","title")] let level = read (drop 1 tagtype) contents <- liftM concat $ manyTill inline (pCloses tagtype <|> eof) - let ident = maybe "" id $ lookup "id" attr + let ident = fromMaybe "" $ lookup "id" attr let classes = maybe [] words $ lookup "class" attr let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"] return $ if bodyTitle @@ -249,7 +266,7 @@ pCol = try $ do skipMany pBlank return $ case lookup "width" attribs of Just x | not (null x) && last x == '%' -> - maybe 0.0 id $ safeRead ('0':'.':init x) + fromMaybe 0.0 $ safeRead ('0':'.':init x) _ -> 0.0 pColgroup :: TagParser [Double] @@ -295,11 +312,7 @@ pCodeBlock = try $ do let result = case reverse result' of '\n':_ -> init result' _ -> result' - let attribsId = fromMaybe "" $ lookup "id" attr - let attribsClasses = words $ fromMaybe "" $ lookup "class" attr - let attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr - let attribs = (attribsId, attribsClasses, attribsKV) - return [CodeBlock attribs result] + return [CodeBlock (mkAttr attr) result] inline :: TagParser [Inline] inline = choice @@ -314,6 +327,7 @@ inline = choice , pLink , pImage , pCode + , pSpan , pRawHtmlInline ] @@ -397,11 +411,14 @@ pCode :: TagParser [Inline] pCode = try $ do (TagOpen open attr) <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True) result <- manyTill pAnyTag (pCloses open) - let ident = fromMaybe "" $ lookup "id" attr - let classes = words $ fromMaybe [] $ lookup "class" attr - let rest = filter (\(x,_) -> x /= "id" && x /= "class") attr - return [Code (ident,classes,rest) - $ intercalate " " $ lines $ innerText result] + return [Code (mkAttr attr) $ intercalate " " $ lines $ innerText result] + +pSpan :: TagParser [Inline] +pSpan = try $ do + getOption readerParseRaw >>= guard + TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True) + contents <- pInTags "span" inline + return [Span (mkAttr attr) contents] pRawHtmlInline :: TagParser [Inline] pRawHtmlInline = do @@ -459,7 +476,13 @@ pBlank = try $ do pTagContents :: Parser [Char] ParserState Inline pTagContents = - pStr <|> pSpace <|> smartPunctuation pTagContents <|> pSymbol <|> pBad + Math InlineMath `fmap` mathInline + <|> Math DisplayMath `fmap` mathDisplay + <|> pStr + <|> pSpace + <|> smartPunctuation pTagContents + <|> pSymbol + <|> pBad pStr :: Parser [Char] ParserState Inline pStr = do @@ -474,6 +497,7 @@ isSpecial '"' = True isSpecial '\'' = True isSpecial '.' = True isSpecial '-' = True +isSpecial '$' = True isSpecial '\8216' = True isSpecial '\8217' = True isSpecial '\8220' = True @@ -549,7 +573,7 @@ blockHtmlTags = ["address", "article", "aside", "blockquote", "body", "button", "noframes", "noscript", "object", "ol", "output", "p", "pre", "progress", "section", "table", "tbody", "textarea", "thead", "tfoot", "ul", "dd", "dt", "frameset", "li", "tbody", "td", "tfoot", - "th", "thead", "tr", "script", "style", "video"] + "th", "thead", "tr", "script", "style", "svg", "video"] -- We want to allow raw docbook in markdown documents, so we -- include docbook block tags here too. @@ -648,3 +672,10 @@ htmlTag f = try $ do _ -> do rendered <- manyTill anyChar (char '>') return (next, rendered ++ ">") + +mkAttr :: [(String, String)] -> Attr +mkAttr attr = (attribsId, attribsClasses, attribsKV) + where attribsId = fromMaybe "" $ lookup "id" attr + attribsClasses = words $ fromMaybe "" $ lookup "class" attr + attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr + diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs index ff5b73348..51271edc5 100644 --- a/src/Text/Pandoc/Readers/LaTeX.hs +++ b/src/Text/Pandoc/Readers/LaTeX.hs @@ -38,12 +38,13 @@ import Text.Pandoc.Definition import Text.Pandoc.Walk import Text.Pandoc.Shared import Text.Pandoc.Options -import Text.Pandoc.Parsing hiding ((<|>), many, optional, space) +import Text.Pandoc.Parsing hiding ((<|>), many, optional, space, + mathDisplay, mathInline) import qualified Text.Pandoc.UTF8 as UTF8 import Data.Char ( chr, ord ) import Control.Monad import Text.Pandoc.Builder -import Data.Char (isLetter) +import Data.Char (isLetter, isAlphaNum) import Control.Applicative import Data.Monoid import Data.Maybe (fromMaybe) @@ -163,28 +164,40 @@ mathChars = concat <$> <|> (\c -> ['\\',c]) <$> (try $ char '\\' *> anyChar) ) +quoted' :: (Inlines -> Inlines) -> LP String -> LP () -> LP Inlines +quoted' f starter ender = do + startchs <- starter + try ((f . mconcat) <$> manyTill inline ender) <|> lit startchs + double_quote :: LP Inlines -double_quote = (doubleQuoted . mconcat) <$> - (try $ string "``" *> manyTill inline (try $ string "''")) +double_quote = + ( quoted' doubleQuoted (try $ string "``") (void $ try $ string "''") + <|> quoted' doubleQuoted (string "“") (void $ char '”') + -- the following is used by babel for localized quotes: + <|> quoted' doubleQuoted (try $ string "\"`") (void $ try $ string "\"'") + <|> quoted' doubleQuoted (string "\"") (void $ char '"') + ) single_quote :: LP Inlines -single_quote = (singleQuoted . mconcat) <$> - (try $ char '`' *> manyTill inline (try $ char '\'' >> notFollowedBy letter)) +single_quote = + ( quoted' singleQuoted (string "`") (try $ char '\'' >> notFollowedBy letter) + <|> quoted' singleQuoted (string "‘") (try $ char '’' >> notFollowedBy letter) + ) inline :: LP Inlines inline = (mempty <$ comment) <|> (space <$ sp) <|> inlineText <|> inlineCommand - <|> grouped inline + <|> inlineGroup <|> (char '-' *> option (str "-") ((char '-') *> option (str "–") (str "—" <$ char '-'))) <|> double_quote <|> single_quote - <|> (str "“" <$ try (string "``")) -- nb. {``} won't be caught by double_quote <|> (str "”" <$ try (string "''")) - <|> (str "‘" <$ char '`') -- nb. {`} won't be caught by single_quote + <|> (str "”" <$ char '”') <|> (str "’" <$ char '\'') + <|> (str "’" <$ char '’') <|> (str "\160" <$ char '~') <|> (mathDisplay $ string "$$" *> mathChars <* string "$$") <|> (mathInline $ char '$' *> mathChars <* char '$') @@ -199,6 +212,15 @@ inline = (mempty <$ comment) inlines :: LP Inlines inlines = mconcat <$> many (notFollowedBy (char '}') *> inline) +inlineGroup :: LP Inlines +inlineGroup = do + ils <- grouped inline + if isNull ils + then return mempty + else return $ spanWith nullAttr ils + -- we need the span so we can detitlecase bibtex entries; + -- we need to know when something is {C}apitalized + block :: LP Blocks block = (mempty <$ comment) <|> (mempty <$ ((spaceChar <|> newline) *> spaces)) @@ -364,6 +386,7 @@ inlineCommands = M.fromList $ , ("backslash", lit "\\") , ("slash", lit "/") , ("textbf", strong <$> tok) + , ("textnormal", spanWith ("",["nodecor"],[]) <$> tok) , ("ldots", lit "…") , ("dots", lit "…") , ("mdots", lit "…") @@ -434,6 +457,7 @@ inlineCommands = M.fromList $ , ("footnote", (note . mconcat) <$> (char '{' *> manyTill block (char '}'))) , ("verb", doverb) , ("lstinline", doverb) + , ("Verb", doverb) , ("texttt", (code . stringify . toList) <$> tok) , ("url", (unescapeURL <$> braced) >>= \url -> pure (link url "" (str url))) @@ -518,9 +542,7 @@ inNote ils = unescapeURL :: String -> String unescapeURL ('\\':x:xs) | isEscapable x = x:unescapeURL xs - where isEscapable '%' = True - isEscapable '#' = True - isEscapable _ = False + where isEscapable c = c `elem` "#$%&~_^\\{}" unescapeURL (x:xs) = x:unescapeURL xs unescapeURL [] = "" @@ -747,7 +769,7 @@ inlineText :: LP Inlines inlineText = str <$> many1 inlineChar inlineChar :: LP Char -inlineChar = noneOf "\\$%^_&~#{}^'`-[] \t\n" +inlineChar = noneOf "\\$%^_&~#{}^'`\"‘’“”-[] \t\n" environment :: LP Blocks environment = do @@ -852,9 +874,8 @@ verbatimEnv = do (_,r) <- withRaw $ do controlSeq "begin" name <- braced - guard $ name == "verbatim" || name == "Verbatim" || - name == "lstlisting" || name == "minted" || - name == "alltt" + guard $ name `elem` ["verbatim", "Verbatim", "lstlisting", + "minted", "alltt"] verbEnv name rest <- getInput return (r,rest) @@ -1030,14 +1051,14 @@ paragraph = do preamble :: LP Blocks preamble = mempty <$> manyTill preambleBlock beginDoc where beginDoc = lookAhead $ controlSeq "begin" *> string "{document}" - preambleBlock = (mempty <$ comment) - <|> (mempty <$ sp) - <|> (mempty <$ blanklines) - <|> (mempty <$ macro) - <|> blockCommand - <|> (mempty <$ anyControlSeq) - <|> (mempty <$ braced) - <|> (mempty <$ anyChar) + preambleBlock = (void comment) + <|> (void sp) + <|> (void blanklines) + <|> (void macro) + <|> (void blockCommand) + <|> (void anyControlSeq) + <|> (void braced) + <|> (void anyChar) ------- @@ -1058,6 +1079,7 @@ simpleCiteArgs = try $ do first <- optionMaybe $ toList <$> opt second <- optionMaybe $ toList <$> opt char '{' + optional sp keys <- manyTill citationLabel (char '}') let (pre, suf) = case (first , second ) of (Just s , Nothing) -> (mempty, s ) @@ -1073,18 +1095,24 @@ simpleCiteArgs = try $ do return $ addPrefix pre $ addSuffix suf $ map conv keys citationLabel :: LP String -citationLabel = trim <$> - (many1 (satisfy $ \c -> c /=',' && c /='}') <* optional (char ',') <* optional sp) +citationLabel = optional sp *> + (many1 (satisfy isBibtexKeyChar) + <* optional sp + <* optional (char ',') + <* optional sp) + where isBibtexKeyChar c = isAlphaNum c || c `elem` ".:;?!`'()/*@_+=-[]*" cites :: CitationMode -> Bool -> LP [Citation] cites mode multi = try $ do cits <- if multi then many1 simpleCiteArgs else count 1 simpleCiteArgs - let (c:cs) = concat cits + let cs = concat cits return $ case mode of - AuthorInText -> c {citationMode = mode} : cs - _ -> map (\a -> a {citationMode = mode}) (c:cs) + AuthorInText -> case cs of + (c:rest) -> c {citationMode = mode} : rest + [] -> [] + _ -> map (\a -> a {citationMode = mode}) cs citation :: String -> CitationMode -> Bool -> LP Inlines citation name mode multi = do diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index 9b98cbc3e..3feafd362 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -215,10 +215,10 @@ pandocTitleBlock = try $ do author' <- author date' <- date return $ - ( if B.isNull title' then id else B.setMeta "title" title' - . if null author' then id else B.setMeta "author" author' - . if B.isNull date' then id else B.setMeta "date" date' ) - nullMeta + (if B.isNull title' then id else B.setMeta "title" title') + . (if null author' then id else B.setMeta "author" author') + . (if B.isNull date' then id else B.setMeta "date" date') + $ nullMeta updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' } yamlMetaBlock :: MarkdownParser (F Blocks) @@ -227,6 +227,7 @@ yamlMetaBlock = try $ do pos <- getPosition string "---" blankline + notFollowedBy blankline -- if --- is followed by a blank it's an HRULE rawYamlLines <- manyTill anyLine stopLine -- by including --- and ..., we allow yaml blocks with just comments: let rawYaml = unlines ("---" : (rawYamlLines ++ ["..."])) @@ -443,6 +444,9 @@ block = choice [ mempty <$ blanklines , codeBlockFenced , yamlMetaBlock , guardEnabled Ext_latex_macros *> (macro >>= return . return) + -- note: bulletList needs to be before header because of + -- the possibility of empty list items: - + , bulletList , header , lhsCodeBlock , rawTeXBlock @@ -453,7 +457,6 @@ block = choice [ mempty <$ blanklines , codeBlockIndented , blockQuote , hrule - , bulletList , orderedList , definitionList , noteBlock @@ -698,7 +701,7 @@ bulletListStart = try $ do skipNonindentSpaces notFollowedBy' (() <$ hrule) -- because hrules start out just like lists satisfy isBulletListMarker - spaceChar + spaceChar <|> lookAhead newline skipSpaces anyOrderedListStart :: MarkdownParser (Int, ListNumberStyle, ListNumberDelim) @@ -726,11 +729,15 @@ listStart = bulletListStart <|> (anyOrderedListStart >> return ()) -- parse a line of a list item (start = parser for beginning of list item) listLine :: MarkdownParser String listLine = try $ do - notFollowedBy blankline notFollowedBy' (do indentSpaces - many (spaceChar) + many spaceChar listStart) - chunks <- manyTill (liftM snd (htmlTag isCommentTag) <|> count 1 anyChar) newline + notFollowedBy' $ htmlTag (~== TagClose "div") + chunks <- manyTill + ( many1 (satisfy $ \c -> c /= '\n' && c /= '<') + <|> liftM snd (htmlTag isCommentTag) + <|> count 1 anyChar + ) newline return $ concat chunks -- parse raw text for one list item, excluding start marker and continuations @@ -739,7 +746,7 @@ rawListItem :: MarkdownParser a rawListItem start = try $ do start first <- listLine - rest <- many (notFollowedBy listStart >> listLine) + rest <- many (notFollowedBy listStart >> notFollowedBy blankline >> listLine) blanks <- many blankline return $ unlines (first:rest) ++ blanks @@ -757,6 +764,7 @@ listContinuationLine :: MarkdownParser String listContinuationLine = try $ do notFollowedBy blankline notFollowedBy' listStart + notFollowedBy' $ htmlTag (~== TagClose "div") optional indentSpaces result <- anyLine return $ result ++ "\n" @@ -781,8 +789,8 @@ listItem start = try $ do orderedList :: MarkdownParser (F Blocks) orderedList = try $ do (start, style, delim) <- lookAhead anyOrderedListStart - unless ((style == DefaultStyle || style == Decimal || style == Example) && - (delim == DefaultDelim || delim == Period)) $ + unless (style `elem` [DefaultStyle, Decimal, Example] && + delim `elem` [DefaultDelim, Period]) $ guardEnabled Ext_fancy_lists when (style == Example) $ guardEnabled Ext_example_lists items <- fmap sequence $ many1 $ listItem @@ -871,8 +879,11 @@ para = try $ do $ try $ do newline (blanklines >> return mempty) - <|> (guardDisabled Ext_blank_before_blockquote >> lookAhead blockQuote) - <|> (guardDisabled Ext_blank_before_header >> lookAhead header) + <|> (guardDisabled Ext_blank_before_blockquote >> () <$ lookAhead blockQuote) + <|> (guardEnabled Ext_backtick_code_blocks >> () <$ lookAhead codeBlockFenced) + <|> (guardDisabled Ext_blank_before_header >> () <$ lookAhead header) + <|> (guardEnabled Ext_lists_without_preceding_blankline >> + () <$ lookAhead listStart) return $ do result' <- result case B.toList result' of @@ -891,7 +902,9 @@ plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline -- htmlElement :: MarkdownParser String -htmlElement = strictHtmlBlock <|> liftM snd (htmlTag isBlockTag) +htmlElement = rawVerbatimBlock + <|> strictHtmlBlock + <|> liftM snd (htmlTag isBlockTag) htmlBlock :: MarkdownParser (F Blocks) htmlBlock = do @@ -912,8 +925,8 @@ strictHtmlBlock = htmlInBalanced (not . isInlineTag) rawVerbatimBlock :: MarkdownParser String rawVerbatimBlock = try $ do - (TagOpen tag _, open) <- htmlTag (tagOpen (\t -> - t == "pre" || t == "style" || t == "script") + (TagOpen tag _, open) <- htmlTag (tagOpen (flip elem + ["pre", "style", "script"]) (const True)) contents <- manyTill anyChar (htmlTag (~== TagClose tag)) return $ open ++ contents ++ renderTags [TagClose tag] @@ -1113,12 +1126,12 @@ multilineTableHeader headless = try $ do then liftM (map (:[]) . tail . splitStringByIndices (init indices)) $ lookAhead anyLine else return $ transpose $ map - (\ln -> tail $ splitStringByIndices (init indices) ln) + (tail . splitStringByIndices (init indices)) rawContent let aligns = zipWith alignType rawHeadsList lengths let rawHeads = if headless then replicate (length dashes) "" - else map unwords rawHeadsList + else map (unlines . map trim) rawHeadsList heads <- fmap sequence $ mapM (parseFromString (mconcat <$> many plain)) $ map trim rawHeads @@ -1175,7 +1188,7 @@ gridTableHeader headless = try $ do -- RST does not have a notion of alignments let rawHeads = if headless then replicate (length dashes) "" - else map unwords $ transpose + else map (unlines . map trim) $ transpose $ map (gridTableSplitLine indices) rawContent heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads return (heads, aligns, indices) @@ -1401,39 +1414,6 @@ math :: MarkdownParser (F Inlines) math = (return . B.displayMath <$> (mathDisplay >>= applyMacros')) <|> (return . B.math <$> (mathInline >>= applyMacros')) -mathDisplay :: MarkdownParser String -mathDisplay = - (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$") - <|> (guardEnabled Ext_tex_math_single_backslash >> - mathDisplayWith "\\[" "\\]") - <|> (guardEnabled Ext_tex_math_double_backslash >> - mathDisplayWith "\\\\[" "\\\\]") - -mathDisplayWith :: String -> String -> MarkdownParser String -mathDisplayWith op cl = try $ do - string op - many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl) - -mathInline :: MarkdownParser String -mathInline = - (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$") - <|> (guardEnabled Ext_tex_math_single_backslash >> - mathInlineWith "\\(" "\\)") - <|> (guardEnabled Ext_tex_math_double_backslash >> - mathInlineWith "\\\\(" "\\\\)") - -mathInlineWith :: String -> String -> MarkdownParser String -mathInlineWith op cl = try $ do - string op - notFollowedBy space - words' <- many1Till (count 1 (noneOf "\n\\") - <|> (char '\\' >> anyChar >>= \c -> return ['\\',c]) - <|> count 1 newline <* notFollowedBy' blankline - *> return " ") - (try $ string cl) - notFollowedBy digit -- to prevent capture of $5 - return $ concat words' - -- Parses material enclosed in *s, **s, _s, or __s. -- Designed to avoid backtracking. enclosure :: Char @@ -1450,6 +1430,7 @@ enclosure c = do -- Parse inlines til you hit one c or a sequence of two cs. -- If one c, emit emph and then parse two. -- If two cs, emit strong and then parse one. +-- Otherwise, emit ccc then the results. three :: Char -> MarkdownParser (F Inlines) three c = do contents <- mconcat <$> many (notFollowedBy (char c) >> inline) @@ -1474,7 +1455,7 @@ one c prefix' = do contents <- mconcat <$> many ( (notFollowedBy (char c) >> inline) <|> try (string [c,c] >> notFollowedBy (char c) >> - two c prefix') ) + two c mempty) ) (char c >> return (B.emph <$> (prefix' <> contents))) <|> return (return (B.str [c]) <> (prefix' <> contents)) @@ -1559,8 +1540,11 @@ endline :: MarkdownParser (F Inlines) endline = try $ do newline notFollowedBy blankline + guardDisabled Ext_lists_without_preceding_blankline <|> notFollowedBy listStart guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart guardEnabled Ext_blank_before_header <|> notFollowedBy (char '#') -- atx header + guardEnabled Ext_backtick_code_blocks >> + notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced)) -- parse potential list-starts differently if in a list: st <- getState when (stateParserContext st == ListItemState) $ do @@ -1738,7 +1722,7 @@ spanHtml = try $ do guardEnabled Ext_markdown_in_html_blocks (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" []) contents <- mconcat <$> manyTill inline (htmlTag (~== TagClose "span")) - let ident = maybe "" id $ lookup "id" attrs + let ident = fromMaybe "" $ lookup "id" attrs let classes = maybe [] words $ lookup "class" attrs let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"] return $ B.spanWith (ident, classes, keyvals) <$> contents @@ -1748,7 +1732,7 @@ divHtml = try $ do guardEnabled Ext_markdown_in_html_blocks (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "div" []) contents <- mconcat <$> manyTill block (htmlTag (~== TagClose "div")) - let ident = maybe "" id $ lookup "id" attrs + let ident = fromMaybe "" $ lookup "id" attrs let classes = maybe [] words $ lookup "class" attrs let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"] return $ B.divWith (ident, classes, keyvals) <$> contents @@ -1768,12 +1752,11 @@ rawHtmlInline = do cite :: MarkdownParser (F Inlines) cite = do guardEnabled Ext_citations - citations <- textualCite <|> (fmap (flip B.cite unknownC) <$> normalCite) + citations <- textualCite + <|> do (cs, raw) <- withRaw normalCite + return $ (flip B.cite (B.text raw)) <$> cs return citations -unknownC :: Inlines -unknownC = B.str "???" - textualCite :: MarkdownParser (F Inlines) textualCite = try $ do (_, key) <- citeKey @@ -1784,14 +1767,18 @@ textualCite = try $ do , citationNoteNum = 0 , citationHash = 0 } - mbrest <- option Nothing $ try $ spnl >> Just <$> normalCite + mbrest <- option Nothing $ try $ spnl >> Just <$> withRaw normalCite case mbrest of - Just rest -> return $ (flip B.cite unknownC . (first:)) <$> rest - Nothing -> (fmap (flip B.cite unknownC) <$> bareloc first) <|> - return (do st <- askF - return $ case M.lookup key (stateExamples st) of - Just n -> B.str (show n) - _ -> B.cite [first] unknownC) + Just (rest, raw) -> + return $ (flip B.cite (B.text $ '@':key ++ " " ++ raw) . (first:)) + <$> rest + Nothing -> + (do (cs, raw) <- withRaw $ bareloc first + return $ (flip B.cite (B.text $ '@':key ++ " " ++ raw)) <$> cs) + <|> return (do st <- askF + return $ case M.lookup key (stateExamples st) of + Just n -> B.str (show n) + _ -> B.cite [first] $ B.str $ '@':key) bareloc :: Citation -> MarkdownParser (F [Citation]) bareloc c = try $ do @@ -1817,11 +1804,17 @@ normalCite = try $ do citeKey :: MarkdownParser (Bool, String) citeKey = try $ do + -- make sure we're not right after an alphanumeric, + -- since foo@bar.baz is probably an email address + lastStrPos <- stateLastStrPos <$> getState + pos <- getPosition + guard $ lastStrPos /= Just pos suppress_author <- option False (char '-' >> return True) char '@' - first <- letter - let internal p = try $ p >>~ lookAhead (letter <|> digit) - rest <- many $ letter <|> digit <|> internal (oneOf ":.#$%&-_+?<>~/") + first <- letter <|> char '_' + let regchar = satisfy (\c -> isAlphaNum c || c == '_') + let internal p = try $ p >>~ lookAhead regchar + rest <- many $ regchar <|> internal (oneOf ":.#$%&-+?<>~/") let key = first:rest return (suppress_author, key) diff --git a/src/Text/Pandoc/Readers/MediaWiki.hs b/src/Text/Pandoc/Readers/MediaWiki.hs index 2b938cd82..8d8ea0199 100644 --- a/src/Text/Pandoc/Readers/MediaWiki.hs +++ b/src/Text/Pandoc/Readers/MediaWiki.hs @@ -1,4 +1,5 @@ -{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7 +{-# LANGUAGE RelaxedPolyRec, FlexibleInstances, TypeSynonymInstances #-} +-- RelaxedPolyRec needed for inlinesBetween on GHC < 7 {- Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu> @@ -43,7 +44,7 @@ import Text.Pandoc.Readers.HTML ( htmlTag, isBlockTag, isCommentTag ) import Text.Pandoc.XML ( fromEntities ) import Text.Pandoc.Parsing hiding ( nested ) import Text.Pandoc.Walk ( walk ) -import Text.Pandoc.Shared ( stripTrailingNewlines, safeRead ) +import Text.Pandoc.Shared ( stripTrailingNewlines, safeRead, stringify, trim ) import Data.Monoid (mconcat, mempty) import Control.Applicative ((<$>), (<*), (*>), (<$)) import Control.Monad @@ -51,7 +52,9 @@ import Data.List (intersperse, intercalate, isPrefixOf ) import Text.HTML.TagSoup import Data.Sequence (viewl, ViewL(..), (<|)) import qualified Data.Foldable as F +import qualified Data.Map as M import Data.Char (isDigit, isSpace) +import Data.Maybe (fromMaybe) -- | Read mediawiki from an input string and return a Pandoc document. readMediaWiki :: ReaderOptions -- ^ Reader options @@ -62,6 +65,8 @@ readMediaWiki opts s = , mwMaxNestingLevel = 4 , mwNextLinkNumber = 1 , mwCategoryLinks = [] + , mwHeaderMap = M.empty + , mwIdentifierList = [] } "source" (s ++ "\n") of Left err' -> error $ "\nError:\n" ++ show err' @@ -71,10 +76,23 @@ data MWState = MWState { mwOptions :: ReaderOptions , mwMaxNestingLevel :: Int , mwNextLinkNumber :: Int , mwCategoryLinks :: [Inlines] + , mwHeaderMap :: M.Map Inlines String + , mwIdentifierList :: [String] } type MWParser = Parser [Char] MWState +instance HasReaderOptions MWParser where + askReaderOption f = (f . mwOptions) `fmap` getState + +instance HasHeaderMap MWParser where + getHeaderMap = fmap mwHeaderMap getState + putHeaderMap hm = updateState $ \st -> st{ mwHeaderMap = hm } + +instance HasIdentifierList MWParser where + getIdentifierList = fmap mwIdentifierList getState + putIdentifierList l = updateState $ \st -> st{ mwIdentifierList = l } + -- -- auxiliary functions -- @@ -91,7 +109,7 @@ nested p = do return res specialChars :: [Char] -specialChars = "'[]<=&*{}|\"" +specialChars = "'[]<=&*{}|\":\\" spaceChars :: [Char] spaceChars = " \n\t" @@ -187,7 +205,7 @@ table = do tableStart styles <- option [] parseAttrs <* blankline let tableWidth = case lookup "width" styles of - Just w -> maybe 1.0 id $ parseWidth w + Just w -> fromMaybe 1.0 $ parseWidth w Nothing -> 1.0 caption <- option mempty tableCaption optional rowsep @@ -268,7 +286,7 @@ tableCell = try $ do Just "center" -> AlignCenter _ -> AlignDefault let width = case lookup "width" attrs of - Just xs -> maybe 0.0 id $ parseWidth xs + Just xs -> fromMaybe 0.0 $ parseWidth xs Nothing -> 0.0 return ((align, width), bs) @@ -351,7 +369,8 @@ header = try $ do let lev = length eqs guard $ lev <= 6 contents <- trimInlines . mconcat <$> manyTill inline (count lev $ char '=') - return $ B.header lev contents + attr <- registerHeader nullAttr contents + return $ B.headerWith attr lev contents bulletList :: MWParser Blocks bulletList = B.bulletList <$> @@ -369,7 +388,7 @@ orderedList = spaces items <- many (listItem '#' <|> li) optional (htmlTag (~== TagClose "ol")) - let start = maybe 1 id $ safeRead $ fromAttrib "start" tag + let start = fromMaybe 1 $ safeRead $ fromAttrib "start" tag return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items definitionList :: MWParser Blocks @@ -380,8 +399,9 @@ defListItem = try $ do terms <- mconcat . intersperse B.linebreak <$> many defListTerm -- we allow dd with no dt, or dt with no dd defs <- if B.isNull terms - then many1 $ listItem ':' - else many $ listItem ':' + then notFollowedBy (try $ string ":<math>") *> + many1 (listItem ':') + else many (listItem ':') return (terms, defs) defListTerm :: MWParser Inlines @@ -462,6 +482,7 @@ inline = whitespace <|> image <|> internalLink <|> externalLink + <|> math <|> inlineTag <|> B.singleton <$> charRef <|> inlineHtml @@ -472,6 +493,16 @@ inline = whitespace str :: MWParser Inlines str = B.str <$> many1 (noneOf $ specialChars ++ spaceChars) +math :: MWParser Inlines +math = (B.displayMath . trim <$> try (char ':' >> charsInTags "math")) + <|> (B.math . trim <$> charsInTags "math") + <|> (B.displayMath . trim <$> try (dmStart *> manyTill anyChar dmEnd)) + <|> (B.math . trim <$> try (mStart *> manyTill (satisfy (/='\n')) mEnd)) + where dmStart = string "\\[" + dmEnd = try (string "\\]") + mStart = string "\\(" + mEnd = try (string "\\)") + variable :: MWParser String variable = try $ do string "{{{" @@ -495,7 +526,6 @@ inlineTag = do TagOpen "del" _ -> B.strikeout <$> inlinesInTags "del" TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub" TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup" - TagOpen "math" _ -> B.math <$> charsInTags "math" TagOpen "code" _ -> B.code <$> charsInTags "code" TagOpen "tt" _ -> B.code <$> charsInTags "tt" TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask" @@ -528,7 +558,7 @@ image = try $ do _ <- many (try $ char '|' *> imageOption) caption <- (B.str fname <$ sym "]]") <|> try (char '|' *> (mconcat <$> manyTill inline (sym "]]"))) - return $ B.image fname "image" caption + return $ B.image fname ("fig:" ++ stringify caption) caption imageOption :: MWParser String imageOption = diff --git a/src/Text/Pandoc/Readers/TeXMath.hs b/src/Text/Pandoc/Readers/TeXMath.hs index 1f7088f72..6bd617f7e 100644 --- a/src/Text/Pandoc/Readers/TeXMath.hs +++ b/src/Text/Pandoc/Readers/TeXMath.hs @@ -27,16 +27,30 @@ 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 ) where +module Text.Pandoc.Readers.TeXMath ( readTeXMath, readTeXMath' ) where import Text.Pandoc.Definition import Text.TeXMath -- | Converts a raw TeX math formula to a list of 'Pandoc' inlines. --- Defaults to raw formula between @$@ characters if entire formula +-- Defaults to raw formula between @$@ or @$$@ characters if entire formula -- can't be converted. +readTeXMath' :: MathType + -> String -- ^ String to parse (assumes @'\n'@ line endings) + -> [Inline] +readTeXMath' mt inp = case texMathToPandoc dt inp of + Left _ -> [Str (delim ++ inp ++ delim)] + Right res -> res + where (dt, delim) = case mt of + DisplayMath -> (DisplayBlock, "$$") + InlineMath -> (DisplayInline, "$") + +{-# DEPRECATED readTeXMath "Use readTeXMath' from Text.Pandoc.JSON instead" #-} +-- | 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. (This is provided for backwards compatibility; +-- it is better to use @readTeXMath'@, which properly distinguishes +-- between display and inline math.) readTeXMath :: String -- ^ String to parse (assumes @'\n'@ line endings) -> [Inline] -readTeXMath inp = case texMathToPandoc DisplayInline inp of - Left _ -> [Str ("$" ++ inp ++ "$")] - Right res -> res +readTeXMath = readTeXMath' InlineMath diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs index 23e07f621..93658cdea 100644 --- a/src/Text/Pandoc/Readers/Textile.hs +++ b/src/Text/Pandoc/Readers/Textile.hs @@ -594,7 +594,7 @@ surrounded border = enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try bo simpleInline :: Parser [Char] ParserState t -- ^ surrounding parser -> ([Inline] -> Inline) -- ^ Inline constructor -> Parser [Char] ParserState Inline -- ^ content parser (to be used repeatedly) -simpleInline border construct = surrounded border (inlineWithAttribute) >>= +simpleInline border construct = surrounded border inlineWithAttribute >>= return . construct . normalizeSpaces where inlineWithAttribute = (try $ optional attributes) >> inline diff --git a/src/Text/Pandoc/SelfContained.hs b/src/Text/Pandoc/SelfContained.hs index 0547bc065..6112e764f 100644 --- a/src/Text/Pandoc/SelfContained.hs +++ b/src/Text/Pandoc/SelfContained.hs @@ -32,7 +32,7 @@ the HTML using data URIs. -} module Text.Pandoc.SelfContained ( makeSelfContained ) where import Text.HTML.TagSoup -import Network.URI (isAbsoluteURI, escapeURIString) +import Network.URI (isURI, escapeURIString) import Data.ByteString.Base64 import qualified Data.ByteString.Char8 as B import Data.ByteString (ByteString) @@ -86,7 +86,7 @@ cssURLs userdata d orig = "\"" -> B.takeWhile (/='"') $ B.drop 1 u "'" -> B.takeWhile (/='\'') $ B.drop 1 u _ -> u - let url' = if isAbsoluteURI url + let url' = if isURI url then url else d </> url (raw, mime) <- getRaw userdata "" url' @@ -97,7 +97,7 @@ cssURLs userdata d orig = getItem :: Maybe FilePath -> String -> IO (ByteString, Maybe String) getItem userdata f = - if isAbsoluteURI f + if isURI f then openURL f >>= either handleErr return else do -- strip off trailing query or fragment part, if relative URL. diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs index 9a9a092fc..714402e42 100644 --- a/src/Text/Pandoc/Shared.hs +++ b/src/Text/Pandoc/Shared.hs @@ -91,7 +91,8 @@ import Data.Char ( toLower, isLower, isUpper, isAlpha, isLetter, isDigit, isSpace ) import Data.List ( find, isPrefixOf, intercalate ) import qualified Data.Map as M -import Network.URI ( escapeURIString, isAbsoluteURI, unEscapeString ) +import Network.URI ( escapeURIString, isURI, nonStrictRelativeTo, + unEscapeString, parseURIReference ) import System.Directory import Text.Pandoc.MIME (getMimeType) import System.FilePath ( (</>), takeExtension, dropExtension ) @@ -108,6 +109,7 @@ import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..), import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as B8 import Text.Pandoc.Compat.Monoid +import Data.ByteString.Base64 (decodeLenient) #ifdef EMBED_DATA_FILES import Text.Pandoc.Data (dataFiles) @@ -120,6 +122,7 @@ import Data.ByteString.Lazy (toChunks) import Network.HTTP.Conduit (httpLbs, parseUrl, withManager, responseBody, responseHeaders) import Network.HTTP.Types.Header ( hContentType) +import Network (withSocketsDo) #else import Network.URI (parseURI) import Network.HTTP (findHeader, rspBody, @@ -269,7 +272,7 @@ normalizeDate s = fmap (formatTime defaultTimeLocale "%F") (msum $ map (\fs -> parsetimeWith fs s) formats :: Maybe Day) where parsetimeWith = parseTime defaultTimeLocale formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y", - "%d %B %Y", "%b. %d, %Y", "%B %d, %Y"] + "%d %B %Y", "%b. %d, %Y", "%B %d, %Y", "%Y"] -- -- Pandoc block and inline list processing @@ -530,7 +533,7 @@ headerShift n = walk shift -- | Detect if a list is tight. isTightList :: [[Block]] -> Bool -isTightList = and . map firstIsPlain +isTightList = all firstIsPlain where firstIsPlain (Plain _ : _) = True firstIsPlain _ = False @@ -562,14 +565,10 @@ makeMeta title authors date = -- | Render HTML tags. renderTags' :: [Tag String] -> String renderTags' = renderTagsOptions - renderOptions{ optMinimize = \x -> - let y = map toLower x - in y == "hr" || y == "br" || - y == "img" || y == "meta" || - y == "link" - , optRawTag = \x -> - let y = map toLower x - in y == "script" || y == "style" } + renderOptions{ optMinimize = matchTags ["hr", "br", "img", + "meta", "link"] + , optRawTag = matchTags ["script", "style"] } + where matchTags = \tags -> flip elem tags . map toLower -- -- File handling @@ -624,10 +623,14 @@ readDataFileUTF8 userDir fname = fetchItem :: Maybe String -> String -> IO (Either E.SomeException (BS.ByteString, Maybe String)) fetchItem sourceURL s - | isAbsoluteURI s = openURL s - | otherwise = case sourceURL of - Just u -> openURL (u ++ "/" ++ s) - Nothing -> E.try readLocalFile + | isURI s = openURL s + | otherwise = + case sourceURL >>= parseURIReference of + Just u -> case parseURIReference s of + Just s' -> openURL $ show $ + s' `nonStrictRelativeTo` u + Nothing -> openURL $ show u ++ "/" ++ s + Nothing -> E.try readLocalFile where readLocalFile = do let mime = case takeExtension s of ".gz" -> getMimeType $ dropExtension s @@ -641,9 +644,9 @@ openURL u | "data:" `isPrefixOf` u = let mime = takeWhile (/=',') $ drop 5 u contents = B8.pack $ unEscapeString $ drop 1 $ dropWhile (/=',') u - in return $ Right (contents, Just mime) + in return $ Right (decodeLenient contents, Just mime) #ifdef HTTP_CONDUIT - | otherwise = E.try $ do + | otherwise = withSocketsDo $ E.try $ do req <- parseUrl u resp <- withManager $ httpLbs req return (BS.concat $ toChunks $ responseBody resp, diff --git a/src/Text/Pandoc/Slides.hs b/src/Text/Pandoc/Slides.hs index 2bbdb120f..50c46d17f 100644 --- a/src/Text/Pandoc/Slides.hs +++ b/src/Text/Pandoc/Slides.hs @@ -46,13 +46,18 @@ getSlideLevel = go 6 -- | Prepare a block list to be passed to hierarchicalize. prepSlides :: Int -> [Block] -> [Block] -prepSlides slideLevel = ensureStartWithH . splitHrule +prepSlides slideLevel = ensureStartWithH . splitHrule . extractRefsHeader where splitHrule (HorizontalRule : Header n attr xs : ys) | n == slideLevel = Header slideLevel attr xs : splitHrule ys splitHrule (HorizontalRule : xs) = Header slideLevel nullAttr [Str "\0"] : splitHrule xs splitHrule (x : xs) = x : splitHrule xs splitHrule [] = [] + extractRefsHeader bs = + case reverse bs of + (Div ("",["references"],[]) (Header n attrs xs : ys) : zs) + -> reverse zs ++ (Header n attrs xs : [Div ("",["references"],[]) ys]) + _ -> bs ensureStartWithH bs@(Header n _ _:_) | n <= slideLevel = bs ensureStartWithH bs = Header slideLevel nullAttr [Str "\0"] : bs diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs index 22a44e735..ad8838f72 100644 --- a/src/Text/Pandoc/Templates.hs +++ b/src/Text/Pandoc/Templates.hs @@ -117,6 +117,7 @@ import Text.Blaze (preEscapedText, Html) #endif import Data.ByteString.Lazy (ByteString, fromChunks) import Text.Pandoc.Shared (readDataFileUTF8) +import Data.Vector ((!?)) -- | Get default template for the specified writer. getDefaultTemplate :: (Maybe FilePath) -- ^ User data directory to search first @@ -185,7 +186,7 @@ var = Template . resolveVar resolveVar :: Variable -> Value -> Text resolveVar var' val = case multiLookup var' val of - Just (Array vec) -> mconcat $ map (resolveVar []) $ toList vec + Just (Array vec) -> maybe mempty (resolveVar []) $ vec !? 0 Just (String t) -> T.stripEnd t Just (Number n) -> T.pack $ show n Just (Bool True) -> "true" @@ -212,7 +213,7 @@ iter var' template sep = Template $ \val -> unTemplate Just (Array vec) -> mconcat $ intersperse sep $ map (setVar template var') $ toList vec - Just x -> setVar template var' x + Just x -> cond var' (setVar template var' x) mempty Nothing -> mempty) val setVar :: Template -> Variable -> Value -> Template diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs index 0379f8b0a..3095cf508 100644 --- a/src/Text/Pandoc/Writers/ConTeXt.hs +++ b/src/Text/Pandoc/Writers/ConTeXt.hs @@ -130,7 +130,7 @@ blockToConTeXt (Plain lst) = inlineListToConTeXt lst -- title beginning with fig: indicates that the image is a figure blockToConTeXt (Para [Image txt (src,'f':'i':'g':':':_)]) = do capt <- inlineListToConTeXt txt - return $ blankline $$ "\\placefigure[here,nonumber]" <> braces capt <> + return $ blankline $$ "\\placefigure" <> braces capt <> braces ("\\externalfigure" <> brackets (text src)) <> blankline blockToConTeXt (Para lst) = do contents <- inlineListToConTeXt lst @@ -205,9 +205,9 @@ blockToConTeXt (Table caption aligns widths heads rows) = do else liftM ($$ "\\HL") $ tableRowToConTeXt heads captionText <- inlineListToConTeXt caption rows' <- mapM tableRowToConTeXt rows - return $ "\\placetable" <> brackets ("here" <> if null caption - then ",none" - else "") + return $ "\\placetable" <> (if null caption + then brackets "none" + else empty) <> braces captionText $$ "\\starttable" <> brackets (text colDescriptors) $$ "\\HL" $$ headers $$ diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs index 7c03c07dc..02d875be3 100644 --- a/src/Text/Pandoc/Writers/Docbook.hs +++ b/src/Text/Pandoc/Writers/Docbook.hs @@ -85,8 +85,9 @@ writeDocbook opts (Pandoc meta blocks) = auths' = map (authorToDocbook opts) $ docAuthors meta meta' = B.setMeta "author" auths' meta Just metadata = metaToJSON opts - (Just . render colwidth . blocksToDocbook opts) - (Just . render colwidth . inlinesToDocbook opts) + (Just . render colwidth . (vcat . + (map (elementToDocbook opts' startLvl)) . hierarchicalize)) + (Just . render colwidth . inlinesToDocbook opts') meta' main = render' $ vcat (map (elementToDocbook opts' startLvl) elements) context = defField "body" main @@ -281,8 +282,8 @@ inlineToDocbook opts (Math t str) $ fixNS $ removeAttr r Left _ -> inlinesToDocbook opts - $ readTeXMath str - | otherwise = inlinesToDocbook opts $ readTeXMath str + $ readTeXMath' t str + | otherwise = inlinesToDocbook opts $ readTeXMath' t str where (dt, tagtype) = case t of InlineMath -> (DisplayInline,"inlineequation") DisplayMath -> (DisplayBlock,"informalequation") diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index c8673ae48..2a834c2da 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -29,7 +29,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Conversion of 'Pandoc' documents to docx. -} module Text.Pandoc.Writers.Docx ( writeDocx ) where -import Data.List ( intercalate, groupBy ) +import Data.Maybe (fromMaybe) +import Data.List ( intercalate, isPrefixOf, isSuffixOf ) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BL8 @@ -42,6 +43,7 @@ import Text.Pandoc.Definition import Text.Pandoc.Generic import Text.Pandoc.ImageSize import Text.Pandoc.Shared hiding (Element) +import Text.Pandoc.Writers.Shared (fixDisplayMath) import Text.Pandoc.Options import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Highlighting ( highlight ) @@ -55,8 +57,8 @@ import Data.Unique (hashUnique, newUnique) import System.Random (randomRIO) import Text.Printf (printf) import qualified Control.Exception as E -import System.FilePath (takeExtension) -import Text.Pandoc.MIME (getMimeType) +import Text.Pandoc.MIME (getMimeType, extensionFromMimeType) +import Control.Applicative ((<|>)) data WriterState = WriterState{ stTextProperties :: [Element] @@ -130,7 +132,8 @@ writeDocx opts doc@(Pandoc meta _) = do let mkOverrideNode (part', contentType') = mknode "Override" [("PartName",part'),("ContentType",contentType')] () let mkImageOverride (_, imgpath, mbMimeType, _, _) = - mkOverrideNode ("/word/" ++ imgpath, maybe "application/octet-stream" id mbMimeType) + mkOverrideNode ("/word/" ++ imgpath, + fromMaybe "application/octet-stream" mbMimeType) let overrides = map mkOverrideNode [("/word/webSettings.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml") @@ -231,10 +234,11 @@ writeDocx opts doc@(Pandoc meta _) = do ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/") ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")] $ mknode "dc:title" [] (stringify $ docTitle meta) - : mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] - (maybe "" id $ normalizeDate $ stringify $ docDate meta) - : mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] () -- put current time here - : map (mknode "dc:creator" [] . stringify) (docAuthors meta) + : mknode "dc:creator" [] (intercalate "; " (map stringify $ docAuthors meta)) + : maybe [] + (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] $ x + , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] $ x + ]) (normalizeDate $ stringify $ docDate meta) let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps let relsPath = "_rels/.rels" @@ -247,7 +251,7 @@ writeDocx opts doc@(Pandoc meta _) = do ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties") ,("Target","docProps/app.xml")] , [("Id","rId3") - ,("Type","http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties") + ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties") ,("Target","docProps/core.xml")] ] let relsEntry = toEntry relsPath epochtime $ renderXml rels @@ -257,14 +261,22 @@ writeDocx opts doc@(Pandoc meta _) = do docPropsAppEntry <- entryFromArchive "docProps/app.xml" themeEntry <- entryFromArchive "word/theme/theme1.xml" fontTableEntry <- entryFromArchive "word/fontTable.xml" + settingsEntry <- entryFromArchive "word/settings.xml" webSettingsEntry <- entryFromArchive "word/webSettings.xml" + let miscRels = [ f | f <- filesInArchive refArchive + , "word/_rels/" `isPrefixOf` f + , ".xml.rels" `isSuffixOf` f + , f /= "word/_rels/document.xml.rels" + , f /= "word/_rels/footnotes.xml.rels" ] + miscRelEntries <- mapM entryFromArchive miscRels -- Create archive let archive = foldr addEntryToArchive emptyArchive $ contentTypesEntry : relsEntry : contentEntry : relEntry : footnoteRelEntry : numEntry : styleEntry : footnotesEntry : docPropsEntry : docPropsAppEntry : themeEntry : - fontTableEntry : webSettingsEntry : imageEntries + fontTableEntry : settingsEntry : webSettingsEntry : + imageEntries ++ miscRelEntries return $ fromArchive archive styleToOpenXml :: Style -> [Element] @@ -319,7 +331,7 @@ mkNum markers marker numid = NumberMarker _ _ start -> map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",show (lvl :: Int))] $ mknode "w:startOverride" [("w:val",show start)] ()) [0..6] - where absnumid = maybe 0 id $ M.lookup marker markers + where absnumid = fromMaybe 0 $ M.lookup marker markers mkAbstractNum :: (ListMarker,Int) -> IO Element mkAbstractNum (marker,numid) = do @@ -635,7 +647,12 @@ formattedString str = do inlineToOpenXML :: WriterOptions -> Inline -> WS [Element] inlineToOpenXML _ (Str str) = formattedString str inlineToOpenXML opts Space = inlineToOpenXML opts (Str " ") -inlineToOpenXML opts (Span _ ils) = inlinesToOpenXML opts ils +inlineToOpenXML opts (Span (_,classes,_) ils) = do + let off x = withTextProp (mknode x [("w:val","0")] ()) + ((if "csl-no-emph" `elem` classes then off "w:i" else id) . + (if "csl-no-strong" `elem` classes then off "w:b" else id) . + (if "csl-no-smallcaps" `elem` classes then off "w:smallCaps" else id)) + $ inlinesToOpenXML opts ils inlineToOpenXML opts (Strong lst) = withTextProp (mknode "w:b" [] ()) $ inlinesToOpenXML opts lst inlineToOpenXML opts (Emph lst) = @@ -667,7 +684,7 @@ inlineToOpenXML opts (Math mathType str) = do else DisplayInline case texMathToOMML displayType str of Right r -> return [r] - Left _ -> inlinesToOpenXML opts (readTeXMath str) + Left _ -> inlinesToOpenXML opts (readTeXMath' mathType str) inlineToOpenXML opts (Cite _ lst) = inlinesToOpenXML opts lst inlineToOpenXML opts (Code attrs str) = withTextProp (rStyle "VerbatimChar") @@ -734,7 +751,7 @@ inlineToOpenXML opts (Image alt (src, tit)) = do liftIO $ warn $ "Could not find image `" ++ src ++ "', skipping..." -- emit alt text inlinesToOpenXML opts alt - Right (img, _) -> do + Right (img, mt) -> do ident <- ("rId"++) `fmap` getUniqueId let size = imageSize img let (xpt,ypt) = maybe (120,120) sizeInPoints size @@ -773,19 +790,21 @@ inlineToOpenXML opts (Image alt (src, tit)) = do , mknode "wp:effectExtent" [("b","0"),("l","0"),("r","0"),("t","0")] () , mknode "wp:docPr" [("descr",tit),("id","1"),("name","Picture")] () , graphic ] - let imgext = case imageType img of - Just Png -> ".png" - Just Jpeg -> ".jpeg" - Just Gif -> ".gif" - Just Pdf -> ".pdf" - Just Eps -> ".eps" - Nothing -> takeExtension src + let imgext = case mt >>= extensionFromMimeType of + Just x -> '.':x + Nothing -> case imageType img of + Just Png -> ".png" + Just Jpeg -> ".jpeg" + Just Gif -> ".gif" + Just Pdf -> ".pdf" + Just Eps -> ".eps" + Nothing -> "" if null imgext then -- without an extension there is no rule for content type inlinesToOpenXML opts alt -- return alt to avoid corrupted docx else do let imgpath = "media/" ++ ident ++ imgext - let mbMimeType = getMimeType imgpath + let mbMimeType = mt <|> getMimeType imgpath -- insert mime type to use in constructing [Content_Types].xml modify $ \st -> st{ stImages = M.insert src (ident, imgpath, mbMimeType, imgElt, img) @@ -797,30 +816,8 @@ br = mknode "w:r" [] [mknode "w:br" [("w:type","textWrapping")] () ] parseXml :: Archive -> String -> IO Element parseXml refArchive relpath = - case (findEntryByPath relpath refArchive >>= parseXMLDoc . UTF8.toStringLazy . fromEntry) of - Just d -> return d + case findEntryByPath relpath refArchive of + Just e -> case parseXMLDoc $ UTF8.toStringLazy $ fromEntry e of + Just d -> return d + Nothing -> fail $ relpath ++ " corrupt in reference docx" Nothing -> fail $ relpath ++ " missing in reference docx" - -isDisplayMath :: Inline -> Bool -isDisplayMath (Math DisplayMath _) = True -isDisplayMath _ = False - -stripLeadingTrailingSpace :: [Inline] -> [Inline] -stripLeadingTrailingSpace = go . reverse . go . reverse - where go (Space:xs) = xs - go xs = xs - -fixDisplayMath :: Block -> Block -fixDisplayMath (Plain lst) - | any isDisplayMath lst && not (all isDisplayMath lst) = - -- chop into several paragraphs so each displaymath is its own - Div ("",["math"],[]) $ map (Plain . stripLeadingTrailingSpace) $ - groupBy (\x y -> (isDisplayMath x && isDisplayMath y) || - not (isDisplayMath x || isDisplayMath y)) lst -fixDisplayMath (Para lst) - | any isDisplayMath lst && not (all isDisplayMath lst) = - -- chop into several paragraphs so each displaymath is its own - Div ("",["math"],[]) $ map (Para . stripLeadingTrailingSpace) $ - groupBy (\x y -> (isDisplayMath x && isDisplayMath y) || - not (isDisplayMath x || isDisplayMath y)) lst -fixDisplayMath x = x diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs index ac0e7610c..a48300939 100644 --- a/src/Text/Pandoc/Writers/EPUB.hs +++ b/src/Text/Pandoc/Writers/EPUB.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE PatternGuards, CPP #-} +{-# LANGUAGE PatternGuards, CPP, ScopedTypeVariables #-} {- Copyright (C) 2010 John MacFarlane <jgm@berkeley.edu> @@ -30,16 +30,18 @@ Conversion of 'Pandoc' documents to EPUB. -} module Text.Pandoc.Writers.EPUB ( writeEPUB ) where import Data.IORef -import Data.Maybe ( fromMaybe, isNothing ) +import qualified Data.Map as M +import Data.Maybe ( fromMaybe ) import Data.List ( isInfixOf, intercalate ) import System.Environment ( getEnv ) import Text.Printf (printf) import System.FilePath ( (</>), takeBaseName, takeExtension, takeFileName ) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.Char8 as B8 -import Text.Pandoc.UTF8 ( fromStringLazy, toString ) +import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.SelfContained ( makeSelfContained ) import Codec.Archive.Zip +import Control.Applicative ((<$>)) import Data.Time.Clock.POSIX import Data.Time import System.Locale @@ -54,7 +56,7 @@ 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 ) +import Data.Char ( toLower, isDigit ) import Network.URI ( unEscapeString ) import Text.Pandoc.MIME (getMimeType) #if MIN_VERSION_base(4,6,0) @@ -70,12 +72,237 @@ import Text.Blaze.Html.Renderer.Utf8 (renderHtml) -- in filenames, chapter0003.xhtml. data Chapter = Chapter (Maybe [Int]) [Block] +data EPUBMetadata = EPUBMetadata{ + epubIdentifier :: [Identifier] + , epubTitle :: [Title] + , epubDate :: String + , epubLanguage :: String + , epubCreator :: [Creator] + , epubContributor :: [Creator] + , epubSubject :: [String] + , epubDescription :: Maybe String + , epubType :: Maybe String + , epubFormat :: Maybe String + , epubPublisher :: Maybe String + , epubSource :: Maybe String + , epubRelation :: Maybe String + , epubCoverage :: Maybe String + , epubRights :: Maybe String + , epubCoverImage :: Maybe String + , epubStylesheet :: Maybe Stylesheet + } deriving Show + +data Stylesheet = StylesheetPath FilePath + | StylesheetContents String + deriving Show + +data Creator = Creator{ + creatorText :: String + , creatorRole :: Maybe String + , creatorFileAs :: Maybe String + } deriving Show + +data Identifier = Identifier{ + identifierText :: String + , identifierScheme :: Maybe String + } deriving Show + +data Title = Title{ + titleText :: String + , titleFileAs :: Maybe String + , titleType :: Maybe String + } deriving Show + +dcName :: String -> QName +dcName n = QName n Nothing (Just "dc") + +dcNode :: Node t => String -> t -> Element +dcNode = node . dcName + +opfName :: String -> QName +opfName n = QName n Nothing (Just "opf") + +plainify :: [Inline] -> String +plainify t = + trimr $ writePlain def{ writerStandalone = False } + $ Pandoc nullMeta [Plain $ walk removeNote t] + +removeNote :: Inline -> Inline +removeNote (Note _) = Str "" +removeNote x = x + +getEPUBMetadata :: WriterOptions -> Meta -> IO EPUBMetadata +getEPUBMetadata opts meta = do + let md = metadataFromMeta opts meta + let elts = onlyElems $ parseXML $ writerEpubMetadata opts + let md' = foldr addMetadataFromXML md elts + let addIdentifier m = + if null (epubIdentifier m) + then do + randomId <- fmap show getRandomUUID + return $ m{ epubIdentifier = [Identifier randomId Nothing] } + else return m + let addLanguage m = + if null (epubLanguage m) + then case lookup "lang" (writerVariables opts) of + Just x -> return m{ epubLanguage = x } + Nothing -> do + localeLang <- catch (liftM + (map (\c -> if c == '_' then '-' else c) . + takeWhile (/='.')) $ getEnv "LANG") + (\e -> let _ = (e :: SomeException) in return "en-US") + return m{ epubLanguage = localeLang } + else return m + let fixDate m = + if null (epubDate m) + then do + currentTime <- getCurrentTime + return $ m{ epubDate = showDateTimeISO8601 currentTime } + else return m + let addAuthor m = + if any (\c -> creatorRole c == Just "aut") $ epubCreator m + then return m + else do + let authors' = map plainify $ docAuthors meta + let toAuthor name = Creator{ creatorText = name + , creatorRole = Just "aut" + , creatorFileAs = Nothing } + return $ m{ epubCreator = map toAuthor authors' ++ epubCreator m } + addIdentifier md' >>= fixDate >>= addAuthor >>= addLanguage + +addMetadataFromXML :: Element -> EPUBMetadata -> EPUBMetadata +addMetadataFromXML e@(Element (QName name _ (Just "dc")) attrs _ _) md + | name == "identifier" = md{ epubIdentifier = + Identifier{ identifierText = strContent e + , identifierScheme = lookupAttr (opfName "scheme") attrs + } : epubIdentifier md } + | name == "title" = md{ epubTitle = + Title{ titleText = strContent e + , titleFileAs = getAttr "file-as" + , titleType = getAttr "type" + } : epubTitle md } + | name == "date" = md{ epubDate = fromMaybe "" $ normalizeDate' + $ strContent e } + | name == "language" = md{ epubLanguage = strContent e } + | name == "creator" = md{ epubCreator = + Creator{ creatorText = strContent e + , creatorRole = getAttr "role" + , creatorFileAs = getAttr "file-as" + } : epubCreator md } + | name == "contributor" = md{ epubContributor = + Creator { creatorText = strContent e + , creatorRole = getAttr "role" + , creatorFileAs = getAttr "file-as" + } : epubContributor md } + | name == "subject" = md{ epubSubject = strContent e : epubSubject md } + | name == "description" = md { epubDescription = Just $ strContent e } + | name == "type" = md { epubType = Just $ strContent e } + | name == "format" = md { epubFormat = Just $ strContent e } + | name == "type" = md { epubType = Just $ strContent e } + | name == "publisher" = md { epubPublisher = Just $ strContent e } + | name == "source" = md { epubSource = Just $ strContent e } + | name == "relation" = md { epubRelation = Just $ strContent e } + | name == "coverage" = md { epubCoverage = Just $ strContent e } + | name == "rights" = md { epubRights = Just $ strContent e } + | otherwise = md + where getAttr n = lookupAttr (opfName n) attrs +addMetadataFromXML _ md = md + +metaValueToString :: MetaValue -> String +metaValueToString (MetaString s) = s +metaValueToString (MetaInlines ils) = plainify ils +metaValueToString (MetaBlocks bs) = plainify $ query (:[]) bs +metaValueToString (MetaBool b) = show b +metaValueToString _ = "" + +getList :: String -> Meta -> (MetaValue -> a) -> [a] +getList s meta handleMetaValue = + case lookupMeta s meta of + Just (MetaList xs) -> map handleMetaValue xs + Just mv -> [handleMetaValue mv] + Nothing -> [] + +getIdentifier :: Meta -> [Identifier] +getIdentifier meta = getList "identifier" meta handleMetaValue + where handleMetaValue (MetaMap m) = + Identifier{ identifierText = maybe "" metaValueToString + $ M.lookup "text" m + , identifierScheme = metaValueToString <$> + M.lookup "scheme" m } + handleMetaValue mv = Identifier (metaValueToString mv) Nothing + +getTitle :: Meta -> [Title] +getTitle meta = getList "title" meta handleMetaValue + where handleMetaValue (MetaMap m) = + Title{ titleText = maybe "" metaValueToString $ M.lookup "text" m + , titleFileAs = metaValueToString <$> M.lookup "file-as" m + , titleType = metaValueToString <$> M.lookup "type" m } + handleMetaValue mv = Title (metaValueToString mv) Nothing Nothing + +getCreator :: String -> Meta -> [Creator] +getCreator s meta = getList s meta handleMetaValue + where handleMetaValue (MetaMap m) = + Creator{ creatorText = maybe "" metaValueToString $ M.lookup "text" m + , creatorFileAs = metaValueToString <$> M.lookup "file-as" m + , creatorRole = metaValueToString <$> M.lookup "role" m } + handleMetaValue mv = Creator (metaValueToString mv) Nothing Nothing + +simpleList :: String -> Meta -> [String] +simpleList s meta = + case lookupMeta s meta of + Just (MetaList xs) -> map metaValueToString xs + Just x -> [metaValueToString x] + Nothing -> [] + +metadataFromMeta :: WriterOptions -> Meta -> EPUBMetadata +metadataFromMeta opts meta = EPUBMetadata{ + epubIdentifier = identifiers + , epubTitle = titles + , epubDate = date + , epubLanguage = language + , epubCreator = creators + , epubContributor = contributors + , epubSubject = subjects + , epubDescription = description + , epubType = epubtype + , epubFormat = format + , epubPublisher = publisher + , epubSource = source + , epubRelation = relation + , epubCoverage = coverage + , epubRights = rights + , epubCoverImage = coverImage + , epubStylesheet = stylesheet + } + where identifiers = getIdentifier meta + titles = getTitle meta + date = fromMaybe "" $ + (metaValueToString <$> lookupMeta "date" meta) >>= normalizeDate' + language = maybe "" metaValueToString $ + lookupMeta "language" meta `mplus` lookupMeta "lang" meta + creators = getCreator "creator" meta + contributors = getCreator "contributor" meta + subjects = simpleList "subject" meta + description = metaValueToString <$> lookupMeta "description" meta + epubtype = metaValueToString <$> lookupMeta "type" meta + format = metaValueToString <$> lookupMeta "format" meta + publisher = metaValueToString <$> lookupMeta "publisher" meta + source = metaValueToString <$> lookupMeta "source" meta + relation = metaValueToString <$> lookupMeta "relation" meta + coverage = metaValueToString <$> lookupMeta "coverage" meta + rights = metaValueToString <$> lookupMeta "rights" meta + coverImage = lookup "epub-cover-image" (writerVariables opts) `mplus` + (metaValueToString <$> lookupMeta "cover-image" meta) + stylesheet = (StylesheetContents <$> writerEpubStylesheet opts) `mplus` + ((StylesheetPath . metaValueToString) <$> + lookupMeta "stylesheet" meta) + -- | Produce an EPUB file from a Pandoc document. writeEPUB :: WriterOptions -- ^ Writer options -> Pandoc -- ^ Document to convert -> IO B.ByteString writeEPUB opts doc@(Pandoc meta _) = do - let version = maybe EPUB2 id (writerEpubVersion opts) + let version = fromMaybe EPUB2 (writerEpubVersion opts) let epub3 = version == EPUB3 epochtime <- floor `fmap` getPOSIXTime let mkEntry path content = toEntry path epochtime content @@ -93,11 +320,11 @@ writeEPUB opts doc@(Pandoc meta _) = do then MathML Nothing else writerHTMLMathMethod opts , writerWrapText = False } - let mbCoverImage = lookup "epub-cover-image" vars + metadata <- getEPUBMetadata opts' meta -- cover page (cpgEntry, cpicEntry) <- - case mbCoverImage of + case epubCoverImage metadata of Nothing -> return ([],[]) Just img -> do let coverImage = "cover-image" ++ takeExtension img @@ -179,32 +406,33 @@ writeEPUB opts doc@(Pandoc meta _) = do chapToEntry num (Chapter mbnum bs) = mkEntry (showChapter num) $ renderHtml $ writeHtml opts'{ writerNumberOffset = - maybe [] id mbnum } + fromMaybe [] mbnum } $ case bs of (Header _ _ xs : _) -> - Pandoc (setMeta "title" (fromList xs) nullMeta) bs + -- remove notes or we get doubled footnotes + Pandoc (setMeta "title" (walk removeNote $ fromList xs) + nullMeta) bs _ -> Pandoc nullMeta bs let chapterEntries = zipWith chapToEntry [1..] chapters -- incredibly inefficient (TODO): - let containsMathML ent = "<math" `isInfixOf` (B8.unpack $ fromEntry ent) + let containsMathML ent = epub3 && + "<math" `isInfixOf` (B8.unpack $ fromEntry ent) + let containsSVG ent = epub3 && + "<svg" `isInfixOf` (B8.unpack $ fromEntry ent) + let props ent = ["mathml" | containsMathML ent] ++ ["svg" | containsSVG ent] -- contents.opf - localeLang <- catch (liftM (map (\c -> if c == '_' then '-' else c) . - takeWhile (/='.')) $ getEnv "LANG") - (\e -> let _ = (e :: SomeException) in return "en-US") - let lang = case lookup "lang" (writerVariables opts') of - Just x -> x - Nothing -> localeLang - uuid <- getRandomUUID let chapterNode ent = unode "item" ! ([("id", takeBaseName $ eRelativePath ent), ("href", eRelativePath ent), ("media-type", "application/xhtml+xml")] - ++ [("properties","mathml") | epub3 && - containsMathML ent]) $ () + ++ case props ent of + [] -> [] + xs -> [("properties", unwords xs)]) + $ () let chapterRefNode ent = unode "itemref" ! [("idref", takeBaseName $ eRelativePath ent)] $ () let pictureNode ent = unode "item" ! @@ -215,23 +443,23 @@ writeEPUB opts doc@(Pandoc meta _) = do let fontNode ent = unode "item" ! [("id", takeBaseName $ eRelativePath ent), ("href", eRelativePath ent), - ("media-type", maybe "" id $ getMimeType $ eRelativePath ent)] $ () - let plainify t = trimr $ - writePlain opts'{ writerStandalone = False } $ - Pandoc meta [Plain t] - let plainTitle = plainify $ docTitle meta - let plainAuthors = map plainify $ docAuthors meta + ("media-type", fromMaybe "" $ getMimeType $ eRelativePath ent)] $ () + let plainTitle = case docTitle meta of + [] -> case epubTitle metadata of + [] -> "UNTITLED" + (x:_) -> titleText x + x -> plainify x + let uuid = case epubIdentifier metadata of + (x:_) -> identifierText x -- use first identifier as UUID + [] -> error "epubIdentifier is null" -- shouldn't happen currentTime <- getCurrentTime - let plainDate = maybe (showDateTimeISO8601 currentTime) id - $ normalizeDate $ stringify $ docDate meta - let contentsData = fromStringLazy $ ppTopElement $ + let contentsData = UTF8.fromStringLazy $ ppTopElement $ unode "package" ! [("version", case version of EPUB2 -> "2.0" EPUB3 -> "3.0") ,("xmlns","http://www.idpf.org/2007/opf") - ,("unique-identifier","BookId")] $ - [ metadataElement version (writerEpubMetadata opts') - uuid lang plainTitle plainAuthors plainDate currentTime mbCoverImage + ,("unique-identifier","epub-id-1")] $ + [ metadataElement version metadata currentTime , unode "manifest" $ [ unode "item" ! [("id","ncx"), ("href","toc.ncx") ,("media-type","application/x-dtbncx+xml")] $ () @@ -243,10 +471,15 @@ writeEPUB opts doc@(Pandoc meta _) = do [("properties","nav") | epub3 ]) $ () ] ++ map chapterNode (cpgEntry ++ (tpEntry : chapterEntries)) ++ - map pictureNode (cpicEntry ++ picEntries) ++ + (case cpicEntry of + [] -> [] + (x:_) -> [add_attrs + [Attr (unqual "properties") "cover-image" | epub3] + (pictureNode x)]) ++ + map pictureNode picEntries ++ map fontNode fontEntries , unode "spine" ! [("toc","ncx")] $ - case mbCoverImage of + case epubCoverImage metadata of Nothing -> [] Just _ -> [ unode "itemref" ! [("idref", "cover"),("linear","no")] $ () ] @@ -260,8 +493,13 @@ writeEPUB opts doc@(Pandoc meta _) = do else "no")] $ ()) : map chapterRefNode chapterEntries) , unode "guide" $ - unode "reference" ! - [("type","toc"),("title",plainTitle),("href","nav.xhtml")] $ () + [ unode "reference" ! + [("type","toc"),("title",plainTitle), + ("href","nav.xhtml")] $ () + ] ++ + [ unode "reference" ! + [("type","cover"),("title","Cover"),("href","cover.xhtml")] $ () | epubCoverImage metadata /= Nothing + ] ] let contentsEntry = mkEntry "content.opf" contentsData @@ -303,19 +541,19 @@ writeEPUB opts doc@(Pandoc meta _) = do [ unode "navLabel" $ unode "text" (plainify $ docTitle meta) , unode "content" ! [("src","title_page.xhtml")] $ () ] - let tocData = fromStringLazy $ ppTopElement $ + let tocData = UTF8.fromStringLazy $ ppTopElement $ unode "ncx" ! [("version","2005-1") ,("xmlns","http://www.daisy.org/z3986/2005/ncx/")] $ [ unode "head" $ [ unode "meta" ! [("name","dtb:uid") - ,("content", show uuid)] $ () + ,("content", uuid)] $ () , unode "meta" ! [("name","dtb:depth") ,("content", "1")] $ () , unode "meta" ! [("name","dtb:totalPageCount") ,("content", "0")] $ () , unode "meta" ! [("name","dtb:maxPageNumber") ,("content", "0")] $ () - ] ++ case mbCoverImage of + ] ++ case epubCoverImage metadata of Nothing -> [] Just _ -> [unode "meta" ! [("name","cover"), ("content","cover-image")] $ ()] @@ -335,7 +573,7 @@ writeEPUB opts doc@(Pandoc meta _) = do (_:_) -> [unode "ol" ! [("class","toc")] $ subs] let navtag = if epub3 then "nav" else "div" - let navData = fromStringLazy $ ppTopElement $ + let navData = UTF8.fromStringLazy $ ppTopElement $ unode "html" ! [("xmlns","http://www.w3.org/1999/xhtml") ,("xmlns:epub","http://www.idpf.org/2007/ops")] $ [ unode "head" $ @@ -349,10 +587,10 @@ writeEPUB opts doc@(Pandoc meta _) = do let navEntry = mkEntry "nav.xhtml" navData -- mimetype - let mimetypeEntry = mkEntry "mimetype" $ fromStringLazy "application/epub+zip" + let mimetypeEntry = mkEntry "mimetype" $ UTF8.fromStringLazy "application/epub+zip" -- container.xml - let containerData = fromStringLazy $ ppTopElement $ + let containerData = UTF8.fromStringLazy $ ppTopElement $ unode "container" ! [("version","1.0") ,("xmlns","urn:oasis:names:tc:opendocument:xmlns:container")] $ unode "rootfiles" $ @@ -361,18 +599,19 @@ writeEPUB opts doc@(Pandoc meta _) = do let containerEntry = mkEntry "META-INF/container.xml" containerData -- com.apple.ibooks.display-options.xml - let apple = fromStringLazy $ ppTopElement $ + let apple = UTF8.fromStringLazy $ ppTopElement $ unode "display_options" $ unode "platform" ! [("name","*")] $ unode "option" ! [("name","specified-fonts")] $ "true" let appleEntry = mkEntry "META-INF/com.apple.ibooks.display-options.xml" apple -- stylesheet - stylesheet <- case writerEpubStylesheet opts of - Just s -> return s - Nothing -> toString `fmap` + stylesheet <- case epubStylesheet metadata of + Just (StylesheetPath fp) -> UTF8.readFile fp + Just (StylesheetContents s) -> return s + Nothing -> UTF8.toString `fmap` readDataFile (writerUserDataDir opts) "epub.css" - let stylesheetEntry = mkEntry "stylesheet.css" $ fromStringLazy stylesheet + let stylesheetEntry = mkEntry "stylesheet.css" $ UTF8.fromStringLazy stylesheet -- construct archive let archive = foldr addEntryToArchive emptyArchive @@ -381,33 +620,97 @@ writeEPUB opts doc@(Pandoc meta _) = do (picEntries ++ cpicEntry ++ cpgEntry ++ chapterEntries ++ fontEntries)) return $ fromArchive archive -metadataElement :: EPUBVersion -> String -> UUID -> String -> String -> [String] - -> String -> UTCTime -> Maybe a -> Element -metadataElement version metadataXML uuid lang title authors date currentTime mbCoverImage = - let userNodes = parseXML metadataXML - elt = unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/") - ,("xmlns:opf","http://www.idpf.org/2007/opf")] $ - filter isMetadataElement $ onlyElems userNodes - dublinElements = ["contributor","coverage","creator","date", - "description","format","identifier","language","publisher", - "relation","rights","source","subject","title","type"] - isMetadataElement e = (qPrefix (elName e) == Just "dc" && - qName (elName e) `elem` dublinElements) || - (qPrefix (elName e) == Nothing && - qName (elName e) `elem` ["link","meta"]) - contains e n = not (null (findElements (QName n Nothing (Just "dc")) e)) - newNodes = [ unode "dc:title" title | not (elt `contains` "title") ] ++ - [ unode "dc:language" lang | not (elt `contains` "language") ] ++ - [ unode "dc:identifier" ! [("id","BookId")] $ show uuid | - not (elt `contains` "identifier") ] ++ - [ unode "dc:creator" ! [("opf:role","aut") | version == EPUB2] - $ a | a <- authors, not (elt `contains` "creator") ] ++ - [ unode "dc:date" date | not (elt `contains` "date") ] ++ - [ unode "meta" ! [("property", "dcterms:modified")] $ - (showDateTimeISO8601 currentTime) | version == EPUB3] ++ - [ unode "meta" ! [("name","cover"), ("content","cover-image")] $ () | - not (isNothing mbCoverImage) ] - in elt{ elContent = elContent elt ++ map Elem newNodes } +metadataElement :: EPUBVersion -> EPUBMetadata -> UTCTime -> Element +metadataElement version md currentTime = + unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/") + ,("xmlns:opf","http://www.idpf.org/2007/opf")] $ mdNodes + where mdNodes = identifierNodes ++ titleNodes ++ dateNodes ++ languageNodes + ++ creatorNodes ++ contributorNodes ++ subjectNodes + ++ descriptionNodes ++ typeNodes ++ formatNodes + ++ publisherNodes ++ sourceNodes ++ relationNodes + ++ coverageNodes ++ rightsNodes ++ coverImageNodes + ++ modifiedNodes + withIds base f = concat . zipWith f (map (\x -> base ++ ('-' : show x)) + ([1..] :: [Int])) + identifierNodes = withIds "epub-id" toIdentifierNode $ + epubIdentifier md + titleNodes = withIds "epub-title" toTitleNode $ epubTitle md + dateNodes = dcTag' "date" $ epubDate md + languageNodes = [dcTag "language" $ epubLanguage md] + creatorNodes = withIds "epub-creator" (toCreatorNode "creator") $ + epubCreator md + contributorNodes = withIds "epub-contributor" + (toCreatorNode "contributor") $ epubContributor md + subjectNodes = map (dcTag "subject") $ epubSubject md + descriptionNodes = maybe [] (dcTag' "description") $ epubDescription md + typeNodes = maybe [] (dcTag' "type") $ epubType md + formatNodes = maybe [] (dcTag' "format") $ epubFormat md + publisherNodes = maybe [] (dcTag' "publisher") $ epubPublisher md + sourceNodes = maybe [] (dcTag' "source") $ epubSource md + relationNodes = maybe [] (dcTag' "relation") $ epubRelation md + coverageNodes = maybe [] (dcTag' "coverage") $ epubCoverage md + rightsNodes = maybe [] (dcTag' "rights") $ epubRights md + coverImageNodes = maybe [] + (const $ [unode "meta" ! [("name","cover"), + ("content","cover-image")] $ ()]) + $ epubCoverImage md + modifiedNodes = [ unode "meta" ! [("property", "dcterms:modified")] $ + (showDateTimeISO8601 currentTime) | version == EPUB3 ] + dcTag n s = unode ("dc:" ++ n) s + dcTag' n s = [dcTag n s] + toIdentifierNode id' (Identifier txt scheme) + | version == EPUB2 = [dcNode "identifier" ! + ([("id",id')] ++ maybe [] (\x -> [("opf:scheme", x)]) scheme) $ + txt] + | otherwise = [dcNode "identifier" ! [("id",id')] $ txt] ++ + maybe [] (\x -> [unode "meta" ! + [("refines",'#':id'),("property","identifier-type"), + ("scheme","onix:codelist5")] $ x]) + (schemeToOnix `fmap` scheme) + toCreatorNode s id' creator + | version == EPUB2 = [dcNode s ! + ([("id",id')] ++ + maybe [] (\x -> [("opf:file-as",x)]) (creatorFileAs creator) ++ + maybe [] (\x -> [("opf:role",x)]) + (creatorRole creator >>= toRelator)) $ creatorText creator] + | otherwise = [dcNode s ! [("id",id')] $ creatorText creator] ++ + maybe [] (\x -> [unode "meta" ! + [("refines",'#':id'),("property","file-as")] $ x]) + (creatorFileAs creator) ++ + maybe [] (\x -> [unode "meta" ! + [("refines",'#':id'),("property","role"), + ("scheme","marc:relators")] $ x]) + (creatorRole creator >>= toRelator) + toTitleNode id' title + | version == EPUB2 = [dcNode "title" ! + ([("id",id')] ++ + maybe [] (\x -> [("opf:file-as",x)]) (titleFileAs title) ++ + maybe [] (\x -> [("opf:title-type",x)]) (titleType title)) $ + titleText title] + | otherwise = [dcNode "title" ! [("id",id')] $ titleText title] + ++ + maybe [] (\x -> [unode "meta" ! + [("refines",'#':id'),("property","file-as")] $ x]) + (titleFileAs title) ++ + maybe [] (\x -> [unode "meta" ! + [("refines",'#':id'),("property","title-type")] $ x]) + (titleType title) + schemeToOnix "ISBN-10" = "02" + schemeToOnix "GTIN-13" = "03" + schemeToOnix "UPC" = "04" + schemeToOnix "ISMN-10" = "05" + schemeToOnix "DOI" = "06" + schemeToOnix "LCCN" = "13" + schemeToOnix "GTIN-14" = "14" + schemeToOnix "ISBN-13" = "15" + schemeToOnix "Legal deposit number" = "17" + schemeToOnix "URN" = "22" + schemeToOnix "OCLC" = "23" + schemeToOnix "ISMN-13" = "25" + schemeToOnix "ISBN-A" = "26" + schemeToOnix "JP" = "27" + schemeToOnix "OLCC" = "28" + schemeToOnix _ = "01" showDateTimeISO8601 :: UTCTime -> String showDateTimeISO8601 = formatTime defaultTimeLocale "%FT%TZ" @@ -457,15 +760,9 @@ ppTopElement = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++) . unEntity . unEntity (x:xs) = x : unEntity xs 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 - +imageTypeOf x = case getMimeType x of + Just y@('i':'m':'a':'g':'e':_) -> Just y + _ -> Nothing data IdentState = IdentState{ chapterNumber :: Int, @@ -519,3 +816,287 @@ replaceRefs refTable = walk replaceOneRef Just url -> Link lab (url,tit) Nothing -> x replaceOneRef x = x + +-- Variant of normalizeDate that allows partial dates: YYYY, YYYY-MM +normalizeDate' :: String -> Maybe String +normalizeDate' xs = + let xs' = trim xs in + case xs' of + [y1,y2,y3,y4] | all isDigit [y1,y2,y3,y4] -> Just xs' -- YYYY + [y1,y2,y3,y4,'-',m1,m2] | all isDigit [y1,y2,y3,y4,m1,m2] -- YYYY-MM + -> Just xs' + _ -> normalizeDate xs' + +toRelator :: String -> Maybe String +toRelator x + | x `elem` relators = Just x + | otherwise = lookup (map toLower x) relatorMap + +relators :: [String] +relators = map snd relatorMap + +relatorMap :: [(String, String)] +relatorMap = + [("abridger", "abr") + ,("actor", "act") + ,("adapter", "adp") + ,("addressee", "rcp") + ,("analyst", "anl") + ,("animator", "anm") + ,("annotator", "ann") + ,("appellant", "apl") + ,("appellee", "ape") + ,("applicant", "app") + ,("architect", "arc") + ,("arranger", "arr") + ,("art copyist", "acp") + ,("art director", "adi") + ,("artist", "art") + ,("artistic director", "ard") + ,("assignee", "asg") + ,("associated name", "asn") + ,("attributed name", "att") + ,("auctioneer", "auc") + ,("author", "aut") + ,("author in quotations or text abstracts", "aqt") + ,("author of afterword, colophon, etc.", "aft") + ,("author of dialog", "aud") + ,("author of introduction, etc.", "aui") + ,("autographer", "ato") + ,("bibliographic antecedent", "ant") + ,("binder", "bnd") + ,("binding designer", "bdd") + ,("blurb writer", "blw") + ,("book designer", "bkd") + ,("book producer", "bkp") + ,("bookjacket designer", "bjd") + ,("bookplate designer", "bpd") + ,("bookseller", "bsl") + ,("braille embosser", "brl") + ,("broadcaster", "brd") + ,("calligrapher", "cll") + ,("cartographer", "ctg") + ,("caster", "cas") + ,("censor", "cns") + ,("choreographer", "chr") + ,("cinematographer", "cng") + ,("client", "cli") + ,("collection registrar", "cor") + ,("collector", "col") + ,("collotyper", "clt") + ,("colorist", "clr") + ,("commentator", "cmm") + ,("commentator for written text", "cwt") + ,("compiler", "com") + ,("complainant", "cpl") + ,("complainant-appellant", "cpt") + ,("complainant-appellee", "cpe") + ,("composer", "cmp") + ,("compositor", "cmt") + ,("conceptor", "ccp") + ,("conductor", "cnd") + ,("conservator", "con") + ,("consultant", "csl") + ,("consultant to a project", "csp") + ,("contestant", "cos") + ,("contestant-appellant", "cot") + ,("contestant-appellee", "coe") + ,("contestee", "cts") + ,("contestee-appellant", "ctt") + ,("contestee-appellee", "cte") + ,("contractor", "ctr") + ,("contributor", "ctb") + ,("copyright claimant", "cpc") + ,("copyright holder", "cph") + ,("corrector", "crr") + ,("correspondent", "crp") + ,("costume designer", "cst") + ,("court governed", "cou") + ,("court reporter", "crt") + ,("cover designer", "cov") + ,("creator", "cre") + ,("curator", "cur") + ,("dancer", "dnc") + ,("data contributor", "dtc") + ,("data manager", "dtm") + ,("dedicatee", "dte") + ,("dedicator", "dto") + ,("defendant", "dfd") + ,("defendant-appellant", "dft") + ,("defendant-appellee", "dfe") + ,("degree granting institution", "dgg") + ,("delineator", "dln") + ,("depicted", "dpc") + ,("depositor", "dpt") + ,("designer", "dsr") + ,("director", "drt") + ,("dissertant", "dis") + ,("distribution place", "dbp") + ,("distributor", "dst") + ,("donor", "dnr") + ,("draftsman", "drm") + ,("dubious author", "dub") + ,("editor", "edt") + ,("editor of compilation", "edc") + ,("editor of moving image work", "edm") + ,("electrician", "elg") + ,("electrotyper", "elt") + ,("enacting jurisdiction", "enj") + ,("engineer", "eng") + ,("engraver", "egr") + ,("etcher", "etr") + ,("event place", "evp") + ,("expert", "exp") + ,("facsimilist", "fac") + ,("field director", "fld") + ,("film director", "fmd") + ,("film distributor", "fds") + ,("film editor", "flm") + ,("film producer", "fmp") + ,("filmmaker", "fmk") + ,("first party", "fpy") + ,("forger", "frg") + ,("former owner", "fmo") + ,("funder", "fnd") + ,("geographic information specialist", "gis") + ,("honoree", "hnr") + ,("host", "hst") + ,("host institution", "his") + ,("illuminator", "ilu") + ,("illustrator", "ill") + ,("inscriber", "ins") + ,("instrumentalist", "itr") + ,("interviewee", "ive") + ,("interviewer", "ivr") + ,("inventor", "inv") + ,("issuing body", "isb") + ,("judge", "jud") + ,("jurisdiction governed", "jug") + ,("laboratory", "lbr") + ,("laboratory director", "ldr") + ,("landscape architect", "lsa") + ,("lead", "led") + ,("lender", "len") + ,("libelant", "lil") + ,("libelant-appellant", "lit") + ,("libelant-appellee", "lie") + ,("libelee", "lel") + ,("libelee-appellant", "let") + ,("libelee-appellee", "lee") + ,("librettist", "lbt") + ,("licensee", "lse") + ,("licensor", "lso") + ,("lighting designer", "lgd") + ,("lithographer", "ltg") + ,("lyricist", "lyr") + ,("manufacture place", "mfp") + ,("manufacturer", "mfr") + ,("marbler", "mrb") + ,("markup editor", "mrk") + ,("metadata contact", "mdc") + ,("metal-engraver", "mte") + ,("moderator", "mod") + ,("monitor", "mon") + ,("music copyist", "mcp") + ,("musical director", "msd") + ,("musician", "mus") + ,("narrator", "nrt") + ,("onscreen presenter", "osp") + ,("opponent", "opn") + ,("organizer of meeting", "orm") + ,("originator", "org") + ,("other", "oth") + ,("owner", "own") + ,("panelist", "pan") + ,("papermaker", "ppm") + ,("patent applicant", "pta") + ,("patent holder", "pth") + ,("patron", "pat") + ,("performer", "prf") + ,("permitting agency", "pma") + ,("photographer", "pht") + ,("plaintiff", "ptf") + ,("plaintiff-appellant", "ptt") + ,("plaintiff-appellee", "pte") + ,("platemaker", "plt") + ,("praeses", "pra") + ,("presenter", "pre") + ,("printer", "prt") + ,("printer of plates", "pop") + ,("printmaker", "prm") + ,("process contact", "prc") + ,("producer", "pro") + ,("production company", "prn") + ,("production designer", "prs") + ,("production manager", "pmn") + ,("production personnel", "prd") + ,("production place", "prp") + ,("programmer", "prg") + ,("project director", "pdr") + ,("proofreader", "pfr") + ,("provider", "prv") + ,("publication place", "pup") + ,("publisher", "pbl") + ,("publishing director", "pbd") + ,("puppeteer", "ppt") + ,("radio director", "rdd") + ,("radio producer", "rpc") + ,("recording engineer", "rce") + ,("recordist", "rcd") + ,("redaktor", "red") + ,("renderer", "ren") + ,("reporter", "rpt") + ,("repository", "rps") + ,("research team head", "rth") + ,("research team member", "rtm") + ,("researcher", "res") + ,("respondent", "rsp") + ,("respondent-appellant", "rst") + ,("respondent-appellee", "rse") + ,("responsible party", "rpy") + ,("restager", "rsg") + ,("restorationist", "rsr") + ,("reviewer", "rev") + ,("rubricator", "rbr") + ,("scenarist", "sce") + ,("scientific advisor", "sad") + ,("screenwriter", "aus") + ,("scribe", "scr") + ,("sculptor", "scl") + ,("second party", "spy") + ,("secretary", "sec") + ,("seller", "sll") + ,("set designer", "std") + ,("setting", "stg") + ,("signer", "sgn") + ,("singer", "sng") + ,("sound designer", "sds") + ,("speaker", "spk") + ,("sponsor", "spn") + ,("stage director", "sgd") + ,("stage manager", "stm") + ,("standards body", "stn") + ,("stereotyper", "str") + ,("storyteller", "stl") + ,("supporting host", "sht") + ,("surveyor", "srv") + ,("teacher", "tch") + ,("technical director", "tcd") + ,("television director", "tld") + ,("television producer", "tlp") + ,("thesis advisor", "ths") + ,("transcriber", "trc") + ,("translator", "trl") + ,("type designer", "tyd") + ,("typographer", "tyg") + ,("university place", "uvp") + ,("videographer", "vdg") + ,("witness", "wit") + ,("wood engraver", "wde") + ,("woodcutter", "wdc") + ,("writer of accompanying material", "wam") + ,("writer of added commentary", "wac") + ,("writer of added lyrics", "wal") + ,("writer of added text", "wat") + ] + diff --git a/src/Text/Pandoc/Writers/FB2.hs b/src/Text/Pandoc/Writers/FB2.hs index adbe948be..803617f95 100644 --- a/src/Text/Pandoc/Writers/FB2.hs +++ b/src/Text/Pandoc/Writers/FB2.hs @@ -44,7 +44,7 @@ import qualified Text.XML.Light.Cursor as XC import Text.Pandoc.Definition import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def) -import Text.Pandoc.Shared (orderedListMarkers) +import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock) import Text.Pandoc.Walk -- | Data to be written at the end of the document: @@ -157,9 +157,7 @@ renderSection level (ttl, body) = do else cMapM blockToXml body return $ el "section" (title ++ content) where - hasSubsections = any isHeader - isHeader (Header _ _ _) = True - isHeader _ = False + hasSubsections = any isHeaderBlock -- | Only <p> and <empty-line> are allowed within <title> in FB2. formatTitle :: [Inline] -> [Content] diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs index 63b466af3..805bb57f1 100644 --- a/src/Text/Pandoc/Writers/HTML.hs +++ b/src/Text/Pandoc/Writers/HTML.hs @@ -39,13 +39,13 @@ import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Slides import Text.Pandoc.Highlighting ( highlight, styleToCss, formatHtmlInline, formatHtmlBlock ) -import Text.Pandoc.XML (fromEntities) +import Text.Pandoc.XML (fromEntities, escapeStringForXML) import Network.HTTP ( urlEncode ) import Numeric ( showHex ) import Data.Char ( ord, toLower ) import Data.List ( isPrefixOf, intersperse ) import Data.String ( fromString ) -import Data.Maybe ( catMaybes ) +import Data.Maybe ( catMaybes, fromMaybe ) import Control.Monad.State import Text.Blaze.Html hiding(contents) import Text.Blaze.Internal(preEscapedString) @@ -115,9 +115,10 @@ pandocToHtml opts (Pandoc meta blocks) = do (fmap renderHtml . blockListToHtml opts) (fmap renderHtml . inlineListToHtml opts) meta - let authsMeta = map stringify $ docAuthors meta - let dateMeta = stringify $ docDate meta - let slideLevel = maybe (getSlideLevel blocks) id $ writerSlideLevel opts + let stringifyHTML = escapeStringForXML . stringify + let authsMeta = map stringifyHTML $ docAuthors meta + let dateMeta = stringifyHTML $ docDate meta + let slideLevel = fromMaybe (getSlideLevel blocks) $ writerSlideLevel opts let sects = hierarchicalize $ if writerSlideVariant opts == NoSlides then blocks @@ -143,8 +144,11 @@ pandocToHtml opts (Pandoc meta blocks) = do MathJax url -> H.script ! A.src (toValue url) ! A.type_ "text/javascript" - $ preEscapedString - "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);" + $ case writerSlideVariant opts of + SlideousSlides -> + preEscapedString + "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);" + _ -> mempty JsMath (Just url) -> H.script ! A.src (toValue url) ! A.type_ "text/javascript" @@ -168,7 +172,7 @@ pandocToHtml opts (Pandoc meta blocks) = do maybe id (defField "toc" . renderHtml) toc $ defField "author-meta" authsMeta $ maybe id (defField "date-meta") (normalizeDate dateMeta) $ - defField "pagetitle" (stringify $ docTitle meta) $ + defField "pagetitle" (stringifyHTML $ docTitle meta) $ defField "idprefix" (writerIdentifierPrefix opts) $ -- these should maybe be set in pandoc.hs defField "slidy-url" @@ -268,11 +272,23 @@ elementToHtml slideLevel opts (Sec level num (id',classes,keyvals) title' elemen else blockToHtml opts (Header level' (id',classes,keyvals) title') let isSec (Sec _ _ _ _ _) = True isSec (Blk _) = False + let isPause (Blk x) = x == Para [Str ".",Space,Str ".",Space,Str "."] + isPause _ = False + let fragmentClass = case writerSlideVariant opts of + RevealJsSlides -> "fragment" + _ -> "incremental" + let inDiv xs = Blk (RawBlock (Format "html") ("<div class=\"" + ++ fragmentClass ++ "\">")) : + (xs ++ [Blk (RawBlock (Format "html") "</div>")]) innerContents <- mapM (elementToHtml slideLevel opts) $ if titleSlide -- title slides have no content of their own then filter isSec elements - else elements + else if slide + then case splitBy isPause elements of + [] -> [] + (x:xs) -> x ++ concatMap inDiv xs + else elements let inNl x = mconcat $ nl opts : intersperse (nl opts) x ++ [nl opts] let classes' = ["titleslide" | titleSlide] ++ ["slide" | slide] ++ ["section" | (slide || writerSectionDivs opts) && @@ -401,16 +417,19 @@ blockToHtml opts (Para [Image txt (s,'f':'i':'g':':':tit)]) = do [nl opts, img, capt, nl opts] else H.div ! A.class_ "figure" $ mconcat [nl opts, img, capt, nl opts] --- . . . indicates a pause in a slideshow -blockToHtml opts (Para [Str ".",Space,Str ".",Space,Str "."]) - | writerSlideVariant opts == RevealJsSlides = - blockToHtml opts (RawBlock "html" "<div class=\"fragment\" />") blockToHtml opts (Para lst) = do contents <- inlineListToHtml opts lst return $ H.p contents -blockToHtml opts (Div attr bs) = do +blockToHtml opts (Div attr@(_,classes,_) bs) = do contents <- blockListToHtml opts bs - return $ addAttrs opts attr $ H.div $ nl opts >> contents >> nl opts + let contents' = nl opts >> contents >> nl opts + return $ + if "notes" `elem` classes + then case writerSlideVariant opts of + RevealJsSlides -> addAttrs opts attr $ H5.aside $ contents' + NoSlides -> addAttrs opts attr $ H.div $ contents' + _ -> mempty + else addAttrs opts attr $ H.div $ contents' blockToHtml _ (RawBlock f str) | f == Format "html" = return $ preEscapedString str | otherwise = return mempty @@ -456,28 +475,21 @@ blockToHtml opts (BlockQuote blocks) = else do contents <- blockListToHtml opts blocks return $ H.blockquote $ nl opts >> contents >> nl opts -blockToHtml opts (Header level (ident,_,_) lst) = do +blockToHtml opts (Header level (_,_,_) lst) = do contents <- inlineListToHtml opts lst secnum <- liftM stSecNum get let contents' = if writerNumberSections opts && not (null secnum) then (H.span ! A.class_ "header-section-number" $ toHtml $ showSecNum secnum) >> strToHtml " " >> contents else contents - let revealSlash = ['/' | writerSlideVariant opts == RevealJsSlides] - let contents'' = if writerTableOfContents opts && not (null ident) - then H.a ! A.href (toValue $ - '#' : revealSlash ++ - writerIdentifierPrefix opts ++ - ident) $ contents' - else contents' return $ case level of - 1 -> H.h1 contents'' - 2 -> H.h2 contents'' - 3 -> H.h3 contents'' - 4 -> H.h4 contents'' - 5 -> H.h5 contents'' - 6 -> H.h6 contents'' - _ -> H.p contents'' + 1 -> H.h1 contents' + 2 -> H.h2 contents' + 3 -> H.h3 contents' + 4 -> H.h4 contents' + 5 -> H.h5 contents' + 6 -> H.h6 contents' + _ -> H.p contents' blockToHtml opts (BulletList lst) = do contents <- mapM (blockListToHtml opts) lst return $ unordList opts contents @@ -505,7 +517,7 @@ blockToHtml opts (DefinitionList lst) = do contents <- mapM (\(term, defs) -> do term' <- if null term then return mempty - else liftM (H.dt) $ inlineListToHtml opts term + else liftM H.dt $ inlineListToHtml opts term defs' <- mapM ((liftM (\x -> H.dd $ (x >> nl opts))) . blockListToHtml opts) defs return $ mconcat $ nl opts : term' : nl opts : @@ -580,8 +592,7 @@ toListItem opts item = nl opts >> H.li item blockListToHtml :: WriterOptions -> [Block] -> State WriterState Html blockListToHtml opts lst = - mapM (blockToHtml opts) lst >>= - return . mconcat . intersperse (nl opts) + fmap (mconcat . intersperse (nl opts)) $ mapM (blockToHtml opts) lst -- | Convert list of Pandoc inline elements to HTML. inlineListToHtml :: WriterOptions -> [Inline] -> State WriterState Html @@ -595,8 +606,22 @@ inlineToHtml opts inline = (Str str) -> return $ strToHtml str (Space) -> return $ strToHtml " " (LineBreak) -> return $ if writerHtml5 opts then H5.br else H.br - (Span attr ils) -> inlineListToHtml opts ils >>= - return . addAttrs opts attr . H.span + (Span (id',classes,kvs) ils) + -> inlineListToHtml opts ils >>= + return . addAttrs opts attr' . H.span + where attr' = (id',classes',kvs') + classes' = filter (`notElem` ["csl-no-emph", + "csl-no-strong", + "csl-no-smallcaps"]) classes + kvs' = if null styles + then kvs + else (("style", concat styles) : kvs) + styles = ["font-style:normal;" + | "csl-no-emph" `elem` classes] + ++ ["font-weight:normal;" + | "csl-no-strong" `elem` classes] + ++ ["font-variant:normal;" + | "csl-no-smallcaps" `elem` classes] (Emph lst) -> inlineListToHtml opts lst >>= return . H.em (Strong lst) -> inlineListToHtml opts lst >>= return . H.strong (Code attr str) -> case hlCode of @@ -667,14 +692,14 @@ inlineToHtml opts inline = Right r -> return $ preEscapedString $ ppcElement conf r Left _ -> inlineListToHtml opts - (readTeXMath str) >>= return . + (readTeXMath' t str) >>= return . (H.span ! A.class_ "math") MathJax _ -> return $ H.span ! A.class_ "math" $ toHtml $ case t of InlineMath -> "\\(" ++ str ++ "\\)" DisplayMath -> "\\[" ++ str ++ "\\]" PlainMath -> do - x <- inlineListToHtml opts (readTeXMath str) + x <- inlineListToHtml opts (readTeXMath' t str) let m = H.span ! A.class_ "math" $ x let brtag = if writerHtml5 opts then H5.br else H.br return $ case t of @@ -724,7 +749,9 @@ inlineToHtml opts inline = else [A.title $ toValue tit]) return $ foldl (!) H5.embed attributes -- note: null title included, as in Markdown.pl - (Note contents) -> do + (Note contents) + | writerIgnoreNotes opts -> return mempty + | otherwise -> do st <- get let notes = stNotes st let number = (length notes) + 1 @@ -739,11 +766,11 @@ inlineToHtml opts inline = writerIdentifierPrefix opts ++ "fn" ++ ref) ! A.class_ "footnoteRef" ! prefixedId opts ("fnref" ++ ref) + $ H.sup $ toHtml ref - let link' = case writerEpubVersion opts of - Just EPUB3 -> link ! customAttribute "epub:type" "noteref" - _ -> link - return $ H.sup $ link' + return $ case writerEpubVersion opts of + Just EPUB3 -> link ! customAttribute "epub:type" "noteref" + _ -> link (Cite cits il)-> do contents <- inlineListToHtml opts il let citationIds = unwords $ map citationId cits let result = H.span ! A.class_ "citation" $ contents diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index 37ca60ce3..a76d6d82b 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -36,10 +36,11 @@ import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Templates import Text.Printf ( printf ) -import Network.URI ( isAbsoluteURI, unEscapeString ) +import Network.URI ( isURI, unEscapeString ) import Data.List ( (\\), isSuffixOf, isInfixOf, isPrefixOf, intercalate, intersperse ) -import Data.Char ( toLower, isPunctuation ) +import Data.Char ( toLower, isPunctuation, isAscii, isLetter, isDigit, ord ) +import Data.Maybe ( fromMaybe ) import Control.Applicative ((<|>)) import Control.Monad.State import Text.Pandoc.Pretty @@ -50,6 +51,8 @@ import Text.Pandoc.Highlighting (highlight, styleToLaTeX, data WriterState = WriterState { stInNote :: Bool -- true if we're in a note + , stInMinipage :: Bool -- true if in minipage + , stNotes :: [Doc] -- notes in a minipage , stOLLevel :: Int -- level of ordered list nesting , stOptions :: WriterOptions -- writer options, so they don't have to be parameter , stVerbInNote :: Bool -- true if document has verbatim text in note @@ -70,7 +73,7 @@ data WriterState = writeLaTeX :: WriterOptions -> Pandoc -> String writeLaTeX options document = evalState (pandocToLaTeX options document) $ - WriterState { stInNote = False, + WriterState { stInNote = False, stInMinipage = False, stNotes = [], stOLLevel = 1, stOptions = options, stVerbInNote = False, stTable = False, stStrikeout = False, @@ -82,10 +85,17 @@ writeLaTeX options document = pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String pandocToLaTeX options (Pandoc meta blocks) = do + -- Strip off final 'references' header if --natbib or --biblatex + let method = writerCiteMethod options + let blocks' = if method == Biblatex || method == Natbib + then case reverse blocks of + (Div (_,["references"],_) _):xs -> reverse xs + _ -> blocks + else blocks -- see if there are internal links let isInternalLink (Link _ ('#':xs,_)) = [xs] isInternalLink _ = [] - modify $ \s -> s{ stInternalLinks = query isInternalLink blocks } + modify $ \s -> s{ stInternalLinks = query isInternalLink blocks' } let template = writerTemplate options -- set stBook depending on documentclass let bookClasses = ["memoir","book","report","scrreprt","scrbook"] @@ -107,26 +117,28 @@ pandocToLaTeX options (Pandoc meta blocks) = do (fmap (render colwidth) . blockListToLaTeX) (fmap (render colwidth) . inlineListToLaTeX) meta - let (blocks', lastHeader) = if writerCiteMethod options == Citeproc then - (blocks, []) - else case last blocks of - Header 1 _ il -> (init blocks, il) - _ -> (blocks, []) - blocks'' <- if writerBeamer options - then toSlides blocks' - else return blocks' - body <- mapM (elementToLaTeX options) $ hierarchicalize blocks'' + let (blocks'', lastHeader) = if writerCiteMethod options == Citeproc then + (blocks', []) + else case last blocks' of + Header 1 _ il -> (init blocks', il) + _ -> (blocks', []) + blocks''' <- if writerBeamer options + then toSlides blocks'' + else return blocks'' + body <- mapM (elementToLaTeX options) $ hierarchicalize blocks''' (biblioTitle :: String) <- liftM (render colwidth) $ inlineListToLaTeX lastHeader let main = render colwidth $ vsep body st <- get + titleMeta <- stringToLaTeX TextString $ stringify $ docTitle meta + authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta let context = defField "toc" (writerTableOfContents options) $ defField "toc-depth" (show (writerTOCDepth options - if writerChapters options then 1 else 0)) $ defField "body" main $ - defField "title-meta" (stringify $ docTitle meta) $ - defField "author-meta" (intercalate "; " $ map stringify $ docAuthors meta) $ + defField "title-meta" titleMeta $ + defField "author-meta" (intercalate "; " authorsMeta) $ defField "documentclass" (if writerBeamer options then ("beamer" :: String) else if writerChapters options @@ -179,7 +191,7 @@ stringToLaTeX _ [] = return "" stringToLaTeX ctx (x:xs) = do opts <- gets stOptions rest <- stringToLaTeX ctx xs - let ligatures = writerTeXLigatures opts && not (ctx == CodeString) + let ligatures = writerTeXLigatures opts && (ctx /= CodeString) let isUrl = ctx == URLString when (x == '€') $ modify $ \st -> st{ stUsesEuro = True } @@ -215,6 +227,13 @@ stringToLaTeX ctx (x:xs) = do '\x2013' | ligatures -> "--" ++ rest _ -> x : rest +toLabel :: String -> String +toLabel [] = "" +toLabel (x:xs) + | (isLetter x || isDigit x) && isAscii x = x:toLabel xs + | elem x "-+=:;." = x:toLabel xs + | otherwise = "ux" ++ printf "%x" (ord x) ++ toLabel xs + -- | Puts contents into LaTeX command. inCmd :: String -> Doc -> Doc inCmd cmd contents = char '\\' <> text cmd <> braces contents @@ -222,7 +241,7 @@ inCmd cmd contents = char '\\' <> text cmd <> braces contents toSlides :: [Block] -> State WriterState [Block] toSlides bs = do opts <- gets stOptions - let slideLevel = maybe (getSlideLevel bs) id $ writerSlideLevel opts + let slideLevel = fromMaybe (getSlideLevel bs) $ writerSlideLevel opts let bs' = prepSlides slideLevel bs concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs') @@ -278,7 +297,12 @@ isLineBreakOrSpace _ = False blockToLaTeX :: Block -- ^ Block to convert -> State WriterState Doc blockToLaTeX Null = return empty -blockToLaTeX (Div _ bs) = blockListToLaTeX bs +blockToLaTeX (Div (_,classes,_) bs) = do + beamer <- writerBeamer `fmap` gets stOptions + contents <- blockListToLaTeX bs + if beamer && "notes" `elem` classes -- speaker notes + then return $ "\\note" <> braces contents + else return contents blockToLaTeX (Plain lst) = inlineListToLaTeX $ dropWhile isLineBreakOrSpace lst -- title beginning with fig: indicates that the image is a figure @@ -317,17 +341,23 @@ blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do | writerListings opts -> listingsCodeBlock | writerHighlight opts && not (null classes) -> highlightedCodeBlock | otherwise -> rawCodeBlock - where lhsCodeBlock = do + where ref = text $ toLabel identifier + linkAnchor = if null identifier + then empty + else "\\hyperdef{}" <> braces ref <> + braces ("\\label" <> braces ref) + lhsCodeBlock = do modify $ \s -> s{ stLHS = True } - return $ flush ("\\begin{code}" $$ text str $$ "\\end{code}") $$ cr + return $ flush (linkAnchor $$ "\\begin{code}" $$ text str $$ + "\\end{code}") $$ cr rawCodeBlock = do st <- get env <- if stInNote st then modify (\s -> s{ stVerbInNote = True }) >> return "Verbatim" else return "verbatim" - return $ flush (text ("\\begin{" ++ env ++ "}") $$ text str $$ - text ("\\end{" ++ env ++ "}")) <> cr + return $ flush (linkAnchor $$ text ("\\begin{" ++ env ++ "}") $$ + text str $$ text ("\\end{" ++ env ++ "}")) <> cr listingsCodeBlock = do st <- get let params = if writerListings (stOptions st) @@ -343,7 +373,7 @@ blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do (key,attr) <- keyvalAttr ] ++ (if identifier == "" then [] - else [ "label=" ++ identifier ]) + else [ "label=" ++ toLabel identifier ]) else [] printParams @@ -355,7 +385,7 @@ blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do case highlight formatLaTeXBlock ("",classes,keyvalAttr) str of Nothing -> rawCodeBlock Just h -> modify (\st -> st{ stHighlighting = True }) >> - return (flush $ text h) + return (flush $ linkAnchor $$ text h) blockToLaTeX (RawBlock f x) | f == Format "latex" || f == Format "tex" = return $ text x @@ -414,7 +444,7 @@ blockToLaTeX (DefinitionList lst) = do incremental <- gets stIncremental let inc = if incremental then "[<+->]" else "" items <- mapM defListItemToLaTeX lst - let spacing = if and $ map isTightList (map snd lst) + let spacing = if all isTightList (map snd lst) then text "\\itemsep1pt\\parskip0pt\\parsep0pt" else empty return $ text ("\\begin{description}" ++ inc) $$ spacing $$ vcat items $$ @@ -426,12 +456,12 @@ blockToLaTeX (Header level (id',classes,_) lst) = blockToLaTeX (Table caption aligns widths heads rows) = do headers <- if all null heads then return empty - else ($$ "\\hline\\noalign{\\medskip}") `fmap` + else ($$ "\\midrule\\endhead") `fmap` (tableRowToLaTeX True aligns widths) heads captionText <- inlineListToLaTeX caption let capt = if isEmpty captionText then empty - else text "\\noalign{\\medskip}" + else text "\\addlinespace" $$ text "\\caption" <> braces captionText rows' <- mapM (tableRowToLaTeX False aligns widths) rows let colDescriptors = text $ concat $ map toColDescriptor aligns @@ -439,10 +469,10 @@ blockToLaTeX (Table caption aligns widths heads rows) = do return $ "\\begin{longtable}[c]" <> braces ("@{}" <> colDescriptors <> "@{}") -- the @{} removes extra space at beginning and end - $$ "\\hline\\noalign{\\medskip}" + $$ "\\toprule\\addlinespace" $$ headers $$ vcat rows' - $$ "\\hline" + $$ "\\bottomrule" $$ capt $$ "\\end{longtable}" @@ -463,23 +493,42 @@ tableRowToLaTeX :: Bool -> [[Block]] -> State WriterState Doc tableRowToLaTeX header aligns widths cols = do - renderedCells <- mapM blockListToLaTeX cols - let valign = text $ if header then "[b]" else "[t]" - let halign x = case x of - AlignLeft -> "\\raggedright" - AlignRight -> "\\raggedleft" - AlignCenter -> "\\centering" - AlignDefault -> "\\raggedright" -- scale factor compensates for extra space between columns -- so the whole table isn't larger than columnwidth let scaleFactor = 0.97 ** fromIntegral (length aligns) - let toCell 0 _ c = c - toCell w a c = "\\begin{minipage}" <> valign <> - braces (text (printf "%.2f\\columnwidth" - (w * scaleFactor))) <> - (halign a <> cr <> c <> cr) <> "\\end{minipage}" - let cells = zipWith3 toCell widths aligns renderedCells - return $ hsep (intersperse "&" cells) $$ "\\\\\\noalign{\\medskip}" + let widths' = map (scaleFactor *) widths + cells <- mapM (tableCellToLaTeX header) $ zip3 widths' aligns cols + return $ hsep (intersperse "&" cells) $$ "\\\\\\addlinespace" + +tableCellToLaTeX :: Bool -> (Double, Alignment, [Block]) + -> State WriterState Doc +tableCellToLaTeX _ (0, _, blocks) = blockListToLaTeX blocks +tableCellToLaTeX header (width, align, blocks) = do + modify $ \st -> st{ stInMinipage = True, stNotes = [] } + cellContents <- blockListToLaTeX blocks + notes <- gets stNotes + modify $ \st -> st{ stInMinipage = False, stNotes = [] } + let valign = text $ if header then "[b]" else "[t]" + let halign = case align of + AlignLeft -> "\\raggedright" + AlignRight -> "\\raggedleft" + AlignCenter -> "\\centering" + AlignDefault -> "\\raggedright" + return $ ("\\begin{minipage}" <> valign <> + braces (text (printf "%.2f\\columnwidth" width)) <> + (halign <> cr <> cellContents <> cr) <> "\\end{minipage}") + $$ case notes of + [] -> empty + ns -> (case length ns of + n | n > 1 -> "\\addtocounter" <> + braces "footnote" <> + braces (text $ show $ 1 - n) + | otherwise -> empty) + $$ + vcat (intersperse + ("\\addtocounter" <> braces "footnote" <> braces "1") + $ map (\x -> "\\footnotetext" <> braces x) + $ reverse ns) listItemToLaTeX :: [Block] -> State WriterState Doc listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item" $$) . @@ -488,8 +537,15 @@ listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item" $$) . defListItemToLaTeX :: ([Inline], [[Block]]) -> State WriterState Doc defListItemToLaTeX (term, defs) = do term' <- inlineListToLaTeX term + -- put braces around term if it contains an internal link, + -- since otherwise we get bad bracket interactions: \item[\hyperref[..] + let isInternalLink (Link _ ('#':_,_)) = True + isInternalLink _ = False + let term'' = if any isInternalLink term + then braces term' + else term' def' <- liftM vsep $ mapM blockListToLaTeX defs - return $ "\\item" <> brackets term' $$ def' + return $ "\\item" <> brackets term'' $$ def' -- | Craft the section header, inserting the secton reference, if supplied. sectionHeader :: Bool -- True for unnumbered @@ -519,13 +575,13 @@ sectionHeader unnumbered ref level lst = do let refLabel x = (if ref `elem` internalLinks then text "\\hyperdef" <> braces empty - <> braces (text ref) + <> braces (text $ toLabel ref) <> braces x else x) let headerWith x y r = refLabel $ text x <> y <> if null r then empty - else text "\\label" <> braces (text r) + else text "\\label" <> braces (text $ toLabel r) let sectionType = case level' of 0 | writerBeamer opts -> "part" | otherwise -> "chapter" @@ -568,7 +624,16 @@ isQuoted _ = False -- | Convert inline element to LaTeX inlineToLaTeX :: Inline -- ^ Inline to convert -> State WriterState Doc -inlineToLaTeX (Span _ ils) = inlineListToLaTeX ils >>= return . braces +inlineToLaTeX (Span (_,classes,_) ils) = do + let noEmph = "csl-no-emph" `elem` classes + let noStrong = "csl-no-strong" `elem` classes + let noSmallCaps = "csl-no-smallcaps" `elem` classes + ((if noEmph then inCmd "textup" else id) . + (if noStrong then inCmd "textnormal" else id) . + (if noSmallCaps then inCmd "textnormal" else id) . + (if not (noEmph || noStrong || noSmallCaps) + then braces + else id)) `fmap` inlineListToLaTeX ils inlineToLaTeX (Emph lst) = inlineListToLaTeX lst >>= return . inCmd "emph" inlineToLaTeX (Strong lst) = @@ -646,7 +711,8 @@ inlineToLaTeX Space = return space inlineToLaTeX (Link txt ('#':ident, _)) = do contents <- inlineListToLaTeX txt ident' <- stringToLaTeX URLString ident - return $ text "\\hyperref" <> brackets (text ident') <> braces contents + return $ text "\\hyperref" <> brackets (text $ toLabel ident') <> + braces contents inlineToLaTeX (Link txt (src, _)) = case txt of [Str x] | x == src -> -- autolink @@ -659,20 +725,26 @@ inlineToLaTeX (Link txt (src, _)) = contents <> char '}' inlineToLaTeX (Image _ (source, _)) = do modify $ \s -> s{ stGraphics = True } - let source' = if isAbsoluteURI source + let source' = if isURI source then source else unEscapeString source source'' <- stringToLaTeX URLString source' return $ "\\includegraphics" <> braces (text source'') inlineToLaTeX (Note contents) = do + inMinipage <- gets stInMinipage modify (\s -> s{stInNote = True}) contents' <- blockListToLaTeX contents modify (\s -> s {stInNote = False}) let optnl = case reverse contents of (CodeBlock _ _ : _) -> cr _ -> empty - return $ "\\footnote" <> braces (nest 2 contents' <> optnl) - -- note: a \n before } needed when note ends with a Verbatim environment + let noteContents = nest 2 contents' <> optnl + modify $ \st -> st{ stNotes = noteContents : stNotes st } + return $ + if inMinipage + then "\\footnotemark{}" + -- note: a \n before } needed when note ends with a Verbatim environment + else "\\footnote" <> braces noteContents citationsToNatbib :: [Citation] -> State WriterState Doc citationsToNatbib (one:[]) @@ -693,9 +765,9 @@ citationsToNatbib cits | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits = citeCommand "citep" p s ks where - noPrefix = and . map (null . citationPrefix) - noSuffix = and . map (null . citationSuffix) - ismode m = and . map (((==) m) . citationMode) + noPrefix = all (null . citationPrefix) + noSuffix = all (null . citationSuffix) + ismode m = all (((==) m) . citationMode) p = citationPrefix $ head $ cits s = citationSuffix $ last $ cits ks = intercalate ", " $ map citationId cits diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs index 642a002d6..b31cc2b70 100644 --- a/src/Text/Pandoc/Writers/Man.hs +++ b/src/Text/Pandoc/Writers/Man.hs @@ -330,9 +330,10 @@ inlineToMan opts (Cite _ lst) = inlineToMan _ (Code _ str) = return $ text $ "\\f[C]" ++ escapeCode str ++ "\\f[]" inlineToMan _ (Str str) = return $ text $ escapeString str -inlineToMan opts (Math InlineMath str) = inlineListToMan opts $ readTeXMath str +inlineToMan opts (Math InlineMath str) = + inlineListToMan opts $ readTeXMath' InlineMath str inlineToMan opts (Math DisplayMath str) = do - contents <- inlineListToMan opts $ readTeXMath str + contents <- inlineListToMan opts $ readTeXMath' DisplayMath str return $ cr <> text ".RS" $$ contents $$ text ".RE" inlineToMan _ (RawInline f str) | f == Format "man" = return $ text str diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs index 23e730bf0..278e5cc9d 100644 --- a/src/Text/Pandoc/Writers/Markdown.hs +++ b/src/Text/Pandoc/Writers/Markdown.hs @@ -45,9 +45,9 @@ import Text.Pandoc.Pretty import Control.Monad.State import qualified Data.Set as Set import Text.Pandoc.Writers.HTML (writeHtmlString) -import Text.Pandoc.Readers.TeXMath (readTeXMath) +import Text.Pandoc.Readers.TeXMath (readTeXMath') import Text.HTML.TagSoup (renderTags, parseTags, isTagText, Tag(..)) -import Network.URI (isAbsoluteURI) +import Network.URI (isURI) import Data.Default import Data.Yaml (Value(Object,String,Array,Bool,Number)) import qualified Data.HashMap.Strict as H @@ -187,10 +187,11 @@ pandocToMarkdown opts (Pandoc meta blocks) = do then tableOfContents opts headerBlocks else empty -- Strip off final 'references' header if markdown citations enabled - let blocks' = case reverse blocks of - (Div (_,["references"],_) _):xs - | isEnabled Ext_citations opts -> reverse xs - _ -> blocks + let blocks' = if not isPlain && isEnabled Ext_citations opts + then case reverse blocks of + (Div (_,["references"],_) _):xs -> reverse xs + _ -> blocks + else blocks body <- blockListToMarkdown opts blocks' st <- get notes' <- notesToMarkdown opts (reverse $ stNotes st) @@ -337,7 +338,7 @@ blockToMarkdown opts (RawBlock f str) else return $ if isEnabled Ext_markdown_attribute opts then text (addMarkdownAttribute str) <> text "\n" else text str <> text "\n" - | f == "latex" || f == "tex" || f == "markdown" = do + | f `elem` ["latex", "tex", "markdown"] = do st <- get if stPlain st then return empty @@ -380,13 +381,11 @@ blockToMarkdown opts (CodeBlock (_,classes,_) str) isEnabled Ext_literate_haskell opts = return $ prefixed "> " (text str) <> blankline blockToMarkdown opts (CodeBlock attribs str) = return $ - case attribs of - x | x /= nullAttr && isEnabled Ext_fenced_code_blocks opts -> - tildes <> " " <> attrs <> cr <> text str <> - cr <> tildes <> blankline - (_,(cls:_),_) | isEnabled Ext_backtick_code_blocks opts -> - backticks <> " " <> text cls <> cr <> text str <> - cr <> backticks <> blankline + case attribs == nullAttr of + False | isEnabled Ext_backtick_code_blocks opts -> + backticks <> attrs <> cr <> text str <> cr <> backticks <> blankline + | isEnabled Ext_fenced_code_blocks opts -> + tildes <> attrs <> cr <> text str <> cr <> tildes <> blankline _ -> nest (writerTabStop opts) (text str) <> blankline where tildes = text $ case [ln | ln <- lines str, all (=='~') ln] of [] -> "~~~~" @@ -395,8 +394,10 @@ blockToMarkdown opts (CodeBlock attribs str) = return $ | otherwise -> replicate (n+1) '~' backticks = text "```" attrs = if isEnabled Ext_fenced_code_attributes opts - then nowrap $ attrsToMarkdown attribs - else empty + then nowrap $ " " <> attrsToMarkdown attribs + else case attribs of + (_,[cls],_) -> " " <> text cls + _ -> empty blockToMarkdown opts (BlockQuote blocks) = do st <- get -- if we're writing literate haskell, put a space before the bird tracks @@ -554,7 +555,14 @@ bulletListItemToMarkdown opts items = do contents <- blockListToMarkdown opts items let sps = replicate (writerTabStop opts - 2) ' ' let start = text ('-' : ' ' : sps) - return $ hang (writerTabStop opts) start $ contents <> cr + -- remove trailing blank line if it is a tight list + let contents' = case reverse items of + (BulletList xs:_) | isTightList xs -> + chomp contents <> cr + (OrderedList _ xs:_) | isTightList xs -> + chomp contents <> cr + _ -> contents + return $ hang (writerTabStop opts) start $ contents' <> cr -- | Convert ordered list item (a list of blocks) to markdown. orderedListItemToMarkdown :: WriterOptions -- ^ options @@ -620,10 +628,11 @@ getReference label (src, tit) = do Nothing -> do let label' = case find ((== label) . fst) (stRefs st) of Just _ -> -- label is used; generate numerical label - case find (\n -> not (any (== [Str (show n)]) - (map fst (stRefs st)))) [1..(10000 :: Integer)] of - Just x -> [Str (show x)] - Nothing -> error "no unique label" + case find (\n -> notElem [Str (show n)] + (map fst (stRefs st))) + [1..(10000 :: Integer)] of + Just x -> [Str (show x)] + Nothing -> error "no unique label" Nothing -> label modify (\s -> s{ stRefs = (label', (src,tit)) : stRefs st }) return label' @@ -641,8 +650,11 @@ escapeSpaces x = x -- | Convert Pandoc inline element to markdown. inlineToMarkdown :: WriterOptions -> Inline -> State WriterState Doc inlineToMarkdown opts (Span attrs ils) = do + st <- get contents <- inlineListToMarkdown opts ils - return $ tagWithAttrs "span" attrs <> contents <> text "</span>" + return $ if stPlain st + then contents + else tagWithAttrs "span" attrs <> contents <> text "</span>" inlineToMarkdown opts (Emph lst) = do contents <- inlineListToMarkdown opts lst return $ "*" <> contents <> "*" @@ -696,7 +708,7 @@ inlineToMarkdown opts (Math InlineMath str) return $ "\\(" <> text str <> "\\)" | isEnabled Ext_tex_math_double_backslash opts = return $ "\\\\(" <> text str <> "\\\\)" - | otherwise = inlineListToMarkdown opts $ readTeXMath str + | otherwise = inlineListToMarkdown opts $ readTeXMath' InlineMath str inlineToMarkdown opts (Math DisplayMath str) | isEnabled Ext_tex_math_dollars opts = return $ "$$" <> text str <> "$$" @@ -705,7 +717,7 @@ inlineToMarkdown opts (Math DisplayMath str) | isEnabled Ext_tex_math_double_backslash opts = return $ "\\\\[" <> text str <> "\\\\]" | otherwise = (\x -> cr <> x <> cr) `fmap` - inlineListToMarkdown opts (readTeXMath str) + inlineListToMarkdown opts (readTeXMath' DisplayMath str) inlineToMarkdown opts (RawInline f str) | f == "html" || f == "markdown" || (isEnabled Ext_raw_tex opts && (f == "latex" || f == "tex")) = @@ -752,7 +764,7 @@ inlineToMarkdown opts (Link txt (src, tit)) = do then empty else text $ " \"" ++ tit ++ "\"" let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src - let useAuto = isAbsoluteURI src && + let useAuto = isURI src && case txt of [Str s] | escapeURI s == srcSuffix -> True _ -> False diff --git a/src/Text/Pandoc/Writers/MediaWiki.hs b/src/Text/Pandoc/Writers/MediaWiki.hs index 61741a61e..83fefaa29 100644 --- a/src/Text/Pandoc/Writers/MediaWiki.hs +++ b/src/Text/Pandoc/Writers/MediaWiki.hs @@ -51,7 +51,7 @@ data WriterState = WriterState { writeMediaWiki :: WriterOptions -> Pandoc -> String writeMediaWiki opts document = evalState (pandocToMediaWiki opts document) - (WriterState { stNotes = False, stListLevel = [], stUseTags = False }) + WriterState { stNotes = False, stListLevel = [], stUseTags = False } -- | Return MediaWiki representation of document. pandocToMediaWiki :: WriterOptions -> Pandoc -> State WriterState String diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs index cc0a06243..c3652d65d 100644 --- a/src/Text/Pandoc/Writers/ODT.hs +++ b/src/Text/Pandoc/Writers/ODT.hs @@ -30,7 +30,10 @@ Conversion of 'Pandoc' documents to ODT. -} module Text.Pandoc.Writers.ODT ( writeODT ) where import Data.IORef -import Data.List ( isPrefixOf ) +import Data.List ( isPrefixOf, isSuffixOf ) +import Data.Maybe ( fromMaybe ) +import Text.XML.Light.Output +import Text.TeXMath import qualified Data.ByteString.Lazy as B import Text.Pandoc.UTF8 ( fromStringLazy ) import Codec.Archive.Zip @@ -40,13 +43,14 @@ import Text.Pandoc.ImageSize ( imageSize, sizeInPoints ) import Text.Pandoc.MIME ( getMimeType ) import Text.Pandoc.Definition import Text.Pandoc.Walk +import Text.Pandoc.Writers.Shared ( fixDisplayMath ) import Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) import Control.Monad (liftM) import Text.Pandoc.XML import Text.Pandoc.Pretty import qualified Control.Exception as E import Data.Time.Clock.POSIX ( getPOSIXTime ) -import System.FilePath ( takeExtension ) +import System.FilePath ( takeExtension, takeDirectory ) -- | Produce an ODT file from a Pandoc document. writeODT :: WriterOptions -- ^ Writer options @@ -60,9 +64,9 @@ writeODT opts doc@(Pandoc meta _) = do Just f -> B.readFile f Nothing -> (B.fromChunks . (:[])) `fmap` readDataFile datadir "reference.odt" - -- handle pictures + -- handle formulas and pictures picEntriesRef <- newIORef ([] :: [Entry]) - doc' <- walkM (transformPic opts picEntriesRef) doc + doc' <- walkM (transformPicMath opts picEntriesRef) $ walk fixDisplayMath doc let newContents = writeOpenDocument opts{writerWrapText = False} doc' epochtime <- floor `fmap` getPOSIXTime let contentEntry = toEntry "content.xml" epochtime @@ -72,7 +76,11 @@ writeODT opts doc@(Pandoc meta _) = do $ contentEntry : picEntries -- construct META-INF/manifest.xml based on archive let toFileEntry fp = case getMimeType fp of - Nothing -> empty + Nothing -> if "Formula-" `isPrefixOf` fp && "/" `isSuffixOf` fp + then selfClosingTag "manifest:file-entry" + [("manifest:media-type","application/vnd.oasis.opendocument.formula") + ,("manifest:full-path",fp)] + else empty Just m -> selfClosingTag "manifest:file-entry" [("manifest:media-type", m) ,("manifest:full-path", fp) @@ -80,6 +88,8 @@ writeODT opts doc@(Pandoc meta _) = do ] let files = [ ent | ent <- filesInArchive archive, not ("META-INF" `isPrefixOf` ent) ] + let formulas = [ takeDirectory ent ++ "/" | ent <- filesInArchive archive, + "Formula-" `isPrefixOf` ent, takeExtension ent == ".xml" ] let manifestEntry = toEntry "META-INF/manifest.xml" epochtime $ fromStringLazy $ render Nothing $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>" @@ -91,6 +101,7 @@ writeODT opts doc@(Pandoc meta _) = do [("manifest:media-type","application/vnd.oasis.opendocument.text") ,("manifest:full-path","/")] $$ vcat ( map toFileEntry $ files ) + $$ vcat ( map toFileEntry $ formulas ) ) ) let archive' = addEntryToArchive manifestEntry archive @@ -118,8 +129,8 @@ writeODT opts doc@(Pandoc meta _) = do $ addEntryToArchive metaEntry archive' return $ fromArchive archive'' -transformPic :: WriterOptions -> IORef [Entry] -> Inline -> IO Inline -transformPic opts entriesRef (Image lab (src,_)) = do +transformPicMath :: WriterOptions -> IORef [Entry] -> Inline -> IO Inline +transformPicMath opts entriesRef (Image lab (src,_)) = do res <- fetchItem (writerSourceURL opts) src case res of Left (_ :: E.SomeException) -> do @@ -127,7 +138,7 @@ transformPic opts entriesRef (Image lab (src,_)) = do return $ Emph lab Right (img, _) -> do let size = imageSize img - let (w,h) = maybe (0,0) id $ sizeInPoints `fmap` size + let (w,h) = fromMaybe (0,0) $ sizeInPoints `fmap` size let tit' = show w ++ "x" ++ show h entries <- readIORef entriesRef let newsrc = "Pictures/" ++ show (length entries) ++ takeExtension src @@ -136,5 +147,29 @@ transformPic opts entriesRef (Image lab (src,_)) = do let entry = toEntry newsrc epochtime $ toLazy img modifyIORef entriesRef (entry:) return $ Image lab (newsrc, tit') -transformPic _ _ x = return x +transformPicMath _ entriesRef (Math t math) = do + entries <- readIORef entriesRef + let dt = if t == InlineMath then DisplayInline else DisplayBlock + case texMathToMathML dt math of + Left _ -> return $ Math t math + Right r -> do + let conf = useShortEmptyTags (const False) defaultConfigPP + let mathml = ppcTopElement conf r + epochtime <- floor `fmap` getPOSIXTime + let dirname = "Formula-" ++ show (length entries) ++ "/" + let fname = dirname ++ "content.xml" + let entry = toEntry fname epochtime (fromStringLazy mathml) + modifyIORef entriesRef (entry:) + return $ RawInline (Format "opendocument") $ render Nothing $ + inTags False "draw:frame" [("text:anchor-type", + if t == DisplayMath + then "paragraph" + else "as-char") + ,("style:vertical-pos", "middle") + ,("style:vertical-rel", "text")] $ + selfClosingTag "draw:object" [("xlink:href", dirname) + , ("xlink:type", "simple") + , ("xlink:show", "embed") + , ("xlink:actuate", "onLoad")] +transformPicMath _ _ x = return x diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs index 3ec5c2073..0029c3296 100644 --- a/src/Text/Pandoc/Writers/OpenDocument.hs +++ b/src/Text/Pandoc/Writers/OpenDocument.hs @@ -64,6 +64,7 @@ data WriterState = , stInDefinition :: Bool , stTight :: Bool , stFirstPara :: Bool + , stImageId :: Int } defaultWriterState :: WriterState @@ -78,6 +79,7 @@ defaultWriterState = , stInDefinition = False , stTight = False , stFirstPara = False + , stImageId = 1 } when :: Bool -> Doc -> Doc @@ -283,8 +285,12 @@ blocksToOpenDocument o b = vcat <$> mapM (blockToOpenDocument o) b -- | Convert a Pandoc block element to OpenDocument. blockToOpenDocument :: WriterOptions -> Block -> State WriterState Doc blockToOpenDocument o bs - | Plain b <- bs = inParagraphTags =<< inlinesToOpenDocument o b - | Para b <- bs = inParagraphTags =<< inlinesToOpenDocument o b + | Plain b <- bs = if null b + then return empty + else inParagraphTags =<< inlinesToOpenDocument o b + | Para b <- bs = if null b + then return empty + else inParagraphTags =<< inlinesToOpenDocument o b | Div _ xs <- bs = blocksToOpenDocument o xs | Header i _ b <- bs = setFirstPara >> (inHeaderTags i =<< inlinesToOpenDocument o b) @@ -296,8 +302,8 @@ blockToOpenDocument o bs | Table c a w h r <- bs = setFirstPara >> table c a w h r | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p" [ ("text:style-name", "Horizontal_20_Line") ]) - | RawBlock f s <- bs = if f == "opendocument" - then preformatted s + | RawBlock f s <- bs = if f == Format "opendocument" + then return $ text s else return empty | Null <- bs = return empty | otherwise = return empty @@ -373,23 +379,27 @@ inlineToOpenDocument o ils | Subscript l <- ils = withTextStyle Sub $ inlinesToOpenDocument o l | SmallCaps l <- ils = withTextStyle SmallC $ inlinesToOpenDocument o l | Quoted t l <- ils = inQuotes t <$> inlinesToOpenDocument o l - | Code _ s <- ils = preformatted s - | Math _ s <- ils = inlinesToOpenDocument o (readTeXMath s) + | Code _ s <- ils = withTextStyle Pre $ inTextStyle $ preformatted s + | Math t s <- ils = inlinesToOpenDocument o (readTeXMath' t s) | Cite _ l <- ils = inlinesToOpenDocument o l - | RawInline f s <- ils = if f == "opendocument" || f == "html" - then preformatted s + | RawInline f s <- ils = if f == Format "opendocument" + then return $ text s else return empty | Link l (s,t) <- ils = mkLink s t <$> inlinesToOpenDocument o l - | Image _ (s,t) <- ils = return $ mkImg s t + | Image _ (s,t) <- ils = mkImg s t | Note l <- ils = mkNote l | otherwise = return empty where - preformatted = return . inSpanTags "Teletype" . handleSpaces . escapeStringForXML + preformatted s = handleSpaces $ escapeStringForXML s mkLink s t = inTags False "text:a" [ ("xlink:type" , "simple") , ("xlink:href" , s ) , ("office:name", t ) ] . inSpanTags "Definition" - mkImg s t = inTags False "draw:frame" (attrsFromTitle t) $ + mkImg s t = do + id' <- gets stImageId + modify (\st -> st{ stImageId = id' + 1 }) + return $ inTags False "draw:frame" + (("draw:name", "img" ++ show id'):attrsFromTitle t) $ selfClosingTag "draw:image" [ ("xlink:href" , s ) , ("xlink:type" , "simple") , ("xlink:show" , "embed" ) @@ -524,7 +534,8 @@ paraTableStyles t s (a:xs) [ ("fo:text-align", x) , ("style:justify-single-word", "false")] -data TextStyle = Italic | Bold | Strike | Sub | Sup | SmallC deriving ( Eq,Ord ) +data TextStyle = Italic | Bold | Strike | Sub | Sup | SmallC | Pre + deriving ( Eq,Ord ) textStyleAttr :: TextStyle -> [(String,String)] textStyleAttr s @@ -538,5 +549,8 @@ textStyleAttr s | Sub <- s = [("style:text-position" ,"sub 58%" )] | Sup <- s = [("style:text-position" ,"super 58%" )] | SmallC <- s = [("fo:font-variant" ,"small-caps")] + | Pre <- s = [("style:font-name" ,"Courier New") + ,("style:font-name-asian" ,"Courier New") + ,("style:font-name-complex" ,"Courier New")] | otherwise = [] diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs index 51083f52b..d318c5f6a 100644 --- a/src/Text/Pandoc/Writers/Org.hs +++ b/src/Text/Pandoc/Writers/Org.hs @@ -129,7 +129,7 @@ blockToOrg (Para inlines) = do blockToOrg (RawBlock "html" str) = return $ blankline $$ "#+BEGIN_HTML" $$ nest 2 (text str) $$ "#+END_HTML" $$ blankline -blockToOrg (RawBlock f str) | f == "org" || f == "latex" || f == "tex" = +blockToOrg (RawBlock f str) | f `elem` ["org", "latex", "tex"] = return $ text str blockToOrg (RawBlock _ _) = return empty blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs index 70c6b4421..37bb66632 100644 --- a/src/Text/Pandoc/Writers/RST.hs +++ b/src/Text/Pandoc/Writers/RST.hs @@ -38,7 +38,7 @@ import Text.Pandoc.Writers.Shared import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Builder (deleteMeta) import Data.List ( isPrefixOf, intersperse, transpose ) -import Network.URI (isAbsoluteURI) +import Network.URI (isURI) import Text.Pandoc.Pretty import Control.Monad.State import Control.Applicative ( (<$>) ) @@ -287,7 +287,7 @@ definitionListItemToRST (label, defs) = do label' <- inlineListToRST label contents <- liftM vcat $ mapM blockListToRST defs tabstop <- get >>= (return . writerTabStop . stOptions) - return $ label' $$ nest tabstop (contents <> cr) + return $ label' $$ nest tabstop (nestle contents <> cr) -- | Convert list of Pandoc block elements to RST. blockListToRST :: [Block] -- ^ List of block elements @@ -296,8 +296,14 @@ blockListToRST blocks = mapM blockToRST blocks >>= return . vcat -- | Convert list of Pandoc inline elements to RST. inlineListToRST :: [Inline] -> State WriterState Doc -inlineListToRST lst = mapM inlineToRST (insertBS lst) >>= return . hcat - where insertBS :: [Inline] -> [Inline] -- insert '\ ' where needed +inlineListToRST lst = + mapM inlineToRST (removeSpaceAfterDisplayMath $ insertBS lst) >>= return . hcat + where -- remove spaces after displaymath, as they screw up indentation: + removeSpaceAfterDisplayMath (Math DisplayMath x : zs) = + Math DisplayMath x : dropWhile (==Space) zs + removeSpaceAfterDisplayMath (x:xs) = x : removeSpaceAfterDisplayMath xs + removeSpaceAfterDisplayMath [] = [] + insertBS :: [Inline] -> [Inline] -- insert '\ ' where needed insertBS (x:y:z:zs) | isComplex y && surroundComplex x z = x : y : RawInline "rst" "\\ " : insertBS (z:zs) @@ -387,7 +393,7 @@ inlineToRST (LineBreak) = return cr -- there's no line break in RST (see Para) inlineToRST Space = return space -- autolink inlineToRST (Link [Str str] (src, _)) - | isAbsoluteURI src && + | isURI src && if "mailto:" `isPrefixOf` src then src == escapeURI ("mailto:" ++ str) else src == escapeURI str = do diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs index 0e8ce2ece..fb935fa6a 100644 --- a/src/Text/Pandoc/Writers/RTF.hs +++ b/src/Text/Pandoc/Writers/RTF.hs @@ -40,7 +40,7 @@ import Data.Char ( ord, chr, isDigit, toLower ) import System.FilePath ( takeExtension ) import qualified Data.ByteString as B import Text.Printf ( printf ) -import Network.URI ( isAbsoluteURI, unEscapeString ) +import Network.URI ( isURI, unEscapeString ) import qualified Control.Exception as E -- | Convert Image inlines into a raw RTF embedded image, read from a file. @@ -48,7 +48,7 @@ import qualified Control.Exception as E rtfEmbedImage :: Inline -> IO Inline rtfEmbedImage x@(Image _ (src,_)) = do let ext = map toLower (takeExtension src) - if ext `elem` [".jpg",".jpeg",".png"] && not (isAbsoluteURI src) + if ext `elem` [".jpg",".jpeg",".png"] && not (isURI src) then do let src' = unEscapeString src imgdata <- E.catch (B.readFile src') @@ -324,7 +324,7 @@ inlineToRTF (Quoted DoubleQuote lst) = "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\"" inlineToRTF (Code _ str) = "{\\f1 " ++ (codeStringToRTF str) ++ "}" inlineToRTF (Str str) = stringToRTF str -inlineToRTF (Math _ str) = inlineListToRTF $ readTeXMath str +inlineToRTF (Math t str) = inlineListToRTF $ readTeXMath' t str inlineToRTF (Cite _ lst) = inlineListToRTF lst inlineToRTF (RawInline f str) | f == Format "rtf" = str diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs index 89923822c..604aac1c9 100644 --- a/src/Text/Pandoc/Writers/Shared.hs +++ b/src/Text/Pandoc/Writers/Shared.hs @@ -34,6 +34,7 @@ module Text.Pandoc.Writers.Shared ( , setField , defField , tagWithAttrs + , fixDisplayMath ) where import Text.Pandoc.Definition @@ -46,6 +47,7 @@ import qualified Data.Map as M import qualified Data.Text as T import Data.Aeson (FromJSON(..), fromJSON, ToJSON (..), Value(Object), Result(..)) import qualified Data.Traversable as Traversable +import Data.List ( groupBy ) -- | Create JSON value for template from a 'Meta' and an association list -- of variables, specified at the command line or in the writer. @@ -65,8 +67,7 @@ metaToJSON opts blockWriter inlineWriter (Meta metamap) renderedMap <- Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap - return $ M.foldWithKey (\key val obj -> defField key val obj) - baseContext renderedMap + return $ M.foldWithKey defField baseContext renderedMap | otherwise = return (Object H.empty) metaValueToJSON :: Monad m @@ -134,7 +135,31 @@ tagWithAttrs tag (ident,classes,kvs) = hsep ,if null classes then empty else "class=" <> doubleQuotes (text (unwords classes)) - ] - <> hsep (map (\(k,v) -> text k <> "=" <> + ,hsep (map (\(k,v) -> text k <> "=" <> doubleQuotes (text (escapeStringForXML v))) kvs) - <> ">" + ] <> ">" + +isDisplayMath :: Inline -> Bool +isDisplayMath (Math DisplayMath _) = True +isDisplayMath _ = False + +stripLeadingTrailingSpace :: [Inline] -> [Inline] +stripLeadingTrailingSpace = go . reverse . go . reverse + where go (Space:xs) = xs + go xs = xs + +-- Put display math in its own block (for ODT/DOCX). +fixDisplayMath :: Block -> Block +fixDisplayMath (Plain lst) + | any isDisplayMath lst && not (all isDisplayMath lst) = + -- chop into several paragraphs so each displaymath is its own + Div ("",["math"],[]) $ map (Plain . stripLeadingTrailingSpace) $ + groupBy (\x y -> (isDisplayMath x && isDisplayMath y) || + not (isDisplayMath x || isDisplayMath y)) lst +fixDisplayMath (Para lst) + | any isDisplayMath lst && not (all isDisplayMath lst) = + -- chop into several paragraphs so each displaymath is its own + Div ("",["math"],[]) $ map (Para . stripLeadingTrailingSpace) $ + groupBy (\x y -> (isDisplayMath x && isDisplayMath y) || + not (isDisplayMath x || isDisplayMath y)) lst +fixDisplayMath x = x diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs index b1fd3d6af..bf3df8035 100644 --- a/src/Text/Pandoc/Writers/Texinfo.hs +++ b/src/Text/Pandoc/Writers/Texinfo.hs @@ -40,7 +40,7 @@ import Data.Ord ( comparing ) import Data.Char ( chr, ord ) import Control.Monad.State import Text.Pandoc.Pretty -import Network.URI ( isAbsoluteURI, unEscapeString ) +import Network.URI ( isURI, unEscapeString ) import System.FilePath data WriterState = @@ -293,7 +293,7 @@ blockListToTexinfo (x:xs) = do case x of Header level _ _ -> do -- We need need to insert a menu for this node. - let (before, after) = break isHeader xs + let (before, after) = break isHeaderBlock xs before' <- blockListToTexinfo before let menu = if level < 4 then collectNodes (level + 1) after @@ -315,10 +315,6 @@ blockListToTexinfo (x:xs) = do xs' <- blockListToTexinfo xs return $ x' $$ xs' -isHeader :: Block -> Bool -isHeader (Header _ _ _) = True -isHeader _ = False - collectNodes :: Int -> [Block] -> [Block] collectNodes _ [] = [] collectNodes level (x:xs) = @@ -448,7 +444,7 @@ inlineToTexinfo (Image alternate (source, _)) = do where ext = drop 1 $ takeExtension source' base = dropExtension source' - source' = if isAbsoluteURI source + source' = if isURI source then source else unEscapeString source diff --git a/src/Text/Pandoc/Writers/Textile.hs b/src/Text/Pandoc/Writers/Textile.hs index 7c102cc86..95aedf780 100644 --- a/src/Text/Pandoc/Writers/Textile.hs +++ b/src/Text/Pandoc/Writers/Textile.hs @@ -51,7 +51,7 @@ data WriterState = WriterState { writeTextile :: WriterOptions -> Pandoc -> String writeTextile opts document = evalState (pandocToTextile opts document) - (WriterState { stNotes = [], stListLevel = [], stUseTags = False }) + WriterState { stNotes = [], stListLevel = [], stUseTags = False } -- | Return Textile representation of document. pandocToTextile :: WriterOptions -> Pandoc -> State WriterState String diff --git a/tests/MarkdownTest_1.0.3/MarkdownTest.pl b/tests/MarkdownTest_1.0.3/MarkdownTest.pl deleted file mode 100755 index 55553d09c..000000000 --- a/tests/MarkdownTest_1.0.3/MarkdownTest.pl +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/perl - -# -# MarkdownTester -- Run tests for Markdown implementations -# -# Copyright (c) 2004-2005 John Gruber -# <http://daringfireball.net/projects/markdown/> -# - -use strict; -use warnings; -use Getopt::Long; -use Benchmark; - -our $VERSION = '1.0.2'; -# Sat 24 Dec 2005 - -my $time_start = new Benchmark; -my $test_dir = "Tests"; -my $script = "./Markdown.pl"; -my $use_tidy = 0; -my ($flag_version); - -GetOptions ( - "script=s" => \$script, - "testdir=s" => \$test_dir, - "tidy" => \$use_tidy, - "version" => \$flag_version, - ); - -if($flag_version) { - my $progname = $0; - $progname =~ s{.*/}{}; - die "$progname version $VERSION\n"; -} - -unless (-d $test_dir) { die "'$test_dir' is not a directory.\n"; } -unless (-f $script) { die "$script does not exist.\n"; } -unless (-x $script) { die "$script is not executable.\n"; } - -my $tests_passed = 0; -my $tests_failed = 0; - -TEST: -foreach my $testfile (glob "$test_dir/*.text") { - my $testname = $testfile; - $testname =~ s{.*/(.+)\.text$}{$1}i; - print "$testname ... "; - - # Look for a corresponding .html file for each .text file: - my $resultfile = $testfile; - $resultfile =~ s{\.text$}{\.html}i; - unless (-f $resultfile) { - print "'$resultfile' does not exist.\n\n"; - next TEST; - } - - # open(TEST, $testfile) || die("Can't open testfile: $!"); - open(RESULT, $resultfile) || die("Can't open resultfile: $!"); - undef $/; - # my $t_input = <TEST>; - my $t_result = <RESULT>; - - my $t_output = `'$script' '$testfile'`; - - # Normalize the output and expected result strings: - $t_result =~ s/\s+\z//; # trim trailing whitespace - $t_output =~ s/\s+\z//; # trim trailing whitespace - if ($use_tidy) { - # Escape the strings, pass them through to CLI tidy tool for tag-level equivalency - $t_result =~ s{'}{'\\''}g; # escape ' chars for shell - $t_output =~ s{'}{'\\''}g; - $t_result = `echo '$t_result' | tidy --show-body-only 1 --quiet 1 --show-warnings 0`; - $t_output = `echo '$t_output' | tidy --show-body-only 1 --quiet 1 --show-warnings 0`; - } - - if ($t_output eq $t_result) { - print "OK\n"; - $tests_passed++; - } - else { - print "FAILED\n\n"; -# This part added by JM to print diffs - open(OUT, '>tmp1') or die $!; - print OUT $t_output or die $!; - open(RES, '>tmp2') or die $!; - print RES $t_result or die $!; - print `diff tmp1 tmp2`; - close RES; - close OUT; - print "\n"; - `rm tmp?`; -# End of added part - $tests_failed++; - } -} - -print "\n\n"; -print "$tests_passed passed; $tests_failed failed.\n"; - -my $time_end = new Benchmark; -my $time_diff = timediff($time_end, $time_start); -print "Benchmark: ", timestr($time_diff), "\n"; - - -__END__ - -=pod - -=head1 NAME - -B<MarkdownTest> - - -=head1 SYNOPSIS - -B<MarkdownTest.pl> [ B<--options> ] [ I<file> ... ] - - -=head1 DESCRIPTION - - -=head1 OPTIONS - -Use "--" to end switch parsing. For example, to open a file named "-z", use: - - MarkdownTest.pl -- -z - -=over 4 - -=item B<--script> - -Specify the path to the Markdown script to test. Defaults to -"./Markdown.pl". Example: - - ./MarkdownTest.pl --script ./PHP-Markdown/php-markdown - -=item B<--testdir> - -Specify the path to a directory containing test data. Defaults to "Tests". - -=item B<--tidy> - -Flag to turn on using the command line 'tidy' tool to normalize HTML -output before comparing script output to the expected test result. -Assumes that the 'tidy' command is available in your PATH. Defaults to -off. - -=back - - - -=head1 BUGS - - - -=head1 VERSION HISTORY - -1.0 Mon 13 Dec 2004-2005 - -1.0.1 Mon 19 Sep 2005 - - + Better handling of case when foo.text exists, but foo.html doesn't. - It now prints a message and moves on, rather than dying. - - -=head1 COPYRIGHT AND LICENSE - -Copyright (c) 2004-2005 John Gruber -<http://daringfireball.net/> -All rights reserved. - -This is free software; you may redistribute it and/or modify it under -the same terms as Perl itself. - -=cut diff --git a/tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html b/tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html deleted file mode 100644 index 9606860b6..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html +++ /dev/null @@ -1,17 +0,0 @@ -<p>AT&T has an ampersand in their name.</p> - -<p>AT&T is another way to write it.</p> - -<p>This & that.</p> - -<p>4 < 5.</p> - -<p>6 > 5.</p> - -<p>Here's a <a href="http://example.com/?foo=1&bar=2">link</a> with an ampersand in the URL.</p> - -<p>Here's a link with an amersand in the link text: <a href="http://att.com/" title="AT&T">AT&T</a>.</p> - -<p>Here's an inline <a href="/script?foo=1&bar=2">link</a>.</p> - -<p>Here's an inline <a href="/script?foo=1&bar=2">link</a>.</p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text b/tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text deleted file mode 100644 index 0e9527f93..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text +++ /dev/null @@ -1,21 +0,0 @@ -AT&T has an ampersand in their name. - -AT&T is another way to write it. - -This & that. - -4 < 5. - -6 > 5. - -Here's a [link] [1] with an ampersand in the URL. - -Here's a link with an amersand in the link text: [AT&T] [2]. - -Here's an inline [link](/script?foo=1&bar=2). - -Here's an inline [link](</script?foo=1&bar=2>). - - -[1]: http://example.com/?foo=1&bar=2 -[2]: http://att.com/ "AT&T"
\ No newline at end of file diff --git a/tests/MarkdownTest_1.0.3/Tests/Auto links.html b/tests/MarkdownTest_1.0.3/Tests/Auto links.html deleted file mode 100644 index f8df9852c..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Auto links.html +++ /dev/null @@ -1,18 +0,0 @@ -<p>Link: <a href="http://example.com/">http://example.com/</a>.</p> - -<p>With an ampersand: <a href="http://example.com/?foo=1&bar=2">http://example.com/?foo=1&bar=2</a></p> - -<ul> -<li>In a list?</li> -<li><a href="http://example.com/">http://example.com/</a></li> -<li>It should.</li> -</ul> - -<blockquote> - <p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p> -</blockquote> - -<p>Auto-links should not occur here: <code><http://example.com/></code></p> - -<pre><code>or here: <http://example.com/> -</code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Auto links.text b/tests/MarkdownTest_1.0.3/Tests/Auto links.text deleted file mode 100644 index abbc48869..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Auto links.text +++ /dev/null @@ -1,13 +0,0 @@ -Link: <http://example.com/>. - -With an ampersand: <http://example.com/?foo=1&bar=2> - -* In a list? -* <http://example.com/> -* It should. - -> Blockquoted: <http://example.com/> - -Auto-links should not occur here: `<http://example.com/>` - - or here: <http://example.com/>
\ No newline at end of file diff --git a/tests/MarkdownTest_1.0.3/Tests/Backslash escapes.html b/tests/MarkdownTest_1.0.3/Tests/Backslash escapes.html deleted file mode 100644 index 29870dac5..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Backslash escapes.html +++ /dev/null @@ -1,118 +0,0 @@ -<p>These should all get escaped:</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: ></p> - -<p>Hash: #</p> - -<p>Period: .</p> - -<p>Bang: !</p> - -<p>Plus: +</p> - -<p>Minus: -</p> - -<p>These should not, because they occur within a code block:</p> - -<pre><code>Backslash: \\ - -Backtick: \` - -Asterisk: \* - -Underscore: \_ - -Left brace: \{ - -Right brace: \} - -Left bracket: \[ - -Right bracket: \] - -Left paren: \( - -Right paren: \) - -Greater-than: \> - -Hash: \# - -Period: \. - -Bang: \! - -Plus: \+ - -Minus: \- -</code></pre> - -<p>Nor should these, which occur in code spans:</p> - -<p>Backslash: <code>\\</code></p> - -<p>Backtick: <code>\`</code></p> - -<p>Asterisk: <code>\*</code></p> - -<p>Underscore: <code>\_</code></p> - -<p>Left brace: <code>\{</code></p> - -<p>Right brace: <code>\}</code></p> - -<p>Left bracket: <code>\[</code></p> - -<p>Right bracket: <code>\]</code></p> - -<p>Left paren: <code>\(</code></p> - -<p>Right paren: <code>\)</code></p> - -<p>Greater-than: <code>\></code></p> - -<p>Hash: <code>\#</code></p> - -<p>Period: <code>\.</code></p> - -<p>Bang: <code>\!</code></p> - -<p>Plus: <code>\+</code></p> - -<p>Minus: <code>\-</code></p> - - -<p>These should get escaped, even though they're matching pairs for -other Markdown constructs:</p> - -<p>*asterisks*</p> - -<p>_underscores_</p> - -<p>`backticks`</p> - -<p>This is a code span with a literal backslash-backtick sequence: <code>\`</code></p> - -<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p> - -<p>This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.</p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Backslash escapes.text b/tests/MarkdownTest_1.0.3/Tests/Backslash escapes.text deleted file mode 100644 index 5b014cb33..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Backslash escapes.text +++ /dev/null @@ -1,120 +0,0 @@ -These should all get escaped: - -Backslash: \\ - -Backtick: \` - -Asterisk: \* - -Underscore: \_ - -Left brace: \{ - -Right brace: \} - -Left bracket: \[ - -Right bracket: \] - -Left paren: \( - -Right paren: \) - -Greater-than: \> - -Hash: \# - -Period: \. - -Bang: \! - -Plus: \+ - -Minus: \- - - - -These should not, because they occur within a code block: - - Backslash: \\ - - Backtick: \` - - Asterisk: \* - - Underscore: \_ - - Left brace: \{ - - Right brace: \} - - Left bracket: \[ - - Right bracket: \] - - Left paren: \( - - Right paren: \) - - Greater-than: \> - - Hash: \# - - Period: \. - - Bang: \! - - Plus: \+ - - Minus: \- - - -Nor should these, which occur in code spans: - -Backslash: `\\` - -Backtick: `` \` `` - -Asterisk: `\*` - -Underscore: `\_` - -Left brace: `\{` - -Right brace: `\}` - -Left bracket: `\[` - -Right bracket: `\]` - -Left paren: `\(` - -Right paren: `\)` - -Greater-than: `\>` - -Hash: `\#` - -Period: `\.` - -Bang: `\!` - -Plus: `\+` - -Minus: `\-` - - -These should get escaped, even though they're matching pairs for -other Markdown constructs: - -\*asterisks\* - -\_underscores\_ - -\`backticks\` - -This is a code span with a literal backslash-backtick sequence: `` \` `` - -This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>. - -This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>. diff --git a/tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html b/tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html deleted file mode 100644 index 990202a1b..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html +++ /dev/null @@ -1,15 +0,0 @@ -<blockquote> - <p>Example:</p> - -<pre><code>sub status { - print "working"; -} -</code></pre> - - <p>Or:</p> - -<pre><code>sub status { - return "working"; -} -</code></pre> -</blockquote> diff --git a/tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text b/tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text deleted file mode 100644 index c31d17104..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text +++ /dev/null @@ -1,11 +0,0 @@ -> Example: -> -> sub status { -> print "working"; -> } -> -> Or: -> -> sub status { -> return "working"; -> } diff --git a/tests/MarkdownTest_1.0.3/Tests/Code Blocks.html b/tests/MarkdownTest_1.0.3/Tests/Code Blocks.html deleted file mode 100644 index 32703f5cb..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Code Blocks.html +++ /dev/null @@ -1,18 +0,0 @@ -<pre><code>code block on the first line -</code></pre> - -<p>Regular text.</p> - -<pre><code>code block indented by spaces -</code></pre> - -<p>Regular text.</p> - -<pre><code>the lines in this block -all contain trailing spaces -</code></pre> - -<p>Regular Text.</p> - -<pre><code>code block on the last line -</code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Code Blocks.text b/tests/MarkdownTest_1.0.3/Tests/Code Blocks.text deleted file mode 100644 index b54b09285..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Code Blocks.text +++ /dev/null @@ -1,14 +0,0 @@ - code block on the first line - -Regular text. - - code block indented by spaces - -Regular text. - - the lines in this block - all contain trailing spaces - -Regular Text. - - code block on the last line
\ No newline at end of file diff --git a/tests/MarkdownTest_1.0.3/Tests/Code Spans.html b/tests/MarkdownTest_1.0.3/Tests/Code Spans.html deleted file mode 100644 index 4b8afbb70..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Code Spans.html +++ /dev/null @@ -1,6 +0,0 @@ -<p><code><test a="</code> content of attribute <code>"></code></p> - -<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p> - -<p>Here's how you put <code>`backticks`</code> in a code span.</p> - diff --git a/tests/MarkdownTest_1.0.3/Tests/Code Spans.text b/tests/MarkdownTest_1.0.3/Tests/Code Spans.text deleted file mode 100644 index 750a1973d..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Code Spans.text +++ /dev/null @@ -1,6 +0,0 @@ -`<test a="` content of attribute `">` - -Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span> - -Here's how you put `` `backticks` `` in a code span. - diff --git a/tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html b/tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html deleted file mode 100644 index e21ac79a2..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html +++ /dev/null @@ -1,8 +0,0 @@ -<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> diff --git a/tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text b/tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text deleted file mode 100644 index f8a5b27bf..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text +++ /dev/null @@ -1,8 +0,0 @@ -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. diff --git a/tests/MarkdownTest_1.0.3/Tests/Horizontal rules.html b/tests/MarkdownTest_1.0.3/Tests/Horizontal rules.html deleted file mode 100644 index 2dc2ab656..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Horizontal rules.html +++ /dev/null @@ -1,71 +0,0 @@ -<p>Dashes:</p> - -<hr /> - -<hr /> - -<hr /> - -<hr /> - -<pre><code>--- -</code></pre> - -<hr /> - -<hr /> - -<hr /> - -<hr /> - -<pre><code>- - - -</code></pre> - -<p>Asterisks:</p> - -<hr /> - -<hr /> - -<hr /> - -<hr /> - -<pre><code>*** -</code></pre> - -<hr /> - -<hr /> - -<hr /> - -<hr /> - -<pre><code>* * * -</code></pre> - -<p>Underscores:</p> - -<hr /> - -<hr /> - -<hr /> - -<hr /> - -<pre><code>___ -</code></pre> - -<hr /> - -<hr /> - -<hr /> - -<hr /> - -<pre><code>_ _ _ -</code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Horizontal rules.text b/tests/MarkdownTest_1.0.3/Tests/Horizontal rules.text deleted file mode 100644 index 1594bda27..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Horizontal rules.text +++ /dev/null @@ -1,67 +0,0 @@ -Dashes: - ---- - - --- - - --- - - --- - - --- - -- - - - - - - - - - - - - - - - - - - - - - - - - -Asterisks: - -*** - - *** - - *** - - *** - - *** - -* * * - - * * * - - * * * - - * * * - - * * * - - -Underscores: - -___ - - ___ - - ___ - - ___ - - ___ - -_ _ _ - - _ _ _ - - _ _ _ - - _ _ _ - - _ _ _ diff --git a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html b/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html deleted file mode 100644 index 3af9cafb1..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html +++ /dev/null @@ -1,15 +0,0 @@ -<p>Simple block on one line:</p> - -<div>foo</div> - -<p>And nested without indentation:</p> - -<div> -<div> -<div> -foo -</div> -<div style=">"/> -</div> -<div>bar</div> -</div> diff --git a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text b/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text deleted file mode 100644 index 86b7206d2..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text +++ /dev/null @@ -1,15 +0,0 @@ -Simple block on one line: - -<div>foo</div> - -And nested without indentation: - -<div> -<div> -<div> -foo -</div> -<div style=">"/> -</div> -<div>bar</div> -</div> diff --git a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html b/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html deleted file mode 100644 index 6bf78f8fc..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html +++ /dev/null @@ -1,72 +0,0 @@ -<p>Here's a simple block:</p> - -<div> - foo -</div> - -<p>This should be a code block, though:</p> - -<pre><code><div> - foo -</div> -</code></pre> - -<p>As should this:</p> - -<pre><code><div>foo</div> -</code></pre> - -<p>Now, nested:</p> - -<div> - <div> - <div> - foo - </div> - </div> -</div> - -<p>This should just be an HTML comment:</p> - -<!-- Comment --> - -<p>Multiline:</p> - -<!-- -Blah -Blah ---> - -<p>Code block:</p> - -<pre><code><!-- Comment --> -</code></pre> - -<p>Just plain comment, with trailing spaces on the line:</p> - -<!-- foo --> - -<p>Code:</p> - -<pre><code><hr /> -</code></pre> - -<p>Hr's:</p> - -<hr> - -<hr/> - -<hr /> - -<hr> - -<hr/> - -<hr /> - -<hr class="foo" id="bar" /> - -<hr class="foo" id="bar"/> - -<hr class="foo" id="bar" > diff --git a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text b/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text deleted file mode 100644 index 14aa2dc27..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text +++ /dev/null @@ -1,69 +0,0 @@ -Here's a simple block: - -<div> - foo -</div> - -This should be a code block, though: - - <div> - foo - </div> - -As should this: - - <div>foo</div> - -Now, nested: - -<div> - <div> - <div> - foo - </div> - </div> -</div> - -This should just be an HTML comment: - -<!-- Comment --> - -Multiline: - -<!-- -Blah -Blah ---> - -Code block: - - <!-- Comment --> - -Just plain comment, with trailing spaces on the line: - -<!-- foo --> - -Code: - - <hr /> - -Hr's: - -<hr> - -<hr/> - -<hr /> - -<hr> - -<hr/> - -<hr /> - -<hr class="foo" id="bar" /> - -<hr class="foo" id="bar"/> - -<hr class="foo" id="bar" > - diff --git a/tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.html b/tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.html deleted file mode 100644 index 3f167a161..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.html +++ /dev/null @@ -1,13 +0,0 @@ -<p>Paragraph one.</p> - -<!-- This is a simple comment --> - -<!-- - This is another comment. ---> - -<p>Paragraph two.</p> - -<!-- one comment block -- -- with two comments --> - -<p>The end.</p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.text b/tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.text deleted file mode 100644 index 41d830d03..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.text +++ /dev/null @@ -1,13 +0,0 @@ -Paragraph one. - -<!-- This is a simple comment --> - -<!-- - This is another comment. ---> - -Paragraph two. - -<!-- one comment block -- -- with two comments --> - -The end. diff --git a/tests/MarkdownTest_1.0.3/Tests/Links, inline style.html b/tests/MarkdownTest_1.0.3/Tests/Links, inline style.html deleted file mode 100644 index f36607ddd..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Links, inline style.html +++ /dev/null @@ -1,11 +0,0 @@ -<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 has spaces afterward">URL and title</a>.</p> - -<p><a href="">Empty</a>.</p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Links, inline style.text b/tests/MarkdownTest_1.0.3/Tests/Links, inline style.text deleted file mode 100644 index 09017a90c..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Links, inline style.text +++ /dev/null @@ -1,12 +0,0 @@ -Just a [URL](/url/). - -[URL and title](/url/ "title"). - -[URL and title](/url/ "title preceded by two spaces"). - -[URL and title](/url/ "title preceded by a tab"). - -[URL and title](/url/ "title has spaces afterward" ). - - -[Empty](). diff --git a/tests/MarkdownTest_1.0.3/Tests/Links, reference style.html b/tests/MarkdownTest_1.0.3/Tests/Links, reference style.html deleted file mode 100644 index 8e70c32f4..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Links, reference style.html +++ /dev/null @@ -1,52 +0,0 @@ -<p>Foo <a href="/url/" title="Title">bar</a>.</p> - -<p>Foo <a href="/url/" title="Title">bar</a>.</p> - -<p>Foo <a href="/url/" title="Title">bar</a>.</p> - -<p>With <a href="/url/">embedded [brackets]</a>.</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>Indented [four][] times.</p> - -<pre><code>[four]: /url -</code></pre> - -<hr /> - -<p><a href="foo">this</a> should work</p> - -<p>So should <a href="foo">this</a>.</p> - -<p>And <a href="foo">this</a>.</p> - -<p>And <a href="foo">this</a>.</p> - -<p>And <a href="foo">this</a>.</p> - -<p>But not [that] [].</p> - -<p>Nor [that][].</p> - -<p>Nor [that].</p> - -<p>[Something in brackets like <a href="foo">this</a> should work]</p> - -<p>[Same with <a href="foo">this</a>.]</p> - -<p>In this case, <a href="/somethingelse/">this</a> points to something else.</p> - -<p>Backslashing should suppress [this] and [this].</p> - -<hr /> - -<p>Here's one where the <a href="/url/">link -breaks</a> across lines.</p> - -<p>Here's another where the <a href="/url/">link -breaks</a> across lines, but with a line-ending space.</p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Links, reference style.text b/tests/MarkdownTest_1.0.3/Tests/Links, reference style.text deleted file mode 100644 index 341ec88e3..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Links, reference style.text +++ /dev/null @@ -1,71 +0,0 @@ -Foo [bar] [1]. - -Foo [bar][1]. - -Foo [bar] -[1]. - -[1]: /url/ "Title" - - -With [embedded [brackets]] [b]. - - -Indented [once][]. - -Indented [twice][]. - -Indented [thrice][]. - -Indented [four][] times. - - [once]: /url - - [twice]: /url - - [thrice]: /url - - [four]: /url - - -[b]: /url/ - -* * * - -[this] [this] should work - -So should [this][this]. - -And [this] []. - -And [this][]. - -And [this]. - -But not [that] []. - -Nor [that][]. - -Nor [that]. - -[Something in brackets like [this][] should work] - -[Same with [this].] - -In this case, [this](/somethingelse/) points to something else. - -Backslashing should suppress \[this] and [this\]. - -[this]: foo - - -* * * - -Here's one where the [link -breaks] across lines. - -Here's another where the [link -breaks] across lines, but with a line-ending space. - - -[link breaks]: /url/ diff --git a/tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.html b/tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.html deleted file mode 100644 index bf81e939f..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.html +++ /dev/null @@ -1,9 +0,0 @@ -<p>This is the <a href="/simple">simple case</a>.</p> - -<p>This one has a <a href="/foo">line -break</a>.</p> - -<p>This one has a <a href="/foo">line -break</a> with a line-ending space.</p> - -<p><a href="/that">this</a> and the <a href="/other">other</a></p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.text b/tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.text deleted file mode 100644 index 8c44c98fe..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.text +++ /dev/null @@ -1,20 +0,0 @@ -This is the [simple case]. - -[simple case]: /simple - - - -This one has a [line -break]. - -This one has a [line -break] with a line-ending space. - -[line break]: /foo - - -[this] [that] and the [other] - -[this]: /this -[that]: /that -[other]: /other diff --git a/tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html b/tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html deleted file mode 100644 index 611c1ac61..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html +++ /dev/null @@ -1,3 +0,0 @@ -<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p> - -<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p> diff --git a/tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text b/tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text deleted file mode 100644 index 29d0e4235..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text +++ /dev/null @@ -1,7 +0,0 @@ -Foo [bar][]. - -Foo [bar](/url/ "Title with "quotes" inside"). - - - [bar]: /url/ "Title with "quotes" inside" - diff --git a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html b/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html deleted file mode 100644 index d5bdbb29a..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html +++ /dev/null @@ -1,314 +0,0 @@ -<h1>Markdown: Basics</h1> - -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a class="selected" title="Markdown Basics">Basics</a></li> - <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> - -<h2>Getting the Gist of Markdown's Formatting Syntax</h2> - -<p>This page offers a brief overview of what it's like to use Markdown. -The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for -every feature, but Markdown should be very easy to pick up simply by -looking at a few examples of it in action. The examples on this page -are written in a before/after style, showing example syntax and the -HTML output produced by Markdown.</p> - -<p>It's also helpful to simply try Markdown out; the <a href="/projects/markdown/dingus" title="Markdown Dingus">Dingus</a> is a -web application that allows you type your own Markdown-formatted text -and translate it to XHTML.</p> - -<p><strong>Note:</strong> This document is itself written using Markdown; you -can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p> - -<h2>Paragraphs, Headers, Blockquotes</h2> - -<p>A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs.</p> - -<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>. -Setext-style headers for <code><h1></code> and <code><h2></code> are created by -"underlining" with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively. -To create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the -beginning of the line -- the number of hashes equals the resulting -HTML header level.</p> - -<p>Blockquotes are indicated using email-style '<code>></code>' angle brackets.</p> - -<p>Markdown:</p> - -<pre><code>A First Level Header -==================== - -A Second Level Header ---------------------- - -Now is the time for all good men to come to -the aid of their country. This is just a -regular paragraph. - -The quick brown fox jumped over the lazy -dog's back. - -### Header 3 - -> This is a blockquote. -> -> This is the second paragraph in the blockquote. -> -> ## This is an H2 in a blockquote -</code></pre> - -<p>Output:</p> - -<pre><code><h1>A First Level Header</h1> - -<h2>A Second Level Header</h2> - -<p>Now is the time for all good men to come to -the aid of their country. This is just a -regular paragraph.</p> - -<p>The quick brown fox jumped over the lazy -dog's back.</p> - -<h3>Header 3</h3> - -<blockquote> - <p>This is a blockquote.</p> - - <p>This is the second paragraph in the blockquote.</p> - - <h2>This is an H2 in a blockquote</h2> -</blockquote> -</code></pre> - -<h3>Phrase Emphasis</h3> - -<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p> - -<p>Markdown:</p> - -<pre><code>Some of these words *are emphasized*. -Some of these words _are emphasized also_. - -Use two asterisks for **strong emphasis**. -Or, if you prefer, __use two underscores instead__. -</code></pre> - -<p>Output:</p> - -<pre><code><p>Some of these words <em>are emphasized</em>. -Some of these words <em>are emphasized also</em>.</p> - -<p>Use two asterisks for <strong>strong emphasis</strong>. -Or, if you prefer, <strong>use two underscores instead</strong>.</p> -</code></pre> - -<h2>Lists</h2> - -<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>, -<code>+</code>, and <code>-</code>) as list markers. These three markers are -interchangable; this:</p> - -<pre><code>* Candy. -* Gum. -* Booze. -</code></pre> - -<p>this:</p> - -<pre><code>+ Candy. -+ Gum. -+ Booze. -</code></pre> - -<p>and this:</p> - -<pre><code>- Candy. -- Gum. -- Booze. -</code></pre> - -<p>all produce the same output:</p> - -<pre><code><ul> -<li>Candy.</li> -<li>Gum.</li> -<li>Booze.</li> -</ul> -</code></pre> - -<p>Ordered (numbered) lists use regular numbers, followed by periods, as -list markers:</p> - -<pre><code>1. Red -2. Green -3. Blue -</code></pre> - -<p>Output:</p> - -<pre><code><ol> -<li>Red</li> -<li>Green</li> -<li>Blue</li> -</ol> -</code></pre> - -<p>If you put blank lines between items, you'll get <code><p></code> tags for the -list item text. You can create multi-paragraph list items by indenting -the paragraphs by 4 spaces or 1 tab:</p> - -<pre><code>* A list item. - - With multiple paragraphs. - -* Another item in the list. -</code></pre> - -<p>Output:</p> - -<pre><code><ul> -<li><p>A list item.</p> -<p>With multiple paragraphs.</p></li> -<li><p>Another item in the list.</p></li> -</ul> -</code></pre> - -<h3>Links</h3> - -<p>Markdown supports two styles for creating links: <em>inline</em> and -<em>reference</em>. With both styles, you use square brackets to delimit the -text you want to turn into a link.</p> - -<p>Inline-style links use parentheses immediately after the link text. -For example:</p> - -<pre><code>This is an [example link](http://example.com/). -</code></pre> - -<p>Output:</p> - -<pre><code><p>This is an <a href="http://example.com/"> -example link</a>.</p> -</code></pre> - -<p>Optionally, you may include a title attribute in the parentheses:</p> - -<pre><code>This is an [example link](http://example.com/ "With a Title"). -</code></pre> - -<p>Output:</p> - -<pre><code><p>This is an <a href="http://example.com/" title="With a Title"> -example link</a>.</p> -</code></pre> - -<p>Reference-style links allow you to refer to your links by names, which -you define elsewhere in your document:</p> - -<pre><code>I get 10 times more traffic from [Google][1] than from -[Yahoo][2] or [MSN][3]. - -[1]: http://google.com/ "Google" -[2]: http://search.yahoo.com/ "Yahoo Search" -[3]: http://search.msn.com/ "MSN Search" -</code></pre> - -<p>Output:</p> - -<pre><code><p>I get 10 times more traffic from <a href="http://google.com/" -title="Google">Google</a> than from <a href="http://search.yahoo.com/" -title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" -title="MSN Search">MSN</a>.</p> -</code></pre> - -<p>The title attribute is optional. Link names may contain letters, -numbers and spaces, but are <em>not</em> case sensitive:</p> - -<pre><code>I start my morning with a cup of coffee and -[The New York Times][NY Times]. - -[ny times]: http://www.nytimes.com/ -</code></pre> - -<p>Output:</p> - -<pre><code><p>I start my morning with a cup of coffee and -<a href="http://www.nytimes.com/">The New York Times</a>.</p> -</code></pre> - -<h3>Images</h3> - -<p>Image syntax is very much like link syntax.</p> - -<p>Inline (titles are optional):</p> - -<pre><code> -</code></pre> - -<p>Reference-style:</p> - -<pre><code>![alt text][id] - -[id]: /path/to/img.jpg "Title" -</code></pre> - -<p>Both of the above examples produce the same output:</p> - -<pre><code><img src="/path/to/img.jpg" alt="alt text" title="Title" /> -</code></pre> - -<h3>Code</h3> - -<p>In a regular paragraph, you can create code span by wrapping text in -backtick quotes. Any ampersands (<code>&</code>) and angle brackets (<code><</code> or -<code>></code>) will automatically be translated into HTML entities. This makes -it easy to use Markdown to write about HTML example code:</p> - -<pre><code>I strongly recommend against using any `<blink>` tags. - -I wish SmartyPants used named entities like `&mdash;` -instead of decimal-encoded entites like `&#8212;`. -</code></pre> - -<p>Output:</p> - -<pre><code><p>I strongly recommend against using any -<code>&lt;blink&gt;</code> tags.</p> - -<p>I wish SmartyPants used named entities like -<code>&amp;mdash;</code> instead of decimal-encoded -entites like <code>&amp;#8212;</code>.</p> -</code></pre> - -<p>To specify an entire block of pre-formatted code, indent every line of -the block by 4 spaces or 1 tab. Just like with code spans, <code>&</code>, <code><</code>, -and <code>></code> characters will be escaped automatically.</p> - -<p>Markdown:</p> - -<pre><code>If you want your page to validate under XHTML 1.0 Strict, -you've got to put paragraph tags in your blockquotes: - - <blockquote> - <p>For example.</p> - </blockquote> -</code></pre> - -<p>Output:</p> - -<pre><code><p>If you want your page to validate under XHTML 1.0 Strict, -you've got to put paragraph tags in your blockquotes:</p> - -<pre><code>&lt;blockquote&gt; - &lt;p&gt;For example.&lt;/p&gt; -&lt;/blockquote&gt; -</code></pre> -</code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text b/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text deleted file mode 100644 index 486055ca7..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text +++ /dev/null @@ -1,306 +0,0 @@ -Markdown: Basics -================ - -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a class="selected" title="Markdown Basics">Basics</a></li> - <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> - - -Getting the Gist of Markdown's Formatting Syntax ------------------------------------------------- - -This page offers a brief overview of what it's like to use Markdown. -The [syntax page] [s] provides complete, detailed documentation for -every feature, but Markdown should be very easy to pick up simply by -looking at a few examples of it in action. The examples on this page -are written in a before/after style, showing example syntax and the -HTML output produced by Markdown. - -It's also helpful to simply try Markdown out; the [Dingus] [d] is a -web application that allows you type your own Markdown-formatted text -and translate it to XHTML. - -**Note:** This document is itself written using Markdown; you -can [see the source for it by adding '.text' to the URL] [src]. - - [s]: /projects/markdown/syntax "Markdown Syntax" - [d]: /projects/markdown/dingus "Markdown Dingus" - [src]: /projects/markdown/basics.text - - -## Paragraphs, Headers, Blockquotes ## - -A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs. - -Markdown offers two styles of headers: *Setext* and *atx*. -Setext-style headers for `<h1>` and `<h2>` are created by -"underlining" with equal signs (`=`) and hyphens (`-`), respectively. -To create an atx-style header, you put 1-6 hash marks (`#`) at the -beginning of the line -- the number of hashes equals the resulting -HTML header level. - -Blockquotes are indicated using email-style '`>`' angle brackets. - -Markdown: - - A First Level Header - ==================== - - A Second Level Header - --------------------- - - Now is the time for all good men to come to - the aid of their country. This is just a - regular paragraph. - - The quick brown fox jumped over the lazy - dog's back. - - ### Header 3 - - > This is a blockquote. - > - > This is the second paragraph in the blockquote. - > - > ## This is an H2 in a blockquote - - -Output: - - <h1>A First Level Header</h1> - - <h2>A Second Level Header</h2> - - <p>Now is the time for all good men to come to - the aid of their country. This is just a - regular paragraph.</p> - - <p>The quick brown fox jumped over the lazy - dog's back.</p> - - <h3>Header 3</h3> - - <blockquote> - <p>This is a blockquote.</p> - - <p>This is the second paragraph in the blockquote.</p> - - <h2>This is an H2 in a blockquote</h2> - </blockquote> - - - -### Phrase Emphasis ### - -Markdown uses asterisks and underscores to indicate spans of emphasis. - -Markdown: - - Some of these words *are emphasized*. - Some of these words _are emphasized also_. - - Use two asterisks for **strong emphasis**. - Or, if you prefer, __use two underscores instead__. - -Output: - - <p>Some of these words <em>are emphasized</em>. - Some of these words <em>are emphasized also</em>.</p> - - <p>Use two asterisks for <strong>strong emphasis</strong>. - Or, if you prefer, <strong>use two underscores instead</strong>.</p> - - - -## Lists ## - -Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, -`+`, and `-`) as list markers. These three markers are -interchangable; this: - - * Candy. - * Gum. - * Booze. - -this: - - + Candy. - + Gum. - + Booze. - -and this: - - - Candy. - - Gum. - - Booze. - -all produce the same output: - - <ul> - <li>Candy.</li> - <li>Gum.</li> - <li>Booze.</li> - </ul> - -Ordered (numbered) lists use regular numbers, followed by periods, as -list markers: - - 1. Red - 2. Green - 3. Blue - -Output: - - <ol> - <li>Red</li> - <li>Green</li> - <li>Blue</li> - </ol> - -If you put blank lines between items, you'll get `<p>` tags for the -list item text. You can create multi-paragraph list items by indenting -the paragraphs by 4 spaces or 1 tab: - - * A list item. - - With multiple paragraphs. - - * Another item in the list. - -Output: - - <ul> - <li><p>A list item.</p> - <p>With multiple paragraphs.</p></li> - <li><p>Another item in the list.</p></li> - </ul> - - - -### Links ### - -Markdown supports two styles for creating links: *inline* and -*reference*. With both styles, you use square brackets to delimit the -text you want to turn into a link. - -Inline-style links use parentheses immediately after the link text. -For example: - - This is an [example link](http://example.com/). - -Output: - - <p>This is an <a href="http://example.com/"> - example link</a>.</p> - -Optionally, you may include a title attribute in the parentheses: - - This is an [example link](http://example.com/ "With a Title"). - -Output: - - <p>This is an <a href="http://example.com/" title="With a Title"> - example link</a>.</p> - -Reference-style links allow you to refer to your links by names, which -you define elsewhere in your document: - - I get 10 times more traffic from [Google][1] than from - [Yahoo][2] or [MSN][3]. - - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" - -Output: - - <p>I get 10 times more traffic from <a href="http://google.com/" - title="Google">Google</a> than from <a href="http://search.yahoo.com/" - title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" - title="MSN Search">MSN</a>.</p> - -The title attribute is optional. Link names may contain letters, -numbers and spaces, but are *not* case sensitive: - - I start my morning with a cup of coffee and - [The New York Times][NY Times]. - - [ny times]: http://www.nytimes.com/ - -Output: - - <p>I start my morning with a cup of coffee and - <a href="http://www.nytimes.com/">The New York Times</a>.</p> - - -### Images ### - -Image syntax is very much like link syntax. - -Inline (titles are optional): - -  - -Reference-style: - - ![alt text][id] - - [id]: /path/to/img.jpg "Title" - -Both of the above examples produce the same output: - - <img src="/path/to/img.jpg" alt="alt text" title="Title" /> - - - -### Code ### - -In a regular paragraph, you can create code span by wrapping text in -backtick quotes. Any ampersands (`&`) and angle brackets (`<` or -`>`) will automatically be translated into HTML entities. This makes -it easy to use Markdown to write about HTML example code: - - I strongly recommend against using any `<blink>` tags. - - I wish SmartyPants used named entities like `—` - instead of decimal-encoded entites like `—`. - -Output: - - <p>I strongly recommend against using any - <code><blink></code> tags.</p> - - <p>I wish SmartyPants used named entities like - <code>&mdash;</code> instead of decimal-encoded - entites like <code>&#8212;</code>.</p> - - -To specify an entire block of pre-formatted code, indent every line of -the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`, -and `>` characters will be escaped automatically. - -Markdown: - - If you want your page to validate under XHTML 1.0 Strict, - you've got to put paragraph tags in your blockquotes: - - <blockquote> - <p>For example.</p> - </blockquote> - -Output: - - <p>If you want your page to validate under XHTML 1.0 Strict, - you've got to put paragraph tags in your blockquotes:</p> - - <pre><code><blockquote> - <p>For example.</p> - </blockquote> - </code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html b/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html deleted file mode 100644 index 5c01306cc..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html +++ /dev/null @@ -1,942 +0,0 @@ -<h1>Markdown: Syntax</h1> - -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li> - <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> - -<ul> -<li><a href="#overview">Overview</a> -<ul> -<li><a href="#philosophy">Philosophy</a></li> -<li><a href="#html">Inline HTML</a></li> -<li><a href="#autoescape">Automatic Escaping for Special Characters</a></li> -</ul></li> -<li><a href="#block">Block Elements</a> -<ul> -<li><a href="#p">Paragraphs and Line Breaks</a></li> -<li><a href="#header">Headers</a></li> -<li><a href="#blockquote">Blockquotes</a></li> -<li><a href="#list">Lists</a></li> -<li><a href="#precode">Code Blocks</a></li> -<li><a href="#hr">Horizontal Rules</a></li> -</ul></li> -<li><a href="#span">Span Elements</a> -<ul> -<li><a href="#link">Links</a></li> -<li><a href="#em">Emphasis</a></li> -<li><a href="#code">Code</a></li> -<li><a href="#img">Images</a></li> -</ul></li> -<li><a href="#misc">Miscellaneous</a> -<ul> -<li><a href="#backslash">Backslash Escapes</a></li> -<li><a href="#autolink">Automatic Links</a></li> -</ul></li> -</ul> - -<p><strong>Note:</strong> This document is itself written using Markdown; you -can <a href="/projects/markdown/syntax.text">see the source for it by adding '.text' to the URL</a>.</p> - -<hr /> - -<h2 id="overview">Overview</h2> - -<h3 id="philosophy">Philosophy</h3> - -<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p> - -<p>Readability, however, is emphasized above all else. A Markdown-formatted -document should be publishable as-is, as plain text, without looking -like it's been marked up with tags or formatting instructions. While -Markdown's syntax has been influenced by several existing text-to-HTML -filters -- including <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a>, <a href="http://www.aaronsw.com/2002/atx/">atx</a>, <a href="http://textism.com/tools/textile/">Textile</a>, <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, -<a href="http://www.triptico.com/software/grutatxt.html">Grutatext</a>, and <a href="http://ettext.taint.org/doc/">EtText</a> -- the single biggest source of -inspiration for Markdown's syntax is the format of plain text email.</p> - -<p>To this end, Markdown's syntax is comprised entirely of punctuation -characters, which punctuation characters have been carefully chosen so -as to look like what they mean. E.g., asterisks around a word actually -look like *emphasis*. Markdown lists look like, well, lists. Even -blockquotes look like quoted passages of text, assuming you've ever -used email.</p> - -<h3 id="html">Inline HTML</h3> - -<p>Markdown's syntax is intended for one purpose: to be used as a -format for <em>writing</em> for the web.</p> - -<p>Markdown is not a replacement for HTML, or even close to it. Its -syntax is very small, corresponding only to a very small subset of -HTML tags. The idea is <em>not</em> to create a syntax that makes it easier -to insert HTML tags. In my opinion, HTML tags are already easy to -insert. The idea for Markdown is to make it easy to read, write, and -edit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em> -format. Thus, Markdown's formatting syntax only addresses issues that -can be conveyed in plain text.</p> - -<p>For any markup that is not covered by Markdown's syntax, you simply -use HTML itself. There's no need to preface it or delimit it to -indicate that you're switching from Markdown to HTML; you just use -the tags.</p> - -<p>The only restrictions are that block-level HTML elements -- e.g. <code><div></code>, -<code><table></code>, <code><pre></code>, <code><p></code>, etc. -- must be separated from surrounding -content by blank lines, and the start and end tags of the block should -not be indented with tabs or spaces. Markdown is smart enough not -to add extra (unwanted) <code><p></code> tags around HTML block-level tags.</p> - -<p>For example, to add an HTML table to a Markdown article:</p> - -<pre><code>This is a regular paragraph. - -<table> - <tr> - <td>Foo</td> - </tr> -</table> - -This is another regular paragraph. -</code></pre> - -<p>Note that Markdown formatting syntax is not processed within block-level -HTML tags. E.g., you can't use Markdown-style <code>*emphasis*</code> inside an -HTML block.</p> - -<p>Span-level HTML tags -- e.g. <code><span></code>, <code><cite></code>, or <code><del></code> -- can be -used anywhere in a Markdown paragraph, list item, or header. If you -want, you can even use HTML tags instead of Markdown formatting; e.g. if -you'd prefer to use HTML <code><a></code> or <code><img></code> tags instead of Markdown's -link or image syntax, go right ahead.</p> - -<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within -span-level tags.</p> - -<h3 id="autoescape">Automatic Escaping for Special Characters</h3> - -<p>In HTML, there are two characters that demand special treatment: <code><</code> -and <code>&</code>. Left angle brackets are used to start tags; ampersands are -used to denote HTML entities. If you want to use them as literal -characters, you must escape them as entities, e.g. <code>&lt;</code>, and -<code>&amp;</code>.</p> - -<p>Ampersands in particular are bedeviling for web writers. If you want to -write about 'AT&T', you need to write '<code>AT&amp;T</code>'. You even need to -escape ampersands within URLs. Thus, if you want to link to:</p> - -<pre><code>http://images.google.com/images?num=30&q=larry+bird -</code></pre> - -<p>you need to encode the URL as:</p> - -<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird -</code></pre> - -<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to -forget, and is probably the single most common source of HTML validation -errors in otherwise well-marked-up web sites.</p> - -<p>Markdown allows you to use these characters naturally, taking care of -all the necessary escaping for you. If you use an ampersand as part of -an HTML entity, it remains unchanged; otherwise it will be translated -into <code>&amp;</code>.</p> - -<p>So, if you want to include a copyright symbol in your article, you can write:</p> - -<pre><code>&copy; -</code></pre> - -<p>and Markdown will leave it alone. But if you write:</p> - -<pre><code>AT&T -</code></pre> - -<p>Markdown will translate it to:</p> - -<pre><code>AT&amp;T -</code></pre> - -<p>Similarly, because Markdown supports <a href="#html">inline HTML</a>, if you use -angle brackets as delimiters for HTML tags, Markdown will treat them as -such. But if you write:</p> - -<pre><code>4 < 5 -</code></pre> - -<p>Markdown will translate it to:</p> - -<pre><code>4 &lt; 5 -</code></pre> - -<p>However, inside Markdown code spans and blocks, angle brackets and -ampersands are <em>always</em> encoded automatically. This makes it easy to use -Markdown to write about HTML code. (As opposed to raw HTML, which is a -terrible format for writing about HTML syntax, because every single <code><</code> -and <code>&</code> in your example code needs to be escaped.)</p> - -<hr /> - -<h2 id="block">Block Elements</h2> - -<h3 id="p">Paragraphs and Line Breaks</h3> - -<p>A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing but spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs.</p> - -<p>The implication of the "one or more consecutive lines of text" rule is -that Markdown supports "hard-wrapped" text paragraphs. This differs -significantly from most other text-to-HTML formatters (including Movable -Type's "Convert Line Breaks" option) which translate every line break -character in a paragraph into a <code><br /></code> tag.</p> - -<p>When you <em>do</em> want to insert a <code><br /></code> break tag using Markdown, you -end a line with two or more spaces, then type return.</p> - -<p>Yes, this takes a tad more effort to create a <code><br /></code>, but a simplistic -"every line break is a <code><br /></code>" rule wouldn't work for Markdown. -Markdown's email-style <a href="#blockquote">blockquoting</a> and multi-paragraph <a href="#list">list items</a> -work best -- and look better -- when you format them with hard breaks.</p> - -<h3 id="header">Headers</h3> - -<p>Markdown supports two styles of headers, <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a> and <a href="http://www.aaronsw.com/2002/atx/">atx</a>.</p> - -<p>Setext-style headers are "underlined" using equal signs (for first-level -headers) and dashes (for second-level headers). For example:</p> - -<pre><code>This is an H1 -============= - -This is an H2 -------------- -</code></pre> - -<p>Any number of underlining <code>=</code>'s or <code>-</code>'s will work.</p> - -<p>Atx-style headers use 1-6 hash characters at the start of the line, -corresponding to header levels 1-6. For example:</p> - -<pre><code># This is an H1 - -## This is an H2 - -###### This is an H6 -</code></pre> - -<p>Optionally, you may "close" atx-style headers. This is purely -cosmetic -- you can use this if you think it looks better. The -closing hashes don't even need to match the number of hashes -used to open the header. (The number of opening hashes -determines the header level.) :</p> - -<pre><code># This is an H1 # - -## This is an H2 ## - -### This is an H3 ###### -</code></pre> - -<h3 id="blockquote">Blockquotes</h3> - -<p>Markdown uses email-style <code>></code> characters for blockquoting. If you're -familiar with quoting passages of text in an email message, then you -know how to create a blockquote in Markdown. It looks best if you hard -wrap the text and put a <code>></code> before every line:</p> - -<pre><code>> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, -> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. -> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. -> -> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse -> id sem consectetuer libero luctus adipiscing. -</code></pre> - -<p>Markdown allows you to be lazy and only put the <code>></code> before the first -line of a hard-wrapped paragraph:</p> - -<pre><code>> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, -consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. -Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - -> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse -id sem consectetuer libero luctus adipiscing. -</code></pre> - -<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by -adding additional levels of <code>></code>:</p> - -<pre><code>> This is the first level of quoting. -> -> > This is nested blockquote. -> -> Back to the first level. -</code></pre> - -<p>Blockquotes can contain other Markdown elements, including headers, lists, -and code blocks:</p> - -<pre><code>> ## This is a header. -> -> 1. This is the first list item. -> 2. This is the second list item. -> -> Here's some example code: -> -> return shell_exec("echo $input | $markdown_script"); -</code></pre> - -<p>Any decent text editor should make email-style quoting easy. For -example, with BBEdit, you can make a selection and choose Increase -Quote Level from the Text menu.</p> - -<h3 id="list">Lists</h3> - -<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p> - -<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably --- as list markers:</p> - -<pre><code>* Red -* Green -* Blue -</code></pre> - -<p>is equivalent to:</p> - -<pre><code>+ Red -+ Green -+ Blue -</code></pre> - -<p>and:</p> - -<pre><code>- Red -- Green -- Blue -</code></pre> - -<p>Ordered lists use numbers followed by periods:</p> - -<pre><code>1. Bird -2. McHale -3. Parish -</code></pre> - -<p>It's important to note that the actual numbers you use to mark the -list have no effect on the HTML output Markdown produces. The HTML -Markdown produces from the above list is:</p> - -<pre><code><ol> -<li>Bird</li> -<li>McHale</li> -<li>Parish</li> -</ol> -</code></pre> - -<p>If you instead wrote the list in Markdown like this:</p> - -<pre><code>1. Bird -1. McHale -1. Parish -</code></pre> - -<p>or even:</p> - -<pre><code>3. Bird -1. McHale -8. Parish -</code></pre> - -<p>you'd get the exact same HTML output. The point is, if you want to, -you can use ordinal numbers in your ordered Markdown lists, so that -the numbers in your source match the numbers in your published HTML. -But if you want to be lazy, you don't have to.</p> - -<p>If you do use lazy list numbering, however, you should still start the -list with the number 1. At some point in the future, Markdown may support -starting ordered lists at an arbitrary number.</p> - -<p>List markers typically start at the left margin, but may be indented by -up to three spaces. List markers must be followed by one or more spaces -or a tab.</p> - -<p>To make lists look nice, you can wrap items with hanging indents:</p> - -<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. -* Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. -</code></pre> - -<p>But if you want to be lazy, you don't have to:</p> - -<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit. -Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, -viverra nec, fringilla in, laoreet vitae, risus. -* Donec sit amet nisl. Aliquam semper ipsum sit amet velit. -Suspendisse id sem consectetuer libero luctus adipiscing. -</code></pre> - -<p>If list items are separated by blank lines, Markdown will wrap the -items in <code><p></code> tags in the HTML output. For example, this input:</p> - -<pre><code>* Bird -* Magic -</code></pre> - -<p>will turn into:</p> - -<pre><code><ul> -<li>Bird</li> -<li>Magic</li> -</ul> -</code></pre> - -<p>But this:</p> - -<pre><code>* Bird - -* Magic -</code></pre> - -<p>will turn into:</p> - -<pre><code><ul> -<li><p>Bird</p></li> -<li><p>Magic</p></li> -</ul> -</code></pre> - -<p>List items may consist of multiple paragraphs. Each subsequent -paragraph in a list item must be intended by either 4 spaces -or one tab:</p> - -<pre><code>1. This is a list item with two paragraphs. Lorem ipsum dolor - sit amet, consectetuer adipiscing elit. Aliquam hendrerit - mi posuere lectus. - - Vestibulum enim wisi, viverra nec, fringilla in, laoreet - vitae, risus. Donec sit amet nisl. Aliquam semper ipsum - sit amet velit. - -2. Suspendisse id sem consectetuer libero luctus adipiscing. -</code></pre> - -<p>It looks nice if you indent every line of the subsequent -paragraphs, but here again, Markdown will allow you to be -lazy:</p> - -<pre><code>* This is a list item with two paragraphs. - - This is the second paragraph in the list item. You're -only required to indent the first line. Lorem ipsum dolor -sit amet, consectetuer adipiscing elit. - -* Another item in the same list. -</code></pre> - -<p>To put a blockquote within a list item, the blockquote's <code>></code> -delimiters need to be indented:</p> - -<pre><code>* A list item with a blockquote: - - > This is a blockquote - > inside a list item. -</code></pre> - -<p>To put a code block within a list item, the code block needs -to be indented <em>twice</em> -- 8 spaces or two tabs:</p> - -<pre><code>* A list item with a code block: - - <code goes here> -</code></pre> - -<p>It's worth noting that it's possible to trigger an ordered list by -accident, by writing something like this:</p> - -<pre><code>1986. What a great season. -</code></pre> - -<p>In other words, a <em>number-period-space</em> sequence at the beginning of a -line. To avoid this, you can backslash-escape the period:</p> - -<pre><code>1986\. What a great season. -</code></pre> - -<h3 id="precode">Code Blocks</h3> - -<p>Pre-formatted code blocks are used for writing about programming or -markup source code. Rather than forming normal paragraphs, the lines -of a code block are interpreted literally. Markdown wraps a code block -in both <code><pre></code> and <code><code></code> tags.</p> - -<p>To produce a code block in Markdown, simply indent every line of the -block by at least 4 spaces or 1 tab. For example, given this input:</p> - -<pre><code>This is a normal paragraph: - - This is a code block. -</code></pre> - -<p>Markdown will generate:</p> - -<pre><code><p>This is a normal paragraph:</p> - -<pre><code>This is a code block. -</code></pre> -</code></pre> - -<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each -line of the code block. For example, this:</p> - -<pre><code>Here is an example of AppleScript: - - tell application "Foo" - beep - end tell -</code></pre> - -<p>will turn into:</p> - -<pre><code><p>Here is an example of AppleScript:</p> - -<pre><code>tell application "Foo" - beep -end tell -</code></pre> -</code></pre> - -<p>A code block continues until it reaches a line that is not indented -(or the end of the article).</p> - -<p>Within a code block, ampersands (<code>&</code>) and angle brackets (<code><</code> and <code>></code>) -are automatically converted into HTML entities. This makes it very -easy to include example HTML source code using Markdown -- just paste -it and indent it, and Markdown will handle the hassle of encoding the -ampersands and angle brackets. For example, this:</p> - -<pre><code> <div class="footer"> - &copy; 2004 Foo Corporation - </div> -</code></pre> - -<p>will turn into:</p> - -<pre><code><pre><code>&lt;div class="footer"&gt; - &amp;copy; 2004 Foo Corporation -&lt;/div&gt; -</code></pre> -</code></pre> - -<p>Regular Markdown syntax is not processed within code blocks. E.g., -asterisks are just literal asterisks within a code block. This means -it's also easy to use Markdown to write about Markdown's own syntax.</p> - -<h3 id="hr">Horizontal Rules</h3> - -<p>You can produce a horizontal rule tag (<code><hr /></code>) by placing three or -more hyphens, asterisks, or underscores on a line by themselves. If you -wish, you may use spaces between the hyphens or asterisks. Each of the -following lines will produce a horizontal rule:</p> - -<pre><code>* * * - -*** - -***** - -- - - - ---------------------------------------- - -_ _ _ -</code></pre> - -<hr /> - -<h2 id="span">Span Elements</h2> - -<h3 id="link">Links</h3> - -<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p> - -<p>In both styles, the link text is delimited by [square brackets].</p> - -<p>To create an inline link, use a set of regular parentheses immediately -after the link text's closing square bracket. Inside the parentheses, -put the URL where you want the link to point, along with an <em>optional</em> -title for the link, surrounded in quotes. For example:</p> - -<pre><code>This is [an example](http://example.com/ "Title") inline link. - -[This link](http://example.net/) has no title attribute. -</code></pre> - -<p>Will produce:</p> - -<pre><code><p>This is <a href="http://example.com/" title="Title"> -an example</a> inline link.</p> - -<p><a href="http://example.net/">This link</a> has no -title attribute.</p> -</code></pre> - -<p>If you're referring to a local resource on the same server, you can -use relative paths:</p> - -<pre><code>See my [About](/about/) page for details. -</code></pre> - -<p>Reference-style links use a second set of square brackets, inside -which you place a label of your choosing to identify the link:</p> - -<pre><code>This is [an example][id] reference-style link. -</code></pre> - -<p>You can optionally use a space to separate the sets of brackets:</p> - -<pre><code>This is [an example] [id] reference-style link. -</code></pre> - -<p>Then, anywhere in the document, you define your link label like this, -on a line by itself:</p> - -<pre><code>[id]: http://example.com/ "Optional Title Here" -</code></pre> - -<p>That is:</p> - -<ul> -<li>Square brackets containing the link identifier (optionally -indented from the left margin using up to three spaces);</li> -<li>followed by a colon;</li> -<li>followed by one or more spaces (or tabs);</li> -<li>followed by the URL for the link;</li> -<li>optionally followed by a title attribute for the link, enclosed -in double or single quotes.</li> -</ul> - -<p>The link URL may, optionally, be surrounded by angle brackets:</p> - -<pre><code>[id]: <http://example.com/> "Optional Title Here" -</code></pre> - -<p>You can put the title attribute on the next line and use extra spaces -or tabs for padding, which tends to look better with longer URLs:</p> - -<pre><code>[id]: http://example.com/longish/path/to/resource/here - "Optional Title Here" -</code></pre> - -<p>Link definitions are only used for creating links during Markdown -processing, and are stripped from your document in the HTML output.</p> - -<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p> - -<pre><code>[link text][a] -[link text][A] -</code></pre> - -<p>are equivalent.</p> - -<p>The <em>implicit link name</em> shortcut allows you to omit the name of the -link, in which case the link text itself is used as the name. -Just use an empty set of square brackets -- e.g., to link the word -"Google" to the google.com web site, you could simply write:</p> - -<pre><code>[Google][] -</code></pre> - -<p>And then define the link:</p> - -<pre><code>[Google]: http://google.com/ -</code></pre> - -<p>Because link names may contain spaces, this shortcut even works for -multiple words in the link text:</p> - -<pre><code>Visit [Daring Fireball][] for more information. -</code></pre> - -<p>And then define the link:</p> - -<pre><code>[Daring Fireball]: http://daringfireball.net/ -</code></pre> - -<p>Link definitions can be placed anywhere in your Markdown document. I -tend to put them immediately after each paragraph in which they're -used, but if you want, you can put them all at the end of your -document, sort of like footnotes.</p> - -<p>Here's an example of reference links in action:</p> - -<pre><code>I get 10 times more traffic from [Google] [1] than from -[Yahoo] [2] or [MSN] [3]. - - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" -</code></pre> - -<p>Using the implicit link name shortcut, you could instead write:</p> - -<pre><code>I get 10 times more traffic from [Google][] than from -[Yahoo][] or [MSN][]. - - [google]: http://google.com/ "Google" - [yahoo]: http://search.yahoo.com/ "Yahoo Search" - [msn]: http://search.msn.com/ "MSN Search" -</code></pre> - -<p>Both of the above examples will produce the following HTML output:</p> - -<pre><code><p>I get 10 times more traffic from <a href="http://google.com/" -title="Google">Google</a> than from -<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> -or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p> -</code></pre> - -<p>For comparison, here is the same paragraph written using -Markdown's inline link style:</p> - -<pre><code>I get 10 times more traffic from [Google](http://google.com/ "Google") -than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or -[MSN](http://search.msn.com/ "MSN Search"). -</code></pre> - -<p>The point of reference-style links is not that they're easier to -write. The point is that with reference-style links, your document -source is vastly more readable. Compare the above examples: using -reference-style links, the paragraph itself is only 81 characters -long; with inline-style links, it's 176 characters; and as raw HTML, -it's 234 characters. In the raw HTML, there's more markup than there -is text.</p> - -<p>With Markdown's reference-style links, a source document much more -closely resembles the final output, as rendered in a browser. By -allowing you to move the markup-related metadata out of the paragraph, -you can add links without interrupting the narrative flow of your -prose.</p> - -<h3 id="em">Emphasis</h3> - -<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of -emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an -HTML <code><em></code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML -<code><strong></code> tag. E.g., this input:</p> - -<pre><code>*single asterisks* - -_single underscores_ - -**double asterisks** - -__double underscores__ -</code></pre> - -<p>will produce:</p> - -<pre><code><em>single asterisks</em> - -<em>single underscores</em> - -<strong>double asterisks</strong> - -<strong>double underscores</strong> -</code></pre> - -<p>You can use whichever style you prefer; the lone restriction is that -the same character must be used to open and close an emphasis span.</p> - -<p>Emphasis can be used in the middle of a word:</p> - -<pre><code>un*fucking*believable -</code></pre> - -<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it'll be treated as a -literal asterisk or underscore.</p> - -<p>To produce a literal asterisk or underscore at a position where it -would otherwise be used as an emphasis delimiter, you can backslash -escape it:</p> - -<pre><code>\*this text is surrounded by literal asterisks\* -</code></pre> - -<h3 id="code">Code</h3> - -<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>). -Unlike a pre-formatted code block, a code span indicates code within a -normal paragraph. For example:</p> - -<pre><code>Use the `printf()` function. -</code></pre> - -<p>will produce:</p> - -<pre><code><p>Use the <code>printf()</code> function.</p> -</code></pre> - -<p>To include a literal backtick character within a code span, you can use -multiple backticks as the opening and closing delimiters:</p> - -<pre><code>``There is a literal backtick (`) here.`` -</code></pre> - -<p>which will produce this:</p> - -<pre><code><p><code>There is a literal backtick (`) here.</code></p> -</code></pre> - -<p>The backtick delimiters surrounding a code span may include spaces -- -one after the opening, one before the closing. This allows you to place -literal backtick characters at the beginning or end of a code span:</p> - -<pre><code>A single backtick in a code span: `` ` `` - -A backtick-delimited string in a code span: `` `foo` `` -</code></pre> - -<p>will produce:</p> - -<pre><code><p>A single backtick in a code span: <code>`</code></p> - -<p>A backtick-delimited string in a code span: <code>`foo`</code></p> -</code></pre> - -<p>With a code span, ampersands and angle brackets are encoded as HTML -entities automatically, which makes it easy to include example HTML -tags. Markdown will turn this:</p> - -<pre><code>Please don't use any `<blink>` tags. -</code></pre> - -<p>into:</p> - -<pre><code><p>Please don't use any <code>&lt;blink&gt;</code> tags.</p> -</code></pre> - -<p>You can write this:</p> - -<pre><code>`&#8212;` is the decimal-encoded equivalent of `&mdash;`. -</code></pre> - -<p>to produce:</p> - -<pre><code><p><code>&amp;#8212;</code> is the decimal-encoded -equivalent of <code>&amp;mdash;</code>.</p> -</code></pre> - -<h3 id="img">Images</h3> - -<p>Admittedly, it's fairly difficult to devise a "natural" syntax for -placing images into a plain text document format.</p> - -<p>Markdown uses an image syntax that is intended to resemble the syntax -for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p> - -<p>Inline image syntax looks like this:</p> - -<pre><code> - - -</code></pre> - -<p>That is:</p> - -<ul> -<li>An exclamation mark: <code>!</code>;</li> -<li>followed by a set of square brackets, containing the <code>alt</code> -attribute text for the image;</li> -<li>followed by a set of parentheses, containing the URL or path to -the image, and an optional <code>title</code> attribute enclosed in double -or single quotes.</li> -</ul> - -<p>Reference-style image syntax looks like this:</p> - -<pre><code>![Alt text][id] -</code></pre> - -<p>Where "id" is the name of a defined image reference. Image references -are defined using syntax identical to link references:</p> - -<pre><code>[id]: url/to/image "Optional title attribute" -</code></pre> - -<p>As of this writing, Markdown has no syntax for specifying the -dimensions of an image; if this is important to you, you can simply -use regular HTML <code><img></code> tags.</p> - -<hr /> - -<h2 id="misc">Miscellaneous</h2> - -<h3 id="autolink">Automatic Links</h3> - -<p>Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p> - -<pre><code><http://example.com/> -</code></pre> - -<p>Markdown will turn this into:</p> - -<pre><code><a href="http://example.com/">http://example.com/</a> -</code></pre> - -<p>Automatic links for email addresses work similarly, except that -Markdown will also perform a bit of randomized decimal and hex -entity-encoding to help obscure your address from address-harvesting -spambots. For example, Markdown will turn this:</p> - -<pre><code><address@example.com> -</code></pre> - -<p>into something like this:</p> - -<pre><code><a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65; -&#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111; -&#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61; -&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a> -</code></pre> - -<p>which will render in a browser as a clickable link to "address@example.com".</p> - -<p>(This sort of entity-encoding trick will indeed fool many, if not -most, address-harvesting bots, but it definitely won't fool all of -them. It's better than nothing, but an address published in this way -will probably eventually start receiving spam.)</p> - -<h3 id="backslash">Backslash Escapes</h3> - -<p>Markdown allows you to use backslash escapes to generate literal -characters which would otherwise have special meaning in Markdown's -formatting syntax. For example, if you wanted to surround a word with -literal asterisks (instead of an HTML <code><em></code> tag), you can backslashes -before the asterisks, like this:</p> - -<pre><code>\*literal asterisks\* -</code></pre> - -<p>Markdown provides backslash escapes for the following characters:</p> - -<pre><code>\ backslash -` backtick -* asterisk -_ underscore -{} curly braces -[] square brackets -() parentheses -# hash mark -+ plus sign -- minus sign (hyphen) -. dot -! exclamation mark -</code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text b/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text deleted file mode 100644 index 57360a16c..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text +++ /dev/null @@ -1,888 +0,0 @@ -Markdown: Syntax -================ - -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li> - <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> - - -* [Overview](#overview) - * [Philosophy](#philosophy) - * [Inline HTML](#html) - * [Automatic Escaping for Special Characters](#autoescape) -* [Block Elements](#block) - * [Paragraphs and Line Breaks](#p) - * [Headers](#header) - * [Blockquotes](#blockquote) - * [Lists](#list) - * [Code Blocks](#precode) - * [Horizontal Rules](#hr) -* [Span Elements](#span) - * [Links](#link) - * [Emphasis](#em) - * [Code](#code) - * [Images](#img) -* [Miscellaneous](#misc) - * [Backslash Escapes](#backslash) - * [Automatic Links](#autolink) - - -**Note:** This document is itself written using Markdown; you -can [see the source for it by adding '.text' to the URL][src]. - - [src]: /projects/markdown/syntax.text - -* * * - -<h2 id="overview">Overview</h2> - -<h3 id="philosophy">Philosophy</h3> - -Markdown is intended to be as easy-to-read and easy-to-write as is feasible. - -Readability, however, is emphasized above all else. A Markdown-formatted -document should be publishable as-is, as plain text, without looking -like it's been marked up with tags or formatting instructions. While -Markdown's syntax has been influenced by several existing text-to-HTML -filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], -[Grutatext] [5], and [EtText] [6] -- the single biggest source of -inspiration for Markdown's syntax is the format of plain text email. - - [1]: http://docutils.sourceforge.net/mirror/setext.html - [2]: http://www.aaronsw.com/2002/atx/ - [3]: http://textism.com/tools/textile/ - [4]: http://docutils.sourceforge.net/rst.html - [5]: http://www.triptico.com/software/grutatxt.html - [6]: http://ettext.taint.org/doc/ - -To this end, Markdown's syntax is comprised entirely of punctuation -characters, which punctuation characters have been carefully chosen so -as to look like what they mean. E.g., asterisks around a word actually -look like \*emphasis\*. Markdown lists look like, well, lists. Even -blockquotes look like quoted passages of text, assuming you've ever -used email. - - - -<h3 id="html">Inline HTML</h3> - -Markdown's syntax is intended for one purpose: to be used as a -format for *writing* for the web. - -Markdown is not a replacement for HTML, or even close to it. Its -syntax is very small, corresponding only to a very small subset of -HTML tags. The idea is *not* to create a syntax that makes it easier -to insert HTML tags. In my opinion, HTML tags are already easy to -insert. The idea for Markdown is to make it easy to read, write, and -edit prose. HTML is a *publishing* format; Markdown is a *writing* -format. Thus, Markdown's formatting syntax only addresses issues that -can be conveyed in plain text. - -For any markup that is not covered by Markdown's syntax, you simply -use HTML itself. There's no need to preface it or delimit it to -indicate that you're switching from Markdown to HTML; you just use -the tags. - -The only restrictions are that block-level HTML elements -- e.g. `<div>`, -`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding -content by blank lines, and the start and end tags of the block should -not be indented with tabs or spaces. Markdown is smart enough not -to add extra (unwanted) `<p>` tags around HTML block-level tags. - -For example, to add an HTML table to a Markdown article: - - This is a regular paragraph. - - <table> - <tr> - <td>Foo</td> - </tr> - </table> - - This is another regular paragraph. - -Note that Markdown formatting syntax is not processed within block-level -HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an -HTML block. - -Span-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be -used anywhere in a Markdown paragraph, list item, or header. If you -want, you can even use HTML tags instead of Markdown formatting; e.g. if -you'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's -link or image syntax, go right ahead. - -Unlike block-level HTML tags, Markdown syntax *is* processed within -span-level tags. - - -<h3 id="autoescape">Automatic Escaping for Special Characters</h3> - -In HTML, there are two characters that demand special treatment: `<` -and `&`. Left angle brackets are used to start tags; ampersands are -used to denote HTML entities. If you want to use them as literal -characters, you must escape them as entities, e.g. `<`, and -`&`. - -Ampersands in particular are bedeviling for web writers. If you want to -write about 'AT&T', you need to write '`AT&T`'. You even need to -escape ampersands within URLs. Thus, if you want to link to: - - http://images.google.com/images?num=30&q=larry+bird - -you need to encode the URL as: - - http://images.google.com/images?num=30&q=larry+bird - -in your anchor tag `href` attribute. Needless to say, this is easy to -forget, and is probably the single most common source of HTML validation -errors in otherwise well-marked-up web sites. - -Markdown allows you to use these characters naturally, taking care of -all the necessary escaping for you. If you use an ampersand as part of -an HTML entity, it remains unchanged; otherwise it will be translated -into `&`. - -So, if you want to include a copyright symbol in your article, you can write: - - © - -and Markdown will leave it alone. But if you write: - - AT&T - -Markdown will translate it to: - - AT&T - -Similarly, because Markdown supports [inline HTML](#html), if you use -angle brackets as delimiters for HTML tags, Markdown will treat them as -such. But if you write: - - 4 < 5 - -Markdown will translate it to: - - 4 < 5 - -However, inside Markdown code spans and blocks, angle brackets and -ampersands are *always* encoded automatically. This makes it easy to use -Markdown to write about HTML code. (As opposed to raw HTML, which is a -terrible format for writing about HTML syntax, because every single `<` -and `&` in your example code needs to be escaped.) - - -* * * - - -<h2 id="block">Block Elements</h2> - - -<h3 id="p">Paragraphs and Line Breaks</h3> - -A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing but spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs. - -The implication of the "one or more consecutive lines of text" rule is -that Markdown supports "hard-wrapped" text paragraphs. This differs -significantly from most other text-to-HTML formatters (including Movable -Type's "Convert Line Breaks" option) which translate every line break -character in a paragraph into a `<br />` tag. - -When you *do* want to insert a `<br />` break tag using Markdown, you -end a line with two or more spaces, then type return. - -Yes, this takes a tad more effort to create a `<br />`, but a simplistic -"every line break is a `<br />`" rule wouldn't work for Markdown. -Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] -work best -- and look better -- when you format them with hard breaks. - - [bq]: #blockquote - [l]: #list - - - -<h3 id="header">Headers</h3> - -Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. - -Setext-style headers are "underlined" using equal signs (for first-level -headers) and dashes (for second-level headers). For example: - - This is an H1 - ============= - - This is an H2 - ------------- - -Any number of underlining `=`'s or `-`'s will work. - -Atx-style headers use 1-6 hash characters at the start of the line, -corresponding to header levels 1-6. For example: - - # This is an H1 - - ## This is an H2 - - ###### This is an H6 - -Optionally, you may "close" atx-style headers. This is purely -cosmetic -- you can use this if you think it looks better. The -closing hashes don't even need to match the number of hashes -used to open the header. (The number of opening hashes -determines the header level.) : - - # This is an H1 # - - ## This is an H2 ## - - ### This is an H3 ###### - - -<h3 id="blockquote">Blockquotes</h3> - -Markdown uses email-style `>` characters for blockquoting. If you're -familiar with quoting passages of text in an email message, then you -know how to create a blockquote in Markdown. It looks best if you hard -wrap the text and put a `>` before every line: - - > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, - > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. - > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - > - > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse - > id sem consectetuer libero luctus adipiscing. - -Markdown allows you to be lazy and only put the `>` before the first -line of a hard-wrapped paragraph: - - > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, - consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. - Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - - > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse - id sem consectetuer libero luctus adipiscing. - -Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by -adding additional levels of `>`: - - > This is the first level of quoting. - > - > > This is nested blockquote. - > - > Back to the first level. - -Blockquotes can contain other Markdown elements, including headers, lists, -and code blocks: - - > ## This is a header. - > - > 1. This is the first list item. - > 2. This is the second list item. - > - > Here's some example code: - > - > return shell_exec("echo $input | $markdown_script"); - -Any decent text editor should make email-style quoting easy. For -example, with BBEdit, you can make a selection and choose Increase -Quote Level from the Text menu. - - -<h3 id="list">Lists</h3> - -Markdown supports ordered (numbered) and unordered (bulleted) lists. - -Unordered lists use asterisks, pluses, and hyphens -- interchangably --- as list markers: - - * Red - * Green - * Blue - -is equivalent to: - - + Red - + Green - + Blue - -and: - - - Red - - Green - - Blue - -Ordered lists use numbers followed by periods: - - 1. Bird - 2. McHale - 3. Parish - -It's important to note that the actual numbers you use to mark the -list have no effect on the HTML output Markdown produces. The HTML -Markdown produces from the above list is: - - <ol> - <li>Bird</li> - <li>McHale</li> - <li>Parish</li> - </ol> - -If you instead wrote the list in Markdown like this: - - 1. Bird - 1. McHale - 1. Parish - -or even: - - 3. Bird - 1. McHale - 8. Parish - -you'd get the exact same HTML output. The point is, if you want to, -you can use ordinal numbers in your ordered Markdown lists, so that -the numbers in your source match the numbers in your published HTML. -But if you want to be lazy, you don't have to. - -If you do use lazy list numbering, however, you should still start the -list with the number 1. At some point in the future, Markdown may support -starting ordered lists at an arbitrary number. - -List markers typically start at the left margin, but may be indented by -up to three spaces. List markers must be followed by one or more spaces -or a tab. - -To make lists look nice, you can wrap items with hanging indents: - - * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. - * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. - -But if you want to be lazy, you don't have to: - - * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. - * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. - -If list items are separated by blank lines, Markdown will wrap the -items in `<p>` tags in the HTML output. For example, this input: - - * Bird - * Magic - -will turn into: - - <ul> - <li>Bird</li> - <li>Magic</li> - </ul> - -But this: - - * Bird - - * Magic - -will turn into: - - <ul> - <li><p>Bird</p></li> - <li><p>Magic</p></li> - </ul> - -List items may consist of multiple paragraphs. Each subsequent -paragraph in a list item must be intended by either 4 spaces -or one tab: - - 1. This is a list item with two paragraphs. Lorem ipsum dolor - sit amet, consectetuer adipiscing elit. Aliquam hendrerit - mi posuere lectus. - - Vestibulum enim wisi, viverra nec, fringilla in, laoreet - vitae, risus. Donec sit amet nisl. Aliquam semper ipsum - sit amet velit. - - 2. Suspendisse id sem consectetuer libero luctus adipiscing. - -It looks nice if you indent every line of the subsequent -paragraphs, but here again, Markdown will allow you to be -lazy: - - * This is a list item with two paragraphs. - - This is the second paragraph in the list item. You're - only required to indent the first line. Lorem ipsum dolor - sit amet, consectetuer adipiscing elit. - - * Another item in the same list. - -To put a blockquote within a list item, the blockquote's `>` -delimiters need to be indented: - - * A list item with a blockquote: - - > This is a blockquote - > inside a list item. - -To put a code block within a list item, the code block needs -to be indented *twice* -- 8 spaces or two tabs: - - * A list item with a code block: - - <code goes here> - - -It's worth noting that it's possible to trigger an ordered list by -accident, by writing something like this: - - 1986. What a great season. - -In other words, a *number-period-space* sequence at the beginning of a -line. To avoid this, you can backslash-escape the period: - - 1986\. What a great season. - - - -<h3 id="precode">Code Blocks</h3> - -Pre-formatted code blocks are used for writing about programming or -markup source code. Rather than forming normal paragraphs, the lines -of a code block are interpreted literally. Markdown wraps a code block -in both `<pre>` and `<code>` tags. - -To produce a code block in Markdown, simply indent every line of the -block by at least 4 spaces or 1 tab. For example, given this input: - - This is a normal paragraph: - - This is a code block. - -Markdown will generate: - - <p>This is a normal paragraph:</p> - - <pre><code>This is a code block. - </code></pre> - -One level of indentation -- 4 spaces or 1 tab -- is removed from each -line of the code block. For example, this: - - Here is an example of AppleScript: - - tell application "Foo" - beep - end tell - -will turn into: - - <p>Here is an example of AppleScript:</p> - - <pre><code>tell application "Foo" - beep - end tell - </code></pre> - -A code block continues until it reaches a line that is not indented -(or the end of the article). - -Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) -are automatically converted into HTML entities. This makes it very -easy to include example HTML source code using Markdown -- just paste -it and indent it, and Markdown will handle the hassle of encoding the -ampersands and angle brackets. For example, this: - - <div class="footer"> - © 2004 Foo Corporation - </div> - -will turn into: - - <pre><code><div class="footer"> - &copy; 2004 Foo Corporation - </div> - </code></pre> - -Regular Markdown syntax is not processed within code blocks. E.g., -asterisks are just literal asterisks within a code block. This means -it's also easy to use Markdown to write about Markdown's own syntax. - - - -<h3 id="hr">Horizontal Rules</h3> - -You can produce a horizontal rule tag (`<hr />`) by placing three or -more hyphens, asterisks, or underscores on a line by themselves. If you -wish, you may use spaces between the hyphens or asterisks. Each of the -following lines will produce a horizontal rule: - - * * * - - *** - - ***** - - - - - - - --------------------------------------- - - _ _ _ - - -* * * - -<h2 id="span">Span Elements</h2> - -<h3 id="link">Links</h3> - -Markdown supports two style of links: *inline* and *reference*. - -In both styles, the link text is delimited by [square brackets]. - -To create an inline link, use a set of regular parentheses immediately -after the link text's closing square bracket. Inside the parentheses, -put the URL where you want the link to point, along with an *optional* -title for the link, surrounded in quotes. For example: - - This is [an example](http://example.com/ "Title") inline link. - - [This link](http://example.net/) has no title attribute. - -Will produce: - - <p>This is <a href="http://example.com/" title="Title"> - an example</a> inline link.</p> - - <p><a href="http://example.net/">This link</a> has no - title attribute.</p> - -If you're referring to a local resource on the same server, you can -use relative paths: - - See my [About](/about/) page for details. - -Reference-style links use a second set of square brackets, inside -which you place a label of your choosing to identify the link: - - This is [an example][id] reference-style link. - -You can optionally use a space to separate the sets of brackets: - - This is [an example] [id] reference-style link. - -Then, anywhere in the document, you define your link label like this, -on a line by itself: - - [id]: http://example.com/ "Optional Title Here" - -That is: - -* Square brackets containing the link identifier (optionally - indented from the left margin using up to three spaces); -* followed by a colon; -* followed by one or more spaces (or tabs); -* followed by the URL for the link; -* optionally followed by a title attribute for the link, enclosed - in double or single quotes. - -The link URL may, optionally, be surrounded by angle brackets: - - [id]: <http://example.com/> "Optional Title Here" - -You can put the title attribute on the next line and use extra spaces -or tabs for padding, which tends to look better with longer URLs: - - [id]: http://example.com/longish/path/to/resource/here - "Optional Title Here" - -Link definitions are only used for creating links during Markdown -processing, and are stripped from your document in the HTML output. - -Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: - - [link text][a] - [link text][A] - -are equivalent. - -The *implicit link name* shortcut allows you to omit the name of the -link, in which case the link text itself is used as the name. -Just use an empty set of square brackets -- e.g., to link the word -"Google" to the google.com web site, you could simply write: - - [Google][] - -And then define the link: - - [Google]: http://google.com/ - -Because link names may contain spaces, this shortcut even works for -multiple words in the link text: - - Visit [Daring Fireball][] for more information. - -And then define the link: - - [Daring Fireball]: http://daringfireball.net/ - -Link definitions can be placed anywhere in your Markdown document. I -tend to put them immediately after each paragraph in which they're -used, but if you want, you can put them all at the end of your -document, sort of like footnotes. - -Here's an example of reference links in action: - - I get 10 times more traffic from [Google] [1] than from - [Yahoo] [2] or [MSN] [3]. - - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" - -Using the implicit link name shortcut, you could instead write: - - I get 10 times more traffic from [Google][] than from - [Yahoo][] or [MSN][]. - - [google]: http://google.com/ "Google" - [yahoo]: http://search.yahoo.com/ "Yahoo Search" - [msn]: http://search.msn.com/ "MSN Search" - -Both of the above examples will produce the following HTML output: - - <p>I get 10 times more traffic from <a href="http://google.com/" - title="Google">Google</a> than from - <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> - or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p> - -For comparison, here is the same paragraph written using -Markdown's inline link style: - - I get 10 times more traffic from [Google](http://google.com/ "Google") - than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or - [MSN](http://search.msn.com/ "MSN Search"). - -The point of reference-style links is not that they're easier to -write. The point is that with reference-style links, your document -source is vastly more readable. Compare the above examples: using -reference-style links, the paragraph itself is only 81 characters -long; with inline-style links, it's 176 characters; and as raw HTML, -it's 234 characters. In the raw HTML, there's more markup than there -is text. - -With Markdown's reference-style links, a source document much more -closely resembles the final output, as rendered in a browser. By -allowing you to move the markup-related metadata out of the paragraph, -you can add links without interrupting the narrative flow of your -prose. - - -<h3 id="em">Emphasis</h3> - -Markdown treats asterisks (`*`) and underscores (`_`) as indicators of -emphasis. Text wrapped with one `*` or `_` will be wrapped with an -HTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML -`<strong>` tag. E.g., this input: - - *single asterisks* - - _single underscores_ - - **double asterisks** - - __double underscores__ - -will produce: - - <em>single asterisks</em> - - <em>single underscores</em> - - <strong>double asterisks</strong> - - <strong>double underscores</strong> - -You can use whichever style you prefer; the lone restriction is that -the same character must be used to open and close an emphasis span. - -Emphasis can be used in the middle of a word: - - un*fucking*believable - -But if you surround an `*` or `_` with spaces, it'll be treated as a -literal asterisk or underscore. - -To produce a literal asterisk or underscore at a position where it -would otherwise be used as an emphasis delimiter, you can backslash -escape it: - - \*this text is surrounded by literal asterisks\* - - - -<h3 id="code">Code</h3> - -To indicate a span of code, wrap it with backtick quotes (`` ` ``). -Unlike a pre-formatted code block, a code span indicates code within a -normal paragraph. For example: - - Use the `printf()` function. - -will produce: - - <p>Use the <code>printf()</code> function.</p> - -To include a literal backtick character within a code span, you can use -multiple backticks as the opening and closing delimiters: - - ``There is a literal backtick (`) here.`` - -which will produce this: - - <p><code>There is a literal backtick (`) here.</code></p> - -The backtick delimiters surrounding a code span may include spaces -- -one after the opening, one before the closing. This allows you to place -literal backtick characters at the beginning or end of a code span: - - A single backtick in a code span: `` ` `` - - A backtick-delimited string in a code span: `` `foo` `` - -will produce: - - <p>A single backtick in a code span: <code>`</code></p> - - <p>A backtick-delimited string in a code span: <code>`foo`</code></p> - -With a code span, ampersands and angle brackets are encoded as HTML -entities automatically, which makes it easy to include example HTML -tags. Markdown will turn this: - - Please don't use any `<blink>` tags. - -into: - - <p>Please don't use any <code><blink></code> tags.</p> - -You can write this: - - `—` is the decimal-encoded equivalent of `—`. - -to produce: - - <p><code>&#8212;</code> is the decimal-encoded - equivalent of <code>&mdash;</code>.</p> - - - -<h3 id="img">Images</h3> - -Admittedly, it's fairly difficult to devise a "natural" syntax for -placing images into a plain text document format. - -Markdown uses an image syntax that is intended to resemble the syntax -for links, allowing for two styles: *inline* and *reference*. - -Inline image syntax looks like this: - -  - -  - -That is: - -* An exclamation mark: `!`; -* followed by a set of square brackets, containing the `alt` - attribute text for the image; -* followed by a set of parentheses, containing the URL or path to - the image, and an optional `title` attribute enclosed in double - or single quotes. - -Reference-style image syntax looks like this: - - ![Alt text][id] - -Where "id" is the name of a defined image reference. Image references -are defined using syntax identical to link references: - - [id]: url/to/image "Optional title attribute" - -As of this writing, Markdown has no syntax for specifying the -dimensions of an image; if this is important to you, you can simply -use regular HTML `<img>` tags. - - -* * * - - -<h2 id="misc">Miscellaneous</h2> - -<h3 id="autolink">Automatic Links</h3> - -Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: - - <http://example.com/> - -Markdown will turn this into: - - <a href="http://example.com/">http://example.com/</a> - -Automatic links for email addresses work similarly, except that -Markdown will also perform a bit of randomized decimal and hex -entity-encoding to help obscure your address from address-harvesting -spambots. For example, Markdown will turn this: - - <address@example.com> - -into something like this: - - <a href="mailto:addre - ss@example.co - m">address@exa - mple.com</a> - -which will render in a browser as a clickable link to "address@example.com". - -(This sort of entity-encoding trick will indeed fool many, if not -most, address-harvesting bots, but it definitely won't fool all of -them. It's better than nothing, but an address published in this way -will probably eventually start receiving spam.) - - - -<h3 id="backslash">Backslash Escapes</h3> - -Markdown allows you to use backslash escapes to generate literal -characters which would otherwise have special meaning in Markdown's -formatting syntax. For example, if you wanted to surround a word with -literal asterisks (instead of an HTML `<em>` tag), you can backslashes -before the asterisks, like this: - - \*literal asterisks\* - -Markdown provides backslash escapes for the following characters: - - \ backslash - ` backtick - * asterisk - _ underscore - {} curly braces - [] square brackets - () parentheses - # hash mark - + plus sign - - minus sign (hyphen) - . dot - ! exclamation mark - diff --git a/tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.html b/tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.html deleted file mode 100644 index d8ec7f8e0..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.html +++ /dev/null @@ -1,9 +0,0 @@ -<blockquote> - <p>foo</p> - - <blockquote> - <p>bar</p> - </blockquote> - - <p>foo</p> -</blockquote> diff --git a/tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.text b/tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.text deleted file mode 100644 index ed3c624ff..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.text +++ /dev/null @@ -1,5 +0,0 @@ -> foo -> -> > bar -> -> foo diff --git a/tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html b/tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html deleted file mode 100644 index ba71eab39..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html +++ /dev/null @@ -1,148 +0,0 @@ -<h2>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> - -<hr /> - -<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> - -<hr /> - -<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>Ordered</h2> - -<p>Tight:</p> - -<ol> -<li>First</li> -<li>Second</li> -<li>Third</li> -</ol> - -<p>and:</p> - -<ol> -<li>One</li> -<li>Two</li> -<li>Three</li> -</ol> - -<p>Loose using tabs:</p> - -<ol> -<li><p>First</p></li> -<li><p>Second</p></li> -<li><p>Third</p></li> -</ol> - -<p>and using spaces:</p> - -<ol> -<li><p>One</p></li> -<li><p>Two</p></li> -<li><p>Three</p></li> -</ol> - -<p>Multiple paragraphs:</p> - -<ol> -<li><p>Item 1, graf one.</p> - -<p>Item 2. 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>Nested</h2> - -<ul> -<li>Tab -<ul> -<li>Tab -<ul> -<li>Tab</li> -</ul></li> -</ul></li> -</ul> - -<p>Here's another:</p> - -<ol> -<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> -<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> - - -<p>This was an error in Markdown 1.0.1:</p> - -<ul> -<li><p>this</p> - -<ul><li>sub</li></ul> - -<p>that</p></li> -</ul> diff --git a/tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text b/tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text deleted file mode 100644 index 7f3b49777..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text +++ /dev/null @@ -1,131 +0,0 @@ -## Unordered - -Asterisks tight: - -* asterisk 1 -* asterisk 2 -* asterisk 3 - - -Asterisks loose: - -* asterisk 1 - -* asterisk 2 - -* asterisk 3 - -* * * - -Pluses tight: - -+ Plus 1 -+ Plus 2 -+ Plus 3 - - -Pluses loose: - -+ Plus 1 - -+ Plus 2 - -+ Plus 3 - -* * * - - -Minuses tight: - -- Minus 1 -- Minus 2 -- Minus 3 - - -Minuses loose: - -- Minus 1 - -- Minus 2 - -- Minus 3 - - -## Ordered - -Tight: - -1. First -2. Second -3. Third - -and: - -1. One -2. Two -3. Three - - -Loose using tabs: - -1. First - -2. Second - -3. Third - -and using spaces: - -1. One - -2. Two - -3. Three - -Multiple paragraphs: - -1. Item 1, graf one. - - Item 2. graf two. The quick brown fox jumped over the lazy dog's - back. - -2. Item 2. - -3. Item 3. - - - -## Nested - -* Tab - * Tab - * Tab - -Here's another: - -1. First -2. Second: - * Fee - * Fie - * Foe -3. Third - -Same thing but with paragraphs: - -1. First - -2. Second: - * Fee - * Fie - * Foe - -3. Third - - -This was an error in Markdown 1.0.1: - -* this - - * sub - - that diff --git a/tests/MarkdownTest_1.0.3/Tests/Strong and em together.html b/tests/MarkdownTest_1.0.3/Tests/Strong and em together.html deleted file mode 100644 index 71ec78c70..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Strong and em together.html +++ /dev/null @@ -1,7 +0,0 @@ -<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> diff --git a/tests/MarkdownTest_1.0.3/Tests/Strong and em together.text b/tests/MarkdownTest_1.0.3/Tests/Strong and em together.text deleted file mode 100644 index 95ee690db..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Strong and em together.text +++ /dev/null @@ -1,7 +0,0 @@ -***This is strong and em.*** - -So is ***this*** word. - -___This is strong and em.___ - -So is ___this___ word. diff --git a/tests/MarkdownTest_1.0.3/Tests/Tabs.html b/tests/MarkdownTest_1.0.3/Tests/Tabs.html deleted file mode 100644 index 3301ba803..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Tabs.html +++ /dev/null @@ -1,25 +0,0 @@ -<ul> -<li><p>this is a list item -indented with tabs</p></li> -<li><p>this is a list item -indented with spaces</p></li> -</ul> - -<p>Code:</p> - -<pre><code>this code block is indented by one tab -</code></pre> - -<p>And:</p> - -<pre><code> this code block is indented by two tabs -</code></pre> - -<p>And:</p> - -<pre><code>+ this is an example list item - indented with tabs - -+ this is an example list item - indented with spaces -</code></pre> diff --git a/tests/MarkdownTest_1.0.3/Tests/Tabs.text b/tests/MarkdownTest_1.0.3/Tests/Tabs.text deleted file mode 100644 index 589d1136e..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Tabs.text +++ /dev/null @@ -1,21 +0,0 @@ -+ this is a list item - indented with tabs - -+ this is a list item - indented with spaces - -Code: - - this code block is indented by one tab - -And: - - this code block is indented by two tabs - -And: - - + this is an example list item - indented with tabs - - + this is an example list item - indented with spaces diff --git a/tests/MarkdownTest_1.0.3/Tests/Tidyness.html b/tests/MarkdownTest_1.0.3/Tests/Tidyness.html deleted file mode 100644 index f2a8ce70f..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Tidyness.html +++ /dev/null @@ -1,8 +0,0 @@ -<blockquote> -<p>A list within a blockquote:</p> -<ul> -<li>asterisk 1</li> -<li>asterisk 2</li> -<li>asterisk 3</li> -</ul> -</blockquote> diff --git a/tests/MarkdownTest_1.0.3/Tests/Tidyness.text b/tests/MarkdownTest_1.0.3/Tests/Tidyness.text deleted file mode 100644 index 5f18b8da2..000000000 --- a/tests/MarkdownTest_1.0.3/Tests/Tidyness.text +++ /dev/null @@ -1,5 +0,0 @@ -> A list within a blockquote: -> -> * asterisk 1 -> * asterisk 2 -> * asterisk 3 diff --git a/tests/Tests/Old.hs b/tests/Tests/Old.hs index 01e4403fb..a16784889 100644 --- a/tests/Tests/Old.hs +++ b/tests/Tests/Old.hs @@ -3,7 +3,7 @@ module Tests.Old (tests) where import Test.Framework (testGroup, Test ) import Test.Framework.Providers.HUnit import Test.HUnit ( assertBool ) - +import System.Environment ( getArgs ) import System.IO ( openTempFile, stderr ) import System.Process ( runProcess, waitForProcess ) import System.FilePath ( (</>), (<.>) ) @@ -22,9 +22,6 @@ import Text.Printf readFileUTF8 :: FilePath -> IO String readFileUTF8 f = B.readFile f >>= return . toStringLazy -pandocPath :: FilePath -pandocPath = ".." </> "dist" </> "build" </> "pandoc" </> "pandoc" - data TestResult = TestPassed | TestError ExitCode | TestFailed String FilePath [Diff String] @@ -209,6 +206,11 @@ testWithNormalize :: (String -> String) -- ^ Normalize function for output -> FilePath -- ^ Norm (for test results) filepath -> Test testWithNormalize normalizer testname opts inp norm = testCase testname $ do + args <- getArgs + let buildDir = case args of + (x:_) -> ".." </> x + _ -> error "test-pandoc: missing buildDir argument" + let pandocPath = buildDir </> "pandoc" </> "pandoc" (outputPath, hOut) <- openTempFile "" "pandoc-test" let inpPath = inp let normPath = norm diff --git a/tests/Tests/Readers/LaTeX.hs b/tests/Tests/Readers/LaTeX.hs index c1efd1b68..8ff23ebc1 100644 --- a/tests/Tests/Readers/LaTeX.hs +++ b/tests/Tests/Readers/LaTeX.hs @@ -21,7 +21,7 @@ tests = [ testGroup "basic" [ "simple" =: "word" =?> para "word" , "space" =: - "some text" =?> para ("some text") + "some text" =?> para "some text" , "emphasized" =: "\\emph{emphasized}" =?> para (emph "emphasized") ] diff --git a/tests/Tests/Readers/Markdown.hs b/tests/Tests/Readers/Markdown.hs index ccca147ab..492680a35 100644 --- a/tests/Tests/Readers/Markdown.hs +++ b/tests/Tests/Readers/Markdown.hs @@ -136,6 +136,11 @@ tests = [ testGroup "inline code" "`*` {.haskell .special x=\"7\"}" =?> para (codeWith ("",["haskell","special"],[("x","7")]) "*") ] + , testGroup "emph and strong" + [ "two strongs in emph" =: + "***a**b **c**d*" =?> para (emph (strong (str "a") <> str "b" <> space + <> strong (str "c") <> str "d")) + ] , testGroup "raw LaTeX" [ "in URL" =: "\\begin\n" =?> para (text "\\begin") @@ -166,13 +171,13 @@ tests = [ testGroup "inline code" , testGroup "smart punctuation" [ test markdownSmart "quote before ellipses" ("'...hi'" - =?> para (singleQuoted ("…hi"))) + =?> para (singleQuoted "…hi")) , test markdownSmart "apostrophe before emph" ("D'oh! A l'*aide*!" =?> para ("D’oh! A l’" <> emph "aide" <> "!")) , test markdownSmart "apostrophe in French" ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»" - =?> para ("À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»")) + =?> para "À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»") ] , testGroup "mixed emphasis and strong" [ "emph and strong emph alternating" =: diff --git a/tests/Tests/Walk.hs b/tests/Tests/Walk.hs index f6aa1beae..34350e28a 100644 --- a/tests/Tests/Walk.hs +++ b/tests/Tests/Walk.hs @@ -21,11 +21,11 @@ tests = [ testGroup "Walk" p_walk :: (Typeable a, Walkable a Pandoc) => (a -> a) -> Pandoc -> Bool -p_walk f = (\(d :: Pandoc) -> everywhere (mkT f) d == walk f d) +p_walk f d = everywhere (mkT f) d == walk f d p_query :: (Eq a, Typeable a1, Monoid a, Walkable a1 Pandoc) => (a1 -> a) -> Pandoc -> Bool -p_query f = (\(d :: Pandoc) -> everything mappend (mempty `mkQ` f) d == query f d) +p_query f d = everything mappend (mempty `mkQ` f) d == query f d inlineTrans :: Inline -> Inline inlineTrans (Str xs) = Str $ map toUpper xs diff --git a/tests/Tests/Writers/LaTeX.hs b/tests/Tests/Writers/LaTeX.hs index 5f702a85d..8a9519e2e 100644 --- a/tests/Tests/Writers/LaTeX.hs +++ b/tests/Tests/Writers/LaTeX.hs @@ -39,6 +39,11 @@ tests = [ testGroup "code blocks" , test latexListing "no identifier" $ codeBlock "hi" =?> ("\\begin{lstlisting}\nhi\n\\end{lstlisting}" :: String) ] + , testGroup "definition lists" + [ "with internal link" =: definitionList [(link "#go" "" (str "testing"), + [plain (text "hi there")])] =?> + "\\begin{description}\n\\itemsep1pt\\parskip0pt\\parsep0pt\n\\item[{\\hyperref[go]{testing}}]\nhi there\n\\end{description}" + ] , testGroup "math" [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?> "$\\sigma|_{\\{x\\}}$" diff --git a/tests/Tests/Writers/Markdown.hs b/tests/Tests/Writers/Markdown.hs index 99b85dfb7..c2a8f5903 100644 --- a/tests/Tests/Writers/Markdown.hs +++ b/tests/Tests/Writers/Markdown.hs @@ -31,4 +31,8 @@ tests :: [Test] tests = [ "indented code after list" =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test") =?> "1. one\n\n two\n\n<!-- -->\n\n test" + , "list with tight sublist" + =: bulletList [ plain "foo" <> bulletList [ plain "bar" ], + plain "baz" ] + =?> "- foo\n - bar\n- baz\n" ] diff --git a/tests/html-reader.native b/tests/html-reader.native index 15937e594..e80905729 100644 --- a/tests/html-reader.native +++ b/tests/html-reader.native @@ -1,4 +1,4 @@ -Pandoc (Meta {unMeta = fromList [("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]}) +Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]}) [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Str "'",Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."] ,HorizontalRule ,Header 1 ("",[],[]) [Str "Headers"] @@ -207,18 +207,18 @@ Pandoc (Meta {unMeta = fromList [("title",MetaInlines [Str "Pandoc",Space,Str "T ,BulletList [[Plain [Str "\\cite[22",Str "-",Str "23]{smith",Str ".",Str "1899}"]] ,[Plain [Str "\\doublespacing"]] - ,[Plain [Str "$2+2=4$"]] - ,[Plain [Str "$x",Space,Str "\\in",Space,Str "y$"]] - ,[Plain [Str "$\\alpha",Space,Str "\\wedge",Space,Str "\\omega$"]] - ,[Plain [Str "$223$"]] - ,[Plain [Str "$p$",Str "-",Str "Tree"]] - ,[Plain [Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)",Str "-",Str "f(x)}{h}$"]] - ,[Plain [Str "Here",Str "'",Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",Space,Str "x^2$",Str "."]]] + ,[Plain [Str "$",Str "2+2=4",Str "$"]] + ,[Plain [Str "$",Str "x",Space,Str "\\in",Space,Str "y",Str "$"]] + ,[Plain [Str "$",Str "\\alpha",Space,Str "\\wedge",Space,Str "\\omega",Str "$"]] + ,[Plain [Str "$",Str "223",Str "$"]] + ,[Plain [Str "$",Str "p",Str "$",Str "-",Str "Tree"]] + ,[Plain [Str "$",Str "\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)",Str "-",Str "f(x)}{h}",Str "$"]] + ,[Plain [Str "Here",Str "'",Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$",Str "\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",Space,Str "x^2",Str "$",Str "."]]] ,Para [Str "These",Space,Str "shouldn",Str "'",Str "t",Space,Str "be",Space,Str "math:"] ,BulletList [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]] - ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$34,000",Str ".",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Str "\"",Str "lot",Str "\"",Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]] - ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$",Str "."]]] + ,[Plain [Str "$",Str "22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$",Str "34,000",Str ".",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Str "\"",Str "lot",Str "\"",Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]] + ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$",Str "73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23",Str "$",Str "."]]] ,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"] ,Para [Str "\\begin{tabular}{|l|l|}\\hline",Space,Str "Animal",Space,Str "&",Space,Str "Number",Space,Str "\\\\",Space,Str "\\hline",Space,Str "Dog",Space,Str "&",Space,Str "2",Space,Str "\\\\",Space,Str "Cat",Space,Str "&",Space,Str "1",Space,Str "\\\\",Space,Str "\\hline",Space,Str "\\end{tabular}"] ,HorizontalRule diff --git a/tests/latex-reader.native b/tests/latex-reader.native index 15b667b2f..fcc3153cf 100644 --- a/tests/latex-reader.native +++ b/tests/latex-reader.native @@ -302,7 +302,7 @@ Pandoc (Meta {unMeta = fromList [("authors",MetaList [MetaInlines [Str "John",Sp ,Para [Str "4",Space,Str "<",Space,Str "5."] ,Para [Str "6",Space,Str ">",Space,Str "5."] ,Para [Str "Backslash:",Space,Str "\\"] -,Para [Str "Backtick:",Space,Str "\8216"] +,Para [Str "Backtick:",Space,Str "`"] ,Para [Str "Asterisk:",Space,Str "*"] ,Para [Str "Underscore:",Space,Str "_"] ,Para [Str "Left",Space,Str "brace:",Space,Str "{"] diff --git a/tests/lhs-test.markdown b/tests/lhs-test.markdown index 47ec920d3..75a253bf4 100644 --- a/tests/lhs-test.markdown +++ b/tests/lhs-test.markdown @@ -4,11 +4,11 @@ lhs test `unsplit` is an arrow that takes a pair of values and combines them to return a single value: -~~~~ {.sourceCode .literate .haskell} +``` {.sourceCode .literate .haskell} unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d unsplit = arr . uncurry -- arr (\op (x,y) -> x `op` y) -~~~~ +``` `(***)` 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 diff --git a/tests/markdown-citations.native b/tests/markdown-citations.native index 1cd4bd035..d9738fb4f 100644 --- a/tests/markdown-citations.native +++ b/tests/markdown-citations.native @@ -1,17 +1,17 @@ [Header 1 ("pandoc-with-citeproc-hs",[],[]) [Str "Pandoc",Space,Str "with",Space,Str "citeproc-hs"] ,BulletList - [[Para [Cite [Citation {citationId = "nonexistent", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"]]] - ,[Para [Cite [Citation {citationId = "nonexistent", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "???"]]] - ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "???"],Space,Str "says",Space,Str "blah."]] - ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "30"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "???"],Space,Str "says",Space,Str "blah."]] - ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "30,",Space,Str "with",Space,Str "suffix"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "???"],Space,Str "says",Space,Str "blah."]] - ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [Space,Str "p.",Space,Str "30"], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [Str "see",Space,Str "also"], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Space,Str "says",Space,Str "blah."]] - ,[Para [Str "In",Space,Str "a",Space,Str "note.",Note [Para [Cite [Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "12"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "???"],Space,Str "and",Space,Str "a",Space,Str "citation",Space,Str "without",Space,Str "locators",Space,Cite [Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]]]] - ,[Para [Str "A",Space,Str "citation",Space,Str "group",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "chap.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [Str "also"], citationSuffix = [Space,Str "p.",Space,Str "34-35"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]] - ,[Para [Str "Another",Space,Str "one",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "p.",Space,Str "34-35"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]] - ,[Para [Str "And",Space,Str "another",Space,Str "one",Space,Str "in",Space,Str "a",Space,Str "note.",Note [Para [Str "Some",Space,Str "citations",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "chap.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]]]] - ,[Para [Str "Citation",Space,Str "with",Space,Str "a",Space,Str "suffix",Space,Str "and",Space,Str "locator",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Space,Str "pp.",Space,Str "33,",Space,Str "35-37,",Space,Str "and",Space,Str "nowhere",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]] - ,[Para [Str "Citation",Space,Str "with",Space,Str "suffix",Space,Str "only",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Space,Str "and",Space,Str "nowhere",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]] - ,[Para [Str "Now",Space,Str "some",Space,Str "modifiers.",Note [Para [Str "Like",Space,Str "a",Space,Str "citation",Space,Str "without",Space,Str "author:",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str ",",Space,Str "and",Space,Str "now",Space,Str "Doe",Space,Str "with",Space,Str "a",Space,Str "locator",Space,Cite [Citation {citationId = "item2", citationPrefix = [], citationSuffix = [Space,Str "p.",Space,Str "44"], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]]]] - ,[Para [Str "With",Space,Str "some",Space,Str "markup",Space,Cite [Citation {citationId = "item1", citationPrefix = [Emph [Str "see"]], citationSuffix = [Space,Str "p.",Space,Strong [Str "32"]], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "???"],Str "."]]] + [[Para [Cite [Citation {citationId = "nonexistent", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@nonexistent]"]]] + ,[Para [Cite [Citation {citationId = "nonexistent", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@nonexistent"]]] + ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1"],Space,Str "says",Space,Str "blah."]] + ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "30"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1",Space,Str "[p.",Space,Str "30]"],Space,Str "says",Space,Str "blah."]] + ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "30,",Space,Str "with",Space,Str "suffix"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1",Space,Str "[p.",Space,Str "30,",Space,Str "with",Space,Str "suffix]"],Space,Str "says",Space,Str "blah."]] + ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [Space,Str "p.",Space,Str "30"], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [Str "see",Space,Str "also"], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "@item1",Space,Str "[-@item2",Space,Str "p.",Space,Str "30;",Space,Str "see",Space,Str "also",Space,Str "@\1087\1091\1085\1082\1090\&3]"],Space,Str "says",Space,Str "blah."]] + ,[Para [Str "In",Space,Str "a",Space,Str "note.",Note [Para [Cite [Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "12"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@\1087\1091\1085\1082\1090\&3",Space,Str "[p.",Space,Str "12]"],Space,Str "and",Space,Str "a",Space,Str "citation",Space,Str "without",Space,Str "locators",Space,Cite [Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@\1087\1091\1085\1082\1090\&3]"],Str "."]]]] + ,[Para [Str "A",Space,Str "citation",Space,Str "group",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "chap.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [Str "also"], citationSuffix = [Space,Str "p.",Space,Str "34-35"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[see",Space,Str "@item1",Space,Str "chap.",Space,Str "3;",Space,Str "also",Space,Str "@\1087\1091\1085\1082\1090\&3",Space,Str "p.",Space,Str "34-35]"],Str "."]] + ,[Para [Str "Another",Space,Str "one",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "p.",Space,Str "34-35"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[see",Space,Str "@item1",Space,Str "p.",Space,Str "34-35]"],Str "."]] + ,[Para [Str "And",Space,Str "another",Space,Str "one",Space,Str "in",Space,Str "a",Space,Str "note.",Note [Para [Str "Some",Space,Str "citations",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "chap.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[see",Space,Str "@item1",Space,Str "chap.",Space,Str "3;",Space,Str "@\1087\1091\1085\1082\1090\&3;",Space,Str "@item2]"],Str "."]]]] + ,[Para [Str "Citation",Space,Str "with",Space,Str "a",Space,Str "suffix",Space,Str "and",Space,Str "locator",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Space,Str "pp.",Space,Str "33,",Space,Str "35-37,",Space,Str "and",Space,Str "nowhere",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@item1",Space,Str "pp.",Space,Str "33,",Space,Str "35-37,",Space,Str "and",Space,Str "nowhere",Space,Str "else]"],Str "."]] + ,[Para [Str "Citation",Space,Str "with",Space,Str "suffix",Space,Str "only",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Space,Str "and",Space,Str "nowhere",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@item1",Space,Str "and",Space,Str "nowhere",Space,Str "else]"],Str "."]] + ,[Para [Str "Now",Space,Str "some",Space,Str "modifiers.",Note [Para [Str "Like",Space,Str "a",Space,Str "citation",Space,Str "without",Space,Str "author:",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0}] [Str "[-@item1]"],Str ",",Space,Str "and",Space,Str "now",Space,Str "Doe",Space,Str "with",Space,Str "a",Space,Str "locator",Space,Cite [Citation {citationId = "item2", citationPrefix = [], citationSuffix = [Space,Str "p.",Space,Str "44"], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0}] [Str "[-@item2",Space,Str "p.",Space,Str "44]"],Str "."]]]] + ,[Para [Str "With",Space,Str "some",Space,Str "markup",Space,Cite [Citation {citationId = "item1", citationPrefix = [Emph [Str "see"]], citationSuffix = [Space,Str "p.",Space,Strong [Str "32"]], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[*see*",Space,Str "@item1",Space,Str "p.",Space,Str "**32**]"],Str "."]]] ,Header 1 ("references",[],[]) [Str "References"]] diff --git a/tests/markdown-reader-more.native b/tests/markdown-reader-more.native index ca588571f..27f09dada 100644 --- a/tests/markdown-reader-more.native +++ b/tests/markdown-reader-more.native @@ -40,7 +40,7 @@ ,OrderedList (3,Example,TwoParens) [[Plain [Str "Third",Space,Str "example."]]] ,Header 2 ("macros",[],[]) [Str "Macros"] -,Para [Math InlineMath "\\langle x,y \\rangle"] +,Para [Math InlineMath "{\\langle x,y \\rangle}"] ,Header 2 ("case-insensitive-references",[],[]) [Str "Case-insensitive",Space,Str "references"] ,Para [Link [Str "Fum"] ("/fum","")] ,Para [Link [Str "FUM"] ("/fum","")] diff --git a/tests/mediawiki-reader.native b/tests/mediawiki-reader.native index a424be0ae..238413445 100644 --- a/tests/mediawiki-reader.native +++ b/tests/mediawiki-reader.native @@ -1,39 +1,39 @@ Pandoc (Meta {unMeta = fromList []}) -[Header 1 ("",[],[]) [Str "header"] -,Header 2 ("",[],[]) [Str "header",Space,Str "level",Space,Str "two"] -,Header 3 ("",[],[]) [Str "header",Space,Str "level",Space,Str "3"] -,Header 4 ("",[],[]) [Str "header",Space,Emph [Str "level"],Space,Str "four"] -,Header 5 ("",[],[]) [Str "header",Space,Str "level",Space,Str "5"] -,Header 6 ("",[],[]) [Str "header",Space,Str "level",Space,Str "6"] +[Header 1 ("header",[],[]) [Str "header"] +,Header 2 ("header-level-two",[],[]) [Str "header",Space,Str "level",Space,Str "two"] +,Header 3 ("header-level-3",[],[]) [Str "header",Space,Str "level",Space,Str "3"] +,Header 4 ("header-level-four",[],[]) [Str "header",Space,Emph [Str "level"],Space,Str "four"] +,Header 5 ("header-level-5",[],[]) [Str "header",Space,Str "level",Space,Str "5"] +,Header 6 ("header-level-6",[],[]) [Str "header",Space,Str "level",Space,Str "6"] ,Para [Str "=======",Space,Str "not",Space,Str "a",Space,Str "header",Space,Str "========"] ,Para [Code ("",[],[]) "==\160not\160a\160header\160=="] -,Header 2 ("",[],[]) [Str "emph",Space,Str "and",Space,Str "strong"] +,Header 2 ("emph-and-strong",[],[]) [Str "emph",Space,Str "and",Space,Str "strong"] ,Para [Emph [Str "emph"],Space,Strong [Str "strong"]] ,Para [Strong [Emph [Str "strong",Space,Str "and",Space,Str "emph"]]] ,Para [Strong [Emph [Str "emph",Space,Str "inside"],Space,Str "strong"]] ,Para [Strong [Str "strong",Space,Str "with",Space,Emph [Str "emph"]]] ,Para [Emph [Strong [Str "strong",Space,Str "inside"],Space,Str "emph"]] -,Header 2 ("",[],[]) [Str "horizontal",Space,Str "rule"] +,Header 2 ("horizontal-rule",[],[]) [Str "horizontal",Space,Str "rule"] ,Para [Str "top"] ,HorizontalRule ,Para [Str "bottom"] ,HorizontalRule -,Header 2 ("",[],[]) [Str "nowiki"] +,Header 2 ("nowiki",[],[]) [Str "nowiki"] ,Para [Str "''not",Space,Str "emph''"] -,Header 2 ("",[],[]) [Str "strikeout"] +,Header 2 ("strikeout",[],[]) [Str "strikeout"] ,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "struck",Space,Str "out"]]] -,Header 2 ("",[],[]) [Str "entities"] +,Header 2 ("entities",[],[]) [Str "entities"] ,Para [Str "hi",Space,Str "&",Space,Str "low"] ,Para [Str "hi",Space,Str "&",Space,Str "low"] ,Para [Str "G\246del"] ,Para [Str "\777\2730"] -,Header 2 ("",[],[]) [Str "comments"] +,Header 2 ("comments",[],[]) [Str "comments"] ,Para [Str "inline",Space,Str "comment"] ,Para [Str "between",Space,Str "blocks"] -,Header 2 ("",[],[]) [Str "linebreaks"] +,Header 2 ("linebreaks",[],[]) [Str "linebreaks"] ,Para [Str "hi",LineBreak,Str "there"] ,Para [Str "hi",LineBreak,Str "there"] -,Header 2 ("",[],[]) [Str ":",Space,Str "indents"] +,Header 2 ("indents",[],[]) [Str ":",Space,Str "indents"] ,Para [Str "hi"] ,DefinitionList [([], @@ -46,36 +46,36 @@ Pandoc (Meta {unMeta = fromList []}) [([], [[Plain [Str "there"]]])]]])] ,Para [Str "bud"] -,Header 2 ("",[],[]) [Str "p",Space,Str "tags"] +,Header 2 ("p-tags",[],[]) [Str "p",Space,Str "tags"] ,Para [Str "hi",Space,Str "there"] ,Para [Str "bud"] ,Para [Str "another"] -,Header 2 ("",[],[]) [Str "raw",Space,Str "html"] +,Header 2 ("raw-html",[],[]) [Str "raw",Space,Str "html"] ,Para [Str "hi",Space,RawInline (Format "html") "<span style=\"color:red\">",Emph [Str "there"],RawInline (Format "html") "</span>",Str "."] ,Para [RawInline (Format "html") "<ins>",Str "inserted",RawInline (Format "html") "</ins>"] ,RawBlock (Format "html") "<div class=\"special\">" ,Para [Str "hi",Space,Emph [Str "there"]] ,RawBlock (Format "html") "</div>" -,Header 2 ("",[],[]) [Str "sup,",Space,Str "sub,",Space,Str "del"] +,Header 2 ("sup-sub-del",[],[]) [Str "sup,",Space,Str "sub,",Space,Str "del"] ,Para [Str "H",Subscript [Str "2"],Str "O",Space,Str "base",Superscript [Emph [Str "exponent"]],Space,Strikeout [Str "hello"]] -,Header 2 ("",[],[]) [Str "inline",Space,Str "code"] +,Header 2 ("inline-code",[],[]) [Str "inline",Space,Str "code"] ,Para [Code ("",[],[]) "*\8594*",Space,Code ("",[],[]) "typed",Space,Code ("",["haskell"],[]) ">>="] -,Header 2 ("",[],[]) [Str "code",Space,Str "blocks"] +,Header 2 ("code-blocks",[],[]) [Str "code",Space,Str "blocks"] ,CodeBlock ("",[],[]) "case xs of\n (_:_) -> reverse xs\n [] -> ['*']" ,CodeBlock ("",["haskell"],[]) "case xs of\n (_:_) -> reverse xs\n [] -> ['*']" ,CodeBlock ("",["ruby","numberLines"],[("startFrom","100")]) "widgets.each do |w|\n print w.price\nend" -,Header 2 ("",[],[]) [Str "block",Space,Str "quotes"] +,Header 2 ("block-quotes",[],[]) [Str "block",Space,Str "quotes"] ,Para [Str "Regular",Space,Str "paragraph"] ,BlockQuote [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote."] ,Para [Str "With",Space,Str "two",Space,Str "paragraphs."]] ,Para [Str "Nother",Space,Str "paragraph."] -,Header 2 ("",[],[]) [Str "external",Space,Str "links"] +,Header 2 ("external-links",[],[]) [Str "external",Space,Str "links"] ,Para [Link [Emph [Str "Google"],Space,Str "search",Space,Str "engine"] ("http://google.com","")] ,Para [Link [Str "http://johnmacfarlane.net/pandoc/"] ("http://johnmacfarlane.net/pandoc/","")] ,Para [Link [Str "1"] ("http://google.com",""),Space,Link [Str "2"] ("http://yahoo.com","")] ,Para [Link [Str "email",Space,Str "me"] ("mailto:info@example.org","")] -,Header 2 ("",[],[]) [Str "internal",Space,Str "links"] +,Header 2 ("internal-links",[],[]) [Str "internal",Space,Str "links"] ,Para [Link [Str "Help"] ("Help","wikilink")] ,Para [Link [Str "the",Space,Str "help",Space,Str "page"] ("Help","wikilink")] ,Para [Link [Str "Helpers"] ("Help","wikilink")] @@ -83,12 +83,12 @@ Pandoc (Meta {unMeta = fromList []}) ,Para [Link [Str "Contents"] ("Help:Contents","wikilink")] ,Para [Link [Str "#My",Space,Str "anchor"] ("#My_anchor","wikilink")] ,Para [Link [Str "and",Space,Str "text"] ("Page#with_anchor","wikilink")] -,Header 2 ("",[],[]) [Str "images"] -,Para [Image [Str "caption"] ("example.jpg","image")] -,Para [Image [Str "the",Space,Emph [Str "caption"],Space,Str "with",Space,Link [Str "external",Space,Str "link"] ("http://google.com","")] ("example.jpg","image")] -,Para [Image [Str "caption"] ("example.jpg","image")] -,Para [Image [Str "example.jpg"] ("example.jpg","image")] -,Header 2 ("",[],[]) [Str "lists"] +,Header 2 ("images",[],[]) [Str "images"] +,Para [Image [Str "caption"] ("example.jpg","fig:caption")] +,Para [Image [Str "the",Space,Emph [Str "caption"],Space,Str "with",Space,Link [Str "external",Space,Str "link"] ("http://google.com","")] ("example.jpg","fig:the caption with external link")] +,Para [Image [Str "caption"] ("example.jpg","fig:caption")] +,Para [Image [Str "example.jpg"] ("example.jpg","fig:example.jpg")] +,Header 2 ("lists",[],[]) [Str "lists"] ,BulletList [[Plain [Str "Start",Space,Str "each",Space,Str "line"]] ,[Plain [Str "with",Space,Str "an",Space,Str "asterisk",Space,Str "(*)."] @@ -161,9 +161,10 @@ Pandoc (Meta {unMeta = fromList []}) [[Plain [Str "Amsterdam"]] ,[Plain [Str "Rotterdam"]] ,[Plain [Str "The",Space,Str "Hague"]]] -,Header 2 ("",[],[]) [Str "math"] +,Header 2 ("math",[],[]) [Str "math"] ,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."] -,Header 2 ("",[],[]) [Str "preformatted",Space,Str "blocks"] +,Para [Str "With",Space,Str "spaces:",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."] +,Header 2 ("preformatted-blocks",[],[]) [Str "preformatted",Space,Str "blocks"] ,Para [Code ("",[],[]) "Start\160each\160line\160with\160a\160space.",LineBreak,Code ("",[],[]) "Text\160is\160",Strong [Code ("",[],[]) "preformatted"],Code ("",[],[]) "\160and",LineBreak,Emph [Code ("",[],[]) "markups"],Code ("",[],[]) "\160",Strong [Emph [Code ("",[],[]) "can"]],Code ("",[],[]) "\160be\160done."] ,Para [Code ("",[],[]) "\160hell\160\160\160\160\160\160yeah"] ,Para [Code ("",[],[]) "Start\160with\160a\160space\160in\160the\160first\160column,",LineBreak,Code ("",[],[]) "(before\160the\160<nowiki>).",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "Then\160your\160block\160format\160will\160be",LineBreak,Code ("",[],[]) "\160\160\160\160maintained.",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "This\160is\160good\160for\160copying\160in\160code\160blocks:",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "def\160function():",LineBreak,Code ("",[],[]) "\160\160\160\160\"\"\"documentation\160string\"\"\"",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "\160\160\160\160if\160True:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160True",LineBreak,Code ("",[],[]) "\160\160\160\160else:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160False"] @@ -173,12 +174,12 @@ Pandoc (Meta {unMeta = fromList []}) ,Para [Str "Don't",Space,Str "need"] ,Para [Code ("",[],[]) "a\160blank\160line"] ,Para [Str "around",Space,Str "a",Space,Str "preformatted",Space,Str "block."] -,Header 2 ("",[],[]) [Str "templates"] +,Header 2 ("templates",[],[]) [Str "templates"] ,RawBlock (Format "mediawiki") "{{Welcome}}" ,RawBlock (Format "mediawiki") "{{Foo:Bar}}" ,RawBlock (Format "mediawiki") "{{Thankyou|all your effort|Me}}" ,Para [Str "Written",Space,RawInline (Format "mediawiki") "{{{date}}}",Space,Str "by",Space,RawInline (Format "mediawiki") "{{{name}}}",Str "."] -,Header 2 ("",[],[]) [Str "tables"] +,Header 2 ("tables",[],[]) [Str "tables"] ,Table [] [AlignDefault,AlignDefault] [0.0,0.0] [[] ,[]] @@ -244,6 +245,6 @@ Pandoc (Meta {unMeta = fromList []}) [[]] [[[Para [Str "Orange"]]]] ,Para [Str "Paragraph",Space,Str "after",Space,Str "the",Space,Str "table."] -,Header 2 ("",[],[]) [Str "notes"] +,Header 2 ("notes",[],[]) [Str "notes"] ,Para [Str "My",Space,Str "note!",Note [Plain [Str "This."]]] ,Para [Str "URL",Space,Str "note.",Note [Plain [Link [Str "http://docs.python.org/library/functions.html#range"] ("http://docs.python.org/library/functions.html#range","")]]]] diff --git a/tests/mediawiki-reader.wiki b/tests/mediawiki-reader.wiki index 1e885daf0..26f4ef164 100644 --- a/tests/mediawiki-reader.wiki +++ b/tests/mediawiki-reader.wiki @@ -248,6 +248,8 @@ ends the list. Here is some <math>x=\frac{y^\pi}{z}</math>. +With spaces: <math> x=\frac{y^\pi}{z} </math>. + == preformatted blocks == Start each line with a space. diff --git a/tests/tables.context b/tests/tables.context index e113a8e6a..371e559e5 100644 --- a/tests/tables.context +++ b/tests/tables.context @@ -1,6 +1,6 @@ Simple table with caption: -\placetable[here]{Demonstration of simple table syntax.} +\placetable{Demonstration of simple table syntax.} \starttable[|r|l|c|l|] \HL \NC Right @@ -29,7 +29,7 @@ Simple table with caption: Simple table without caption: -\placetable[here,none]{} +\placetable[none]{} \starttable[|r|l|c|l|] \HL \NC Right @@ -58,7 +58,7 @@ Simple table without caption: Simple table indented two spaces: -\placetable[here]{Demonstration of simple table syntax.} +\placetable{Demonstration of simple table syntax.} \starttable[|r|l|c|l|] \HL \NC Right @@ -87,7 +87,7 @@ Simple table indented two spaces: Multiline table with caption: -\placetable[here]{Here's the caption. It may span multiple lines.} +\placetable{Here's the caption. It may span multiple lines.} \starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|] \HL \NC Centered Header @@ -111,7 +111,7 @@ Multiline table with caption: Multiline table without caption: -\placetable[here,none]{} +\placetable[none]{} \starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|] \HL \NC Centered Header @@ -135,7 +135,7 @@ Multiline table without caption: Table without column headers: -\placetable[here,none]{} +\placetable[none]{} \starttable[|r|l|c|r|] \HL \NC 12 @@ -158,7 +158,7 @@ Table without column headers: Multiline table without column headers: -\placetable[here,none]{} +\placetable[none]{} \starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|] \HL \NC First diff --git a/tests/tables.latex b/tests/tables.latex index c27e10461..1a87c4f71 100644 --- a/tests/tables.latex +++ b/tests/tables.latex @@ -1,59 +1,59 @@ Simple table with caption: \begin{longtable}[c]{@{}rlcl@{}} -\hline\noalign{\medskip} +\toprule\addlinespace Right & Left & Center & Default -\\\noalign{\medskip} -\hline\noalign{\medskip} +\\\addlinespace +\midrule\endhead 12 & 12 & 12 & 12 -\\\noalign{\medskip} +\\\addlinespace 123 & 123 & 123 & 123 -\\\noalign{\medskip} +\\\addlinespace 1 & 1 & 1 & 1 -\\\noalign{\medskip} -\hline -\noalign{\medskip} +\\\addlinespace +\bottomrule +\addlinespace \caption{Demonstration of simple table syntax.} \end{longtable} Simple table without caption: \begin{longtable}[c]{@{}rlcl@{}} -\hline\noalign{\medskip} +\toprule\addlinespace Right & Left & Center & Default -\\\noalign{\medskip} -\hline\noalign{\medskip} +\\\addlinespace +\midrule\endhead 12 & 12 & 12 & 12 -\\\noalign{\medskip} +\\\addlinespace 123 & 123 & 123 & 123 -\\\noalign{\medskip} +\\\addlinespace 1 & 1 & 1 & 1 -\\\noalign{\medskip} -\hline +\\\addlinespace +\bottomrule \end{longtable} Simple table indented two spaces: \begin{longtable}[c]{@{}rlcl@{}} -\hline\noalign{\medskip} +\toprule\addlinespace Right & Left & Center & Default -\\\noalign{\medskip} -\hline\noalign{\medskip} +\\\addlinespace +\midrule\endhead 12 & 12 & 12 & 12 -\\\noalign{\medskip} +\\\addlinespace 123 & 123 & 123 & 123 -\\\noalign{\medskip} +\\\addlinespace 1 & 1 & 1 & 1 -\\\noalign{\medskip} -\hline -\noalign{\medskip} +\\\addlinespace +\bottomrule +\addlinespace \caption{Demonstration of simple table syntax.} \end{longtable} Multiline table with caption: \begin{longtable}[c]{@{}clrl@{}} -\hline\noalign{\medskip} +\toprule\addlinespace \begin{minipage}[b]{0.13\columnwidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright @@ -63,8 +63,8 @@ Right Aligned \end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright Default aligned \end{minipage} -\\\noalign{\medskip} -\hline\noalign{\medskip} +\\\addlinespace +\midrule\endhead \begin{minipage}[t]{0.13\columnwidth}\centering First \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright @@ -74,7 +74,7 @@ row \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Example of a row that spans multiple lines. \end{minipage} -\\\noalign{\medskip} +\\\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering Second \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright @@ -84,16 +84,16 @@ row \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Here's another one. Note the blank line between rows. \end{minipage} -\\\noalign{\medskip} -\hline -\noalign{\medskip} +\\\addlinespace +\bottomrule +\addlinespace \caption{Here's the caption. It may span multiple lines.} \end{longtable} Multiline table without caption: \begin{longtable}[c]{@{}clrl@{}} -\hline\noalign{\medskip} +\toprule\addlinespace \begin{minipage}[b]{0.13\columnwidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright @@ -103,8 +103,8 @@ Right Aligned \end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright Default aligned \end{minipage} -\\\noalign{\medskip} -\hline\noalign{\medskip} +\\\addlinespace +\midrule\endhead \begin{minipage}[t]{0.13\columnwidth}\centering First \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright @@ -114,7 +114,7 @@ row \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Example of a row that spans multiple lines. \end{minipage} -\\\noalign{\medskip} +\\\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering Second \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright @@ -124,27 +124,27 @@ row \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Here's another one. Note the blank line between rows. \end{minipage} -\\\noalign{\medskip} -\hline +\\\addlinespace +\bottomrule \end{longtable} Table without column headers: \begin{longtable}[c]{@{}rlcr@{}} -\hline\noalign{\medskip} +\toprule\addlinespace 12 & 12 & 12 & 12 -\\\noalign{\medskip} +\\\addlinespace 123 & 123 & 123 & 123 -\\\noalign{\medskip} +\\\addlinespace 1 & 1 & 1 & 1 -\\\noalign{\medskip} -\hline +\\\addlinespace +\bottomrule \end{longtable} Multiline table without column headers: \begin{longtable}[c]{@{}clrl@{}} -\hline\noalign{\medskip} +\toprule\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering First \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright @@ -154,7 +154,7 @@ row \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Example of a row that spans multiple lines. \end{minipage} -\\\noalign{\medskip} +\\\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering Second \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright @@ -164,6 +164,6 @@ row \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Here's another one. Note the blank line between rows. \end{minipage} -\\\noalign{\medskip} -\hline +\\\addlinespace +\bottomrule \end{longtable} diff --git a/tests/test-pandoc.hs b/tests/test-pandoc.hs index 67ca5eae2..ae521541a 100644 --- a/tests/test-pandoc.hs +++ b/tests/test-pandoc.hs @@ -38,4 +38,7 @@ tests = [ testGroup "Old" Tests.Old.tests main :: IO () main = do setLocaleEncoding utf8 - inDirectory "tests" $ defaultMain tests + -- we ignore command-line arguments, since we're having cabal pass + -- the build directory as first argument, and we don't want test-framework + -- to choke on that. + inDirectory "tests" $ defaultMainWithArgs tests [] diff --git a/tests/writer.context b/tests/writer.context index 114d00b3c..0b031fd76 100644 --- a/tests/writer.context +++ b/tests/writer.context @@ -30,6 +30,9 @@ \setupitemize[autointro] % prevent orphan list intro \setupitemize[indentnext=no] +\setupfloat[figure][default={here,nonumber}] +\setupfloat[table][default={here,nonumber}] + \setupthinrules[width=15em] % width of horizontal rules \setupdelimitedtext @@ -842,7 +845,7 @@ or here: <http://example.com/> From \quotation{Voyage dans la Lune} by Georges Melies (1902): -\placefigure[here,nonumber]{lalune}{\externalfigure[lalune.jpg]} +\placefigure{lalune}{\externalfigure[lalune.jpg]} Here is a movie {\externalfigure[movie.jpg]} icon. diff --git a/tests/writer.docbook b/tests/writer.docbook index e427d8ffc..1d4da4842 100644 --- a/tests/writer.docbook +++ b/tests/writer.docbook @@ -1084,7 +1084,7 @@ These should not be escaped: \$ \\ \> \[ \{ <listitem> <para> Here’s some display math: - $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$ + $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ </para> </listitem> <listitem> diff --git a/tests/writer.html b/tests/writer.html index e8e619f44..d00b8ca66 100644 --- a/tests/writer.html +++ b/tests/writer.html @@ -439,7 +439,7 @@ Blah <li><span class="math"><em>α</em> ∧ <em>ω</em></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: <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 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>α</em> + <em>ω</em> × <em>x</em><sup>2</sup></span>.</li> </ul> <p>These shouldn’t be math:</p> @@ -544,12 +544,12 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'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> +<p>Here is a footnote reference,<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> and another.<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a> This should <em>not</em> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a></p> <blockquote> -<p>Notes can go in quotes.<sup><a href="#fn4" class="footnoteRef" id="fnref4">4</a></sup></p> +<p>Notes can go in quotes.<a href="#fn4" class="footnoteRef" id="fnref4"><sup>4</sup></a></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> +<li>And in list items.<a href="#fn5" class="footnoteRef" id="fnref5"><sup>5</sup></a></li> </ol> <p>This paragraph should not be part of the note, as it is not indented.</p> <div class="footnotes"> diff --git a/tests/writer.man b/tests/writer.man index 54baaf791..aab588f9c 100644 --- a/tests/writer.man +++ b/tests/writer.man @@ -572,7 +572,7 @@ Ellipses\&...and\&...and\&.... .IP \[bu] 2 Here's some display math: .RS -$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)\-f(x)}{h}$ +$$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)\-f(x)}{h}$$ .RE .IP \[bu] 2 Here's one that has a line break in it: diff --git a/tests/writer.opendocument b/tests/writer.opendocument index 1cee01f76..81c793a62 100644 --- a/tests/writer.opendocument +++ b/tests/writer.opendocument @@ -1,5 +1,8 @@ <?xml version="1.0" encoding="utf-8" ?> <office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.2"> + <office:font-face-decls> + <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" /> + </office:font-face-decls> <office:automatic-styles> <text:list-style style:name="L1"> <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix="."> @@ -665,37 +668,47 @@ <style:style style:name="T35" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style> <style:style style:name="T36" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style> <style:style style:name="T37" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style> - <style:style style:name="T38" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> - <style:style style:name="T39" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> - <style:style style:name="T40" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> - <style:style style:name="T41" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> - <style:style style:name="T42" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style> + <style:style style:name="T38" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></style:style> + <style:style style:name="T39" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></style:style> + <style:style style:name="T40" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></style:style> + <style:style style:name="T41" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></style:style> + <style:style style:name="T42" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></style:style> <style:style style:name="T43" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> - <style:style style:name="T44" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style> - <style:style style:name="T45" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style> - <style:style style:name="T46" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style> - <style:style style:name="T47" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style> - <style:style style:name="T48" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style> - <style:style style:name="T49" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style> - <style:style style:name="T50" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T51" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T52" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T53" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T54" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T55" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> + <style:style style:name="T44" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> + <style:style style:name="T45" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> + <style:style style:name="T46" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> + <style:style style:name="T47" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style> + <style:style style:name="T48" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style> + <style:style style:name="T49" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style> + <style:style style:name="T50" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style> + <style:style style:name="T51" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style> + <style:style style:name="T52" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style> + <style:style style:name="T53" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style> + <style:style style:name="T54" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style> + <style:style style:name="T55" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></style:style> <style:style style:name="T56" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> <style:style style:name="T57" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T58" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style> + <style:style style:name="T58" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> <style:style style:name="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="T63" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T64" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> - <style:style style:name="T65" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style> + <style:style style:name="T64" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style> + <style:style style:name="T65" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></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="T67" style:family="text"><style:text-properties style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></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:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></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 style:font-name="Courier New" style:font-name-asian="Courier New" style:font-name-complex="Courier New" /></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> @@ -1345,22 +1358,22 @@ Markup</text:h> <text:p text:style-name="Text_20_body">So is <text:span text:style-name="T37">this</text:span> word.</text:p> <text:p text:style-name="Text_20_body">This is code: -<text:span text:style-name="Teletype">></text:span>, -<text:span text:style-name="Teletype">$</text:span>, -<text:span text:style-name="Teletype">\</text:span>, -<text:span text:style-name="Teletype">\$</text:span>, -<text:span text:style-name="Teletype"><html></text:span>.</text:p> -<text:p text:style-name="Text_20_body"><text:span text:style-name="T38">This</text:span><text:span text:style-name="T39"> -</text:span><text:span text:style-name="T40">is</text:span><text:span text:style-name="T41"> -</text:span><text:span text:style-name="T42">strikeout</text:span><text:span text:style-name="T43">.</text:span></text:p> +<text:span text:style-name="T38">></text:span>, +<text:span text:style-name="T39">$</text:span>, +<text:span text:style-name="T40">\</text:span>, +<text:span text:style-name="T41">\$</text:span>, +<text:span text:style-name="T42"><html></text:span>.</text:p> +<text:p text:style-name="Text_20_body"><text:span text:style-name="T43">This</text:span><text:span text:style-name="T44"> +</text:span><text:span text:style-name="T45">is</text:span><text:span text:style-name="T46"> +</text:span><text:span text:style-name="T47">strikeout</text:span><text:span text:style-name="T48">.</text:span></text:p> <text:p text:style-name="Text_20_body">Superscripts: -a<text:span text:style-name="T44">bc</text:span>d -a<text:span text:style-name="T45">hello</text:span> -a<text:span text:style-name="T46">hello there</text:span>.</text:p> +a<text:span text:style-name="T49">bc</text:span>d +a<text:span text:style-name="T50">hello</text:span> +a<text:span text:style-name="T51">hello there</text:span>.</text:p> <text:p text:style-name="Text_20_body">Subscripts: -H<text:span text:style-name="T47">2</text:span>O, -H<text:span text:style-name="T48">23</text:span>O, -H<text:span text:style-name="T49">many of them</text:span>O.</text:p> +H<text:span text:style-name="T52">2</text:span>O, +H<text:span text:style-name="T53">23</text:span>O, +H<text:span text:style-name="T54">many of them</text:span>O.</text:p> <text:p text:style-name="Text_20_body">These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</text:p> <text:p text:style-name="Horizontal_20_Line" /> @@ -1374,7 +1387,7 @@ trees. So is ‘pine.’</text:p> <text:p text:style-name="Text_20_body">‘He said, “I want to go.”’ Were you alive in the 70’s?</text:p> <text:p text:style-name="Text_20_body">Here is some quoted -‘<text:span text:style-name="Teletype">code</text:span>’ and a +‘<text:span text:style-name="T55">code</text:span>’ and a “<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">quoted link</text:span></text:a>”.</text:p> <text:p text:style-name="Text_20_body">Some dashes: one—two — three—four — @@ -1392,35 +1405,35 @@ five.</text:p> <text:p text:style-name="P51">2 + 2 = 4</text:p> </text:list-item> <text:list-item> - <text:p text:style-name="P51"><text:span text:style-name="T50">x</text:span> ∈ <text:span text:style-name="T51">y</text:span></text:p> + <text:p text:style-name="P51"><text:span text:style-name="T56">x</text:span> ∈ <text:span text:style-name="T57">y</text:span></text:p> </text:list-item> <text:list-item> - <text:p text:style-name="P51"><text:span text:style-name="T52">α</text:span> ∧ <text:span text:style-name="T53">ω</text:span></text:p> + <text:p text:style-name="P51"><text:span text:style-name="T58">α</text:span> ∧ <text:span text:style-name="T59">ω</text:span></text:p> </text:list-item> <text:list-item> <text:p text:style-name="P51">223</text:p> </text:list-item> <text:list-item> - <text:p text:style-name="P51"><text:span text:style-name="T54">p</text:span>-Tree</text:p> + <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’s some display math: - $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</text:p> + $$\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’s one that has a line break in it: - <text:span text:style-name="T55">α</text:span> + <text:span text:style-name="T56">ω</text:span> × <text:span text:style-name="T57">x</text:span><text:span text:style-name="T58">2</text:span>.</text:p> + <text:span text:style-name="T61">α</text:span> + <text:span text:style-name="T62">ω</text:span> × <text:span text:style-name="T63">x</text:span><text:span text:style-name="T64">2</text:span>.</text:p> </text:list-item> </text:list> <text:p text:style-name="First_20_paragraph">These shouldn’t be math:</text:p> <text:list text:style-name="L27"> <text:list-item> <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:span text:style-name="T65">$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="T59">lot</text:span> of money. So is $34,000. + <text:span text:style-name="T66">lot</text:span> of money. So is $34,000. (It worked if “lot” is emphasized.)</text:p> </text:list-item> <text:list-item> @@ -1428,11 +1441,11 @@ five.</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="T60">this</text:span><text:span text:style-name="T61"> - </text:span><text:span text:style-name="T62">should</text:span><text:span text:style-name="T63"> - </text:span><text:span text:style-name="T64">be</text:span><text:span text:style-name="T65"> - </text:span><text:span text:style-name="T66">emphasized</text:span> + <text:span text:style-name="T67">$</text:span>: $73 + <text:span text:style-name="T68">this</text:span><text:span text:style-name="T69"> + </text:span><text:span text:style-name="T70">should</text:span><text:span text:style-name="T71"> + </text:span><text:span text:style-name="T72">be</text:span><text:span text:style-name="T73"> + </text:span><text:span text:style-name="T74">emphasized</text:span> 23$.</text:p> </text:list-item> </text:list> @@ -1557,15 +1570,15 @@ link in pointy braces</text:span></text:a>.</text:p> <text:p text:style-name="P56">Blockquoted: <text:a xlink:type="simple" xlink:href="http://example.com/" office:name=""><text:span text:style-name="Definition">http://example.com/</text:span></text:a></text:p> <text:p text:style-name="First_20_paragraph">Auto-links should not occur here: -<text:span text:style-name="Teletype"><http://example.com/></text:span></text:p> +<text:span text:style-name="T75"><http://example.com/></text:span></text:p> <text:p text:style-name="P57">or here: <http://example.com/></text:p> <text:p text:style-name="Horizontal_20_Line" /> <text:h text:style-name="Heading_20_1" text:outline-level="1">Images</text:h> <text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by Georges Melies (1902):</text:p> -<text:p text:style-name="Text_20_body"><draw:frame><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p> +<text:p text:style-name="Text_20_body"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p> <text:p text:style-name="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> +<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame> icon.</text:p> <text:p text:style-name="Horizontal_20_Line" /> <text:h text:style-name="Heading_20_1" text:outline-level="1">Footnotes</text:h> @@ -1581,14 +1594,14 @@ 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" />{ <code> }</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="T67">not</text:span> be a footnote +should <text:span text:style-name="T76">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="T68">easier</text:span> to type. Inline notes +is <text:span text:style-name="T77">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> +and <text:span text:style-name="T78">]</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> diff --git a/tests/writer.rtf b/tests/writer.rtf index 42c13d8c7..954d95cc4 100644 --- a/tests/writer.rtf +++ b/tests/writer.rtf @@ -269,7 +269,7 @@ quoted link {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i \u945?}\u8197?\u8743?\u8197?{\i \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\{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 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: {\i \u945?}\u8197?+\u8197?{\i \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} diff --git a/windows/make-windows-installer.bat b/windows/make-windows-installer.bat index 5890479ae..d27859057 100644 --- a/windows/make-windows-installer.bat +++ b/windows/make-windows-installer.bat @@ -2,12 +2,14 @@ cd ..
cabal update
cabal-dev clean
+cabal install hsb2hs cabal-dev
if %errorlevel% neq 0 exit /b %errorlevel%
-cabal-dev install hsb2hs
-cabal-dev install --only-dependencies --force --reinstall --flags="embed_data_files"
-cabal-dev install --reinstall --flags="embed_data_files"
+cabal-dev install -v1 --force --reinstall --flags="embed_data_files"
+if %errorlevel% neq 0 exit /b %errorlevel%
+cabal-dev install -v1 --reinstall --flags="embed_data_files" pandoc-citeproc
if %errorlevel% neq 0 exit /b %errorlevel%
strip cabal-dev\bin\pandoc.exe
+strip cabal-dev\bin\pandoc-citeproc.exe
cabal-dev\bin\pandoc.exe -s --template data\templates\default.html -S README -o README.html
if %errorlevel% neq 0 exit /b %errorlevel%
cabal-dev\bin\pandoc.exe -s --template data\templates\default.rtf COPYING -t rtf -S -o COPYING.rtf
diff --git a/windows/pandoc.wxs b/windows/pandoc.wxs index 2c87e41e9..7a20effe5 100644 --- a/windows/pandoc.wxs +++ b/windows/pandoc.wxs @@ -55,11 +55,8 @@ Guid="0A214839-2E69-4026-8DBB-0F0A9DB75C12">
<RegistryValue Root="HKMU" Key="Software\John MacFarlane\Pandoc"
Name="Version" Type="string" Value="[ProductVersion]" KeyPath="yes"/>
- <RemoveFolder Id="APPLICATIONFOLDER" On="uninstall"/>
<File Id="pandoc_citeprocEXE" Name="pandoc-citeproc.exe"
Source="..\cabal-dev\bin\pandoc-citeproc.exe" />
- <File Id="biblio2yamlEXE" Name="biblio2yaml.exe"
- Source="..\cabal-dev\bin\biblio2yaml.exe" />
</Component>
<Component Id="UpdatePathUser"
@@ -113,6 +110,9 @@ <ComponentRef Id="Documentation" />
<ComponentRef Id="ApplicationShortcut" />
</Feature>
+ <Feature Id="Citation" Title="Citation Support" Description="Citation support.">
+ <ComponentRef Id="CitationSupport" />
+ </Feature>
</Feature>
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER" />
|