pandoc-1.12.2.1/000755 000765 000024 00000000000 12251233602 013114 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/benchmark/000755 000765 000024 00000000000 12251233602 015046 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/BUGS000644 000765 000024 00000000236 12251233602 013600 0ustar00jgmstaff000000 000000 To view a list of known bugs, or to enter a bug report, please use Pandoc's issue tracker: . See also CONTRIBUTING.md. pandoc-1.12.2.1/changelog000644 000765 000024 00000765473 12251233602 015014 0ustar00jgmstaff000000 000000 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: . + 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 `` element. * OpenDocument writer: Skip raw HTML (#1035). Previously it was erroneously included as verbatim text. * HTML/EPUB writer, footnotes: Put `` tag inside `` tags. This allows better control of formatting, since the `` 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 `` 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 `
`, `` 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 `
`. * Slides: Preserve `
` 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 `` 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 `
` and `` 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. * 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. * Made `stringify` polymorphic in `Text.Pandoc.Shared`. * 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). * `Text.Pandoc.Options`: + 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`. * 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`. [bug fixes] * In markdown, don't autolink a bare URI that is followed by `` (#937). * `Text.Pandoc.Shared` + `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). * 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). * `Text.Pandoc.PDF` + 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`. * Produce automatic header identifiers in parsing textile, RST, and LaTeX, unless `auto_identifiers` extension is disabled (#967). * `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: (#739). Handle `src` in `embed`, `audio`, `source`, `input` tags. * `Text.Pandoc.Parsing`: `uri` parser no longer treats punctuation before percent-encoding, or a `+` character, as final punctuation. * `Text.Pandoc.ImageSize`: Handle EPS (#903). This change will make EPS images properly sized on conversion to Word. * 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 + 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). + Allow internal `+` in citation identifiers (#856). + 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. + Allow backtick code blocks not to be preceded by blank line (#975). * Textile reader: + Correctly handle entities. + Improved handling of `
` blocks (#927). Remove internal HTML tags
      in code blocks, rather than printing them verbatim. Parse attributes
      on `
` tag for code blocks.

  * HTML reader: Handle non-simple tables (#893).  Column widths are read from
    `col` tags if present, otherwise divided equally.

  * LaTeX reader

    + Support alltt environment (#892).
    + Support `\textasciitilde`, `\textasciicircum` (#810).
    + Treat `\textsl` as emphasized text reader (#850).
    + Skip positional options after `\begin{figure}`.
    + Support `\v{}` for hacek (#926).
    + Don't add spurious ", " to citation suffixes.
      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 `

` 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. + Fixed regression for `URL`. `<` is no longer allowed in URLs, according to the uri parser in `Text.Pandoc.Parsing`. Added a test case. + Correctly handle indented preformatted text without preceding or following blank line. + Fixed `|` links inside table cells. Improved attribute parsing. + 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 + Don't use ligatures in escaping inline code. + Fixed footnote numbers in LaTeX/PDF tables. This fixes a bug wherein notes were numbered incorrectly in tables (#827). + Always create labels for sections. Previously the labels were only created when there were links to the section in the document (#871). + Stop escaping `|` in LaTeX math. This caused problems with array environments (#891). + Change `\` to `/` in paths. `/` works even on Windows in LaTeX. `\` will cause major problems if unescaped. + Write id for code block to label attribute in LaTeX when listings is used (thanks to Florian Eitel). + 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 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). * MediaWiki writer: Use native mediawiki tables instead of HTML (#720). * HTML writer: + Fixed `--no-highlight` (Alexander Kondratskiy). + Don't convert to lowercase in email obfuscation (#839). + Ensure proper escaping in `` and `<meta>` fields. * AsciiDoc writer: + Support `--atx-headers` (Max Rydahl Andersen). + Don't print empty identifier blocks `([[]])` on headers (Max Rydahl Andersen). * ODT writer: + Fixing wrong numbered-list indentation in open document format (Alexander Kondratskiy) (#369). + `reference.odt`: Added pandoc as "generator" in `meta.xml`. + Minor changes for ODF 1.2 conformance (#939). We leave the nonconforming `contextual-spacing` attribute, which is provided by LibreOffice itself and seems well supported. * 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 item. Now it always appears centered, just as outside of lists, and in proper display math style, no matter how far indented the 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, 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 `reference.docx`, ignoring everything else. This should help with the corruption problems caused when different versions of Word resave the reference.docx and reorganize things. + Made `--no-highlight` work properly. * EPUB writer + Don't add `dc:creator` tags if present in EPUB metadata. + Add `id="toc-title"` to `h1` in `nav.xhtml` (#799). + Don't put blank title page in reading sequence. Set `linear="no"` if no title block. Addresses #797. + Download webtex images and include as data URLs. This allows you to use `--webtex` in creating EPUBs. Math with `--webtex` is automatically made self-contained. + In `data/epub.css`, removed highlighting styles (which are no longer needed, since styles are added by the HTML writer according to `--highlighting-style`). Simplified margin fields. + If resource not found, skip it, as in Docx writer (#916). * 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: + Only autolink absolute URIs. This fixes a regression, #830. + Don't wrap attributes in fenced code blocks. + 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. * `Text.Pandoc.Templates`: + 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. * Citation processing improvements (now part of pandoc-citeproc): + 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). * 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. * 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` + Generalized state type on `readWith` (API change). + Specialize readWith to `String` input. (API change). + In `ParserState`, replace `stateTitle`, `stateAuthors`, `stateDate` with `stateMeta` and `stateMeta'`. * `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). * 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, which is now needed by the HTML writer (#803). * Added `http-conduit` flag, which allows fetching https resources. It also brings in a large number of dependencies (`http-conduit` and its dependencies), which is why for now it is an optional flag (#820). * Added CONTRIBUTING.md. * Improved INSTALL instructions. * `make-windows-installer.bat`: Removed explicit paths for executables. * `aeson` is now used instead of `json` for JSON. * Set default stack size to 16M. This is needed for some large conversions, esp. if pandoc is compiled with 64-bit ghc. * 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: + Fixed regression in which parentheses were lost in link URLs. Added tests. Closes #786. + Better handling of unmatched double quotes in `--smart` mode. These occur frequently in fiction, since it is customary not to close quotes in dialogue if the speaker does not change between 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. * Markdown writer: Reverted 1.11 change that caused citations to be rendered as markdown citations, even if `--bibliography` was specified, unless `citation` extension is disabled. Now, formatted citations are always printed if `--bibliography` was specified. If you want to reformat markdown keeping pandoc markdown citations intact, don't use `--bibliography`. Note that citations parsed from LaTeX documents will be rendered as pandoc markdown citations when `--bibliography` is not specified. * ODT writer: Fixed regression leading to corrupt ODTs. This was due to a change in the `Show` instance for `Text.Pandoc.Pretty.Doc`. Closes #780. * Fixed spacing bugs involving code block attributes in RST reader and Markdown writer. Closes #763. * Windows package: Various improvements due to Fyodor Sheremetyev. + Automatically set installation path (Program Files or Local App Data). + Set system PATH environment variable when installing for all users. + Pandoc can installed for all users using the following command. `msiexec /i pandoc-1.11.msi ALLUSERS=1`. * Bumped QuickCheck version bound. 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. * `--version` now reports the default data directory. * `Text.Pandoc.Parsing` is no longer exposed. (API change.) * `Text.Pandoc.Highlighting` is no longer exposed. (API change.) * `Text.Pandoc.Shared`: Changed type of `Element`. `Sec` now includes a field for `Attr` rather than just `String`. (API change.) * Added `markdown_github` as input format. This was an accidental omission in 1.10. * Added `readerDefaultImageExtension` field to `ReaderOptions`. (API change.) * Added `writerNumberOffset` field in `WriterOptions`. (API change.) * Beamer template: + Fixed captions with longtable. Thanks to Joost Kremers. + Provide `\Oldincludegraphics` as in LaTeX template (Benjamin Bannier). * LaTeX template: + Load microtype after fonts. Microtype needs to know what fonts are being used. Thanks to dfc for the patch. + Set `secnumdepth` to 5 if `--number-sections` specified. This yields behavior equivalent to the other writers, numbering level 4 and 5 headers too. Closes #753. * HTML reader: + Handle `<colgroup>` tag. + Preserve all header attributes. * LaTeX reader: + Parse `\hrule` as `HorizontalRule`. Closes #746. + Parse starred variants of `\section` etc. as headers with attribute `unnumbered`. + Read optional attributes in `lstlisting` and `Verbatim` environments. We convert these to pandoc standard names, e.g. `numberLines` for `numbers=left`, `startFrom=100` from `firstnumber=100`. + Handle language attribute for lstlistings. + 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. + Fixed bug parsing key/value attributes. Parsing failed if you had an unquoted attribute immediately before the final '}'. + Make backslash escape work in attributes. + Fix title block parsing. Now if `mmd_title_blocks` is specified, pandoc will parse a MMD title block if it sees one, even if `pandoc_title_blocks` is enabled. + Refactoring: `litChar` now includes entities, so we don't need to use `fromEntities` e.g. on titles. + Allow spaces around borders in pipe tables. Closes #772. + Allow all punctuation in angle-bracket autolinks. Previously things like `----` were disallowed, because the uri parser treated them as trailing punctuation. Closes #768. + Make `implicit_header_references` work properly when headers are given explicit identifiers. + Check for tables before line blocks. Otherwise some pipe tables get treated as line blocks. + Allow `&` in emails (for entities). + Properly handle entities in titles and links. A markdown link `<http://göogle.com>` should be a link to `http://göogle.com`. Closes #723. * Textile reader: + Handle attributes on headers. * LaTeX reader: + Add `fig:` as title for images with captions. This is needed for them to be rendered as figures. Closes #766. + Never emit an empty paragraph. See #761. + Handle `\caption` for images in figures. Closes #766. + Parse `\section*`, etc. as unnumbered sections. * HTML writer: + Support header attributes. The attributes go on the enclosing `section` or `div` tag if `--section-divs` is specified. + Fixed a regression (only now noticed) in html+lhs output. Previously the bird tracks were being omitted. * LaTeX writer: + Omit lists with no items to avoid LaTeX errors. + Support line numbering with `--listings`. If `numberLines` class is present, we add `numbers=left`; if `startFrom` is present, we add `firstnumber=`. (#763) * ConTeXt writer: + Removed `\placecontent`. This produced a duplicate toc, in conjunction with `\placelist`. + Use `\title`, `\subject` etc. for headers with `unnumbered` class. * Textile writer: + Support header attributes. * Markdown writer: + Use grid tables when needed, and if enabled. Closes #740. + Render citations as pandoc-markdown citations. Previously citations were rendered as citeproc-formatted citations by default. Now we render them as pandoc citations, e.g. `[@item1]`, unless the `citations` extension is disabled. If you still want formatted citations in your markdown output, 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). Partially addresses #742. + Content types and document rels xml files are now created from scratch, rather than being taken over from `reference.docx`. This fixes problems that arise when you edit the `reference.docx` with Word. + We also now encode mime types for each individual image rather than using defaults. This should allow us to handle a wider range of image types (including PDF). Closes #414. + Changed style names in `reference docx`. `FootnoteReference` -> `FootnoteRef`, `Hyperlink` -> `Link`. The old names got changed by Word when the `reference.docx` was 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. + Headers with "unnumbered" attribute are not numbered. (Nor do they cause an increment in running numbering.) Section numbers now work properly, even when there is material before the first numbered section. + Include HTML TOC, even in epub2. The TOC is included in `<spine>`, but `linear` is set to `no` unless the `--toc` option is specified. Include `<guide>` element in OPF. This should allow the TOC to be useable in Kindles when converted with kindlegen. Closes #773. * `Text.Pandoc.Parsing`: Optimized `oneOfStringsCI`. This dramatically reduces the speed penalty that comes from enabling the `autolink_bare_uris` extension. The penalty is still substantial (in one test, from 0.33s to 0.44s), but nowhere near what it used to be. The RST reader is also much faster now, as it autodetects URIs. * `Text.Pandoc.Shared`: `hierarchicalize` will not number section with class "unnumbered". Unnumbered sections get `[]` for their section number. * `Text.Pandoc.Pretty`: + Fixed `chomp` so it works inside `Prefixed` elements. + Changed `Show` instance so it is better for debugging. * `Text.Pandoc.ImageSize`: Added `Pdf` to `ImageType`. * `Text.Pandoc.UTF8`: Strip off BOM if present. Closes #743. * Windows installer improvements: + The installer is now signed with a certificate (thanks to Fyodor Sheremetyev). + WiX is used instead of InnoSetup. The installer is now a standard msi file. + The version number is now auto-detected, and need not be updated separately. * OSX installer improvements: + The package and pandoc executable are now signed with a certificate (thanks to Fyodor Sheremetyev). + RTF version of license is used. + Use full path for sysctl in `InstallationCheck` script (jonahbull). Closes #580. * Converted COPYING to markdown. * pandoc.cabal: Require latest versions of highlighting-kate, texmath, citeproc-hs, zip-archive. pandoc (1.10.1) * Markdown reader: various optimizations, leading to a significant performance boost. * RST reader: Allow anonymous form of inline links: `` `hello <url>`__ `` Closes #724. * Mediawiki reader: Don't require newlines after tables. Thanks to jrunningen for the patch. Closes #733. * Fixed LaTeX macro parsing. Now LaTeX macro definitions are preserved when output is LaTeX, and applied when it is another format. Partially addresses #730. * Markdown and RST readers: Added parser to `block` that skips blank lines. This fixes a subtle regression involving grid tables with empty cells. Also added test for grid table with empty cells. Closes #732. * RST writer: Use `.. code:: language` for code blocks with language. Closes #721. * DocBook writer: Fixed output for hard line breaks, adding a newline between `<literallayout>` tags. * Markdown writer: Use an autolink when link text matches url. Previously we also checked for a null title, but this test fails for links produced by citeproc-hs in bibliographies. So, if the link has a title, it will be lost on conversion to an autolink, but that seems okay. * Markdown writer: Set title, author, date variables as before. These are no longer used in the default template, since we use titleblock, but we set them anyway for those who use custom templates. * LaTeX writer: Avoid extra space at start/end of table cell. 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`. * Relaxed old-time version bound, allowing 1.0.*. * Removed obsolete `hsmarkdown` script. Those who need `hsmarkdown` should create a symlink as described in the README. pandoc (1.10.0.5) * Markdown reader: Try `lhsCodeBlock` before `rawTeXBlock`. Otherwise `\begin{code}...\end{code}` isn't handled properly in markdown+lhs. Thanks to Daniel Miot for noticing the bug and suggesting the fix. * Markdown reader: Fixed bug with headerless grid tables. The 1.10 code assumed that each table header cell contains exactly one block. That failed for headerless tables (0) and also for tables with multiple blocks in a header cell. The code is fixed and tests provided. 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}`). + Backtick code blocks can take the curly-bracketed attributes. + Backtick code blocks don't *require* a language. + Consolidated code for the two kinds of fenced code blocks. * LaTeX template: Use `\urlstyle{same}` to avoid monospace URLs. * Markdown writer: Use proportional font for email autolinks with obfuscation. Closes #714. * Corrected name of `blank_before_blockquote` in README. Closes #718. * `Text.Pandoc.Shared`: Fixed bug in `uri` parser. The bug prevented an autolink at the end of a string (e.g. at the end of a line block line) from counting as a link. Closes #711. * Use the `hsb2hs` preprocessor instead of TH for embed_data_files. This should work on Windows, unlike the TH solution with file-embed. * Eliminated use of TH in test suite. * Added `Text.Pandoc.Data` (non-exported) to hold the association list of embedded data files, if the `embed_data_files` flag is selected. This isolates the code that needs special treatment with file-embed or `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. + Force reinstall of pandoc. * Fixed EPUB writer so it builds with blaze-html 0.4.x. Thanks to Jens Petersen. pandoc (1.10.0.4) * Fixed bug with escaped % in LaTeX reader. Closes #710. pandoc (1.10.0.3) * Added further missing fb2 tests to cabal file. pandoc (1.10.0.2) * Added fb2 tests to cabal file's extra-source-files. pandoc (1.10.0.1) * Bump version bounds on test-framework packages. pandoc (1.10) [new features] * New input formats: `mediawiki` (MediaWiki markup). * New output formats: `epub3` (EPUB v3 with MathML), `fb2` (FictionBook2 ebooks). * New `--toc-depth` option, specifying how many levels of headers to include in a table of contents. * New `--epub-chapter-level` option, specifying the header level at which to divide EPUBs into separate files. Note that this normally affects only performance, not the visual presentation of the EPUB in a reader. * Removed the `--strict` option. Instead of using `--strict`, one can now use the format name `markdown_strict` for either input or output. This gives more fine-grained control that `--strict` did, allowing one to convert from pandoc's markdown to strict markdown or vice versa. * It is now possible to enable or disable specific syntax extensions by appending them (with `+` or `-`) to the writer or reader name. For example, pandoc -f markdown-footnotes+hard_line_breaks disables footnotes and enables treating newlines as hard line breaks. The literate Haskell extensions are now implemented this way as well, using either `+lhs` or `+literate_haskell`. For a list of extension names, see the README under "Pandoc's Markdown." * The following aliases have been introduced for specific combinations of markdown extensions: `markdown_phpextra`, `markdown_github`, `markdown_mmd`, `markdown_strict`. These aliases work just like regular reader and writer names, and can be modified with extension modifiers as described above. (Note that conversion from one markdown dialect to another does not work perfectly, because there are differences in markdown parsers besides just the extensions, and because pandoc's internal document model is not rich enough to capture all of the extensions.) * New `--html-q-tags` option. The previous default was to use `<q>` tags for smart quotes in HTML5. But `<q>` tags are also valid HTML4. Moreover, they are not a robust way of typesetting quotes, since some user agents don't support them, and some CSS resets (e.g. bootstrap) prevent pandoc's quotes CSS from working properly. We now just insert literal quote characters by default in both `html` and `html5` output, but this option is provided for those who still want `<q>` tags. * The markdown reader now prints warnings (to stderr) about duplicate link and note references. Closes #375. * Markdown syntax extensions: + Added pipe tables. Thanks to François Gannaz for the initial patch. These conform to PHP Markdown Extra's pipe table syntax. A subset of org-mode table syntax is also supported, which means that you can use org-mode's nice table editor to create tables. + Added support for RST-style line blocks. These are useful for verse and addresses. + Attributes can now be specified for headers, using the same syntax as in code blocks. (However, currently only the identifier has any effect in most writers.) For example, # My header {#foo} See [the header above](#foo). + Pandoc will now act as if link references have been defined for all headers without explicit identifiers. So, you can do this: # My header Link to [My header]. Another link to [it][My header]. Closes #691. * LaTeX reader: + Command macros now work everywhere, including non-math. Environment macros still not supported. + `\input` now works, as well as `\include`. TEXINPUTS is used. Pandoc looks recursively into included files for more included files. [behavior changes] * The Markdown reader no longer puts the text of autolinks in a `Code` inline. This means that autolinks will no longer appear in a monospace font. * The character `/` can now appear in markdown citation keys. * HTML blocks in strict_markdown are no longer required to begin at the left margin. Technically this is required, according to the markdown syntax document, but `Markdown.pl` and other markdown processors are more liberal. * The `-V` option has been changed so that if there are duplicate variables, those specified later on the command line take precedence. * Tight lists now work in LaTeX and ConTeXt output. * The LaTeX writer no longer relien on the `enumerate` package. Instead, it uses standard LaTeX commands to change the list numbering style. * The LaTeX writer now uses `longtable` instead of `ctable`. This allows tables to be split over page boundaries. * The RST writer now uses a line block to render paragraphs containing linebreaks (which previously weren't supported at all). * The markdown writer now applies the `--id-prefix` to footnote IDs. Closes #614. * The plain writer no longer uses backslash-escaped line breaks (which are not very "plain"). * `Text.Pandoc.UTF8`: Better error message for invalid UTF8. Read bytestring and use `Text`'s decodeUtf8 instead of using `System.IO.hGetContents`. This way you get a message saying "invalid UTF-8 stream" instead of "invalid byte sequence." You are also told which byte caused the problem. * Docx, ODT, and EPUB writers now download images specified by a URL instead of skipping them or raising an error. * EPUB writer: + The default CSS now left-aligns headers by default, instead of centering. This is more consistent with the rest of the writers. + A proper multi-level table of contents is now used in `toc.ncx`. There is no longer a subsidiary table of contents at the beginning of each chapter. + Code highlighting now works by default. + Section divs are used by default for better semantic markup. + The title is used instead of "Title Page" in the table of contents. Otherwise we have a hard-coded English string, which looks strange in ebooks written in other languages. Closes #572. * HTML writer: + Put mathjax in span with class "math". Closes #562. + Put citations in a span with class "citation." In HTML5, also include a `data-cite` attribute with a space-separated list of citation keys. * `Text.Pandoc.UTF8`: use universalNewlineMode in reading. This treats both `\r\n` and `\n` as `\n` on input, no matter what platform we're running on. * Citation processing is now done in the Markdown and LaTeX readers, not in `pandoc.hs`. This makes it easier for library users to use citations. [template changes] * HTML: Added css to template to preserve spaces in `<code>` tags. Thanks to Dirk Laurie. * Beamer: Remove English-centric strings in section pages. Section pages used to have "Section" and a number as well as the section title. Now they just have the title. Similarly for part and subsection. Closes #566. * LaTeX, ConTeXt: Added papersize variable. * LaTeX, Beamer templates: Use longtable instead of ctable. * LaTeX, Beamer templates: Don't require 'float' package for tables. We don't actually seem to use the '[H]' option. * LaTeX: Use `upquote` package if it is available. This fixes straight quotes in verbatim environments. * Markdown, plain: Fixed titleblock so it is just a single string. Previously separate title, author, and date variables were used, but this didn't allow different kinds of title blocks. * EPUB: + Rationalized templates. Previously there were three different templates involved in epub production. There is now just one template, `default.epub` or `default.epub3`. It can now be overridden using `--template`, just like other templates. The titlepage is now folded into the default template. A `titlepage` variable selects it. + UTF-8, lang tag, meta tags, title element. * Added scale-to-width feature to beamer template [API changes] * `Text.Pandoc.Definition`: Added `Attr` field to `Header`. Previously header identifers were autogenerated by the writers. Now they are added in the readers (either automatically or explicitly). * `Text.Pandoc.Builder`: + `Inlines` and `Blocks` are now synonyms for `Many Inline` and `Many Block`. `Many` is a newtype wrapper around `Seq`, with custom Monoid instances for `Many Inline` and `Many Block. This allows `Many` to be made an instance of `Foldable` and `Traversable`. + The old `Listable` class has been removed. + The module now exports `isNull`, `toList`, `fromList`. + The old `Read` and `Show` instances have been removed; derived instances are now used. + Added `headerWith`. * The readers now take a `ReaderOptions` rather than a `ParserState` as a parameter. Indeed, not all parsers use the `ParserState` type; some have a custom state. The motivation for this change was to separate user-specifiable options from the accounting functions of parser state. * New module `Text.Pandoc.Options`. This includes the `WriterOptions` formerly in `Text.Pandoc.Shared`, and its associated data types. It also includes a new type `ReaderOptions`, which contains many options formerly in `ParserState`, and its associated data types: + `ParserState.stateParseRaw` -> `ReaderOptions.readerParseRaw`. + `ParserState.stateColumns` -> `ReaderOptions.readerColumns`. + `ParserState.stateTabStop` -> `ReaderOptions.readerTabStop`. + `ParserState.stateOldDashes` -> `ReaderOptions.readerOldDashes`. + `ParserState.stateLiterateHaskell` -> `ReaderOptions.readerLiterateHaskell`. + `ParserState.stateCitations` -> `ReaderOptions.readerReferences`. + `ParserState.stateApplyMacros` -> `ReaderOptions.readerApplyMacros`. + `ParserState.stateIndentedCodeClasses` -> `ReaderOptions.readerIndentedCodeClasses`. + Added `ReaderOptions.readerCitationStyle`. * `WriterOptions` now includes `writerEpubVersion`, `writerEpubChapterLevel`, `writerEpubStylesheet`, `writerEpubFonts`, `writerReferenceODT`, `writerReferenceDocx`, and `writerTOCDepth`. `writerEPUBMetadata` has been renamed `writerEpubMetadata` for consistency. * Changed signatures of `writeODT`, `writeDocx`, `writeEPUB`, since they no longer stylesheet, fonts, reference files as separate parameters. * Removed `writerLiterateHaskell` from `WriterOptions`, and `readerLiterateHaskell` from `ReaderOptions`. LHS is now handled by an extension (`Ext_literate_haskell`). * Removed deprecated `writerXeTeX`. * Removed `writerStrict` from `WriterOptions`. Added `writerExtensions`. Strict is now handled through extensions. * `Text.Pandoc.Options` exports `pandocExtensions`, `strictExtensions`, `phpMarkdownExtraExtensions`, `githubMarkdownExtensions`, and `multimarkdownExtensions`, as well as the `Extensions` type. * New `Text.Pandoc.Readers.MediaWiki` module, exporting `readMediaWiki`. * New `Text.Pandoc.Writers.FB2` module, exporting `writeFB2` (thanks to Sergey Astanin). * `Text.Pandoc`: + Added `getReader`, `getWriter` to `Text.Pandoc`. + `writers` is now an association list `(String, Writer)`. A `Writer` can be a `PureStringWriter`, an `IOStringWriter`, or an `IOByteStringWriter`. ALL writers are now in the 'writers' list, including the binary writers and FB2 writer. This allows code in `pandoc.hs` to be simplified. + Changed type of `readers`, so all readers are in IO. Users who want pure readers can still get them form the reader modules; this just affects the function `getReader` that looks up a reader based on the format name. The point of this change is to make it possible to print warnings from the parser. * `Text.Pandoc.Parsing`: + `Text.Parsec` now exports all Parsec functions used in pandoc code. No other module directly imports Parsec. This will make it easier to change the parsing backend in the future, if we want to. + `Text.Parsec` is used instead of `Text.ParserCombinators.Parsec`. + Export the type synonym `Parser`. + Export `widthsFromIndices`, `NoteTable'`, `KeyTable'`, `Key'`, `toKey'`, `withQuoteContext`, `singleQuoteStart`, `singleQuoteEnd`, `doubleQuoteStart`, `doubleQuoteEnd`, `ellipses`, `apostrophe`, `dash`, `nested`, `F(..)`, `askF`, `asksF`, `runF`, `lineBlockLines`. + `ParserState` is no longer an instance of `Show`. + Added `stateSubstitutions` and `stateWarnings` to `ParserState`. + Generalized type of `withQuoteContext`. + Added `guardEnabled`, `guardDisabled`, `getOption`. + Removed `failIfStrict`. + `lookupKeySrc` and `fromKey` are no longer exported. * `Data.Default` instances are now provided for `ReaderOptions`, `WriterOptions`, and `ParserState`. `Text.Pandoc` re-exports `def`. Now you can use `def` (which is re-exported by `Text.Pandoc`) instead of `defaultWriterOptions` (which is still defined). Closes #546. * `Text.Pandoc.Shared`: + Added `safeRead`. + Renamed `removedLeadingTrailingSpace` to `trim`, `removeLeadingSpace` to `triml`, and `removeTrailingSpace` to `trimr`. + Count `\r` as space in `trim` functions. + Moved `renderTags'` from HTML reader and `Text.Pandoc.SelfContained` to `Shared`. + Removed `failUnlessLHS`. + Export `compactify'`, formerly in Markdown reader. + Export `isTightList`. + Do not export `findDataFile`. + `readDataFile` now returns a strict ByteString. + Export `readDataFileUTF8` which returns a String, like the old `readDataFile`. + Export `fetchItem` and `openURL`. * `Text.Pandoc.ImageSize`: Use strict, not lazy bytestrings. Removed `readImageSize`. * `Text.Pandoc.UTF8`: Export `encodePath`, `decodePath`, `decodeArg`, `toString`, `fromString`, `toStringLazy`, `fromStringLazy`. * `Text.Pandoc.UTF8` is now an exposed module. * `Text.Pandoc.Biblio`: + csl parameter now a `String` rather than a `FilePath`. + Changed type of `processBiblio`. It is no longer in the IO monad. It now takes a `Maybe Style` argument rather than parameters for CSL and abbrev filenames. (`pandoc.hs` now calls the functions to parse the style file and add abbreviations.) * Markdown reader now exports `readMarkdownWithWarnings`. * `Text.Pandoc.RTF` now exports `writeRTFWithEmbeddedImages` instead of `rtfEmbedImage`. [bug fixes] * Make `--ascii` work properly with `--self-contained`. Closes #568. * Markdown reader: + Fixed link parser to avoid exponential slowdowns. Closes #620. Previously the parser would hang on input like this: [[[[[[[[[[[[[[[[[[hi We fixed this by making the link parser parser characters between balanced brackets (skipping brackets in inline code spans), then parsing the result as an inline list. One change is that [hi *there]* bud](/url) is now no longer parsed as a link. But in this respect pandoc behaved differently from most other implementations anyway, so that seems okay. + Look for raw html/latex blocks before tables. Otherwise the following gets parsed as a table: \begin{code} -------------- -- My comment. \end{code} Closes #578. * RST reader: + Added support for `:target:` on `.. image::` blocks and substitutions. + Field list fixes: - Fixed field lists items with body beginning after a new line (Denis Laxalde). - Allow any char but ':' in names of field lists in RST reader (Denis Laxalde). - Don't allow line breaks in field names. - Require whitespace after field list field names. - Don't create empty definition list for metadata field lists. Previously a field list consisting only of metadata fields (author, title, date) would be parsed as an empty DefinitionList, which is not legal in LaTeX and not needed in any format. + Don't recognize inline-markup starts inside words. For example, `2*2 = 4*1` should not contain an emphasized section. Added test case for "Literal symbols". Closes #569. + Allow dashes as separator in simple tables. Closes #555. + Added support for `container`, `compound`, `epigraph`, `rubric`, `highlights`, `pull-quote`. + Added support for `.. code::`. + Made directive labels case-insensitive. + Removed requirement that directives begin at left margin. This was (correctly) not in earlier releases; docutils doesn't make the requirement. + Added support for `replace::` and `unicode::` substitutions. + Ignore unknown interpreted roles. + Renamed image parser to `subst`, since it now handles all substitution references. * Textile reader: + Allow newlines before pipes in table. Closes #654. + Fixed bug with list items containing line breaks. Now pandoc correctly handles hard line breaks inside list items. Previously they broke list parsing. + Implemented comment blocks. + Fixed bug affected words ending in hyphen. + Properly handle links with surrounding brackets. Square brackets need to be used when the link isn't surrounded by spaces or punctuation, or when the URL ending may be ambiguous. Closes #564. + Removed nullBlock. Better to know about parsing problems than to skip stuff when we get stuck. + Allow ID attributes on headers. + Textile reader: Avoid parsing dashes as strikeout. Previously the input text-- text-- text-- text-- would be parsed with strikeouts rather than dashes. This fixes the problem by requiring that a strikeout delimiting - not be followed by a -. Closes #631. + Expanded list of `stringBreakers`. This fixes a bug on input like "(_hello_)" which should be a parenthesized emphasized "hello". The new list is taken from the PHP source of textile 2.4. + Fixed autolinks. Previously the textile reader and writer incorrectly implented RST-style autolinks for URLs and email addresses. This has been fixed. Now an autolink is done this way: `"$":http://myurl.com`. + Fixed footnotes bug in textile. This affected notes occuring before punctuation, e.g. `foo[1].`. Closes #518. * LaTeX reader: + Better handling of citation commands. + Better handling of `\noindent`. + Added a 'try' in rawLaTeXBlock, so we can handle `\begin` without `{`. Closes #622. + Made `rawLaTeXInline` try to parse block commands as well. This is usually what we want, given how `rawLaTeXInline` is used in the markdown and textile readers. If a block-level LaTeX command is used in the middle of a paragraph (e.g. `\subtitle` inside a title), we can treat it as raw inline LaTeX. + Handle \slash command. Closes #605. + Basic `\enquote` support. + Fixed parsing of paragraphs beginning with a group. Closes #606. + Use curly quotes for bare straight quotes. + Support obeylines environment. Closes #604. + Guard against "begin", "end" in inlineCommand and blockCommand. + Better error messages for environments. Now it should tell you that it was looking for \end{env}, instead of giving "unknown parse error." * HTML reader: + Added HTML 5 tags to list of block-level tags. + HTML reader: Fixed bug in `htmlBalanced`, which caused hangs in parsing certain markdown input using strict mode. + Parse `<q>` as `Quoted DoubleQuote`. + Handle nested `<q>` tags properly. + Modified `htmlTag` for fewer false positives. A tag must start with `<` followed by `!`,`?`, `/`, or a letter. This makes it more useful in the wikimedia and markdown parsers. * DocBook reader: Support title in "figure" element. Closes #650. * MediaWiki writer: + Remove newline after `<br/>` in translation of `LineBreak` There's no particular need for a newline (other than making the generated MediaWiki source look nice to a human), and in fact sometimes it is incorrect: in particular, inside an enumeration, list items cannot have embedded newline characters. (Brent Yorgey) + Use `<code>` not `<tt>` for Code. * Man writer: Escape `-` as `\-`. Unescaped `-`'s become hyphens, while `\-`'s are left as ascii minus signs. That is preferable for use with command-line options. See <http://lintian.debian.org/tags/hyphen-used-as-minus-sign.html>. Thanks to Andrea Bolognani for bringing the issue to our attention. * RST writer: + Improved line block output. Use nonbreaking spaces for initial indent (otherwise lost in HTML and LaTeX). Allow multiple paragraphs in a single line block. Allow soft breaks w continuations in line blocks. + Properly handle images with no alt text. Closes #678. + Fixed bug with links with duplicate text. We now (a) use anonymous links for links with inline URLs, and (b) use an inline link instead of a reference link if the reference link would require a label that has already been used for a different link. Closes #511. + Fixed hyperlinked images. Closes #611. Use `:target:` field when you have a simple linked image. + Don't add `:align: center` to figures. * Texinfo writer: Fixed internal cross-references. Now we insert anchors after each header, and use `@ref` instead of `@uref` for links. Commas are now escaped as `@comma{}` only when needed; previously all commas were escaped. (This change is needed, in part, because `@ref` commands must be followed by a real comma or period.) Also insert a blank line in from of `@verbatim` environments. * DocBook writer: + Made --id-prefix work in DocBook as well as HTML. Closes #607. + Don't include empty captions in figures. Closes #581. * LaTeX writer: + Use `\hspace*` for nonbreaking space after line break, since `~` spaces after a line break are just ignored. Closes #687. + Don't escape `_` in URLs or hyperref identifiers. + Properly escape strings inside \url{}. Closes #576. + Use `[fragile]` only for slides containing code rendered using listings. Closes #649. + Escape `|` as `\vert` in LaTeX math. This avoids a clash with highlighting-kate's macros, which redefine `|` as a short verbatim delimiter. Thanks to Björn Peemöller for raising this issue. + Use minipage rather than parbox for block containers in tables. This allows verbatim code to be included in grid tables. Closes #663. + Prevent paragraphs containing only linebreaks or spaces. * HTML writer: + Included `highlighting-css` for code spans, too. Previously it was only included if used in a code block. Closes #653. + Improved line breaks with `<dd>` tags. We now put a newline between `</dd>` and `<dd>` when there are multiple definitions. + Changed mathjax cdn url so it doesn't use https. (This caused problems when used with `--self-contained`.) See #609. * EPUB writer: + `--number-sections` now works properly. + Don't strip meta and link elements in epub metadata. Patch from aberrancy. Closes #589. + Fixed a couple validation bugs. + Use ch001, ch002, etc. for chapter filenames. This improves sorting of chapters in some readers, which apparently sort ch2 after ch10. Closes #610. * ODT writer: properly set title property (Arlo O'Keeffe). * Docx writer: + Fixed bug with nested lists. Previously a list like 1. one - a - b 2. two would come out with a bullet instead of "2." Thanks to Russell Allen for reporting the bug. + Use `w:cr` in `w:r` instead of `w:br` for linebreaks. This seems to fix a problem viewing pandoc-generated docx files in LibreOffice. + Use integer ids for bookmarks. Closes #626. + Added nsid to abstractNum elements. This helps when merging word documents with numbered or bulleted lists. Closes #627. + Use separate footnotes.xml for notes. This seems to help LibreOffice convert the file, even though it was valid docx before. Closes #637. + Use rIdNN identifiers for r:embed in images. + Avoid reading image files again when we've already processed them. + Fixed typo in `referenc.docx` that prevented image captions from working. Thanks to Huashan Chen. * `Text.Pandoc.Parsing`: + Fixed bug in `withRaw`, which didn't correctly handle the case where nothing is parsed. + Made `emailAddress` parser more correct. Now it is based on RFC 822, though it still doesn't implement quoted strings in email addresses. + Revised URI parser. It now allows many more schemes, allows uppercase URIs, and better handles trailing punctuation and trailing slashes in bare URIs. Added many tests. + Simplified and improved singleQuoteStart. This makes `'s'`, `'l'`, etc. parse properly. Formerly we had some English-centric heuristics, but they are no longer needed. Closes #698. * `Text.Pandoc.Pretty`: Added wide punctuation range to `charWidth`. This fixes bug with Chinese commas in markdown and reST tables, and a bug that caused combining characters to be dropped. * `Text.Pandoc.MIME`: Added MIME types for .wof and .eot. Closes #640. * `Text.Pandoc.Biblio`: + Run `mvPunc` and `deNote` on metadata too. This fixed a bug with notes on titles using footnote styles. + Fixed bug in fetching CSL files from CSL data directory. * `pandoc.hs`: Give correct value to `writerSourceDirectory` when a URL is provided. It should be the URL up to the path. * Fixed/simplified diff output for tests. Biblio: Make sure mvPunc and deNote run on metadata too. This fixed a bug with notes on titles using footnote styles. [under the hood improvements] * We no longer depend on `utf8-string`. Instead we use functions defined in `Text.Pandoc.UTF8` that use `Data.Text`'s conversions. * Use `safeRead` instead of using `reads` directly (various modules). * "Implicit figures" (images alone in a paragraph) are now handled differently. The markdown reader gives their titles the prefix `fig:`; the writers look for this before treating the image as a figure. Though this is a bit of a hack, it has two advantages: (i) implicit figures can be limited to the markdown reader, and (ii) they can be deactivated by turning off the `implicit_figures` extension. * `catch` from `Control.Exception` is now used instead of the old Preface `catch`. * `Text.Pandoc.Shared`: Improved algorithm for `normalizeSpaces` and `oneOfStrings` (which is now non-backtracking). * `Text.Pandoc.Biblio`: Remove workaround for `toCapital`. Now citeproc-hs is fixed upstream, so this is no longer needed. Closes #531. * Textile reader: Improved speed of `hyphenedWords`. This speeds up the textile reader by about a factor of 4. * Use `Text.Pandoc.Builder` in RST reader, for more flexibility, better performance, and automatic normalization. * Major rewrite of markdown reader: + Use `Text.Pandoc.Builder` instead of lists. This also means that everything is normalized automatically. + Move to a one-pass parsing strategy, returning values in the reader monad, which are then run (at the end of parsing) against the final parser state. * In HTML writer, we now use `toHtml` instead of pre-escaping. We work around the problem that blaze-html unnecessarily escapes `'` by pre-escaping just the `'` characters, instead of the whole string. If blaze-html later stops escaping `'` characters, we can simplify `strToHtml` to `toHtml`. Closes #629. * Moved code for embedding images in RTFs from `pandoc.hs` to the RTF writer (which now exports `writeRTFWithEmbeddedImages`). * Moved citation processing from `pandoc.hs` into the readers. This makes things more convenient for library users. * The man pages are now built by an executable `make-pandoc-man-pages`, which has its own stanza in the cabal file so that dependencies can be handled by Cabal. Special treatment in `Setup.hs` ensures that this executable never gets installed; it is only used to create the man pages. * The cabal file has been modified so that the pandoc library is used in building the pandoc executable. (This required moving `pandoc.hs` from `src` to `.`.) This cuts compile time in half. * `-O2` is no longer used in building pandoc. The performance improvement it yields is so slight that it is not worth it. (Measured with benchmarks on ghc 7.4.) * The `executable` and `library` flags have been removed. * `-threaded` has been removed from ghc-options. * Version bounds of dependencies have been raised, and the `blaze_html_0_5` flag now defaults to True. Pandoc now compiles on GHC 7.6. * We now require base >= 4.2. * Integrated the benchmark program into cabal. One can now do: cabal configure --enable-benchmarks && cabal build cabal bench --benchmark-option='markdown' --benchmark-option='-s 20' The benchmark now uses README + testsuite, so benchmark results from older versions aren't comparable. * Integrated test suite with cabal. To run tests, configure with `--enable-tests`, then `cabal test`. You can specify particular tests using `--test-options='-t markdown'`. No output is shown unless tests fail. The Haskell test modules have been moved from `src/` to `tests/`. * Moved all data files and templates to the `data/` subdirectory. * Added an `embed_data_files` cabal flag. This causes all data files to be embedded in the binary, so that the binary is self-sufficient and can be relocated anywhere, copied on a USB key, etc. The Windows installer now uses this. (Since we no longer have the option to build the executable without the library, this is the only way to get a relocatable binary on Windows.) * Removed pcre3.dll from windows package. It isn't needed unless highlighting-kate is compilled with the `pcre-light` flag. By default, regex-prce-builtin is used. pandoc (1.9.4.2) * Don't encode/decode file paths if base >= 4.4. Prior to base 4.4, filepaths and command line arguments were treated as unencoded lists of bytes, not unicode strings, so we had to work around that by encoding and decoding them. This commit adds CPP 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). * Fixed handling of absolute URLs in CSS imports with `--self-contained`. Closes #535. * Added webm to mime types. Closes #543. * 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) * Markdown reader: Added `cf.` and `cp.` to list of likely abbreviations. * LaTeX template: Added `linkcolor`, `urlcolor` and `links-as-notes` variables. Make TOC links black. * LaTeX template improvements. + Don't print date unless one is given explicitly in the document. + Simplified templates. + Use fontenc [T1] by default, and lmodern. + 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]`. + Added workaround for a bug in citeproc-hs 0.3.4 that causes footnotes beginning with a citation to be empty. Closes #531. * Fixed documentation on mixed lists. Closes #533. pandoc (1.9.4) * Simplified `Text.Pandoc.Biblio` and fixed bugs with citations inside footnotes and captions. We now handle note citations by inserting footnotes during initial citation processing, and doing a separate pass later to remove notes inside notes. * Added 'zenburn' highlight style from highlighting-kate. * Added Slideous writer. Slideous is an HTML + javascript slide show format, similar to Slidy, but works with IE 7. (Jonas Smedegaard) * LaTeX writer: + Ensure we don't have extra blank lines at ends of cells. This can cause LaTeX errors, as they are interpreted as new paragraphs. + More consistent interblock spacing. + Require highlighting-kate >= 0.5.1, for proper highlighted inline code in LaTeX. Closes #527. + Ensure that a Verbatim at the end of a footnote is followed by a newline. (Fixes a regression in the previous version.) + In default template, use black for internal links and TOC. Added commented-out code to use footnotes for links, as would be suitable in print output. * Beamer writer: When `--incremental` is used, lists inside a block quote should appear all at once. (This makes Beamer output consistent with the HTML slide show formats.) * ConTeXt writer: + Escape `%` as `\letterpercent{}` not `\letterpercent `, to avoid gobbling spaces after the `%` sign. + Ensure space after `\stopformula`. * Markdown writer: + Use `:` form instead of `~` in definition lists, for better compatibility with other markdown implementations. + Don't wrap the term, because it breaks definition lists. + Use a nonzero space to prevent false recognition of list marker in ordered lists. Closes #516. * Org writer: Add space before language name. Closes #523. * Docx writer: Simplified bullet characters so they work properly with Word 2007. Closes #520. * LaTeX reader: Support `\centerline`. * RST reader: handle figures. Closes #522. * Textile reader: fix for `<notextile>` and `==`. Closes #517. (Paul Rivier) pandoc (1.9.3) * Fixed bug in `fromEntities`. The previous version would turn `hi & low you know;` into `hi &`. * HTML reader: + Don't skip nonbreaking spaces. Previously a paragraph containing just ` ` would be rendered as an empty paragraph. Thanks to Paul Vorbach for pointing out the bug. + Support `<col>` and `<caption>` in tables. Closes #486. * Markdown reader: + Don't recognize references inside delimited code blocks. + Allow list items to begin with lists. * Added basic docbook reader (John MacFarlane and Mauro Bieg). * LaTeX reader: + Handle `\bgroup`, `\egroup`, `\begingroup`, `\endgroup`. + Control sequences can't be followed by a letter. This fixes a bug where `\begingroup` was parsed as `\begin` followed by `group`. + Parse 'dimension' arguments to unknown commands. e.g. `\parindent0pt` + Make `\label` and `\ref` sensitive to `--parse-raw`. If `--parse-raw` is selected, these will be parsed as raw latex inlines, rather than bracketed text. + Don't crash on unknown block commands (like `\vspace{10pt}`) inside `\author`; just skip them. Closes #505. * Textile reader: + Implemented literal escapes with `==` and `<notextile>`. Closes #473. + Added support for LaTeX blocks and inlines (Paul Rivier). + Better conformance to RedCloth inline parsing (Paul Rivier). + Parse '+text+' as emphasized (should be underlined, but this is better than leaving literal plus characters in the output. * Docx writer: Fixed multi-paragraph list items. Previously they each got a list marker. Closes #457. * LaTeX writer: + Added `--no-tex-ligatures` option to avoid replacing quotation marks and dashes with TeX ligatures. + Use `fixltx2e` package to provide '\textsubscript'. + Improve spacing around LaTeX block environments: quote, verbatim, itemize, description, enumerate. Closes #502. + Use blue instead of pink for URL links in latex/pdf output. * ConTeXt writer: Fixed escaping of `%`. In text, `%` needs to be escaped as `\letterpercent`, not `\%` Inside URLs, `%` needs to be escaped as `\%` Thanks to jmarca and adityam for the fix. Closes #492. * Texinfo writer: Escape special characters in node titles. This fixes a problem pointed out by Joost Kremers. Pandoc used to escape an '@' in a chapter title, but not in the corresponding node title, leading to invalid texinfo. * Fixed document encoding in texinfo template. Resolves Debian Bug #667816. * Markdown writer: + Don't force delimited code blocks to be flush left. Fixes bug with delimited code blocks inside lists etc. + Escape `<` and `$`. * LaTeX writer: Use `\hyperref[ident]{text}` for internal links. Previously we used `\href{\#ident}{text}`, which didn't work on all systems. Thanks to Dirk Laurie. * RST writer: Don't wrap link references. Closes #487. * Updated to use latest versions of blaze-html, mtl. pandoc (1.9.2) * LaTeX reader: + Made `lstlisting` work as a proper verbatim environment. + Fixed bug parsing LaTeX tables with one column. * LaTeX writer: + Use `{}` around `ctable` caption, so that formatting can be used. + Don't require eurosym package unless document has a €. * LaTeX template: Added variables for `geometry`, `romanfont`, `sansfont`, `mathfont`, `mainfont` so users can more easily customize fonts. * PDF writer: + Run latex engine at least two times, to ensure that PDFs will have hyperlinked bookmarks. + Added PDF metadata (title,author) in LaTeX standalone + PDF output. * Texinfo writer: retain directories in image paths. (Peter Wang) * RST writer: Better handling of inline formatting, in accord with docutils' "inline markup recognition rules" (though we don't implement the unicode rules fully). Now `hi*there*hi` gets rendered properly as `hi\ *there*\ hi`, and unnecessary `\ ` are avoided around `:math:`, `:sub:`, `:sup:`. * RST reader: + Parse `\ ` as null, not escaped space. + Allow `` :math:`...` `` even when not followed by blank or `\`. This does not implement the complex rule docutils follows, but it should be good enough for most purposes. + Add support for the rST default-role directive. (Greg Maslov) * Text.Pandoc.Parsing: Added `stateRstDefaultRole` field to `ParserState`. (Greg Maslov) * Markdown reader: Properly handle citations nested in other inline elements. * Markdown writer: don't replace empty alt in image with "image". * DZSlides: Updated template.html and styles in default template. Removed bizarre CSS for `q` in dzslides template. * Avoid repeated `id` attribute in section and header in HTML slides. * README improvements: new instructions on internal links, removed misleading note on reST math. * Build system: + Fixed Windows installer so that dzslides works. + Removed stripansi.sh. + Added .travis.yml for Travis continuous integration support.. + Fixed upper bound for zlib (Sergei Trofimovich). + Fixed upper bound for test-framework. + Updated haddocks for haddock-2.10 (Sergei Trofimovich). pandoc (1.9.1.2) * Added `beamer+lhs` as output format. * Don't escape `<` in `<style>` tags with `--self-contained`. This fixes a bug which prevented highlighting from working when using `--self-contained`. * PDF: run latex engine three times if `--toc` specified. This fixes page numbers in the table of contents. * Docx writer: Added TableNormal style to tables. * LaTeX math environment fixes. `aligned` is now used instead of the nonexistent `aligned*`. `multline` instead of the nonexistent `multiline`. * LaTeX writer: Use `\textasciitilde` for literal `~`. * HTML writer: Don't escape contents of EQ tags with --gladtex. This fixes a regression from 1.8. * Use `<q>` tags for Quoted items for HTML5 output. The quote style can be changed by modifying the template or including a css file. A default quote style is included. * LaTeX reader: Fixed accents (\~{a}, `\c{c}`). Correctly handle \^{}. Support "minted" as a LaTeX verbatim block. * Updated LaTeX template for better language support. Use `polyglossia` instead of `babel` with xetex. Set `lang` as documentclass option. `\setmainlanguage` will use the last of a comma-separated list of languages. Thanks to François Gannaz. * Fixed default LaTeX template so `\euro` and `€` work. The `eurosym` package is needed if you are using pdflatex. * Fixed escaping of period in man writer (thanks to Michael Thompson). * Fixed list label positions in beamer. * Set `mainlang` variable in context writer. This parallels behavior of latex writer. `mainlang` is the last of a comma-separated list of languages in lang. * EPUB language metadat: convert e.g. `en_US` from locale to `en-US`. * Changed `-V` so that you can specify a key without a value. Such keys get the value `true`. * Fixed permissions on installed man pages - thanks Magnus Therning. * Windows installer: require XP or higher. The installer is now compiled on a Windows 7 machine, which fixes a problem using citation functions on Windows 7. * OSX package: Check for 64-bit Intel CPU before installing. pandoc (1.9.1.1) * Better handling of raw latex environments in markdown. Now \begin{equation} a_1 \end{equation} turns into a raw latex block as expected. * Improvements to LaTeX reader: + Skip options after block commands. + Correctly handle `{\\}` in braced. + Added a needed 'try'. + Citations: add `, ` to suffix if it doesn't start with space or punctuation. Otherwise we get no space between the year and the suffix in author-date styles. * Added two needed data files for S5. This fixes a problem with `pandoc -t s5 --self-contained`. Also removed `slides.min.js`, which was no longer being used. * Fixed some minor problems in `reference.docx`: name on "Date" style, `xCs` instead of `xIs`. * Fixed a problem creating docx files using a reference docx modified using Word. The problem seems to be that Word modifies `_rels/.rels`, changing the Type of the Relationship to `docProps/core.xml`. Pandoc now changes this back to the correct value if it has been altered, fixing the problem. * Fixed html5 template so it works properly with highlighting. 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): (1) Attributes can contain line breaks. (2) Values in key-value attributes can be surrounded by either double or single quotes, or left unquoted if they contain no spaces. * Don't wrap headers in markdown or RST writers. * Added `stateMaxNestingLevel` to `ParserState`. We set this to 6, so you can still have `Emph` inside `Emph`, just not indefinitely. * More efficient implementation of `nowrap` in `Text.Pandoc.Pretty`. * `Text.Pandoc.PDF`: Only run latex twice if `\tableofcontents` is present. * Require highlighting-kate >= 0.5.0.2, texmath >= 0.6.0.2. pandoc (1.9.0.5) * Changed cabal file so that build-depends for the test program are not required unless the tests flag is used. * LaTeX writer: insert `{}` between adjacent hyphens so they don't form ligatures (dashes) in code spans. pandoc (1.9.0.4) * Raised version bound on test-framework to avoid problems compiling tests on GHC 7.4.1. * LaTeX reader: Use raw LaTeX as fallback inline text for Cites, so citations don't just disappear unless you process with citeproc. Ignore `\bibliographystyle`, `\nocite`. * Simplified tex2pdf; it will always run latex twice to resolve table of contents and hyperrefs. pandoc (1.9.0.3) * Require Cabal >= 1.10. * Tweaked cabal file to meet Cabal 1.10 requirements. pandoc (1.9.0.2) * Allow build with json 0.4 or 0.5. Otherwise we can't build with ghc 6.12. pandoc (1.9) [new features] * Added a Microsoft Word `docx` writer. The writer includes support for highlighted code and for math (which is converted from TeX to OMML, Office's native math markup language, using texmath's new OMML module). A new option `--reference-docx` allows the user to customize the styles. * Added an `asciidoc` writer (<http://www.methods.co.nz/asciidoc/>). * Better support for slide shows: + Added a `dzslides` writer. DZSlides is a lightweight HTML5/javascript slide show format due to Paul Rouget (<http://paulrouget.com/dzslides/>). + Added a LaTeX `beamer` writer. Beamer is a LaTeX package for creating slide presentations. + New, flexible rules for dividing documents into sections and slides (see the "Structuring the slide show" in the User's Guide). These are backward-compatible with the old rules, but they allow slide shows to be organized into sections and subsections containing multiple slides. + A new `--slide-level` option allows users to override defaults and select a slide level below the first header level with content. * A new `--self-contained` option produces HTML output that does not depend on an internet connection or the presence of any external files. Linked images, CSS, and javascript is downloaded (or fetched locally) and encoded in `data:` URIs. This is useful for making portable `HTML slide shows. The --offline` option has been deprecated and is now `treated as a synonym or --self-contained`. * Support for PDF output: + Removed the old `markdown2pdf`. + `pandoc` can now create PDFs (assuming you have latex and a set of appropriate packages installed): just specify an output file with the `.pdf` extension. + A new option `--latex-engine` allows you to specify `pdflatex`, `xelatex`, or `lualatex` as the processor. * Highlighting changes: + Syntax highlighting is now a standard feature; the `highlighting` flag is no longer needed when compiling. + A new `--no-highlight` option allows highlighting to be disabled. + Highlighting now works in `docx`, `latex`, and `epub`, as well as `html`, `html5`, `dzslides`, `s5`, and `slidy`. + A new `--highlight-style` option selects between various highlighting color themes. * Internal links to sections now work in ConTeXt and LaTeX as well as HTML. * LaTeX `\include` and `\usepackage` commands are now processed, provided the files are in the working directory. * EPUB improvements: + Internal and external links now work in EPUB. + Raw HTML is allowed. + New `--epub-embed-font` option. + Customizable templates for EPUB pages offer more control over formatting: `epub-page.html`, `epub-coverimage.html`, `epub-titlepage.html`. * `--mathml` now works with DocBook. * Added support for math in RST reader and writer. Inline math uses the `` :math:`...` `` construct. Display math uses .. math:: ... or if the math is multiline, .. math:: ... These constructions are now supported now by `rst2latex.py`. * Github syntax for fenced code blocks is supported in pandoc's markdown. You can now write ```ruby x = 2 ``` instead of ~~~ {.ruby} x = 2 ~~~~ * Easier scripting: a new `toJsonFilter` function makes it easier to write Haskell scripts to manipulate the Pandoc AST. [behavior changes] * Fixed parsing of consecutive lists in markdown. Pandoc previously behaved like Markdown.pl for consecutive lists of different styles. Thus, the following would be parsed as a single ordered list, rather than an ordered list followed by an unordered list: 1. one 2. two - one - two This change makes pandoc behave more sensibly, parsing this as two lists. Any change in list type (ordered/unordered) or in list number style will trigger a new list. Thus, the following will also be parsed as two lists: 1. one 2. two a. one b. two Since we regard this as a bug in Markdown.pl, and not something anyone would ever rely on, we do not preserve the old behavior even when `--strict` is selected. * Dashes work differently with `--smart`: `---` is always em-dash, and `--` is always en-dash. Pandoc no longer tries to guess when `-` should be en-dash. *Note:* This may change how existing documents look when processed with pandoc. A new option, `--old-dashes`, is provided for legacy documents. * The markdown writer now uses setext headers for levels 1-2. The old behavior (ATX headers for all levels) can be restored using the new `--atx-headers` option. * Links are now allowed in markdown image captions. They are also allowed in links, but will appear there as regular text. So, [link with [link](/url)](/url) will turn into <p><a href="/url">link with link</a></p> * Improved handling of citations using `citeproc-hs-0.3.4`. Added `--citation-abbreviations` option. * Citation keys can no longer end with a punctuation character. This means that `@item1.` will be parsed as a citation with key 'item1', followed by a period, instead of a citation with key 'item1.', as was the case previously. * In HTML output, citations are now put in a span with class `citation`. * The markdown reader now recognizes DocBook block and inline tags. It was always possible to include raw DocBook tags in a markdown document, but now pandoc will be able to distinguish block from inline tags and behave accordingly. Thus, for example, <sidebar> hello </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 environments became BlockQuote elements; now, they are treated as "transparent", so `\begin{unknown}xyz\end{unknown}` is the same as `xyz`. (2) Previously, arguments of unknown commands were passed through with their braces; now the braces are stripped off. * `--smart` is no longer selected automatically with `man` output. * The deprecated `--xetex` option has been removed. * The `--html5`/`-5` option has been deprecated. Use `-t html5` instead. `html5` and `html5+lhs` are now separate output formats. * Single quotes are no longer escaped in HTML output. They do not need to be escaped outside of attributes. * Pandoc will no longer transform leading newlines in code blocks to `<br/>` tags. * The ODT writer now sizes images appropriately, using the image size and DPI information embedded in the image. * `--standalone` is once again implicitly for a non-text output format (ODT, EPUB). You can again do `pandoc test.txt -o test.odt` and get a standalone ODT file. * The Docbook writer now uses `<sect1>`, `<sect2>`, etc. instead of `<section>`. * The HTML writer now uses `<del>` for strikeout. * In HTML output with `--section-divs`, the classes `section` and `level[1,2,..6]` are put on the `div` tags so they can be styled. In HTML 5 output with `--section-divs`, the classes `level[1,2,...6]` are put on `section` tags. * EPUB writer changes: + The `lang` variable now sets the language in the metadata (if it is not set, we default to the locale). + EPUB: UTF-8 is used rather than decimal entities. * Added `titleslide` class to title slide in S5 template. * In HTML, EPUB, and docx metadata, the date is normalized into YYYY-MM-DD format if possible. (This is required for validation.) * Attributes in highlighted code blocks are now preserved in HTML. The container element will have the classes, id, and key-value attributes you specified in the delimited code block. Previously these were stripped off. * The reference backlink in the HTML writer no longer has a special `footnoteBacklink` class. * The HTML template has been split into `html` and `html5` templates. * Author and date are treated more consistently in HTML templates. Authors are now `<h2>`, date `<h3>`. * URLs are hyphenated in the ConTeXt writer (B. Scott Michel). * In `Text.Pandoc.Builder`, `+++` has been replaced by `<>`. [bug fixes] * Better support for combining characters and East Asian wide characters in markdown and reST. * Better handling of single quotes with `--smart`. Previously `D'oh l'*aide*` would be parsed with left and right single quotes instead of apostrophes. This kind of error is now fixed. * Highlighting: Use `reads` instead of `read` for better error handling. Fixes crash on `startNum="abc"`. * Added blank comment after directives in rst template. * Unescape entities in citation `refId`. The `refId`s coming from citeproc contain XML numeric entities, and these don't match with the citation keys parsed by pandoc. Solution is to unescape them. * HTML reader: Fixed bug parsing tables with both thead and tbody. * Markdown reader: + Better handling of escapes in link URLs and titles. + Fixed backslash escapes in reference links. + Fixed bug in table/hrule parsing, by checking that the top line of a table is not followed by a blank line. This bug caused slowdowns on some files with hrules and tables, as pandoc tried to interpret the hrules as the tops of multiline tables. + Fixed bug in code block attribute parser. Previously the ID attribute got lost if it didn't come first. Now attributes can come in any order. * RST reader: allow footnotes followed by newline without space characters. * LaTeX reader: + Ignore empty groups {}, { }. + LaTeX reader: Handle \@. + LaTeX reader: Don't crash on commands like `\itemsep`. + LaTeX reader: Better handling of letter environments. * RST writer: Fixed bug involving empty table cells. isSimple was being calculated in a way that assumed there were no non-empty cells. * ConTeXt writer: + Made `--toc` work even without `--number-sections`. + Escape # in link URLs. + Use buffering for footnotes containing code blocks. + Changed 'descr' to 'description', fixed alignment. * LaTeX writer: + Escape euro character. + Don't escape ~ inside href{...}. + Escape # in href URLs. + Improved detection of book classes. We now check the `documentclass` variable, and if that is not set, we look through the template itself. Also, we have added the KOMA classes scrreprt and scrbook. You can now make a book using `pandoc -V documentclass:book mybook.txt -o mybook.pdf` + LHS files now set the "listings" variable, so that the definition of the `code` environment will be included in the template. + Links are colored blue by default (this can be changed by modifying `hyperref` settings in the template). + Added `lang` variable to LaTeX template. * HTML writer: + Fixed bug in HTML template with html5 and mathml. + Don't use self-closing img, br, hr tags for HTML5. + Use `<section>` for footnotes if HTML5. + Update HTML templates to use Content-Style-Type meta tag. + Use separate variables for meta-date, meta-author. This makes footnotes work in author and date fields. + Use 'vertical-align:middle' in WebTeX math for better alignment. * S5/slidy writer: Make footnotes appear on separate slide at end. * MIME: Added 'layout-cache' to getMimeType. This ensures that the META-INF/manifest.xml for ODT files will have everything it needs, so that ODT files modified by LibreOffice can be used as `--reference-odt`. * `Text.Pandoc.Templates`: Return empty string for json template. * `Text.Pandoc.Biblio`: + Expand citations recursively inside nested inlines. + Treat `\160` as space when parsing locator and suffix. This fixes a bug with "p. 33" when `--smart` is used. Previously the whole "p. 33" would be included in the suffix, with no locator. + Put whole author-in-text citation in a Cite. Previously just the date and other info went in the Cite. + Don't add comma+space to prefix if it ends in punctuation. * Updated chicago-author-date.csl. The old version did not work properly for edited volumes with no author. * EPUB writer: + Add date to EPUB titlepage and metadata. + Added TOC identifier in EPUB page template. + Don't generate superfluous file `cover-image.jpg`. [under the hood improvements] * Modified `make_osx_package.sh` to use cabal-dev. Items are no longer installed as root. Man pages are zipped and given proper permissions. * Modified windows installer generater to use cabal-dev. * Setup: Making man pages now works with cabal-dev (at least on OSX). In Setup.hs we now invoke 'runghc' in a way that points it to the correct package databases, instead of always falling back to the default user package db. * Updated to work with GHC 7.4.1. * Removed dependency on old-time. * Removed dependency on dlist. * New slidy directory for "self-contained." * TeXMath writer: Use unicode thin spaces for thin spaces. * Markdown citations: don't strip off initial space in locator. [API changes] * Removed `Apostrophe`, `EmDash`, `EnDash`, and `Ellipses` from the native `Inline` type in pandoc-types. Now we use `Str` elements with unicode. * Improvements to `Text.Pandoc.Builder`: + `Inlines` and `Blocks` are now newtypes (not synonyms for sequences). + Instances are defined for `IsString`, `Show`, `Read`, `Monoid`, and a new `Listable` class, which allows these to be manipulated to some extent like lists. Monoid append includes automatic normalization. + `+++` has been replaced by `<>` (mappend). * Use blaze-html instead of xhtml for HTML generation. This changes the type of `writeHtml`. * `Text.Pandoc.Shared`: + Added `warn` and `err`. + Removed `unescapeURI`, modified `escapeURI`. (See under [behavior changes], above.) * Changes in URI escaping: Previously the readers escaped URIs by converting unicode characters to octets and then percent encoding. Now unicode characters are left as they are, and `escapeURI` only percent-encodes space characters. This gives more readable URIs, and works well with modern user agents. URIs are no longer unescaped at all on conversion to `markdown`, `asciidoc`, `rst`, `org`. * New module `Text.Pandoc.SelfContained`. * New module `Text.Pandoc.Docx`. * New module `Text.Pandoc.PDF`. * Added `writerBeamer` to `WriterOptions`. * Added `normalizeDate` to `Text.Pandoc.Shared`. * Added `splitStringWithIndices` in `Text.Pandoc.Shared`. This is like `splitWithIndices`, but it is sensitive to distinctions between wide, combining, and regular characters. * `Text.Pandoc.Pretty`: + Added `chomp` combinator. + Added `beforeNonBreak` combinator. This allows you to include something conditionally on it being before a nonblank. Used for RST inline math. + Added `charWidth` function. All characters marked W or F in the unicode spec EastAsianWidth.txt get width 2. + Added `realLength`, based on `charWidth`. `realLength` is now used in calculating offsets. * New module `Text.Pandoc.Slides`, for common functions for breaking a document into slides. * Removed `Text.Pandoc.S5`, which is no longer needed. * Removed `Text.Pandoc.CharacterReferences`. Moved `characterReference` to `Text.Pandoc.Parsing`. `decodeCharacterReferences` is replaced by `fromEntities` in `Text.Pandoc.XML`. * Added `Text.Pandoc.ImageSize`. This is intened for use in `docx` and `odt` writers, so the size and dpi of images can be calculated. * Removed `writerAscii` in `WriterOptions`. * Added `writerHighlight` to `WriterOptions`. * Added `DZSlides` to `HTMLSlideVariant`. * `writeEPUB` has a new argument for font files to embed. * Added `stateLastStrPos` to `ParserState`. This lets us keep track of whether we're parsing the position immediately after a regular (non-space, non-symbol) string, which is useful for distinguishing apostrophes from single quote starts. * `Text.Pandoc.Parsing`: + `escaped` now returns a `Char`. + Removed `charsInBalanced'`, added a character parser as a parameter of `charsInBalanced`. This is needed for proper handling of escapes, etc. + Added `withRaw`. * Added `toEntities` to `Text.Pandoc.XML`. * `Text.Pandoc.Readers.LaTeX`: + Export `handleIncludes`. + Export `rawLaTeXBlock` instead of `rawLaTeXEnvironment'`. * Added `ToJsonFilter` class and `toJsonFilter` function to `Text.Pandoc`, deprecating the old `jsonFilter` function. * `Text.Pandoc.Highlighting`: + Removed `highlightHtml`, `defaultHighlightingCss`. + Export `formatLaTeXInline`, `formatLaTeXBlock`, and `highlight`, plus key functions from highlighting-kate. + Changed types of highlighting function. `highlight` returns a `Maybe`, not an `Either`. pandoc (1.8.2.1) * Relaxed cabal consntraints for test-framework (S. Trofimovich). * Relaxed cabal constraints for pandoc-types. * Adjusted Arbitrary instance to help avoid timeouts in tests. * Added `Tests.Writers.Markdown` to cabal file. pandoc (1.8.2) * Added script to produce OS X package. * Made `templates` directory a git submodule. This should make it easier for people to revise their custom templates when the default templates change. * Changed template naming scheme: `FORMAT.template` -> `default.FORMAT`. **Note:** If you have existing templates in `~/.pandoc/templates`, you must rename them to conform to the new scheme! * Fixed smart quotes bug, now handling `'...hi'` properly. * RST reader: + Partial support for labeled footnotes. + Improved accuracy of `simpleReferenceName` parser. * HTML reader: + Substitute correct unicode characters for characters in the 128..159 range, which are often found even in HTML that purports to be UTF-8. * LaTeX reader: Handle `\subtitle` command (a subtitle is added to the title, after a colon and linebreak). Closes #280. * Leaner `reference.odt`. * Added unexported module `Text.Pandoc.MIME` for use in the ODT writer. * ODT writer: Construct `manifest.xml` based on archive contents. This fixes a bug in ODTs containing images. Recent versions of LibreOffice would reject these as corrupt, because `manifest.xml` did not contain a reference to the image files. * LaTeX writer: + Make verbatim environments flush to avoid spurious blank lines. Closes #277. + Use `\texttt` and escapes insntead of `\verb!...!`, which is too fragile (doesn't work in command arguments). + Use `\enquote{}` for quotes if the template includes the `csquotes` package. This provides better support for local quoting styles. (Thanks to Andreas Wagner for the idea.) * ConTeXt writer: Make `\starttyping`/`\stoptyping` flush with margin, preventing spurious blank lines. * Slidy writer: + Use non-minimized version of `slidy.css` with `--offline` option, so users can more easily edit it. + Also fixed a bug in the CSS that prevented proper centering of title (now reported and fixed upstream). * S5 writer: + Replaced `s5/default/slides.js.{comment,packed}` with new compressed `s5/default/slides.min.js`. + Use `data:` protocol to embed S5 CSS in `<link>` tags, when `--offline` is specified. Using inline CSS didn't work with Chrome or Safari. This fixes offline S5 on those browsers. * HTML writer: Removed English title on footnote backlinks. This is incongrous in non-English documents. * Docbook writer: + Use CALS tables. (Some older docbook software does not work well with XHTML tables.) Closes #77. + Use `programlisting` tags (instead of `screen`) for code blocks. * `markdown2pdf`: + Calls latex with `-halt-on-error -interaction nonstopmode` instead of `-interaction=batchmode`, which essentially just ignored errors, leading to bad results. Better to know when something is wrong. + Fixed issues with non-UTF-8 output of `pdflatex`. + Better error reporting. * `--mathjax` now takes an optional URL argument. If it is not provided, pandoc links directly to the (secure) mathjax CDN, as now recommended (thanks to dsanson). * Deprecated `--xetex` option in `pandoc`. It is no longer needed, since the LaTeX writer now produces a file that can be processed by `latex`, `pdflatex`, `lualatex`, or `xelatex`. * Introduced `--luatex` option to `markdown2pdf`. This causes `lualatex` to be used to create the PDF. * If a template specified with `--template` is not found, look for it in `datadir`. Also, if no extension is provided, supply one based on the writer. So now you can put your `special.latex` template in `~/.pandoc/templates`, and use it from any directory via `pandoc -t latex --template special`. * Default template improvements: + HTML: Display author and date after title. + HTML: Made table of contents more customizable. The container for the TOC is now in the template, so users can insert a header or other styling. (Thanks to Bruce D'Arcus for the suggestion.) + HTML, Slidy, S5: Enclose scripts in CDATA tags. + Slidy, S5: Added `s5-url` and `slidy-url` variables, instead of hard-coding. If you want to put your slidy files in the slidy subdirectory, for example, you can do `pandoc -t slidy -V slidy-url=slidy -s`. + LaTeX: Use `\and` to separate authors in LaTeX documents (reader & writer). Closes #279. + LaTeX: Use different `hyperref` options for `xetex`, fixing problems with unicode bookmarks (thanks to CircleCode). + LaTeX: Removed `ucs` package, use `utf8` rather than `utf8x` with `inputenc`. This covers fewer characters but is more robust with other packages, and `ucs` is unmaintained. Users who need better unicode support should use xelatex or lualatex. pandoc (1.8.1.2) * Added `--epub-cover-image` option. * Documented `--biblatex` and `--natbib` options. * Allow `--section-divs` with slidy output. Resolves Issue #296. * Disallow notes within notes in reST and markdown. These previously caused infinite looping and stack overflows. For example: [^1] [^1]: See [^1] Note references are allowed in reST notes, so this isn't a full implementation of reST. That can come later. For now we need to prevent the stack overflows. Partially resolves Issue #297. * EPUB writer: Allow non-plain math methods. * Forbid ()s in citation item keys. Resolves Issue #304: problems with `(@item1; @item2)` because the final paren was being parsed as part of the item key. * Changed URI parser so it doesn't include trailing punctuation. So, in RST, `http://google.com.` should be parsed as a link followed by a period. The parser is smart enough to recognize balanced parentheses, as often occur in wikipedia links: `http://foo.bar/baz_(bam)`. * Markdown+lhs reader: Require space after inverse bird tracks, so that HTML tags can be used freely at the left margin of a markdown+lhs document. Thanks to Conal Elliot for the suggestion. * Markdown reader: + Improved emph/strong parsing; fixes bug found by Perry Wagle. + Fixed bug in footnote order (reported by CircleCode). * RST reader: + Fixed bug in in field lists with multi-line items at the end of the list. + Added parentheses to RST `specialChars`, so `(http://google.com)` will be parsed as a link in parens. Resolves Issue #291. + Allow `|` followed by newline in RST line block. * LaTeX reader: + Support `\dots`. + Gobble option & space after linebreak `\\[10pt]`. * Textile reader: + Make it possible to have colons after links. (qerub) + Make it possible to have colons after links. (Christoffer Sawicki) * HTML reader: + Skip spaces after `<b>`, `<emph>`, etc. + Handle tbody, thead in simple tables. Closes #274. + Implicit `Para`s instead of `Plains` in some contexts. * OpenDocument writer: Use special `First paragraph` style for first paragraph after most non-paragraph blocks. This allows users to specify e.g. that only paragraphs after the first paragraph of a block are to be indented. Thanks to Andrea Rossato for the patch. Closes #20. * LaTeX writer: use `deVerb` on table and picture captions. Otherwise LaTeX complains about `\verb` inside command argument. Thanks to bbanier for reporting the bug. * Markdown writer: Insert HTML comment btw list and indented code block. This prevents the code block from being interpreted as part of the list. * EPUB writer: Add a meta element specify the cover. Some EPUB e-readers, such as the Nook, require a meta element inside the OPF metadata block to ensure the cover image is properly displayed. (Kelsey Hightower) * HTML writer: Use embed tag for images with non-image extensions. (e.g. PDFs). Closes #264. * LaTeX writer: Improved tables. + More space between lines, top-align cells. + Use ctable package, which allows footnotes and provides additional options. + Made cell alignments work in multiline tables. + Closes #271, #272. * Un-URI-escape image filenames in LaTeX, ConTeXt, RTF, Texinfo. Also do this when copying image files into EPUBs and ODTs. Closes #263. * Changed to github issue tracker. * Added failing emph/strong markdown test case due to Perry Wagle. * Slidy improvements: + Updated to use Slidy2. + Fixed bug, unclosed div tag. + Added `duration` variable in template. Setting this activates the timer. + Use 'titlepage' instead of 'cover' for title div. pandoc (1.8.1.1) * `markdown2pdf`: Removed some debugging lines accidentally included in the 1.8.1 release. With those lines, the temp directory is created in the working directory, and it is not deleted. This fix restores the original behavior. pandoc (1.8.1) * Added `--ascii` option. Currently supported only in HTML writer, which it causes to use numerical entities instead of UTF-8. * EPUB writer: `--toc` now works to provide a table of contents at the beginning of each chapter. * LaTeX writer: Change figure defaults to `htbp`. This prevents "too many unprocessed floats." Resolves Issue #285. * `Text.Pandoc.UTF8`: Encode filenames even when using recent base. * `markdown2pdf`: Fixed filename encoding issues. With help from Paulo Tanimoto. Resolves Issue #286. * HTML writer: Put line breaks in section divs. * `Text.Pandoc.Shared`: Make `writerSectionDivs` default to False. pandoc (1.8.0.3) * Fixed Source-repository stanza in cabal file. pandoc (1.8.0.2) * HTML writer: + Stringify alt text instead of converting to HTML. + Break lines after block elements, not inside tags. HTML output now closely resembles that of tidy. Resolves Issue #134. * Markdown reader: Fixed bug in footnote block parser (pointed out by Jesse Rosenthal). The problem arose when the blank line at the end of a footnote block contained indenting spaces. * Shared: Improved 'normalize' function so it normalizes Spaces too. In normal form, Space elements only occur to separate two non-Space elements. So, we never have [Space], or [, ..., Space]. * Tests: + Improved Arbitrary instance. + Added timeout for test instances. * README: + Added section on four-space rule for lists. Resolves Issue #283. + Clarified optional arguments on math options. * markdown2pdf: Fixed bug with output file extensions. Previously `markdown2pdf test.txt -o test.en.pdf` would produce `test.pdf`, not `test.en.pdf`. Thanks to Paolo Tanimoto for the fix. pandoc (1.8.0.1) * Revised Interact.hs so that it works with the CPP macros in the UTF8 module. * Revised Setup.hs so that we don't call MakeManPage.hs unless the man pages are out of date. pandoc (1.8) [new features] * Support for citations using Andrea Rossato's `citeproc-hs` 0.3. You can now write, for example, Water is wet [see @doe99, pp. 33-35; also @smith04, ch. 1]. and, when you process your document using `pandoc`, specifying a citation style using `--csl` and a bibliography using `--bibliography`, the citation will be replaced by an appropriately formatted citation, and a list of works cited will be added to the end of the document. This means that you can switch effortlessly between different citation and bibliography styles, including footnote, numerical, and author-date formats. The bibliography can be in any of the following formats: MODS, BibTeX, BibLaTeX, RIS, EndNote, EndNote XML, ISI, MEDLINE, Copac, or JSON. See the README for further details. Citations are supported in the markdown reader, using a special syntax, and in the LaTeX reader, using natbib or biblatex syntax. (Thanks to Nathan Gass for the natbib and biblatex support.) * New `textile` reader and writer. Thanks to Paul Rivier for contributing the `textile` reader, an almost complete implementation of the textile syntax used by the ruby [RedCloth library](http://redcloth.org/textile). Resolves Issue #51. * New `org` writer, for Emacs Org-mode, contributed by Puneeth Chaganti. * New `json` reader and writer, for reading and writing a JSON representation of the native Pandoc AST. These are much faster than the `native` reader and writer, and should be used for serializing Pandoc to text. To convert between the JSON representation and native Pandoc, use `encodeJSON` and `decodeJSON` from `Text.JSON.Generic`. * A new `jsonFilter` function in `Text.Pandoc` makes it easy to write scripts that transform a JSON-encoded pandoc document. For example: -- removelinks.hs - removes links from document import Text.Pandoc main = interact $ jsonFilter $ bottomUp removeLink where removeLink (Link xs _) = Emph xs removeLink x = x To use this to remove links while translating markdown to LaTeX: pandoc -t json | runghc removelinks.hs | pandoc -f json -t latex * Attributes are now allowed in inline `Code` elements, for example: In this code, `ulist ! [theclass "special"] << elts`{.haskell} is... The attribute syntax is the same as for delimited code blocks. `Code` inline has an extra argument place for attributes, just like `CodeBlock`. Inline code will be highlighted in HTML output, if pandoc is compiled with highlighting support. Resolves Issue #119. * New `RawBlock` and `RawInline` elements (replacing `RawHtml`, `HtmlInline`, and `TeX`) provide lots of flexibility in writing scripts to transform Pandoc documents. Scripts can now change how each element is rendered in each output format. * You can now define LaTeX macros in markdown documents, and pandoc will apply them to TeX math. For example, \newcommand{\plus}[2]{#1 + #2} $\plus{3}{4}$ yields `3+4`. Since the macros are applied in the reader, they will work in every output format, not just LaTeX. * LaTeX macros can also be used in LaTeX documents (both in math and in non-math contexts). * A new `--mathjax` option has been added for displaying math in HTML using MathJax. Resolves issue #259. * Footnotes are now supported in the RST reader. (Note, however, that unlike docutils, pandoc ignores the numeral or symbol used in the note; footnotes are put in an auto-numbered ordered list.) Resolves Issue #258. * A new `--normalize` option causes pandoc to normalize the AST before writing the document. This means that, for example, `*hi**there*` will be rendered as `<em>hithere</em>` instead of `<em>hi</em><em>there</em>`. This is not the default, because there is a significant performance penalty. * A new `--chapters` command-line option causes headers in DocBook, LaTeX, and ConTeXt to start with "chapter" (level one). Resolves Issue #265. * In DocBook output, `<chapter>` is now used for top-level headers if the template contains `<book>`. Resolves Issue #265. * A new `--listings` option in `pandoc` and `markdown2pdf` causes the LaTeX writer to use the listings package for code blocks. (Thanks to Josef Svennigsson for the pandoc patch, and Etienne Millon for the markdown2pdf patch.) * `markdown2pdf` now supports `--data-dir`. * URLs in autolinks now have class "url" so they can be styled. * Improved prettyprinting in most formats. Lines will be wrapped more evenly and duplicate blank lines avoided. * New `--columns` command-line option sets the column width for line wrapping and relative width calculations for tables. * Made `--smart` work in HTML, RST, and Textile readers, as well as markdown. * Added `--html5` option for HTML5 output. * Added support for listings package in LaTeX reader (Puneeth Chaganti). * Added support for simple tables in the LaTeX reader. * Added support for simple tables in the HTML reader. * Significant performance improvements in many readers and writers. [API and program changes] * Moved `Text.Pandoc.Definition` from the `pandoc` package to a new auxiliary package, `pandoc-types`. This will make it possible for other programs to supply output in Pandoc format, without depending on the whole pandoc package. * Added `Attr` field to `Code`. * Removed `RawHtml`, `HtmlInline`, and `TeX` elements; added generic `RawBlock` and `RawInline`. * Moved generic functions to `Text.Pandoc.Generic`. Deprecated `processWith`, replacing it with two functions, `bottomUp` and `topDown`. Removed previously deprecated functions `processPandoc` and `queryPandoc`. * Added `Text.Pandoc.Builder`, for building `Pandoc` structures. * `Text.Pandoc` now exports association lists `readers` and `writers`. * Added `Text.Pandoc.Readers.Native`, which exports `readNative`. `readNative` can now read full pandoc documents, block lists, blocks, inline lists, or inlines. It will interpret `Str "hi"` as if it were `Pandoc (Meta [] [] []) [Plain [Str "hi"]]`. This should make testing easier. * Removed deprecated `-C/--custom-header` option. Use `--template` instead. * `--biblio-file` has been replaced by `--bibliography`. `--biblio-format` has been removed; pandoc now guesses the format from the file extension (see README). * pandoc will treat an argument as a URI only if it has an `http(s)` scheme. Previously pandoc would treat some Windows pathnames beginning with `C:/` as URIs. * The `--sanitize-html` option and the `stateSanitize` field in `ParserState` have been removed. Sanitization is better done in the resulting HTML using `xss-sanitize`, which is based on pandoc's sanitization, but improved. * pandoc now adds a newline to the end of its output in fragment mode (= not `--standalone`). * Added support for `lang` in `html` tag in the HTML template, so you can do `pandoc -s -V lang=es`, for example. * `highlightHtml` in `Text.Pandoc.Highlighting` now takes a boolean argument that selects between "inline" and "block" HTML. * `Text.Pandoc.Writers.RTF` now exports `rtfEmbedImage`. Images are embedded in RTF output when possible (png, jpeg). Resolves Issue #275. * Added `Text.Pandoc.Pretty`. This is better suited for pandoc than the `pretty` package. Changed all writers that used `Text.PrettyPrint.HughesPJ` to use `Text.Pandoc.Pretty` instead. * Rewrote `writeNative` using the new prettyprinting module. It is now much faster. The output has been made more consistent and compressed. `writeNative` is also now sensitive to writerStandalone`, and will simply `print a block list if writerStandalone` is False. * Removed `Text.Pandoc.Blocks`. `Text.Pandoc.Pretty` allows you to define blocks and concatenate them, so a separate module is no longer needed. * `Text.Pandoc.Shared`: + Added `writerColumns`, `writerChapters`, and `writerHtml5` to `WriterOptions`. + Added `normalize`. + Removed unneeded prettyprinting functions: `wrapped`, `wrapIfNeeded`, `wrappedTeX`, `wrapTeXIfNeeded`, `hang'`, `BlockWrapper`, `wrappedBlocksToDoc`. + Made `splitBy` take a test instead of an element. + Added `findDataFile`, refactored `readDataFile`. + Added `stringify`. Rewrote `inlineListToIdentifier` using `stringify`. + Fixed `inlineListToIdentifier` to treat '\160' as ' '. * `Text.Pandoc.Readers.HTML`: + Removed `rawHtmlBlock`, `anyHtmlBlockTag`, `anyHtmlInlineTag`, `anyHtmlTag`, `anyHtmlEndTag`, `htmlEndTag`, `extractTagType`, `htmlBlockElement`, `htmlComment` + Added `htmlTag`, `htmlInBalanced`, `isInlineTag`, `isBlockTag`, `isTextTag` * Moved `smartPunctuation` from `Text.Pandoc.Readers.Markdown` to `Text.Pandoc.Readers.Parsing`, and parameterized it with an inline parser. * Added `nonspaceChar` to `Text.Pandoc.Parsing`. * Ellipses are no longer allowed to contain spaces. Previously we allowed '. . .', ' . . . ', etc. This caused too many complications, and removed author's flexibility in combining ellipses with spaces and periods. * Allow linebreaks in URLs (treat as spaces). Also, a string of consecutive spaces or tabs is now parsed as a single space. If you have multiple spaces in your URL, use `%20%20`. * `Text.Pandoc.Parsing`: + Removed `refsMatch`. + Hid `Key` constructor. + Removed custom `Ord` and `Eq` instances for `Key`. + Added `toKey` and `fromKey` to convert between `Key` and `[Inline]`. + Generalized type on `readWith`. * Small change in calculation of relative widths of table columns. If the size of the header > the specified column width, use the header size as 100% for purposes of calculating relative widths of columns. * Markdown writer now uses some pandoc-specific features when `--strict` is not specified: `\` newline is used for a hard linebreak instead of two spaces then a newline. And delimited code blocks are used when there are attributes. * HTML writer: improved gladTeX output by setting ENV appropriately for display or inline math (Jonathan Daugherty). * LaTeX writer: Use `\paragraph`, `\subparagraph` for level 4,5 headers. * LaTeX reader: + `\label{foo}` and `\ref{foo}` now become `{foo}` instead of `(foo)`. + `\index{}` commands are skipped. * Added `fontsize` variable to default LaTeX template. This makes it easy to set the font size using `markdown2pdf`: `markdown2pdf -V fontsize=12pt input.txt`. * Fixed problem with strikeout in LaTeX headers when using hyperref, by adding a command to the default LaTeX template that disables `\sout` inside pdf strings. Thanks to Joost Kremers for the fix. * The `COLUMNS` environment variable no longer has any effect. [under-the-hood improvements] * Pandoc now compiles with GHC 7. (This alone leads to a significant performance improvement, 15-20%.) * Completely rewrote HTML reader using tagsoup as a lexer. The new reader is faster and more accurate. Unlike the old reader, it does not get bogged down on some input (Issues #277, 255). And it handles namespaces in tags (Issue #274). * Replaced `escapeStringAsXML` with a faster version. * Rewrote `spaceChar` and some other parsers in Text.Pandoc.Parsing for a significant performance boost. * Improved performance of all readers by rewriting parsers. * Simplified Text.Pandoc.CharacterReferences by using entity lookup functions from TagSoup. * `Text.Pandoc.UTF8` now uses the unicode-aware IO functions from `System.IO` if base >= 4.2. This gives support for windows line endings on windows. * Remove duplications in documentation by generating the pandoc man page from README, using `MakeManPage.hs`. * README now includes a full description of markdown syntax, including non-pandoc-specific parts. A new `pandoc_markdown` man page is extracted from this, so you can look up markdown syntax by doing `man pandoc_markdown`. * Completely revised test framework (with help from Nathan Gass). The new test framework is built when the `tests` Cabal flag is set. It includes the old integration tests, but also some new unit and quickcheck tests. Test output has been much improved, and you can now specify a glob pattern after `cabal test` to indicate which tests should be run; for example `cabal test citations` will run all the citation tests. * Added a shell script, `stripansi.sh`, for filtering ANSI control sequences from test output: `cabal test | ./stripansi.sh > test.log`. * Added `Interact.hs` to make it easier to use ghci while developing. `Interact.hs` loads `ghci` from the `src` directory, specifying all the options needed to load pandoc modules (including specific package dependencies, which it gets by parsing dist/setup-config). * Added `Benchmark.hs`, testing all readers + writers using criterion. * Added `stats.sh`, to make it easier to collect and archive benchmark and lines-of-code stats. * Added upper bounds to all cabal dependencies. * Include man pages in extra-source-files. This allows users to install pandoc from the tarball without needing to build the man pages. [bug fixes] * Filenames are encoded as UTF8. Resolves Issue #252. * Handle curly quotes better in `--smart` mode. Previously, curly quotes were just parsed literally, leading to problems in some output formats. Now they are parsed as `Quoted` inlines, if `--smart` is specified. Resolves Issue #270. * Text.Pandoc.Parsing: Fixed bug in grid table parser. Spaces at end of line were not being stripped properly, resulting in unintended LineBreaks. * Markdown reader: + Allow HTML comments as inline elements in markdown. So, `aaa <!-- comment --> bbb` can be a single paragraph. + Fixed superscripts with links: `^[link](/foo)^` gets recognized as a superscripted link, not an inline note followed by garbage. + Fixed regression, making markdown reference keys case-insensitive again. Resolves Issue #272. + Properly handle abbreviations (like `Mr.`) at the end of a line. + Better handling of intraword underscores, avoiding exponential slowdowns in some cases. Resolves Issue #182. + Fixed bug in alignments in tables with blank rows in the header. * RST reader: + Field lists now allow spaces in field names, and block content in field values. (Thanks to Lachlan Musicman for pointing out the bug.) + Definition list items are now always `Para` instead of `Plain`, matching behavior of `rst2xml.py`. + In image blocks, the description is parsed properly and used for the alt attribute, not also the title. + Skip blank lines at beginning of file. Resolves Debian #611328. * LaTeX reader: + Improved parsing of preamble. Previously you'd get unexpected behavior on a document that contained `\begin{document}` in, say, a verbatim block. + Allow spaces between `\begin` or `\end` and `{`. + Support `\L` and `\l`. + Skip comments inside paragraphs. * LaTeX writer: + Escape strings in `\href{..}`. + In nonsimple tables, put cells in `\parbox`. * OpenDocument writer: don't print raw TeX. * Markdown writer: + Fixed bug in `Image`. URI was getting unescaped twice! + Avoid printing extra blank lines at the end if there are no notes or references. * LaTeX and ConTeXt: Escape `[` and `]` as `{[}` and `{]}`. This avoids unwanted interpretation as an optional argument. * ConTeXt writer: Fixed problem with inline code. Previously `}` would be rendered `\type{}}`. Now we check the string for '}' and '{'. If it contains neither, use `\type{}`; otherwise use `\mono{}` with an escaped version of the string. * `:` now allowed in HTML tags. Resolves Issue #274. pandoc (1.6) [ John MacFarlane ] * New EPUB and HTML Slidy writers. (Issue #122) - EPUB is a standard ebook format, used in Apple's iBooks for the iPad and iPhone, Barnes and Noble's nook reader, the Sony reader, and many other devices. - Slidy, like S5, is a system for producing HTML+javascript slide shows. * All input is assumed to be UTF-8, no matter what the locale and ghc version, and all output is UTF-8. This reverts to pre-1.5 behavior. Also, a BOM, if present, is stripped from the input. * Markdown now supports grid tables, whose cells can contain arbitrary block elements. (Issue #43) * Sequentially numbered example lists in markdown with `@` marker. * Markdown table captions can begin with a bare colon and no longer need to include the English word "table." Also, a caption can now occur either before or after the table. (Issue #227) * New command-line options: - `--epub-stylesheet` allows you to specify a CSS file that will be used to style your ebook. - `--epub-metadata` allows you to specify metadata for the ebook. - `--offline` causes the generated HTML slideshow to include all needed scripts and stylesheets. - `--webtex` causes TeX math to be converted to images using the Google Charts API (unless a different URL is specified). - `--section-divs` causes div tags to be added around each section in an HTML document. (Issue #230, 239) * Default behavior of S5 writer in standalone mode has changed: previously, it would include all needed scripts and stylesheets in the generated HTML; now, only links are included unless the `--offline` option is used. * Default behavior of HTML writer has changed. Between 1.2 and 1.5, pandoc would enclose sections in div tags with identifiers on the div tags, so that the sections can be manipulated in javascript. This caused undesirable interactions with raw HTML div tags. So, starting with 1.6, the default is to put the identifiers directly on the header tags, and not to include the divs. The `--section-divs` option selects the 1.2-1.5 behavior. * API changes: - `HTMLMathMethod`: Added `WebTeX`, removed `MimeTeX`. - `WriterOptions`: Added `writerUserDataDir`, `writerSourceDirectory`, `writerEPUBMetadata` fields. Removed `writerIncludeBefore`, `writerIncludeAfter`. - Added `headerShift` to `Text.Pandoc.Shared`. - Moved parsing code and `ParserState` from `Text.Pandoc.Shared` to a new module, `Text.Pandoc.Parsing`. - Added `stateHasChapters` to `ParserState`. - Added `HTMLSlideVariant`. - Made `KeyTable` a map instead of an association list. - Added accessors for `Meta` fields (`docTitle`, `docAuthors`, `docDate`). - `Pandoc`, `Meta`, `Inline`, and `Block` have been given `Ord` instances. - Reference keys now have a type of their own (`Key`), with its own `Ord` instance for case-insensitive comparison. - Added `Text.Pandoc.Writers.EPUB`. - Added `Text.Pandoc.UUID`. - Removed `Text.Pandoc.ODT`, added `Text.Pandoc.Writers.ODT`. Removed `saveOpenDocumentAsODT`, added `writeODT`. - Added `Text.Pandoc.Writers.Native` and `writeNative`. Removed `prettyPandoc`. - Added `Text.Pandoc.UTF8` for portable UTF8 string IO. - Removed `Text.Pandoc.Writers.S5` and the `writeS5` function. Moved `s5Includes` to a new module, `Text.Pandoc.S5`. To write S5, you now use `writeHtml` with `writerSlideVariant` set to `S5Slides` or `SlidySlides`. * Template changes. If you use custom templates, please update them, particularly if you use syntax highlighting with pandoc. The old HTML templates hardcoded highlighting CSS that will no longer work with the most recent version of highlighting-kate. - HTML template: avoid empty meta tag if no date. - HTML template: Use default highlighting CSS from highlighting-kate instead of hard-coding the CSS into the template. - HTML template: insert-before text goes before the title, and immediately after the <body> tag, as documented. (Issue #241) - Added slidy and s5 templates. - Added amssymb to preamble of latex template. (github Issue 1) * Removed excess newlines at the end of output. Note: because output will not contain an extra newline, you may need to make adjustments if you are inserting pandoc's output into a template. * In S5 and slidy, horizontal rules now cause a new slide, so you are no longer limited to one slide per section. * Improved handling of code in man writer. Inline code is now monospace, not bold, and code blocks now use .nf (no fill) and .IP (indented para). * HTML reader parses `<tt>` as Code. (Issue #247) * html+lhs output now contains bird tracks, even when compiled without highlighting support. (Issue #242) * Colons are now no longer allowed in autogenerated XML/HTML identifiers, since they have a special meaning in XML. * Code improvements in ODT writer. Remote images are now replaced with their alt text rather than a broken link. * LaTeX reader improvements: - Made latex `\section`, `\chapter` parsers more forgiving of whitespace. - Parse `\chapter{}` in latex. - Changed `rawLaTeXInline` to accept `\section`, `\begin`, etc. - Use new `rawLaTeXInline'` in LaTeX reader, and export `rawLaTeXInline` for use in markdown reader. - Fixes bug wherein `\section{foo}` was not recognized as raw TeX in markdown document. * LaTeX writer: images are automatically shrunk if they would extend beyond the page margin. * Plain, markdown, RST writers now use unicode for smart punctuation. * Man writer converts math to unicode when possible, as in other writers. * `markdown2pdf` can now recognize citeproc options. * Command-line arguments are converted to UTF-8. (Issue #234) * `Text.Pandoc.TeXMath` has been rewritten to use texmath's parser. This allows it to handle a wider range of formulas. Also, if a formula cannot be converted, it is left in raw TeX; formulas are no longer partially converted. * Unicode curly quotes are left alone when parsing smart quotes. (Issue #143) * Cabal file changes: - Removed parsec < 3 restriction. - Added 'threaded' flag for architectures where GHC lacks a threaded runtime. - Use 'threaded' only for markdown2pdf; it is not needed for pandoc. - Require highlighting-kate 0.2.7. * Use explicit imports from `Data.Generics`. Otherwise we have a conflict with the 'empty' symbol, introduced in syb >= 0.2. (Issue #237) * New data files: slidy/slidy.min.js, slidy/slidy.min.css, epub.css. pandoc (1.5.1.1) [ John MacFarlane ] * Fixed uniqueIdent in Shared so that header identifiers work as advertized in the README and are are valid XHTML names. pandoc (1.5.1) [ John MacFarlane ] * Fixed treatment of unicode characters in URIs. + Shared now exports escapeURI and unescapeURI. These handle UTF8 encoding and decoding as well as URI escaping/unescaping. + Shared: uri and emailAddress now return a pair of the original parsed text and the escaped URI (in the latter case, with the mailto: prefix). + HTML reader: unsanitaryURI has been modified to allow unicode high characters in a URI. + Readers: All link and image URIs are now escaped using escapeURI. + Markdown and RST writers: unescapeURI is used so that URIs in these formats are human-readable. * Setup.hs: Don't assume that the build directory is "dist". Instead, get it from localBuildInfo. * OpenDocument writer: Use a Map for stTextStyleAttr. This avoids duplicates (and invalid xml). Resolves Issue #222. pandoc (1.5.0.1) [ John MacFarlane ] * HTML writer: Fixed error in math writer (with MathML option) that caused an infinite loop for unparsable MathML. pandoc (1.5) [ John MacFarlane ] * Added --mathml option. When this is selected, pandoc will convert TeX math into MathML. + Added data/MathMLinHTML.js, which is included when no URL is provided for --mathml. This allows MathML to be displayed (in better browsers) as text/html. + Removed Text.Pandoc.LaTeXMathML. The module was no longer necessary; it was replaced by two lines in pandoc.hs. + Replaced LaTeXMathML.js.commend and LaTeXMathML.js.packed with a single combined file, LaTeXMathML.js. * Added --data-dir option. This specifies a user data directory. If not specified, will default to ~/.pandoc on unix or Application Data\pandoc on Windows. Files placed in the user data directory will override system default data files. * Added Maybe datadir parameter to readDataFile, saveOpenDocumentAsODT, latexMathMLScript, s5HeaderIncludes, and getDefaultTemplate. If Nothing, no user directory is searched for an override. * Added 'plain' output format. This is similar to markdown, but removes links, pictures, inline formatting, and most anything that looks even vaguely markupish. The function writePlain is exported by Text.Pandoc.Writers.Markdown, with which it shares most of its code. * Allow multi-line titles and authors in meta block. Titles may span multiple lines, provided continuation lines begin with a space character. Separate authors may be put on multiple lines, provided each line after the first begins with a space character. Each author must fit on one line. Multiple authors on a single line may still be separated by a semicolon. Based on a patch by Justin Bogner. * When given an absolute URI as parameter, pandoc will try to fetch the content via HTTP. So you can do: 'pandoc -r html -w markdown http://www.fsf.org' Adds dependency on HTTP. * Made HTML reader much more forgiving. + Incorporated idea (from HXT) that an element can be closed by an open tag for another element. + Javascript is partially parsed to make sure that a <script> section is not closed by a </script> in a comment or string. + More lenient non-quoted attribute values. Now we accept anything but a space character, quote, or <>. This helps in parsing e.g. www.google.com! + Bare & signs are now parsed as a string. This is a common HTML mistake. + Skip a bare < in malformed HTML. * Removed html2markdown and hsmarkdown. + html2markdown is no longer needed, since you can now pass URI arguments to pandoc and directly convert web pages. (Note, however, that pandoc assumes the pages are UTF8. html2markdown made an attempt to guess the encoding and convert them.) + hsmarkdown is pointless -- a large executable that could be replaced by 'pandoc --strict'. * In most writers, an image in a paragraph by itself is now rendered as a figure, with the alt text as the caption. (Texinfo, HTML, RST, MediaWiki, Docbook, LaTeX, ConTeXt, HTML.) Other images are rendered inline. * Depend on extensible-exceptions. This allows pandoc to be compiled on GHC 6.8. * Added --base-header-level option. For example, --base-header-level=2 will change level 1 headers to level 2, level 2 to level 3, etc. Closes Debian #563416. * Incomplete support for RST tables (simple and grid). Thanks to Eric Kow. Colspans and rowspans not yet supported. * Added accessors (docTitle, docAuthors, docDate) to Meta type. * MediaWiki writer: format links with relative URLs as wikilinks. The new rule: If the link target is an absolute URL, an external link is created. Otherwise, a wikilink is created. * Text.Pandoc.Shared: Export uniqueIdent, and don't allow tilde in identifier. Note: This may break links to sections that involve tildes. * Markdown(+lhs) reader: handle "inverse bird tracks." Inverse bird tracks (<) are used for haskell example code that is not part of the literate Haskell program. Resolves Issue #211. * LaTeX reader: + Recognize '\ ' (interword space). + Recognize nonbreaking space '~'. + Ignore \section, \pdfannot, \pdfstringdef. Ignore alt title in section headers. Don't treat \section as inline LaTeX. Resolves Issue #202. + LaTeX reader: allow any special character to be escaped. Resolves Issue #221. + LaTeX reader: treat \paragraph and \subparagraph as level 4, 5 headers. Resolves Issue #207. * Use template variables for include-before/after. + These options now imply -s; previously they worked also in fragment mode. + Users can now adjust position of include-before and include-after text in the templates. + Default position of include-before moved back (as it was before 1.4) before table of contents. + Resolves Issue #217. * Don't print an empty table header: (all writers). Resolves Issue #210. * HTML, Docbook writer: Use tbody, thead, and cols in tables. * HTML writer: Don't include TOC div if table of contents is empty. * Markdown writer: Fixed citations. Previously the markdown writer printed raw citation codes, e.g. [geach1970], rather than the expanded citations provided by citeproc, e.g. (Geach 1970). Now it prints the expanded citations. This means that the document produced can be processed as a markdown document without citeproc. Thanks to dsanson for reporting, and Andrea Rossato for the patch. * Improved and simplified title block in context template. Previously it caused an error if there was no title. This method should also be easier for users to customize. * Markdown reader: + Treat p., pp., sec., ch., as abbreviations in smart mode. + Disallow blank lines in inline code span. + Allow footnotes to be indented < 4 spaces. This fixes a regression. A test case has been added. + Escape spaces in URLs as %20. Previously they were incorrectly escaped as +, which is appropriate only for the query part of a URL. Resolves Issue #220. + Require two spaces after capital letter + period for list item. Otherwise "E. coli" starts a list. This might change the semantics of some existing documents, since previously the two-space requirement was only enforced when the second word started with a capital letter. But it is consistent with the existing documentation and follows the principle of least surprise. Resolves Issue #212. * LaTeX template: redefine labelwidth when using enumerate package. Otherwise the list labels (numbers) often extend past the left margin, which looks bad. * Mediawiki writer: Don't print a "== Notes ==" header before references. This is too English-centric. Writers can provide their own header at the end of the document. * Promoted mediawiki headers. '= head =' is now level 1, '== head ==' level 2, etc. This seems to be correct; it's only by convention that wikipedia articles have level 2 headers at most. Patch due to Eric Kow. * RunTests.hs: Set LANG to a UTF-8 locale. Use 'pandoc --data-dir=' so data files don't need to have been installed. This removes the need to set HOME. * HTML reader: + Handle spaces before <html>. Resolves Issue #216. + Be forgiving in parsing a bare list within a list. The following is not valid xhtml, but the intent is clear: <ol> <li>one</li> <ol><li>sub</li></ol> <li>two</li> </ol> We'll treat the <ol> as if it's in a <li>. Resolves Issue #215. * Updated INSTALL instructions. cabal method is now promoted. * Updated markdown2pdf man page. It no longer says all pandoc options are accepted. * README/man pages: Removed advice to pipe through tidy before HTML reader. This is obsolete, now that we have a forgiving HTML parser. * LaTeX writer: set numbersections template variable, so the section numbering options work again. * Removed obsolete Makefile. * Website: renamed index.txt.in -> index.txt. * New batch file to make-windows-installer. + Removed old Makefile.windows + Added make-windows-installer.bat + Modified default installer name in pandoc-setup.iss * Removed freebsd and macports directories. They are no longer up to date. * Setup.hs: + Made man page building sensitive to build verbosity. + Improved detection of highlighting support in test hook. + Install wrapper scripts into cabal bin directory. + Also simplified installManpages. + Setup.hs: install manpages to mandir. Code borrowed from darcs. * Changed default of writerXeTeX to False. * HTML writer: don't include empty UL if --toc but no sections. Resolves Issue #199. * LaTeX writer: + If book, report, or memoir documentclass, use \chapter{} for first-level headers. Otherwise use \section{}. + Removed stLink, link template variable. Reason: we now always include hyperref in the template. * LaTeX template: + Only show \author if there are some. + Always include hyperref package. It is used not just for links but for toc, section heading bookmarks, footnotes, etc. Also added unicode=true on hyperref options. * markdown2pdf: always do at least two runs. hyperref bookmarks require this. * cabal file: Removed unneeded dependency on template-haskell. * Windows installer - fixed bug in data file locations. Resolves Issue #197. * Deprecated --custom-header in documentation. Removed old "Custom Headers" section in README. pandoc (1.4) [ John MacFarlane ] * Pandoc will now compile with either GHC 6.10 or 6.12. + Don't use System.IO.UTF8 when compiling with 6.12 + Use -fno-warn-unused-do-bind option when compiling with 6.12 * Replaced old headers with templates. Now users have much more control over the way documents appear in --standalone mode, and writer code is simplified. Resolves Issues #59, 147. Every effort has been made to retain backwards compatibilty. So, the --custom-header option should still work as before. + Added Text.Pandoc.Templates. This provides functions for retrieving default templates and for rendering templates. + System templates (in the pandoc data directory) can be overridden by user templates in $HOME/.pandoc/templates. + Removed Text.Pandoc.DefaultHeaders. + Removed data/headers directory. + Added templates directory. + Added writerTemplate and writerVariables fields to WriterOptions. + Removed writerTitlePrefix, writerHeader fields from WriterOptions. + Changed --print-default-header to --print-default-template. + Added --template option. + Added -V/--variable option to set custom template variables. * Pandoc no longer requires Template Haskell. Resolves Issue #186. + Removed need for TH in ODT module. Instead get reference.odt from data file at run time. + Removed TH dependency from S5 module. S5 module now exports s5HeaderIncludes, which pandoc.hs includes if writer is s5 and standalone. + Refactored LaTeXMathML not to use TH. * Meta is now Meta [Inline] [[Inline]] [Inline] rather than Meta [Inline] [String] String. Authors and date in Meta are now lists of Inline elements rather than raw strings. This means that they can be formatted and can include footnotes. NOTE: This may be a breaking change for those using pandoc as a library. * Added readDataFile to Text.Pandoc.Shared. This retrieves a data file from the user pandoc data directory (~/.pandoc on unix), or, if not found there, from the system data directory ($CABALDIR/shared/pandoc-VERSION/). All data files, including templates, LaTeXMathML.js, s5 styles, and reference.odt, can be overridden by the user. * s5 files moved from data/ui/default to s5/default. * Use unicode instead of entities in HTML and XML output. Resolves Issue #163. * Prettier HTML footnote references: put anchor inside sup, instead of other way. Resolves Issue #191. Thanks to infinity0x. * Added --xetex option to pandoc and markdown2pdf. If --xetex is specified, pandoc produces latex suitable for processing by xelatex, and markdown2pdf uses xelatex to create the PDF. Resolves Issue #185. * RTF writer: multiple authors now occupy multiple paragraphs rather than using a line break. * Man writer: now the "--after-body" will come after the "AUTHORS" section, whereas before it would come before it. This is a slight break from backwards compatibility. * Added --reference-odt option, so users may customize the styles used in pandoc-generated ODT files. Users may also place a default reference.odt in the ~\.pandoc directory. * ODT writer: + Indented and line-broke styles.xml so it can be modified more easily. + Omitted some unnecessary style declarations. + Don't wrap text in OpenDocument writer. The tags are too long, making wrapping ugly and pointless. * LaTeX reader: use \\ to separate multiple authors. * Markdown reader: use ; as separator between authors. This allows you to use ',' within author names: e.g. "John Jones, Jr." * S5 writer: use linebreak to separate authors in title page. * RST reader: Allow :: before lhs code block. The RST spec requires the :: before verbatim blocks. This :: should not be treated as literal colons. Resolves Issue #189. * Documented pandoc 1.3's new definition list syntax in README. (An oversight in the last release.) * markdown2pdf.hs: + interpret ! in a log as an error line. + --toc now works properly. * Changes in RunTests.hs: + Use the Diff library rather than a local copy of Diff.hs. (This vastly increases performance.) This change means that 'cabal test' presupposes that the Diff library is installed. + Removed tests/Diff.hs from cabal file. + Changed RunTests to use local environment. We need at least HOME, so pandoc can find its data directory. * Updated windows installer to install data files in the app directory. * Windows installer now installs portable wrappers hsmarkdown and markdown2pdf. pandoc (1.3) [ John MacFarlane ] * Added --id-prefix option (Issue #41). This adds a prefix to all automatically generated HTML identifiers, which helps prevent duplicate identifiers when you're generating a fragment (say a blog post). * Added --indented-code-classes option. This specifies classes to use for indented code blocks. (Patch due to buttock; Issue #87.) * --number-sections now affects HTML output as well as ConTeXt and LaTeX (Issue #150). * Improved syntax for markdown definition lists (Issue #24). Definition lists are now more compatible with PHP Markdown Extra. + You can have multiple definitions for a term (but still not multiple terms). + Multi-block definitions no longer need a column before each block (indeed, this will now cause multiple definitions). + The marker no longer needs to be flush with the left margin, but can be indented at or two spaces. Also, ~ as well as : can be used as the marker (this suggestion due to David Wheeler.) + There can now be a blank line between the term and the definitions. * Better looking simple tables. Resolves Issue #180. + Markdown reader: simple tables are now given column widths of 0. + Column width of 0 is interpreted as meaning: use default column width. + Writers now include explicit column width information only for multiline tables. (Exception: RTF writer, which requires column widths. In this case, columns are given equal widths, adding up to the text width.) + Simple tables should now look better in most output formats. * Allow markdown tables without headers (Issue #50). The new syntax is described in README. Also allow optional line of dashes at bottom of simple tables. * Compensate for width of final table column (Issue #144). * Treat a backslash followed by a newline as a hard line break in markdown. Resolves Issue #154. This is a nice alternative to markdown's "invisible" way of indicating hardline breaks using lines that end with two spaces. * Improved performance of markdown reader by ~10% by eliminating the need for a separate parsing pass for notes. Raw notes are now stored on the first pass (which parses references), then parsed when the note is inserted into the AST. The stateNotes field in ParserState is now a list of [(String, String)] pairs instead of [(String, [Block])]. * In markdown reader, treat 4 or more * or _ in a row as literal text. (Trying to parse long strings of * or _ as strong or emph leads to exponential performance problems.) * Markdown reader: Use + rather than %20 for spaces in URLs. * Fixed htmlComment parser, adding a needed 'try'. * Don't print raw HTML in man output. * Allow . _ and ~ in header identifiers. * Specially mark code blocks that were "literate" in the input. They can then be treated differently in the writers. This allows authors to distinguish bits of the literate program they are writing from source code examples, even if the examples are marked as Haskell for highlighting. (Issue #174.) * Modified html+lhs output to use "haskell" highlighter instead of "literateHaskell". The highlighting module now adds bird tracks after highlighting (for HTML output), if the code block has the "literate" class. This gives better results, because kate's haskell highlighter is much better than the literateHaskell highlighter. * Fixed handling of footnotes in titles (HTML) and headers (LaTeX). (Issue #137.) * Support for "..code-block" directive in RST reader. Not core RST, but used in Sphinx for code blocks annotated with syntax information. Thanks to Luke Plant for the patch. * Added "head" to list of block-level HTML tags. Resolves Issue #108. * Added stripTags to Text.Pandoc.XML. This is used in the HTML writer. * Set utf-8 encoding in texinfo headers. * Docbook writer: add ids to sections. Use link for internal links. (Issue #60.) * Blank lines after lists in MediaWiki writer. * Properly handle commented-out list items in markdown. Resolves Issue #142. Example: - a <!-- - b --> - c * Changed heuristic in compactify. compactify has to decide whether a Para that ends a list is a Para intentionally, or just because of the blank lines at the end of every list. In the latter case the Para is turned to a Plain. The old heuristic was: change final Para to Plain iff the other items all end in Plain. This produces bad results when, for example, an item contains just a Plain and an HTML comment, as it does in the list above. The new heuristic: change final Para to Plain iff the other items don't contain a Para. * Added % as an rst underline character. Resolves Issue #173. * Fix inline math parser so that \$ is allowed in math. Resolves Issue #169. * Translate \int (integral) into unicode when using unicode math method. Resolves Issue #177. * markdown2pdf.hs improvements: + Use System.IO.UTF8. + Print error messages on last attempt. + Do not create a backup when overwriting a PDF (Issue #166). + Accept --longopt=val options. + Added man/man1/markdown2pdf.1 to extra-tmp-files in cabal, so that it is properly cleaned. * Added haddock comments warning that readers assume \n line endings. * Updated COPYRIGHT file. * Makefile: Changed EXECSBASE so it doesn't pull in hsmarkdown & markdown2pdf. Otherwise strip tries to strip shell scripts when you install using 'make'. * Changed Makefile so it doesn't build Haskell wrappers. * Fixed Makefile so it doesn't try to build man pages in build-doc. * Install pcre3.dll in Windows install script; this allows us to package a version of pandoc with highlighting support. pandoc (1.2.1) [ John MacFarlane ] * Fixed regression with --preserveTabs. Brought back optPreserveTabs. The trick of setting tabStop to 0 to mean "preserve tabs" had a bad side effect: strings of 0 spaces were interpreted as indentation. So, with --preserve-tabs, unindented paragraphs were treated as code. Resolves Issue #138. * HTML writer: wrap sections in divs. Resolves Issue #70. + hierarchicalize has been rationalized; it builds a hierarchical representation of the document from the headers, and simultaneously gives each section a unique identifier based on the heading title. + Identifiers are now attached to the divs rather than to the headers themselves. + Table of content backlinks go to the beginning of the table, rather than to the section reference that was clicked. + Code for constructing identifiers has been moved to Text.Pandoc.Shared from the HTML writer, since it is now consumed only by hierarchicalize. + In --strict mode, pandoc just prints bare headings, as before (unless --toc has been specified). + In s5 output, it does not wrap sections in divs, as that seems to confuse the s5 javascript. * Man writer: break lines at end of each sentence. groff expects this and treats '.' and '?' differently when followed by line ending as opposed to ordinary space. Also, don't escape periods. Instead, use zero-width character \& to avoid unwanted interpretation of periods at start of line. Resolves Issue #148. * Markdown writer: Added '#' and '>' to list of characters to be escaped in markdown output. Removed '<', as it is not an officially escapable character. This partially resolves Issue #96. * Make --smart the default for man output format. Otherwise we have trouble dividing lists of endlines into sentences. * DocBook writer: Use language attribute to indicate source language in code blocks. * RST reader: + Allow # to continue list, even if the list was started with an explicit marker. For example: A. my list #. continued Resolves Issue #140. + Allow continuation lines in line blocks. Also added test cases for line blocks for RST reader. Resolves Issue #149. + Allow explicit links with spaces in URL: `link <to this>`_ * Improved LaTeX reader's coverage of math modes. Remove displaymath* (which is not in LaTeX) and recognize all the amsmath environments that are alternatives to eqnarray, namely equation, equation*, gather, gather*, gathered, multline, multline*, align, align*, alignat, alignat*, aligned, alignedat, split. Resolves Issue #103. Thanks to shreevatsa.public for the patch. * Markdown reader: + Allow -, _, :, . in markdown attribute names. These are legal in XML attribute names. + Use non-breaking spaces in abbreviations. + Markdown reader: improved efficiency of abbreviation parsing. Instead of a separate abbrev parser, we just check for abbreviations each time we parse a string. This gives a huge performance boost with -S. Resolves Issue #141. * Improved efficiency of shared parsers: hexNum, htmlComment, whitespace, indentSpaces. * Export HTMLMathMethod in Text.Pandoc. * Export languagesByExtension in Text.Pandoc.Highlighting. * Added new Haskell version of markdown2pdf, due to Paulo Tanimoto. This should be more portable than the old shell script. * Made 'pandoc -v' more explicit about compiler options. Resolves Issue #139. * pandoc.hs: Made --strict compatible with --standalone, --toc. * Use Paths_pandoc to get version number, instead of hard-coding it into Text/Pandoc.hs. pandoc (1.2) [ John MacFarlane ] * Added support for literate Haskell. lhs support is triggered by '+lhs' suffixes in formats. For example, 'latex+lhs' is literate Haskell LaTeX. '.lhs' files are treated by default as literate markdown. + Added stateLiterateHaskell to parser state. + Added parser for lhsCodeBlock to Markdown, RST, LaTeX readers. + Added parser for |inline lhs| to LaTeX reader. + Added writerLiterateHaskell to WriterOptions. + Added lhs support to Markdown, RST, LaTeX, HTML writers. + Added definition of code environment to LaTeX header. + Added tests (run only if highlighting support compiled in). + Documented lhs features in man page and README. * In Text.Pandoc.Definition, added processWith, processWithM, and queryWith, and deprecated processPandoc and queryPandoc for these more general functions. * Fixed bug in mediawiki writer: improper closing tags in tables. Thanks to Benct Philip Jonsson for reporting the bug. * Added --email-obfuscation option. + Added writer option for email obfuscation. + Implemented email obfuscation options in HTML writer. + Added option to option parser. + Documented in README and pandoc man page. + Resolves Issue #97. * LaTeX writer: fixed bug with empty table cells. Resolves Issue #107. Thanks to rodja.trappe for the patch. * Fixed bug with header spacing in Markdown and RST writers. A null header (Meta [] [] []) should not cause a blank line at the beginning of output. But a blank line is needed between a non-null header and the main text. * Markdown reader: Relax spacing rules for $$ in display math. Now space and newlines are allowed after the opening $$ and before the closing $$. However, the display math cannot contain an entirely blank line. Resolves Issue #105. * Markdown reader: Gobble space after Plain blocks containing only raw html inline. Otherwise following header blocks are not parsed correctly, since the parser sees blank space before them. Resolves Issue #124. * Markdown reader: Allow " as well as '' to end a latex double-quote. * Conditionally depend on syb and base >= 4 if ghc >= 6.10. Resolves Issue #109. * Fixed problems in RST and markdown output due to bug in pretty-1.0.1.0 + Added hang' function to Text.Pandoc.Shared; this will be used instead of hang, which doesn't work properly in pretty-1.0.1.0. When pretty is upgraded, we can go back to hang. See http://article.gmane.org/gmane.comp.lang.haskell.general/16687 + Use hang' (and some different techniques) in RST and markdown writers. Some output is now a bit different. * Brought citeproc support up to date for citeproc-hs-0.2. (Patch by Andrea Rossato.) * Moved all haskell source to src subdirectory. Renamed Main.hs to pandoc.hs. * Rewrote hsmarkdown in Haskell for portability (src/hsmarkdown.hs). For now, keeping the old shell script too. * Added TemplateHaskell to Extensions for executable, removed -threaded for library. Thanks to duncan.coutts for the bug report. Resolves Issue #121. * Moved some Extra-Source-Files to Data-Files. * Moved tabFilter to Shared. * In pandoc.hs, removed optPreserveTabs; instead, tabstop of 0 means preserve tabs. * Minor code cleanup based on hlint suggestions. pandoc (1.1) [ John MacFarlane ] * Main.hs: + Changed date on copyright message in Main.hs. + Have the '-v' option print syntax highlighting languages separated by commas, and wrapped in lines, instead of in five columns as before. * Added --jsmath option. Resolves Issue #68. + Added --jsmath option to Main.hs + Added JsMath to HTMLMathMethod in Text.Pandoc.Shared. + Handle math appropriately in HTML writer when JsMath selected. + Documented the option in README and man page. * Text.Pandoc.Shared: Changed compactify to use a better heuristic for tight and loose lists. Final Para is changed to Plain if all other list items *end* with a Plain block. Addresses Issue #99. * HTML reader: + Added colons to protocols in unsanitaryURI. Closes Issue #88. + HTML reader: Don't interpret contents of <pre> blocks as markdown. Added rawVerbatimBlock parser. Resolves Issue #94. * Markdown reader: + Allow URLs with spaces in them in links and references, but escape them as "%20". + Allow blank space at the end of horizontal rules. * RST reader: Modified 'unknownDirective' parser to handle comment blocks correctly, and added tests for comment blocks. Resolves Issue #86. Closes Debian Bug #500662. * HTML writer: + Include classes on tr elements in HTML output: "header", "odd", "even". This allows tables to be styled with lines in alternating colors. Resolves Issue #91. + Enclose all LaTeXMathML bits in <span class="LaTeX">. This prevents parts of the document that are not math from being interpreted as math by LaTeXMathML.js. * OpenDocument and ODT writers: Added support for HorizontalRule elements, which were formerly ignored. Resolves Issue #95. * Text.Pandoc.Shared: Modified wrappedTeX to eliminate the line break between a footnote and immediately following nonspace characters in LaTeX and ConTeXt output. (This gets interpreted as a space, which is not desired in cases like "text^[note]---".) Resolves Issue #93. * Windows installer: Don't require admin privileges to run installer. Modified pandoc-setup.iss, and changed modpath.iss to modify HKCU path if user lacks admin privileges. Also fixed case where oldpath is empty (previously this led to the new path beginning with a semicolon). * Updated INSTALL instructions for Arch packages and OS X install using cabal-install. * Removed the (now unneeded) debian directory. Removed empty Codec and System directories. * Moved odt-styles/ to data/. Removed unneeded variable in Makefile. * Modified Setup.hs so that the "test" target returns an error status when tests fail, and "build" returns a success status if the build succeeds. Resolves Issue #100. * Added BUGS to files in tarball. pandoc (1.0.0.1) [ John MacFarlane ] * Removed spurious reference to pdf output format from pandoc(1) man page. pandoc (1.0) [ Andrea Rossato ] * Added new OpenDocument writer. * Added support for SmallCaps inline element. * Added support for integrating pandoc with citeproc-hs. + Added Cite element to definition and writers. + Added Text.Pandoc.Biblio module + Note: This support is included only if the 'citeproc' Cabal configuration flag is set. * Made Pandoc data structure an instance of Typeable. Added new processPandoc and queryPandoc functions, to query or transform matching elements in a Pandoc structure. [ Peter Wang ] * Added new Texinfo writer. [ John MacFarlane ] * Changes to Texinfo writer: + No space between paragraph and following @verbatim (provides more pleasing appearance in text formats) + Blank line consistently after list environments. + Removed deVerb. + Use @code instead of @verb for inline code (this solves the character escaping problem for texi2dvi and texi2pdf). + Added news of Texinfo writer to README. + Added Texinfo to list of formats in man page, and removed extra 'groff'. + Added texi & texinfo extensions to Main.hs, and fixed bug in determining default output extension. + Modified disallowedInNode in Texinfo writer to correct list of disallowed characters. * Added tests for OpenDocument writer. * Added ODT writer (using zip-archive library to package output of OpenDocument writer). Added odt-styles directory with default ODT styles. * Added new mediawiki writer and tests. * Markdown reader: Added support for delimited code blocks, with optional syntax highlighting using highlighting-kate (if the 'highlighting' configuration option is selected). + Currently highlighting is supported only in the HTML writer. + Delimited code blocks can have attributes; using the language name as class triggers highlighting. + New Attributes parameter in CodeBlock structure. + --version now indicates whether syntax highlighting support is compiled in, and prints a list of supported languages * Removed debian directory. Pandoc is no longer a native debian package. * Changes to build process: pandoc can now be built from the repository using Cabal. No unix tools are needed (so, pandoc can be built on Windows without Cygwin). + Include shell scripts themselves in repo, rather than generating from wrappers. Removed wrappers directory and wrappers Makefile target. + Text/Pandoc/ASCIIMathML.hs, Text/Pandoc/DefaultHeaders.hs, and Text/Pandoc/Writers/S5.hs are no longer built in Makefile from templates in the templates/ directory. Instead, they use template haskell to read data at compile time from the relevant files in data/. Template haskell functions go in a new module, Text.Pandoc.TH. + man pages are now generated in Setup.hs hook, not by Makefile + Makefile 'tarball' target now calls Cabal's 'sdist' + Added "Extra-Source-Files" to pandoc.cabal, so sdist contains everything needed + Added "Build-Type" field to pandoc.cabal to avoid warning. + Added to "Extra-source-files" and "Extra-tmp-files" in pandoc.cabal, so 'sdist' and 'clean' will work properly. + Setup.hs now generates man pages in a postbuild hook. + Added dependency-checking to Setup.hs, so it only rebuilds things that need rebuilding. + Added 'library' and 'executable' configuration flags. Cabal can now be told to build just the library or just the executable. + CABALOPTS may now be specified with 'make' to pass Cabal configuration flags. For example: CABALOPTS=-fhighlighting make * Rewrote test suite so it doesn't depend on perl or unix tools. + Replaced old runtests.pl with a Haskell script RunTests.hs. + Added Diff.hs module to be used by RunTests.hs instead of unix 'diff'. + Added test hook to Setup.hs, so tests may be run from cabal. + Changed Makefile's 'test' target to run tests via cabal. + Removed old generate.sh. + Since we no longer have 'sed' to filter out raw HTML sections from the docbook writer test, or raw LaTeX sections from the context writer test, we now just include these sections. They can be taken out if it is necessary to process the files. + Updated latex and context writer tests to remove extra spaces after '\\item' + Added a markdown table reader test. + Added markdown-reader-more.txt to test suite, for additional test cases for raw ConTeXt environments and more. * Compatibility fixes for CPP, Cabal, and haddock: + Use CPP in "Extensions" field in pandoc.cabal. + Removed use of backslash string continuations in source files. * Removed pandoc.cabal.ghc66. We now require Cabal >= 1.2, GHC >= 6.8, base >= 3. * Require parsec < 3. The compatibility module in parsec 3.0.0 gives far worse performance than parsec 2.1. Eventually pandoc will be upgraded to use the new bytestring version of parsec, and then we'll go to parsec 3.0.0. * Removed Text.Regex dependencies by rewriting using plain Haskell (Text.Pandoc.Writers.RTF, Text.Pandoc.Writers.HTML, Main.hs) * Moved Text.Pandoc.Writers.DefaultHeaders -> Text.Pandoc.DefaultHeaders. * Makefile: + Added 'configure' as dependency of 'uninstall-all'. (It uses the Cabal build program.) + Makefile: only use --with-hc-pkg if GHC_PKG is defined. Note that Cabal will automatically choose the ghc-pkg appropriate for the compiler selected, so normally specifying GHC by itself is sufficient. * Removed Text.Pandoc.UTF8 module; instead, depend on utf8-string and use its IO and conversion functions. * Added -Wall to ghc-options in pandoc.cabal. Cleaned up modules so that everything is -Wall clean. + Added pragma to HTML writer to avoid deprecation warning for use of "start" attribute. + Added pragma to Text/Pandoc/Shared.hs to get rid of "orphan instance" warnings. (These are caused by the Lift instance for ByteString.) * Changed the comment used to replace unsafe HTML if sanitize-html option selected. * Made -c/--css option repeatable on the command line (like -H, -A, -B). * Moved XML-formatting functions to new unexported module Text.Pandoc.XML. * Escape '\160' as " ", not " " in XML. "nbsp" isn't a predefined XML entity. * Fixed bug in RST reader, which would choke on: "p. one\ntwo\n". Added some try's in ordered list parsers. * Man writer: don't escape " as \". * Allow newline before URL in markdown link references. Resolves Issue #81. Added tests for this issue in new "markdown-reader-more" tests. Changed RunTests.hs to run these tests. * Support for display math. Resolves Issue #47. + Added a DisplayMath/InlineMath selector to Math inlines. + Markdown parser yields DisplayMath for $$...$$. + LaTeX parser yields DisplayMath when appropriate. Removed mathBlock parsers, since the same effect is achieved by the math inline parsers, now that they handle display math. + Writers handle DisplayMath as appropriate for the format. + Modified tests accordingly; added new tests for display math. * Use LaTeXMathML instead of ASCIIMathML. LaTeXMathML is closer to LaTeX in its display of math, and supports many non-math LaTeX environments. + Changed -m option to use LaTeXMathML rather than ASCIIMathML. + Modified HTML writer to print raw TeX when LaTeXMathML is being used instead of suppressing it. + Removed ASCIIMathML files from data/ and added LaTeXMathML. + Replaced ASCIIMathML with LaTeXMathML in source files. + Modified README and pandoc man page source. + Added --latexmathml option (kept --asciimathml as a synonym for backwards compatibility) * Markdown reader: Parse setext headers before atx headers. Test case: # hi ==== parsed by Markdown.pl as an H1 header with contents "# hi". * Markdown reader: Treat "mixed" lists the same way as Markdown.pl does. The marker on the first list item determines the type of the whole list. Thus, a list like 1. one - two * three gets parsed as a single ordered list. (Previous versions of pandoc treated this as an ordered list with an unordered sublist.) * Markdown smart typography: + Em dashes no longer eat surrounding whitespace. Resolves Issue #69. + Use nonbreaking spaces after known abbreviations in markdown parser. Thus, for example, "Mr. Brown" comes out as "Mr.~Brown" in LaTeX, and does not produce a sentence-separating space. Resolves Issue #75. * Markdown writer: Print unicode \160 literally, rather than as  . * Treat '\ ' in (extended) markdown as nonbreaking space. Print nonbreaking space appropriately in each writer (e.g. ~ in LaTeX). * The '--sanitize-html' option now examines URIs in markdown links and images, and in HTML href and src attributes. If the URI scheme is not on a whitelist of safe schemes, it is rejected. The main point is to prevent cross-site scripting attacks using 'javascript:' URIs. See http://www.mail-archive.com/markdown-discuss@six.pairlist.net/msg01186.html and http://ha.ckers.org/xss.html. Resolves Issue #62. * HTML writer: + Override Text.XHtml's stringToHtml function, so that characters below 0xff are not converted to numerical entity references. Also convert '\160' to " ". This should aid readability and editability of the HTML source. It does presuppose that the HTML will be served as UTF-8. + In code blocks, change leading newlines to <br /> tags. (Some browsers ignore them.) Resolves Issue #71. See http://six.pairlist.net/pipermail/markdown-discuss/2008-May/001297.html + Use style attributes rather than css classes for strikethrough and ordered list styles. This works better when fragments, rather than standalone documents, are generated. * HTML reader: Count anything that isn't a known block (HTML) tag as an inline tag (rather than the other way around). Added "html", "head", and "body" to list of block tags. Resolves Issue #66, allowing <lj> to count as an inline tag. * RTF writer: Fixed bug. Extra spaces were being printed after emphasized, boldface, and other inline elements. Resolves Issue #64. * LaTeX reader: improvements in raw LaTeX parsing. + "loose punctuation" (like {}) parsed as Space + Para elements must contain more than Str "" and Space elements + Added parser for "\ignore" command used in literate haskell. + Reworked unknownCommand and rawLaTeXInline: when not in "parse raw" mode, these parsers simply strip off the command part and allow the arguments to be parsed normally. So, for example, \blorg{\emph{hi}} will be parsed as Emph "hi" rather than Str "{\\emph{hi}}". + Parse lhs "code" environments as verbatim. Refactored parsers for verbatim environments. + Removed specialEnvironment parser. + parse '{}', if present, after \textless, \textgreater, \textbar, \textbackslash, \ldots. + Parse unescaped special characters verbatim rather than changing them to spaces. This way arguments of unknown commands will appear in braces. * Parse raw ConTeXt environments as TeX in markdown reader. Resolves Issue #73. * Moved BlockWrapper and wrappedBlocksToDoc from ConTeXt writer to Shared. * Made some structural changes to parsing of raw LaTeX environments. Previously there was a special block parser for LaTeX environments. It returned a Para element containing the raw TeX inline. This has been removed, and the raw LaTeX environment parser is now used in the rawLaTeXInline parser. The effect is exactly the same, except that we can now handle consecutive LaTeX and ConTeXt environments not separated by spaces. This new flexibility is required by the example in Issue #73: \placeformula \startformula L_{1} = L_{2} \stopformula API change: The LaTeX reader now exports rawLaTeXEnvironment' (which returns a string) rather than rawLaTeXEnvironment (which returns a block element). This is more likely to be useful in other applications. * Use \textsubscr instead of \textsubscript for LaTeX subscript macro. \textsubscript conflicts with a definition in the memoir class. Resolves Issue #65. * Removed unneeded space after "\\item" in LaTeX and ConTeXt output. * Added amsmath package to default LaTeX header. Resolves Issue #48. * Added \setupitemize[autointro] to ConTeXt header, to prevent orphaned list introduction lines. * Changed Float to Double in definition of Table element. (Double is more efficient in GHC.) * Fixed bug in Markdown parser: regular $s triggering math mode. For example: "shoes ($20) and socks ($5)." The fix consists in two new restrictions: + the $ that ends a math span may not be directly followed by a digit. + no blank lines may be included within a math span. Thanks to Joseph Reagle for noticing the bug. * Use Data.List's 'intercalate' instead of custom 'joinWithSep'. Removed 'joinWithSep' from Text.Pandoc.Shared. * Updated README and man pages. Acknowledge contributors in README. Added paragraph to README about producing S5 with separate CSS/javascript. * Updated INSTALL to reflect new build system (including configuration options) and document new dependencies. Added note to INSTALL that Cabal >= 1.2 is required for build. Resolves Issue #74. * Fixed some haddock documentation errors. * Small fix to markdown2pdf man page: only input needs to be piped through iconv. pandoc (0.46) unstable; urgency=low [ John MacFarlane ] * Made -H, -A, and -B options cumulative: if they are specified multiple times, multiple files will be included. * Added optional HTML sanitization using a whitelist. When this option is specified (--sanitize-html on the command line), unsafe HTML tags will be replaced by HTML comments, and unsafe HTML attributes will be removed. This option should be especially useful for those who want to use pandoc libraries in web applications, where users will provide the input. + Main.hs: Added --sanitize-html option. + Text.Pandoc.Shared: Added stateSanitizeHTML to ParserState. + Text.Pandoc.Readers.HTML: - Added whitelists of sanitaryTags and sanitaryAttributes. - Added parsers to check these lists (and state) to see if a given tag or attribute should be counted unsafe. - Modified anyHtmlTag and anyHtmlEndTag to replace unsafe tags with comments. - Modified htmlAttribute to remove unsafe attributes. - Modified htmlScript and htmlStyle to remove these elements if unsafe. + Modified README and man pages to document new option. * Improved handling of email addresses in markdown and reStructuredText. Consolidated uri and email address parsers. (Resolves Issue #37.) + New emailAddress and uri parsers in Text.Pandoc.Shared. - uri parser uses parseURI from Network.URI. - emailAddress parser properly handles email addresses with periods in them. + Removed uri and emailAddress parsers from Text.Pandoc.Readers.RST and Text.Pandoc.Readers.Markdown. * Markdown reader: + Fixed emph parser so that "*hi **there***" is parsed as a Strong nested in an Emph. (A '*' is only recognized as the end of the emphasis if it's not the beginning of a strong emphasis.) + Moved blockQuote parser before list parsers for performance. + Modified 'source' parser to allow backslash-escapes in URLs. So, for example, [my](/url\(1\)) yields a link to /url(1). Resolves Issue #34. + Disallowed links within links. (Resolves Issue #35.) - Replaced inlinesInBalanced with inlinesInBalancedBrackets, which instead of hard-coding the inline parser takes an inline parser as a parameter. - Modified reference and inlineNote to use inlinesInBalancedBrackets. - Removed unneeded inlineString function. - Added inlineNonLink parser, which is now used in the definition of reference. - Added inlineParsers list and redefined inline and inlineNonLink parsers in terms of it. - Added failIfLink parser. + Better handling of parentheses in URLs and quotation marks in titles. - 'source' parser first tries to parse URL with balanced parentheses; if that doesn't work, it tries to parse everything beginning with '(' and ending with ')'. - source parser now uses an auxiliary function source'. - linkTitle parser simplified and improved, under assumption that it will be called in context of source'. + Make 'block' conditional on strictness state, instead of using failIfStrict in block parsers. Use a different ordering of parsers in strict mode (raw HTML block before paragraph) for performance. In non-strict mode use rawHtmlBlocks instead of htmlBlock. Simplified htmlBlock, since we know it's only called in strict mode. + Improved handling of raw HTML. (Resolves Issue #36.) - Tags that can be either block or inline (e.g. <ins>) should be treated as block when appropriate and as inline when appropriate. Thus, for example, <ins>hi</ins> should be treated as a paragraph with inline <ins> tags, while <ins> hi </ins> should be treated as a paragraph within <ins> tags. - Moved htmlBlock after para in list of block parsers. This ensures that tags that can be either block or inline get parsed as inline when appropriate. - Modified rawHtmlInline' so that block elements aren't treated as inline. - Modified para parser so that paragraphs containing only HTML tags and blank space are not allowed. Treat these as raw HTML blocks instead. + Fixed bug wherein HTML preceding a code block could cause it to be parsed as a paragraph. The problem is that the HTML parser used to eat all blank space after an HTML block, including the indentation of the code block. (Resolves Issue #39.) - In Text.Pandoc.Readers.HTML, removed parsing of following space from rawHtmlBlock. - In Text.Pandoc.Readers.Markdown, modified rawHtmlBlocks so that indentation is eaten *only* on the first line after the HTML block. This means that in <div> foo <div> the foo won't be treated as a code block, but in <div> foo </div> it will. This seems the right approach for least surprise. * RST reader: + Fixed bug in parsing explicit links (resolves Issue #44). The problem was that we were looking for inlines until a '<' character signaled the start of the URL; so, if you hit a reference-style link, it would keep looking til the end of the document. Fix: change inline => (notFollowedBy (char '`') >> inline). Note that this won't allow code inlines in links, but these aren't allowed in resT anyway. + Cleaned up parsing of reference names in key blocks and links. Allow nonquoted reference links to contain isolated '.', '-', '_', so so that strings like 'a_b_' count as links. + Removed unnecessary check for following link in str. This is unnecessary now that link is above str in the definition of 'inline'. * HTML reader: + Modified rawHtmlBlock so it parses </html> and </body> tags. This allows these tags to be handled correctly in Markdown. 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>`). + Don't interpret contents of style tags as markdown. (Resolves Issue #40.) - Added htmlStyle, analagous to htmlScript. - Use htmlStyle in htmlBlockElement and rawHtmlInline. - Moved "script" from the list of tags that can be either block or inline to the list of block tags. + Modified rawHtmlBlock to use anyHtmlBlockTag instead of anyHtmlTag and anyHtmlEndTag. This fixes a bug in markdown parsing, where inline tags would be included in raw HTML blocks. + Modified anyHtmlBlockTag to test for (not inline) rather than directly for block. This allows us to handle e.g. docbook in the markdown reader. * LaTeX reader: Properly recognize --parse-raw in rawLaTeXInline. Updated LaTeX reader test to use --parse-raw. * HTML writer: + Modified rules for automatic HTML header identifiers to ensure that identifiers begin with an alphabetic character. The new rules are described in README. (Resolves Issue #33.) + Changed handling of titles in HTML writer so you don't get "titleprefix - " followed by nothing. * ConTeXt writer: Use wrappers around Doc elements to ensure proper spacing. Each block element is wrapped with either Pad or Reg. Pad'ed elements are guaranteed to have a blank line in between. * RST writer: + Refactored RST writer to use a record instead of a tuple for state, and to include options in state so it doesn't need to be passed as a parameter. + Use an interpreted text role to render math in restructuredText. See http://www.american.edu/econ/itex2mml/mathhack.rst for the strategy. [ Recai Oktaş ] * Debian packaging changes: + Remove the empty 'include' directory in -dev package, which lintian complains about. + Bump Standarts-Version to 3.7.3. + Use new 'Homepage:' field to specify the upstream URL on suggestion of lintian. -- Recai Oktaş <roktas@debian.org> Tue, 08 Jan 2008 05:13:31 +0200 pandoc (0.45) unstable; urgency=low [ John MacFarlane ] * Simplified parsing of reference keys and notes in markdown and RST readers: The Reference data structure from Text.Pandoc.Shared is no longer needed, since referenceKey and noteBlock parses return strings (as many blank lines as were occupied by the key or note) and update state themselves. getPosition and setPosition are now used to ensure that error messages will give the correct line number. This yields cleaner (and slightly faster) code, with more accurate parsing error messages. * Added new Math inline element: + Markdown and LaTeX readers now convert TeX math into Math elements, not TeX. + This allows math to be treated differently from raw TeX in output. TeX elements are no longer printed in output formats other than Markdown, LaTeX, and ConTeXt. But Math elements are always printed. * New default handling of math in writers: + New module Text.Pandoc.Readers.TeXMath exports readTeXMath, which parses raw TeX math and outputs a string of Pandoc inlines that tries to render it as far as possible using unicode characters, lapsing into literal TeX when needed. + 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 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 it can be processed by gladTeX. + 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. + HTMLMathMethod structure in WriterOptions keeps track of how to display math in HTML output. + Updated README with a description of the four options for displaying math in HTML. * HTML reader: + 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 (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. + Remove just one leading and one trailing newline from contents of `<pre>...</pre>` in codeBlock parser. * Markdown reader: + Removed support for box-style block quotes. + Require space before title in links and references. This fixes a bug in parsing URLs like http://silly/url(withparen). + Improved and simplified setextHeader parser. + Fixed logic in smart quote parsing, adding some needed 'try' statements. + Fixed smart quote parsing so that unicode characters 8216 and 8217 are recognized as single quotes, and 8220 and 8221 as double quotes. * RST reader: + Fixed bug in parsing of code blocks. Previously a full tab indent was required, but RST allows code to be indented any amount. Resolves Issue #27. + Allow field lists to be indented. + Parse the contents of field lists instead of treating as a raw string. + Represent field lists as definition lists instead of blockquotes. + Fixed bug in which metadata would be overridden if the document contained multiple field lists. + Parse fields associated with '.. image::' blocks, and use 'alt' field, if given, for image alt and title attributes. * LaTeX reader: + Modified specialChar so that '"' characters are parsed. + Fixed a bug in parsing of \[ \] math blocks (thanks to Mark Kalderon). * HTML writer: + Changes in handling of math (see above). + Don't produce HTML for table of contents if there are no headers. (This would be an empty list, which is invalid XHTML.) * Markdown writer: + Don't print title attribute if title is empty. (This differs from the behavior of Markdown.pl, and agrees with PHP Markdown. But John Gruber has indicated that he prefers this behavior.) Adjusted test suite accordingly. + Fixed incorrect line wrapping in paragraphs including hard line breaks. Resolves Issue #25. + Fixed bug in markdown writer: If an ordered list item began with a marker greater than 3 characters in width, and the item took more than one line, it would appear on the line after the list marker, e.g.: (12) My list item. Multiline. Now it works as follows: (12) My list item. Multiline. * RST writer + Fixed bug in RST writer's handling of ordered lists. Previously, list items with multiple lines would not always line up with single-line list items. Now, list items are nested the length of the list marker + 1. This looks better and ensures that list items all line up. (Note that list markers are padded to the length of the longest list marker in the series.) + Use 3-space indent for unordered lists. + If label for a link reference contains a colon, surround it by ` signs so it won't be interpreted as the end of the link label. * LaTeX writer: + Cleaner output for footnotes. Footnotes now always begin on a new line, and the final } is on a line by itself only when it needs to be (i.e. only when the note ends with a Verbatim environment). + Added writer options to state, so state doesn't need to be passed as a parameter. + Text wrapping now provided, using wrapTeXIfNeeded. * ConTeXt writer: many improvements for more idiomatic ConTeXt output (thanks to Idris Samawi Hamid for suggestions). + PrettyPrint module now used for output. + Writer options are now in state, so they don't have to be passed as a parameter. + Text wrapping now provided, using wrapTeXIfNeeded. + Better treatment of footnotes: footnotes are always on lines by themselves, and the final } is on a line by itself only when it needs to be (after \stoptyping). + Use \subject, \subsubject, ... or \section, \subsection, ... for headings, depending on whether --number-sections option is selected. + Extra blank line inserted after \stopitemize + Use new, "official" definition of blockquote environment. Also, use blank line after \startblockquote to balance blank line at the end. + Both itemized and enumerated lists are now generated using \start-stopitemize, with appropriate options. Removed definitions of ltxenum and ltxitem, which are no longer needed. Provided defaults for itemized lists in the preamble. State keeps track of ordered list level, so that when default numbering is specified, the appropriate scheme can be used. + Changed \useurl to \useURL. + Changed link color from red to blue. + Use \subsubsubsubsection etc., since these are supported (up to at least sub x 5). * Text.Pandoc.Shared: + Save and restore position in parseFromString, so that accurate error messages can be given. + Improved efficiency of romanNumeral parser. + Added wrappedTeX and wrapTeXIfNeeded functions. These ensure that footnotes occur on lines by themselves (to make them easier to see and move) and do not screw up line wrapping. * Text.Pandoc.UTF8: modified fromUTF8 to strip out the BOM if present. Windows Notepad and other applications insert a BOM at the beginning of a UTF8 file. * Main.hs (tabFilter): Treat '\r' at end of line as newline (in addition to "\r\n" and '\n'). * Added a writer option for wrapped text and a command-line option '--no-wrap', which disables text wrapping and minimizes whitespace in HTML. (Resolves Issue #26.) + Added support for '--no-wrap' to Main.hs. + Added wrapIfNeeded function to Text.Pandoc.Shared. + Use wrapIfNeeded instead of wrapped in the RST, Man, Docbook, and Markdown writers. + Added render and renderFragment helpers to HTML writer. * Modified html2markdown to run tidy only if the HTML cannot be parsed. Previously html2markdown piped all input through tidy before passing it to pandoc. This caused problems on certain pages (e.g. http://daringfireball.com/markdown) which have well-formed XHTML that causes tidy to choke. The solution is to pipe through tidy only if pandoc cannot parse the input by itself. This means that a temp file is now always used, even when input comes from a local file or standard input. * Removed 'version' constant from Main.hs; added 'pandocVersion' to Text.Pandoc library. * pandoc.cabal: + Modified to work with GHC 6.8 and Cabal configurations. (For GHC 6.8, pretty and containers must be added to Build-Depends, and it is desirable to use the -O2 compiler option.) Cabal configurations allows one to select options depending on the compiler version. For GHC 6.6, the splitBase option can be disabled. + pandoc.cabal.ghc66 is provided for users with older versions of Cabal, which do not support configurations. + Use Ghc-Prof-Options to ensure that '-auto-all' is used when '--enable-(executable|library)-profiling' is specified. Updated PROFILING instructions accordingly. * Makefile: + Makefile now checks GHC version. If GHC is 6.6, pandoc.cabal.ghc66 is copied to pandoc.cabal, and the old pandoc.cabal is copied to pandoc.cabal.orig. Otherwise, pandoc.cabal is copied to pandoc.cabal.orig but otherwise unmodified. This way, the Makefile will work properly with either GHC 6.6 or 6.8. + Changed BUILDCONF to point to dist/setup-config, not .setup-config. This is where current versions of Cabal put it. + Added $(BUILDCMD) target, so setup doesn't get compiled every time. + Removed dependency of templates on ./templates, which is circular now that templates is a subdirectory of the top-level. * MacPorts Portfile: + Modified to install the pandoc library in addition to programs. + Installation must be done manually rather than using Makefile's install-all. + Note that the library must be registered in the activate phase, after the library files have been copied out of the destroot. Cabal generates a 'register.sh' script that will do this. * debian/control: Added libghc6-network-dev, libghc6-xhtml-dev, and libghc6-mtl-dev as dependencies for libghc6-pandoc-dev. Closes: #445235 * debian/rules: Converted to UTF-8. * Changed pandoc home page to http://johnmacfarlane.net/pandoc/. * Updated ASCIIMathML.js to latest version. * Directory structure: + Moved everything from src into the top-level directory. + Changed references to source directory in Makefile and pandoc.cabal.*. + Moved ASCIIMathML.js, headers, and ui into templates directory. + Modified fillTemplates.pl to reflect new paths. [ Recai Oktaş ] * Makefile: Fixed the issue of having two copies of the library documentation under some usage scenarios. * Replaced 'ghc' with '$(GHC)' in Makefile, and made GHC and GHC_PKG configurable through the environment, to support unusual ghc installations. For example: GHC=/opt/ghc/bin/ghc GHC_PKG=/opt/ghc/bin/ghc-pkg make -- Recai Oktaş <roktas@debian.org> Sun, 07 Oct 2007 20:51:43 +0300 pandoc (0.44) unstable; urgency=low [ John MacFarlane ] * Fixed bug in HTML writer: when --toc was used, anchors were put around headers, which is invalid XHTML (block content within inline element). Now the anchors are put inside the header tags. Resolves Issue #23. * Added xmlns attribute to html element in html writer tests. This attribute is added by more recent versions of the xhtml library (>= 3000), and is required for valid XHTML. [ Recai Oktaş ] * On configure, compile 'Setup.hs' to 'setup' and use 'setup' as the build command instead of 'runhaskell', which, on some platforms (such as s390, alpha, m68k), throws the following error: runhaskell Setup.hs configure --prefix=/usr ghc-6.6.1: not built for interactive use This causes a serious FTBFS bug. Closes: #440668. -- Recai Oktaş <roktas@debian.org> Mon, 03 Sep 2007 18:24:02 +0300 pandoc (0.43) unstable; urgency=low [ John MacFarlane ] * The focus of this release is performance. The markdown parser is about five times faster than in 0.42, based on benchmarks with the TextMate manual. * Main.hs: Replaced CRFilter and tabFilter with single function tabFilter, which operates on the whole string rather than breaking it into lines, and handles dos-style line-endings as well as tabs. * Added separate LaTeX reader and native reader tests; removed round-trip tests. * Text.Pandoc.Shared: + Removed tabsToSpaces and tabsInLine (they were used only in Main.hs.) + General code cleanup (to elimante warnings when compiling with -Wall.) + Added 'wrapped' function, which helps wrap text into paragraphs, using the prettyprinting library. + Rewrote charsInBalanced and charsInBalanced'. - Documented restriction: open and close must be distinct characters. - Rearranged options for greater efficiency. - Bug fix: Changed inner call to charsInBalanced inside charsInBalanced' to charsInBalanced'. + anyLine now requires that the line end with a newline (not eof). This is a harmless assumption, since we always add newlines to the end of a block before parsing with anyLine, and it yields a 10% speed boost. + Removed unnecessary 'try' in anyLine. + Removed unneeded 'try' from romanNumeral parser. + Use notFollowedBy instead of notFollowedBy' in charsInBalanced. + Removed unneeded 'try' in parseFromString. + Removed unneeded 'try' from stringAnyCase. (Now it behaves like 'string'.) + Changed definition of 'enclosed' in Text.Pandoc.Shared so that 'try' is not automatically applied to the 'end' parser. Added 'try' in calls to 'enclosed' where needed. Slight speed increase. * Writers: + Replaced individual wrapping routines in RST, Man, and Markdown writers with 'wrapped' from Text.Pandoc.Shared. + Rewrote LaTeX writer to use the prettyprinting library, so we get word wrapping, etc. + Modified latex writer tests for new latex writer using prettyprinter. + Fixed bug in LaTeX writer: autolinks would not cause '\usepackage{url}' to be put in the document header. Also, changes to state in enumerated list items would be overwritten. + In Markdown writer, escape paragraphs that begin with ordered list markers, so they don't get interpreted as ordered lists. * Text.Pandoc.Reades.LaTeX: + Fixed bug in LaTeX reader, which wrongly assumed that the roman numeral after "enum" in "setcounter" would consist entirely of "i"s. 'enumiv' is legitimate. + LaTeX command and environment names can't contain numbers. + Rearranged order of parsers in inline for slight speed improvement. + Added '`' to special characters and 'unescapedChar'. * Text.Pandoc.Readers.RST: + Removed unneeded try's in RST reader; also minor code cleanup. + Removed tabchar. + Rearranged parsers in inline (doubled speed). * Text.Pandoc.Readers.Markdown: + Skip notes parsing if running in strict mode. (This yields a nice speed improvement in strict mode.) + Simplify autolink parsing code, using Network.URI to test for URIs. Added dependency on network library to debian/control and pandoc.cabal. + More perspicuous definition of nonindentSpaces. + Removed unneeded 'try' in 'rawLine'. + Combined linebreak and whitespace into a new whitespace parser, to avoid unnecessary reparsing of space characters. + Removed unnecessary 'try' in 'codeBlock', 'ellipses', 'noteMarker', 'multilineRow', 'dashedLine', 'rawHtmlBlocks'. + Use lookAhead in parsers for setext headers and definition lists to see if the next line begins appropriately; if not, don't waste any more time parsing. + Don't require blank lines after code block. (It's sufficient to 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`. + 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]. + Fixed markdown inline code parsing so it better accords with 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>`. + Split 'title' into 'linkTitle' and 'referenceTitle', since the rules are slightly different. + Rewrote 'para' for greater efficiency. + Rewrote link parsers for greater efficiency. + Removed redundant 'referenceLink' in definition of inline (it's already in 'link'). + Refactored escapeChar so it doesn't need 'try'. + Refactored hrule for performance in Markdown reader. + More intelligent rearranging of 'inline' so that most frequently used parsers are tried first. + Removed tabchar parser, as whitespace handles tabs anyway. * Text.Pandoc.CharacterReferences: + Refactored. + Removed unnecessary 'try's for a speed improvement. + Removed unnecessary '&' and ';' from the entity table. * Build process: + Makefile: Get VERSION from cabal file, not Main.hs. + Modified MacPorts Portfile: - Depend on haddock - Build and install libraries and library documentation in addition to pandoc executable - Added template item for md5 sum in Portfile.in. - Incorporated changes from MacPorts repository (r28278). + FreeBSD port: Don't try to generate distinfo in Makefile. It can be made using 'make makesum' in FreeBSD. + Make both freebsd and macports targets depend on tarball. * Website and documentation: + Updated INSTALL instructions. + Added pandocwiki demo to website. + Removed local references to Portfile, since pandoc is now in the MacPorts repository. -- Recai Oktaş <roktas@debian.org> Sun, 02 Sep 2007 15:50:11 +0300 pandoc (0.42) unstable; urgency=low [ John MacFarlane ] * Main.hs: Use utf8 conversion on the extra files loaded with the -H, -C, -B, and -A options. This fixes problems with unicode characters in these files. * Exposed Text.Pandoc.ASCIIMathML, since it is imported in Text.Pandoc.Readers.HTML and without it we get a linking error when using the library. * Markdown reader: + Added new rule for enhanced markdown ordered lists: if the list marker is a capital letter followed by a period (including a single-letter capital roman numeral), then it must be followed by at least two spaces. The point of this is to avoid accidentally treating people's initials as list markers: a paragraph might begin, "B. Russell was an English philosopher," and this shouldn't be treated as a list. Documented change in README. + Blocks that start with "p. " and a digit are no longer treated as ordered lists (it's a page number). + Added a needed 'try' to listItem. + Removed check for a following setext header in endline. A full test is too inefficient (doubles benchmark time), and the substitute we had before is not 100% accurate. + Don't use Code elements for autolinks if --strict specified. * LaTeX writer: When a footnote ends with a Verbatim environment, the close } of the footnote cannot occur on the same line or an error occurs. Fixed this by adding a newline before the closing } of every footnote. * HTML writer: + Removed incorrect "{}" around style information in HTML tables. Column widths now work properly in HTML. + If --strict option is specified (and --toc is not), don't include identifiers in headers, for better Markdown compatibility. * Build process: + Separated $(web_dest) and website targets. + In website, index.txt is now constructed from template index.txt.in. + Added freebsd target to Markefile. This creates the freebsd Makefile from Makefile.in, and creates distinfo. Removed Makefile and distinfo from the repository. + Added macport target to Makefile. Portfile is built from template Portfile.in. + Removed OSX package targets. (Too many difficulties involving dependencies on dynamic libraries.) + More complete INSTALL instructions for all architectures. * Website: + Added a programming demo, pandocwiki. [ Recai Oktaş ] * Do not forget to close pandoc's ITP. Closes: #391666 -- Recai Oktaş <roktas@debian.org> Sun, 26 Aug 2007 22:51:32 +0300 pandoc (0.41) unstable; urgency=low [ John MacFarlane ] * Fixed bugs in HTML reader: + 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 count either as block-level or as inline. Modified isInline and isBlock to take this into account. + Modified rawHtmlBlock to accept any tag (even an inline tag): this is innocuous, because rawHtmlBlock is tried only if a regular inline element can't be parsed. + Added a necessary 'try' in definition of 'para'. * Fixed bug in markdown ordered list parsing. The problem was that anyOrderedListStart did not check for a space following the ordered list marker. So in 'A.B. 2007' the parser would be expecting a list item, but would not find one, causing an error. Fixed a similar bug in the RST reader. Resolves Issue #22. * Refactored RST and Markdown readers using parseFromString. * LaTeX reader will now skip anything after \end{document}. * Fixed blockquote output in markdown writer: previously, block quotes in indented contexts would be indented only in the first line. * Added note to INSTALL about variations in versions of the xhtml library that can lead to failed tests (thanks to Leif LeBaron). -- Recai Oktaş <roktas@debian.org> Sun, 19 Aug 2007 23:26:07 +0300 pandoc (0.4) unstable; urgency=low [ John MacFarlane ] * Added two new output formats: groff man pages and ConTeXt. By default, output files with extensions ".ctx" and ".context" are assumed to be ConTeXt, and output files with single-digit extensions are assumed to be man pages. * Enhanced ordered lists (documented in README, under Lists): + The OrderedList block element now stores information about list number style, list number delimiter, and starting number. + The readers parse this information when possible. + The writers use this information to style ordered lists. + The enhancement can be disabled using the --strict option. * Added support for tables (with a new Table block element). Two kinds of tables are supported: a simple table with one-line rows, and a more complex variety with multiline rows. All output formats are supported, but only markdown tables are parsed at the moment. The syntax is documented in README. * Added support for definition lists (with a new DefinitionList block element). All output and input formats are supported. The syntax is documented in README. * Added support for superscripts and subscripts (with new Superscript and Subscript inline elements). All input and output formats. The syntax is documented in README. * Added support for strikeout (with a new Strikeout inline element). All input and output formats are supported. Thanks to Bradley Kuhn, who contributed a patch. The syntax is documented in README. Resolves Issue #18. * Added a --toc|--table-of-contents option. This causes an automatically generated table of contents (or an instruction that creates one) to be inserted at the beginning of the document. Not supported in S5, DocBook, or man page writers. * Modified the -m|--asciimathml option: + If an optional URL argument is provided, a link is inserted instead of the contents of the ASCIIMathML.js script. + Nothing is inserted unless the document actually contains LaTeX math. * Removed Blank block element as unnecessary. * Removed Key and Note blocks from the Pandoc data structure. All links are now stored as explicit links, and note contents are stored with the (inline) notes. + All link Targets are now explicit (URL, title) pairs; there is no longer a 'Ref' target. + Markdown and RST parsers now need to extract data from key and note blocks and insert them into the relevant inline elements. Other parsers have been simplified, since there is no longer any need to construct separate key and note blocks. + Markdown, RST, and HTML writers need to construct lists of notes; Markdown and RST writers need to construct lists of link references (when the --reference-links option is specified); and the RST writer needs to construct a list of image substitution references. All writers have been rewritten to use the State monad when state is required. + Several functions (generateReference, keyTable, replaceReferenceLinks, replaceRefLinksBlockList, and some auxiliaries used by them) have been removed from Text.Pandoc.Shared, since they are no longer needed. New functions and data structures (Reference, isNoteBlock, isKeyBlock, isLineClump) have been added. The functions inTags, selfClosingTag, inTagsSimple, and inTagsIndented have been moved to the DocBook writer, since that is now the only module that uses them. NoteTable is now exported in Text.Pandoc.Shared. + Added stateKeys and stateNotes to ParserState; removed stateKeyBlocks, stateKeysUsed, stateNoteBlocks, stateNoteIdentifiers, stateInlineLinks. + Added writerNotes and writerReferenceLinks to WriterOptions. * Added Text.Pandoc module that exports basic readers, writers, definitions, and utility functions. This should export everything needed for most uses of Pandoc libraries. The haddock documentation includes a short example program. * Text.Pandoc.ASCIIMathML is no longer an exported module. * Added Text.Pandoc.Blocks module to help in printing markdown and RST tables. This module provides functions for working with fixed-width blocks of text--e.g., placing them side by side, as in a table row. * Refactored to avoid reliance on Haskell's Text.Regex library, which (a) is slow, and (b) does not properly handle unicode. This fixed some strange bugs, e.g. in parsing S-cedilla, and improved performance. + Replaced 'gsub' with a general list function 'substitute' that does not rely on Text.Regex. + Rewrote extractTagType in HTML reader so that it doesn't use regexs. + In Markdown reader, replaced email regex test with a custom email autolink parser (autoLinkEmail). Also replaced selfClosingTag regex with a custom function isSelfClosingTag. + Modified Docbook writer so that it doesn't rely on Text.Regex for detecting 'mailto' links. + Removed escapePreservingRegex and reamped entity-handling functions in Text.Pandoc.Shared and Text.Pandoc.CharacterReferences to avoid reliance on Text.Regex (see below on character reference handling changes). * Renamed Text.Pandoc.Entities as Text.Pandoc.CharacterReferences. * Changed handling of XML entities. Entities are now parsed (and unicode characters returned) in the Markdown and HTML readers, rather than being handled in the writers. In HTML and Docbook writers, UTF-8 is now used instead of entities for characters above 128. This makes the HTML and DocBook output much more readable and more easily editable. + Removed sgmlHexEntity, sgmlDecimalEntity, sgmlNamedEntity, and sgmlCharacterEntity regexes from Text.Pandoc.Shared. + Renamed escapeSGMLChar to escapeCharForXML. Added escapeStringForXML. Moved both functions to Text.Pandoc.Writers.Docbook. + Added characterReference parser to Text.Pandoc.CharacterReferences. This parses a string and return a unicode character. + Rewrote decodeCharacterReferences to use the new parser instead of Text.Regex. + Added new charRef parser for Markdown and HTML, which replaces the old 'entity' parser. Added '&' as a special character in Markdown reader. + Modified HTML and Markdown readers to call decodeEntities on all raw strings (e.g. authors, dates, link titles), to ensure that no unprocessed entities are included in the native representation of the document. (In the HTML reader, most of this work is done by a change in extractAttributeName.) + In XML and Markdown output, escape unicode nonbreaking space as ' ', since a unicode non-breaking space is impossible to distinguish visually from a regular space. (Resolves Issue #3.) + Removed encodeEntitiesNumerical. + Use Data.Map for entityTable and (new) reverseEntityTable, for a slight performance boost over the old association list. + Removed unneeded decodeEntities from 'str' parser in HTML and Markdown readers. * Text.Pandoc.UTF8: Renamed encodeUTF8 to toUTF8, decodeUTF8 to fromUTF8, for clarity. * Replaced old haskell98 module names replaced by hierarchical module names, e.g. List by Data.List. Removed haskell98 from dependencies in pandoc.cabal, and added mtl (needed for state monad). Substituted xhtml for html. * Refactored and cleaned up character escaping in writers, using backslashEscapes and escapeStringUsing functions. * Instead of adding "\n\n" to the end of an input string in Main.hs, this is now done in the readers. This makes the libraries behave the way you'd expect from the pandoc program. Resolves Issue #10. * URLs and email addresses in autolinks are now typeset as Code. * In Main.hs, changed putStr to putStrLn -- mainly because MacOS X doesn't display the whole output unless there's a line ending. * Major code cleanup in all modules, for greater consistency, concision, and readability. * HTML reader: + Fixed several bugs (extractTagType, attribute parsing). + Remove Null blocks in lists of blocks when possible. + Allow HTML comments as raw HTML inline. * Markdown reader: + Ordered list items may no longer begin with uppercase letters, or letters greater than 'n'. (This prevents first initials and page reference, e.g. 'p. 400', from being parsed as beginning lists.) Also, numbers beginning list items may no longer end with ')', which is now allowed only after letters. Note: These changes 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. + 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), instead of parsing normally, then using setInput to reset input. This yields a slight performance boost. + Fixed several bugs in smart quote recognition. + Fixed bug in indentSpaces (which didn't properly handle cases with mixed spaces and tabs). + Consolidated 'text', 'special', and 'inline' into 'inline'. + Fixed bug which allowed URL and title to be separated by multiple blank lines in links and reference keys. They can be on separate lines but can't have blank lines between them. + Correctly handle bracketed text inside inline footnotes and links,using new function inlinesInBalanced. Resolves Issue #14. + Fixed bug in footnotes: links in footnotes were not being processed. Solution: three-stage parse. First, get all the reference keys and add information to state. Next, get all the notes and add information to state. (Reference keys may be needed at this stage.) Finally, parse everything else. + Replaced named constants like 'emphStart' with literals. + Removed an extra occurance of escapedChar in definition of inline. * RST reader: + Allow the URI in a RST hyperlink target to start on the line after the reference key. + Added 'try' in front of 'string', where needed, or used a different parser. This fixes a bug where ````` would not be correctly parsed as a verbatim `. + Fixed slow performance in parsing inline literals in RST reader. The problem was that ``#`` was seen by 'inline' as a potential link or image. Fix: inserted 'notFollowedBy (char '`')' in link parsers. Resolves Issue #8. + Use lookAhead instead of getInput/setInput in RST reader. Removed unneeded getState call, since lookAhead automatically saves and restores the parser state. + Allow hyperlink target URIs to be split over multiple lines, and to start on the line after the reference. Resolves Issue #7. + Fixed handling of autolinks. * LaTeX reader: + Replaced 'choice [(try (string ...), ...]' idiom with 'oneOfStrings', for clarity. + Added clauses for tilde and caret. Tilde is \ensuremath{\sim}, and caret is \^{}, not \^ as before. + Added parsing for \url. + Parse \texttt{} as code, provided there's nothing fancy inside. * HTML writer: + Modified HTML writer to use the Text.XHtml library. This results in cleaner, faster code, and it makes it easier to use Pandoc in other projects, like wikis, which use Text.XHtml. Two functions are now provided, writeHtml and writeHtmlString: the former outputs an Html structure, the latter a rendered string. The S5 writer is also changed, in parallel ways (writeS5, writeS5String). + The Html header is now written programmatically, so it has been removed from the 'headers' directory. The S5 header is still needed, but the doctype and some of the meta declarations have been removed, since they are written programatically. This change 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 Issue #9. + Fixed another bug in email obfuscation: If the text to be obfuscated contains an entity, this needs to be decoded before obfuscation. Thanks to thsutton for the patch. Resolves Issue #15. + Changed the way the backlink is displayed in HTML footnotes. Instead of appearing on a line by itself, it now generally appears on the last line of the note. (Exception: when the note does not end with a Plain or Para block.) This saves space and looks better. + Added automatic unique identifiers to headers: - The identifier is derived from the header via a scheme documented in README. - WriterState now includes a list of header identifiers and a table of contents in addition to notes. - The function uniqueIdentifiers creates a list of unique identifiers from a list of inline lists (e.g. headers). - This list is part of WriterState and gets consumed by blockToHtml each time a header is encountered. + Include CSS for .strikethrough class in header only if strikethrough text appears in the document. + If the 'strict' option is specified, elements that do not appear in standard markdown (like definition lists) are passed through as raw HTML. + Simplified treatment of autolinks, using pattern matching instead of conditionals. * Markdown writer: + 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>`. * LaTeX writer: + Rewrote to use the State monad. The preamble now includes only those packages that are actually required, given the document's content. Thus, for example, if strikeout is not used, ulem is not required. Modified LaTeXHeader accordingly. + Modified LaTeX writer to insert '\,' between consecutive quotes. + Removed unused function tableRowColumnWidths. + Simplified code for escaping special characters. + Leave extra blank line after \maketitle. + Include empty '\author{}' when no author specified to avoid LaTeX errors. + Include fancyvrb code in header only if needed -- that is, only if there is actually code in a footnote. + Use \url{} for autolinks. + Include [mathletters] option in ucs package, so that basic unicode Greek letters will work correctly. * RST writer: Force blank line before lists, so that sublists will be handled correctly. * Docbook writer: Fixed a bug: email links with text, like [foo](me@bar.baz), were being incorrectly treated as autolinks. * Removed Text.ParserCombinators.Pandoc and moved all its functions to Text.Pandoc.Shared. * Text.Pandoc.Shared: + Added defaultWriterOptions. + Added writerTableOfContents to WriterOptions. + Added writerIgnoreNotes option to WriterOptions. This is needed for processing header blocks for a table of contents, since notes on headers should not appear in the TOC. + Added prettyprinting for native Table format. + Removed some unneeded imports. + Moved escape and nullBlock parsers from Text.ParserCombinators.Pandoc, since the latter is for general-purpose parsers that don't depend on Text.Pandoc.Definition. + Moved isHeaderBlock from Text.Pandoc.Writers.HTML. + Moved Element, headerAtLeast, and hierarchicalize from Docbook writer, because HTML writer now uses these in constructing a table of contents. + Added clauses for new inline elements (Strikeout, Superscript, Subscript) to refsMatch. + Removed backslashEscape; added new functions escapeStringUsing and backslashEscapes. + Moved failIfStrict from markdown reader, since it is now used also by the HTML reader. + Added a 'try' to the definition of indentSpaces. + In definition of 'reference', added check to make sure it's not a note reference. + Added functions: camelCaseToHyphenated, toRomanNumeral, anyOrderedListMarker, orderedListmarker, orderedListMarkers, charsInBalanced', withHorizDisplacement, romanNumeral + Fixed a bug in the anyLine parser. Previously it would parse an empty string "", but it should fail on an empty string, or we get an error when it is used inside "many" combinators. + Removed followedBy' parser, replacing it with the lookAhead parser from Parsec. + Added some needed 'try's before multicharacter parsers, especially in 'option' contexts. + Removed the 'try' from the 'end' parser in 'enclosed', so that 'enclosed' behaves like 'option', 'manyTill', etc. + Added lineClump parser, which parses a raw line block up to and including any following blank lines. + Renamed parseFromStr to parseFromString. + Added a 'try' to the 'end' parser in 'enclosed'. This makes errors in the use of 'enclosed' less likely. Removed some now-unnecessary 'try's in calling code. + Removed unneeded 'try' in blanklines. + Removed endsWith function and rewrote calling functions to use isSuffixOf instead. + Added >>~ combinator. + Fixed bug in normalizeSpaces: Space:Str "":Space should compress to Space. * Refactored runtests.pl; added separate tests for tables. * Shell scripts: + Added -asxhtml flag to tidy in html2markdown. This will perhaps help the parser, which expects closing tags. + Modified markdown2pdf to run pdflatex a second time if --toc or --table-of-contents was specified; otherwise the table of contents won't appear. + Modified markdown2pdf to print a helpful message if the 'ulem' LaTeX package is required and not found. * Changes to build process: + Dropped support for compilation with GHC 6.4. GHC 6.6 or higher is now required. + Removed cabalize and Pandoc.cabal.in. The repository now contains pandoc.cabal itself. + Pandoc.cabal has been changed to pandoc.cabal, because HackageDB likes the cabal file to have the same name as the tarball. + Expanded and revised the package description in pandoc.cabal. Revised the package synopsis. + The tarball built by 'make tarball' now contains files built from templates (including man pages and shell scripts), so pandoc can be built directly using Cabal tools, without preprocessing. + Executable binaries are now stripped before installing. + Man pages are now generated from markdown sources, using pandoc's man page writer. + Use HTML version of README (instead of RTF) in Mac OS X installer. + Instead of testing for the existence of a pandoc symlink in build-exec, use ln -f. * Documentation: + Updated README and man pages with information on new features. + Updated INSTALL instructions with some useful clarifications and links. + Updated web content. * Added FreeBSD port. [ Recai Oktaş ] * debian/control: + Changed pandoc's Build-Depends to include libghc6-mtl-dev and libghc6-xhtml-dev. Removed libghc6-html-dev. + Suggest texlive-latex-recommended | tetex-extra instead of tetex-bin. This brings in fancyvrb and unicode support. -- Recai Oktaş <roktas@debian.org> Tue, 16 Jan 2007 00:37:21 +0200 pandoc (0.3) unstable; urgency=low [ John MacFarlane ] * Changes in pandoc options: + Allow options to follow or precede arguments. + Changed '--smartypants' to '--smart' and adjusted symbols accordingly. + Added '--strict' option. + Added '-o/--output' option. + Added '--dump-args' and '--ignore-args' options (for use in wrappers). + Modified '-v' and '-h' output to go to STDERR, not STDOUT, and return error conditions. This is helpful for writing wrappers. + Added copyright message to '-v' output, modeled after FSF messages. + Reformatted usage message so that it doesn't wrap illegibly. + Removed extra blanks after '-h' and '-D' output. * Added docbook writer. * Added implicit setting of default input and output format based on input and output filename extensions. These defaults are overridden if explicit input and output formats are specified using '-t', '-f', '-r', or '-w' options. Documented in pandoc(1) man page and README. * Allow ordered list items to begin with (single) letters, as well as numbers. The list item marker may now be terminated either by '.' or by ')'. This extension to standard markdown is documented in README. * Revised footnote syntax. (See README for full details.) The '[^1]' format now standard in markdown extensions is supported, as are inline footnotes with this syntax: '^[My note.]'. The earlier footnote syntax '^(1)' is no longer supported. * Improved HTML representation of footnotes. All footnotes are now auto-numbered and appear in an ordered list at the end of the HTML document. Since the default appearance is now acceptable, the old footnote styles have been removed from the HTML header. * Bug fixes: + Fixed a serious bug in the markdown, LaTeX, and RST readers. These readers ran 'runParser' on processed chunks of text to handle embedded block lists in lists and quotation blocks. But then any changes made to the parser state in these chunks was lost, as the state is local to the parser. So, for example, footnotes didn't work in quotes or list items. The fix: instead of calling runParser on some raw text, use setInput to make it the input, then parse it, then use setInput to restore the input to what it was before. This is shorter and more elegant, and it fixes the problem. + Fixed bug in notFollowedBy' combinator (adding 'try' before 'parser'). Adjusted code that uses this combinator accordingly. + Fixed bug in RTF writer that caused improper indentation on footnotes occurring in indented blocks like lists. + Fixed parsing of metadata in LaTeX reader. Now the title, author, and date are parsed correctly. Everything else in the preamble is skipped. + Modified escapedChar in LaTeX reader to allow a '\' at the end of a line to count as escaped whitespace. + Modified LaTeX reader to produce inline links rather than reference links. Otherwise, links in footnotes aren't handled properly. + Fixed handling of titles in links in Markdown reader, so that embedded quotation marks are now handled properly. + Fixed Markdown reader's handling of embedded brackets in links. + Fixed Markdown reader so that it only parses bracketed material as a reference link if there is actually a corresponding key. + Revised inline code parsing in Markdown reader to conform to markdown standard. Now any number of `s can begin inline code, which will end with the same number of `s. For example, to have two backticks as code, write ``` `` ```. Modified Markdown writer accordingly. + Fixed bug in text-wrapping routine in Markdown and RST writers. Now LineBreaks no longer cause wrapping problems. + Supported hexadecimal numerical entity references as well as decimal ones. + Fixed bug in Markdown reader's handling of underscores and other inline formatting markers inside reference labels: for example, in '[A_B]: /url/a_b', the material between underscores was being parsed as emphasized inlines. + Changed Markdown reader's handling of backslash escapes so that 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. Otherwise the newline will be treated as a space at the beginning of the next line. * Made handling of code blocks more consistent. Previously, some readers allowed trailing newlines, while others stripped them. Now, all readers strip trailing newlines in code blocks. Writers insert a newline at the end of code blocks as needed. * Modified readers to make spacing at the end of output more consistent. * Minor improvements to LaTeX reader: + '\thanks' now treated like a footnote. + Simplified parsing of LaTeX command arguments and options. commandArgs now returns a list of arguments OR options (in whatever order they appear). The brackets are included, and a new stripFirstAndLast function is provided to strip them off when needed. This fixes a problem in dealing with \newcommand and \newenvironment. * Revised RTF writer: + Default font is now Helvetica. + An '\f0' is added to each '\pard', so that font resizing works correctly. * 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 the parser state rather than a writer option. Several new kinds of inline elements have been added: Quoted, Ellipses, Apostrophe, EmDash, EnDash. * Changes in HTML writer: + Include title block in header even when title is null. + Made javascript obfuscation of emails even more obfuscatory, by combining it with entity obfuscation. * Changed default ASCIIMathML text color to black. * Test suite: + Added --strip-trailing-cr option to diff in runtests.pl, for compatibility with Windows. + Added regression tests with footnotes in quote blocks and lists. * Makefile changes: + osx-pkg target creates a Mac OS X package (directory). New osx directory contains files needed for construction of the package. + osx-dmg target creates a compressed disk image containing the package. + win-pkg target creates Windows binary package. + tarball target creates distribution source tarball. + website target generates pandoc's website automatically, including demos. New 'web' directory containts files needed for construction of the website (which will be created as the 'pandoc' subdirectory of 'web'). + Makefile checks to see if we're running Windows/Cygwin; if so, a '.exe' extension is added to each executable in EXECS. * Removed all wrappers except markdown2pdf and html2markdown. * Added new wrapper hsmarkdown, to be used as a drop-in replacement for Markdown.pl. hsmarkdown calls pandoc with the '--strict' option and disables other options. * Added code to html2markdown that tries to determine the character encoding of an HTML file, by parsing the "Content-type" meta tag. + If the encoding can't be determined, then if the content is local, the local encoding is used; if it comes from a URL, UTF-8 is used by default. + If input is from STDIN, don't try to determine character encoding. + Encoding can be specified explicitly using '-e' option. * Improved warning messages in wrappers: + Print warning if iconv not available + More user-friendly error messages in markdown2pdf, when pdflatex fails. * Code cleanup: + Renamed 'Text/Pandoc/HtmlEntities' module to 'Text/Pandoc/Entities'. Also changed function names so as not to be HTML-specific. + Refactored SGML string escaping functions from HTML and Docbook writers into Text/Pandoc/Shared. (escapeSGML, stringToSGML) + Removed 'BlockQuoteContext' from ParserContext, as it isn't used anywhere. + Removed splitBySpace and replaced it with a general, polymorphic splitBy function. + Refactored LaTeX reader for clarity (added isArg function). + Converted some CR's to LF's in src/ui/default/print.css. + Added license text to top of source files. + Added module data for haddock to source files. + Reformatted code for consistency. * Rewrote documentation and man pages. Split README into INSTALL and README. * Split LICENSE into COPYING and COPYRIGHT. * Removed TODO, since we now maintain ToDo on the wiki. * Made COPYRIGHT in top level a symlink to debian/copyright, to avoid duplication. [ Recai Oktaş ] * Revamped build process to conform to debian standards and created a proper debian package. Closes: #391666. * Modified build process to support GHC 6.6. + The package can still be compiled using GHC 6.4.2, though because of dependencies the "make deb" target works only with GHC 6.6+. + The script 'cabalize' is used to create an appropriate 'Pandoc.cabal' from 'Pandoc.cabal.in', depending on the GHC and Cabal versions. * Refactored template processing (fillTemplates.pl). * Modified wrapper scripts to make them more robust and portable. To avoid code duplication and ensure consistency, wrappers are generated via a templating system from templates in src/wrappers. + Wrappers now accept multiple filenames, when appropriate. + Spaces and tabs allowed in filenames. + getopts shell builtin is used for portable option parsing. + Improved html2markdown's web grabber code, making it more robust, configurable and verbose. Added '-e', '-g' options. -- Recai Oktaş <roktas@debian.org> Fri, 05 Jan 2007 09:41:19 +0200 pandoc (0.2) unstable; urgency=low * Fixed unicode/utf-8 translation -- John MacFarlane <jgm@berkeley.edu> Mon, 14 Aug 2006 00:00:00 -0400 pandoc (0.1) unstable; urgency=low * Initial creation of debian package -- John MacFarlane <jgm@berkeley.edu> Mon, 14 Aug 2006 00:00:00 -0400 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/CONTRIBUTING.md���������������������������������������������������������������������000644 �000765 �000024 �00000016176 12251233602 015360� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������Contributing to pandoc ====================== Found a bug? ------------ Bug reports are welcome! Please report all bugs on pandoc's github [issue tracker]. Before you submit a bug report, search the (open *and* closed) issues to make sure the issue hasn't come up before. Also, check the [User's Guide] and [FAQs] for anything relevant. Make sure you can reproduce the bug with the latest released version of pandoc (or, even better, the development version). Your report should give detailed instructions for how to reproduce the problem, including * the exact command line used * the exact input used * the output received * the output you expected instead A small test case (just a few lines) is ideal. If your input is large, try to whittle it down to the minimum necessary to illustrate the problem. Have an idea for a new feature? ------------------------------- First, search [pandoc-discuss] and the issue tracker (both open and closed issues) to make sure that the idea has not been discussed before. Explain the rationale for the feature you're requesting. Why would this feature be useful? Consider also any possible drawbacks, including backwards compatibility, new library dependencies, and performance issues. It is best to discuss a potential new feature on [pandoc-discuss] before opening an issue. Patches and pull requests ------------------------- Patches and pull requests are welcome. Before you put time into a nontrivial patch, it is a good idea to discuss it on [pandoc-discuss], especially if it is for a new feature (rather than fixing a bug). Please follow these guidelines: 1. Each patch (commit) should make a single logical change (fix a bug, add a feature, clean up some code, add documentation). Everything related to that change should be included (including tests and documentation), and nothing unrelated should be included. 2. The first line of the commit message should be a short description of the whole commit (ideally <= 50 characters). Then there should be a blank line, followed by a more detailed description of the change. 3. Follow the stylistic conventions you find in the existing pandoc code. Use spaces, not tabs, and wrap code to 80 columns. Always include type signatures for top-level functions. 4. Your code should compile without warnings (`-Wall` clean). 5. Run the tests to make sure your code does not introduce new bugs. (See below under [Tests](#tests).) All tests should pass. 6. It is a good idea to add test cases for the bug you are fixing. (See below under [Tests](#tests).) If you are adding a new writer or reader, you must include tests. 7. If you are adding a new feature, include updates to the README. 8. All code must be released under the general license governing pandoc (GPL v2). 9. It is better not to introduce new dependencies. Dependencies on external C libraries should especially be avoided. Tests ----- Tests can be run as follows: cabal configure --enable-tests cabal build cabal test The test program is `tests/test-pandoc.hs`. Benchmarks can be enabled by passing the `--enable-benchmarks` flag to `cabal configure`, and run using `cabal bench`. The code -------- Pandoc has a publicly accessible git repository on github: <http://github.com/jgm/pandoc>. To get a local copy of the source: git clone git://github.com/jgm/pandoc.git Note: after cloning the repository (and in the future after pulling from it), you should do git submodule update --init to pull in changes to the templates (`data/templates/`). You can automate this by creating a file `.git/hooks/post-merge` with the contents: #!/bin/sh git submodule update --init and making it executable: chmod +x .git/hooks/post-merge The source for the main pandoc program is `pandoc.hs`. The source for the pandoc library is in `src/`, the source for the tests is in `tests/`, and the source for the benchmarks is in `benchmark/`. The modules `Text.Pandoc.Definition`, `Text.Pandoc.Builder`, and `Text.Pandoc.Generics` are in a separate library `pandoc-types`. The code can be found in a <http://github.com/jgm/pandoc-types>. To build pandoc, you will need a working installation of the [Haskell platform]. The library is structured as follows: - `Text.Pandoc` is a top-level module that exports what is needed by most users of the library. Any patches that add new readers or writers will need to make changes here, too. - `Text.Pandoc.Definition` (in `pandoc-types`) defines the types used for representing a pandoc document. - `Text.Pandoc.Builder` (in `pandoc-types`) provides functions for building pandoc documents programatically. - `Text.Pandoc.Generics` (in `pandoc-types`) provides functions allowing you to promote functions that operate on parts of pandoc documents to functions that operate on whole pandoc documents, walking the tree automatically. - `Text.Pandoc.Readers.*` are the readers, and `Text.Pandoc.Writers.*` are the writers. - `Text.Pandoc.Biblio` is a utility module for formatting citations using citeproc-hs. - `Text.Pandoc.Data` is used to embed data files when the `embed_data_files` cabal flag is used. It is generated from `src/Text/Pandoc/Data.hsb` using the preprocessor [hsb2hs]. - `Text.Pandoc.Highlighting` contains the interface to the highlighting-kate library, which is used for code syntax highlighting. - `Text.Pandoc.ImageSize` is a utility module containing functions for calculating image sizes from the contents of image files. - `Text.Pandoc.MIME` contains functions for associating MIME types with extensions. - `Text.Pandoc.Options` defines reader and writer options. - `Text.Pandoc.PDF` contains functions for producing a PDF from a LaTeX source. - `Text.Pandoc.Parsing` contains parsing functions used in multiple readers. - `Text.Pandoc.Pretty` is a pretty-printing library specialized to the needs of pandoc. - `Text.Pandoc.SelfContained` contains functions for making an HTML file "self-contained," by importing remotely linked images, CSS, and javascript and turning them into `data:` URLs. - `Text.Pandoc.Shared` is a grab-bag of shared utility functions. - `Text.Pandoc.Writers.Shared` contains utilities used in writers only. - `Text.Pandoc.Slides` contains functions for splitting a markdown document into slides, using the conventions described in the README. - `Text.Pandoc.Templates` defines pandoc's templating system. - `Text.Pandoc.UTF8` contains functions for converting text to and from UTF8 bytestrings (strict and lazy). - `Text.Pandoc.Asciify` contains functions to derive ascii versions of identifiers that use accented characters. - `Text.Pandoc.UUID` contains functions for generating UUIDs. - `Text.Pandoc.XML` contains functions for formatting XML. [pandoc-discuss]: http://groups.google.com/group/pandoc-discuss [issue tracker]: https://github.com/jgm/pandoc/issues [User's Guide]: http://johnmacfarlane.net/pandoc/README.html [FAQs]: http://johnmacfarlane.net/pandoc/faqs.html [Haskell platform]: http://www.haskell.org/platform/ [hsb2hs]: http://hackage.haskell.org/package/hsb2hs ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/COPYING�����������������������������������������������������������������������������000644 �000765 �000024 �00000044233 12251233602 014155� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������GNU GENERAL PUBLIC LICENSE ========================== Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble -------- The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE -------------------------- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs --------------------------------------------- If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/COPYRIGHT���������������������������������������������������������������������������000644 �000765 �000024 �00000007421 12251233602 014413� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������Pandoc Copyright (C) 2006-2013 John MacFarlane <jgm at berkeley dot edu> This code is released under the [GPL], version 2 or later: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA The GNU General Public License is available in the file COPYING in the source distribution. On Debian systems, the complete text of the GPL can be found in `/usr/share/common-licenses/GPL`. [GPL]: http://www.gnu.org/copyleft/gpl.html Pandoc's complete source code is available from the [Pandoc home page]. [Pandoc home page]: http://johnmacfarlane.net/pandoc/ Pandoc includes some code from other authors. The copyright and license statements for these sources are included below. All are GPL-compatible licenses. ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Texinfo.hs Copyright (C) 2008-2010 John MacFarlane and Peter Wang Released under the GPL. ---------------------------------------------------------------------- src/Text/Pandoc/Writers/OpenDocument.hs Copyright (C) 2008-2010 Andrea Rossato and John MacFarlane Released under the GPL. ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Org.hs Copyright (C) 2010 Puneeth Chaganti Released under the GPL. ---------------------------------------------------------------------- src/Text/Pandoc/Readers/Textile.hs Copyright (C) 2010 Paul Rivier Released under the GPL. ---------------------------------------------------------------------- src/Text/Pandoc/Biblio.hs Copyright (C) 2008-2010 Andrea Rossato Released under the GPL. ---------------------------------------------------------------------- data/LaTeXMathML.js Adapted by Jeff Knisely and Douglas Woodall from ASCIIMathML.js v. 1.4.7 Copyright (C) 2005 Peter Jipsen Released under the GPL. ---------------------------------------------------------------------- data/MathMLInHTML.js Copyright (C) 2004 Peter Jipsen http://www.chapman.edu/~jipsen Released under the GNU General Public License version 2 or later. See the GNU General Public License (at http://www.gnu.org/copyleft/gpl.html) for more details. ---------------------------------------------------------------------- s5/default S5 slides.js and css files by Eric A. Meyer <http://meyerweb.com/eric/tools/s5 Released under an explicit Public Domain License ---------------------------------------------------------------------- slidy/default Slidy javascript and CSS by Dave Raggett http://www.w3.org/Talks/Tools/Slidy2 Released under W3C document and software licenses ---------------------------------------------------------------------- slideous/default Slideous javascript and CSS by Stefan Gössner http://goessner.net/ Released under Creative Commons GNU LGPL License ------------------------------------------------------------------------ windows/modpath.iss Copyright (c) 2007 Jared Breland http://legroom.net/software Released under the GPL. ------------------------------------------------------------------------ The dzslides template contains javascript and CSS from Paul Rouget's dzslides template. http://github.com/apulrouget/dzslides Released under the Do What the Fuck You Want To Public License. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/data/�������������������������������������������������������������������������������000755 �000765 �000024 �00000000000 12251233602 014025� 5����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/INSTALL�����������������������������������������������������������������������������000644 �000765 �000024 �00000015221 12251233602 014146� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Installing pandoc These instructions explain how to install pandoc from source. Binary packages or ports of pandoc are available for freebsd and several linux distributions, so check your package manager. There are also binary installers for Windows and Mac OS X. If you are installing the development version from github, see also: https://github.com/jgm/pandoc/wiki/Installing-the-development-version-of-pandoc Quick install ------------- 1. Install the [Haskell platform]. This will give you [GHC] and the [cabal-install] build tool, as well as `alex` and `happy`. If you do not use the Haskell platform, you'll need to install `alex` and `happy` separately: cabal install alex happy 2. Update your package database: cabal update 3. Use `cabal` to install pandoc and its dependencies: cabal install pandoc This procedure will install the released version of pandoc, which will be downloaded automatically from HackageDB. If you want to install a modified or development version of pandoc instead, switch to the source directory and do as above, but without the 'pandoc': cabal install Note: If you obtained the source from the git repository (rather than a release tarball), you'll need to do git submodule update --init to fetch the contents of `data/templates` before `cabal install`. 4. Make sure the `$CABALDIR/bin` directory is in your path. You should now be able to run `pandoc`: pandoc --help [Not sure where `$CABALDIR` is?](http://www.haskell.org/haskellwiki/Cabal-Install#The_cabal-install_configuration_file) 5. Make sure the `$CABALDIR/share/man/man1` directory is in your `MANPATH`. You should now be able to access the `pandoc` man page: man pandoc 6. If you want to process citations with pandoc, you will also need to install a separate package, `pandoc-citeproc`. This can be installed using cabal: 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 Custom install -------------- This is a step-by-step procedure that offers maximal control over the build and installation. Most users should use the quick install, but this information may be of use to packagers. For more details, see the [Cabal User's Guide]. These instructions assume that the pandoc source directory is your working directory. 1. Install dependencies: in addition to the [Haskell platform], you will need a number of additional libraries. You can install them all with cabal update cabal install --only-dependencies 2. Configure: cabal configure --prefix=DIR --bindir=DIR --libdir=DIR \ --datadir=DIR --libsubdir=DIR --datasubdir=DIR --docdir=DIR \ --htmldir=DIR --program-prefix=PREFIX --program-suffix=SUFFIX \ --mandir=DIR --flags=FLAGSPEC All of the options have sensible defaults that can be overridden as needed. `FLAGSPEC` is a list of Cabal configuration flags, optionally preceded by a `-` (to force the flag to `false`), and separated by spaces. Pandoc's flags include: - `embed_data_files`: embed all data files into the binary (default no). This is helpful if you want to create a relocatable binary. Note: if this option is selected, you need to install the `hsb2hs` preprocessor: cabal install hsb2hs - `http-conduit`: use the `http-conduit` library to fetch external resources (default yes -- without this, pandoc cannot make SSL connections) 3. Build: cabal build 4. Build API documentation: cabal haddock --html-location=URL --hyperlink-source 5. Copy the files: cabal copy --destdir=PATH The default destdir is `/`. 6. Register pandoc as a GHC package: cabal register Package managers may want to use the `--gen-script` option to generate a script that can be run to register the package at install time. Creating a relocatable binary ----------------------------- It is possible to compile pandoc such that the data files pandoc uses are embedded in the binary. The resulting binary can be run from any directory and is completely self-contained. cabal install hsb2hs # a required build tool cabal install --flags="embed_data_files" citeproc-hs cabal configure --flags="embed_data_files" cabal build You can find the pandoc executable in `dist/build/pandoc`. Copy this wherever you please. [zip-archive]: http://hackage.haskell.org/package/zip-archive [highlighting-kate]: http://hackage.haskell.org/package/highlighting-kate [blaze-html]: http://hackage.haskell.org/package/blaze-html [Cabal User's Guide]: http://www.haskell.org/cabal/release/latest/doc/users-guide/builders.html#setup-configure-paths Running tests ------------- Pandoc comes with an automated test suite integrated to cabal. To build the tests: cabal configure --enable-tests && cabal build To run the tests: cabal test To run particular tests (pattern-matching on their names), use the `-t` option: cabal test --test-options='-t markdown' If you add a new feature to pandoc, please add tests as well, following the pattern of the existing tests. The test suite code is in `tests/test-pandoc.hs`. If you are adding a new reader or writer, it is probably easiest to add some data files to the `tests` directory, and modify `tests/Tests/Old.hs`. Otherwise, it is better to modify the module under the `tests/Tests` hierarchy corresponding to the pandoc module you are changing. Running benchmarks ------------------ To build the benchmarks: cabal configure --enable-benchmarks && cabal build To run the benchmarks: cabal bench To use a smaller sample size so the benchmarks run faster: cabal bench --benchmark-options='-s 20' To run just the markdown benchmarks: cabal bench --benchmark-options='markdown' �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/man/��������������������������������������������������������������������������������000755 �000765 �000024 �00000000000 12251233602 013667� 5����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/pandoc.cabal������������������������������������������������������������������������000644 �000765 �000024 �00000040637 12251233602 015356� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������Name: pandoc Version: 1.12.2.1 Cabal-Version: >= 1.10 Build-Type: Custom License: GPL License-File: COPYING Copyright: (c) 2006-2013 John MacFarlane Author: John MacFarlane <jgm@berkeley.edu> Maintainer: John MacFarlane <jgm@berkeley.edu> Bug-Reports: https://github.com/jgm/pandoc/issues Stability: alpha Homepage: http://johnmacfarlane.net/pandoc Category: Text Tested-With: GHC == 7.4.2, GHC == 7.6.1 Synopsis: Conversion between markup formats Description: Pandoc is a Haskell library for converting from one markup format to another, and a command-line tool that uses this library. It can read markdown and (subsets of) HTML, reStructuredText, LaTeX, DocBook, MediaWiki markup, Haddock markup, OPML, and Textile, and it can write markdown, reStructuredText, HTML, LaTeX, ConTeXt, Docbook, OPML, OpenDocument, ODT, Word docx, RTF, MediaWiki, Textile, groff man pages, plain text, Emacs Org-Mode, AsciiDoc, EPUB (v2 and v3), FictionBook2, and several kinds of HTML/javascript slide shows (S5, Slidy, Slideous, DZSlides, reveal.js). . Pandoc extends standard markdown syntax with footnotes, embedded LaTeX, definition lists, tables, and other features. A compatibility mode is provided for those who need a drop-in replacement for Markdown.pl. . In contrast to existing tools for converting markdown to HTML, which use regex substitutions, pandoc has a modular design: it consists of a set of readers, which parse text in a given format and produce a native representation of the document, and a set of writers, which convert this native representation into a target format. Thus, adding an input or output format requires only adding a reader or writer. Data-Files: -- templates data/templates/default.html, data/templates/default.html5, data/templates/default.docbook, data/templates/default.beamer, data/templates/default.opendocument, data/templates/default.opml, data/templates/default.latex, data/templates/default.context, data/templates/default.texinfo, data/templates/default.man, data/templates/default.markdown, data/templates/default.rst, data/templates/default.plain, data/templates/default.mediawiki, data/templates/default.rtf, data/templates/default.s5, data/templates/default.slidy, data/templates/default.slideous, data/templates/default.revealjs, data/templates/default.dzslides, data/templates/default.asciidoc, data/templates/default.textile, data/templates/default.org, data/templates/default.epub, data/templates/default.epub3, -- data for ODT writer data/reference.odt, -- data for docx writer data/reference.docx, -- stylesheet for EPUB writer data/epub.css, -- data for LaTeXMathML writer data/LaTeXMathML.js, data/MathMLinHTML.js, -- data for dzslides writer data/dzslides/template.html, -- sample lua custom writer data/sample.lua -- documentation README, INSTALL, COPYRIGHT, BUGS, CONTRIBUTING.md, changelog Extra-Source-Files: -- code to create pandoc.1 man page man/man1/pandoc.1.template, man/man5/pandoc_markdown.5.template, -- generated man pages (produced post-build) man/man1/pandoc.1, man/man5/pandoc_markdown.5, -- tests tests/bodybg.gif, tests/docbook-reader.docbook tests/docbook-reader.native tests/html-reader.html, tests/html-reader.native, tests/opml-reader.opml, tests/opml-reader.native, tests/haddock-reader.haddock, tests/haddock-reader.native, tests/insert, tests/lalune.jpg, tests/movie.jpg, tests/latex-reader.latex, tests/latex-reader.native, tests/textile-reader.textile, tests/textile-reader.native, tests/markdown-reader-more.txt, tests/markdown-reader-more.native, tests/markdown-citations.txt, tests/markdown-citations.native, tests/textile-reader.textile, tests/mediawiki-reader.wiki, tests/mediawiki-reader.native, tests/rst-reader.native, tests/rst-reader.rst, tests/s5.basic.html, tests/s5.fancy.html, tests/s5.fragment.html, tests/s5.inserts.html, tests/s5.native, tests/tables.context, tests/tables.docbook, tests/tables.html, tests/tables.latex, tests/tables.man, tests/tables.plain, tests/tables.markdown, tests/tables.mediawiki, tests/tables.textile, tests/tables.native, tests/tables.opendocument, tests/tables.org, tests/tables.asciidoc, tests/tables.texinfo, tests/tables.rst, tests/tables.rtf, tests/tables.txt, tests/tables-rstsubset.native, tests/tables.fb2, tests/testsuite.native, tests/testsuite.txt, tests/writer.latex, tests/writer.context, tests/writer.docbook, tests/writer.html, tests/writer.man, tests/writer.markdown, tests/writer.plain, tests/writer.mediawiki, tests/writer.textile, tests/writer.native, tests/writer.opendocument, tests/writer.org, tests/writer.asciidoc, tests/writer.rst, tests/writer.rtf, tests/writer.texinfo, tests/writer.fb2, tests/writer.opml, tests/lhs-test.native, tests/lhs-test-markdown.native, tests/lhs-test.markdown, tests/lhs-test.markdown+lhs, tests/lhs-test.rst, tests/lhs-test.rst+lhs, tests/lhs-test.latex, tests/lhs-test.latex+lhs, tests/lhs-test.html, tests/lhs-test.html+lhs, tests/lhs-test.fragment.html+lhs, tests/pipe-tables.txt, tests/pipe-tables.native, tests/fb2.basic.markdown, tests/fb2.basic.fb2, tests/fb2.titles.markdown, tests/fb2.titles.fb2, tests/fb2.images.markdown, tests/fb2.images.fb2, tests/fb2.images-embedded.html, tests/fb2.images-embedded.fb2, tests/fb2.math.markdown, tests/fb2.math.fb2, tests/fb2.test-small.png, tests/fb2.test.jpg Extra-Tmp-Files: man/man1/pandoc.1, man/man5/pandoc_markdown.5 Source-repository head type: git location: git://github.com/jgm/pandoc.git Flag embed_data_files Description: Embed data files in binary for relocatable executable. Default: False Flag http-conduit Description: Enable downloading of resources over https. Default: True Library Build-Depends: base >= 4.2 && <5, syb >= 0.1 && < 0.5, containers >= 0.1 && < 0.6, unordered-containers >= 0.2 && < 0.3, array >= 0.3 && < 0.5, parsec >= 3.1 && < 3.2, mtl >= 1.1 && < 2.2, network >= 2 && < 2.5, filepath >= 1.1 && < 1.4, process >= 1 && < 1.2, directory >= 1 && < 1.3, bytestring >= 0.9 && < 0.11, text >= 0.11 && < 0.12, zip-archive >= 0.1.3.3 && < 0.2, old-locale >= 1 && < 1.1, time >= 1.2 && < 1.5, HTTP >= 4000.0.5 && < 4000.3, texmath >= 0.6.5.2 && < 0.7, xml >= 1.3.12 && < 1.4, random >= 1 && < 1.1, extensible-exceptions >= 0.1 && < 0.2, pandoc-types >= 1.12.3 && < 1.13, aeson >= 0.6 && < 0.7, tagsoup >= 0.12.5 && < 0.14, base64-bytestring >= 0.1 && < 1.1, zlib >= 0.5 && < 0.6, highlighting-kate >= 0.5.5 && < 0.6, data-default >= 0.4 && < 0.6, temporary >= 1.1 && < 1.2, blaze-html >= 0.5 && < 0.7, blaze-markup >= 0.5.1 && < 0.6, attoparsec >= 0.10 && < 0.11, yaml >= 0.8.3 && < 0.9, vector >= 0.10 && < 0.11, hslua >= 0.3 && < 0.4 Build-Tools: alex, happy if flag(http-conduit) Build-Depends: http-conduit >= 1.9 && < 1.10, http-types >= 0.8 && < 0.9 cpp-options: -DHTTP_CONDUIT if flag(embed_data_files) cpp-options: -DEMBED_DATA_FILES -- 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 Default-Language: Haskell98 Other-Extensions: PatternGuards, OverloadedStrings, ScopedTypeVariables, GeneralizedNewtypeDeriving, RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances, FlexibleInstances Hs-Source-Dirs: src Exposed-Modules: Text.Pandoc, Text.Pandoc.Options, Text.Pandoc.Pretty, Text.Pandoc.Shared, Text.Pandoc.Readers.HTML, Text.Pandoc.Readers.LaTeX, Text.Pandoc.Readers.Markdown, Text.Pandoc.Readers.MediaWiki, Text.Pandoc.Readers.RST, Text.Pandoc.Readers.DocBook, Text.Pandoc.Readers.OPML, Text.Pandoc.Readers.TeXMath, Text.Pandoc.Readers.Textile, Text.Pandoc.Readers.Native, Text.Pandoc.Readers.Haddock, Text.Pandoc.Writers.Native, Text.Pandoc.Writers.Docbook, Text.Pandoc.Writers.OPML, Text.Pandoc.Writers.HTML, Text.Pandoc.Writers.LaTeX, Text.Pandoc.Writers.ConTeXt, Text.Pandoc.Writers.OpenDocument, Text.Pandoc.Writers.Texinfo, Text.Pandoc.Writers.Man, Text.Pandoc.Writers.Markdown, Text.Pandoc.Writers.RST, Text.Pandoc.Writers.Org, Text.Pandoc.Writers.AsciiDoc, Text.Pandoc.Writers.Custom, Text.Pandoc.Writers.Textile, Text.Pandoc.Writers.MediaWiki, Text.Pandoc.Writers.RTF, Text.Pandoc.Writers.ODT, Text.Pandoc.Writers.Docx, Text.Pandoc.Writers.EPUB, Text.Pandoc.Writers.FB2, Text.Pandoc.PDF, Text.Pandoc.UTF8, Text.Pandoc.Templates, Text.Pandoc.XML, Text.Pandoc.SelfContained, Text.Pandoc.Process Other-Modules: Text.Pandoc.Readers.Haddock.Lex, Text.Pandoc.Readers.Haddock.Parse, Text.Pandoc.Writers.Shared, Text.Pandoc.Asciify, Text.Pandoc.MIME, Text.Pandoc.Parsing, Text.Pandoc.UUID, Text.Pandoc.ImageSize, Text.Pandoc.Slides, Text.Pandoc.Highlighting, Text.Pandoc.Compat.Monoid, Text.Pandoc.Compat.TagSoupEntity, Paths_pandoc Buildable: True Executable pandoc Build-Depends: pandoc, 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, bytestring >= 0.9 && < 0.11, extensible-exceptions >= 0.1 && < 0.2, highlighting-kate >= 0.5.5 && < 0.6, aeson >= 0.6 && < 0.7, text >= 0.11 && < 0.12, 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 if os(windows) Cpp-options: -D_WINDOWS Default-Language: Haskell98 Other-Extensions: PatternGuards, OverloadedStrings, ScopedTypeVariables, GeneralizedNewtypeDeriving, RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances, FlexibleInstances Hs-Source-Dirs: . Main-Is: pandoc.hs Buildable: True -- NOTE: A trick in Setup.hs makes sure this won't be installed: Executable make-pandoc-man-pages Main-Is: make-pandoc-man-pages.hs Hs-Source-Dirs: man Build-Depends: pandoc, base >= 4.2 && < 5, directory >= 1 && < 1.3, filepath >= 1.1 && < 1.4, old-time >= 1.0 && < 1.2, time >= 1.2 && < 1.5 Default-Language: Haskell98 Test-Suite test-pandoc Type: exitcode-stdio-1.0 Main-Is: test-pandoc.hs Hs-Source-Dirs: tests Build-Depends: base >= 4.2 && < 5, syb >= 0.1 && < 0.5, pandoc, pandoc-types >= 1.12.3 && < 1.13, bytestring >= 0.9 && < 0.11, text >= 0.11 && < 0.12, directory >= 1 && < 1.3, filepath >= 1.1 && < 1.4, process >= 1 && < 1.2, highlighting-kate >= 0.5.5 && < 0.6, Diff >= 0.2 && < 0.4, test-framework >= 0.3 && < 0.9, test-framework-hunit >= 0.2 && < 0.4, test-framework-quickcheck2 >= 0.2.9 && < 0.4, QuickCheck >= 2.4 && < 2.7, HUnit >= 1.2 && < 1.3, containers >= 0.1 && < 0.6, ansi-terminal >= 0.5 && < 0.7 Other-Modules: Tests.Old Tests.Helpers Tests.Arbitrary Tests.Shared Tests.Walk Tests.Readers.LaTeX Tests.Readers.Markdown Tests.Readers.RST Tests.Writers.Native Tests.Writers.ConTeXt Tests.Writers.HTML Tests.Writers.Markdown Tests.Writers.LaTeX Ghc-Options: -rtsopts -Wall -fno-warn-unused-do-bind Default-Language: Haskell98 benchmark benchmark-pandoc Type: exitcode-stdio-1.0 Main-Is: benchmark-pandoc.hs Hs-Source-Dirs: benchmark Build-Depends: pandoc, base >= 4.2 && < 5, syb >= 0.1 && < 0.5, criterion >= 0.5 && < 0.9 Ghc-Options: -rtsopts -Wall -fno-warn-unused-do-bind Default-Language: Haskell98 �������������������������������������������������������������������������������������������������pandoc-1.12.2.1/pandoc.hs���������������������������������������������������������������������������000644 �000765 �000024 �00000144144 12251233602 014724� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE CPP #-} {- Copyright (C) 2006-2013 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Main Copyright : Copyright (C) 2006-2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu> Stability : alpha Portability : portable Parses command-line options and calls the appropriate readers and writers. -} module Main where import Text.Pandoc 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, openURL ) import Text.Pandoc.XML ( toEntities ) import Text.Pandoc.SelfContained ( makeSelfContained ) import Text.Pandoc.Process (pipeProcess) import Text.Highlighting.Kate ( languages, Style, tango, pygments, espresso, zenburn, kate, haddock, monochrome ) import System.Environment ( getArgs, getProgName ) import System.Exit ( exitWith, ExitCode (..) ) import System.FilePath import System.Console.GetOpt import Data.Char ( toLower ) import Data.List ( intercalate, isPrefixOf, sort ) import System.Directory ( getAppUserDataDirectory, findExecutable ) import System.IO ( stdout, stderr ) import System.IO.Error ( isDoesNotExistError ) import qualified Control.Exception as E import Control.Exception.Extensible ( throwIO ) import qualified Text.Pandoc.UTF8 as UTF8 import Control.Monad (when, unless, liftM) import Data.Foldable (foldrM) 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" ++ "Web: http://johnmacfarlane.net/pandoc\n" ++ "This is free software; see the source for copying conditions. There is no\n" ++ "warranty, not even for merchantability or fitness for a particular purpose." compileInfo :: String compileInfo = "\nCompiled with texmath " ++ VERSION_texmath ++ ", highlighting-kate " ++ VERSION_highlighting_kate ++ ".\nSyntax highlighting is supported for the following languages:\n " ++ wrapWords 4 78 [map toLower l | l <- languages, l /= "Alert" && l /= "Alert_indent"] -- | Converts a list of strings into a single string with the items printed as -- comma separated words in lines with a maximum line length. wrapWords :: Int -> Int -> [String] -> String wrapWords indent c = wrap' (c - indent) (c - indent) where wrap' _ _ [] = "" wrap' cols remaining (x:xs) = if remaining == cols then x ++ wrap' cols (remaining - length x) xs else if (length x + 1) > remaining then ",\n" ++ replicate indent ' ' ++ x ++ wrap' cols (cols - length x) xs else ", " ++ x ++ wrap' cols (remaining - (length x + 2)) xs isTextFormat :: String -> Bool isTextFormat s = takeWhile (`notElem` "+-") s `notElem` ["odt","docx","epub","epub3"] externalFilter :: FilePath -> [String] -> Pandoc -> IO Pandoc externalFilter f args' d = do (exitcode, outbs, errbs) <- E.handle filterException $ pipeProcess Nothing f args' $ encode d when (not $ B.null errbs) $ B.hPutStr stderr errbs case exitcode of 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" ++ 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 { optTabStop :: Int -- ^ Number of spaces per tab , optPreserveTabs :: Bool -- ^ Preserve tabs instead of converting to spaces , optStandalone :: Bool -- ^ Include header, footer , optReader :: String -- ^ Reader format , optWriter :: String -- ^ Writer format , optParseRaw :: Bool -- ^ Parse unconvertable HTML and TeX , optTableOfContents :: Bool -- ^ Include table of contents , optTransforms :: [Pandoc -> Pandoc] -- ^ Doc transforms to apply , optTemplate :: Maybe FilePath -- ^ Custom template , optVariables :: [(String,String)] -- ^ Template variables 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 , optSectionDivs :: Bool -- ^ Put sections in div tags in HTML , optIncremental :: Bool -- ^ Use incremental lists in Slidy/Slideous/S5 , optSelfContained :: Bool -- ^ Make HTML accessible offline , optSmart :: Bool -- ^ Use smart typography , optOldDashes :: Bool -- ^ Parse dashes like pandoc <=1.8.2.1 , optHtml5 :: Bool -- ^ Produce HTML5 in HTML , optHtmlQTags :: Bool -- ^ Use <q> tags in HTML , optHighlight :: Bool -- ^ Highlight source code , optHighlightStyle :: Style -- ^ Style to use for highlighted code , optChapters :: Bool -- ^ Use chapter for top-level sects , optHTMLMathMethod :: HTMLMathMethod -- ^ Method to print HTML math , optReferenceODT :: Maybe FilePath -- ^ Path of reference.odt , optReferenceDocx :: Maybe FilePath -- ^ Path of reference.docx , optEpubStylesheet :: Maybe String -- ^ EPUB stylesheet , optEpubMetadata :: String -- ^ EPUB metadata , optEpubFonts :: [FilePath] -- ^ EPUB fonts to embed , optEpubChapterLevel :: Int -- ^ Header level at which to split chapters , optTOCDepth :: Int -- ^ Number of levels to include in TOC , optDumpArgs :: Bool -- ^ Output command-line arguments , optIgnoreArgs :: Bool -- ^ Ignore command-line arguments , optReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst , optWrapText :: Bool -- ^ Wrap text , optColumns :: Int -- ^ Line length in characters , optFilters :: [FilePath] -- ^ Filters to apply , optEmailObfuscation :: ObfuscationMethod , optIdentifierPrefix :: String , optIndentedCodeClasses :: [String] -- ^ Default classes for indented code blocks , optDataDir :: Maybe FilePath , optCiteMethod :: CiteMethod -- ^ Method to output cites , optListings :: Bool -- ^ Use listings package for code blocks , optLaTeXEngine :: String -- ^ Program to use for latex -> pdf , optSlideLevel :: Maybe Int -- ^ Header level that creates slides , optSetextHeaders :: Bool -- ^ Use atx headers for markdown level 1-2 , optAscii :: Bool -- ^ Use ascii characters only in html , optTeXLigatures :: Bool -- ^ Use TeX ligatures for quotes/dashes , optDefaultImageExtension :: String -- ^ Default image extension } -- | Defaults for command-line options. defaultOpts :: Opt defaultOpts = Opt { optTabStop = 4 , optPreserveTabs = False , optStandalone = False , optReader = "" -- null for default reader , optWriter = "" -- null for default writer , optParseRaw = False , optTableOfContents = False , optTransforms = [] , optTemplate = Nothing , optVariables = [] , optMetadata = M.empty , optOutputFile = "-" -- "-" means stdout , optNumberSections = False , optNumberOffset = [0,0,0,0,0,0] , optSectionDivs = False , optIncremental = False , optSelfContained = False , optSmart = False , optOldDashes = False , optHtml5 = False , optHtmlQTags = False , optHighlight = True , optHighlightStyle = pygments , optChapters = False , optHTMLMathMethod = PlainMath , optReferenceODT = Nothing , optReferenceDocx = Nothing , optEpubStylesheet = Nothing , optEpubMetadata = "" , optEpubFonts = [] , optEpubChapterLevel = 1 , optTOCDepth = 3 , optDumpArgs = False , optIgnoreArgs = False , optReferenceLinks = False , optWrapText = True , optColumns = 72 , optFilters = [] , optEmailObfuscation = JavascriptObfuscation , optIdentifierPrefix = "" , optIndentedCodeClasses = [] , optDataDir = Nothing , optCiteMethod = Citeproc , optListings = False , optLaTeXEngine = "pdflatex" , optSlideLevel = Nothing , optSetextHeaders = True , optAscii = False , optTeXLigatures = True , optDefaultImageExtension = "" } -- | A list of functions, each transforming the options data structure -- in response to a command-line option. options :: [OptDescr (Opt -> IO Opt)] options = [ Option "fr" ["from","read"] (ReqArg (\arg opt -> return opt { optReader = map toLower arg }) "FORMAT") "" , Option "tw" ["to","write"] (ReqArg (\arg opt -> return opt { optWriter = map toLower arg }) "FORMAT") "" , Option "o" ["output"] (ReqArg (\arg opt -> return opt { optOutputFile = arg }) "FILENAME") "" -- "Name of output file" , Option "" ["data-dir"] (ReqArg (\arg opt -> return opt { optDataDir = Just arg }) "DIRECTORY") -- "Directory containing pandoc data files." "" , Option "" ["strict"] (NoArg (\opt -> do err 59 $ "The --strict option has been removed.\n" ++ "Use `markdown_strict' input or output format instead." return opt )) "" -- "Disable markdown syntax extensions" , Option "R" ["parse-raw"] (NoArg (\opt -> return opt { optParseRaw = True })) "" -- "Parse untranslatable HTML codes and LaTeX environments as raw" , Option "S" ["smart"] (NoArg (\opt -> return opt { optSmart = True })) "" -- "Use smart quotes, dashes, and ellipses" , Option "" ["old-dashes"] (NoArg (\opt -> return opt { optSmart = True , optOldDashes = True })) "" -- "Use smart quotes, dashes, and ellipses" , Option "" ["base-header-level"] (ReqArg (\arg opt -> case safeRead arg of Just t | t > 0 -> do let oldTransforms = optTransforms opt let shift = t - 1 return opt{ optTransforms = headerShift shift : oldTransforms } _ -> err 19 "base-header-level must be a number > 0") "NUMBER") "" -- "Headers base level" , Option "" ["indented-code-classes"] (ReqArg (\arg opt -> return opt { optIndentedCodeClasses = words $ map (\c -> if c == ',' then ' ' else c) arg }) "STRING") "" -- "Classes (whitespace- or comma-separated) to use for indented code-blocks" , Option "F" ["filter"] (ReqArg (\arg opt -> return opt { optFilters = arg : optFilters opt }) "PROGRAM") "" -- "External JSON filter" , Option "" ["normalize"] (NoArg (\opt -> return opt { optTransforms = normalize : optTransforms opt } )) "" -- "Normalize the Pandoc AST" , Option "p" ["preserve-tabs"] (NoArg (\opt -> return opt { optPreserveTabs = True })) "" -- "Preserve tabs instead of converting to spaces" , Option "" ["tab-stop"] (ReqArg (\arg opt -> case safeRead arg of Just t | t > 0 -> return opt { optTabStop = t } _ -> err 31 "tab-stop must be a number greater than 0") "NUMBER") "" -- "Tab stop (default 4)" , Option "s" ["standalone"] (NoArg (\opt -> return opt { optStandalone = True })) "" -- "Include needed header and footer on output" , Option "" ["template"] (ReqArg (\arg opt -> do return opt{ optTemplate = Just arg, optStandalone = True }) "FILENAME") "" -- "Use custom template" , Option "M" ["metadata"] (ReqArg (\arg opt -> do let (key,val) = case break (`elem` ":=") arg of (k,_:v) -> (k, readMetaValue v) (k,_) -> (k, MetaBool True) return opt{ optMetadata = addMetadata key val $ optMetadata opt }) "KEY[:VALUE]") "" , Option "V" ["variable"] (ReqArg (\arg opt -> do let (key,val) = case break (`elem` ":=") arg of (k,_:v) -> (k,v) (k,_) -> (k,"true") return opt{ optVariables = (key,val) : optVariables opt }) "KEY[:VALUE]") "" , Option "D" ["print-default-template"] (ReqArg (\arg _ -> do templ <- getDefaultTemplate Nothing arg case templ of Right t -> UTF8.hPutStr stdout t Left e -> error $ show e exitWith ExitSuccess) "FORMAT") "" -- "Print default template for FORMAT" , Option "" ["print-default-data-file"] (ReqArg (\arg _ -> do readDataFile Nothing arg >>= BS.hPutStr stdout exitWith ExitSuccess) "FILE") "" -- "Print default data file" , Option "" ["no-wrap"] (NoArg (\opt -> return opt { optWrapText = False })) "" -- "Do not wrap text in output" , Option "" ["columns"] (ReqArg (\arg opt -> case safeRead arg of Just t | t > 0 -> return opt { optColumns = t } _ -> err 33 $ "columns must be a number greater than 0") "NUMBER") "" -- "Length of line in characters" , Option "" ["toc", "table-of-contents"] (NoArg (\opt -> return opt { optTableOfContents = True })) "" -- "Include table of contents" , Option "" ["toc-depth"] (ReqArg (\arg opt -> do case safeRead arg of Just t | t >= 1 && t <= 6 -> return opt { optTOCDepth = t } _ -> err 57 $ "TOC level must be a number between 1 and 6") "NUMBER") "" -- "Number of levels to include in TOC" , Option "" ["no-highlight"] (NoArg (\opt -> return opt { optHighlight = False })) "" -- "Don't highlight source code" , Option "" ["highlight-style"] (ReqArg (\arg opt -> do newStyle <- case map toLower arg of "pygments" -> return pygments "tango" -> return tango "espresso" -> return espresso "zenburn" -> return zenburn "kate" -> return kate "monochrome" -> return monochrome "haddock" -> return haddock _ -> err 39 $ "Unknown style :" ++ arg return opt{ optHighlightStyle = newStyle }) "STYLE") "" -- "Style for highlighted code" , Option "H" ["include-in-header"] (ReqArg (\arg opt -> do text <- UTF8.readFile arg -- add new ones to end, so they're included in order specified let newvars = optVariables opt ++ [("header-includes",text)] return opt { optVariables = newvars, optStandalone = True }) "FILENAME") "" -- "File to include at end of header (implies -s)" , Option "B" ["include-before-body"] (ReqArg (\arg opt -> do text <- UTF8.readFile arg -- add new ones to end, so they're included in order specified let newvars = optVariables opt ++ [("include-before",text)] return opt { optVariables = newvars, optStandalone = True }) "FILENAME") "" -- "File to include before document body" , Option "A" ["include-after-body"] (ReqArg (\arg opt -> do text <- UTF8.readFile arg -- add new ones to end, so they're included in order specified let newvars = optVariables opt ++ [("include-after",text)] return opt { optVariables = newvars, optStandalone = True }) "FILENAME") "" -- "File to include after document body" , Option "" ["self-contained"] (NoArg (\opt -> return opt { optSelfContained = True, optStandalone = True })) "" -- "Make slide shows include all the needed js and css" , Option "" ["offline"] (NoArg (\opt -> do warn $ "--offline is deprecated. Use --self-contained instead." return opt { optSelfContained = True, optStandalone = True })) "" -- "Make slide shows include all the needed js and css" -- deprecated synonym for --self-contained , Option "5" ["html5"] (NoArg (\opt -> do warn $ "--html5 is deprecated. " ++ "Use the html5 output format instead." return opt { optHtml5 = True })) "" -- "Produce HTML5 in HTML output" , Option "" ["html-q-tags"] (NoArg (\opt -> do return opt { optHtmlQTags = True })) "" -- "Use <q> tags for quotes in HTML" , Option "" ["ascii"] (NoArg (\opt -> return opt { optAscii = True })) "" -- "Use ascii characters only in HTML output" , Option "" ["reference-links"] (NoArg (\opt -> return opt { optReferenceLinks = True } )) "" -- "Use reference links in parsing HTML" , Option "" ["atx-headers"] (NoArg (\opt -> return opt { optSetextHeaders = False } )) "" -- "Use atx-style headers for markdown" , Option "" ["chapters"] (NoArg (\opt -> return opt { optChapters = True })) "" -- "Use chapter for top-level sections in LaTeX, DocBook" , Option "N" ["number-sections"] (NoArg (\opt -> return opt { optNumberSections = True })) "" -- "Number sections in LaTeX" , Option "" ["number-offset"] (ReqArg (\arg opt -> case safeRead ('[':arg ++ "]") of Just ns -> return opt { optNumberOffset = ns, optNumberSections = True } _ -> err 57 "could not parse number-offset") "NUMBERS") "" -- "Starting number for sections, subsections, etc." , Option "" ["no-tex-ligatures"] (NoArg (\opt -> return opt { optTeXLigatures = False })) "" -- "Don't use tex ligatures for quotes, dashes" , Option "" ["listings"] (NoArg (\opt -> return opt { optListings = True })) "" -- "Use listings package for LaTeX code blocks" , Option "i" ["incremental"] (NoArg (\opt -> return opt { optIncremental = True })) "" -- "Make list items display incrementally in Slidy/Slideous/S5" , Option "" ["slide-level"] (ReqArg (\arg opt -> do case safeRead arg of Just t | t >= 1 && t <= 6 -> return opt { optSlideLevel = Just t } _ -> err 39 $ "slide level must be a number between 1 and 6") "NUMBER") "" -- "Force header level for slides" , Option "" ["section-divs"] (NoArg (\opt -> return opt { optSectionDivs = True })) "" -- "Put sections in div tags in HTML" , Option "" ["default-image-extension"] (ReqArg (\arg opt -> return opt { optDefaultImageExtension = arg }) "extension") "" -- "Default extension for extensionless images" , Option "" ["email-obfuscation"] (ReqArg (\arg opt -> do method <- case arg of "references" -> return ReferenceObfuscation "javascript" -> return JavascriptObfuscation "none" -> return NoObfuscation _ -> err 6 ("Unknown obfuscation method: " ++ arg) return opt { optEmailObfuscation = method }) "none|javascript|references") "" -- "Method for obfuscating email in HTML" , Option "" ["id-prefix"] (ReqArg (\arg opt -> return opt { optIdentifierPrefix = arg }) "STRING") "" -- "Prefix to add to automatically generated HTML identifiers" , Option "T" ["title-prefix"] (ReqArg (\arg opt -> do let newvars = ("title-prefix", arg) : optVariables opt return opt { optVariables = newvars, optStandalone = True }) "STRING") "" -- "String to prefix to HTML window title" , Option "c" ["css"] (ReqArg (\arg opt -> do -- add new link to end, so it is included in proper order let newvars = optVariables opt ++ [("css",arg)] return opt { optVariables = newvars, optStandalone = True }) "URL") "" -- "Link to CSS style sheet" , Option "" ["reference-odt"] (ReqArg (\arg opt -> do return opt { optReferenceODT = Just arg }) "FILENAME") "" -- "Path of custom reference.odt" , Option "" ["reference-docx"] (ReqArg (\arg opt -> do return opt { optReferenceDocx = Just arg }) "FILENAME") "" -- "Path of custom reference.docx" , Option "" ["epub-stylesheet"] (ReqArg (\arg opt -> do text <- UTF8.readFile arg return opt { optEpubStylesheet = Just text }) "FILENAME") "" -- "Path of epub.css" , Option "" ["epub-cover-image"] (ReqArg (\arg opt -> return opt { optVariables = ("epub-cover-image", arg) : optVariables opt }) "FILENAME") "" -- "Path of epub cover image" , Option "" ["epub-metadata"] (ReqArg (\arg opt -> do text <- UTF8.readFile arg return opt { optEpubMetadata = text }) "FILENAME") "" -- "Path of epub metadata file" , Option "" ["epub-embed-font"] (ReqArg (\arg opt -> do return opt{ optEpubFonts = arg : optEpubFonts opt }) "FILE") "" -- "Directory of fonts to embed" , Option "" ["epub-chapter-level"] (ReqArg (\arg opt -> do case safeRead arg of Just t | t >= 1 && t <= 6 -> return opt { optEpubChapterLevel = t } _ -> err 59 $ "chapter level must be a number between 1 and 6") "NUMBER") "" -- "Header level at which to split chapters in EPUB" , Option "" ["latex-engine"] (ReqArg (\arg opt -> do let b = takeBaseName arg if (b == "pdflatex" || b == "lualatex" || b == "xelatex") then return opt { optLaTeXEngine = arg } else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.") "PROGRAM") "" -- "Name of latex program to use in generating PDF" , Option "" ["bibliography"] (ReqArg (\arg opt -> return opt{ optMetadata = addMetadata "bibliography" (readMetaValue arg) $ optMetadata opt }) "FILE") "" , Option "" ["csl"] (ReqArg (\arg opt -> return opt{ optMetadata = addMetadata "csl" (readMetaValue arg) $ optMetadata opt }) "FILE") "" , Option "" ["citation-abbreviations"] (ReqArg (\arg opt -> return opt{ optMetadata = addMetadata "citation-abbreviations" (readMetaValue arg) $ optMetadata opt }) "FILE") "" , Option "" ["natbib"] (NoArg (\opt -> return opt { optCiteMethod = Natbib })) "" -- "Use natbib cite commands in LaTeX output" , Option "" ["biblatex"] (NoArg (\opt -> return opt { optCiteMethod = Biblatex })) "" -- "Use biblatex cite commands in LaTeX output" , Option "m" ["latexmathml", "asciimathml"] (OptArg (\arg opt -> return opt { optHTMLMathMethod = LaTeXMathML arg }) "URL") "" -- "Use LaTeXMathML script in html output" , Option "" ["mathml"] (OptArg (\arg opt -> return opt { optHTMLMathMethod = MathML arg }) "URL") "" -- "Use mathml for HTML math" , Option "" ["mimetex"] (OptArg (\arg opt -> do let url' = case arg of Just u -> u ++ "?" Nothing -> "/cgi-bin/mimetex.cgi?" return opt { optHTMLMathMethod = WebTeX url' }) "URL") "" -- "Use mimetex for HTML math" , Option "" ["webtex"] (OptArg (\arg opt -> do let url' = case arg of Just u -> u Nothing -> "http://chart.apis.google.com/chart?cht=tx&chl=" return opt { optHTMLMathMethod = WebTeX url' }) "URL") "" -- "Use web service for HTML math" , Option "" ["jsmath"] (OptArg (\arg opt -> return opt { optHTMLMathMethod = JsMath arg}) "URL") "" -- "Use jsMath for HTML math" , Option "" ["mathjax"] (OptArg (\arg opt -> do let url' = case arg of Just u -> u Nothing -> "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" return opt { optHTMLMathMethod = MathJax url'}) "URL") "" -- "Use MathJax for HTML math" , Option "" ["gladtex"] (NoArg (\opt -> return opt { optHTMLMathMethod = GladTeX })) "" -- "Use gladtex for HTML math" , Option "" ["dump-args"] (NoArg (\opt -> return opt { optDumpArgs = True })) "" -- "Print output filename and arguments to stdout." , Option "" ["ignore-args"] (NoArg (\opt -> return opt { optIgnoreArgs = True })) "" -- "Ignore command-line arguments." , Option "v" ["version"] (NoArg (\_ -> do prg <- getProgName defaultDatadir <- getAppUserDataDirectory "pandoc" UTF8.hPutStrLn stdout (prg ++ " " ++ pandocVersion ++ compileInfo ++ "\nDefault user data directory: " ++ defaultDatadir ++ copyrightMessage) exitWith ExitSuccess )) "" -- "Print version" , Option "h" ["help"] (NoArg (\_ -> do prg <- getProgName UTF8.hPutStr stdout (usageMessage prg options) exitWith ExitSuccess )) "" -- "Show help" ] 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 (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++ (wrapWords 16 78 $ readers'names) ++ "\nOutput formats: " ++ (wrapWords 16 78 $ writers'names) ++ '\n' : replicate 16 ' ' ++ "[*for pdf output, use latex or beamer and -o FILENAME.pdf]\nOptions:") where writers'names = sort $ "pdf*" : map fst writers readers'names = sort $ map fst readers -- Determine default reader based on source file extensions defaultReaderName :: String -> [FilePath] -> String defaultReaderName fallback [] = fallback defaultReaderName fallback (x:xs) = case takeExtension (map toLower x) of ".xhtml" -> "html" ".html" -> "html" ".htm" -> "html" ".tex" -> "latex" ".latex" -> "latex" ".ltx" -> "latex" ".rst" -> "rst" ".lhs" -> "markdown+lhs" ".db" -> "docbook" ".opml" -> "opml" ".wiki" -> "mediawiki" ".textile" -> "textile" ".native" -> "native" ".json" -> "json" _ -> defaultReaderName fallback xs -- Returns True if extension of first source is .lhs lhsExtension :: [FilePath] -> Bool lhsExtension (x:_) = takeExtension x == ".lhs" lhsExtension _ = False -- Determine default writer based on output file extension defaultWriterName :: FilePath -> String defaultWriterName "-" = "html" -- no output file defaultWriterName x = case takeExtension (map toLower x) of "" -> "markdown" -- empty extension ".tex" -> "latex" ".latex" -> "latex" ".ltx" -> "latex" ".context" -> "context" ".ctx" -> "context" ".rtf" -> "rtf" ".rst" -> "rst" ".s5" -> "s5" ".native" -> "native" ".json" -> "json" ".txt" -> "markdown" ".text" -> "markdown" ".md" -> "markdown" ".markdown" -> "markdown" ".textile" -> "textile" ".lhs" -> "markdown+lhs" ".texi" -> "texinfo" ".texinfo" -> "texinfo" ".db" -> "docbook" ".odt" -> "odt" ".docx" -> "docx" ".epub" -> "epub" ".org" -> "org" ".asciidoc" -> "asciidoc" ".pdf" -> "latex" ".fb2" -> "fb2" ".opml" -> "opml" ['.',y] | y `elem` ['1'..'9'] -> "man" _ -> "html" main :: IO () main = do rawArgs <- liftM (map UTF8.decodeArg) getArgs prg <- getProgName let compatMode = (prg == "hsmarkdown") let (actions, args, errors) = if compatMode then ([], rawArgs, []) else getOpt Permute options rawArgs unless (null errors) $ err 2 $ concat $ errors ++ ["Try " ++ prg ++ " --help for more information."] let defaultOpts' = if compatMode then defaultOpts { optReader = "markdown_strict" , optWriter = "html" , optEmailObfuscation = ReferenceObfuscation } else defaultOpts -- thread option data structure through all supplied option actions opts <- foldl (>>=) (return defaultOpts') actions let Opt { optTabStop = tabStop , optPreserveTabs = preserveTabs , optStandalone = standalone , optReader = readerName , optWriter = writerName , optParseRaw = parseRaw , optVariables = variables , optMetadata = metadata , optTableOfContents = toc , optTransforms = transforms , optTemplate = templatePath , optOutputFile = outputFile , optNumberSections = numberSections , optNumberOffset = numberFrom , optSectionDivs = sectionDivs , optIncremental = incremental , optSelfContained = selfContained , optSmart = smart , optOldDashes = oldDashes , optHtml5 = html5 , optHtmlQTags = htmlQTags , optHighlight = highlight , optHighlightStyle = highlightStyle , optChapters = chapters , optHTMLMathMethod = mathMethod , optReferenceODT = referenceODT , optReferenceDocx = referenceDocx , optEpubStylesheet = epubStylesheet , optEpubMetadata = epubMetadata , optEpubFonts = epubFonts , optEpubChapterLevel = epubChapterLevel , optTOCDepth = epubTOCDepth , optDumpArgs = dumpArgs , optIgnoreArgs = ignoreArgs , optReferenceLinks = referenceLinks , optWrapText = wrap , optColumns = columns , optFilters = filters , optEmailObfuscation = obfuscationMethod , optIdentifierPrefix = idPrefix , optIndentedCodeClasses = codeBlockClasses , optDataDir = mbDataDir , optCiteMethod = citeMethod , optListings = listings , optLaTeXEngine = latexEngine , optSlideLevel = slideLevel , optSetextHeaders = setextHeaders , optAscii = ascii , optTeXLigatures = texLigatures , optDefaultImageExtension = defaultImageExtension } = opts when dumpArgs $ do UTF8.hPutStrLn stdout outputFile 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 _ | 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 Nothing -> E.catch (liftM Just $ getAppUserDataDirectory "pandoc") (\e -> let _ = (e :: E.SomeException) in return Nothing) Just _ -> return mbDataDir -- assign reader and writer based on options and filenames let readerName' = if null readerName then let fallback = if any isURI sources then "html" else "markdown" in defaultReaderName fallback sources else readerName let writerName' = if null writerName then defaultWriterName outputFile else case writerName of "epub2" -> "epub" "html4" -> "html" x -> x let pdfOutput = map toLower (takeExtension outputFile) == ".pdf" let laTeXOutput = "latex" `isPrefixOf` writerName' || "beamer" `isPrefixOf` writerName' when pdfOutput $ do -- make sure writer is latex or beamer unless laTeXOutput $ err 47 $ "cannot produce pdf output with " ++ writerName' ++ " writer" -- check for latex program mbLatex <- findExecutable latexEngine case mbLatex of Nothing -> err 41 $ latexEngine ++ " not found. " ++ latexEngine ++ " is needed for pdf output." Just _ -> return () reader <- case getReader readerName' of Right r -> return r Left e -> err 7 e let standalone' = standalone || not (isTextFormat writerName') || pdfOutput templ <- case templatePath of _ | not standalone' -> return "" Nothing -> do deftemp <- getDefaultTemplate datadir writerName' case deftemp of Left e -> throwIO e Right t -> return t Just tp -> do -- strip off extensions let format = takeWhile (`notElem` "+-") writerName' let tp' = case takeExtension tp of "" -> tp <.> format _ -> tp E.catch (UTF8.readFile tp') (\e -> if isDoesNotExistError e then E.catch (readDataFileUTF8 datadir ("templates" </> tp')) (\e' -> let _ = (e' :: E.SomeException) in throwIO e') else throwIO e) variables' <- case mathMethod of LaTeXMathML Nothing -> do s <- readDataFileUTF8 datadir ("LaTeXMathML.js") return $ ("mathml-script", s) : variables MathML Nothing -> do s <- readDataFileUTF8 datadir ("MathMLinHTML.js") return $ ("mathml-script", s) : variables _ -> return variables variables'' <- if "dzslides" `isPrefixOf` writerName' then do dztempl <- readDataFileUTF8 datadir ("dzslides" </> "template.html") let dzcore = unlines $ dropWhile (not . isPrefixOf "<!-- {{{{ dzslides core") $ lines dztempl return $ ("dzslides-core", dzcore) : variables' else return variables' let sourceURL = case sources of [] -> Nothing (x:_) -> case parseURI x of Just u | uriScheme u `elem` ["http:","https:"] -> Just $ show u{ uriPath = "", uriQuery = "", uriFragment = "" } _ -> Nothing let readerOpts = def{ readerSmart = smart || (texLigatures && (laTeXOutput || "context" `isPrefixOf` writerName')) , readerStandalone = standalone' , readerParseRaw = parseRaw , readerColumns = columns , readerTabStop = tabStop , readerOldDashes = oldDashes , readerIndentedCodeClasses = codeBlockClasses , readerApplyMacros = not laTeXOutput , readerDefaultImageExtension = defaultImageExtension } let writerOptions = def { writerStandalone = standalone', writerTemplate = templ, writerVariables = variables'', writerTabStop = tabStop, writerTableOfContents = toc, writerHTMLMathMethod = mathMethod, writerIncremental = incremental, writerCiteMethod = citeMethod, writerIgnoreNotes = False, writerNumberSections = numberSections, writerNumberOffset = numberFrom, writerSectionDivs = sectionDivs, writerReferenceLinks = referenceLinks, writerWrapText = wrap, writerColumns = columns, writerEmailObfuscation = obfuscationMethod, writerIdentifierPrefix = idPrefix, writerSourceURL = sourceURL, writerUserDataDir = datadir, writerHtml5 = html5, writerHtmlQTags = htmlQTags, writerChapters = chapters, writerListings = listings, writerBeamer = False, writerSlideLevel = slideLevel, writerHighlight = highlight, writerHighlightStyle = highlightStyle, writerSetextHeaders = setextHeaders, writerTeXLigatures = texLigatures, writerEpubMetadata = epubMetadata, writerEpubStylesheet = epubStylesheet, writerEpubFonts = epubFonts, writerEpubChapterLevel = epubChapterLevel, writerTOCDepth = epubTOCDepth, writerReferenceODT = referenceODT, writerReferenceDocx = referenceDocx } when (not (isTextFormat writerName') && outputFile == "-") $ err 5 $ "Cannot write " ++ writerName' ++ " output to stdout.\n" ++ "Specify an output file using the -o option." let readSources [] = mapM readSource ["-"] readSources srcs = mapM readSource srcs readSource "-" = UTF8.getContents readSource src = case parseURI src of Just u | uriScheme u `elem` ["http:","https:"] -> readURI src _ -> UTF8.readFile src 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) let handleIncludes' = if readerName' == "latex" || readerName' == "latex+lhs" then handleIncludes else return doc <- readSources sources >>= handleIncludes' . convertTabs . intercalate "\n" >>= reader readerOpts let doc0 = M.foldWithKey setMeta doc metadata let doc1 = foldr ($) doc0 transforms doc2 <- foldrM ($) doc1 $ map ($ [writerName']) plugins let writeBinary :: B.ByteString -> IO () writeBinary = B.writeFile (UTF8.encodePath outputFile) let writerFn :: FilePath -> String -> IO () writerFn "-" = UTF8.putStr writerFn f = UTF8.writeFile f case getWriter writerName' of Left e -> err 9 e Right (IOStringWriter f) -> f writerOptions doc2 >>= writerFn outputFile Right (IOByteStringWriter f) -> f writerOptions doc2 >>= writeBinary Right (PureStringWriter f) | pdfOutput -> do res <- makePDF latexEngine f writerOptions doc2 case res of Right pdf -> writeBinary pdf Left err' -> err 43 $ UTF8.toStringLazy err' | otherwise -> selfcontain (f writerOptions doc2 ++ ['\n' | not standalone']) >>= writerFn outputFile . handleEntities where htmlFormat = writerName' `elem` ["html","html+lhs","html5","html5+lhs", "s5","slidy","slideous","dzslides","revealjs"] selfcontain = if selfContained && htmlFormat then makeSelfContained datadir else return handleEntities = if htmlFormat && ascii then toEntities else id ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/README������������������������������������������������������������������������������000644 �000765 �000024 �00000315747 12251233602 014015� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Pandoc User's Guide % John MacFarlane % January 19, 2013 Synopsis ======== pandoc [*options*] [*input-file*]... Description =========== Pandoc is a [Haskell] library for converting from one markup format to another, and a command-line tool that uses this library. It can read [markdown] and (subsets of) [Textile], [reStructuredText], [HTML], [LaTeX], [MediaWiki markup], [Haddock markup], [OPML], and [DocBook]; and it can write plain text, [markdown], [reStructuredText], [XHTML], [HTML 5], [LaTeX] (including [beamer] slide shows), [ConTeXt], [RTF], [OPML], [DocBook], [OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [EPUB] (v2 or v3), [FictionBook2], [Textile], [groff man] pages, [Emacs Org-Mode], [AsciiDoc], and [Slidy], [Slideous], [DZSlides], [reveal.js] or [S5] HTML slide shows. It can also produce [PDF] output on systems where LaTeX is installed. Pandoc's enhanced version of markdown includes syntax for footnotes, tables, flexible ordered lists, definition lists, fenced code blocks, superscript, subscript, strikeout, title blocks, automatic tables of contents, embedded LaTeX math, citations, and markdown inside HTML block elements. (These enhancements, described below under [Pandoc's markdown](#pandocs-markdown), can be disabled using the `markdown_strict` input or output format.) In contrast to most existing tools for converting markdown to HTML, which use regex substitutions, Pandoc has a modular design: it consists of a set of readers, which parse text in a given format and produce a native representation of the document, and a set of writers, which convert this native representation into a target format. Thus, adding an input or output format requires only adding a reader or writer. Using `pandoc` -------------- If no *input-file* is specified, input is read from *stdin*. Otherwise, the *input-files* are concatenated (with a blank line between each) and used as input. Output goes to *stdout* by default (though output to *stdout* is disabled for the `odt`, `docx`, `epub`, and `epub3` output formats). For output to a file, use the `-o` option: pandoc -o output.html input.txt Instead of a file, an absolute URI may be given. In this case pandoc will fetch the content using HTTP: pandoc -f html -t markdown http://www.fsf.org If multiple input files are given, `pandoc` will concatenate them all (with blank lines between them) before parsing. The format of the input and output can be specified explicitly using command-line options. The input format can be specified using the `-r/--read` or `-f/--from` options, the output format using the `-w/--write` or `-t/--to` options. Thus, to convert `hello.txt` from markdown to LaTeX, you could type: pandoc -f markdown -t latex hello.txt To convert `hello.html` from html to markdown: pandoc -f html -t markdown hello.html Supported output formats are listed below under the `-t/--to` option. Supported input formats are listed below under the `-f/--from` option. Note that the `rst`, `textile`, `latex`, and `html` readers are not complete; there are some constructs that they do not parse. If the input or output format is not specified explicitly, `pandoc` will attempt to guess it from the extensions of the input and output filenames. Thus, for example, pandoc -o hello.tex hello.txt will convert `hello.txt` from markdown to LaTeX. If no output file is specified (so that output goes to *stdout*), or if the output file's extension is unknown, the output format will default to HTML. If no input file is specified (so that input comes from *stdin*), or if the input files' extensions are unknown, the input format will be assumed to be markdown unless explicitly specified. Pandoc uses the UTF-8 character encoding for both input and output. If your local character encoding is not UTF-8, you should pipe input and output through `iconv`: iconv -t utf-8 input.txt | pandoc | iconv -f utf-8 Creating a PDF -------------- Earlier versions of pandoc came with a program, `markdown2pdf`, that used pandoc and pdflatex to produce a PDF. This is no longer needed, since `pandoc` can now produce `pdf` output itself. To produce a PDF, simply specify an output file with a `.pdf` extension. Pandoc will create a latex file and use pdflatex (or another engine, see `--latex-engine`) to convert it to PDF: pandoc test.txt -o test.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`, `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). `hsmarkdown` ------------ A user who wants a drop-in replacement for `Markdown.pl` may create a symbolic link to the `pandoc` executable called `hsmarkdown`. When invoked under the name `hsmarkdown`, `pandoc` will behave as if invoked with `-f markdown_strict --email-obfuscation=references`, and all command-line options will be treated as regular arguments. However, this approach does not work under Cygwin, due to problems with its simulation of symbolic links. [Cygwin]: http://www.cygwin.com/ [`iconv`]: http://www.gnu.org/software/libiconv/ [CTAN]: http://www.ctan.org "Comprehensive TeX Archive Network" [TeX Live]: http://www.tug.org/texlive/ [MacTeX]: http://www.tug.org/mactex/ Options ======= General options --------------- `-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT* : Specify input format. *FORMAT* can be `native` (native Haskell), `json` (JSON version of native AST), `markdown` (pandoc's extended markdown), `markdown_strict` (original unextended markdown), `markdown_phpextra` (PHP Markdown Extra extended markdown), `markdown_github` (github extended markdown), `textile` (Textile), `rst` (reStructuredText), `html` (HTML), `docbook` (DocBook), `opml` (OPML), `mediawiki` (MediaWiki markup), `haddock` (Haddock markup), or `latex` (LaTeX). If `+lhs` is appended to `markdown`, `rst`, `latex`, or `html`, the input will be treated as literate Haskell source: see [Literate Haskell support](#literate-haskell-support), below. Markdown syntax extensions can be individually enabled or disabled by appending `+EXTENSION` or `-EXTENSION` to the format name. So, for example, `markdown_strict+footnotes+definition_lists` is strict markdown with footnotes and definition lists enabled, and `markdown-pipe_tables+hard_line_breaks` is pandoc's markdown without pipe tables and with hard line breaks. See [Pandoc's markdown](#pandocs-markdown), below, for a list of extensions and their names. `-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT* : Specify output format. *FORMAT* can be `native` (native Haskell), `json` (JSON version of native AST), `plain` (plain text), `markdown` (pandoc's extended markdown), `markdown_strict` (original unextended markdown), `markdown_phpextra` (PHP Markdown extra extended markdown), `markdown_github` (github extended markdown), `rst` (reStructuredText), `html` (XHTML 1), `html5` (HTML 5), `latex` (LaTeX), `beamer` (LaTeX beamer slide show), `context` (ConTeXt), `man` (groff man), `mediawiki` (MediaWiki markup), `textile` (Textile), `org` (Emacs Org-Mode), `texinfo` (GNU Texinfo), `opml` (OPML), `docbook` (DocBook), `opendocument` (OpenDocument), `odt` (OpenOffice text document), `docx` (Word docx), `rtf` (rich text format), `epub` (EPUB v2 book), `epub3` (EPUB v3), `fb2` (FictionBook2 e-book), `asciidoc` (AsciiDoc), `slidy` (Slidy HTML and javascript slide show), `slideous` (Slideous HTML and javascript slide show), `dzslides` (DZSlides HTML5 + javascript slide show), `revealjs` (reveal.js HTML5 + javascript slide show), `s5` (S5 HTML and javascript slide show), or the path of a custom lua writer (see [Custom writers](#custom-writers), below). Note that `odt`, `epub`, and `epub3` output will not be directed to *stdout*; an output filename must be specified using the `-o/--output` option. If `+lhs` is appended to `markdown`, `rst`, `latex`, `beamer`, `html`, or `html5`, the output will be rendered as literate Haskell source: see [Literate Haskell support](#literate-haskell-support), below. Markdown syntax extensions can be individually enabled or disabled by appending `+EXTENSION` or `-EXTENSION` to the format name, as described above under `-f`. `-o` *FILE*, `--output=`*FILE* : Write output to *FILE* instead of *stdout*. If *FILE* is `-`, output will go to *stdout*. (Exception: if the output format is `odt`, `docx`, `epub`, or `epub3`, output to stdout is disabled.) `--data-dir=`*DIRECTORY* : Specify the user data directory to search for pandoc data files. If this option is not specified, the default user data directory will be used. This is $HOME/.pandoc in unix, C:\Documents And Settings\USERNAME\Application Data\pandoc in Windows XP, and C:\Users\USERNAME\AppData\Roaming\pandoc in Windows 7. (You can find the default user data directory on your system by looking at the output of `pandoc --version`.) A `reference.odt`, `reference.docx`, `default.csl`, `epub.css`, `templates`, `slidy`, `slideous`, or `s5` directory placed in this directory will override pandoc's normal defaults. `-v`, `--version` : Print version. `-h`, `--help` : Show usage message. Reader options -------------- `-R`, `--parse-raw` : Parse untranslatable HTML codes and LaTeX environments as raw HTML or LaTeX, instead of ignoring them. Affects only HTML and LaTeX input. Raw HTML can be printed in markdown, reStructuredText, HTML, Slidy, Slideous, DZSlides, reveal.js, and S5 output; raw LaTeX can be printed in markdown, reStructuredText, LaTeX, and ConTeXt output. The default is for the readers to omit untranslatable HTML codes and LaTeX environments. (The LaTeX reader does pass through untranslatable LaTeX *commands*, even if `-R` is not specified.) `-S`, `--smart` : Produce typographically correct output, converting straight quotes to curly quotes, `---` to em-dashes, `--` to en-dashes, and `...` to ellipses. Nonbreaking spaces are inserted after certain abbreviations, such as "Mr." (Note: This option is significant only when the input format is `markdown`, `markdown_strict`, or `textile`. It is selected automatically when the input format is `textile` or the output format is `latex` or `context`, unless `--no-tex-ligatures` is used.) `--old-dashes` : Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes: `-` before a numeral is an en-dash, and `--` is an em-dash. This option is selected automatically for `textile` input. `--base-header-level=`*NUMBER* : Specify the base level for headers (defaults to 1). `--indented-code-classes=`*CLASSES* : Specify classes to use for indented code blocks--for example, `perl,numberLines` or `haskell`. Multiple classes may be separated by spaces or commas. `--default-image-extension=`*EXTENSION* : Specify a default extension to use when image paths/URLs have no extension. This allows you to use the same source for formats that require different kinds of images. Currently this option only affects the markdown and LaTeX readers. `--filter=`*EXECUTABLE* : Specify an executable to be used as a filter transforming the Pandoc AST after the input is parsed and before the output is written. The executable should read JSON from stdin and write JSON to stdout. The JSON must be formatted like pandoc's own JSON input and output. The name of the output format will be passed to the filter as the first argument. Hence, pandoc --filter ./caps.py -t latex is equivalent to pandoc -t json | ./caps.py latex | pandoc -f json -t latex The latter form may be useful for debugging filters. 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 `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*. 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 `Str` or `Emph` elements, for example, and remove repeated `Space`s. `-p`, `--preserve-tabs` : Preserve tabs instead of converting them to spaces (the default). Note that this will only affect tabs in literal code spans and code blocks; tabs in regular text will be treated as spaces. `--tab-stop=`*NUMBER* : Specify the number of spaces per tab (default is 4). General writer options ---------------------- `-s`, `--standalone` : Produce output with an appropriate header and footer (e.g. a standalone HTML, LaTeX, or RTF file, not a fragment). This option is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt` output. `--template=`*FILE* : Use *FILE* as a custom template for the generated document. Implies `--standalone`. See [Templates](#templates) below for a description of template syntax. If no extension is specified, an extension corresponding to the writer will be added, so that `--template=special` looks for `special.html` for HTML output. If the template is not found, pandoc will search for it in the user data directory (see `--data-dir`). If this option is not used, a default template appropriate for the output format will be used (see `-D/--print-default-template`). `-V` *KEY[=VAL]*, `--variable=`*KEY[:VAL]* : Set the template variable *KEY* to the value *VAL* when rendering the document in standalone mode. This is generally only useful when the `--template` option is used to specify a custom template, since pandoc automatically sets the variables used in the default templates. If no *VAL* is specified, the key will be given the value `true`. `-D` *FORMAT*, `--print-default-template=`*FORMAT* : Print the default template for an output *FORMAT*. (See `-t` for a list of possible *FORMAT*s.) `--print-default-data-file=`*FILE* : Print a default data file. `--no-wrap` : Disable text wrapping in output. By default, text is wrapped appropriately for the output format. `--columns`=*NUMBER* : Specify length of lines in characters (for text wrapping). `--toc`, `--table-of-contents` : Include an automatically generated table of contents (or, in the case of `latex`, `context`, and `rst`, an instruction to create one) in the output document. This option has no effect on `man`, `docbook`, `slidy`, `slideous`, `s5`, `docx`, or `odt` output. `--toc-depth=`*NUMBER* : Specify the number of section levels to include in the table of contents. The default is 3 (which means that level 1, 2, and 3 headers will be listed in the contents). `--no-highlight` : Disables syntax highlighting for code blocks and inlines, even when a language attribute is given. `--highlight-style`=*STYLE* : Specifies the coloring style to be used in highlighted source code. Options are `pygments` (the default), `kate`, `monochrome`, `espresso`, `zenburn`, `haddock`, and `tango`. `-H` *FILE*, `--include-in-header=`*FILE* : Include contents of *FILE*, verbatim, at the end of the header. This can be used, for example, to include special CSS or javascript in HTML documents. This option can be used repeatedly to include multiple files in the header. They will be included in the order specified. Implies `--standalone`. `-B` *FILE*, `--include-before-body=`*FILE* : Include contents of *FILE*, verbatim, at the beginning of the document body (e.g. after the `<body>` tag in HTML, or the `\begin{document}` command in LaTeX). This can be used to include navigation bars or banners in HTML documents. This option can be used repeatedly to include multiple files. They will be included in the order specified. Implies `--standalone`. `-A` *FILE*, `--include-after-body=`*FILE* : Include contents of *FILE*, verbatim, at the end of the document body (before the `</body>` tag in HTML, or the `\end{document}` command in LaTeX). This option can be be used repeatedly to include multiple files. They will be included in the order specified. Implies `--standalone`. Options affecting specific writers ---------------------------------- `--self-contained` : Produce a standalone HTML file with no external dependencies, using `data:` URIs to incorporate the contents of linked scripts, stylesheets, images, and videos. The resulting file should be "self-contained," in the sense that it needs no external files and no net access to be displayed properly by a browser. This option works only with HTML output formats, including `html`, `html5`, `html+lhs`, `html5+lhs`, `s5`, `slidy`, `slideous`, `dzslides`, and `revealjs`. Scripts, images, and stylesheets at absolute URLs will be downloaded; those at relative URLs will be sought first relative to the working directory, then relative to the user data directory (see `--data-dir`), and finally relative to pandoc's default data directory. `--self-contained` does not work with `--mathjax`. `--offline` : Deprecated synonym for `--self-contained`. `-5`, `--html5` : Produce HTML5 instead of HTML4. This option has no effect for writers other than `html`. (*Deprecated:* Use the `html5` output format instead.) `--html-q-tags` : Use `<q>` tags for quotes in HTML. `--ascii` : Use only ascii characters in output. Currently supported only for HTML output (which uses numerical entities instead of UTF-8 when this option is selected). `--reference-links` : Use reference-style links, rather than inline links, in writing markdown or reStructuredText. By default inline links are used. `--atx-headers` : Use ATX style headers in markdown and asciidoc output. The default is to use setext-style headers for levels 1-2, and then ATX headers. `--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{..}`. `-N`, `--number-sections` : Number section headings in LaTeX, ConTeXt, HTML, or EPUB output. By default, sections are not numbered. Sections with class `unnumbered` will never be numbered, even if `--number-sections` is specified. `--number-offset`=*NUMBER[,NUMBER,...]*, : Offset for section headings in HTML output (ignored in other output formats). The first number is added to the section number for top-level headers, the second for second-level headers, and so on. So, for example, if you want the first top-level header in your document to be numbered "6", specify `--number-offset=5`. If your document starts with a level-2 header which you want to be numbered "1.5", specify `--number-offset=1,4`. Offsets are 0 by default. Implies `--number-sections`. `--no-tex-ligatures` : Do not convert quotation marks, apostrophes, and dashes to the TeX ligatures when writing LaTeX or ConTeXt. Instead, just use literal unicode characters. This is needed for using advanced OpenType features with XeLaTeX and LuaLaTeX. Note: normally `--smart` is selected automatically for LaTeX and ConTeXt output, but it must be specified explicitly if `--no-tex-ligatures` is selected. If you use literal curly quotes, dashes, and ellipses in your source, then you may want to use `--no-tex-ligatures` without `--smart`. `--listings` : Use listings package for LaTeX code blocks `-i`, `--incremental` : Make list items in slide shows display incrementally (one by one). The default is for lists to be displayed all at once. `--slide-level`=*NUMBER* : Specifies that headers with the specified level create slides (for `beamer`, `s5`, `slidy`, `slideous`, `dzslides`). Headers above this level in the hierarchy are used to divide the slide show into sections; headers below this level create subheads within a slide. The default is to set the slide level based on the contents of the document; see [Structuring the slide show](#structuring-the-slide-show), below. `--section-divs` : Wrap sections in `<div>` tags (or `<section>` tags in HTML5), and attach identifiers to the enclosing `<div>` (or `<section>`) rather than the header itself. See [Section identifiers](#header-identifiers-in-html-latex-and-context), below. `--email-obfuscation=`*none|javascript|references* : Specify a method for obfuscating `mailto:` links in HTML documents. *none* leaves `mailto:` links as they are. *javascript* obfuscates them using javascript. *references* obfuscates them by printing their letters as decimal or hexadecimal character references. `--id-prefix`=*STRING* : Specify a prefix to be added to all automatically generated identifiers in HTML and DocBook output, and to footnote numbers in markdown output. This is useful for preventing duplicate identifiers when generating fragments to be included in other pages. `-T` *STRING*, `--title-prefix=`*STRING* : Specify *STRING* as a prefix at the beginning of the title that appears in the HTML header (but not in the title as it appears at the beginning of the HTML body). Implies `--standalone`. `-c` *URL*, `--css=`*URL* : Link to a CSS style sheet. This option can be be used repeatedly to include multiple files. They will be included in the order specified. `--reference-odt=`*FILE* : Use the specified file as a style reference in producing an ODT. For best results, the reference ODT should be a modified version of an ODT produced using pandoc. The contents of the reference ODT are ignored, but its stylesheets are used in the new ODT. If no reference ODT is specified on the command line, pandoc will look for a file `reference.odt` in the user data directory (see `--data-dir`). If this is not found either, sensible defaults will be used. `--reference-docx=`*FILE* : Use the specified file as a style reference in producing a docx file. For best results, the reference docx should be a modified version of a docx file produced using pandoc. The contents of the reference docx are ignored, but its stylesheets are used in the new docx. If no reference docx is specified on the command line, pandoc will look for a file `reference.docx` in the user data directory (see `--data-dir`). If this is not found either, sensible defaults will be used. The following styles are used by pandoc: [paragraph] Normal, Compact, Title, Authors, Date, Heading 1, Heading 2, Heading 3, Heading 4, Heading 5, Block Quote, Definition Term, Definition, Body Text, Table Caption, Image Caption; [character] Default Paragraph Font, Body Text Char, Verbatim Char, Footnote Ref, Link. `--epub-stylesheet=`*FILE* : Use the specified CSS file to style the EPUB. If no stylesheet is specified, pandoc will look for a file `epub.css` in the user data directory (see `--data-dir`). If it is not found there, sensible defaults will be used. `--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. 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. The file should contain a series of Dublin Core elements, as documented at <http://dublincore.org/documents/dces/>. For example: <dc:rights>Creative Commons</dc:rights> <dc:language>es-AR</dc:language> By default, pandoc will include the following metadata elements: `<dc:title>` (from the document title), `<dc:creator>` (from the document authors), `<dc:date>` (from the document date, which should be in [ISO 8601 format]), `<dc:language>` (from the `lang` variable, or, if is not set, the locale), and `<dc:identifier 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 will need to add declarations like the following to your CSS (see `--epub-stylesheet`): @font-face { font-family: DejaVuSans; font-style: normal; font-weight: normal; src:url("DejaVuSans-Regular.ttf"); } @font-face { font-family: DejaVuSans; font-style: normal; font-weight: bold; src:url("DejaVuSans-Bold.ttf"); } @font-face { font-family: DejaVuSans; font-style: italic; font-weight: normal; src:url("DejaVuSans-Oblique.ttf"); } @font-face { font-family: DejaVuSans; font-style: italic; font-weight: bold; src:url("DejaVuSans-BoldOblique.ttf"); } body { font-family: "DejaVuSans"; } `--epub-chapter-level=`*NUMBER* : Specify the header level at which to split the EPUB into separate "chapter" files. The default is to split into chapters at level 1 headers. This option only affects the internal composition of the EPUB, not the way chapters and sections are displayed to users. Some readers may be slow if the chapter files are too large, so for large documents with few level 1 headers, one might want to use a chapter level of 2 or 3. `--latex-engine=`*pdflatex|lualatex|xelatex* : Use the specified LaTeX engine when producing PDF output. The default is `pdflatex`. If the engine is not in your PATH, the full path of the engine may be specified here. Citation rendering ------------------ `--bibliography=`*FILE* : Set the `bibliography` field in the document's metadata to *FILE*, 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*, overriding any value set in the metadata. (This is equivalent to `--metadata csl=FILE`.) `--citation-abbreviations=`*FILE* : Set the `citation-abbreviations` field in the document's metadata to *FILE*, overriding any value set in the metadata. (This is equivalent to `--metadata citation-abbreviations=FILE`.) `--natbib` : Use natbib for citations in LaTeX output. `--biblatex` : Use biblatex for citations in LaTeX output. Math rendering in HTML ---------------------- `-m` [*URL*], `--latexmathml`[=*URL*] : Use the [LaTeXMathML] script to display embedded TeX math in HTML output. To insert a link to a local copy of the `LaTeXMathML.js` script, provide a *URL*. If no *URL* is provided, the contents of the script will be inserted directly into the HTML header, preserving portability at the price of efficiency. If you plan to use math on several pages, it is much better to link to a copy of the script, so it can be cached. `--mathml`[=*URL*] : Convert TeX math to MathML (in `docbook` as well as `html` and `html5`). In standalone `html` output, a small javascript (or a link to such a script if a *URL* is supplied) will be inserted that allows the MathML to be viewed on some browsers. `--jsmath`[=*URL*] : Use [jsMath] to display embedded TeX math in HTML output. The *URL* should point to the jsMath load script (e.g. `jsMath/easy/load.js`); if provided, it will be linked to in the header of standalone HTML documents. If a *URL* is not provided, no link to the jsMath load script will be inserted; it is then up to the author to provide such a link in the HTML template. `--mathjax`[=*URL*] : Use [MathJax] to display embedded TeX math in HTML output. The *URL* should point to the `MathJax.js` load script. If a *URL* is not provided, a link to the MathJax CDN will be inserted. `--gladtex` : Enclose TeX math in `<eq>` tags in HTML output. These can then be processed by [gladTeX] to produce links to images of the typeset formulas. `--mimetex`[=*URL*] : Render TeX math using the [mimeTeX] CGI script. If *URL* is not specified, it is assumed that the script is at `/cgi-bin/mimetex.cgi`. `--webtex`[=*URL*] : Render TeX formulas using an external script that converts TeX formulas to images. The formula will be concatenated with the URL provided. If *URL* is not specified, the Google Chart API will be used. Options for wrapper scripts --------------------------- `--dump-args` : Print information about command-line arguments to *stdout*, then exit. This option is intended primarily for use in wrapper scripts. The first line of output contains the name of the output file specified with the `-o` option, or `-` (for *stdout*) if no output file was specified. The remaining lines contain the command-line arguments, one per line, in the order they appear. These do not include regular Pandoc options and their arguments, but do include any options appearing after a `--` separator at the end of the line. `--ignore-args` : Ignore command-line arguments (for use in wrapper scripts). Regular Pandoc options are not ignored. Thus, for example, pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1 is equivalent to pandoc -o foo.html -s [LaTeXMathML]: http://math.etsu.edu/LaTeXMathML/ [jsMath]: http://www.math.union.edu/~dpvc/jsmath/ [MathJax]: http://www.mathjax.org/ [gladTeX]: http://ans.hsh.no/home/mgg/gladtex/ [mimeTeX]: http://www.forkosh.com/mimetex.html [CSL]: http://CitationStyles.org Templates ========= When the `-s/--standalone` option is used, pandoc uses a template to add header and footer material that is needed for a self-standing document. To see the default template that is used, just type pandoc -D FORMAT where `FORMAT` is the name of the output format. A custom template can be specified using the `--template` option. You can also override the system default templates for a given output format `FORMAT` by putting a file `templates/default.FORMAT` in the user data directory (see `--data-dir`, above). *Exceptions:* For `odt` output, customize the `default.opendocument` template. For `pdf` output, customize the `default.latex` template. Templates may contain *variables*. Variable names are sequences of alphanumerics, `-`, and `_`, starting with a letter. A variable name surrounded by `$` signs will be replaced by its value. For example, the string `$title$` in <title>$title$ will be replaced by the document title. To write a literal `$` in a template, use `$$`. Some variables are set automatically by pandoc. These vary somewhat depending on the output format, but include metadata fields (such as `title`, `author`, and `date`) as well as the following: `header-includes` : contents specified by `-H/--include-in-header` (may have multiple values) `toc` : non-null value if `--toc/--table-of-contents` was specified `include-before` : contents specified by `-B/--include-before-body` (may have multiple values) `include-after` : contents specified by `-A/--include-after-body` (may have multiple values) `body` : body of document `lang` : language code for HTML or LaTeX documents `slidy-url` : base URL for Slidy documents (defaults to `http://www.w3.org/Talks/Tools/Slidy2`) `slideous-url` : base URL for Slideous documents (defaults to `default`) `s5-url` : base URL for S5 documents (defaults to `ui/default`) `revealjs-url` : base URL for reveal.js documents (defaults to `reveal.js`) `theme` : reveal.js or LaTeX beamer theme `transition` : reveal.js transition `fontsize` : font size (10pt, 11pt, 12pt) for LaTeX documents `documentclass` : document class for LaTeX documents `classoption` : option for LaTeX documentclass, e.g. `oneside`; may be repeated for multiple options `geometry` : options for LaTeX `geometry` class, e.g. `margin=1in`; may be repeated for multiple options `mainfont`, `sansfont`, `monofont`, `mathfont` : fonts for LaTeX documents (works only with xelatex and lualatex) `colortheme` : colortheme for LaTeX beamer documents `fonttheme` : fonttheme for LaTeX beamer documents `linkcolor` : color for internal links in LaTeX documents (`red`, `green`, `magenta`, `cyan`, `blue`, `black`) `urlcolor` : color for external links in LaTeX documents `citecolor` : color for citation links in LaTeX documents `links-as-notes` : causes links to be printed as footnotes in LaTeX documents `biblio-style` : bibliography style in LaTeX, when used with `--natbib` `section` : section number in man pages `header` : header in man pages `footer` : footer in man pages Variables may be set at the command line using the `-V/--variable` option. Variables set in this way override metadata fields with the same name. Templates may contain conditionals. The syntax is as follows: $if(variable)$ X $else$ Y $endif$ This will include `X` in the template if `variable` has a non-null value; otherwise it will include `Y`. `X` and `Y` are placeholders for any valid template text, and may include interpolated variables or other conditionals. The `$else$` section may be omitted. When variables can have multiple values (for example, `author` in a multi-author document), you can use the `$for$` keyword: $for(author)$ $endfor$ You can optionally specify a separator to be used between consecutive items: $for(author)$$author$$sep$, $endfor$ A dot can be used to select a field of a variable that takes an object as its value. So, for example: $author.name$ ($author.affiliation$) If you use custom templates, you may need to revise them as pandoc changes. We recommend tracking the changes in the default templates, and modifying your custom templates accordingly. An easy way to do this is to fork the pandoc-templates repository () and merge in changes after each pandoc release. Pandoc's markdown ================= Pandoc understands an extended and slightly revised version of John Gruber's [markdown] syntax. This document explains the syntax, noting differences from standard markdown. Except where noted, these differences can be suppressed by using the `markdown_strict` format instead of `markdown`. An extensions can be enabled by adding `+EXTENSION` to the format name and disabled by adding `-EXTENSION`. For example, `markdown_strict+footnotes` is strict markdown with footnotes enabled, while `markdown-footnotes-pipe_tables` is pandoc's markdown without footnotes or pipe tables. Philosophy ---------- Markdown is designed to be easy to write, and, even more importantly, easy to read: > 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. > -- [John Gruber](http://daringfireball.net/projects/markdown/syntax#philosophy) This principle has guided pandoc's decisions in finding syntax for tables, footnotes, and other extensions. There is, however, one respect in which pandoc's aims are different from the original aims of markdown. Whereas markdown was originally designed with HTML generation in mind, pandoc is designed for multiple output formats. Thus, while pandoc allows the embedding of raw HTML, it discourages it, and provides other, non-HTMLish ways of representing important document elements like definition lists, tables, mathematics, and footnotes. Paragraphs ---------- A paragraph is one or more lines of text followed by one or more blank line. Newlines are treated as spaces, so you can reflow your paragraphs as you like. If you need a hard line break, put two or more spaces at the end of a line. **Extension: `escaped_line_breaks`** A backslash followed by a newline is also a hard line break. Headers ------- There are two kinds of headers, Setext and atx. ### Setext-style headers ### A setext-style header is a line of text "underlined" with a row of `=` signs (for a level one header) or `-` signs (for a level two header): A level-one header ================== A level-two header ------------------ The header text can contain inline formatting, such as emphasis (see [Inline formatting](#inline-formatting), below). ### Atx-style headers ### An Atx-style header consists of one to six `#` signs and a line of text, optionally followed by any number of `#` signs. The number of `#` signs at the beginning of the line is the header level: ## A level-two header ### A level-three header ### As with setext-style headers, the header text can contain formatting: # A level-one header with a [link](/url) and *emphasis* **Extension: `blank_before_header`** Standard markdown syntax does not require a blank line before a header. Pandoc does require this (except, of course, at the beginning of the document). The reason for the requirement is that it is all too easy for a `#` to end up at the beginning of a line by accident (perhaps through line wrapping). Consider, for example: I like several of their flavors of ice cream: #22, for example, and #5. ### Header identifiers in HTML, LaTeX, and ConTeXt ### **Extension: `header_attributes`** Headers can be assigned attributes using this syntax at the end of the line containing the header text: {#identifier .class .class key=value key=value} Although this syntax allows assignment of classes and key/value attributes, only identifiers currently have any affect in the writers (and only in some writers: HTML, LaTeX, ConTeXt, Textile, AsciiDoc). Thus, for example, the following headers will all be assigned the identifier `foo`: # My header {#foo} ## My header ## {#foo} My other header {#foo} --------------- (This syntax is compatible with [PHP Markdown Extra].) Headers with the class `unnumbered` will not be numbered, even if `--number-sections` is specified. A single hyphen (`-`) in an attribute context is equivalent to `.unnumbered`, and preferable in non-English documents. So, # My header {-} is just the same as # My header {.unnumbered} **Extension: `auto_identifiers`** A header without an explicitly specified identifier will be automatically assigned a unique identifier based on the header text. To derive the identifier from the header text, - Remove all formatting, links, etc. - Remove all footnotes. - Remove all punctuation, except underscores, hyphens, and periods. - Replace all spaces and newlines with hyphens. - Convert all alphabetic characters to lowercase. - Remove everything up to the first letter (identifiers may not begin with a number or punctuation mark). - If nothing is left after this, use the identifier `section`. Thus, for example, Header Identifier ------------------------------- ---------------------------- Header identifiers in HTML `header-identifiers-in-html` *Dogs*?--in *my* house? `dogs--in-my-house` [HTML], [S5], or [RTF]? `html-s5-or-rtf` 3. Applications `applications` 33 `section` These rules should, in most cases, allow one to determine the identifier from the header text. The exception is when several headers have the same text; in this case, the first will get an identifier as described above; the second will get the same identifier with `-1` appended; the third with `-2`; and so on. These identifiers are used to provide link targets in the table of contents generated by the `--toc|--table-of-contents` option. They also make it easy to provide links from one section of a document to another. A link to this section, for example, might look like this: See the section on [header identifiers](#header-identifiers-in-html-latex-and-context). Note, however, that this method of providing links to sections works only in HTML, LaTeX, and ConTeXt formats. If the `--section-divs` option is specified, then each section will be wrapped in a `div` (or a `section`, if `--html5` was specified), and the identifier will be attached to the enclosing `

` (or `
`) tag rather than the header itself. This allows entire sections to be manipulated using javascript or treated differently in CSS. **Extension: `implicit_header_references`** Pandoc behaves as if reference links have been defined for each header. So, instead of [header identifiers](#header-identifiers-in-html) you can simply write [header identifiers] or [header identifiers][] or [the section on header identifiers][header identifiers] If there are multiple headers with identical text, the corresponding reference will link to the first one only, and you will need to use explicit links to link to the others, as described above. Unlike regular reference links, these references are case-sensitive. Note: if you have defined an explicit identifier for a header, then implicit references to it will not work. Block quotations ---------------- Markdown uses email conventions for quoting blocks of text. A block quotation is one or more paragraphs or other block elements (such as lists or headers), with each line preceded by a `>` character and a space. (The `>` need not start at the left margin, but it should not be indented more than three spaces.) > This is a block quote. This > paragraph has two lines. > > 1. This is a list inside a block quote. > 2. Second item. A "lazy" form, which requires the `>` character only on the first line of each block, is also allowed: > This is a block quote. This paragraph has two lines. > 1. This is a list inside a block quote. 2. Second item. Among the block elements that can be contained in a block quote are other block quotes. That is, block quotes can be nested: > This is a block quote. > > > A block quote within a block quote. **Extension: `blank_before_blockquote`** Standard markdown syntax does not require a blank line before a block quote. Pandoc does require this (except, of course, at the beginning of the document). The reason for the requirement is that it is all too easy for a `>` to end up at the beginning of a line by accident (perhaps through line wrapping). So, unless the `markdown_strict` format is used, the following does not produce a nested block quote in pandoc: > This is a block quote. >> Nested. Verbatim (code) blocks ---------------------- ### Indented code blocks ### A block of text indented four spaces (or one tab) is treated as verbatim text: that is, special characters do not trigger special formatting, and all spaces and line breaks are preserved. For example, if (a > 3) { moveShip(5 * gravity, DOWN); } The initial (four space or one tab) indentation is not considered part of the verbatim text, and is removed in the output. Note: blank lines in the verbatim text need not begin with four spaces. ### Fenced code blocks ### **Extension: `fenced_code_blocks`** In addition to standard indented code blocks, Pandoc supports *fenced* code blocks. These begin with a row of three or more tildes (`~`) or backticks (`` ` ``) and end with a row of tildes or backticks that must be at least as long as the starting row. Everything between these lines is treated as code. No indentation is necessary: ~~~~~~~ if (a > 3) { moveShip(5 * gravity, DOWN); } ~~~~~~~ Like regular code blocks, fenced code blocks must be separated from surrounding text by blank lines. If the code itself contains a row of tildes or backticks, just use a longer row of tildes or backticks at the start and end: ~~~~~~~~~~~~~~~~ ~~~~~~~~~~ code including tildes ~~~~~~~~~~ ~~~~~~~~~~~~~~~~ Optionally, you may attach attributes to the code block using this syntax: ~~~~ {#mycode .haskell .numberLines startFrom="100"} qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here `mycode` is an identifier, `haskell` and `numberLines` are classes, and `startFrom` is an attribute with value `100`. Some output formats can use this information to do syntax highlighting. Currently, the only output formats that uses this information are HTML and LaTeX. If highlighting is supported for your output format and language, then the code block above will appear highlighted, with numbered lines. (To see which languages are supported, do `pandoc --version`.) Otherwise, the code block above will appear as follows:
      
      ...
      
    
A shortcut form can also be used for specifying the language of the code block: ```haskell qsort [] = [] ``` This is equivalent to: ``` {.haskell} qsort [] = [] ``` To prevent all highlighting, use the `--no-highlight` flag. To set the highlighting style, use `--highlight-style`. Line blocks ----------- **Extension: `line_blocks`** A line block is a sequence of lines beginning with a vertical bar (`|`) followed by a space. The division into lines will be preserved in the output, as will any leading spaces; otherwise, the lines will be formatted as markdown. This is useful for verse and addresses: | The limerick packs laughs anatomical | In space that is quite economical. | But the good ones I've seen | So seldom are clean | And the clean ones so seldom are comical | 200 Main St. | Berkeley, CA 94718 The lines can be hard-wrapped if needed, but the continuation line must begin with a space. | The Right Honorable Most Venerable and Righteous Samuel L. Constable, Jr. | 200 Main St. | Berkeley, CA 94718 This syntax is borrowed from [reStructuredText]. Lists ----- ### Bullet lists ### A bullet list is a list of bulleted list items. A bulleted list item begins with a bullet (`*`, `+`, or `-`). Here is a simple example: * one * two * three This will produce a "compact" list. If you want a "loose" list, in which each item is formatted as a paragraph, put spaces between the items: * one * two * three The bullets need not be flush with the left margin; they may be indented one, two, or three spaces. The bullet must be followed by whitespace. List items look best if subsequent lines are flush with the first line (after the bullet): * here is my first list item. * and my second. But markdown also allows a "lazy" format: * here is my first list item. * and my second. ### The four-space rule ### A list item may contain multiple paragraphs and other block-level content. However, subsequent paragraphs must be preceded by a blank line and indented four spaces or a tab. The list will look better if the first paragraph is aligned with the rest: * First paragraph. Continued. * Second paragraph. With a code block, which must be indented eight spaces: { code } List items may include other lists. In this case the preceding blank line is optional. The nested list must be indented four spaces or one tab: * fruits + apples - macintosh - red delicious + pears + peaches * vegetables + brocolli + chard As noted above, markdown allows you to write list items "lazily," instead of indenting continuation lines. However, if there are multiple paragraphs or other blocks in a list item, the first line of each must be indented. + A lazy, lazy, list item. + Another one; this looks bad but is legal. Second paragraph of second list item. **Note:** Although the four-space rule for continuation paragraphs comes from the official [markdown syntax guide], the reference implementation, `Markdown.pl`, does not follow it. So pandoc will give different results than `Markdown.pl` when authors have indented continuation paragraphs fewer than four spaces. The [markdown syntax guide] is not explicit whether the four-space rule applies to *all* block-level content in a list item; it only mentions paragraphs and code blocks. But it implies that the rule applies to all block-level content (including nested lists), and pandoc interprets it that way. [markdown syntax guide]: http://daringfireball.net/projects/markdown/syntax#list ### Ordered lists ### Ordered lists work just like bulleted lists, except that the items begin with enumerators rather than bullets. In standard markdown, enumerators are decimal numbers followed by a period and a space. The numbers themselves are ignored, so there is no difference between this list: 1. one 2. two 3. three and this one: 5. one 7. two 1. three **Extension: `fancy_lists`** Unlike standard markdown, Pandoc allows ordered list items to be marked with uppercase and lowercase letters and roman numerals, in addition to arabic numerals. List markers may be enclosed in parentheses or followed by a single right-parentheses or period. They must be separated from the text that follows by at least one space, and, if the list marker is a capital letter with a period, by at least two spaces.[^2] [^2]: The point of this rule is to ensure that normal paragraphs starting with people's initials, like B. Russell was an English philosopher. do not get treated as list items. This rule will not prevent (C) 2007 Joe Smith from being interpreted as a list item. In this case, a backslash escape can be used: (C\) 2007 Joe Smith The `fancy_lists` extension also allows '`#`' to be used as an ordered list marker in place of a numeral: #. one #. two **Extension: `startnum`** Pandoc also pays attention to the type of list marker used, and to the starting number, and both of these are preserved where possible in the output format. Thus, the following yields a list with numbers followed by a single parenthesis, starting with 9, and a sublist with lowercase roman numerals: 9) Ninth 10) Tenth 11) Eleventh i. subone ii. subtwo iii. subthree Pandoc will start a new list each time a different type of list marker is used. So, the following will create three lists: (2) Two (5) Three 1. Four * Five If default list markers are desired, use `#.`: #. one #. two #. three ### Definition lists ### **Extension: `definition_lists`** Pandoc supports definition lists, using a syntax inspired by [PHP Markdown Extra] and [reStructuredText]:[^3] Term 1 : Definition 1 Term 2 with *inline markup* : Definition 2 { some code, part of Definition 2 } Third paragraph of definition 2. Each term must fit on one line, which may optionally be followed by a blank line, and must be followed by one or more definitions. A definition begins with a colon or tilde, which may be indented one or two spaces. The body of the definition (including the first line, aside from the colon or tilde) should be indented four spaces. A term may have multiple definitions, and each definition may consist of one or more block elements (paragraph, code block, list, etc.), each indented four spaces or one tab stop. If you leave space after the definition (as in the example above), the blocks of the definitions will be considered paragraphs. In some output formats, this will mean greater spacing between term/definition pairs. For a compact definition list, do not leave space between the definition and the next term: Term 1 ~ Definition 1 Term 2 ~ Definition 2a ~ Definition 2b [^3]: I have also been influenced by the suggestions of [David Wheeler](http://www.justatheory.com/computers/markup/modest-markdown-proposal.html). [PHP Markdown Extra]: http://www.michelf.com/projects/php-markdown/extra/ ### Numbered example lists ### **Extension: `example_lists`** The special list marker `@` can be used for sequentially numbered examples. The first list item with a `@` marker will be numbered '1', the next '2', and so on, throughout the document. The numbered examples need not occur in a single list; each new list using `@` will take up where the last stopped. So, for example: (@) My first example will be numbered (1). (@) My second example will be numbered (2). Explanation of examples. (@) My third example will be numbered (3). Numbered examples can be labeled and referred to elsewhere in the document: (@good) This is a good example. As (@good) illustrates, ... The label can be any string of alphanumeric characters, underscores, or hyphens. ### Compact and loose lists ### Pandoc behaves differently from `Markdown.pl` on some "edge cases" involving lists. Consider this source: + First + Second: - Fee - Fie - Foe + Third Pandoc transforms this into a "compact list" (with no `

` tags around "First", "Second", or "Third"), while markdown puts `

` tags around "Second" and "Third" (but not "First"), because of the blank space around "Third". Pandoc follows a simple rule: if the text is followed by a blank line, it is treated as a paragraph. Since "Second" is followed by a list, and not a blank line, it isn't treated as a paragraph. The fact that the list is followed by a blank line is irrelevant. (Note: Pandoc works this way even when the `markdown_strict` format is specified. This behavior is consistent with the official markdown syntax description, even though it is different from that of `Markdown.pl`.) ### Ending a list ### What if you want to put an indented code block after a list? - item one - item two { my code block } Trouble! Here pandoc (like other markdown implementations) will treat `{ my code block }` as the second paragraph of item two, and not as a code block. To "cut off" the list after item two, you can insert some non-indented content, like an HTML comment, which won't produce visible output in any format: - item one - item two { my code block } You can use the same trick if you want two consecutive lists instead of one big list: 1. one 2. two 3. three 1. uno 2. dos 3. tres Horizontal rules ---------------- A line containing a row of three or more `*`, `-`, or `_` characters (optionally separated by spaces) produces a horizontal rule: * * * * --------------- Tables ------ Four kinds of tables may be used. The first three kinds presuppose the use of a fixed-width font, such as Courier. The fourth kind can be used with proportionally spaced fonts, as it does not require lining up columns. ### Simple tables **Extension: `simple_tables`, `table_captions`** Simple tables look like this: Right Left Center Default ------- ------ ---------- ------- 12 12 12 12 123 123 123 123 1 1 1 1 Table: Demonstration of simple table syntax. The headers and table rows must each fit on one line. Column alignments are determined by the position of the header text relative to the dashed line below it:[^4] - If the dashed line is flush with the header text on the right side but extends beyond it on the left, the column is right-aligned. - If the dashed line is flush with the header text on the left side but extends beyond it on the right, the column is left-aligned. - If the dashed line extends beyond the header text on both sides, the column is centered. - If the dashed line is flush with the header text on both sides, the default alignment is used (in most cases, this will be left). [^4]: This scheme is due to Michel Fortin, who proposed it on the [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html). The table must end with a blank line, or a line of dashes followed by a blank line. A caption may optionally be provided (as illustrated in the example above). A caption is a paragraph beginning with the string `Table:` (or just `:`), which will be stripped off. It may appear either before or after the table. The column headers may be omitted, provided a dashed line is used to end the table. For example: ------- ------ ---------- ------- 12 12 12 12 123 123 123 123 1 1 1 1 ------- ------ ---------- ------- When headers are omitted, column alignments are determined on the basis of the first line of the table body. So, in the tables above, the columns would be right, left, center, and right aligned, respectively. ### Multiline tables **Extension: `multiline_tables`, `table_captions`** Multiline tables allow headers and table rows to span multiple lines of text (but cells that span multiple columns or rows of the table are not supported). Here is an example: ------------------------------------------------------------- Centered Default Right Left Header Aligned Aligned Aligned ----------- ------- --------------- ------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. ------------------------------------------------------------- Table: Here's the caption. It, too, may span multiple lines. These work like simple tables, but with the following differences: - They must begin with a row of dashes, before the header text (unless the headers are omitted). - They must end with a row of dashes, then a blank line. - The rows must be separated by blank lines. In multiline tables, the table parser pays attention to the widths of the columns, and the writers try to reproduce these relative widths in the output. So, if you find that one of the columns is too narrow in the output, try widening it in the markdown source. Headers may be omitted in multiline tables as well as simple tables: ----------- ------- --------------- ------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. ----------- ------- --------------- ------------------------- : Here's a multiline table without headers. It is possible for a multiline table to have just one row, but the row should be followed by a blank line (and then the row of dashes that ends the table), or the table may be interpreted as a simple table. ### Grid tables **Extension: `grid_tables`, `table_captions`** Grid tables look like this: : Sample grid table. +---------------+---------------+--------------------+ | Fruit | Price | Advantages | +===============+===============+====================+ | Bananas | $1.34 | - built-in wrapper | | | | - bright color | +---------------+---------------+--------------------+ | Oranges | $2.10 | - cures scurvy | | | | - tasty | +---------------+---------------+--------------------+ The row of `=`s separates the header from the table body, and can be omitted for a headerless table. The cells of grid tables may contain arbitrary block elements (multiple paragraphs, code blocks, lists, etc.). Alignments are not supported, nor are cells that span multiple columns or rows. Grid tables can be created easily using [Emacs table mode]. [Emacs table mode]: http://table.sourceforge.net/ ### Pipe tables **Extension: `pipe_tables`, `table_captions`** Pipe tables look like this: | Right | Left | Default | Center | |------:|:-----|---------|:------:| | 12 | 12 | 12 | 12 | | 123 | 123 | 123 | 123 | | 1 | 1 | 1 | 1 | : Demonstration of simple table syntax. The syntax is [the same as in PHP markdown extra]. The beginning and ending pipe characters are optional, but pipes are required between all columns. The colons indicate column alignment as shown. The header can be omitted, but the horizontal line must still be included, as it defines column alignments. Since the pipes indicate column boundaries, columns need not be vertically aligned, as they are in the above example. So, this is a perfectly legal (though ugly) pipe table: fruit| price -----|-----: apple|2.05 pear|1.37 orange|3.09 The cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines. [the same as in PHP markdown extra]: http://michelf.ca/projects/php-markdown/extra/#table Note: Pandoc also recognizes pipe tables of the following form, as can produced by Emacs' orgtbl-mode: | One | Two | |-----+-------| | my | table | | is | nice | The difference is that `+` is used instead of `|`. Other orgtbl features are not supported. In particular, to get non-default column alignment, you'll need to add colons as above. Title block ----------- **Extension: `pandoc_title_block`** If the file begins with a title block % title % author(s) (separated by semicolons) % date it will be parsed as bibliographic information, not regular text. (It will be used, for example, in the title of standalone LaTeX or HTML output.) The block may contain just a title, a title and an author, or all three elements. If you want to include an author but no title, or a title and a date but no author, you need a blank line: % % Author % My title % % June 15, 2006 The title may occupy multiple lines, but continuation lines must begin with leading space, thus: % My title on multiple lines If a document has multiple authors, the authors may be put on separate lines with leading space, or separated by semicolons, or both. So, all of the following are equivalent: % Author One Author Two % Author One; Author Two % Author One; Author Two The date must fit on one line. All three metadata fields may contain standard inline formatting (italics, links, footnotes, etc.). Title blocks will always be parsed, but they will affect the output only when the `--standalone` (`-s`) option is chosen. In HTML output, titles will appear twice: once in the document head -- this is the title that will appear at the top of the window in a browser -- and once at the beginning of the document body. The title in the document head can have an optional prefix attached (`--title-prefix` or `-T` option). The title in the body appears as an H1 element with class "title", so it can be suppressed or reformatted with CSS. If a title prefix is specified with `-T` and no title block appears in the document, the title prefix will be used by itself as the HTML title. The man page writer extracts a title, man page section number, and other header and footer information from the title line. The title is assumed to be the first word on the title line, which may optionally end with a (single-digit) section number in parentheses. (There should be no space between the title and the parentheses.) Anything after this is assumed to be additional footer and header text. A single pipe character (`|`) should be used to separate the footer text from the header text. Thus, % PANDOC(1) will yield a man page with the title `PANDOC` and section 1. % PANDOC(1) Pandoc User Manuals will also have "Pandoc User Manuals" in the footer. % PANDOC(1) Pandoc User Manuals | Version 4.0 will also have "Version 4.0" in the header. YAML metadata block ------------------- **Extension: `yaml_metadata_block`** A YAML metadata block is a valid YAML object, delimited by a line of three hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots (`...`) at the bottom. A YAML metadata block may occur anywhere in the document, but if it is not at the beginning, it must be preceded by a blank line. Metadata will be taken from the fields of the YAML object and added to any existing document metadata. Metadata can contain lists and objects (nested arbitrarily), but all string scalars will be interpreted as markdown. Fields with names ending in an underscore will be ignored by pandoc. (They may be given a role by external processors.) A document may contain multiple metadata blocks. The metadata fields will be combined through a *left-biased union*: if two metadata blocks attempt to set the same field, the value from the first block will be taken. Note that YAML escaping rules must be followed. Thus, for example, if a title contains a colon, it must be quoted. The pipe character (`|`) can be used to begin an indented block that will be interpreted literally, without need for escaping. This form is necessary when the field contains blank lines: --- title: 'This is the title: it contains a colon' author: - name: Author One affiliation: University of Somewhere - name: Author Two affiliation: University of Nowhere tags: [nothing, nothingness] abstract: | This is the abstract. It consists of two paragraphs. ... Template variables will be set automatically from the metadata. Thus, for example, in writing HTML, the variable `abstract` will be set to the HTML equivalent of the markdown in the `abstract` field:

This is the abstract.

It consists of two paragraphs.

Backslash escapes ----------------- **Extension: `all_symbols_escapable`** Except inside a code block or inline code, any punctuation or space character preceded by a backslash will be treated literally, even if it would normally indicate formatting. Thus, for example, if one writes *\*hello\** one will get *hello* instead of hello This rule is easier to remember than standard markdown's rule, which allows only the following characters to be backslash-escaped: \`*_{}[]()>#+-.! (However, if the `markdown_strict` format is used, the standard markdown rule will be used.) A backslash-escaped space is parsed as a nonbreaking space. It will appear in TeX output as `~` and in HTML and XML as `\ ` or `\ `. A backslash-escaped newline (i.e. a backslash occurring at the end of a line) is parsed as a hard line break. It will appear in TeX output as `\\` and in HTML as `
`. This is a nice alternative to markdown's "invisible" way of indicating hard line breaks using two trailing spaces on a line. Backslash escapes do not work in verbatim contexts. Smart punctuation ----------------- **Extension** If the `--smart` option is specified, pandoc will produce typographically correct output, converting straight quotes to curly quotes, `---` to em-dashes, `--` to en-dashes, and `...` to ellipses. Nonbreaking spaces are inserted after certain abbreviations, such as "Mr." Note: if your LaTeX template uses the `csquotes` package, pandoc will detect automatically this and use `\enquote{...}` for quoted text. Inline formatting ----------------- ### Emphasis ### To *emphasize* some text, surround it with `*`s or `_`, like this: This text is _emphasized with underscores_, and this is *emphasized with asterisks*. Double `*` or `_` produces **strong emphasis**: This is **strong emphasis** and __with underscores__. A `*` or `_` character surrounded by spaces, or backslash-escaped, will not trigger emphasis: This is * not emphasized *, and \*neither is this\*. **Extension: `intraword_underscores`** Because `_` is sometimes used inside words and identifiers, pandoc does not interpret a `_` surrounded by alphanumeric characters as an emphasis marker. If you want to emphasize just part of a word, use `*`: feas*ible*, not feas*able*. ### Strikeout ### **Extension: `strikeout`** To strikeout a section of text with a horizontal line, begin and end it with `~~`. Thus, for example, This ~~is deleted text.~~ ### Superscripts and subscripts ### **Extension: `superscript`, `subscript`** Superscripts may be written by surrounding the superscripted text by `^` characters; subscripts may be written by surrounding the subscripted text by `~` characters. Thus, for example, H~2~O is a liquid. 2^10^ is 1024. If the superscripted or subscripted text contains spaces, these spaces must be escaped with backslashes. (This is to prevent accidental superscripting and subscripting through the ordinary use of `~` and `^`.) Thus, if you want the letter P with 'a cat' in subscripts, use `P~a\ cat~`, not `P~a cat~`. ### Verbatim ### To make a short span of text verbatim, put it inside backticks: What is the difference between `>>=` and `>>`? If the verbatim text includes a backtick, use double backticks: Here is a literal backtick `` ` ``. (The spaces after the opening backticks and before the closing backticks will be ignored.) The general rule is that a verbatim span starts with a string of consecutive backticks (optionally followed by a space) and ends with a string of the same number of backticks (optionally preceded by a space). Note that backslash-escapes (and other markdown constructs) do not work in verbatim contexts: This is a backslash followed by an asterisk: `\*`. **Extension: `inline_code_attributes`** Attributes can be attached to verbatim text, just as with [fenced code blocks](#fenced-code-blocks): `<$>`{.haskell} Math ---- **Extension: `tex_math_dollars`** Anything between two `$` characters will be treated as TeX math. The opening `$` must have a character immediately to its right, while the closing `$` must have a character immediately to its left. Thus, `$20,000 and $30,000` won't parse as math. If for some reason you need to enclose text in literal `$` characters, backslash-escape them and they won't be treated as math delimiters. TeX math will be printed in all output formats. How it is rendered depends on the output format: Markdown, LaTeX, Org-Mode, ConTeXt ~ It will appear verbatim between `$` characters. reStructuredText ~ It will be rendered using an interpreted text role `:math:`, as described [here](http://www.american.edu/econ/itex2mml/mathhack.rst). AsciiDoc ~ It will be rendered as `latexmath:[...]`. Texinfo ~ It will be rendered inside a `@math` command. groff man ~ It will be rendered verbatim without `$`'s. MediaWiki ~ It will be rendered inside `` tags. Textile ~ It will be rendered inside `` tags. RTF, OpenDocument, ODT ~ It will be rendered, if possible, using unicode characters, and will otherwise appear verbatim. Docbook ~ If the `--mathml` flag is used, it will be rendered using mathml in an `inlineequation` or `informalequation` tag. Otherwise it will be rendered, if possible, using unicode characters. Docx ~ It will be rendered using OMML math markup. FictionBook2 ~ If the `--webtex` option is used, formulas are rendered as images using Google Charts or other compatible web service, downloaded and embedded in the e-book. Otherwise, they will appear verbatim. HTML, Slidy, DZSlides, S5, EPUB ~ The way math is rendered in HTML will depend on the command-line options selected: 1. The default is to render TeX math as far as possible using unicode characters, as with RTF, DocBook, and OpenDocument output. Formulas are put inside a `span` with `class="math"`, so that they may be styled differently from the surrounding text if needed. 2. If the `--latexmathml` option is used, TeX math will be displayed between `$` or `$$` characters and put in `` tags with class `LaTeX`. The [LaTeXMathML] script will be used to render it as formulas. (This trick does not work in all browsers, but it works in Firefox. In browsers that do not support LaTeXMathML, TeX math will appear verbatim between `$` characters.) 3. If the `--jsmath` option is used, TeX math will be put inside `` tags (for inline math) or `
` tags (for display math) with class `math`. The [jsMath] script will be used to render it. 4. If the `--mimetex` option is used, the [mimeTeX] CGI script will be called to generate images for each TeX formula. This should work in all browsers. The `--mimetex` option takes an optional URL as argument. If no URL is specified, it will be assumed that the mimeTeX CGI script is at `/cgi-bin/mimetex.cgi`. 5. If the `--gladtex` option is used, TeX formulas will be enclosed in `` tags in the HTML output. The resulting `htex` file may then be processed by [gladTeX], which will produce image files for each formula and an `html` file with links to these images. So, the procedure is: pandoc -s --gladtex myfile.txt -o myfile.htex gladtex -d myfile-images myfile.htex # produces myfile.html and images in myfile-images 6. If the `--webtex` option is used, TeX formulas will be converted to `` tags that link to an external script that converts formulas to images. The formula will be URL-encoded and concatenated with the URL provided. If no URL is specified, the Google Chart API will be used (`http://chart.apis.google.com/chart?cht=tx&chl=`). 7. If the `--mathjax` option is used, TeX math will be displayed between `\(...\)` (for inline math) or `\[...\]` (for display math) and put in `` tags with class `math`. The [MathJax] script will be used to render it as formulas. Raw HTML -------- **Extension: `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 markdown allows it, but it has been made an extension so that it can be disabled if desired.) The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous, DZSlides, EPUB, Markdown, and Textile output, and suppressed in other formats. **Extension: `markdown_in_html_blocks`** Standard markdown allows you to include HTML "blocks": blocks of HTML between balanced tags that are separated from the surrounding text with blank lines, and start and end at the left margin. Within these blocks, everything is interpreted as HTML, not markdown; so (for example), `*` does not signify emphasis. Pandoc behaves this way when the `markdown_strict` format is used; but by default, pandoc interprets material between HTML block tags as markdown. Thus, for example, Pandoc will turn
*one* [a link](http://google.com)
into
one a link
whereas `Markdown.pl` will preserve it as is. There is one exception to this rule: text between `

My S5 Document

Sam Smith
Jen Jones

July 15, 2006

First slide

  • first bullet
  • second bullet

Math

  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
pandoc-1.12.2.1/tests/s5.fancy.html000644 000765 000024 00000224116 12251233602 016600 0ustar00jgmstaff000000 000000 My S5 Document

My S5 Document

Sam Smith
Jen Jones

July 15, 2006

First slide

  • first bullet
  • second bullet

Math

  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
pandoc-1.12.2.1/tests/s5.fragment.html000644 000765 000024 00000000332 12251233602 017273 0ustar00jgmstaff000000 000000

First slide

  • first bullet
  • second bullet

Math

  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
pandoc-1.12.2.1/tests/s5.inserts.html000644 000765 000024 00000002112 12251233602 017155 0ustar00jgmstaff000000 000000 My S5 Document STUFF INSERTED STUFF INSERTED

First slide

  • first bullet
  • second bullet

Math

  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
STUFF INSERTED pandoc-1.12.2.1/tests/s5.native000644 000765 000024 00000001104 12251233602 016011 0ustar00jgmstaff000000 000000 Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Sam",Space,Str "Smith"],MetaInlines [Str "Jen",Space,Str "Jones"]]),("date",MetaInlines [Str "July",Space,Str "15,",Space,Str "2006"]),("title",MetaInlines [Str "My",Space,Str "S5",Space,Str "Document"])]}) [Header 1 ("first-slide",[],[]) [Str "First",Space,Str "slide"] ,BulletList [[Plain [Str "first",Space,Str "bullet"]] ,[Plain [Str "second",Space,Str "bullet"]]] ,Header 1 ("math",[],[]) [Str "Math"] ,BulletList [[Plain [Math InlineMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]]]] pandoc-1.12.2.1/tests/tables-rstsubset.native000644 000765 000024 00000011274 12251233602 021001 0ustar00jgmstaff000000 000000 [Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.125,0.1125,0.1375,0.15] [[Plain [Str "Right"]] ,[Plain [Str "Left"]] ,[Plain [Str "Center"]] ,[Plain [Str "Default"]]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Table:",Space,Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.125,0.1125,0.1375,0.15] [[Plain [Str "Right"]] ,[Plain [Str "Left"]] ,[Plain [Str "Center"]] ,[Plain [Str "Default"]]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.125,0.1125,0.1375,0.15] [[Plain [Str "Right"]] ,[Plain [Str "Left"]] ,[Plain [Str "Center"]] ,[Plain [Str "Default"]]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Table:",Space,Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.175,0.1625,0.1875,0.3625] [[Plain [Str "Centered",Space,Str "Header"]] ,[Plain [Str "Left",Space,Str "Aligned"]] ,[Plain [Str "Right",Space,Str "Aligned"]] ,[Plain [Str "Default",Space,Str "aligned"]]] [[[Plain [Str "First"]] ,[Plain [Str "row"]] ,[Plain [Str "12.0"]] ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] ,[[Plain [Str "Second"]] ,[Plain [Str "row"]] ,[Plain [Str "5.0"]] ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] ,Para [Str "Table:",Space,Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.175,0.1625,0.1875,0.3625] [[Plain [Str "Centered",Space,Str "Header"]] ,[Plain [Str "Left",Space,Str "Aligned"]] ,[Plain [Str "Right",Space,Str "Aligned"]] ,[Plain [Str "Default",Space,Str "aligned"]]] [[[Plain [Str "First"]] ,[Plain [Str "row"]] ,[Plain [Str "12.0"]] ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] ,[[Plain [Str "Second"]] ,[Plain [Str "row"]] ,[Plain [Str "5.0"]] ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1,0.1,0.1,0.1] [[] ,[] ,[] ,[]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"] ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.175,0.1625,0.1875,0.3625] [[] ,[] ,[] ,[]] [[[Plain [Str "First"]] ,[Plain [Str "row"]] ,[Plain [Str "12.0"]] ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] ,[[Plain [Str "Second"]] ,[Plain [Str "row"]] ,[Plain [Str "5.0"]] ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]] pandoc-1.12.2.1/tests/tables.asciidoc000644 000765 000024 00000004313 12251233602 017231 0ustar00jgmstaff000000 000000 Simple table with caption: .Demonstration of simple table syntax. [cols=">,<,^,",options="header",] |============================ |Right |Left |Center |Default |12 |12 |12 |12 |123 |123 |123 |123 |1 |1 |1 |1 |============================ Simple table without caption: [cols=">,<,^,",options="header",] |============================ |Right |Left |Center |Default |12 |12 |12 |12 |123 |123 |123 |123 |1 |1 |1 |1 |============================ Simple table indented two spaces: .Demonstration of simple table syntax. [cols=">,<,^,",options="header",] |============================ |Right |Left |Center |Default |12 |12 |12 |12 |123 |123 |123 |123 |1 |1 |1 |1 |============================ Multiline table with caption: .Here's the caption. It may span multiple lines. [width="78%",cols="^21%,<17%,>20%,<42%",options="header",] |======================================================================= |Centered Header |Left Aligned |Right Aligned |Default aligned |First |row |12.0 |Example of a row that spans multiple lines. |Second |row |5.0 |Here's another one. Note the blank line between rows. |======================================================================= Multiline table without caption: [width="78%",cols="^21%,<17%,>20%,<42%",options="header",] |======================================================================= |Centered Header |Left Aligned |Right Aligned |Default aligned |First |row |12.0 |Example of a row that spans multiple lines. |Second |row |5.0 |Here's another one. Note the blank line between rows. |======================================================================= Table without column headers: [cols=">,<,^,>",] |============================================================================= |12 |12 |12 |12 |123 |123 |123 |123 |1 |1 |1 |1 |============================================================================= Multiline table without column headers: [width="78%",cols="^21%,<17%,>20%,42%",] |============================================================================= |First |row |12.0 |Example of a row that spans multiple lines. |Second |row |5.0 |Here's another one. Note the blank line between rows. |============================================================================= pandoc-1.12.2.1/tests/tables.context000644 000765 000024 00000004313 12251233602 017137 0ustar00jgmstaff000000 000000 Simple table with caption: \placetable{Demonstration of simple table syntax.} \starttable[|r|l|c|l|] \HL \NC Right \NC Left \NC Center \NC Default \NC\AR \HL \NC 12 \NC 12 \NC 12 \NC 12 \NC\AR \NC 123 \NC 123 \NC 123 \NC 123 \NC\AR \NC 1 \NC 1 \NC 1 \NC 1 \NC\AR \HL \stoptable Simple table without caption: \placetable[none]{} \starttable[|r|l|c|l|] \HL \NC Right \NC Left \NC Center \NC Default \NC\AR \HL \NC 12 \NC 12 \NC 12 \NC 12 \NC\AR \NC 123 \NC 123 \NC 123 \NC 123 \NC\AR \NC 1 \NC 1 \NC 1 \NC 1 \NC\AR \HL \stoptable Simple table indented two spaces: \placetable{Demonstration of simple table syntax.} \starttable[|r|l|c|l|] \HL \NC Right \NC Left \NC Center \NC Default \NC\AR \HL \NC 12 \NC 12 \NC 12 \NC 12 \NC\AR \NC 123 \NC 123 \NC 123 \NC 123 \NC\AR \NC 1 \NC 1 \NC 1 \NC 1 \NC\AR \HL \stoptable Multiline table with caption: \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 \NC Left Aligned \NC Right Aligned \NC Default aligned \NC\AR \HL \NC First \NC row \NC 12.0 \NC Example of a row that spans multiple lines. \NC\AR \NC Second \NC row \NC 5.0 \NC Here's another one. Note the blank line between rows. \NC\AR \HL \stoptable Multiline table without caption: \placetable[none]{} \starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|] \HL \NC Centered Header \NC Left Aligned \NC Right Aligned \NC Default aligned \NC\AR \HL \NC First \NC row \NC 12.0 \NC Example of a row that spans multiple lines. \NC\AR \NC Second \NC row \NC 5.0 \NC Here's another one. Note the blank line between rows. \NC\AR \HL \stoptable Table without column headers: \placetable[none]{} \starttable[|r|l|c|r|] \HL \NC 12 \NC 12 \NC 12 \NC 12 \NC\AR \NC 123 \NC 123 \NC 123 \NC 123 \NC\AR \NC 1 \NC 1 \NC 1 \NC 1 \NC\AR \HL \stoptable Multiline table without column headers: \placetable[none]{} \starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|] \HL \NC First \NC row \NC 12.0 \NC Example of a row that spans multiple lines. \NC\AR \NC Second \NC row \NC 5.0 \NC Here's another one. Note the blank line between rows. \NC\AR \HL \stoptable pandoc-1.12.2.1/tests/tables.docbook000644 000765 000024 00000016536 12251233602 017105 0ustar00jgmstaff000000 000000 Simple table with caption: Demonstration of simple table syntax. Right Left Center Default 12 12 12 12 123 123 123 123 1 1 1 1
Simple table without caption: Right Left Center Default 12 12 12 12 123 123 123 123 1 1 1 1 Simple table indented two spaces: Demonstration of simple table syntax. Right Left Center Default 12 12 12 12 123 123 123 123 1 1 1 1
Multiline table with caption: Here's the caption. It may span multiple lines. Centered Header Left Aligned Right Aligned Default aligned First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows.
Multiline table without caption: Centered Header Left Aligned Right Aligned Default aligned First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. Table without column headers: 12 12 12 12 123 123 123 123 1 1 1 1 Multiline table without column headers: First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. pandoc-1.12.2.1/tests/tables.fb2000644 000765 000024 00000010037 12251233602 016124 0ustar00jgmstaff000000 000000 pandoc<p />

Simple table with caption:

RightLeftCenterDefault
12121212
123123123123
1111

Demonstration of simple table syntax.

Simple table without caption:

RightLeftCenterDefault
12121212
123123123123
1111

Simple table indented two spaces:

RightLeftCenterDefault
12121212
123123123123
1111

Demonstration of simple table syntax.

Multiline table with caption:

Centered HeaderLeft AlignedRight AlignedDefault aligned
Firstrow12.0Example of a row that spans multiple lines.
Secondrow5.0Here's another one. Note the blank line between rows.

Here's the caption. It may span multiple lines.

Multiline table without caption:

Centered HeaderLeft AlignedRight AlignedDefault aligned
Firstrow12.0Example of a row that spans multiple lines.
Secondrow5.0Here's another one. Note the blank line between rows.

Table without column headers:

12121212
123123123123
1111

Multiline table without column headers:

Firstrow12.0Example of a row that spans multiple lines.
Secondrow5.0Here's another one. Note the blank line between rows.

pandoc-1.12.2.1/tests/tables.html000644 000765 000024 00000010444 12251233602 016421 0ustar00jgmstaff000000 000000

Simple table with caption:

Demonstration of simple table syntax.
Right Left Center Default
12 12 12 12
123 123 123 123
1 1 1 1

Simple table without caption:

Right Left Center Default
12 12 12 12
123 123 123 123
1 1 1 1

Simple table indented two spaces:

Demonstration of simple table syntax.
Right Left Center Default
12 12 12 12
123 123 123 123
1 1 1 1

Multiline table with caption:

Here's the caption. It may span multiple lines.
Centered Header Left Aligned Right Aligned Default aligned
First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here's another one. Note the blank line between rows.

Multiline table without caption:

Centered Header Left Aligned Right Aligned Default aligned
First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here's another one. Note the blank line between rows.

Table without column headers:

12 12 12 12
123 123 123 123
1 1 1 1

Multiline table without column headers:

First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here's another one. Note the blank line between rows.
pandoc-1.12.2.1/tests/tables.latex000644 000765 000024 00000010441 12251233602 016567 0ustar00jgmstaff000000 000000 Simple table with caption: \begin{longtable}[c]{@{}rlcl@{}} \toprule\addlinespace Right & Left & Center & Default \\\addlinespace \midrule\endhead 12 & 12 & 12 & 12 \\\addlinespace 123 & 123 & 123 & 123 \\\addlinespace 1 & 1 & 1 & 1 \\\addlinespace \bottomrule \addlinespace \caption{Demonstration of simple table syntax.} \end{longtable} Simple table without caption: \begin{longtable}[c]{@{}rlcl@{}} \toprule\addlinespace Right & Left & Center & Default \\\addlinespace \midrule\endhead 12 & 12 & 12 & 12 \\\addlinespace 123 & 123 & 123 & 123 \\\addlinespace 1 & 1 & 1 & 1 \\\addlinespace \bottomrule \end{longtable} Simple table indented two spaces: \begin{longtable}[c]{@{}rlcl@{}} \toprule\addlinespace Right & Left & Center & Default \\\addlinespace \midrule\endhead 12 & 12 & 12 & 12 \\\addlinespace 123 & 123 & 123 & 123 \\\addlinespace 1 & 1 & 1 & 1 \\\addlinespace \bottomrule \addlinespace \caption{Demonstration of simple table syntax.} \end{longtable} Multiline table with caption: \begin{longtable}[c]{@{}clrl@{}} \toprule\addlinespace \begin{minipage}[b]{0.13\columnwidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright Left Aligned \end{minipage} & \begin{minipage}[b]{0.14\columnwidth}\raggedleft Right Aligned \end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright Default aligned \end{minipage} \\\addlinespace \midrule\endhead \begin{minipage}[t]{0.13\columnwidth}\centering First \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright row \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft 12.0 \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Example of a row that spans multiple lines. \end{minipage} \\\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering Second \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright row \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft 5.0 \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Here's another one. Note the blank line between rows. \end{minipage} \\\addlinespace \bottomrule \addlinespace \caption{Here's the caption. It may span multiple lines.} \end{longtable} Multiline table without caption: \begin{longtable}[c]{@{}clrl@{}} \toprule\addlinespace \begin{minipage}[b]{0.13\columnwidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright Left Aligned \end{minipage} & \begin{minipage}[b]{0.14\columnwidth}\raggedleft Right Aligned \end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright Default aligned \end{minipage} \\\addlinespace \midrule\endhead \begin{minipage}[t]{0.13\columnwidth}\centering First \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright row \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft 12.0 \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Example of a row that spans multiple lines. \end{minipage} \\\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering Second \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright row \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft 5.0 \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Here's another one. Note the blank line between rows. \end{minipage} \\\addlinespace \bottomrule \end{longtable} Table without column headers: \begin{longtable}[c]{@{}rlcr@{}} \toprule\addlinespace 12 & 12 & 12 & 12 \\\addlinespace 123 & 123 & 123 & 123 \\\addlinespace 1 & 1 & 1 & 1 \\\addlinespace \bottomrule \end{longtable} Multiline table without column headers: \begin{longtable}[c]{@{}clrl@{}} \toprule\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering First \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright row \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft 12.0 \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Example of a row that spans multiple lines. \end{minipage} \\\addlinespace \begin{minipage}[t]{0.13\columnwidth}\centering Second \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright row \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft 5.0 \end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright Here's another one. Note the blank line between rows. \end{minipage} \\\addlinespace \bottomrule \end{longtable} pandoc-1.12.2.1/tests/tables.man000644 000765 000024 00000003666 12251233602 016240 0ustar00jgmstaff000000 000000 .PP Simple table with caption: .PP Demonstration of simple table syntax. .TS tab(@); r l c l. T{ Right T}@T{ Left T}@T{ Center T}@T{ Default T} _ T{ 12 T}@T{ 12 T}@T{ 12 T}@T{ 12 T} T{ 123 T}@T{ 123 T}@T{ 123 T}@T{ 123 T} T{ 1 T}@T{ 1 T}@T{ 1 T}@T{ 1 T} .TE .PP Simple table without caption: .PP .TS tab(@); r l c l. T{ Right T}@T{ Left T}@T{ Center T}@T{ Default T} _ T{ 12 T}@T{ 12 T}@T{ 12 T}@T{ 12 T} T{ 123 T}@T{ 123 T}@T{ 123 T}@T{ 123 T} T{ 1 T}@T{ 1 T}@T{ 1 T}@T{ 1 T} .TE .PP Simple table indented two spaces: .PP Demonstration of simple table syntax. .TS tab(@); r l c l. T{ Right T}@T{ Left T}@T{ Center T}@T{ Default T} _ T{ 12 T}@T{ 12 T}@T{ 12 T}@T{ 12 T} T{ 123 T}@T{ 123 T}@T{ 123 T}@T{ 123 T} T{ 1 T}@T{ 1 T}@T{ 1 T}@T{ 1 T} .TE .PP Multiline table with caption: .PP Here\[aq]s the caption. It may span multiple lines. .TS tab(@); cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n). T{ Centered Header T}@T{ Left Aligned T}@T{ Right Aligned T}@T{ Default aligned T} _ T{ First T}@T{ row T}@T{ 12.0 T}@T{ Example of a row that spans multiple lines. T} T{ Second T}@T{ row T}@T{ 5.0 T}@T{ Here\[aq]s another one. Note the blank line between rows. T} .TE .PP Multiline table without caption: .PP .TS tab(@); cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n). T{ Centered Header T}@T{ Left Aligned T}@T{ Right Aligned T}@T{ Default aligned T} _ T{ First T}@T{ row T}@T{ 12.0 T}@T{ Example of a row that spans multiple lines. T} T{ Second T}@T{ row T}@T{ 5.0 T}@T{ Here\[aq]s another one. Note the blank line between rows. T} .TE .PP Table without column headers: .PP .TS tab(@); r l c r. T{ 12 T}@T{ 12 T}@T{ 12 T}@T{ 12 T} T{ 123 T}@T{ 123 T}@T{ 123 T}@T{ 123 T} T{ 1 T}@T{ 1 T}@T{ 1 T}@T{ 1 T} .TE .PP Multiline table without column headers: .PP .TS tab(@); cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n). T{ First T}@T{ row T}@T{ 12.0 T}@T{ Example of a row that spans multiple lines. T} T{ Second T}@T{ row T}@T{ 5.0 T}@T{ Here\[aq]s another one. Note the blank line between rows. T} .TE pandoc-1.12.2.1/tests/tables.markdown000644 000765 000024 00000004770 12251233602 017304 0ustar00jgmstaff000000 000000 Simple table with caption: Right Left Center Default ------- ------ -------- --------- 12 12 12 12 123 123 123 123 1 1 1 1 : Demonstration of simple table syntax. Simple table without caption: Right Left Center Default ------- ------ -------- --------- 12 12 12 12 123 123 123 123 1 1 1 1 Simple table indented two spaces: Right Left Center Default ------- ------ -------- --------- 12 12 12 12 123 123 123 123 1 1 1 1 : Demonstration of simple table syntax. Multiline table with caption: -------------------------------------------------------------- Centered Left Right Default aligned Header Aligned Aligned ----------- ---------- ------------ -------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. -------------------------------------------------------------- : Here's the caption. It may span multiple lines. Multiline table without caption: -------------------------------------------------------------- Centered Left Right Default aligned Header Aligned Aligned ----------- ---------- ------------ -------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. -------------------------------------------------------------- Table without column headers: ----- ----- ----- ----- 12 12 12 12 123 123 123 123 1 1 1 1 ----- ----- ----- ----- Multiline table without column headers: ----------- ---------- ------------ -------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. ----------- ---------- ------------ -------------------------- pandoc-1.12.2.1/tests/tables.mediawiki000644 000765 000024 00000004122 12251233602 017414 0ustar00jgmstaff000000 000000 Simple table with caption: {| |+ Demonstration of simple table syntax. !align="right"|Right !Left !align="center"|Center !Default |- |align="right"|12 |12 |align="center"|12 |12 |- |align="right"|123 |123 |align="center"|123 |123 |- |align="right"|1 |1 |align="center"|1 |1 |} Simple table without caption: {| !align="right"|Right !Left !align="center"|Center !Default |- |align="right"|12 |12 |align="center"|12 |12 |- |align="right"|123 |123 |align="center"|123 |123 |- |align="right"|1 |1 |align="center"|1 |1 |} Simple table indented two spaces: {| |+ Demonstration of simple table syntax. !align="right"|Right !Left !align="center"|Center !Default |- |align="right"|12 |12 |align="center"|12 |12 |- |align="right"|123 |123 |align="center"|123 |123 |- |align="right"|1 |1 |align="center"|1 |1 |} Multiline table with caption: {| |+ Here's the caption. It may span multiple lines. !align="center" width="15%"|Centered Header !width="13%"|Left Aligned !align="right" width="16%"|Right Aligned !width="33%"|Default aligned |- |align="center"|First |row |align="right"|12.0 |Example of a row that spans multiple lines. |- |align="center"|Second |row |align="right"|5.0 |Here's another one. Note the blank line between rows. |} Multiline table without caption: {| !align="center" width="15%"|Centered Header !width="13%"|Left Aligned !align="right" width="16%"|Right Aligned !width="33%"|Default aligned |- |align="center"|First |row |align="right"|12.0 |Example of a row that spans multiple lines. |- |align="center"|Second |row |align="right"|5.0 |Here's another one. Note the blank line between rows. |} Table without column headers: {| |align="right"|12 |12 |align="center"|12 |align="right"|12 |- |align="right"|123 |123 |align="center"|123 |align="right"|123 |- |align="right"|1 |1 |align="center"|1 |align="right"|1 |} Multiline table without column headers: {| |align="center" width="15%"|First |width="13%"|row |align="right" width="16%"|12.0 |width="33%"|Example of a row that spans multiple lines. |- |align="center"|Second |row |align="right"|5.0 |Here's another one. Note the blank line between rows. |} pandoc-1.12.2.1/tests/tables.native000644 000765 000024 00000011030 12251233602 016733 0ustar00jgmstaff000000 000000 [Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"] ,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0] [[Plain [Str "Right"]] ,[Plain [Str "Left"]] ,[Plain [Str "Center"]] ,[Plain [Str "Default"]]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"] ,Table [] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0] [[Plain [Str "Right"]] ,[Plain [Str "Left"]] ,[Plain [Str "Center"]] ,[Plain [Str "Default"]]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"] ,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0] [[Plain [Str "Right"]] ,[Plain [Str "Left"]] ,[Plain [Str "Center"]] ,[Plain [Str "Default"]]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"] ,Table [Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375] [[Plain [Str "Centered",Space,Str "Header"]] ,[Plain [Str "Left",Space,Str "Aligned"]] ,[Plain [Str "Right",Space,Str "Aligned"]] ,[Plain [Str "Default",Space,Str "aligned"]]] [[[Plain [Str "First"]] ,[Plain [Str "row"]] ,[Plain [Str "12.0"]] ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] ,[[Plain [Str "Second"]] ,[Plain [Str "row"]] ,[Plain [Str "5.0"]] ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"] ,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375] [[Plain [Str "Centered",Space,Str "Header"]] ,[Plain [Str "Left",Space,Str "Aligned"]] ,[Plain [Str "Right",Space,Str "Aligned"]] ,[Plain [Str "Default",Space,Str "aligned"]]] [[[Plain [Str "First"]] ,[Plain [Str "row"]] ,[Plain [Str "12.0"]] ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] ,[[Plain [Str "Second"]] ,[Plain [Str "row"]] ,[Plain [Str "5.0"]] ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"] ,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0] [[] ,[] ,[] ,[]] [[[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]] ,[Plain [Str "12"]]] ,[[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]] ,[Plain [Str "123"]]] ,[[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]] ,[Plain [Str "1"]]]] ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"] ,Table [] [AlignCenter,AlignLeft,AlignRight,AlignDefault] [0.15,0.1375,0.1625,0.3375] [[] ,[] ,[] ,[]] [[[Plain [Str "First"]] ,[Plain [Str "row"]] ,[Plain [Str "12.0"]] ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] ,[[Plain [Str "Second"]] ,[Plain [Str "row"]] ,[Plain [Str "5.0"]] ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]] pandoc-1.12.2.1/tests/tables.opendocument000644 000765 000024 00000045351 12251233602 020162 0ustar00jgmstaff000000 000000 Simple table with caption: Right Left Center Default 12 12 12 12 123 123 123 123 1 1 1 1 Demonstration of simple table syntax. Simple table without caption: Right Left Center Default 12 12 12 12 123 123 123 123 1 1 1 1 Simple table indented two spaces: Right Left Center Default 12 12 12 12 123 123 123 123 1 1 1 1 Demonstration of simple table syntax. Multiline table with caption: Centered Header Left Aligned Right Aligned Default aligned First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. Here's the caption. It may span multiple lines. Multiline table without caption: Centered Header Left Aligned Right Aligned Default aligned First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. Table without column headers: 12 12 12 12 123 123 123 123 1 1 1 1 Multiline table without column headers: First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. pandoc-1.12.2.1/tests/tables.org000644 000765 000024 00000004315 12251233602 016244 0ustar00jgmstaff000000 000000 Simple table with caption: | Right | Left | Center | Default | |---------+--------+----------+-----------| | 12 | 12 | 12 | 12 | | 123 | 123 | 123 | 123 | | 1 | 1 | 1 | 1 | #+CAPTION: Demonstration of simple table syntax. Simple table without caption: | Right | Left | Center | Default | |---------+--------+----------+-----------| | 12 | 12 | 12 | 12 | | 123 | 123 | 123 | 123 | | 1 | 1 | 1 | 1 | Simple table indented two spaces: | Right | Left | Center | Default | |---------+--------+----------+-----------| | 12 | 12 | 12 | 12 | | 123 | 123 | 123 | 123 | | 1 | 1 | 1 | 1 | #+CAPTION: Demonstration of simple table syntax. Multiline table with caption: | Centered Header | Left Aligned | Right Aligned | Default aligned | |-------------------+----------------+-----------------+---------------------------------------------------------| | First | row | 12.0 | Example of a row that spans multiple lines. | | Second | row | 5.0 | Here's another one. Note the blank line between rows. | #+CAPTION: Here's the caption. It may span multiple lines. Multiline table without caption: | Centered Header | Left Aligned | Right Aligned | Default aligned | |-------------------+----------------+-----------------+---------------------------------------------------------| | First | row | 12.0 | Example of a row that spans multiple lines. | | Second | row | 5.0 | Here's another one. Note the blank line between rows. | Table without column headers: | 12 | 12 | 12 | 12 | | 123 | 123 | 123 | 123 | | 1 | 1 | 1 | 1 | Multiline table without column headers: | First | row | 12.0 | Example of a row that spans multiple lines. | | Second | row | 5.0 | Here's another one. Note the blank line between rows. | pandoc-1.12.2.1/tests/tables.plain000644 000765 000024 00000004770 12251233602 016565 0ustar00jgmstaff000000 000000 Simple table with caption: Right Left Center Default ------- ------ -------- --------- 12 12 12 12 123 123 123 123 1 1 1 1 : Demonstration of simple table syntax. Simple table without caption: Right Left Center Default ------- ------ -------- --------- 12 12 12 12 123 123 123 123 1 1 1 1 Simple table indented two spaces: Right Left Center Default ------- ------ -------- --------- 12 12 12 12 123 123 123 123 1 1 1 1 : Demonstration of simple table syntax. Multiline table with caption: -------------------------------------------------------------- Centered Left Right Default aligned Header Aligned Aligned ----------- ---------- ------------ -------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. -------------------------------------------------------------- : Here's the caption. It may span multiple lines. Multiline table without caption: -------------------------------------------------------------- Centered Left Right Default aligned Header Aligned Aligned ----------- ---------- ------------ -------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. -------------------------------------------------------------- Table without column headers: ----- ----- ----- ----- 12 12 12 12 123 123 123 123 1 1 1 1 ----- ----- ----- ----- Multiline table without column headers: ----------- ---------- ------------ -------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. ----------- ---------- ------------ -------------------------- pandoc-1.12.2.1/tests/tables.rst000644 000765 000024 00000007642 12251233602 016273 0ustar00jgmstaff000000 000000 Simple table with caption: +---------+--------+----------+-----------+ | Right | Left | Center | Default | +=========+========+==========+===========+ | 12 | 12 | 12 | 12 | +---------+--------+----------+-----------+ | 123 | 123 | 123 | 123 | +---------+--------+----------+-----------+ | 1 | 1 | 1 | 1 | +---------+--------+----------+-----------+ Table: Demonstration of simple table syntax. Simple table without caption: +---------+--------+----------+-----------+ | Right | Left | Center | Default | +=========+========+==========+===========+ | 12 | 12 | 12 | 12 | +---------+--------+----------+-----------+ | 123 | 123 | 123 | 123 | +---------+--------+----------+-----------+ | 1 | 1 | 1 | 1 | +---------+--------+----------+-----------+ Simple table indented two spaces: +---------+--------+----------+-----------+ | Right | Left | Center | Default | +=========+========+==========+===========+ | 12 | 12 | 12 | 12 | +---------+--------+----------+-----------+ | 123 | 123 | 123 | 123 | +---------+--------+----------+-----------+ | 1 | 1 | 1 | 1 | +---------+--------+----------+-----------+ Table: Demonstration of simple table syntax. Multiline table with caption: +-------------+------------+--------------+----------------------------+ | Centered | Left | Right | Default aligned | | Header | Aligned | Aligned | | +=============+============+==============+============================+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-------------+------------+--------------+----------------------------+ | Second | row | 5.0 | Here's another one. Note | | | | | the blank line between | | | | | rows. | +-------------+------------+--------------+----------------------------+ Table: Here's the caption. It may span multiple lines. Multiline table without caption: +-------------+------------+--------------+----------------------------+ | Centered | Left | Right | Default aligned | | Header | Aligned | Aligned | | +=============+============+==============+============================+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-------------+------------+--------------+----------------------------+ | Second | row | 5.0 | Here's another one. Note | | | | | the blank line between | | | | | rows. | +-------------+------------+--------------+----------------------------+ Table without column headers: +-------+-------+-------+-------+ | 12 | 12 | 12 | 12 | +-------+-------+-------+-------+ | 123 | 123 | 123 | 123 | +-------+-------+-------+-------+ | 1 | 1 | 1 | 1 | +-------+-------+-------+-------+ Multiline table without column headers: +-------------+------------+--------------+----------------------------+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-------------+------------+--------------+----------------------------+ | Second | row | 5.0 | Here's another one. Note | | | | | the blank line between | | | | | rows. | +-------------+------------+--------------+----------------------------+ pandoc-1.12.2.1/tests/tables.rtf000644 000765 000024 00000020567 12251233602 016257 0ustar00jgmstaff000000 000000 {\pard \ql \f0 \sa180 \li0 \fi0 Simple table with caption:\par} { \trowd \trgaph120 \clbrdrb\brdrs\cellx2160\clbrdrb\brdrs\cellx4320\clbrdrb\brdrs\cellx6480\clbrdrb\brdrs\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 Right\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Left\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Center\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Default\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 Demonstration of simple table syntax.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Simple table without caption:\par} { \trowd \trgaph120 \clbrdrb\brdrs\cellx2160\clbrdrb\brdrs\cellx4320\clbrdrb\brdrs\cellx6480\clbrdrb\brdrs\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 Right\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Left\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Center\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Default\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 \par} {\pard \ql \f0 \sa180 \li0 \fi0 Simple table indented two spaces:\par} { \trowd \trgaph120 \clbrdrb\brdrs\cellx2160\clbrdrb\brdrs\cellx4320\clbrdrb\brdrs\cellx6480\clbrdrb\brdrs\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 Right\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Left\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Center\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Default\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 Demonstration of simple table syntax.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiline table with caption:\par} { \trowd \trgaph120 \clbrdrb\brdrs\cellx1296\clbrdrb\brdrs\cellx2484\clbrdrb\brdrs\cellx3888\clbrdrb\brdrs\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Centered Header\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Left Aligned\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 Right Aligned\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Default aligned\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx1296\cellx2484\cellx3888\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 First\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 row\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12.0\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Example of a row that spans multiple lines.\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx1296\cellx2484\cellx3888\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Second\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 row\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 5.0\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Here's another one. Note the blank line between rows.\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 Here's the caption. It may span multiple lines.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiline table without caption:\par} { \trowd \trgaph120 \clbrdrb\brdrs\cellx1296\clbrdrb\brdrs\cellx2484\clbrdrb\brdrs\cellx3888\clbrdrb\brdrs\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Centered Header\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Left Aligned\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 Right Aligned\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Default aligned\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx1296\cellx2484\cellx3888\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 First\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 row\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12.0\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Example of a row that spans multiple lines.\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx1296\cellx2484\cellx3888\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Second\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 row\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 5.0\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Here's another one. Note the blank line between rows.\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 \par} {\pard \ql \f0 \sa180 \li0 \fi0 Table without column headers:\par} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 12\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 123\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 123\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx2160\cellx4320\cellx6480\cellx8640 \trkeep\intbl { {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 1\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 1\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 \par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiline table without column headers:\par} { \trowd \trgaph120 \cellx1296\cellx2484\cellx3888\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 First\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 row\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 12.0\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Example of a row that spans multiple lines.\par} \cell} } \intbl\row} { \trowd \trgaph120 \cellx1296\cellx2484\cellx3888\cellx6804 \trkeep\intbl { {\intbl {\pard \qc \f0 \sa0 \li0 \fi0 Second\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 row\par} \cell} {\intbl {\pard \qr \f0 \sa0 \li0 \fi0 5.0\par} \cell} {\intbl {\pard \ql \f0 \sa0 \li0 \fi0 Here's another one. Note the blank line between rows.\par} \cell} } \intbl\row} {\pard \ql \f0 \sa180 \li0 \fi0 \par} pandoc-1.12.2.1/tests/tables.texinfo000644 000765 000024 00000004255 12251233602 017134 0ustar00jgmstaff000000 000000 @node Top @top Top Simple table with caption: @float @multitable {Right} {Left} {Center} {Default} @headitem Right @tab Left @tab Center @tab Default @item 12 @tab 12 @tab 12 @tab 12 @item 123 @tab 123 @tab 123 @tab 123 @item 1 @tab 1 @tab 1 @tab 1 @end multitable @caption{Demonstration of simple table syntax.} @end float Simple table without caption: @multitable {Right} {Left} {Center} {Default} @headitem Right @tab Left @tab Center @tab Default @item 12 @tab 12 @tab 12 @tab 12 @item 123 @tab 123 @tab 123 @tab 123 @item 1 @tab 1 @tab 1 @tab 1 @end multitable Simple table indented two spaces: @float @multitable {Right} {Left} {Center} {Default} @headitem Right @tab Left @tab Center @tab Default @item 12 @tab 12 @tab 12 @tab 12 @item 123 @tab 123 @tab 123 @tab 123 @item 1 @tab 1 @tab 1 @tab 1 @end multitable @caption{Demonstration of simple table syntax.} @end float Multiline table with caption: @float @multitable @columnfractions 0.15 0.14 0.16 0.34 @headitem Centered Header @tab Left Aligned @tab Right Aligned @tab Default aligned @item First @tab row @tab 12.0 @tab Example of a row that spans multiple lines. @item Second @tab row @tab 5.0 @tab Here's another one. Note the blank line between rows. @end multitable @caption{Here's the caption. It may span multiple lines.} @end float Multiline table without caption: @multitable @columnfractions 0.15 0.14 0.16 0.34 @headitem Centered Header @tab Left Aligned @tab Right Aligned @tab Default aligned @item First @tab row @tab 12.0 @tab Example of a row that spans multiple lines. @item Second @tab row @tab 5.0 @tab Here's another one. Note the blank line between rows. @end multitable Table without column headers: @multitable {123} {123} {123} {123} @item 12 @tab 12 @tab 12 @tab 12 @item 123 @tab 123 @tab 123 @tab 123 @item 1 @tab 1 @tab 1 @tab 1 @end multitable Multiline table without column headers: @multitable @columnfractions 0.15 0.14 0.16 0.34 @item First @tab row @tab 12.0 @tab Example of a row that spans multiple lines. @item Second @tab row @tab 5.0 @tab Here's another one. Note the blank line between rows. @end multitable pandoc-1.12.2.1/tests/tables.textile000644 000765 000024 00000010401 12251233602 017124 0ustar00jgmstaff000000 000000 Simple table with caption:
Demonstration of simple table syntax.
Right Left Center Default
12 12 12 12
123 123 123 123
1 1 1 1
Simple table without caption:
Right Left Center Default
12 12 12 12
123 123 123 123
1 1 1 1
Simple table indented two spaces:
Demonstration of simple table syntax.
Right Left Center Default
12 12 12 12
123 123 123 123
1 1 1 1
Multiline table with caption:
Here's the caption. It may span multiple lines.
Centered Header Left Aligned Right Aligned Default aligned
First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here's another one. Note the blank line between rows.
Multiline table without caption:
Centered Header Left Aligned Right Aligned Default aligned
First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here's another one. Note the blank line between rows.
Table without column headers:
12 12 12 12
123 123 123 123
1 1 1 1
Multiline table without column headers:
First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here's another one. Note the blank line between rows.
pandoc-1.12.2.1/tests/tables.txt000644 000765 000024 00000005136 12251233602 016276 0ustar00jgmstaff000000 000000 Simple table with caption: Right Left Center Default ------- ------ ---------- ------- 12 12 12 12 123 123 123 123 1 1 1 1 Table: Demonstration of simple table syntax. Simple table without caption: Right Left Center Default ------- ------ ---------- ------- 12 12 12 12 123 123 123 123 1 1 1 1 Simple table indented two spaces: Right Left Center Default ------- ------ ---------- ------- 12 12 12 12 123 123 123 123 1 1 1 1 : Demonstration of simple table syntax. Multiline table with caption: : Here's the caption. It may span multiple lines. --------------------------------------------------------------- Centered Left Right Header Aligned Aligned Default aligned ---------- --------- ----------- --------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. --------------------------------------------------------------- Multiline table without caption: --------------------------------------------------------------- Centered Left Right Header Aligned Aligned Default aligned ---------- --------- ----------- --------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. --------------------------------------------------------------- Table without column headers: ------- ------ ---------- ------- 12 12 12 12 123 123 123 123 1 1 1 1 ------- ------ ---------- ------- Multiline table without column headers: ---------- --------- ----------- --------------------------- First row 12.0 Example of a row that spans multiple lines. Second row 5.0 Here's another one. Note the blank line between rows. ---------- --------- ----------- --------------------------- pandoc-1.12.2.1/tests/test-pandoc.hs000644 000765 000024 00000002727 12251233602 017043 0ustar00jgmstaff000000 000000 {-# OPTIONS_GHC -Wall #-} module Main where import Test.Framework import GHC.IO.Encoding import qualified Tests.Old import qualified Tests.Readers.LaTeX import qualified Tests.Readers.Markdown import qualified Tests.Readers.RST import qualified Tests.Writers.ConTeXt import qualified Tests.Writers.LaTeX import qualified Tests.Writers.HTML import qualified Tests.Writers.Native import qualified Tests.Writers.Markdown import qualified Tests.Shared import qualified Tests.Walk import Text.Pandoc.Shared (inDirectory) tests :: [Test] tests = [ testGroup "Old" Tests.Old.tests , testGroup "Shared" Tests.Shared.tests , testGroup "Walk" Tests.Walk.tests , testGroup "Writers" [ testGroup "Native" Tests.Writers.Native.tests , testGroup "ConTeXt" Tests.Writers.ConTeXt.tests , testGroup "LaTeX" Tests.Writers.LaTeX.tests , testGroup "HTML" Tests.Writers.HTML.tests , testGroup "Markdown" Tests.Writers.Markdown.tests ] , testGroup "Readers" [ testGroup "LaTeX" Tests.Readers.LaTeX.tests , testGroup "Markdown" Tests.Readers.Markdown.tests , testGroup "RST" Tests.Readers.RST.tests ] ] main :: IO () main = do setLocaleEncoding utf8 -- 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 [] pandoc-1.12.2.1/tests/Tests/000755 000765 000024 00000000000 12251233602 015360 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/tests/testsuite.native000644 000765 000024 00000064012 12251233602 017522 0ustar00jgmstaff000000 000000 Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Space,Str "MacFarlane"],MetaInlines [Str "Anonymous"]]),("date",MetaInlines [Str "July",Space,Str "17,",Space,Str "2006"]),("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.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."] ,HorizontalRule ,Header 1 ("headers",[],[]) [Str "Headers"] ,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embedded",Space,Str "link"] ("/url","")] ,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Emph [Str "emphasis"]] ,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"] ,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"] ,Header 1 ("level-1",[],[]) [Str "Level",Space,Str "1"] ,Header 2 ("level-2-with-emphasis",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Emph [Str "emphasis"]] ,Header 3 ("level-3",[],[]) [Str "Level",Space,Str "3"] ,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"] ,Header 2 ("level-2",[],[]) [Str "Level",Space,Str "2"] ,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"] ,HorizontalRule ,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"] ,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph."] ,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."] ,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."] ,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here."] ,HorizontalRule ,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"] ,Para [Str "E-mail",Space,Str "style:"] ,BlockQuote [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]] ,BlockQuote [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"] ,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}" ,Para [Str "A",Space,Str "list:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "item",Space,Str "one"]] ,[Plain [Str "item",Space,Str "two"]]] ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"] ,BlockQuote [Para [Str "nested"]] ,BlockQuote [Para [Str "nested"]]] ,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."] ,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."] ,HorizontalRule ,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"] ,Para [Str "Code:"] ,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab" ,Para [Str "And:"] ,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{" ,HorizontalRule ,Header 1 ("lists",[],[]) [Str "Lists"] ,Header 2 ("unordered",[],[]) [Str "Unordered"] ,Para [Str "Asterisks",Space,Str "tight:"] ,BulletList [[Plain [Str "asterisk",Space,Str "1"]] ,[Plain [Str "asterisk",Space,Str "2"]] ,[Plain [Str "asterisk",Space,Str "3"]]] ,Para [Str "Asterisks",Space,Str "loose:"] ,BulletList [[Para [Str "asterisk",Space,Str "1"]] ,[Para [Str "asterisk",Space,Str "2"]] ,[Para [Str "asterisk",Space,Str "3"]]] ,Para [Str "Pluses",Space,Str "tight:"] ,BulletList [[Plain [Str "Plus",Space,Str "1"]] ,[Plain [Str "Plus",Space,Str "2"]] ,[Plain [Str "Plus",Space,Str "3"]]] ,Para [Str "Pluses",Space,Str "loose:"] ,BulletList [[Para [Str "Plus",Space,Str "1"]] ,[Para [Str "Plus",Space,Str "2"]] ,[Para [Str "Plus",Space,Str "3"]]] ,Para [Str "Minuses",Space,Str "tight:"] ,BulletList [[Plain [Str "Minus",Space,Str "1"]] ,[Plain [Str "Minus",Space,Str "2"]] ,[Plain [Str "Minus",Space,Str "3"]]] ,Para [Str "Minuses",Space,Str "loose:"] ,BulletList [[Para [Str "Minus",Space,Str "1"]] ,[Para [Str "Minus",Space,Str "2"]] ,[Para [Str "Minus",Space,Str "3"]]] ,Header 2 ("ordered",[],[]) [Str "Ordered"] ,Para [Str "Tight:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "First"]] ,[Plain [Str "Second"]] ,[Plain [Str "Third"]]] ,Para [Str "and:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "One"]] ,[Plain [Str "Two"]] ,[Plain [Str "Three"]]] ,Para [Str "Loose",Space,Str "using",Space,Str "tabs:"] ,OrderedList (1,Decimal,Period) [[Para [Str "First"]] ,[Para [Str "Second"]] ,[Para [Str "Third"]]] ,Para [Str "and",Space,Str "using",Space,Str "spaces:"] ,OrderedList (1,Decimal,Period) [[Para [Str "One"]] ,[Para [Str "Two"]] ,[Para [Str "Three"]]] ,Para [Str "Multiple",Space,Str "paragraphs:"] ,OrderedList (1,Decimal,Period) [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."] ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",Space,Str "back."]] ,[Para [Str "Item",Space,Str "2."]] ,[Para [Str "Item",Space,Str "3."]]] ,Header 2 ("nested",[],[]) [Str "Nested"] ,BulletList [[Plain [Str "Tab"] ,BulletList [[Plain [Str "Tab"] ,BulletList [[Plain [Str "Tab"]]]]]]] ,Para [Str "Here\8217s",Space,Str "another:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "First"]] ,[Plain [Str "Second:"] ,BulletList [[Plain [Str "Fee"]] ,[Plain [Str "Fie"]] ,[Plain [Str "Foe"]]]] ,[Plain [Str "Third"]]] ,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"] ,OrderedList (1,Decimal,Period) [[Para [Str "First"]] ,[Para [Str "Second:"] ,BulletList [[Plain [Str "Fee"]] ,[Plain [Str "Fie"]] ,[Plain [Str "Foe"]]]] ,[Para [Str "Third"]]] ,Header 2 ("tabs-and-spaces",[],[]) [Str "Tabs",Space,Str "and",Space,Str "spaces"] ,BulletList [[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]] ,[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"] ,BulletList [[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]] ,[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]]]]] ,Header 2 ("fancy-list-markers",[],[]) [Str "Fancy",Space,Str "list",Space,Str "markers"] ,OrderedList (2,Decimal,TwoParens) [[Plain [Str "begins",Space,Str "with",Space,Str "2"]] ,[Para [Str "and",Space,Str "now",Space,Str "3"] ,Para [Str "with",Space,Str "a",Space,Str "continuation"] ,OrderedList (4,LowerRoman,Period) [[Plain [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals,",Space,Str "starting",Space,Str "with",Space,Str "4"]] ,[Plain [Str "more",Space,Str "items"] ,OrderedList (1,UpperAlpha,TwoParens) [[Plain [Str "a",Space,Str "subsublist"]] ,[Plain [Str "a",Space,Str "subsublist"]]]]]]] ,Para [Str "Nesting:"] ,OrderedList (1,UpperAlpha,Period) [[Plain [Str "Upper",Space,Str "Alpha"] ,OrderedList (1,UpperRoman,Period) [[Plain [Str "Upper",Space,Str "Roman."] ,OrderedList (6,Decimal,TwoParens) [[Plain [Str "Decimal",Space,Str "start",Space,Str "with",Space,Str "6"] ,OrderedList (3,LowerAlpha,OneParen) [[Plain [Str "Lower",Space,Str "alpha",Space,Str "with",Space,Str "paren"]]]]]]]]] ,Para [Str "Autonumbering:"] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "Autonumber."]] ,[Plain [Str "More."] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "Nested."]]]]] ,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item:"] ,Para [Str "M.A.\160\&2007"] ,Para [Str "B.",Space,Str "Williams"] ,HorizontalRule ,Header 1 ("definition-lists",[],[]) [Str "Definition",Space,Str "Lists"] ,Para [Str "Tight",Space,Str "using",Space,Str "spaces:"] ,DefinitionList [([Str "apple"], [[Plain [Str "red",Space,Str "fruit"]]]) ,([Str "orange"], [[Plain [Str "orange",Space,Str "fruit"]]]) ,([Str "banana"], [[Plain [Str "yellow",Space,Str "fruit"]]])] ,Para [Str "Tight",Space,Str "using",Space,Str "tabs:"] ,DefinitionList [([Str "apple"], [[Plain [Str "red",Space,Str "fruit"]]]) ,([Str "orange"], [[Plain [Str "orange",Space,Str "fruit"]]]) ,([Str "banana"], [[Plain [Str "yellow",Space,Str "fruit"]]])] ,Para [Str "Loose:"] ,DefinitionList [([Str "apple"], [[Para [Str "red",Space,Str "fruit"]]]) ,([Str "orange"], [[Para [Str "orange",Space,Str "fruit"]]]) ,([Str "banana"], [[Para [Str "yellow",Space,Str "fruit"]]])] ,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics:"] ,DefinitionList [([Emph [Str "apple"]], [[Para [Str "red",Space,Str "fruit"] ,Para [Str "contains",Space,Str "seeds,",Space,Str "crisp,",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]]) ,([Emph [Str "orange"]], [[Para [Str "orange",Space,Str "fruit"] ,CodeBlock ("",[],[]) "{ orange code block }" ,BlockQuote [Para [Str "orange",Space,Str "block",Space,Str "quote"]]]])] ,Para [Str "Multiple",Space,Str "definitions,",Space,Str "tight:"] ,DefinitionList [([Str "apple"], [[Plain [Str "red",Space,Str "fruit"]] ,[Plain [Str "computer"]]]) ,([Str "orange"], [[Plain [Str "orange",Space,Str "fruit"]] ,[Plain [Str "bank"]]])] ,Para [Str "Multiple",Space,Str "definitions,",Space,Str "loose:"] ,DefinitionList [([Str "apple"], [[Para [Str "red",Space,Str "fruit"]] ,[Para [Str "computer"]]]) ,([Str "orange"], [[Para [Str "orange",Space,Str "fruit"]] ,[Para [Str "bank"]]])] ,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term,",Space,Str "indented",Space,Str "marker,",Space,Str "alternate",Space,Str "markers:"] ,DefinitionList [([Str "apple"], [[Para [Str "red",Space,Str "fruit"]] ,[Para [Str "computer"]]]) ,([Str "orange"], [[Para [Str "orange",Space,Str "fruit"] ,OrderedList (1,Decimal,Period) [[Plain [Str "sublist"]] ,[Plain [Str "sublist"]]]]])] ,Header 1 ("html-blocks",[],[]) [Str "HTML",Space,Str "Blocks"] ,Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line:"] ,Div ("",[],[]) [Plain [Str "foo"]] ,Para [Str "And",Space,Str "nested",Space,Str "without",Space,Str "indentation:"] ,Div ("",[],[]) [Div ("",[],[]) [Div ("",[],[]) [Plain [Str "foo"]]],Div ("",[],[]) [Plain [Str "bar"]]] ,Para [Str "Interpreted",Space,Str "markdown",Space,Str "in",Space,Str "a",Space,Str "table:"] ,RawBlock (Format "html") "\n\n\n\n\n
" ,Plain [Str "This",Space,Str "is",Space,Emph [Str "emphasized"]] ,RawBlock (Format "html") "" ,Plain [Str "And",Space,Str "this",Space,Str "is",Space,Strong [Str "strong"]] ,RawBlock (Format "html") "
\n\n\n" ,Para [Str "Here\8217s",Space,Str "a",Space,Str "simple",Space,Str "block:"] ,Div ("",[],[]) [Plain [Str "foo"]] ,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "code",Space,Str "block,",Space,Str "though:"] ,CodeBlock ("",[],[]) "
\n foo\n
" ,Para [Str "As",Space,Str "should",Space,Str "this:"] ,CodeBlock ("",[],[]) "
foo
" ,Para [Str "Now,",Space,Str "nested:"] ,Div ("",[],[]) [Div ("",[],[]) [Div ("",[],[]) [Plain [Str "foo"]]]] ,Para [Str "This",Space,Str "should",Space,Str "just",Space,Str "be",Space,Str "an",Space,Str "HTML",Space,Str "comment:"] ,RawBlock (Format "html") "\n" ,Para [Str "Multiline:"] ,RawBlock (Format "html") "\n\n\n" ,Para [Str "Code",Space,Str "block:"] ,CodeBlock ("",[],[]) "" ,Para [Str "Just",Space,Str "plain",Space,Str "comment,",Space,Str "with",Space,Str "trailing",Space,Str "spaces",Space,Str "on",Space,Str "the",Space,Str "line:"] ,RawBlock (Format "html") " \n" ,Para [Str "Code:"] ,CodeBlock ("",[],[]) "
" ,Para [Str "Hr\8217s:"] ,RawBlock (Format "html") "
\n\n
\n\n
\n\n
\n\n
\n\n
\n\n
\n\n
\n\n
\n" ,HorizontalRule ,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"] ,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str "."] ,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str "."] ,Para [Str "An",Space,Emph [Link [Str "emphasized",Space,Str "link"] ("/url","")],Str "."] ,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]] ,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."] ,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]] ,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."] ,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "",Str "."] ,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "strikeout"],Str "."]] ,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Emph [Str "hello"]],Space,Str "a",Superscript [Str "hello\160there"],Str "."] ,Para [Str "Subscripts:",Space,Str "H",Subscript [Str "2"],Str "O,",Space,Str "H",Subscript [Str "23"],Str "O,",Space,Str "H",Subscript [Str "many\160of\160them"],Str "O."] ,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts,",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",Space,Str "spaces:",Space,Str "a^b",Space,Str "c^d,",Space,Str "a~b",Space,Str "c~d."] ,HorizontalRule ,Header 1 ("smart-quotes-ellipses-dashes",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"] ,Para [Quoted DoubleQuote [Str "Hello,"],Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",Space,Str "name."]] ,Para [Quoted SingleQuote [Str "A"],Str ",",Space,Quoted SingleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted SingleQuote [Str "C"],Space,Str "are",Space,Str "letters."] ,Para [Quoted SingleQuote [Str "Oak,"],Space,Quoted SingleQuote [Str "elm,"],Space,Str "and",Space,Quoted SingleQuote [Str "beech"],Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Quoted SingleQuote [Str "pine."]] ,Para [Quoted SingleQuote [Str "He",Space,Str "said,",Space,Quoted DoubleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70\8217s?"] ,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Quoted SingleQuote [Code ("",[],[]) "code"],Space,Str "and",Space,Str "a",Space,Quoted DoubleQuote [Link [Str "quoted",Space,Str "link"] ("http://example.com/?foo=1&bar=2","")],Str "."] ,Para [Str "Some",Space,Str "dashes:",Space,Str "one\8212two",Space,Str "\8212",Space,Str "three\8212four",Space,Str "\8212",Space,Str "five."] ,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5\8211\&7,",Space,Str "255\8211\&66,",Space,Str "1987\8211\&1999."] ,Para [Str "Ellipses\8230and\8230and\8230."] ,HorizontalRule ,Header 1 ("latex",[],[]) [Str "LaTeX"] ,BulletList [[Plain [RawInline (Format "tex") "\\cite[22-23]{smith.1899}"]] ,[Plain [Math InlineMath "2+2=4"]] ,[Plain [Math InlineMath "x \\in y"]] ,[Plain [Math InlineMath "\\alpha \\wedge \\omega"]] ,[Plain [Math InlineMath "223"]] ,[Plain [Math InlineMath "p",Str "-Tree"]] ,[Plain [Str "Here\8217s",Space,Str "some",Space,Str "display",Space,Str "math:",Space,Math DisplayMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]] ,[Plain [Str "Here\8217s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math InlineMath "\\alpha + \\omega \\times x^2",Str "."]]] ,Para [Str "These",Space,Str "shouldn\8217t",Space,Str "be",Space,Str "math:"] ,BulletList [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]] ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized.)"]] ,[Plain [Str "Shoes",Space,Str "($20)",Space,Str "and",Space,Str "socks",Space,Str "($5)."]] ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$."]]] ,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"] ,RawBlock (Format "latex") "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}" ,HorizontalRule ,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"] ,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"] ,BulletList [[Plain [Str "I",Space,Str "hat:",Space,Str "\206"]] ,[Plain [Str "o",Space,Str "umlaut:",Space,Str "\246"]] ,[Plain [Str "section:",Space,Str "\167"]] ,[Plain [Str "set",Space,Str "membership:",Space,Str "\8712"]] ,[Plain [Str "copyright:",Space,Str "\169"]]] ,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."] ,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."] ,Para [Str "This",Space,Str "&",Space,Str "that."] ,Para [Str "4",Space,Str "<",Space,Str "5."] ,Para [Str "6",Space,Str ">",Space,Str "5."] ,Para [Str "Backslash:",Space,Str "\\"] ,Para [Str "Backtick:",Space,Str "`"] ,Para [Str "Asterisk:",Space,Str "*"] ,Para [Str "Underscore:",Space,Str "_"] ,Para [Str "Left",Space,Str "brace:",Space,Str "{"] ,Para [Str "Right",Space,Str "brace:",Space,Str "}"] ,Para [Str "Left",Space,Str "bracket:",Space,Str "["] ,Para [Str "Right",Space,Str "bracket:",Space,Str "]"] ,Para [Str "Left",Space,Str "paren:",Space,Str "("] ,Para [Str "Right",Space,Str "paren:",Space,Str ")"] ,Para [Str "Greater-than:",Space,Str ">"] ,Para [Str "Hash:",Space,Str "#"] ,Para [Str "Period:",Space,Str "."] ,Para [Str "Bang:",Space,Str "!"] ,Para [Str "Plus:",Space,Str "+"] ,Para [Str "Minus:",Space,Str "-"] ,HorizontalRule ,Header 1 ("links",[],[]) [Str "Links"] ,Header 2 ("explicit",[],[]) [Str "Explicit"] ,Para [Str "Just",Space,Str "a",Space,Link [Str "URL"] ("/url/",""),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title"),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by two spaces"),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with single quotes")] ,Para [Link [Str "with_underscore"] ("/url/with_underscore","")] ,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")] ,Para [Link [Str "Empty"] ("",""),Str "."] ,Header 2 ("reference",[],[]) [Str "Reference"] ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."] ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."] ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."] ,Para [Str "With",Space,Link [Str "embedded",Space,Str "[brackets]"] ("/url/",""),Str "."] ,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."] ,Para [Str "Indented",Space,Link [Str "once"] ("/url",""),Str "."] ,Para [Str "Indented",Space,Link [Str "twice"] ("/url",""),Str "."] ,Para [Str "Indented",Space,Link [Str "thrice"] ("/url",""),Str "."] ,Para [Str "This",Space,Str "should",Space,Str "[not][]",Space,Str "be",Space,Str "a",Space,Str "link."] ,CodeBlock ("",[],[]) "[not]: /url" ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."] ,Para [Str "Foo",Space,Link [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."] ,Header 2 ("with-ampersands",[],[]) [Str "With",Space,Str "ampersands"] ,Para [Str "Here\8217s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."] ,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] ("http://att.com/","AT&T"),Str "."] ,Para [Str "Here\8217s",Space,Str "an",Space,Link [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."] ,Para [Str "Here\8217s",Space,Str "an",Space,Link [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."] ,Header 2 ("autolinks",[],[]) [Str "Autolinks"] ,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")] ,BulletList [[Plain [Str "In",Space,Str "a",Space,Str "list?"]] ,[Plain [Link [Str "http://example.com/"] ("http://example.com/","")]] ,[Plain [Str "It",Space,Str "should."]]] ,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")] ,BlockQuote [Para [Str "Blockquoted:",Space,Link [Str "http://example.com/"] ("http://example.com/","")]] ,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",Space,Code ("",[],[]) ""] ,CodeBlock ("",[],[]) "or here: " ,HorizontalRule ,Header 1 ("images",[],[]) [Str "Images"] ,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"] ,Para [Image [Str "lalune"] ("lalune.jpg","fig:Voyage dans la Lune")] ,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon."] ,HorizontalRule ,Header 1 ("footnotes",[],[]) [Str "Footnotes"] ,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference.",Space,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document."]],Space,Str "and",Space,Str "another.",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "list",Space,Str "items)."],CodeBlock ("",[],[]) " { }",Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line,",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",Space,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space.[^my",Space,Str "note]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note.",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type.",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",Space,Link [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",Space,Str "verbatim",Space,Str "characters,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[bracketed",Space,Str "text]."]]] ,BlockQuote [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes.",Note [Para [Str "In",Space,Str "quote."]]]] ,OrderedList (1,Decimal,Period) [[Plain [Str "And",Space,Str "in",Space,Str "list",Space,Str "items.",Note [Para [Str "In",Space,Str "list."]]]]] ,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented."]] pandoc-1.12.2.1/tests/testsuite.txt000644 000765 000024 00000022016 12251233602 017051 0ustar00jgmstaff000000 000000 % Pandoc Test Suite % John MacFarlane; Anonymous % July 17, 2006 This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. ----- # Headers ## Level 2 with an [embedded link](/url) ### Level 3 with *emphasis* #### Level 4 ##### Level 5 Level 1 ======= Level 2 with *emphasis* ----------------------- ### Level 3 with no blank line Level 2 ------- with no blank line ---------- # Paragraphs Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. * criminey. There should be a hard line break here. --- # Block Quotes E-mail style: > This is a block quote. > It is pretty short. > Code in a block quote: > > sub status { > print "working"; > } > > A list: > > 1. item one > 2. item two > > Nested block quotes: > > > nested > >> nested > This should not be a block quote: 2 > 1. And a following paragraph. * * * * # Code Blocks Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ ___________ # Lists ## 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 1. 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 ## Tabs and spaces + this is a list item indented with tabs + this is a list item indented with spaces + this is an example list item indented with tabs + this is an example list item indented with spaces ## Fancy list markers (2) begins with 2 (3) and now 3 with a continuation iv. sublist with roman numerals, starting with 4 v. more items (A) a subsublist (B) a subsublist Nesting: A. Upper Alpha I. Upper Roman. (6) Decimal start with 6 c) Lower alpha with paren Autonumbering: #. Autonumber. #. More. #. Nested. Should not be a list item: M.A. 2007 B. Williams * * * * * # Definition Lists Tight using spaces: apple : red fruit orange : orange fruit banana : yellow fruit Tight using tabs: apple : red fruit orange : orange fruit banana : yellow fruit Loose: apple : red fruit orange : orange fruit banana : yellow fruit Multiple blocks with italics: *apple* : red fruit contains seeds, crisp, pleasant to taste *orange* : orange fruit { orange code block } > orange block quote Multiple definitions, tight: apple : red fruit : computer orange : orange fruit : bank Multiple definitions, loose: apple : red fruit : computer orange : orange fruit : bank Blank line after term, indented marker, alternate markers: apple ~ red fruit ~ computer orange ~ orange fruit 1. sublist 2. sublist # HTML Blocks Simple block on one line:
foo
And nested without indentation:
foo
bar
Interpreted markdown in a table:
This is *emphasized* And this is **strong**
Here's a simple block:
foo
This should be a code block, though:
foo
As should this:
foo
Now, nested:
foo
This should just be an HTML comment: Multiline: Code block: Just plain comment, with trailing spaces on the line: Code:
Hr's:








----- # Inline Markup This is *emphasized*, and so _is this_. This is **strong**, and so __is this__. An *[emphasized link](/url)*. ***This is strong and em.*** So is ***this*** word. ___This is strong and em.___ So is ___this___ word. This is code: `>`, `$`, `\`, `\$`, ``. ~~This is *strikeout*.~~ Superscripts: a^bc^d a^*hello*^ a^hello\ there^. Subscripts: H~2~O, H~23~O, H~many\ of\ them~O. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. ----- # Smart quotes, ellipses, dashes "Hello," said the spider. "'Shelob' is my name." 'A', 'B', and 'C' are letters. 'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.' 'He said, "I want to go."' Were you alive in the 70's? Here is some quoted '`code`' and a "[quoted link][1]". Some dashes: one---two --- three---four --- five. Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses...and...and.... ----- # LaTeX - \cite[22-23]{smith.1899} - $2+2=4$ - $x \in y$ - $\alpha \wedge \omega$ - $223$ - $p$-Tree - Here's some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ - Here's one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn't be math: - To get the famous equation, write `$e = mc^2$`. - $22,000 is a *lot* of money. So is $34,000. (It worked if "lot" is emphasized.) - Shoes ($20) and socks ($5). - Escaped `$`: $73 *this should be emphasized* 23\$. Here's a LaTeX table: \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} * * * * * # Special Characters Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \\ Backtick: \` Asterisk: \* Underscore: \_ Left brace: \{ Right brace: \} Left bracket: \[ Right bracket: \] Left paren: \( Right paren: \) Greater-than: \> Hash: \# Period: \. Bang: \! Plus: \+ Minus: \- - - - - - - - - - - - - - # Links ## Explicit 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 with "quotes" in it") [URL and title](/url/ 'title with single quotes') [with\_underscore](/url/with_underscore) [Email link](mailto:nobody@nowhere.net) [Empty](). ## Reference Foo [bar] [a]. Foo [bar][a]. Foo [bar] [a]. [a]: /url/ With [embedded [brackets]] [b]. [b] by itself should be a link. Indented [once][]. Indented [twice][]. Indented [thrice][]. This should [not][] be a link. [once]: /url [twice]: /url [thrice]: /url [not]: /url [b]: /url/ Foo [bar][]. Foo [biz](/url/ "Title with "quote" inside"). [bar]: /url/ "Title with "quotes" inside" ## With ampersands Here's a [link with an ampersand in the URL] [1]. 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 in pointy braces](). [1]: http://example.com/?foo=1&bar=2 [2]: http://att.com/ "AT&T" ## Autolinks With an ampersand: * In a list? * * It should. An e-mail address: > Blockquoted: Auto-links should not occur here: `` or here: ---- # Images From "Voyage dans la Lune" by Georges Melies (1902): ![lalune][] [lalune]: lalune.jpg "Voyage dans la Lune" Here is a movie ![movie](movie.jpg) icon. ---- # Footnotes Here is a footnote reference,[^1] and another.[^longnote] This should *not* be a footnote reference, because it contains a space.[^my note] Here is an inline note.^[This is *easier* to type. Inline notes may contain [links](http://google.com) and `]` verbatim characters, as well as [bracketed text].] > Notes can go in quotes.^[In quote.] 1. And in list items.^[In list.] [^longnote]: Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). { } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. This paragraph should not be part of the note, as it is not indented. [^1]: Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. pandoc-1.12.2.1/tests/textile-reader.native000644 000765 000024 00000031601 12251233602 020405 0ustar00jgmstaff000000 000000 Pandoc (Meta {unMeta = fromList []}) [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Space,Str "Textile",Space,Str "Reader",Str ".",Space,Str "Part",Space,Str "of",Space,Str "it",Space,Str "comes",LineBreak,Str "from",Space,Str "John",Space,Str "Gruber",Str "\8217",Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."] ,HorizontalRule ,Header 1 ("headers",[],[]) [Str "Headers"] ,Header 2 ("level-2-with-an-embeded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embeded",Space,Str "link"] ("http://www.example.com","")] ,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Strong [Str "emphasis"]] ,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"] ,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"] ,Header 6 ("level-6",[],[]) [Str "Level",Space,Str "6"] ,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"] ,Para [Str "Here",Str "\8217",Str "s",Space,Str "a",Space,Str "regular",Space,Str "paragraph",Str "."] ,Para [Str "Line",Space,Str "breaks",Space,Str "are",Space,Str "preserved",Space,Str "in",Space,Str "textile",Str ",",Space,Str "so",Space,Str "you",Space,Str "can",Space,Str "not",Space,Str "wrap",Space,Str "your",Space,Str "very",LineBreak,Str "long",Space,Str "paragraph",Space,Str "with",Space,Str "your",Space,Str "favourite",Space,Str "text",Space,Str "editor",Space,Str "and",Space,Str "have",Space,Str "it",Space,Str "rendered",LineBreak,Str "with",Space,Str "no",Space,Str "break",Str "."] ,Para [Str "Here",Str "\8217",Str "s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet",Str "."] ,BulletList [[Plain [Str "criminey",Str "."]]] ,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "paragraph",Space,Str "break",Space,Str "between",Space,Str "here"] ,Para [Str "and",Space,Str "here",Str "."] ,Para [Str "pandoc",Space,Str "converts",Space,Str "textile",Str "."] ,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"] ,BlockQuote [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "famous",Space,Str "quote",Space,Str "from",Space,Str "somebody",Str ".",Space,Str "He",Space,Str "had",Space,Str "a",Space,Str "lot",Space,Str "of",Space,Str "things",Space,Str "to",LineBreak,Str "say",Str ",",Space,Str "so",Space,Str "the",Space,Str "text",Space,Str "is",Space,Str "really",Space,Str "really",Space,Str "long",Space,Str "and",Space,Str "spans",Space,Str "on",Space,Str "multiple",Space,Str "lines",Str "."]] ,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."] ,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"] ,Para [Str "Code",Str ":"] ,CodeBlock ("",[],[]) " ---- (should be four hyphens)\n\n sub status {\n print \"working\";\n }\n\n this code block is indented by one tab" ,Para [Str "And",Str ":"] ,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\n These should not be escaped: \\$ \\\\ \\> \\[ \\{" ,CodeBlock ("",[],[]) "Code block with .bc\n continued\n @",Str ",",Space,Code ("",[],[]) "@",Str "."] ,Header 1 ("notextile",[],[]) [Str "Notextile"] ,Para [Str "A",Space,Str "block",Space,Str "of",Space,Str "text",Space,Str "can",Space,Str "be",Space,Str "protected",Space,Str "with",Space,Str "notextile",Space,Str ":"] ,Para [Str "\nNo *bold* and\n* no bullet\n"] ,Para [Str "and",Space,Str "inlines",Space,Str "can",Space,Str "be",Space,Str "protected",Space,Str "with",Space,Str "double *equals (=)* markup",Str "."] ,Header 1 ("lists",[],[]) [Str "Lists"] ,Header 2 ("unordered",[],[]) [Str "Unordered"] ,Para [Str "Asterisks",Space,Str "tight",Str ":"] ,BulletList [[Plain [Str "asterisk",Space,Str "1"]] ,[Plain [Str "asterisk",Space,Str "2"]] ,[Plain [Str "asterisk",Space,Str "3"]]] ,Para [Str "With",Space,Str "line",Space,Str "breaks",Str ":"] ,BulletList [[Plain [Str "asterisk",Space,Str "1",LineBreak,Str "newline"]] ,[Plain [Str "asterisk",Space,Str "2"]]] ,Header 2 ("ordered",[],[]) [Str "Ordered"] ,Para [Str "Tight",Str ":"] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "First"]] ,[Plain [Str "Second"]] ,[Plain [Str "Third"]]] ,Header 2 ("nested",[],[]) [Str "Nested"] ,BulletList [[Plain [Str "ui",Space,Str "1"] ,BulletList [[Plain [Str "ui",Space,Str "1",Str ".",Str "1"] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "oi",Space,Str "1",Str ".",Str "1",Str ".",Str "1"]] ,[Plain [Str "oi",Space,Str "1",Str ".",Str "1",Str ".",Str "2"]]]] ,[Plain [Str "ui",Space,Str "1",Str ".",Str "2"]]]] ,[Plain [Str "ui",Space,Str "2"] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "oi",Space,Str "2",Str ".",Str "1"] ,BulletList [[Plain [Str "ui",Space,Str "2",Str ".",Str "1",Str ".",Str "1"]] ,[Plain [Str "ui",Space,Str "2",Str ".",Str "1",Str ".",Str "2"]]]]]]] ,Header 2 ("definition-list",[],[]) [Str "Definition",Space,Str "List"] ,DefinitionList [([Str "coffee"], [[Plain [Str "Hot",Space,Str "and",Space,Str "black"]]]) ,([Str "tea"], [[Plain [Str "Also",Space,Str "hot",Str ",",Space,Str "but",Space,Str "a",Space,Str "little",Space,Str "less",Space,Str "black"]]]) ,([Str "milk"], [[Para [Str "Nourishing",Space,Str "beverage",Space,Str "for",Space,Str "baby",Space,Str "cows",Str "."] ,Para [Str "Cold",Space,Str "drink",Space,Str "that",Space,Str "goes",Space,Str "great",Space,Str "with",Space,Str "cookies",Str "."]]]) ,([Str "beer"], [[Plain [Str "fresh",Space,Str "and",Space,Str "bitter"]]])] ,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"] ,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "Hyphenated-words-are-ok",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation",Str ".",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."] ,Para [Emph [Strong [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]],LineBreak,Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Space,Str "and",Space,Emph [Strong [Str "that",Space,Str "one"]],Str ".",LineBreak,Strikeout [Str "This",Space,Str "is",Space,Str "strikeout",Space,Str "and",Space,Strong [Str "strong"]]] ,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts",Str ":",Space,Subscript [Str "here"],Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O",Str "."] ,Para [Str "Dashes",Space,Str ":",Space,Str "How",Space,Str "cool",Space,Str "\8212",Space,Str "automatic",Space,Str "dashes",Str "."] ,Para [Str "Elipses",Space,Str ":",Space,Str "He",Space,Str "thought",Space,Str "and",Space,Str "thought",Space,Str "\8230",Space,Str "and",Space,Str "then",Space,Str "thought",Space,Str "some",Space,Str "more",Str "."] ,Para [Str "Quotes",Space,Str "and",Space,Str "apostrophes",Space,Str ":",Space,Quoted DoubleQuote [Str "I",Str "\8217",Str "d",Space,Str "like",Space,Str "to",Space,Str "thank",Space,Str "you"],Space,Str "for",Space,Str "example",Str "."] ,Header 1 ("links",[],[]) [Str "Links"] ,Header 2 ("explicit",[],[]) [Str "Explicit"] ,Para [Str "Just",Space,Str "a",Space,Link [Str "url"] ("http://www.url.com","")] ,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")] ,Para [Str "Automatic",Space,Str "linking",Space,Str "to",Space,Link [Str "http://www.example.com"] ("http://www.example.com",""),Str "."] ,Para [Link [Str "Example"] ("http://www.example.com/",""),Str ":",Space,Str "Example",Space,Str "of",Space,Str "a",Space,Str "link",Space,Str "followed",Space,Str "by",Space,Str "a",Space,Str "colon",Str "."] ,Para [Str "A",Space,Str "link",Link [Str "with",Space,Str "brackets"] ("http://www.example.com",""),Str "and",Space,Str "no",Space,Str "spaces",Str "."] ,Header 1 ("tables",[],[]) [Str "Tables"] ,Para [Str "Textile",Space,Str "allows",Space,Str "tables",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "headers",Space,Str ":"] ,Header 2 ("without-headers",[],[]) [Str "Without",Space,Str "headers"] ,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0] [] [[[Plain [Str "name"]] ,[Plain [Str "age"]] ,[Plain [Str "sex"]]] ,[[Plain [Str "joan"]] ,[Plain [Str "24"]] ,[Plain [Str "f"]]] ,[[Plain [Str "archie"]] ,[Plain [Str "29"]] ,[Plain [Str "m"]]] ,[[Plain [Str "bella"]] ,[Plain [Str "45"]] ,[Plain [Str "f"]]]] ,Para [Str "and",Space,Str "some",Space,Str "text",Space,Str "following",Space,Str "\8230"] ,Header 2 ("with-headers",[],[]) [Str "With",Space,Str "headers"] ,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0] [[Plain [Str "name"]] ,[Plain [Str "age"]] ,[Plain [Str "sex"]]] [[[Plain [Str "joan"]] ,[Plain [Str "24"]] ,[Plain [Str "f"]]] ,[[Plain [Str "archie"]] ,[Plain [Str "29"]] ,[Plain [Str "m"]]] ,[[Plain [Str "bella"]] ,[Plain [Str "45"]] ,[Plain [Str "f"]]]] ,Header 1 ("images",[],[]) [Str "Images"] ,Para [Str "Textile",Space,Str "inline",Space,Str "image",Space,Str "syntax",Str ",",Space,Str "like",Space,LineBreak,Str "here",Space,Image [Str "this is the alt text"] ("this_is_an_image.png","this is the alt text"),LineBreak,Str "and",Space,Str "here",Space,Image [Str ""] ("this_is_an_image.png",""),Str "."] ,Header 1 ("attributes",[],[]) [Str "Attributes"] ,Header 2 ("ident",["bar","foo"],[("style","color:red"),("lang","en")]) [Str "HTML",Space,Str "and",Space,Str "CSS",Space,Str "attributes",Space,Str "are",Space,Str "parsed",Space,Str "in",Space,Str "headers",Str "."] ,Para [Str "as",Space,Str "well",Space,Str "as",Space,Strong [Str "inline",Space,Str "attributes"],Space,Str "of",Space,Str " all kind"] ,Para [Str "and",Space,Str "paragraph",Space,Str "attributes",Str ",",Space,Str "and",Space,Str "table",Space,Str "attributes",Str "."] ,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0] [] [[[Plain [Str "name"]] ,[Plain [Str "age"]] ,[Plain [Str "sex"]]] ,[[Plain [Str "joan"]] ,[Plain [Str "24"]] ,[Plain [Str "f"]]]] ,Header 1 ("entities",[],[]) [Str "Entities"] ,Para [Str "*",LineBreak,Str "&"] ,Header 1 ("raw-html",[],[]) [Str "Raw",Space,Str "HTML"] ,Para [Str "However",Str ",",Space,RawInline (Format "html") "",Space,Str "raw",Space,Str "HTML",Space,Str "inlines",Space,RawInline (Format "html") "",Space,Str "are",Space,Str "accepted",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str ":"] ,RawBlock (Format "html") "
" ,Para [Str "any",Space,Strong [Str "Raw",Space,Str "HTML",Space,Str "Block"],Space,Str "with",Space,Str "bold"] ,RawBlock (Format "html") "
" ,Para [Str "Html",Space,Str "blocks",Space,Str "can",Space,Str "be"] ,RawBlock (Format "html") "
" ,Para [Str "inlined"] ,RawBlock (Format "html") "
" ,Para [Str "as",Space,Str "well",Str "."] ,BulletList [[Plain [Str "this",Space,Str "<",Str "div",Str ">",Space,Str "won",Str "\8217",Str "t",Space,Str "produce",Space,Str "raw",Space,Str "html",Space,Str "blocks",Space,Str "<",Str "/div",Str ">"]] ,[Plain [Str "but",Space,Str "this",Space,RawInline (Format "html") "",Space,Str "will",Space,Str "produce",Space,Str "inline",Space,Str "html",Space,RawInline (Format "html") ""]]] ,Para [Str "Can",Space,Str "you",Space,Str "prove",Space,Str "that",Space,Str "2",Space,Str "<",Space,Str "3",Space,Str "?"] ,Header 1 ("raw-latex",[],[]) [Str "Raw",Space,Str "LaTeX"] ,Para [Str "This",Space,Str "Textile",Space,Str "reader",Space,Str "also",Space,Str "accepts",Space,Str "raw",Space,Str "LaTeX",Space,Str "for",Space,Str "blocks",Space,Str ":"] ,RawBlock (Format "latex") "\\begin{itemize}\n \\item one\n \\item two\n\\end{itemize}" ,Para [Str "and",Space,Str "for",Space,RawInline (Format "latex") "\\emph{inlines}",Str "."] ,Header 1 ("acronyms-and-marks",[],[]) [Str "Acronyms",Space,Str "and",Space,Str "marks"] ,Para [Str "PBS (Public Broadcasting System)"] ,Para [Str "Hi",Str "\8482"] ,Para [Str "Hi",Space,Str "\8482"] ,Para [Str "\174",Space,Str "Hi",Str "\174"] ,Para [Str "Hi",Str "\169",Str "2008",Space,Str "\169",Space,Str "2008"] ,Header 1 ("footnotes",[],[]) [Str "Footnotes"] ,Para [Str "A",Space,Str "note",Str ".",Note [Para [Str "The",Space,Str "note",LineBreak,Str "is",Space,Str "here",Str "!"]],Space,Str "Another",Space,Str "note",Note [Para [Str "Other",Space,Str "note",Str "."]],Str "."] ,Header 1 ("comment-blocks",[],[]) [Str "Comment",Space,Str "blocks"] ,Null ,Para [Str "not",Space,Str "a",Space,Str "comment",Str "."]] pandoc-1.12.2.1/tests/textile-reader.textile000644 000765 000024 00000010153 12251233602 020574 0ustar00jgmstaff000000 000000 This is a set of tests for pandoc Textile Reader. Part of it comes from John Gruber's markdown test suite. ----- h1. Headers h2. Level 2 with an "embeded link":http://www.example.com h3. Level 3 with *emphasis* h4. Level 4 h5. Level 5 h6. Level 6 h1. Paragraphs Here's a regular paragraph. Line breaks are preserved in textile, so you can not wrap your very long paragraph with your favourite text editor and have it rendered with no break. Here's one with a bullet. * criminey. There should be a paragraph break between here and here. pandoc converts textile. h1. Block Quotes bq. This is a famous quote from somebody. He had a lot of things to say, so the text is really really long and spans on multiple lines. And a following paragraph. h1. Code Blocks Code:
    ---- (should be four hyphens)

    sub status {
        print "working";
    }

	this code block is indented by one tab
And:
		this code block is indented by two tabs

    These should not be escaped:  \$ \\ \> \[ \{
bc. Code block with .bc continued @@, @. h1. Notextile A block of text can be protected with notextile : No *bold* and * no bullet and inlines can be protected with ==double *equals (=)* markup==. h1. Lists h2. Unordered Asterisks tight: * asterisk 1 * asterisk 2 * asterisk 3 With line breaks: * asterisk 1 newline * asterisk 2 h2. Ordered Tight: # First # Second # Third h2. Nested * ui 1 ** ui 1.1 ### oi 1.1.1 ### oi 1.1.2 ** ui 1.2 * ui 2 ## oi 2.1 *** ui 2.1.1 *** ui 2.1.2 h2. Definition List - coffee := Hot and black - tea := Also hot, but a little less black - milk := Nourishing beverage for baby cows. Cold drink that goes great with cookies.=: - beer := fresh and bitter h1. Inline Markup This is _emphasized_, and so __is this__. This is *strong*, and so **is this**. Hyphenated-words-are-ok, as well as strange_underscore_notation. A "*strong link*":http://www.foobar.com. _*This is strong and em.*_ So is *_this_* word and __**that one**__. -This is strikeout and *strong*- Superscripts: a[^bc^]d a^*hello*^ a[^hello there^]. Subscripts: ~here~ H[~2~]O, H[~23~]O, H[~many of them~]O. Dashes : How cool -- automatic dashes. Elipses : He thought and thought ... and then thought some more. Quotes and apostrophes : "I'd like to thank you" for example. h1. Links h2. Explicit Just a "url":http://www.url.com "Email link":mailto:nobody@nowhere.net Automatic linking to "$":http://www.example.com. "Example":http://www.example.com/: Example of a link followed by a colon. A link["with brackets":http://www.example.com]and no spaces. h1. Tables Textile allows tables with and without headers : h2. Without headers | name | age | sex | | joan | 24 | f | | archie | 29 | m | | bella | 45 | f | and some text following ... h2. With headers |_. name |_. age |_. sex | | joan | 24 | f | | archie | 29 | m | | bella | 45 | f | h1. Images Textile inline image syntax, like here !this_is_an_image.png(this is the alt text)! and here !this_is_an_image.png!. h1. Attributes h2[en]{color:red}(foo bar #ident). HTML and CSS attributes are parsed in headers. as well as *(foo)inline attributes* of %{color:red} all kind% p{color:green}. and paragraph attributes, and table attributes. table{foo:bar}. | name | age | sex | | joan | 24 | f | h1. Entities * & h1. Raw HTML However, raw HTML inlines are accepted, as well as :
any *Raw HTML Block* with bold
Html blocks can be
inlined
as well. * this
won't produce raw html blocks
* but this will produce inline html Can you prove that 2 < 3 ? h1. Raw LaTeX This Textile reader also accepts raw LaTeX for blocks : \begin{itemize} \item one \item two \end{itemize} and for \emph{inlines}. h1. Acronyms and marks PBS(Public Broadcasting System) Hi(tm) Hi (TM) (r) Hi(r) Hi(c)2008 (C) 2008 h1. Footnotes A note.[1] Another note[2]. fn1. The note is here! fn2. Other note. h1. Comment blocks ###. my comment is here. not a comment. pandoc-1.12.2.1/tests/writer.asciidoc000644 000765 000024 00000022617 12251233603 017303 0ustar00jgmstaff000000 000000 Pandoc Test Suite ================= :author: John MacFarlane :author: Anonymous :date: July 17, 2006 This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. ''''' [[headers]] Headers ------- [[level-2-with-an-embedded-link]] Level 2 with an link:/url[embedded link] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [[level-3-with-emphasis]] Level 3 with _emphasis_ ^^^^^^^^^^^^^^^^^^^^^^^ [[level-4]] Level 4 +++++++ [[level-5]] Level 5 [[level-1]] Level 1 ------- [[level-2-with-emphasis]] Level 2 with _emphasis_ ~~~~~~~~~~~~~~~~~~~~~~~ [[level-3]] Level 3 ^^^^^^^ with no blank line [[level-2]] Level 2 ~~~~~~~ with no blank line ''''' [[paragraphs]] Paragraphs ---------- Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. * criminey. There should be a hard line break + here. ''''' [[block-quotes]] Block Quotes ------------ E-mail style: __________________________________________ This is a block quote. It is pretty short. __________________________________________ ______________________ -- Code in a block quote: -------------------- sub status { print "working"; } -------------------- A list: 1. item one 2. item two Nested block quotes: ______ nested ______ ______ nested ______ -- ______________________ This should not be a block quote: 2 > 1. And a following paragraph. ''''' [[code-blocks]] Code Blocks ----------- Code: -------------------------------------- ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab -------------------------------------- And: -------------------------------------------- this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ -------------------------------------------- ''''' [[lists]] Lists ----- [[unordered]] 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]] 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 1. graf two. The quick brown fox jumped over the lazy dog’s back. 2. Item 2. 3. Item 3. [[nested]] 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 [[tabs-and-spaces]] Tabs and spaces ~~~~~~~~~~~~~~~ * this is a list item indented with tabs * this is a list item indented with spaces ** this is an example list item indented with tabs ** this is an example list item indented with spaces [[fancy-list-markers]] Fancy list markers ~~~~~~~~~~~~~~~~~~ 1. begins with 2 2. and now 3 + with a continuation a. sublist with roman numerals, starting with 4 b. more items A. a subsublist B. a subsublist Nesting: A. Upper Alpha A. Upper Roman. 1. Decimal start with 6 a. Lower alpha with paren Autonumbering: 1. Autonumber. 2. More. 1. Nested. Should not be a list item: M.A. 2007 B. Williams ''''' [[definition-lists]] Definition Lists ---------------- Tight using spaces: apple:: red fruit orange:: orange fruit banana:: yellow fruit Tight using tabs: apple:: red fruit orange:: orange fruit banana:: yellow fruit Loose: apple:: red fruit orange:: orange fruit banana:: yellow fruit Multiple blocks with italics: _apple_:: red fruit + contains seeds, crisp, pleasant to taste _orange_:: orange fruit + --------------------- { orange code block } --------------------- + __________________ orange block quote __________________ Multiple definitions, tight: apple:: red fruit + computer orange:: orange fruit + bank Multiple definitions, loose: apple:: red fruit + computer orange:: orange fruit + bank Blank line after term, indented marker, alternate markers: apple:: red fruit + computer orange:: orange fruit + 1. sublist 2. sublist [[html-blocks]] HTML Blocks ----------- Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table: This is _emphasized_ And this is *strong* Here’s a simple block: foo This should be a code block, though: -------
foo
------- As should this: --------------
foo
-------------- Now, nested: foo This should just be an HTML comment: Multiline: Code block: ---------------- ---------------- Just plain comment, with trailing spaces on the line: Code: ------
------ Hr’s: ''''' [[inline-markup]] Inline Markup ------------- This is _emphasized_, and so _is this_. This is *strong*, and so *is this*. An _link:/url[emphasized link]_. *_This is strong and em._* So is *_this_* word. *_This is strong and em._* So is *_this_* word. This is code: `>`, `$`, `\`, `\$`, ``. [line-through]*This is _strikeout_.* Superscripts: a^bc^d a^_hello_^ a^hello there^. Subscripts: H~2~O, H~23~O, H~many of them~O. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. ''''' [[smart-quotes-ellipses-dashes]] Smart quotes, ellipses, dashes ------------------------------ ``Hello,'' said the spider. ```Shelob' is my name.'' `A', `B', and `C' are letters. `Oak,' `elm,' and `beech' are names of trees. So is `pine.' `He said, ``I want to go.''' Were you alive in the 70’s? Here is some quoted ``code`' and a ``http://example.com/?foo=1&bar=2[quoted link]''. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. ''''' [[latex]] LaTeX ----- * * latexmath:[$2+2=4$] * latexmath:[$x \in y$] * latexmath:[$\alpha \wedge \omega$] * latexmath:[$223$] * latexmath:[$p$]-Tree * Here’s some display math: latexmath:[\[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\]] * Here’s one that has a line break in it: latexmath:[$\alpha + \omega \times x^2$]. These shouldn’t be math: * To get the famous equation, write `$e = mc^2$`. * $22,000 is a _lot_ of money. So is $34,000. (It worked if ``lot'' is emphasized.) * Shoes ($20) and socks ($5). * Escaped `$`: $73 _this should be emphasized_ 23$. Here’s a LaTeX table: ''''' [[special-characters]] Special Characters ------------------ Here is some unicode: * I hat: Î * o umlaut: ö * section: § * set membership: ∈ * copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: \{ Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - ''''' [[links]] Links ----- [[explicit]] Explicit ~~~~~~~~ Just a link:/url/[URL]. link:/url/[URL and title]. link:/url/[URL and title]. link:/url/[URL and title]. link:/url/[URL and title] link:/url/[URL and title] link:/url/with_underscore[with_underscore] mailto:nobody@nowhere.net[Email link] link:[Empty]. [[reference]] Reference ~~~~~~~~~ Foo link:/url/[bar]. Foo link:/url/[bar]. Foo link:/url/[bar]. With link:/url/[embedded [brackets]]. link:/url/[b] by itself should be a link. Indented link:/url[once]. Indented link:/url[twice]. Indented link:/url[thrice]. This should [not][] be a link. ----------- [not]: /url ----------- Foo link:/url/[bar]. Foo link:/url/[biz]. [[with-ampersands]] With ampersands ~~~~~~~~~~~~~~~ Here’s a http://example.com/?foo=1&bar=2[link with an ampersand in the URL]. Here’s a link with an amersand in the link text: http://att.com/[AT&T]. Here’s an link:/script?foo=1&bar=2[inline link]. Here’s an link:/script?foo=1&bar=2[inline link in pointy braces]. [[autolinks]] Autolinks ~~~~~~~~~ With an ampersand: http://example.com/?foo=1&bar=2 * In a list? * http://example.com/ * It should. An e-mail address: nobody@nowhere.net ________________________________ Blockquoted: http://example.com/ ________________________________ Auto-links should not occur here: `` ------------------------------ or here: ------------------------------ ''''' [[images]] Images ------ From ``Voyage dans la Lune'' by Georges Melies (1902): image:lalune.jpg[lalune,title="Voyage dans la Lune"] Here is a movie image:movie.jpg[movie] icon. ''''' [[footnotes]] Footnotes --------- Here is a footnote reference,footnote:[Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.] and another.[multiblock footnote omitted] This should _not_ be a footnote reference, because it contains a space.[^my note] Here is an inline note.footnote:[This is _easier_ to type. Inline notes may contain http://google.com[links] and `]` verbatim characters, as well as [bracketed text].] ___________________________________________ Notes can go in quotes.footnote:[In quote.] ___________________________________________ 1. And in list items.footnote:[In list.] This paragraph should not be part of the note, as it is not indented. pandoc-1.12.2.1/tests/writer.context000644 000765 000024 00000034666 12251233602 017217 0ustar00jgmstaff000000 000000 \startmode[*mkii] \enableregime[utf-8] \setupcolors[state=start] \stopmode % Enable hyperlinks \setupinteraction[state=start, color=middleblue] \setuppapersize [letter][letter] \setuplayout [width=middle, backspace=1.5in, cutspace=1.5in, height=middle, topspace=0.75in, bottomspace=0.75in] \setuppagenumbering[location={footer,center}] \setupbodyfont[11pt] \setupwhitespace[medium] \setuphead[chapter] [style=\tfd] \setuphead[section] [style=\tfc] \setuphead[subsection] [style=\tfb] \setuphead[subsubsection][style=\bf] \setuphead[chapter, section, subsection, subsubsection][number=no] \definedescription [description] [headstyle=bold, style=normal, location=hanging, width=broad, margin=1cm] \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 [blockquote] [before={\blank[medium]}, after={\blank[medium]}, indentnext=no, ] \starttext \startalignment[center] \blank[2*big] {\tfd Pandoc Test Suite} \blank[3*medium] {\tfa John MacFarlane\crlf Anonymous} \blank[2*medium] {\tfa July 17, 2006} \blank[3*medium] \stopalignment This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. \thinrule \section[headers]{Headers} \subsection[level-2-with-an-embedded-link]{Level 2 with an \useURL[url1][/url][][embedded link]\from[url1]} \subsubsection[level-3-with-emphasis]{Level 3 with {\em emphasis}} \subsubsubsection[level-4]{Level 4} \subsubsubsubsection[level-5]{Level 5} \section[level-1]{Level 1} \subsection[level-2-with-emphasis]{Level 2 with {\em emphasis}} \subsubsection[level-3]{Level 3} with no blank line \subsection[level-2]{Level 2} with no blank line \thinrule \section[paragraphs]{Paragraphs} Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. * criminey. There should be a hard line break\crlf here. \thinrule \section[block-quotes]{Block Quotes} E-mail style: \startblockquote This is a block quote. It is pretty short. \stopblockquote \startblockquote Code in a block quote: \starttyping sub status { print "working"; } \stoptyping A list: \startitemize[n,packed][stopper=.] \item item one \item item two \stopitemize Nested block quotes: \startblockquote nested \stopblockquote \startblockquote nested \stopblockquote \stopblockquote This should not be a block quote: 2 > 1. And a following paragraph. \thinrule \section[code-blocks]{Code Blocks} Code: \starttyping ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab \stoptyping And: \starttyping this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ \stoptyping \thinrule \section[lists]{Lists} \subsection[unordered]{Unordered} Asterisks tight: \startitemize[packed] \item asterisk 1 \item asterisk 2 \item asterisk 3 \stopitemize Asterisks loose: \startitemize \item asterisk 1 \item asterisk 2 \item asterisk 3 \stopitemize Pluses tight: \startitemize[packed] \item Plus 1 \item Plus 2 \item Plus 3 \stopitemize Pluses loose: \startitemize \item Plus 1 \item Plus 2 \item Plus 3 \stopitemize Minuses tight: \startitemize[packed] \item Minus 1 \item Minus 2 \item Minus 3 \stopitemize Minuses loose: \startitemize \item Minus 1 \item Minus 2 \item Minus 3 \stopitemize \subsection[ordered]{Ordered} Tight: \startitemize[n,packed][stopper=.] \item First \item Second \item Third \stopitemize and: \startitemize[n,packed][stopper=.] \item One \item Two \item Three \stopitemize Loose using tabs: \startitemize[n][stopper=.] \item First \item Second \item Third \stopitemize and using spaces: \startitemize[n][stopper=.] \item One \item Two \item Three \stopitemize Multiple paragraphs: \startitemize[n][stopper=.] \item Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog's back. \item Item 2. \item Item 3. \stopitemize \subsection[nested]{Nested} \startitemize[packed] \item Tab \startitemize[packed] \item Tab \startitemize[packed] \item Tab \stopitemize \stopitemize \stopitemize Here's another: \startitemize[n,packed][stopper=.] \item First \item Second: \startitemize[packed] \item Fee \item Fie \item Foe \stopitemize \item Third \stopitemize Same thing but with paragraphs: \startitemize[n][stopper=.] \item First \item Second: \startitemize[packed] \item Fee \item Fie \item Foe \stopitemize \item Third \stopitemize \subsection[tabs-and-spaces]{Tabs and spaces} \startitemize \item this is a list item indented with tabs \item this is a list item indented with spaces \startitemize \item this is an example list item indented with tabs \item this is an example list item indented with spaces \stopitemize \stopitemize \subsection[fancy-list-markers]{Fancy list markers} \startitemize[n][start=2,left=(,stopper=),width=2.0em] \item begins with 2 \item and now 3 with a continuation \startitemize[r,packed][start=4,stopper=.,width=2.0em] \item sublist with roman numerals, starting with 4 \item more items \startitemize[A,packed][left=(,stopper=),width=2.0em] \item a subsublist \item a subsublist \stopitemize \stopitemize \stopitemize Nesting: \startitemize[A,packed][stopper=.] \item Upper Alpha \startitemize[R,packed][stopper=.] \item Upper Roman. \startitemize[n,packed][start=6,left=(,stopper=),width=2.0em] \item Decimal start with 6 \startitemize[a,packed][start=3,stopper=)] \item Lower alpha with paren \stopitemize \stopitemize \stopitemize \stopitemize Autonumbering: \startitemize[n,packed] \item Autonumber. \item More. \startitemize[a,packed] \item Nested. \stopitemize \stopitemize Should not be a list item: M.A.~2007 B. Williams \thinrule \section[definition-lists]{Definition Lists} Tight using spaces: \startdescription{apple} red fruit \stopdescription \startdescription{orange} orange fruit \stopdescription \startdescription{banana} yellow fruit \stopdescription Tight using tabs: \startdescription{apple} red fruit \stopdescription \startdescription{orange} orange fruit \stopdescription \startdescription{banana} yellow fruit \stopdescription Loose: \startdescription{apple} red fruit \stopdescription \startdescription{orange} orange fruit \stopdescription \startdescription{banana} yellow fruit \stopdescription Multiple blocks with italics: \startdescription{{\em apple}} red fruit contains seeds, crisp, pleasant to taste \stopdescription \startdescription{{\em orange}} orange fruit \starttyping { orange code block } \stoptyping \startblockquote orange block quote \stopblockquote \stopdescription Multiple definitions, tight: \startdescription{apple} red fruit computer \stopdescription \startdescription{orange} orange fruit bank \stopdescription Multiple definitions, loose: \startdescription{apple} red fruit computer \stopdescription \startdescription{orange} orange fruit bank \stopdescription Blank line after term, indented marker, alternate markers: \startdescription{apple} red fruit computer \stopdescription \startdescription{orange} orange fruit \startitemize[n,packed][stopper=.] \item sublist \item sublist \stopitemize \stopdescription \section[html-blocks]{HTML Blocks} Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table: This is {\em emphasized} And this is {\bf strong} Here's a simple block: foo This should be a code block, though: \starttyping
foo
\stoptyping As should this: \starttyping
foo
\stoptyping Now, nested: foo This should just be an HTML comment: Multiline: Code block: \starttyping \stoptyping Just plain comment, with trailing spaces on the line: Code: \starttyping
\stoptyping Hr's: \thinrule \section[inline-markup]{Inline Markup} This is {\em emphasized}, and so {\em is this}. This is {\bf strong}, and so {\bf is this}. An {\em \useURL[url2][/url][][emphasized link]\from[url2]}. {\bf {\em This is strong and em.}} So is {\bf {\em this}} word. {\bf {\em This is strong and em.}} So is {\bf {\em this}} word. This is code: \type{>}, \type{$}, \type{\}, \type{\$}, \type{}. \overstrikes{This is {\em strikeout}.} Superscripts: a\high{bc}d a\high{{\em hello}} a\high{hello~there}. Subscripts: H\low{2}O, H\low{23}O, H\low{many~of~them}O. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a\lettertilde{}b c\lettertilde{}d. \thinrule \section[smart-quotes-ellipses-dashes]{Smart quotes, ellipses, dashes} \quotation{Hello,} said the spider. \quotation{\quote{Shelob} is my name.} \quote{A}, \quote{B}, and \quote{C} are letters. \quote{Oak,} \quote{elm,} and \quote{beech} are names of trees. So is \quote{pine.} \quote{He said, \quotation{I want to go.}} Were you alive in the 70's? Here is some quoted \quote{\type{code}} and a \quotation{\useURL[url3][http://example.com/?foo=1&bar=2][][quoted link]\from[url3]}. Some dashes: one---two --- three---four --- five. Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses\ldots{}and\ldots{}and\ldots{}. \thinrule \section[latex]{LaTeX} \startitemize[packed] \item \cite[22-23]{smith.1899} \item $2+2=4$ \item $x \in y$ \item $\alpha \wedge \omega$ \item $223$ \item $p$-Tree \item Here's some display math: \startformula \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h} \stopformula \item Here's one that has a line break in it: $\alpha + \omega \times x^2$. \stopitemize These shouldn't be math: \startitemize[packed] \item To get the famous equation, write \type{$e = mc^2$}. \item \$22,000 is a {\em lot} of money. So is \$34,000. (It worked if \quotation{lot} is emphasized.) \item Shoes (\$20) and socks (\$5). \item Escaped \type{$}: \$73 {\em this should be emphasized} 23\$. \stopitemize Here's a LaTeX table: \thinrule \section[special-characters]{Special Characters} Here is some unicode: \startitemize[packed] \item I hat: Î \item o umlaut: ö \item section: § \item set membership: ∈ \item copyright: © \stopitemize AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \letterbackslash{} Backtick: ` Asterisk: * Underscore: _ Left brace: \{ Right brace: \} Left bracket: {[} Right bracket: {]} Left paren: ( Right paren: ) Greater-than: > Hash: \# Period: . Bang: ! Plus: + Minus: - \thinrule \section[links]{Links} \subsection[explicit]{Explicit} Just a \useURL[url4][/url/][][URL]\from[url4]. \useURL[url5][/url/][][URL and title]\from[url5]. \useURL[url6][/url/][][URL and title]\from[url6]. \useURL[url7][/url/][][URL and title]\from[url7]. \useURL[url8][/url/][][URL and title]\from[url8] \useURL[url9][/url/][][URL and title]\from[url9] \useURL[url10][/url/with_underscore][][with_underscore]\from[url10] \useURL[url11][mailto:nobody@nowhere.net][][Email link]\from[url11] \useURL[url12][][][Empty]\from[url12]. \subsection[reference]{Reference} Foo \useURL[url13][/url/][][bar]\from[url13]. Foo \useURL[url14][/url/][][bar]\from[url14]. Foo \useURL[url15][/url/][][bar]\from[url15]. With \useURL[url16][/url/][][embedded {[}brackets{]}]\from[url16]. \useURL[url17][/url/][][b]\from[url17] by itself should be a link. Indented \useURL[url18][/url][][once]\from[url18]. Indented \useURL[url19][/url][][twice]\from[url19]. Indented \useURL[url20][/url][][thrice]\from[url20]. This should {[}not{]}{[}{]} be a link. \starttyping [not]: /url \stoptyping Foo \useURL[url21][/url/][][bar]\from[url21]. Foo \useURL[url22][/url/][][biz]\from[url22]. \subsection[with-ampersands]{With ampersands} Here's a \useURL[url23][http://example.com/?foo=1&bar=2][][link with an ampersand in the URL]\from[url23]. Here's a link with an amersand in the link text: \useURL[url24][http://att.com/][][AT&T]\from[url24]. Here's an \useURL[url25][/script?foo=1&bar=2][][inline link]\from[url25]. Here's an \useURL[url26][/script?foo=1&bar=2][][inline link in pointy braces]\from[url26]. \subsection[autolinks]{Autolinks} With an ampersand: \useURL[url27][http://example.com/?foo=1&bar=2][][\hyphenatedurl{http://example.com/?foo=1&bar=2}]\from[url27] \startitemize[packed] \item In a list? \item \useURL[url28][http://example.com/][][\hyphenatedurl{http://example.com/}]\from[url28] \item It should. \stopitemize An e-mail address: \useURL[url29][mailto:nobody@nowhere.net][][\hyphenatedurl{nobody@nowhere.net}]\from[url29] \startblockquote Blockquoted: \useURL[url30][http://example.com/][][\hyphenatedurl{http://example.com/}]\from[url30] \stopblockquote Auto-links should not occur here: \type{} \starttyping or here: \stoptyping \thinrule \section[images]{Images} From \quotation{Voyage dans la Lune} by Georges Melies (1902): \placefigure{lalune}{\externalfigure[lalune.jpg]} Here is a movie {\externalfigure[movie.jpg]} icon. \thinrule \section[footnotes]{Footnotes} Here is a footnote reference,\footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.} and another.\startbuffer Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). \starttyping { } \stoptyping If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.\stopbuffer\footnote{\getbuffer} This should {\em not} be a footnote reference, because it contains a space.{[}^my note{]} Here is an inline note.\footnote{This is {\em easier} to type. Inline notes may contain \useURL[url31][http://google.com][][links]\from[url31] and \type{]} verbatim characters, as well as {[}bracketed text{]}.} \startblockquote Notes can go in quotes.\footnote{In quote.} \stopblockquote \startitemize[n,packed][stopper=.] \item And in list items.\footnote{In list.} \stopitemize This paragraph should not be part of the note, as it is not indented. \stoptext pandoc-1.12.2.1/tests/writer.docbook000644 000765 000024 00000071124 12251233602 017141 0ustar00jgmstaff000000 000000
Pandoc Test Suite John MacFarlane Anonymous July 17, 2006 This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. Headers Level 2 with an <ulink url="/url">embedded link</ulink> Level 3 with <emphasis>emphasis</emphasis> Level 4 Level 5 Level 1 Level 2 with <emphasis>emphasis</emphasis> Level 3 with no blank line Level 2 with no blank line Paragraphs Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. * criminey. There should be a hard line break here. Block Quotes E-mail style:
This is a block quote. It is pretty short.
Code in a block quote: sub status { print "working"; } A list: item one item two Nested block quotes:
nested
nested
This should not be a block quote: 2 > 1. And a following paragraph.
Code Blocks Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ Lists 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: First Second Third and: One Two Three Loose using tabs: First Second Third and using spaces: One Two Three Multiple paragraphs: Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog’s back. Item 2. Item 3. Nested Tab Tab Tab Here’s another: First Second: Fee Fie Foe Third Same thing but with paragraphs: First Second: Fee Fie Foe Third Tabs and spaces this is a list item indented with tabs this is a list item indented with spaces this is an example list item indented with tabs this is an example list item indented with spaces Fancy list markers begins with 2 and now 3 with a continuation sublist with roman numerals, starting with 4 more items a subsublist a subsublist Nesting: Upper Alpha Upper Roman. Decimal start with 6 Lower alpha with paren Autonumbering: Autonumber. More. Nested. Should not be a list item: M.A. 2007 B. Williams Definition Lists Tight using spaces: apple red fruit orange orange fruit banana yellow fruit Tight using tabs: apple red fruit orange orange fruit banana yellow fruit Loose: apple red fruit orange orange fruit banana yellow fruit Multiple blocks with italics: apple red fruit contains seeds, crisp, pleasant to taste orange orange fruit { orange code block }
orange block quote
Multiple definitions, tight: apple red fruit computer orange orange fruit bank Multiple definitions, loose: apple red fruit computer orange orange fruit bank Blank line after term, indented marker, alternate markers: apple red fruit computer orange orange fruit sublist sublist
HTML Blocks Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table:
This is emphasized And this is strong
Here’s a simple block: foo This should be a code block, though: <div> foo </div> As should this: <div>foo</div> Now, nested: foo This should just be an HTML comment: Multiline: Code block: <!-- Comment --> Just plain comment, with trailing spaces on the line: Code: <hr /> Hr’s:








Inline Markup This is emphasized, and so is this. This is strong, and so is this. An emphasized link. This is strong and em. So is this word. This is strong and em. So is this word. This is code: >, $, \, \$, <html>. This is strikeout. Superscripts: abcd ahello ahello there. Subscripts: H2O, H23O, Hmany of themO. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. Smart quotes, ellipses, dashes Hello, said the spider. Shelob is my name. A, B, and C are letters. Oak, elm, and beech are names of trees. So is pine. He said, I want to go. Were you alive in the 70’s? Here is some quoted code and a quoted link. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. LaTeX 2 + 2 = 4 x ∈ y α ∧ ω 223 p-Tree Here’s some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ Here’s one that has a line break in it: α + ω × x2. These shouldn’t be math: To get the famous equation, write $e = mc^2$. $22,000 is a lot of money. So is $34,000. (It worked if lot is emphasized.) Shoes ($20) and socks ($5). Escaped $: $73 this should be emphasized 23$. Here’s a LaTeX table: Special Characters Here is some unicode: I hat: Î o umlaut: ö section: § set membership: ∈ copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - Links Explicit Just a URL. URL and title. URL and title. URL and title. URL and title URL and title with_underscore Email link (nobody@nowhere.net) Empty. Reference Foo bar. Foo bar. Foo bar. With embedded [brackets]. b by itself should be a link. Indented once. Indented twice. Indented thrice. This should [not][] be a link. [not]: /url Foo bar. Foo biz. With ampersands Here’s a link with an ampersand in the URL. Here’s a link with an amersand in the link text: AT&T. Here’s an inline link. Here’s an inline link in pointy braces. Autolinks With an ampersand: http://example.com/?foo=1&bar=2 In a list? http://example.com/ It should. An e-mail address: nobody@nowhere.net
Blockquoted: http://example.com/
Auto-links should not occur here: <http://example.com/> or here: <http://example.com/>
Images From Voyage dans la Lune by Georges Melies (1902):
lalune lalune
Here is a movie icon.
Footnotes Here is a footnote reference, Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. and another. Here’s the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). { <code> } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. This should not be a footnote reference, because it contains a space.[^my note] Here is an inline note. This is easier to type. Inline notes may contain links and ] verbatim characters, as well as [bracketed text].
Notes can go in quotes. In quote.
And in list items. In list. This paragraph should not be part of the note, as it is not indented.
pandoc-1.12.2.1/tests/writer.fb2000644 000765 000024 00000126226 12251233603 016177 0ustar00jgmstaff000000 000000 Pandoc Test SuiteJohnMacFarlaneAnonymousJuly 17, 2006pandoc<p>Pandoc Test Suite</p>

John MacFarlane

Anonymous

July 17, 2006

This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.

——————————

<p>Headers</p>
<p>Level 2 with an embedded link </url></p>
<p>Level 3 with emphasis</p>
<p>Level 4</p>
<p>Level 5</p>
<p>Level 1</p>
<p>Level 2 with emphasis</p>
<p>Level 3</p>

with no blank line

<p>Level 2</p>

with no blank line

——————————

<p>Paragraphs</p>

Here’s a regular paragraph.

In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.

Here’s one with a bullet. * criminey.

There should be a hard line breakhere.

——————————

<p>Block Quotes</p>

E-mail style:

This is a block quote. It is pretty short.

Code in a block quote:

sub status {

print "working";

}

A list:

 1. item one

 2. item two

Nested block quotes:

nested

nested

This should not be a block quote: 2 > 1.

And a following paragraph.

——————————

<p>Code Blocks</p>

Code:

---- (should be four hyphens)

sub status {

print "working";

}

this code block is indented by one tab

And:

this code block is indented by two tabs

These should not be escaped: \$ \\ \> \[ \{

——————————

<p>Lists</p>
<p>Unordered</p>

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

<p>Ordered</p>

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 1. graf two. The quick brown fox jumped over the lazy dog’s back.

 2. Item 2.

 3. Item 3.

<p>Nested</p>

• 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

<p>Tabs and spaces</p>

• this is a list item indented with tabs

• this is a list item indented with spaces

◦ this is an example list item indented with tabs

◦ this is an example list item indented with spaces

<p>Fancy list markers</p>

 (2) begins with 2

 (3) and now 3with a continuation

 (3) iv. sublist with roman numerals, starting with 4

 (3) v. more items

 (3) v. (A) a subsublist

 (3) v. (B) a subsublist

Nesting:

 A. Upper Alpha

 A. I. Upper Roman.

 A. I. (6) Decimal start with 6

 A. I. (6) c) Lower alpha with paren

Autonumbering:

 1. Autonumber.

 2. More.

 2. 1. Nested.

Should not be a list item:

M.A. 2007

B. Williams

——————————

<p>Definition Lists</p>

Tight using spaces:

apple

    red fruit

orange

    orange fruit

banana

    yellow fruit

Tight using tabs:

apple

    red fruit

orange

    orange fruit

banana

    yellow fruit

Loose:

apple

    red fruit

orange

    orange fruit

banana

    yellow fruit

Multiple blocks with italics:

apple

    red fruit    contains seeds, crisp, pleasant to taste

orange

    orange fruit

    { orange code block }

    orange block quote

Multiple definitions, tight:

apple

    red fruit    computer

orange

    orange fruit    bank

Multiple definitions, loose:

apple

    red fruit    computer

orange

    orange fruit    bank

Blank line after term, indented marker, alternate markers:

apple

    red fruit    computer

orange

    orange fruit

 1. sublist

 2. sublist

<p>HTML Blocks</p>

Simple block on one line:

foo

And nested without indentation:

foobar

Interpreted markdown in a table:

<table>

<tr>

<td>

This is emphasized

</td>

<td>

And this is strong

</td>

</tr>

</table>

<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>

Here’s a simple block:

foo

This should be a code block, though:

<div>

foo

</div>

As should this:

<div>foo</div>

Now, nested:

foo

This should just be an HTML comment:

<!-- Comment -->

Multiline:

<!--

Blah

Blah

-->

<!--

This is another comment.

-->

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">

——————————

<p>Inline Markup</p>

This is emphasized, and so is this.

This is strong, and so is this.

An emphasized link[1].

This is strong and em.

So is this word.

This is strong and em.

So is this word.

This is code: >, $, \, \$, <html>.

This is strikeout.

Superscripts: abcd ahello ahello there.

Subscripts: H2O, H23O, Hmany of themO.

These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.

——————————

<p>Smart quotes, ellipses, dashes</p>

“Hello,” said the spider. “‘Shelob’ is my name.”

‘A’, ‘B’, and ‘C’ are letters.

‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’

‘He said, “I want to go.”’ Were you alive in the 70’s?

Here is some quoted ‘code’ and a “quoted link[2]”.

Some dashes: one—two — three—four — five.

Dashes between numbers: 5–7, 255–66, 1987–1999.

Ellipses…and…and….

——————————

<p>LaTeX</p>

• 

• 2+2=4

• x \in y

• \alpha \wedge \omega

• 223

• p-Tree

• Here’s some display math: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}

• Here’s one that has a line break in it: \alpha + \omega \times x^2.

These shouldn’t be math:

• To get the famous equation, write $e = mc^2$.

• $22,000 is a lot of money. So is $34,000. (It worked if “lot” is emphasized.)

• Shoes ($20) and socks ($5).

• Escaped $: $73 this should be emphasized 23$.

Here’s a LaTeX table:

\begin{tabular}{|l|l|}\hline

Animal & Number \\ \hline

Dog & 2 \\

Cat & 1 \\ \hline

\end{tabular}

——————————

<p>Special Characters</p>

Here is some unicode:

• I hat: Î

• o umlaut: ö

• section: §

• set membership: ∈

• copyright: ©

AT&T has an ampersand in their name.

AT&T is another way to write it.

This & that.

4 < 5.

6 > 5.

Backslash: \

Backtick: `

Asterisk: *

Underscore: _

Left brace: {

Right brace: }

Left bracket: [

Right bracket: ]

Left paren: (

Right paren: )

Greater-than: >

Hash: #

Period: .

Bang: !

Plus: +

Minus: -

——————————

<p>Links</p>
<p>Explicit</p>

Just a URL[3].

URL and title[4].

URL and title[5].

URL and title[6].

URL and title[7]

URL and title[8]

with_underscore[9]

Email link[10]

Empty[11].

<p>Reference</p>

Foo bar[12].

Foo bar[13].

Foo bar[14].

With embedded [brackets][15].

b[16] by itself should be a link.

Indented once[17].

Indented twice[18].

Indented thrice[19].

This should [not][] be a link.

[not]: /url

Foo bar[20].

Foo biz[21].

<p>With ampersands</p>

Here’s a link with an ampersand in the URL[22].

Here’s a link with an amersand in the link text: AT&T[23].

Here’s an inline link[24].

Here’s an inline link in pointy braces[25].

<p>Autolinks</p>

With an ampersand: http://example.com/?foo=1&bar=2[26]

• In a list?

• http://example.com/[27]

• It should.

An e-mail address: nobody@nowhere.net[28]

Blockquoted: http://example.com/[29]

Auto-links should not occur here: <http://example.com/>

or here: <http://example.com/>

——————————

<p>Images</p>

From “Voyage dans la Lune” by Georges Melies (1902):

lalune

Here is a movie movie icon.

——————————

<p>Footnotes</p>

Here is a footnote reference,[30] and another.[31] This should not be a footnote reference, because it contains a space.[^my note] Here is an inline note.[32]

Notes can go in quotes.[33]

 1. And in list items.[34]

This paragraph should not be part of the note, as it is not indented.

<p>1</p>

/url

<p>2</p>

http://example.com/?foo=1&bar=2

<p>3</p>

/url/

<p>4</p>

title: /url/

<p>5</p>

title preceded by two spaces: /url/

<p>6</p>

title preceded by a tab: /url/

<p>7</p>

title with "quotes" in it: /url/

<p>8</p>

title with single quotes: /url/

<p>9</p>

/url/with_underscore

<p>10</p>

mailto:nobody@nowhere.net

<p>11</p>

<p>12</p>

/url/

<p>13</p>

/url/

<p>14</p>

/url/

<p>15</p>

/url/

<p>16</p>

/url/

<p>17</p>

/url

<p>18</p>

/url

<p>19</p>

/url

<p>20</p>

Title with "quotes" inside: /url/

<p>21</p>

Title with "quote" inside: /url/

<p>22</p>

http://example.com/?foo=1&bar=2

<p>23</p>

AT&T: http://att.com/

<p>24</p>

/script?foo=1&bar=2

<p>25</p>

/script?foo=1&bar=2

<p>26</p>

http://example.com/?foo=1&bar=2

<p>27</p>

http://example.com/

<p>28</p>

mailto:nobody@nowhere.net

<p>29</p>

http://example.com/

<p>30</p>

Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.

<p>31</p>

Here’s the long note. This one contains multiple blocks.

Subsequent blocks are indented to show that they belong to the footnote (as with list items).

{ <code> }

If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.

<p>32</p>

This is easier to type. Inline notes may contain links[32] and ] verbatim characters, as well as [bracketed text].

<p>33</p>

In quote.

<p>34</p>

In list.

/9j/4AAQSkZJRgABAQEASABIAAD//gBQVGhpcyBhcnQgaXMgaW4gdGhlIHB1YmxpYyBkb21haW4uIEtldmluIEh1Z2hlcywga2V2aW5oQGVpdC5jb20sIFNlcHRlbWJlciAxOTk1/9sAQwABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/9sAQwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/8AAEQgAFgAUAwEiAAIRAQMRAf/EABoAAQACAwEAAAAAAAAAAAAAAAAICQUGCgf/xAAjEAABBQEAAwABBQAAAAAAAAAGAwQFBwgCAAEJChEVOXa3/8QAFgEBAQEAAAAAAAAAAAAAAAAABggA/8QAJhEBAAECBQEJAAAAAAAAAAAAAQIAAwQFBhEhszE0NlFUcXR1tP/aAAwDAQACEQMRAD8AqQzziPNmpiqnIO1q4H+WkB84MdlzRSuM82/jVw/JCORtRmQz5d2VTy6WmS2eSYx3U/qkSRbgFsqRzH2Is4/mCluXc33vy8xTnJjTNqV/T8LKmkhr8Hq1da2aOvTfIh2CFeNt+GxFBP8AJFdFUbPWh+4FdXV7OtZOMR7mK9lBWNN+JBmMQ5cwmfH8DEFhTZUCRlE6CBq/ds/nBh9oYygeY1L9FnCUnBSN1t+w0l9bNomx1cllsOrL9OCTKtKOIqua6UVjP0dEvTyM7gp/3whbkAD0ScX3r6MLg+C2/XsMhCnJRn/5cVNHyJHiX6JKIFhhqnFeagm9BIgjfcJyNBTZiROBUk6Mp8CJRmT4NWU2MatV7n495DPk/wAbMJSRJOTBDItq0KR5s/nJN7LPW8AJWtYAoKQaDp+u4XShxgXhYcbHoxNTllCwETGQ8ag2jmDVsk8w/wCOp/C/hn+mWV/utpePH+D5wmF39NY6UakjUYR1Dn0YgRM5zQAAAMdfAA4AOAOArjkMNQ3vgm7UKtBR+m9QHFD5tpnDtpy+t2R20gK/OsmFtuDpaL5mVyiT5qdEVAvZci5ch5VoSGKbwlWTBr0RPoZT07av9lHfrXo6yLApWMugKpPM9SV1cDm65s/wkOHZBojoqiM+6GpMSj4FhtayNAUi5H3LfQBG2KWssFoSPuJdKyMLKtpuLi+e3jwFICUg7CSHsNVlYlKdizOTvKdq3KTsG8pQirsAG6vAB5FdhP490U4gfjxi+DedoqO4YftmKdKNulO26jiOv+2Ga/bftVNFXpHtVHrpLpRFJTpP3z77T469++fTx48e4LueE+NY6UKk7UniLP8A7rNf3X6//9k=/9j/4AAQSkZJRgABAQEAeAB4AAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAD6APoDAREAAhEBAxEB/8QAHAAAAAcBAQAAAAAAAAAAAAAAAQIDBAUGBwAI/8QAPhAAAgEDAwIEBAQFAgUFAAMAAQIDAAQRBRIhBjETIkFRB2FxgRQykaEjQlKxwRXwFjNictEIJEPh8SZTgv/EABcBAQEBAQAAAAAAAAAAAAAAAAABAgT/xAAbEQEBAQEAAwEAAAAAAAAAAAAAARECEiExQf/aAAwDAQACEQMRAD8A2t0YoQpwT2qVzMV+N3UHgrDY2eoM0y58VEbgfp9K1yMRmnuJ5h40jyYHGSeKrWE8u2QAApOMdqGCsmT8h70TAJwMAZx249aKBy4c9vTNUC0zDCgmmmG7Ockjkj1PrUTAjcy5XP0ouCgHae4IomOJHhgIc55PHY0Uk5IXLMcUBQ27n96JYO2MYLebHtRBA7BcMx29sdxQJqwZRtIP+BQKpjHHc+xzigNGoAO/k+nPAoAYlee5oBiGeWySO9AJCgY5PHagFCADzj2GaA2N2TkjA/U0HMwbPPeiyBLDfkkj04FCl1cBMgn6URwYFGySR6D2oAeQDAxnHGKAhU4IbGc+tFwnwDj9aK7f8v2oNu+IHxNvJdXmt9EmKWSqArA/mPvxUxMZNe3Ml1dvNcMzSSEsxPOferJhht/OWyAPc0UfdgDcuM8n50AMCykZFARsngcY/egTcbjnJz9O9AB2kZGSQOcUCX8x83bntQCMruJ4B7D1oCyOGzxtJ9M80CAdg5UjFE0aFJrghLeNpHY4IRdx/QUNWCw6D6q1EZttEvirHAZ4ig/U4qw1b9H+CHVN3Mq6hJaWMJ5ZjJ4hA/7R3P3q3ET+pf8Ap/lWNm03XkkkA8qTW+3PHupP9qxopV78G+s7VSV0+OcAn/kzqSfscVvIKzqPTWu6XKE1LSL+Bhz5oDg/cd6lEZzGwLrtPqrA8frUCJfcw9gfegUjZsEAffNADyHt78UAjCjzDJxRcO5Pw3gwCGOVJQp8ZncMGOeNoxwMY96GCbQffFFcUXKjDDt2NEo+N3yyM5z3okKuqJgIzONoJyuMGi4QfGcqSfXBoYHJx659qKIRnnsfUGgJn/poJYoTIGLY+eDzQFlQK2G/KCTmgbspfO0qce/agPGcR7nHf9vnQFfBPlOc88Gg7uucc/M0Bd208YJJweKAYrea4kKQICRGW5IUYUZJ570DYqcknt3FE0VuVyDzj1oamOlulda6puvC0a0eZVIWSbtGn1Y1NNbX0x8ENH0qL8X1NdtqDoNxiQbIh8u+WpqL70Tc6fcxypouiRadbW8hhLFFXcB7Edz+tNFvEZxkmmgShbA9PlUA+Hgg/wBqDgmBkd6ArJuJBGR7VdEdqWgaVqMfh6hp9pcLj/5Ig2KaKJrvwW6S1EFoLaWwmPIe2fAz81ORTRm3UfwI1mzBbRL+K/ReyS/w3x/b+1Wexmev9O6xoE2zWdOubUDszr5T9G7H9auCJj2n3PPrUXTlGBB2kYx96GlQMjJJHuRRXBgDgk8DtRKH8w4OfYA0SUlIMsFXJ4oujHH8ufnRRGOSNoJNAeFC77F2jPucfvQFEqgY3nj/AKaCUY58wwq54AoCzOmVMke9QeRnGR7ZoEIF7pnaTk49KDpSSwQntQJsGKjgggZ9uDQc4OOe1Am2UCkHOR7dqA8t/cSW8MEkrGGEsUTPCk4zj9KJT3pzQtS6m1aPT9Jh8SVxlmJwqL/UfYURuuhfArR7f8NLrF1cXciKDJCrbI2b7c4+9NGtaRptrpdqltYW0VtAn5Y41wBUodvGjqUdQyn0YZqAIreOBFSFFRF7BQAKA1xcRwKplcJuOBn1NAR7y2ikWMzoZnGVQHJNAuQcD3oBKkD2FBy8jnvQFxnjjmg4rxwKBMqCBtPNA3vbCC+tngvYo54HGGSRQQR9DV0Y91n8DNOvFkuOmZmsrk5PgSNuiY98D1X+1XRhWu6DqWgX72er2j2069t/ZvmD2IoGG7jbnj1FFlB224PB+VClN4DYJHyAojmPGCck8cetCAxgjPp6UaAGKtx6+9ATAXO7nFBw8HHLN+goJhBuj2FeAcnmgNazW8U0vjweODGyqpYrsYjytx3x3oGa5LEEjH9XvQGlgmjjMmQq4HBPfPYgevagG5nhe3tkFuInQHxJQTmQntn0wKBKTlAeDx60DSY+U9zn+mgsnQvROr9Y3W2xi8KxV8SXUnCrjvj1Y/IUR6c6A6H03o6wMVgrSXMoBmuX/NIf8Djt/eiLfjJwO9ZBiOfmKDhktzQAzYBLZ8oyaDF+rOptVv8AUjNZL4tjA/lT+kr3wvqTQX/pi3Y+DqFxKXurmFWAaPaVzg4I/b0oHlxqV7penRTXFu93dPLsESYB2k8n7CgnradLq1WaIOFI/K42sPkRQCg3Kcd6Dgp3d6AdrGg5VxnjmgKWB8uQGxnFAUgKuSefSghuqNC0jXbAWGtxQyJKdsYc4YMf6T6GtDzR8S/hnqfSUz3NvuvNILYSZR5o+ezj/Pb6UGfLzyD/AJoFFySQVBHpQDJ5kGByPahAbWxn5+po0OF3D+XPtQJsNwOe+aAuygmMkebgHnHFALHYpJwSeGz2oGpOJWAI49BQEZlYAHkg4oARVOMvtBIJJ7AUAX6xxSOsUgmjViFcKRuHviiVfvhT8NZuqpk1LVFeHRkPlHZpznsP+n50qPS+mWVppdnFa2cEcFtGu1I41ChR8qyHVxK8cLPDD4kgGVQHBNAa0maaBJGTYzDJXOcUCy5JOaA2OMfoaArkheM7vlQNYNOtoWLJCgLHJwo5NApPKLaNpGRQB6j2oGmnRvcyNd3O/DkeErLhkWgklIdCyZOCRzxzQEeRxhdpUnncBkD5UCxXjJ7+tAlctMsIMLohz5mcZAH09aBQYdQwyAeaAuA7MAQxHH0oG1481nbGVInuWU5Kr+bHrgepoKB1u+o6jqlvBH05NevEBPBK0pQR4I4BHZj+1Bb9IS7lsFtNWtYwDGFYB/EXHqpJ7/WtQYx8VfhGbdZtV6Uh8gy81mpyR6koPb5UGKY4YkeYd88fbFAI5AC98c5oQBb+U9+9GnN5RgDgjOPWgAN3yMfWgAqc91/UUD2RSSRg9+49KCR6e0WfX9WS0icRwgb55WOFijH5nP0FBYNRi6dSR7HRNPmu0hOW1GaXaZMdwBwAP3oynE0XRYrFtV02wS4ECj8dp1wcsE7eJEf39qlFZ616ZttPu7Kbp9Zbi0vYzNCcgjHqoHuKsEp8LPh7P1PqjXerxywaXaviRSu1pWH8g+XuflQemIIY7S3SK3hVIo12pGoAAA7AClEL1N1RH0/oTalcwx+IACLaSQKx59Ppmshv0D1jH1ZbTubU27xkkAnKsuSMg/UUFluLlLaJXETyecKAg554zigXiubeRnSKeJ5FOGVXBIPsaBLULoWkIfw3kYsAqIOSTQJMbpm3oqlmwACeF9yfn+1A+Bx34oE5IY5P+YFbnPIzQKAckHuRQCAQOO1AL8r9KDhkZOT9M8UCcrxgAyYJzwD70CT3Itxm8kgi3fly+P7/AOKA9pskhEkZysnOfeg6RH8w3tgjAHtQRZ1uystSg0m5eRJ2UbHceV8fP3oJkBSAVII9xQFdSRwKDDvjN8L/AMSJte6chxcgFrm1QcSf9aj39x61YMH8Q+CkfhqpQncxBDH5H6VRwXJ/Ke1Am2QchuMYOaNFSAVznB9qAm8f10D2RmX8jDHP3oLbebtA6ej0m2LrfX6LcX7IMskf8kf6HcffIoG8yTadZxSTxCK3kRZUwSFfkruIJ78GhiS6Y1OS3160uZJFWO5bwZtxzuQ8bcfPNMZXvo2wsLnQ9R0q/maJNNv5Yo3bjCuMAHPzqA2jdUan0lF0/ZXcElxp9zE+5WVd/DE71IPPB7H2po1bSNXsdYthLp1ykyEcj+ZT817ioITrnoux6vs1gv5JYnjz4ckZ/Ln5etA+6N0BemdBttMina4WEFfFdQpIJJ7D60E5I4Vo9qnnsQO1A3k0yzeTxhCizZJ3qNpz9RQO449igMSxHGW5NAIwBtUAUAMORkfegMhG3jtQD8+fvQGXJz7UAHuRQA5YDI5FB0qCQA5yaCs2/SFit/Jd3AmvJ2bO64ctt5zwD2oLMilVAUDgcAelAJLbhgZz3oGN9HPIYmhtrWRw2czjt7Y+dA+h3mJS67W9gc0AvuLYANADpkZABHY85oPOnxy+Hx06Z+odGjC2jt/7qBRwjH+cY9D6/OrKMebcceHwfaqCYIyDgZ96GhHOFJI4/WjQpXnsaCz9J6fDqGvRC8OLO3Vri5PB/hqMkfc4H3oDT3UupapcXrKS9zISgDdhnAGPbsKC5aLLBHq9p01c6bbagPE23kpJYhmz5IySAAMj6nNGdRnT2lu3V9vaQQrJDHfCMFj5kAfufsMUFogu5H0jrLUYXK+Lq0aRse/lf/8AOKlFfudagvbnQpNQRmtILydCwPdCQcgMOMZFQanPoeiawBd9M6s9jeKPK1vKQp+RFA4septa6fuFtuqbRrmzx5b+BAdo927A+vsflQXfTr2z1O3W5025juIW/mjOR9KAZI914khaRNo4XdwT9KAl3b2+oWpjMoZWbOVfnI9sUCrXUNssUU8w3sQoJH5jQLvwQQC3NAKvuUPtK54waDg23v6UA7weBnNAIOBigMr+hoOjdZQdhBx3waAVG0Z7UBWfAOQSflQChyNxBAxQRutarb6bHALi9trSW4kEcJnGd7ewFA/j8QEK/IA/MBjmgWDDBB7igj9dupLTTbiaHZ4oQ7A7bQW9ATVgwXSNV6onl8azW6t45pWdxHIxWA/zNtz7A8Glg2S1u7fX+nt0J/H2c4MMhmQoW9GBUjj60g8sfEHpebpDqi4sHLG2Y77eQ486E8fcdvtVFekGW4UfegKVAAKgnFGhuDzxQXbpDTZF6a13UnUqrCOzQ5wGZmXIJ+lE0ppkEK6nJcRWcTW9hA08iKcjcowpye/mxQ0+6VRbC/jvLm48L8LG9y8pIOXxkDnuSTipqHXQMng3es9S3fhn8DbvcZI5Mr/lH700dc3Dad8NtPs4nU6jeXD6nMCwBRF5XOfU8YHrTNJFF1X8RawW1jc4GxTKNrZB385yPkBTFw1stSu7Ni9tPLGSQfK5Aphi8J8UNUm6fn0u72yvJ5fGbuF/39aYYtGgadp9/axXnRetzaXqnhqZI3bEcj4547Ak/X6UxFisPiXe6NMdO65057eQAr+LhUlHHbOPX07UwWXpQ6BqMo1LpgW0sioVI8Qgxk+684qC028M5890Y3kHKbUwF+lA4LDOzu2M4FAOG3DaoI9cntQdJxzQEyR259f/AKoGl5fSQRFo7ZpB/MhYIR9zxQdayyXKb7gqox5Yo2yB9WHc0DPUIWnhWKxkuYFRs5gcKWbPY59KBkx6isVeSGW31JNwHhyOUkA+o8v9qCfjkMo/LJFKqBmRvSgc2swnRyFcYODuXGfpQMtRsLK8vYJL+wjuGiUtHK6hghz6Z7H6UEmCsig84I9RigiruC9t0DaaVmIIHhTOQMeuGwT9qCJ1ywv9T0U29xFFiaVBJGHz5M5ODgYPY/arKJPTtLW1t44i7SKq48w8x+ZPrTRJoipGFQAAdgKgzX47dMJrXSrXkUe6807MykDkp/MP8/aro80FQyZ+tUJ7hvH0x270XQ7KGtXvIk0T4c9P2bIhkvpnvJVfjIxhf7qftRDXpu0/1DpzXltUlkvmWMBI+2zdnn64oYa6yX0XTm0i4jQ3t6wmuV53xov5UPpyeeKyLbpFtZ6Xpmn6TqNq7/ic6pqQRR/DVf8Alq2fTOP0FXBnXU+ox32o3lzeW+JrxlMXHKR9wfbJ/tVWK5f3AnaAjafCTwwcY4BOM/qKKSjA4Dg8j37UHZKkE5P0olSFlcLDdJPbTNBOigjxOVZu3+80Rbbnrq9l0t9I6isRd2rgKpPlZMdyre9An07oupoh1zo2+lea2fMlr+WZFx7ZwwqWDVug/ihDq7R6b1EPwmpMNokPlVj8xng1BqEUe1EAJOMDOc5oDSxq6YYeuaAJF4oCBUQ7mJ45zQHYB14wR86AVjBXyjge1AEcRTHlA9hQE8kbgEohJ5yQM0ETHNqMOr3IZQ9tIMQyEjKt7D3FBLqywRPJKTuxlj3zQI3Ut14e+yhWRj28Q7RjH60EfpF3rU/jLqFrHbS4/hqpJXH19aCRa8jgiVr1xGwXzYyf99qA9tc29/aRXFnKs1vINyOO2KByoxwe9AYocHGKBvdwLcWzxSLuR1KuD6gjBoPHXWujt071Nf6YSSkUnkJ4yp5H7f2rQgWAA3Y+1An4j/1t+tBrHxKuYS+gx24LRx6ZFtI/lz60FY0+/v8ASphNpd68EpXY5AGNvzFF1YOirZbzVrvX9dkNxZWH8eeaY5Lyj8qj7kcVlETqOqXd/HrPUNzcNE16Tbwxf1JkEgD2AA/etBte9R2Oq2cv+p6XHJfBFjgmjkMaRgAAEqO5o1FWfbgjsR8+9AlI5CgEggeoNAq0iug8uD7g80KKmCcZ7fPmjJzJfT/hWtjJvhOPK/OOe49u9A96X1W90/VrRtNkkSfxQF8I5yScdvX6UGidSLpfVFzcvbRiy6kgZBGysFW7B9T7HHNSjU+o9S1iz0e2uNLmX8RYxJ+KgYeVwVGTn5d6gjug/iU3UOt/6TewQpP59skL5B29x/8AYoNHPB78Ggb2l3bXO78PKsoyVyvIBHBFAoSkbfyhn4GfWgTnmWFN7ybAvc4Jz9hQRdx1dp0S3Dw+JJHbDdPIUZUjX3yRz9Bmrgzbqb4x9Oxho4bB751O5HPkXPsc80wQHT/xrJ1IHUbGKO0kdRiBiAgz+YjnsPpTKN/tLy3vLOK5t5klt5F3LKhyCPemAYLuK5XMDEj1OCP71ArGWLMPT0oIbU7h11u2t49OllWWNm/FIRsjI4AI/egfQ2ktpbww2XgxoDl9wJ49cUCHUGv2GixM13Mkcm0squwUH5/SrgxDW/jFcXOteHb3otrKEEiRISRM3zGc49v1qDT+gfiBpvV7y2unxTxywRhz4ozuHbOR2+9Bmf8A6kNIEWpaZqiooEqtBIR6kHI/atfRjDEt3AKjgVQjug9j+lQWh72e/htTOzyeCnhHPomeMYoJvQum7vVD47K9jpsQBkvZ5NoAHcgUAa7rKamE0Lp9Xh0G1OZZTwZSO8jn9cCsivdS38F9cJDZIY7G2URxKe5x/MT7nNaEKrENwAFPPlosFwS2cd/cc0UlIm3JOeKDo2LH+UA0SjgDk98URzPiJ2449e/NAbS7v8PdpKkpikQ5WQLkqccGgmYNQmXWLeQLG9wVRQVPlcj+Yn3xQa98OviAjz3WjdXSpFdliEuJCNjDtsJ7enepRdel+kdL0rqOTVdIsoYklV1dixO3nunpg9jUCnU3WMeka5b2EUcl3JInmigQs6ZPlJAHY8+vpQP9O1m3nthNo0cTwM2JDwoVj6H5gd6CbhtUiVn8TcXO4ktkZ+We1BAf8Z6fZ2uqXWpyxQrbStGseQzMB2IA961B59+IHXmodXal+HsPFh04HbHCo25+bY/zQWv4f/CCxvII73qC8iuXYb1tYZeF9txHf6U3BatX+DvSl86x6cr2dwjbnEUmcj6Enj6U8hLdJdEX/SmowJp2tTT6Oc+La3HO0442+3NBf1LmRUjjQAfmc+nyHvWQockYyQcY3CgaabaPZxGNnaUFi3mPb6f+KA2q3RstNurnBxDE0mPfCk1YPMemaP1L8RtYN9fJPc2aMUaVmCKg54H0z6VRYendf6Z6T1W56a6j6fgfwJyguhGJmPzbIzjHtSjTn0zSunbi01fSkt9Os5GAmWNCDOGxtXb6HnNZEZ8etOF90DPKFy1rKk3zAzg/3rXI8u7zvOTg4zVoTLDJ81QWDTb2SwuvFgcrkbXwM5H0PFGqsjpd6+kcT61Nc2ieb8OikFc/9PA+WfSjKA1nWBzpFlZ/hLWM4KH8zsPVj6mghN4IyQRk5NGo5BkFmyAfSgVjChdpGO/FAXYpOHLBe/FAQqoBJbA9sUBGxgtgEj/eaCf6DGjt1TZf8RNGumKS7mQZQkDIB+WaMrf8Ub/ovV7V20JIYL62K4khhCLOCcEcAdu9BmCuEQvxvyFUg42+v+/rQaj0zax/EXRY9Nns0t9TtM+BqCKAjEclXA98jn+1Si7Cz6u6O0tLjTrxLu2tQJJrDwcKE/m2M2SfeoLrpupDV9Mh1OytUS2vIN8m4BZQf6T7+vPpj50GfdK9L6rJqk1y1y0elRDKRqdjHHoyDhjx39e9BZr7fagW0j3kul3iETRqHkeF8ZBUjkZIxjtk5rQ86dW6r+O1OcW0UtvaRsY4oWfLKBxz7k/5NA46P6X1rqS6WPS7V9v88rAqi/f3oN46X6C1DSotkus+BIwKl8hn2+3PapROXPT2t20bPY6kJ5UGYmbIfIHGW5z68VBI6DrzzWSrrAjtrwFUbDja5OBlfuaCbluJLeNwIpLiVF3bVXAP0Pv8qBxLO8cYcW7vnuqkAigNFKs8CyxlwG/lcYI+1A31ayF/pt1auSFmiaM/LIxVgwfoO413o3qqfSLyUSwodogAyZVGcbPTPr71aNDvendJ6wtbu7Fi1lezK0bS4VZMjtnFZE0bC5u9Jh0qRAr2yw4uWx59vBI44PegN1tpbap0lqOk2sipLPB4aFsnHbBNOR5A1exFhqFxbeKkngyMhdOxIPcVuhiZFz/zBUEwcKvYnP6fWi0+6chjn6h062uATFLcRrIMnzAsO9EehNR+GvTV3GUh0+O2YsGaWHIf9amjIfib0no3S0VtFY3M000zMzLJtLKvvkenyx96oz0rwNjA8cj2osFLbVAbOc9jRQiXOAwxnj3oBlAxwDj37UDY+vHOQeTQBIdqjcPMfnQwJclWyBgCjJBFeefw4VaVycBUGST2wAKD0L8H9C1rSIILjWLSCytY1lZASVnlL4PI/wD8+vvUo1uwbxI5GkjdVc7isvOBjtj2qBWKFZiQ8CJCB5FHYj5jHFArDbQ20ey3RY1HOAOPsKCH1u61CPSLt9MtlXUHUrbCbJBbPdtvYetXR5T1y2udD6lni1ErJdJLvlK4wWOCePvVgsV/8Sr67UW1vA0NiowIonMe4+7FeT9ARQRmodWa9EYpPBhs1Tygw26rk9xknkn70EjonxZ17TXjAeKTkZ3L+YZ7N8vpSjX+lOpNM6umgkMG3EgBV1DYbG4kewz2NZGkC43CP8MPFBONysMAD50DaHVH8S6N1a+BaxMUjd280pA5wPb296DrXWLK9WNoJdtwybxDKPDcAnHIoJBifTBzzmgaz2UFzPFNNbwvLCcxuyglT7igdRRKg8qAZ5JAAzQEnuYoHiSWQIZW2ID/ADH2H6UERr12BY6hueIQJaO7SK/nHfnHtx3pyPGWoN4jynuCfU963RF+DL/UtQWTkjaWY/8ATnHFGql+j1VerdJY8r+KiJz/ANwoy9C/EjqSbpbRY723RJC8ojIcZ4IJ/wAVkecer9en1+9FzeLCCq4URjgDP7mtLhteadBY2kMczyHUpcO0YxtiUjgH/q9celAiLy1kjCX1ruyMLNGdrj0+h+lE0+t+kNQltJ7yKS3jgiTxUFw/hySp7qp70NV6YEBgWUNjBoaKeAODnHrRoVgDnBP0ozpxZ2f4y5trVeGuJFiBPpk4zQep9C0LTembS30fQbWP8ZsDyTugZgf6ix9fYZpbgmbXSmXULaa6kMzpltzcjJ//AGpaLCY1CDsF74PrUCgHY0HbSx7Z96BGUfxB2xjtQZ11t0Tb6jNfyw2wM18gV5AcBdpzyPnV0Yp1F0o/TEczXjXaTOQYpIk3QlT3B9Rj0zVl0VKbVppImheUSwbsgFfXHc0De0tri/ujFYQSSyfmKopPHqaDV/g9p+padr/gkSRTzKu0kZRlPLYPbOPf2pg9GWzRCMJAFxH5do4wayKX1z/G0CdzqLWRkiaTxQBLudclQvovbv3oMU/4Z67uwnUAt3u1Zw42yhmx3/Ln8v0oN86L1d00i3i1UiGQIocNnEbnkqT2xgiguEbI4DIysp7EHNAZnxQQ/Usksej3EsCl5EUthR5sY52/Mjigr6Qrp3R15LqEcIlmgdpFGAsY2navPJApyPJtwd8rnGBuJz6Gt0MzGSTyf0qCwSKA5ZsAjnn2otTXQYj/AOMNIDqCrXUZwf8AuGDRG6fF6Gyfo6+ub0CR4EPgIScLIeAcfc1keatN0661a+S3sYTPKzAbV9B7/StLrQ/iXp9pYLp8elWsUM11AzXMqt53I7g7j244oiB6W6Tn6j2TeAy2FspTeB+Z+/8AmgtnWlvpdl1Dp1pq07Ja20GFQpuDHHAwPf39KDHriVTKSPOCeBnHHtQGsrG5v5pfwcTOIlMjgEeVfck0XRIreS7uUigRpJXOEVe5PtRE/wBJ9HaxqvUcdhNFJp0lviaSWVcMgzxgdySeBipo9T6O8NppUJ1K4iW5KgSvIyqxb5jPH0paJm1NvKivE6Mp7MpyP1FQLRTwy58F0cjuAckfagOTtO3+Y8igMWCIWbOPlzQNhNBOWEbq5Q+YKc4+tAD7JEZgQfXj0oI/VtIttXsZLW5hRopByCP/ADVlGRa78Erae63aXK1tG3LAncM/Kmh10l8IZdBv4rxtTE0yggJsyoz6/P0po0zSNKEMdo9xGnjxuzkqMAEgjj7GmialjWQMgyCRyQcGoITqHT7q/a30+G2jFmwLSzl8GPBGFA9c5NBPRwJDbpHCipEi4CjtigqfWltqCaG8WhNbxyzOBIs8W8FcY4+dWQQ/wtuZdIGqadrknhy2u2QyOSEZOeRngY+XvTBZZevOmhC8janbqiZ53Zzj2FMFcs+sh1ZqsFrp8UkGkrlpbh+DNzhVX5Z5NQTfXyWUXSV2t+wW3EZ5I4HHt61eYPI0mA5C9snFaoLsPv8AvUEk5JcA8cZG480WnOlXX4PVLO4yQ0cyP244Yf8AiiPUfUump1B0/c2O8xfi4v8AmL3UcGpgw/SujNX0Trj8PpckimOMvHO/kEg9Rjs3PpV0aFq/Qqa1ZJ/qcrverEqNOwGM+uMfemiVtrKbQdMNjp9rvtkhPht6mU5yT8u1BkvXg1qXUtOvddgRY1R3j2YHiMvZSD27CgzSCyuNQ1KK0giL3Mz4VAOc/wDignoNNOnaHeiW8hgkku/Al2+Ziqgn09M0ETp0qpqSmGKOdFcEeLwMfPHag3JLuCRtPmQWsDhNphtVAcn1w3BPFSwDdWGpX1/OYdOtbbSrlQ80szHdn0GR24/c1AbWemdatLbTJdGvJIJypDQwMV3exwOPatSz9Ei/R+txy2mr3evyHV4miWIDhGwwyGA7nGRS2YNZAUBWYDdjGayEvxMYB3nYu4KCfU+woG93c2enWs1xcPFDCp8zEgDPzq4GGgz22saS1zZSZhkdsFePXt86YHWmySeLNDMYikZ4YNlvvUD+VARxQJqgwRQHUAAe2O1AWOFRM8mDlgB37fagb6reXFt4ItLZJnZsuWfaI0Hdjwcn2FAz0nWX1i4u4xY3VpFbv4eZ1x4vGdy/KgkriN2aMRlQoOW3DOR/5qwYr1P1tp2pdS3WnanKkGh24kRl2eaYgcb/AFxnnAqiv9Jno0dRLJPbtdQtkNPIALaMnODsPPpSjbdK0DTbWQXui+Gsco3BU5hPP5gPT7VkU74t6PZHpq/1N5ZZbwrtRnmOwDPOFJwPsK1xR5ybudw788VaC5X2WoJRULSBpAe5PA/aiinAZnHck4A70THq/Qr23/4Y0u4lmCpLBGA7epxjH60Du+WGOBvFlFuWOFcYyCfbPrUojri6k06xX8PFNfBUJ3ltzM3scVBjfVvVXVNit5dapNDZGQGK3shjeAe7YHIwAOT3zVggNTiu+orrR4p7m+upJFR7h3TPhggDaoBwRjnPH5hV0af0xotnoD3l5dWdrY2YjGLhwPEHoef996CC6m0HpuPpk3Wny2s9sJPHJ3AeI2D39T37UGU9QTDULuGPSLPwIyoVIYk2lj6/X70G2/DPp0hVudRuBLcwxhRGkeEjB9M+p96DSLprVHiieaAE+YxHkke4H1qUOIBawL4uAuc8nvj71AwjRtQ1eO78QNp9odyLju/qT8uf70Gb6r8SpLzryy0vp+4NxYSSCEswI2u2Rn3OOD9qC4dVamen9NlaC7tUaIFvCmnHiy4HJXJxnOeDVwed+rOvLnqSyWO4jZSru/kc7ck+30GKosXw2+KmqaDJDY3jR3OmqNoRhtZAP6SP7Ggtmt63qbTJ1XLazJpslwBFblypEOAA7L2OWANS+xrnR2vW3UmjJeWp8wJSRf6WHeoJdSPMCRmgMq8DmgBpNsgUIxBGSccD70DczmS8MDWoe28MN4+f588rj980CktuJZYpFdlKZ4B4OfegQ1hpIrVjbsRMBhBj8x9qsHnX/hm36y1O/u9V1ddPmS6aD8OkQdyxOSe4OMmqLUvwQsYY4Xjv7m4YEEhwFyMY7fXB5pRbvhp0jqfSMV7b6jqZvLGQAwxAEBDk54PuD6VkVb49a5DBpiaNaeF/FIaQDumOwpzMGDEZQZ5+VboR8In1I+9QWDY6gFn7jjHpQhtJEFbAGBnijT0P8H7qPVOh47a42yNaymPBOcDupoykep+m73V7g/8Av2itQowvJIx6j5/OpRjfUWrax051RPY6LqFy8YACkebO4Z7HjNWCY0ToW2utJbqPreW5na4O4R78cehY9+fQVKLX05p1ro97awC4kX8VFmJLeEKdoyfOxJPbHbHYVAz0rqKPWNauri9t1ktJgILYgEiNFJ/Op9STmrBBdeaFCo0y3jt444DI3jLE204Y5DD+9UPPhv0NaRtPq99mSLOy22nOfdh75oNC0vT7m1uJGvGiii3AW8UDbQAeDu9zUohLlhouqap1VciF4I1FtbxSthtobBIPuTn7VBJ2vUth1TYk2ULi9iALwyKQYz6Z9CM0Ft060/DWEcDHe2Mucdye9BFW3SekWt3LPb2cUTsd2UGCG9x7VYMzufhzdX/WmoXj+BPpx3I7XZMmXYckc8EVRKaP8I+nXikLQuxOQSTnBzj6UEjonw90XSrq3S3s7dplJcl1EhGDx396lFx1TQ4NVjaC7UNCU2lAO/8AvNWDCLp9X+E/WgWImXSp2LRq7eSRT3B9iP8AFSjd9P1+21TRodVsMS2rLmTbyUGOePXFQSltcLcW0c1vh4mXcjDswoDLdRm4FvISsgXeTghDzjAPbPyzmgVFxCzuiOC0WN3sM+5oDqySJmNg3rx7UFb60tNUubGJdFdEvhIdryflUFSM49TVgyTQenJemOorf/U4H1Fpp1edAh/hOQTuQ9375JA4q0bnbPBcxxT20wkjKkqYzlT9ayGWu38um2MbLEJ7iRtoUds+/wAgBzQeW/iHqi6j1PdzeL44HkL9txHtWhVUOVyvHNB2F9zQT8hUAhAdp5FCG0mSAzE4HGDRppvwL1bwOpJbEsFiuYyVX3deR98Zoy2ZtRgmjkSRZocEp51K7se3vUow/rfpFE124mVpfD4mk2MWdCc4A+VWCH1281/UmFnpklzPYRFBEG8uGC4yQfcn9alGgaJo95rRsbi53WaxwrHOm7BjYcHnvz/moJaw07pXSI5IW1K0CQnDhpAWB9R796CudY62msTRW+gadI8KnDXMkLLv9MA8HGOKC3dAXF1dRfh75f41moi4G0AdwcfTj7UFhv7RjqMBV5AJFZHkR8FRjIx6CgpXVNjJ1JqNn07p26CztSJLlpIydyj2J+fGaC+afplrazqLa3SKNIggx3IHYUEsBk4wQc4oK11L1z070/M9rql6wuVA3QopLcjNBDwfFboqeSO2W7kQNxuaEhQfnQLt8TuireVoV1UeXnckTFT9DigHRuv+mbu9ZV1W3Nyc4IRlVl9O47/KgtU+s6baw+JcX1umRkAuM/p3oK/1t0rYdX6cqXKESqN8Ug/Mp9P1qwZ702mo9GdUTWJsmOn3EY8CAORGXJAwScjJ5q0bJDNLb6YklxbKsgA3wwndg9sDtWQN3aw3ZKTwLLEQOGORn6ehoG1vYAw3FikRt7JSuH3Hc/GSc5P0oHn4aO2uGuYyiose044wBQIm6F1dwfh5ARs8R8L2BHGfnQHv9PS4PjxrGLtFKxysm4qD3oCxboIIo7e1jhQHzAYUJ8wP8VYM56j1ktaal1BMrS2sAaK1OQDD6eUepY9yfQVR5zv7hrmaSaRtzyHJY0DcE4BPIPb5UBwOO4oJYzFvzEYHAH9XvQhNZN7AEgDOSDRo/wBA1SXRdVtNQgb/AJUgfBHcZ/8AGaGPVlhPbarZ2t5CEeORBKje2RUrI1zYxTBhMinIwcjvUEcugWkO4AMisMEA8N69u3yoERrOhWNxNYy6hapcxAeJHM+D8u9ASLStLlm/EWdpZyxy+Z3RQ3I5B44oJKTT4blFWSNBEOeBg5+goFYbOK1TKhIxnIbGMH50Cpcyo6AMrIcM2OD68Ggb6Lbbllu5Cd88hYBu6rztWglSNkfm4P70Gaat8Rba96w0vp3R2mhufxyi4kO3YyDOV9+f8VYMw+P0cP8Ax4JVuEKzW8bEr5tuMj0+lUZ7Y2X4288GK+towRlZXYqv9uKCQi6YmbT2u11GzaJWKnYxbBB49KCFnhubdiwL+U8OhP60ElpXUFxY6nDdXQF0qYbZKxwT9vWg3npb42aHcmC11C3uLSQjEkpIdQfr3xUondP6x6e6tv7e101hczRzrNtaFiFC/wAxPYHtUF+lj8bYCTgMG59cUC4OBQQOo2eoXepFTeL/AKYQN1sEwWx6Fu+DQLX2kw3Ok3Vjas9qJ48Exd1PHb9KCE6R0G86Ut7mK71KK4gklM7TyKRIBjtjtjj96AOreudJsrMJbXksk8jBCbVdzRjONxBHP/3QQ9x1jcWGkERWWqXdpMPCt7x4wfFOOWPbA+fAqwZr8TJ9Qbp2ymvEjsrSTEVvawyHz45Lv6E4wPqaoyl8g91OKDlYEc8mgKW5PH7UE80f8PPHl7gDFAZkUjawUIQG8w5ouknAUbl9Dg59KK1X4Z9XXFvo8mlRXax3KHfBG8Rk3qe6jHOc54+dMZO7jr/qK8vWtba4tYu38TwvDOMc8N60wPLbrW10PS7pnvrnUtbAKobgBUUk9jg8f/lMC2rydMdRSaRqWoLEbx4UefwxkL2BVvvn9Klgv3Tp0lPxFno6wJ4IVmEOMEHsf2xUD2e4ks7n+NGDaCMu8q8lCMcEfPNA6tW/EwrMybEYZUHnI9Cf/FAzu7G4LXTWs38SRNqhs4Bz3z9KCO6x07UNT6altNMvEs7xkC7nPlI9R2/egwbrDT+r+kupLCeK9nu3KBYGRy+QvdWFWCU6avtA6h1iKDqLRhpmpvkxz2p8JGb3z7k557VRX77TdHteuPBut401CAouyXGcdvmASaC069030brYaay/CwPFwWspRErfUN7UGZX2hWSiY6ZrMc0CvhUlBUk/UcGgiLq2mtG8F54yDwfDfIoGkrRsSZXwOB2zmgsvw06XHVfUcFvI22xQ753Ze4H8v3OBUo9a6XodjpltHbabDHZIhVsQqBuA9DxznFQTQUe5oDYGMnn7UEbpV3JqDyz+BJFbBtsXiDBf/qx6CgDXL42cSRwGM3UzBQrHGFzy32oG2i2kKTSI80lzMow0rqQoyew+3tQO59KtJJRI9rEzgg7igz3z/egZ6paJdGGwW4eBXy7pGeXUdwT6A5qwebPjJrcOr9TvbWZQ2Onr+Gi2nIJHcj7+vyqigOuRk+vtxQAqEk4BU0ABj7j96CzzKxYD0GeM0CQG3OMAjkfOgbSZwzE4PJyfWi6caTdzaffW95akrPFIrLg/tRHpGzs9C6t0W31FrO3Y43MrcbH9c/eloZ6v0JpWoKlrHHBbScSFEHYc5Pz71NDXUoJrK1g0dvw9qsspW3nXaN6KMrHnH5ieSfan0U3Rr1uidaRbiwk8BUSS6naQkjc3ZcHaRnn70wbja6lZX+nw3NvMksM+FXnPJ9DUCeoXj2hSG2t2km7op4U/f/FAvHaNePb3N0jRzRA7VD8Akc9u/FAvcxnawZQ3HYtjJoKfDFAdeub6Vo1dSULIBtTbgYOfU8jNWUVvrm5ih0m1urixhlsI5HJliOwR5/LkkHHJPamjHdQ0HWdemlutN0+YWBYtC0rHDhjwVz3zWgx1n4e9U6QE8XT5Zd//APR5se9XBXbjS9S0zAvbO5tyWKAOhG4/KpQ3ZHXO5JFK98qRUGhfCbph77Uvx91pv463wVjR0LR7s483796WjW7rTrXpHWrSW2YK7lmXTbaIFpCRjjHOOSeeBipaNLtXuIre3R43lnkGXYADZnnmoH6Dkbzn6UDGWe9a/hKG3jsW8riQMJS3svp86B6zgMQmDtGT8qDNb6XUpOoPx72tzOkjFYowOduDwDjj70Gg6Wsq2KNeAJKRuKk52fIn5DvVkENrvW+iaSAsl0txI2Asdud5Yk4A4pgzv4l9ST6JZSXbyyprWpw+FFa5G21gz5icfzH3pgwCSQlh688+tUEwjjngZ7UHAHuWAHpn+1AXj5frQWXOGBZcKSe3c/rQIyAtnI27eBj/ADQIMAuH8vHBB9DQwVpPLjOckEZ/ahi9/Czqj/S9VhtLm6aG1uZFUsT5VOfX5Gpg9GiNJArxsrxsv1BHypYGF7pljeG3kvLZSlqzNGGxhSRjP6GoG1yLUWiWc2nSPA4KJGItyYHYHHarop3wu0jWYNUvzriNBp8ErraRMANxJ/N7nA7ZqDUHgSQLvAbacjI7H3oOuIFuYzGS68jJRyp4+lA0m0yDwGjiTw3bzBwTuDe+TQVbV+mLmW1NtbSok9weZiC2zPLEZ+/FBM6Xo40/TYdL8Jr21G4vJcuCck55HbFWUKQ/h4tR/DTz2o8TK21qmMgKOf8AfpmrokljG1i5BHI57D5VNorut9Lab1LA638W6H8sboNrqQckq3pntV0RWsfD6K7SGC3vTFahQJY2iVmkI9d+Mimie0Hp2DQ7AQacio3JZgqjcT3zxk1KHGldPWtnqMupS5uNTmGGnk5KjGNqf0r8qgmkhVGcquGblm96BDUZZYLGVrdN8+MIvux7UGKTdXdbaRrFvbaxbWN4d58BmwCjHPORycLx2q4LNe9S9TdN6I13qkWmzSXdwBCGlO4hiMKAB2A9ag0WySQwpLLtMjDcQBhVz6CgoHxF17XbnUYunulgsUsu4TTvjIUAEhR+x4qwZwtkOi7651PXJobm4tohHbQhdgecjnaPZeOfeqMy1vWLvWNQlvb+ZpJpWyT2A9gB6Cgjy5AO4A5oAGRgBR39aA7Z8MkFtxPY0AbV9UGfpQWhj5TkBQGxuBoEGG1iQCyHvj1oELgSkK6oRnIBIxzRdJ28Q3+fHiAds96LoH3AF1wCfyijNbF8JviI1rbQ6Pq/iSopxFOx5Uf0n3qUbWQk8II2SRyDPuCDUHMpSIiJQSBwDwKAgTxApnEbyIQ+APyn0+9A5B3AgfmoEWgcb3VlMpGFYjt+negSs7zxH/C3RWO9UElM8SAHG5fl/agNdXcEbJAZ1WadvDQDJO7Gf7c0ED1dqWv2enzw6Rb24nZfJd3EwREHqxyMZHzOKBbT7H8PZWTK5uZ9o3Xm1SzEry5PsT7UFF+JnUezSZ9LttRs2km2m5KSFWXDZI491AyBzVwK6J8T7CRtPjee0tbaGAtdNISdoXgLEo5JJxyfSmC6aF1fo2vELZXDJOxwkMybHYe4HtUFiJWJd8rKqjuTQcZV8SNI0dy43BlGVA+ZoBniE0RU7tp77Tg5zQUv4hNrU2tdNWOhylPEnaS5UHGYlAzn5cn74oHGt6l0z07k6nJC123HhKPFlbPptGTj9q0Kx0XMvU+ty6vqQtpWlZo4LOdGDWsak8Aflycgk+v2qC8a1q8OnaXLPOz2kCIWkZ+CqjgYx6n0xTBkmp9Sabp0KdRyI5vJkaGw08MVKIDw8jA557896QY1q2o3eqXr3N7O8skjnlnzgn5e1UMCGV/MOM0BJFOVwfX0oFtgZTjkg8UBtpOeO1B3hg85FBZXVMM+VJAA2+h96BO4IMJ/p7qvuKBKacmOKB5CYYx5UzgDPfHzoGwD5OApJHAHrQEAk8NWdNpx+XdkA0AIGhkGWOQcgg8UGw/DP4kmwhi07WCTZqAiSbstGc4+pFKNvs5o7q2Sa3kWaJxkOp4NZDOHUh/qL2k8LW78eG7kbZv+0+/yoEZp7fUpX/BXpgvYZTCSRtO7vtwe/vQdY6jeyatPp91FEPw8aSNMoYbi2cADt6Z70DS60KW7luJdV1JniJzBtURG2b0KN7+/vQKSWUWnLLqN3cSLP4ex5Y8jxiPykr23+nzzigpXUPVOu6Vqmmf8UWttb9OXDqkjRnfI3H849uRkDOKC0axLFr+nLB0rrUMM0bqCIGGGX1AH09qsGc9UfBiTV9Vhu9Pu5oPGLNeG6bczN7jHvVEr058Gre3sLeDVrmOdo3LmSFNjEH+XdntQXO51XQOl5YrCKGWa8SMYS3tzMyLjjJHb9alDqz1S5ktJ7nVdLmSVDiOONfEMiE4Xy+h9xUDm11CaTxEOn3VmpHFxKFCr9s5GPmKAus6jb9M6RJf3c88yxpjcxL7uM5OO3HrQVTSupoOuYdZMTSpptriNFtXKXDA/Pjhs9h2xQOJ7Xpnpa2S91WK2swqjbGw3ysfcnuxrQsGmapYvpwvra1FtDL52Mi+Gx49sZoMb+LXV0t+jWl3OYLGTO2zjx4h2nyszHsG4/Sgxt5ZJmEsjl3PB3GgSlyXBxkDnNADseB2PsaA8SoXQyFgmQCV70B5R/EIjYmPJxnvigEKcYDfrQF2/X9aCwqC7l2zwfT/FAJJ5747E5oGTqZArKOfccftQHZWwmOD23Z4NAEkTEBmwR7g5AoG7KSSE5HyFAMTyQsMHa/cEcEc5oL58P+v7rppdryPNAXx+GfsQe7Z9D2/Wg3zSdX0fqzT08F433eYwscOpHt9PcVkQPW632mX9vfWdrbXiRgrIdu2eHIwGD57+nIoKdc/ELVdC0u5afp27SUtta5vJMMzk+UDjzYHtQWDpj4gxXmif/wAitXZkGZzFGW8MehZO+PmM0Fibr/poWQmF6xXA2xmFg59sKRk0C2nQP1KFvdb0vwIUJNtDKcsVP8zD0Jx2oJDTNA0vR5p7qzs44pJOXkUc/SgNfa/pNvbF5L2JgTsCo2WJzjGKA1jcNcxOF/m/I0zbt4+gxgenNA5s7CCxWWYQxpNLgyMiY3nt2oHajcuexAoEL1C1uyFkVHO1ixHb17/KgwT4rdXWep6oul2OpywaTYqVLxDyySDjaM9x6Z+tWDPdB1TW7Wa9sumpGlursqMQRlpXwd3BA4571RcdN0i41G7h/wBSmNxqdkwn1O6u5/4cAXlYgcnngE/pQNvih8S211obHRyYbWInfJG/Ex9MD2+tBmNzcTXTtJcSSSSHH5jngDAH0oEdxbg5A9wKAzPwO+fegSLfLJoFoR5fUfegXOcHGAT8qAM+XaBzQCCwGDuyPlQWJpV37Q5TIweM7u/f9qA9vNYpFML2KaR8YiaJgAh55PvQRvnYoqA+MThcDnPai4PKWQlH3K6tggjnPaiEmz4ZznBPfFAVWG0AZDH1z2HzoE7lhv8AJIHI/mGRQI8AEeuOMGgndN6pu7V4RJLKY4WDLhypXj0oNL6d+MMS4ttetDdQgDNwAPEwPRh2NZGkabrvTXVZiexvba5aI+ILWZQG3Y4IDdvtQScvTdjK8chtFjkQ+VlYgqPXGKA17daV07apJrV9CsZbELTgbu3YY78UEHf9evJ4K9P6JqGoiR1XxjCUjAJ5OT3NBM9YdSWPTenwy3t7bWbSuBunUthfUhRyT+1BA2vXnS/jGdeo9LnIHljeLwSCe5zgmgejrOz1S3kGhazoaXYGAJ5Sw3e38uaCsJfX02rPD1XfXtvcCXdBJGjLbOO+EK88Y7nIoLB1H1Bb6WkN1ddSQ29io/5MZEjzt7DGTjj2FXNGUfEH4wRaxCtnp2kwGGM7llvBvIOO4XOAe/fNMwZbqusalfLBHfzSvFH+SIgKo+igYqiwWfWV30rpp03p6exJnUPJexQnxuR+Ulu2PkKCrT6jcSiTxZnbxCWcFidxPJJ96BBDlQ35fbFAbahBHJIGO+KAIwg5YnB455oDkKcbW7UAOowSMjOORQcCVXPp+9AqDkHcDmgMNpHPcUBTuzQWCJXcFvKR2Y0CMiqjnz4UcH/6oG8gKluwxyAfSjQ6ylEJBJfv37/OiYQMjbjkZXOSP/FEELAEkNn1waBCXdjORnPoc80CZeTb5wQe2BQAm4y7jlhjvQcWO3cW4GB7ZpgGC5a3uUeNyGQ5GCR+45pgt+l/EzqLTgxj1O5Zc4CSOXCj70wOE+Jd/Pq0V7qVvb3bISAWUBhnuc+/2pgvkHx0soLaNIdKkEiqR5yDg47cYpgresfELSNc1n8VrFtAw2ZBiiywwcgeb14x2xTBYNA13ozUo/GOqWVizDc1nf6crIh/7wOf1rOURvVupdE6ncpFeakiSWsZdbjSLfw1Zs+VVyMHA75xWsFDHU0idTJdf65rT28YKpPvHjKp9Bk49qYK/rGpXF/qU9zPdyzyyMSJJAAx9ifnVlwNZ7vxYEh8GAEHO8DDH5H5U0IPK8jHxSzFQAMnOKgJkFwPT6UBlAII5z3zQCjnA5OKBXeuAT9KABMA208DtxQHRhzgUC3KjJx9z2oAP6/L3NAHC8Hg/XNAcNtGe4oEy5yeaCdLk7yx2qQCAO1AmXZSSexHbPNAhJuLJkgjvzRonuAJy2cd8UCbyOi453Dj7GiYTZyVPPl74oYLJIyq68EH3Gf3oYTDEjLbiP1FEDHOUOdgOfXIBFAm77j5Mnng/WgLI5UE8Eg9iO9AnuJbuQx5wOBQFRxuIbOc54PrQK28ws76F722EyI4d4HJUOPb35yKBm8oeQsi4BPbPb71RyYIHmPGRg00GRsbsHIPY0Bg52AEEseBUCQJyOPXtQDtcdvvjtQCQ/GBwKAuXU4PrQBvZE5IGeO1AffjBJ57UBvEO045HagFWAAzktQKIzBeMg0C5kz5mOG/WgMrDJJ7jmgEnIyOccYoA3cEMRj05oC7/wDeBQTduzEoNxwcZGaAJOWfPNAlISVOT60aIQfkj+amgJ3bnnigKeFGPQUCf/x0Smw4V8exogX/AOY3+/SgKxKxeU459KAgJOckntQJkkcgkGgAAFFz/XQEmJaY7jnk96BM9yPQelAf/wCX7UBv/jagGP8AKB6ZoDf00HMfO/0oAH5TQA/5moECSMDPFAvGASMjPP8AigVX+b60BW7/AHoHEJJD55oDd4snv70CsSjCcDmgVAAbgYoGYJ3nk9qBUAYHAoP/2Q==
pandoc-1.12.2.1/tests/writer.html000644 000765 000024 00000040100 12251233603 016454 0ustar00jgmstaff000000 000000 Pandoc Test Suite

This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.


Headers

Level 3 with emphasis

Level 4

Level 5

Level 1

Level 2 with emphasis

Level 3

with no blank line

Level 2

with no blank line


Paragraphs

Here’s a regular paragraph.

In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.

Here’s one with a bullet. * criminey.

There should be a hard line break
here.


Block Quotes

E-mail style:

This is a block quote. It is pretty short.

Code in a block quote:

sub status {
    print "working";
}

A list:

  1. item one
  2. item two

Nested block quotes:

nested

nested

This should not be a block quote: 2 > 1.

And a following paragraph.


Code Blocks

Code:

---- (should be four hyphens)

sub status {
    print "working";
}

this code block is indented by one tab

And:

    this code block is indented by two tabs

These should not be escaped:  \$ \\ \> \[ \{

Lists

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 1. 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

Tabs and spaces

  • this is a list item indented with tabs

  • this is a list item indented with spaces

    • this is an example list item indented with tabs

    • this is an example list item indented with spaces

Fancy list markers

  1. begins with 2
  2. and now 3

    with a continuation

    1. sublist with roman numerals, starting with 4
    2. more items
      1. a subsublist
      2. a subsublist

Nesting:

  1. Upper Alpha
    1. Upper Roman.
      1. Decimal start with 6
        1. Lower alpha with paren

Autonumbering:

  1. Autonumber.
  2. More.
    1. Nested.

Should not be a list item:

M.A. 2007

B. Williams


Definition Lists

Tight using spaces:

apple
red fruit
orange
orange fruit
banana
yellow fruit

Tight using tabs:

apple
red fruit
orange
orange fruit
banana
yellow fruit

Loose:

apple

red fruit

orange

orange fruit

banana

yellow fruit

Multiple blocks with italics:

apple

red fruit

contains seeds, crisp, pleasant to taste

orange

orange fruit

{ orange code block }

orange block quote

Multiple definitions, tight:

apple
red fruit
computer
orange
orange fruit
bank

Multiple definitions, loose:

apple

red fruit

computer

orange

orange fruit

bank

Blank line after term, indented marker, alternate markers:

apple

red fruit

computer

orange

orange fruit

  1. sublist
  2. sublist

HTML Blocks

Simple block on one line:

foo

And nested without indentation:

foo
bar

Interpreted markdown in a table:

This is emphasized And this is strong

Here’s a simple block:

foo

This should be a code block, though:

<div>
    foo
</div>

As should this:

<div>foo</div>

Now, nested:

foo

This should just be an HTML comment:

Multiline:

Code block:

<!-- Comment -->

Just plain comment, with trailing spaces on the line:

Code:

<hr />

Hr’s:











Inline Markup

This is emphasized, and so is this.

This is strong, and so is this.

An emphasized link.

This is strong and em.

So is this word.

This is strong and em.

So is this word.

This is code: >, $, \, \$, <html>.

This is strikeout.

Superscripts: abcd ahello ahello there.

Subscripts: H2O, H23O, Hmany of themO.

These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.


Smart quotes, ellipses, dashes

“Hello,” said the spider. “‘Shelob’ is my name.”

‘A’, ‘B’, and ‘C’ are letters.

‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’

‘He said, “I want to go.”’ Were you alive in the 70’s?

Here is some quoted ‘code’ and a “quoted link”.

Some dashes: one—two — three—four — five.

Dashes between numbers: 5–7, 255–66, 1987–1999.

Ellipses…and…and….


LaTeX

  • 2 + 2 = 4
  • x ∈ y
  • α ∧ ω
  • 223
  • p-Tree
  • Here’s some display math:
    $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$
  • Here’s one that has a line break in it: α + ω × x2.

These shouldn’t be math:

  • To get the famous equation, write $e = mc^2$.
  • $22,000 is a lot of money. So is $34,000. (It worked if “lot” is emphasized.)
  • Shoes ($20) and socks ($5).
  • Escaped $: $73 this should be emphasized 23$.

Here’s a LaTeX table:


Special Characters

Here is some unicode:

  • I hat: Î
  • o umlaut: ö
  • section: §
  • set membership: ∈
  • copyright: ©

AT&T has an ampersand in their name.

AT&T is another way to write it.

This & that.

4 < 5.

6 > 5.

Backslash: \

Backtick: `

Asterisk: *

Underscore: _

Left brace: {

Right brace: }

Left bracket: [

Right bracket: ]

Left paren: (

Right paren: )

Greater-than: >

Hash: #

Period: .

Bang: !

Plus: +

Minus: -


Links

Explicit

Just a URL.

URL and title.

URL and title.

URL and title.

URL and title

URL and title

with_underscore

Empty.

Reference

Foo bar.

Foo bar.

Foo bar.

With embedded [brackets].

b by itself should be a link.

Indented once.

Indented twice.

Indented thrice.

This should [not][] be a link.

[not]: /url

Foo bar.

Foo biz.

With ampersands

Here’s a link with an ampersand in the URL.

Here’s a link with an amersand in the link text: AT&T.

Here’s an inline link.

Here’s an inline link in pointy braces.

With an ampersand: http://example.com/?foo=1&bar=2

An e-mail address:

Blockquoted: http://example.com/

Auto-links should not occur here: <http://example.com/>

or here: <http://example.com/>

Images

From “Voyage dans la Lune” by Georges Melies (1902):

lalune

lalune

Here is a movie movie icon.


Footnotes

Here is a footnote reference,1 and another.2 This should not be a footnote reference, because it contains a space.[^my note] Here is an inline note.3

Notes can go in quotes.4

  1. And in list items.5

This paragraph should not be part of the note, as it is not indented.


  1. Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.

  2. Here’s the long note. This one contains multiple blocks.

    Subsequent blocks are indented to show that they belong to the footnote (as with list items).

      { <code> }

    If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.

  3. This is easier to type. Inline notes may contain links and ] verbatim characters, as well as [bracketed text].

  4. In quote.

  5. In list.

pandoc-1.12.2.1/tests/writer.latex000644 000765 000024 00000041031 12251233602 016630 0ustar00jgmstaff000000 000000 \documentclass[]{article} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{amssymb,amsmath} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript % use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex \usepackage[utf8]{inputenc} \else % if luatex or xelatex \ifxetex \usepackage{mathspec} \usepackage{xltxtra,xunicode} \else \usepackage{fontspec} \fi \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \newcommand{\euro}{€} \fi % use microtype if available \IfFileExists{microtype.sty}{\usepackage{microtype}}{} \usepackage{fancyvrb} \usepackage{graphicx} % Redefine \includegraphics so that, unless explicit options are % given, the image width will not exceed the width of the page. % Images get their normal width if they fit onto the page, but % are scaled down if they would overflow the margins. \makeatletter \def\ScaleIfNeeded{% \ifdim\Gin@nat@width>\linewidth \linewidth \else \Gin@nat@width \fi } \makeatother \let\Oldincludegraphics\includegraphics {% \catcode`\@=11\relax% \gdef\includegraphics{\@ifnextchar[{\Oldincludegraphics}{\Oldincludegraphics[width=\ScaleIfNeeded]}}% }% \ifxetex \usepackage[setpagesize=false, % page size defined by xetex unicode=false, % unicode breaks when used with xetex xetex]{hyperref} \else \usepackage[unicode=true]{hyperref} \fi \hypersetup{breaklinks=true, bookmarks=true, pdfauthor={John MacFarlane; Anonymous}, pdftitle={Pandoc Test Suite}, colorlinks=true, citecolor=blue, urlcolor=blue, linkcolor=magenta, pdfborder={0 0 0}} \urlstyle{same} % don't use monospace font for urls \usepackage[normalem]{ulem} % avoid problems with \sout in headers with hyperref: \pdfstringdefDisableCommands{\renewcommand{\sout}{}} \setlength{\parindent}{0pt} \setlength{\parskip}{6pt plus 2pt minus 1pt} \setlength{\emergencystretch}{3em} % prevent overfull lines \setcounter{secnumdepth}{0} \VerbatimFootnotes % allows verbatim text in footnotes \title{Pandoc Test Suite} \author{John MacFarlane \and Anonymous} \date{July 17, 2006} \begin{document} \maketitle This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. \begin{center}\rule{3in}{0.4pt}\end{center} \section{Headers}\label{headers} \subsection{Level 2 with an \href{/url}{embedded link}}\label{level-2-with-an-embedded-link} \subsubsection{Level 3 with \emph{emphasis}}\label{level-3-with-emphasis} \paragraph{Level 4}\label{level-4} \subparagraph{Level 5}\label{level-5} \section{Level 1}\label{level-1} \subsection{Level 2 with \emph{emphasis}}\label{level-2-with-emphasis} \subsubsection{Level 3}\label{level-3} with no blank line \subsection{Level 2}\label{level-2} with no blank line \begin{center}\rule{3in}{0.4pt}\end{center} \section{Paragraphs}\label{paragraphs} Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. * criminey. There should be a hard line break\\here. \begin{center}\rule{3in}{0.4pt}\end{center} \section{Block Quotes}\label{block-quotes} E-mail style: \begin{quote} This is a block quote. It is pretty short. \end{quote} \begin{quote} Code in a block quote: \begin{verbatim} sub status { print "working"; } \end{verbatim} A list: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item item one \item item two \end{enumerate} Nested block quotes: \begin{quote} nested \end{quote} \begin{quote} nested \end{quote} \end{quote} This should not be a block quote: 2 \textgreater{} 1. And a following paragraph. \begin{center}\rule{3in}{0.4pt}\end{center} \section{Code Blocks}\label{code-blocks} Code: \begin{verbatim} ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab \end{verbatim} And: \begin{verbatim} this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ \end{verbatim} \begin{center}\rule{3in}{0.4pt}\end{center} \section{Lists}\label{lists} \subsection{Unordered}\label{unordered} Asterisks tight: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item asterisk 1 \item asterisk 2 \item asterisk 3 \end{itemize} Asterisks loose: \begin{itemize} \item asterisk 1 \item asterisk 2 \item asterisk 3 \end{itemize} Pluses tight: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Plus 1 \item Plus 2 \item Plus 3 \end{itemize} Pluses loose: \begin{itemize} \item Plus 1 \item Plus 2 \item Plus 3 \end{itemize} Minuses tight: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Minus 1 \item Minus 2 \item Minus 3 \end{itemize} Minuses loose: \begin{itemize} \item Minus 1 \item Minus 2 \item Minus 3 \end{itemize} \subsection{Ordered}\label{ordered} Tight: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item First \item Second \item Third \end{enumerate} and: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item One \item Two \item Three \end{enumerate} Loose using tabs: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \item First \item Second \item Third \end{enumerate} and using spaces: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \item One \item Two \item Three \end{enumerate} Multiple paragraphs: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \item Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog's back. \item Item 2. \item Item 3. \end{enumerate} \subsection{Nested}\label{nested} \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Tab \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Tab \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Tab \end{itemize} \end{itemize} \end{itemize} Here's another: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item First \item Second: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Fee \item Fie \item Foe \end{itemize} \item Third \end{enumerate} Same thing but with paragraphs: \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \item First \item Second: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item Fee \item Fie \item Foe \end{itemize} \item Third \end{enumerate} \subsection{Tabs and spaces}\label{tabs-and-spaces} \begin{itemize} \item this is a list item indented with tabs \item this is a list item indented with spaces \begin{itemize} \item this is an example list item indented with tabs \item this is an example list item indented with spaces \end{itemize} \end{itemize} \subsection{Fancy list markers}\label{fancy-list-markers} \begin{enumerate} \def\labelenumi{(\arabic{enumi})} \setcounter{enumi}{1} \item begins with 2 \item and now 3 with a continuation \begin{enumerate} \def\labelenumii{\roman{enumii}.} \setcounter{enumii}{3} \itemsep1pt\parskip0pt\parsep0pt \item sublist with roman numerals, starting with 4 \item more items \begin{enumerate} \def\labelenumiii{(\Alph{enumiii})} \itemsep1pt\parskip0pt\parsep0pt \item a subsublist \item a subsublist \end{enumerate} \end{enumerate} \end{enumerate} Nesting: \begin{enumerate} \def\labelenumi{\Alph{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item Upper Alpha \begin{enumerate} \def\labelenumii{\Roman{enumii}.} \itemsep1pt\parskip0pt\parsep0pt \item Upper Roman. \begin{enumerate} \def\labelenumiii{(\arabic{enumiii})} \setcounter{enumiii}{5} \itemsep1pt\parskip0pt\parsep0pt \item Decimal start with 6 \begin{enumerate} \def\labelenumiv{\alph{enumiv})} \setcounter{enumiv}{2} \itemsep1pt\parskip0pt\parsep0pt \item Lower alpha with paren \end{enumerate} \end{enumerate} \end{enumerate} \end{enumerate} Autonumbering: \begin{enumerate} \itemsep1pt\parskip0pt\parsep0pt \item Autonumber. \item More. \begin{enumerate} \itemsep1pt\parskip0pt\parsep0pt \item Nested. \end{enumerate} \end{enumerate} Should not be a list item: M.A.~2007 B. Williams \begin{center}\rule{3in}{0.4pt}\end{center} \section{Definition Lists}\label{definition-lists} Tight using spaces: \begin{description} \itemsep1pt\parskip0pt\parsep0pt \item[apple] red fruit \item[orange] orange fruit \item[banana] yellow fruit \end{description} Tight using tabs: \begin{description} \itemsep1pt\parskip0pt\parsep0pt \item[apple] red fruit \item[orange] orange fruit \item[banana] yellow fruit \end{description} Loose: \begin{description} \item[apple] red fruit \item[orange] orange fruit \item[banana] yellow fruit \end{description} Multiple blocks with italics: \begin{description} \item[\emph{apple}] red fruit contains seeds, crisp, pleasant to taste \item[\emph{orange}] orange fruit \begin{verbatim} { orange code block } \end{verbatim} \begin{quote} orange block quote \end{quote} \end{description} Multiple definitions, tight: \begin{description} \itemsep1pt\parskip0pt\parsep0pt \item[apple] red fruit computer \item[orange] orange fruit bank \end{description} Multiple definitions, loose: \begin{description} \item[apple] red fruit computer \item[orange] orange fruit bank \end{description} Blank line after term, indented marker, alternate markers: \begin{description} \item[apple] red fruit computer \item[orange] orange fruit \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item sublist \item sublist \end{enumerate} \end{description} \section{HTML Blocks}\label{html-blocks} Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table: This is \emph{emphasized} And this is \textbf{strong} Here's a simple block: foo This should be a code block, though: \begin{verbatim}
foo
\end{verbatim} As should this: \begin{verbatim}
foo
\end{verbatim} Now, nested: foo This should just be an HTML comment: Multiline: Code block: \begin{verbatim} \end{verbatim} Just plain comment, with trailing spaces on the line: Code: \begin{verbatim}
\end{verbatim} Hr's: \begin{center}\rule{3in}{0.4pt}\end{center} \section{Inline Markup}\label{inline-markup} This is \emph{emphasized}, and so \emph{is this}. This is \textbf{strong}, and so \textbf{is this}. An \emph{\href{/url}{emphasized link}}. \textbf{\emph{This is strong and em.}} So is \textbf{\emph{this}} word. \textbf{\emph{This is strong and em.}} So is \textbf{\emph{this}} word. This is code: \texttt{\textgreater{}}, \texttt{\$}, \texttt{\textbackslash{}}, \texttt{\textbackslash{}\$}, \texttt{\textless{}html\textgreater{}}. \sout{This is \emph{strikeout}.} Superscripts: a\textsuperscript{bc}d a\textsuperscript{\emph{hello}} a\textsuperscript{hello~there}. Subscripts: H\textsubscript{2}O, H\textsubscript{23}O, H\textsubscript{many~of~them}O. These should not be superscripts or subscripts, because of the unescaped spaces: a\^{}b c\^{}d, a\textasciitilde{}b c\textasciitilde{}d. \begin{center}\rule{3in}{0.4pt}\end{center} \section{Smart quotes, ellipses, dashes}\label{smart-quotes-ellipses-dashes} ``Hello,'' said the spider. ``\,`Shelob' is my name.'' `A', `B', and `C' are letters. `Oak,' `elm,' and `beech' are names of trees. So is `pine.' `He said, ``I want to go.''\,' Were you alive in the 70's? Here is some quoted `\texttt{code}' and a ``\href{http://example.com/?foo=1\&bar=2}{quoted link}''. Some dashes: one---two --- three---four --- five. Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses\ldots{}and\ldots{}and\ldots{}. \begin{center}\rule{3in}{0.4pt}\end{center} \section{LaTeX}\label{latex} \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item \cite[22-23]{smith.1899} \item $2+2=4$ \item $x \in y$ \item $\alpha \wedge \omega$ \item $223$ \item $p$-Tree \item Here's some display math: \[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\] \item Here's one that has a line break in it: $\alpha + \omega \times x^2$. \end{itemize} These shouldn't be math: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item To get the famous equation, write \texttt{\$e = mc\^{}2\$}. \item \$22,000 is a \emph{lot} of money. So is \$34,000. (It worked if ``lot'' is emphasized.) \item Shoes (\$20) and socks (\$5). \item Escaped \texttt{\$}: \$73 \emph{this should be emphasized} 23\$. \end{itemize} Here's a LaTeX table: \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} \begin{center}\rule{3in}{0.4pt}\end{center} \section{Special Characters}\label{special-characters} Here is some unicode: \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item I hat: Î \item o umlaut: ö \item section: § \item set membership: ∈ \item copyright: © \end{itemize} AT\&T has an ampersand in their name. AT\&T is another way to write it. This \& that. 4 \textless{} 5. 6 \textgreater{} 5. Backslash: \textbackslash{} Backtick: ` Asterisk: * Underscore: \_ Left brace: \{ Right brace: \} Left bracket: {[} Right bracket: {]} Left paren: ( Right paren: ) Greater-than: \textgreater{} Hash: \# Period: . Bang: ! Plus: + Minus: - \begin{center}\rule{3in}{0.4pt}\end{center} \section{Links}\label{links} \subsection{Explicit}\label{explicit} Just a \href{/url/}{URL}. \href{/url/}{URL and title}. \href{/url/}{URL and title}. \href{/url/}{URL and title}. \href{/url/}{URL and title} \href{/url/}{URL and title} \href{/url/with_underscore}{with\_underscore} \href{mailto:nobody@nowhere.net}{Email link} \href{}{Empty}. \subsection{Reference}\label{reference} Foo \href{/url/}{bar}. Foo \href{/url/}{bar}. Foo \href{/url/}{bar}. With \href{/url/}{embedded {[}brackets{]}}. \href{/url/}{b} by itself should be a link. Indented \href{/url}{once}. Indented \href{/url}{twice}. Indented \href{/url}{thrice}. This should {[}not{]}{[}{]} be a link. \begin{verbatim} [not]: /url \end{verbatim} Foo \href{/url/}{bar}. Foo \href{/url/}{biz}. \subsection{With ampersands}\label{with-ampersands} Here's a \href{http://example.com/?foo=1\&bar=2}{link with an ampersand in the URL}. Here's a link with an amersand in the link text: \href{http://att.com/}{AT\&T}. Here's an \href{/script?foo=1\&bar=2}{inline link}. Here's an \href{/script?foo=1\&bar=2}{inline link in pointy braces}. \subsection{Autolinks}\label{autolinks} With an ampersand: \url{http://example.com/?foo=1\&bar=2} \begin{itemize} \itemsep1pt\parskip0pt\parsep0pt \item In a list? \item \url{http://example.com/} \item It should. \end{itemize} An e-mail address: \href{mailto:nobody@nowhere.net}{nobody@nowhere.net} \begin{quote} Blockquoted: \url{http://example.com/} \end{quote} Auto-links should not occur here: \texttt{\textless{}http://example.com/\textgreater{}} \begin{verbatim} or here: \end{verbatim} \begin{center}\rule{3in}{0.4pt}\end{center} \section{Images}\label{images} From ``Voyage dans la Lune'' by Georges Melies (1902): \begin{figure}[htbp] \centering \includegraphics{lalune.jpg} \caption{lalune} \end{figure} Here is a movie \includegraphics{movie.jpg} icon. \begin{center}\rule{3in}{0.4pt}\end{center} \section{Footnotes}\label{footnotes} Here is a footnote reference,\footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.} and another.\footnote{Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). \begin{Verbatim} { } \end{Verbatim} If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.} This should \emph{not} be a footnote reference, because it contains a space.{[}\^{}my note{]} Here is an inline note.\footnote{This is \emph{easier} to type. Inline notes may contain \href{http://google.com}{links} and \texttt{{]}} verbatim characters, as well as {[}bracketed text{]}.} \begin{quote} Notes can go in quotes.\footnote{In quote.} \end{quote} \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \itemsep1pt\parskip0pt\parsep0pt \item And in list items.\footnote{In list.} \end{enumerate} This paragraph should not be part of the note, as it is not indented. \end{document} pandoc-1.12.2.1/tests/writer.man000644 000765 000024 00000024463 12251233603 016301 0ustar00jgmstaff000000 000000 .TH "Pandoc Test Suite" "" "July 17, 2006" "" "" .PP This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. .PP * * * * * .SH Headers .SS Level 2 with an embedded link (/url) .SS Level 3 with \f[I]emphasis\f[] .SS Level 4 .SS Level 5 .SH Level 1 .SS Level 2 with \f[I]emphasis\f[] .SS Level 3 .PP with no blank line .SS Level 2 .PP with no blank line .PP * * * * * .SH Paragraphs .PP Here's a regular paragraph. .PP 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. .PP Here's one with a bullet. * criminey. .PP There should be a hard line break .PD 0 .P .PD here. .PP * * * * * .SH Block Quotes .PP E\-mail style: .RS .PP This is a block quote. It is pretty short. .RE .RS .PP Code in a block quote: .IP .nf \f[C] sub\ status\ { \ \ \ \ print\ "working"; } \f[] .fi .PP A list: .IP "1." 3 item one .IP "2." 3 item two .PP Nested block quotes: .RS .PP nested .RE .RS .PP nested .RE .RE .PP This should not be a block quote: 2 > 1. .PP And a following paragraph. .PP * * * * * .SH Code Blocks .PP Code: .IP .nf \f[C] \-\-\-\-\ (should\ be\ four\ hyphens) sub\ status\ { \ \ \ \ print\ "working"; } this\ code\ block\ is\ indented\ by\ one\ tab \f[] .fi .PP And: .IP .nf \f[C] \ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{ \f[] .fi .PP * * * * * .SH Lists .SS Unordered .PP Asterisks tight: .IP \[bu] 2 asterisk 1 .IP \[bu] 2 asterisk 2 .IP \[bu] 2 asterisk 3 .PP Asterisks loose: .IP \[bu] 2 asterisk 1 .IP \[bu] 2 asterisk 2 .IP \[bu] 2 asterisk 3 .PP Pluses tight: .IP \[bu] 2 Plus 1 .IP \[bu] 2 Plus 2 .IP \[bu] 2 Plus 3 .PP Pluses loose: .IP \[bu] 2 Plus 1 .IP \[bu] 2 Plus 2 .IP \[bu] 2 Plus 3 .PP Minuses tight: .IP \[bu] 2 Minus 1 .IP \[bu] 2 Minus 2 .IP \[bu] 2 Minus 3 .PP Minuses loose: .IP \[bu] 2 Minus 1 .IP \[bu] 2 Minus 2 .IP \[bu] 2 Minus 3 .SS Ordered .PP Tight: .IP "1." 3 First .IP "2." 3 Second .IP "3." 3 Third .PP and: .IP "1." 3 One .IP "2." 3 Two .IP "3." 3 Three .PP Loose using tabs: .IP "1." 3 First .IP "2." 3 Second .IP "3." 3 Third .PP and using spaces: .IP "1." 3 One .IP "2." 3 Two .IP "3." 3 Three .PP Multiple paragraphs: .IP "1." 3 Item 1, graf one. .RS 4 .PP Item 1. graf two. The quick brown fox jumped over the lazy dog's back. .RE .IP "2." 3 Item 2. .IP "3." 3 Item 3. .SS Nested .IP \[bu] 2 Tab .RS 2 .IP \[bu] 2 Tab .RS 2 .IP \[bu] 2 Tab .RE .RE .PP Here's another: .IP "1." 3 First .IP "2." 3 Second: .RS 4 .IP \[bu] 2 Fee .IP \[bu] 2 Fie .IP \[bu] 2 Foe .RE .IP "3." 3 Third .PP Same thing but with paragraphs: .IP "1." 3 First .IP "2." 3 Second: .RS 4 .IP \[bu] 2 Fee .IP \[bu] 2 Fie .IP \[bu] 2 Foe .RE .IP "3." 3 Third .SS Tabs and spaces .IP \[bu] 2 this is a list item indented with tabs .IP \[bu] 2 this is a list item indented with spaces .RS 2 .IP \[bu] 2 this is an example list item indented with tabs .IP \[bu] 2 this is an example list item indented with spaces .RE .SS Fancy list markers .IP "(2)" 4 begins with 2 .IP "(3)" 4 and now 3 .RS 4 .PP with a continuation .IP "iv." 4 sublist with roman numerals, starting with 4 .IP " v." 4 more items .RS 4 .IP "(A)" 4 a subsublist .IP "(B)" 4 a subsublist .RE .RE .PP Nesting: .IP "A." 3 Upper Alpha .RS 4 .IP "I." 3 Upper Roman. .RS 4 .IP "(6)" 4 Decimal start with 6 .RS 4 .IP "c)" 3 Lower alpha with paren .RE .RE .RE .PP Autonumbering: .IP "1." 3 Autonumber. .IP "2." 3 More. .RS 4 .IP "1." 3 Nested. .RE .PP Should not be a list item: .PP M.A.\ 2007 .PP B. Williams .PP * * * * * .SH Definition Lists .PP Tight using spaces: .TP .B apple red fruit .RS .RE .TP .B orange orange fruit .RS .RE .TP .B banana yellow fruit .RS .RE .PP Tight using tabs: .TP .B apple red fruit .RS .RE .TP .B orange orange fruit .RS .RE .TP .B banana yellow fruit .RS .RE .PP Loose: .TP .B apple red fruit .RS .RE .TP .B orange orange fruit .RS .RE .TP .B banana yellow fruit .RS .RE .PP Multiple blocks with italics: .TP .B \f[I]apple\f[] red fruit .RS .PP contains seeds, crisp, pleasant to taste .RE .TP .B \f[I]orange\f[] orange fruit .RS .IP .nf \f[C] {\ orange\ code\ block\ } \f[] .fi .RS .PP orange block quote .RE .RE .PP Multiple definitions, tight: .TP .B apple red fruit .RS .RE computer .RS .RE .TP .B orange orange fruit .RS .RE bank .RS .RE .PP Multiple definitions, loose: .TP .B apple red fruit .RS .RE computer .RS .RE .TP .B orange orange fruit .RS .RE bank .RS .RE .PP Blank line after term, indented marker, alternate markers: .TP .B apple red fruit .RS .RE computer .RS .RE .TP .B orange orange fruit .RS .IP "1." 3 sublist .IP "2." 3 sublist .RE .SH HTML Blocks .PP Simple block on one line: foo .PP And nested without indentation: foo bar .PP Interpreted markdown in a table: This is \f[I]emphasized\f[] And this is \f[B]strong\f[] .PP Here's a simple block: foo .PP This should be a code block, though: .IP .nf \f[C]
\ \ \ \ foo
\f[] .fi .PP As should this: .IP .nf \f[C]
foo
\f[] .fi .PP Now, nested: foo .PP This should just be an HTML comment: .PP Multiline: .PP Code block: .IP .nf \f[C] \f[] .fi .PP Just plain comment, with trailing spaces on the line: .PP Code: .IP .nf \f[C] \f[] .fi .PP Hr's: .PP * * * * * .SH Inline Markup .PP This is \f[I]emphasized\f[], and so \f[I]is this\f[]. .PP This is \f[B]strong\f[], and so \f[B]is this\f[]. .PP An \f[I]emphasized link (/url)\f[]. .PP \f[B]\f[I]This is strong and em.\f[]\f[] .PP So is \f[B]\f[I]this\f[]\f[] word. .PP \f[B]\f[I]This is strong and em.\f[]\f[] .PP So is \f[B]\f[I]this\f[]\f[] word. .PP This is code: \f[C]>\f[], \f[C]$\f[], \f[C]\\\f[], \f[C]\\$\f[], \f[C]\f[]. .PP [STRIKEOUT:This is \f[I]strikeout\f[].] .PP Superscripts: a^bc^d a^\f[I]hello\f[]^ a^hello\ there^. .PP Subscripts: H~2~O, H~23~O, H~many\ of\ them~O. .PP These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. .PP * * * * * .SH Smart quotes, ellipses, dashes .PP \[lq]Hello,\[rq] said the spider. \[lq]`Shelob' is my name.\[rq] .PP `A', `B', and `C' are letters. .PP `Oak,' `elm,' and `beech' are names of trees. So is `pine.' .PP `He said, \[lq]I want to go.\[rq]' Were you alive in the 70's? .PP Here is some quoted `\f[C]code\f[]' and a \[lq]quoted link (http://example.com/?foo=1&bar=2)\[rq]. .PP Some dashes: one\[em]two \[em] three\[em]four \[em] five. .PP Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999. .PP Ellipses\&...and\&...and\&.... .PP * * * * * .SH LaTeX .IP \[bu] 2 .IP \[bu] 2 2 + 2 = 4 .IP \[bu] 2 \f[I]x\f[] ∈ \f[I]y\f[] .IP \[bu] 2 \f[I]α\f[] ∧ \f[I]ω\f[] .IP \[bu] 2 223 .IP \[bu] 2 \f[I]p\f[]\-Tree .IP \[bu] 2 Here's some display math: .RS $$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)\-f(x)}{h}$$ .RE .IP \[bu] 2 Here's one that has a line break in it: \f[I]α\f[] + \f[I]ω\f[] × \f[I]x\f[]^2^. .PP These shouldn't be math: .IP \[bu] 2 To get the famous equation, write \f[C]$e\ =\ mc^2$\f[]. .IP \[bu] 2 $22,000 is a \f[I]lot\f[] of money. So is $34,000. (It worked if \[lq]lot\[rq] is emphasized.) .IP \[bu] 2 Shoes ($20) and socks ($5). .IP \[bu] 2 Escaped \f[C]$\f[]: $73 \f[I]this should be emphasized\f[] 23$. .PP Here's a LaTeX table: .PP * * * * * .SH Special Characters .PP Here is some unicode: .IP \[bu] 2 I hat: Î .IP \[bu] 2 o umlaut: ö .IP \[bu] 2 section: § .IP \[bu] 2 set membership: ∈ .IP \[bu] 2 copyright: © .PP AT&T has an ampersand in their name. .PP AT&T is another way to write it. .PP This & that. .PP 4 < 5. .PP 6 > 5. .PP Backslash: \\ .PP Backtick: ` .PP Asterisk: * .PP Underscore: _ .PP Left brace: { .PP Right brace: } .PP Left bracket: [ .PP Right bracket: ] .PP Left paren: ( .PP Right paren: ) .PP Greater\-than: > .PP Hash: # .PP Period: . .PP Bang: ! .PP Plus: + .PP Minus: \- .PP * * * * * .SH Links .SS Explicit .PP Just a URL (/url/). .PP URL and title (/url/). .PP URL and title (/url/). .PP URL and title (/url/). .PP URL and title (/url/) .PP URL and title (/url/) .PP with_underscore (/url/with_underscore) .PP Email link (mailto:nobody@nowhere.net) .PP Empty (). .SS Reference .PP Foo bar (/url/). .PP Foo bar (/url/). .PP Foo bar (/url/). .PP With embedded [brackets] (/url/). .PP b (/url/) by itself should be a link. .PP Indented once (/url). .PP Indented twice (/url). .PP Indented thrice (/url). .PP This should [not][] be a link. .IP .nf \f[C] [not]:\ /url \f[] .fi .PP Foo bar (/url/). .PP Foo biz (/url/). .SS With ampersands .PP Here's a link with an ampersand in the URL (http://example.com/?foo=1&bar=2). .PP Here's a link with an amersand in the link text: AT&T (http://att.com/). .PP Here's an inline link (/script?foo=1&bar=2). .PP Here's an inline link in pointy braces (/script?foo=1&bar=2). .SS Autolinks .PP With an ampersand: .IP \[bu] 2 In a list? .IP \[bu] 2 .IP \[bu] 2 It should. .PP An e\-mail address: .RS .PP Blockquoted: .RE .PP Auto\-links should not occur here: \f[C]\f[] .IP .nf \f[C] or\ here:\ \f[] .fi .PP * * * * * .SH Images .PP From \[lq]Voyage dans la Lune\[rq] by Georges Melies (1902): .PP [IMAGE: lalune (lalune.jpg)] .PP Here is a movie [IMAGE: movie (movie.jpg)] icon. .PP * * * * * .SH Footnotes .PP Here is a footnote reference,[1] and another.[2] This should \f[I]not\f[] be a footnote reference, because it contains a space.[^my note] Here is an inline note.[3] .RS .PP Notes can go in quotes.[4] .RE .IP "1." 3 And in list items.[5] .PP This paragraph should not be part of the note, as it is not indented. .SH NOTES .SS [1] .PP Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. .SS [2] .PP Here's the long note. This one contains multiple blocks. .PP Subsequent blocks are indented to show that they belong to the footnote (as with list items). .IP .nf \f[C] \ \ {\ \ } \f[] .fi .PP If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. .SS [3] .PP This is \f[I]easier\f[] to type. Inline notes may contain links (http://google.com) and \f[C]]\f[] verbatim characters, as well as [bracketed text]. .SS [4] .PP In quote. .SS [5] .PP In list. .SH AUTHORS John MacFarlane; Anonymous. pandoc-1.12.2.1/tests/writer.markdown000644 000765 000024 00000023021 12251233603 017335 0ustar00jgmstaff000000 000000 --- author: - John MacFarlane - Anonymous date: 'July 17, 2006' title: Pandoc Test Suite ... This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. * * * * * Headers ======= Level 2 with an [embedded link](/url) ------------------------------------- ### Level 3 with *emphasis* #### Level 4 ##### Level 5 Level 1 ======= Level 2 with *emphasis* ----------------------- ### Level 3 with no blank line Level 2 ------- with no blank line * * * * * Paragraphs ========== Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. \* criminey. There should be a hard line break\ here. * * * * * Block Quotes ============ E-mail style: > This is a block quote. It is pretty short. > Code in a block quote: > > sub status { > print "working"; > } > > A list: > > 1. item one > 2. item two > > Nested block quotes: > > > nested > > > nested This should not be a block quote: 2 \> 1. And a following paragraph. * * * * * Code Blocks =========== Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ * * * * * Lists ===== 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 1. 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 Tabs and spaces --------------- - this is a list item indented with tabs - this is a list item indented with spaces - this is an example list item indented with tabs - this is an example list item indented with spaces Fancy list markers ------------------ (2) begins with 2 (3) and now 3 with a continuation iv. sublist with roman numerals, starting with 4 v. more items (A) a subsublist (B) a subsublist Nesting: A. Upper Alpha I. Upper Roman. (6) Decimal start with 6 c) Lower alpha with paren Autonumbering: 1. Autonumber. 2. More. 1. Nested. Should not be a list item: M.A. 2007 B. Williams * * * * * Definition Lists ================ Tight using spaces: apple : red fruit orange : orange fruit banana : yellow fruit Tight using tabs: apple : red fruit orange : orange fruit banana : yellow fruit Loose: apple : red fruit orange : orange fruit banana : yellow fruit Multiple blocks with italics: *apple* : red fruit contains seeds, crisp, pleasant to taste *orange* : orange fruit { orange code block } > orange block quote Multiple definitions, tight: apple : red fruit : computer orange : orange fruit : bank Multiple definitions, loose: apple : red fruit : computer orange : orange fruit : bank Blank line after term, indented marker, alternate markers: apple : red fruit : computer orange : orange fruit 1. sublist 2. sublist HTML Blocks =========== Simple block on one line:
foo
And nested without indentation:
foo
bar
Interpreted markdown in a table:
This is *emphasized* And this is **strong**
Here’s a simple block:
foo
This should be a code block, though:
foo
As should this:
foo
Now, nested:
foo
This should just be an HTML comment: Multiline: Code block: Just plain comment, with trailing spaces on the line: Code:
Hr’s:








* * * * * Inline Markup ============= This is *emphasized*, and so *is this*. This is **strong**, and so **is this**. An *[emphasized link](/url)*. ***This is strong and em.*** So is ***this*** word. ***This is strong and em.*** So is ***this*** word. This is code: `>`, `$`, `\`, `\$`, ``. ~~This is *strikeout*.~~ Superscripts: a^bc^d a^*hello*^ a^hello there^. Subscripts: H~2~O, H~23~O, H~many of them~O. These should not be superscripts or subscripts, because of the unescaped spaces: a\^b c\^d, a\~b c\~d. * * * * * Smart quotes, ellipses, dashes ============================== “Hello,” said the spider. “‘Shelob’ is my name.” ‘A’, ‘B’, and ‘C’ are letters. ‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ ‘He said, “I want to go.”’ Were you alive in the 70’s? Here is some quoted ‘`code`’ and a “[quoted link](http://example.com/?foo=1&bar=2)”. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. * * * * * LaTeX ===== - \cite[22-23]{smith.1899} - $2+2=4$ - $x \in y$ - $\alpha \wedge \omega$ - $223$ - $p$-Tree - Here’s some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ - Here’s one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn’t be math: - To get the famous equation, write `$e = mc^2$`. - \$22,000 is a *lot* of money. So is \$34,000. (It worked if “lot” is emphasized.) - Shoes (\$20) and socks (\$5). - Escaped `$`: \$73 *this should be emphasized* 23\$. Here’s a LaTeX table: \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} * * * * * Special Characters ================== Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 \< 5. 6 \> 5. Backslash: \\ Backtick: \` Asterisk: \* Underscore: \_ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: \> Hash: \# Period: . Bang: ! Plus: + Minus: - * * * * * Links ===== Explicit -------- 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 with "quotes" in it") [URL and title](/url/ "title with single quotes") [with\_underscore](/url/with_underscore) [Email link](mailto:nobody@nowhere.net) [Empty](). Reference --------- Foo [bar](/url/). Foo [bar](/url/). Foo [bar](/url/). With [embedded [brackets]](/url/). [b](/url/) by itself should be a link. Indented [once](/url). Indented [twice](/url). Indented [thrice](/url). This should [not][] be a link. [not]: /url Foo [bar](/url/ "Title with "quotes" inside"). Foo [biz](/url/ "Title with "quote" inside"). With ampersands --------------- Here’s a [link with an ampersand in the URL](http://example.com/?foo=1&bar=2). Here’s a link with an amersand in the link text: [AT&T](http://att.com/ "AT&T"). Here’s an [inline link](/script?foo=1&bar=2). Here’s an [inline link in pointy braces](/script?foo=1&bar=2). Autolinks --------- With an ampersand: - In a list? - - It should. An e-mail address: > Blockquoted: Auto-links should not occur here: `` or here: * * * * * Images ====== From “Voyage dans la Lune” by Georges Melies (1902): ![lalune](lalune.jpg "Voyage dans la Lune") Here is a movie ![movie](movie.jpg) icon. * * * * * Footnotes ========= Here is a footnote reference,[^1] and another.[^2] This should *not* be a footnote reference, because it contains a space.[\^my note] Here is an inline note.[^3] > Notes can go in quotes.[^4] 1. And in list items.[^5] This paragraph should not be part of the note, as it is not indented. [^1]: Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. [^2]: Here’s the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). { } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. [^3]: This is *easier* to type. Inline notes may contain [links](http://google.com) and `]` verbatim characters, as well as [bracketed text]. [^4]: In quote. [^5]: In list. pandoc-1.12.2.1/tests/writer.mediawiki000644 000765 000024 00000023327 12251233603 017467 0ustar00jgmstaff000000 000000 This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. ----- = Headers = == Level 2 with an [[url|embedded link]] == === Level 3 with ''emphasis'' === ==== Level 4 ==== ===== Level 5 ===== = Level 1 = == Level 2 with ''emphasis'' == === Level 3 === with no blank line == Level 2 == with no blank line ----- = Paragraphs = Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. * criminey. There should be a hard line break
here. ----- = Block Quotes = E-mail style:
This is a block quote. It is pretty short.
Code in a block quote:
sub status {
    print "working";
}
A list: # item one # item two Nested block quotes:
nested
nested
This should not be a block quote: 2 > 1. And a following paragraph. ----- = Code Blocks = Code:
---- (should be four hyphens)

sub status {
    print "working";
}

this code block is indented by one tab
And:
    this code block is indented by two tabs

These should not be escaped:  \$ \\ \> \[ \{
----- = Lists = == 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: # First # Second # Third and: # One # Two # Three Loose using tabs: # First # Second # Third and using spaces: # One # Two # Three Multiple paragraphs:
  1. Item 1, graf one.

    Item 1. 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: # First # Second: #* Fee #* Fie #* Foe # Third Same thing but with paragraphs: # First # Second: #* Fee #* Fie #* Foe # Third == Tabs and spaces == * this is a list item indented with tabs * this is a list item indented with spaces ** this is an example list item indented with tabs ** this is an example list item indented with spaces == Fancy list markers ==
  1. begins with 2
  2. and now 3

    with a continuation

    1. sublist with roman numerals, starting with 4
    2. more items
      1. a subsublist
      2. a subsublist
Nesting:
  1. Upper Alpha
    1. Upper Roman.
      1. Decimal start with 6
        1. Lower alpha with paren
Autonumbering: # Autonumber. # More. ## Nested. Should not be a list item: M.A. 2007 B. Williams ----- = Definition Lists = Tight using spaces: ; apple : red fruit ; orange : orange fruit ; banana : yellow fruit Tight using tabs: ; apple : red fruit ; orange : orange fruit ; banana : yellow fruit Loose: ; apple : red fruit ; orange : orange fruit ; banana : yellow fruit Multiple blocks with italics:
''apple''

red fruit

contains seeds, crisp, pleasant to taste

''orange''

orange fruit

{ orange code block }

orange block quote

Multiple definitions, tight: ; apple : red fruit : computer ; orange : orange fruit : bank Multiple definitions, loose: ; apple : red fruit : computer ; orange : orange fruit : bank Blank line after term, indented marker, alternate markers: ; apple : red fruit : computer ; orange : orange fruit ;# sublist ;# sublist = HTML Blocks = Simple block on one line:
foo
And nested without indentation:
foo
bar
Interpreted markdown in a table:
This is ''emphasized'' And this is '''strong'''
Here’s a simple block:
foo
This should be a code block, though:
<div>
    foo
</div>
As should this:
<div>foo</div>
Now, nested:
foo
This should just be an HTML comment: Multiline: Code block:
<!-- Comment -->
Just plain comment, with trailing spaces on the line: Code:
<hr />
Hr’s:








----- = Inline Markup = This is ''emphasized'', and so ''is this''. This is '''strong''', and so '''is this'''. An ''[[url|emphasized link]]''. '''''This is strong and em.''''' So is '''''this''''' word. '''''This is strong and em.''''' So is '''''this''''' word. This is code: >, $, \, \$, <html>. This is ''strikeout''. Superscripts: abcd a''hello'' ahello there. Subscripts: H2O, H23O, Hmany of themO. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. ----- = Smart quotes, ellipses, dashes = “Hello,” said the spider. “‘Shelob’ is my name.” ‘A’, ‘B’, and ‘C’ are letters. ‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ ‘He said, “I want to go.”’ Were you alive in the 70’s? Here is some quoted ‘code’ and a “[http://example.com/?foo=1&bar=2 quoted link]”. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. ----- = LaTeX = * * 2+2=4 * x \in y * \alpha \wedge \omega * 223 * p-Tree * Here’s some display math: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h} * Here’s one that has a line break in it: \alpha + \omega \times x^2. These shouldn’t be math: * To get the famous equation, write $e = mc^2$. * $22,000 is a ''lot'' of money. So is $34,000. (It worked if “lot” is emphasized.) * Shoes ($20) and socks ($5). * Escaped $: $73 ''this should be emphasized'' 23$. Here’s a LaTeX table: ----- = Special Characters = Here is some unicode: * I hat: Î * o umlaut: ö * section: § * set membership: ∈ * copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - ----- = Links = == Explicit == Just a [[url/|URL]]. [[url/|URL and title]]. [[url/|URL and title]]. [[url/|URL and title]]. [[url/|URL and title]] [[url/|URL and title]] [[url/with_underscore|with_underscore]] [mailto:nobody@nowhere.net Email link] [[|Empty]]. == Reference == Foo [[url/|bar]]. Foo [[url/|bar]]. Foo [[url/|bar]]. With [[url/|embedded [brackets]]]. [[url/|b]] by itself should be a link. Indented [[url|once]]. Indented [[url|twice]]. Indented [[url|thrice]]. This should [not][] be a link.
[not]: /url
Foo [[url/|bar]]. Foo [[url/|biz]]. == With ampersands == Here’s a [http://example.com/?foo=1&bar=2 link with an ampersand in the URL]. Here’s a link with an amersand in the link text: [http://att.com/ AT&T]. Here’s an [[script?foo=1&bar=2|inline link]]. Here’s an [[script?foo=1&bar=2|inline link in pointy braces]]. == Autolinks == With an ampersand: http://example.com/?foo=1&bar=2 * In a list? * http://example.com/ * It should. An e-mail address: [mailto:nobody@nowhere.net nobody@nowhere.net]
Blockquoted: http://example.com/
Auto-links should not occur here: <http://example.com/>
or here: <http://example.com/>
----- = Images = From “Voyage dans la Lune” by Georges Melies (1902): [[Image:lalune.jpg|frame|none|alt=Voyage dans la Lune|caption lalune]] Here is a movie [[Image:movie.jpg|movie]] icon. ----- = Footnotes = Here is a footnote reference,Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. and another.Here’s the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items).
  { <code> }
If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.
This should ''not'' be a footnote reference, because it contains a space.[^my note] Here is an inline note.This is ''easier'' to type. Inline notes may contain [http://google.com links] and ] verbatim characters, as well as [bracketed text].
Notes can go in quotes.In quote.
# And in list items.In list. This paragraph should not be part of the note, as it is not indented. pandoc-1.12.2.1/tests/writer.native000644 000765 000024 00000064012 12251233603 017006 0ustar00jgmstaff000000 000000 Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Space,Str "MacFarlane"],MetaInlines [Str "Anonymous"]]),("date",MetaInlines [Str "July",Space,Str "17,",Space,Str "2006"]),("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.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."] ,HorizontalRule ,Header 1 ("headers",[],[]) [Str "Headers"] ,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embedded",Space,Str "link"] ("/url","")] ,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Emph [Str "emphasis"]] ,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"] ,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"] ,Header 1 ("level-1",[],[]) [Str "Level",Space,Str "1"] ,Header 2 ("level-2-with-emphasis",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Emph [Str "emphasis"]] ,Header 3 ("level-3",[],[]) [Str "Level",Space,Str "3"] ,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"] ,Header 2 ("level-2",[],[]) [Str "Level",Space,Str "2"] ,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"] ,HorizontalRule ,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"] ,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph."] ,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."] ,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."] ,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here."] ,HorizontalRule ,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"] ,Para [Str "E-mail",Space,Str "style:"] ,BlockQuote [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]] ,BlockQuote [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"] ,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}" ,Para [Str "A",Space,Str "list:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "item",Space,Str "one"]] ,[Plain [Str "item",Space,Str "two"]]] ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"] ,BlockQuote [Para [Str "nested"]] ,BlockQuote [Para [Str "nested"]]] ,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."] ,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."] ,HorizontalRule ,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"] ,Para [Str "Code:"] ,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab" ,Para [Str "And:"] ,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{" ,HorizontalRule ,Header 1 ("lists",[],[]) [Str "Lists"] ,Header 2 ("unordered",[],[]) [Str "Unordered"] ,Para [Str "Asterisks",Space,Str "tight:"] ,BulletList [[Plain [Str "asterisk",Space,Str "1"]] ,[Plain [Str "asterisk",Space,Str "2"]] ,[Plain [Str "asterisk",Space,Str "3"]]] ,Para [Str "Asterisks",Space,Str "loose:"] ,BulletList [[Para [Str "asterisk",Space,Str "1"]] ,[Para [Str "asterisk",Space,Str "2"]] ,[Para [Str "asterisk",Space,Str "3"]]] ,Para [Str "Pluses",Space,Str "tight:"] ,BulletList [[Plain [Str "Plus",Space,Str "1"]] ,[Plain [Str "Plus",Space,Str "2"]] ,[Plain [Str "Plus",Space,Str "3"]]] ,Para [Str "Pluses",Space,Str "loose:"] ,BulletList [[Para [Str "Plus",Space,Str "1"]] ,[Para [Str "Plus",Space,Str "2"]] ,[Para [Str "Plus",Space,Str "3"]]] ,Para [Str "Minuses",Space,Str "tight:"] ,BulletList [[Plain [Str "Minus",Space,Str "1"]] ,[Plain [Str "Minus",Space,Str "2"]] ,[Plain [Str "Minus",Space,Str "3"]]] ,Para [Str "Minuses",Space,Str "loose:"] ,BulletList [[Para [Str "Minus",Space,Str "1"]] ,[Para [Str "Minus",Space,Str "2"]] ,[Para [Str "Minus",Space,Str "3"]]] ,Header 2 ("ordered",[],[]) [Str "Ordered"] ,Para [Str "Tight:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "First"]] ,[Plain [Str "Second"]] ,[Plain [Str "Third"]]] ,Para [Str "and:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "One"]] ,[Plain [Str "Two"]] ,[Plain [Str "Three"]]] ,Para [Str "Loose",Space,Str "using",Space,Str "tabs:"] ,OrderedList (1,Decimal,Period) [[Para [Str "First"]] ,[Para [Str "Second"]] ,[Para [Str "Third"]]] ,Para [Str "and",Space,Str "using",Space,Str "spaces:"] ,OrderedList (1,Decimal,Period) [[Para [Str "One"]] ,[Para [Str "Two"]] ,[Para [Str "Three"]]] ,Para [Str "Multiple",Space,Str "paragraphs:"] ,OrderedList (1,Decimal,Period) [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."] ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",Space,Str "back."]] ,[Para [Str "Item",Space,Str "2."]] ,[Para [Str "Item",Space,Str "3."]]] ,Header 2 ("nested",[],[]) [Str "Nested"] ,BulletList [[Plain [Str "Tab"] ,BulletList [[Plain [Str "Tab"] ,BulletList [[Plain [Str "Tab"]]]]]]] ,Para [Str "Here\8217s",Space,Str "another:"] ,OrderedList (1,Decimal,Period) [[Plain [Str "First"]] ,[Plain [Str "Second:"] ,BulletList [[Plain [Str "Fee"]] ,[Plain [Str "Fie"]] ,[Plain [Str "Foe"]]]] ,[Plain [Str "Third"]]] ,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"] ,OrderedList (1,Decimal,Period) [[Para [Str "First"]] ,[Para [Str "Second:"] ,BulletList [[Plain [Str "Fee"]] ,[Plain [Str "Fie"]] ,[Plain [Str "Foe"]]]] ,[Para [Str "Third"]]] ,Header 2 ("tabs-and-spaces",[],[]) [Str "Tabs",Space,Str "and",Space,Str "spaces"] ,BulletList [[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]] ,[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"] ,BulletList [[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]] ,[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]]]]] ,Header 2 ("fancy-list-markers",[],[]) [Str "Fancy",Space,Str "list",Space,Str "markers"] ,OrderedList (2,Decimal,TwoParens) [[Plain [Str "begins",Space,Str "with",Space,Str "2"]] ,[Para [Str "and",Space,Str "now",Space,Str "3"] ,Para [Str "with",Space,Str "a",Space,Str "continuation"] ,OrderedList (4,LowerRoman,Period) [[Plain [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals,",Space,Str "starting",Space,Str "with",Space,Str "4"]] ,[Plain [Str "more",Space,Str "items"] ,OrderedList (1,UpperAlpha,TwoParens) [[Plain [Str "a",Space,Str "subsublist"]] ,[Plain [Str "a",Space,Str "subsublist"]]]]]]] ,Para [Str "Nesting:"] ,OrderedList (1,UpperAlpha,Period) [[Plain [Str "Upper",Space,Str "Alpha"] ,OrderedList (1,UpperRoman,Period) [[Plain [Str "Upper",Space,Str "Roman."] ,OrderedList (6,Decimal,TwoParens) [[Plain [Str "Decimal",Space,Str "start",Space,Str "with",Space,Str "6"] ,OrderedList (3,LowerAlpha,OneParen) [[Plain [Str "Lower",Space,Str "alpha",Space,Str "with",Space,Str "paren"]]]]]]]]] ,Para [Str "Autonumbering:"] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "Autonumber."]] ,[Plain [Str "More."] ,OrderedList (1,DefaultStyle,DefaultDelim) [[Plain [Str "Nested."]]]]] ,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item:"] ,Para [Str "M.A.\160\&2007"] ,Para [Str "B.",Space,Str "Williams"] ,HorizontalRule ,Header 1 ("definition-lists",[],[]) [Str "Definition",Space,Str "Lists"] ,Para [Str "Tight",Space,Str "using",Space,Str "spaces:"] ,DefinitionList [([Str "apple"], [[Plain [Str "red",Space,Str "fruit"]]]) ,([Str "orange"], [[Plain [Str "orange",Space,Str "fruit"]]]) ,([Str "banana"], [[Plain [Str "yellow",Space,Str "fruit"]]])] ,Para [Str "Tight",Space,Str "using",Space,Str "tabs:"] ,DefinitionList [([Str "apple"], [[Plain [Str "red",Space,Str "fruit"]]]) ,([Str "orange"], [[Plain [Str "orange",Space,Str "fruit"]]]) ,([Str "banana"], [[Plain [Str "yellow",Space,Str "fruit"]]])] ,Para [Str "Loose:"] ,DefinitionList [([Str "apple"], [[Para [Str "red",Space,Str "fruit"]]]) ,([Str "orange"], [[Para [Str "orange",Space,Str "fruit"]]]) ,([Str "banana"], [[Para [Str "yellow",Space,Str "fruit"]]])] ,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics:"] ,DefinitionList [([Emph [Str "apple"]], [[Para [Str "red",Space,Str "fruit"] ,Para [Str "contains",Space,Str "seeds,",Space,Str "crisp,",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]]) ,([Emph [Str "orange"]], [[Para [Str "orange",Space,Str "fruit"] ,CodeBlock ("",[],[]) "{ orange code block }" ,BlockQuote [Para [Str "orange",Space,Str "block",Space,Str "quote"]]]])] ,Para [Str "Multiple",Space,Str "definitions,",Space,Str "tight:"] ,DefinitionList [([Str "apple"], [[Plain [Str "red",Space,Str "fruit"]] ,[Plain [Str "computer"]]]) ,([Str "orange"], [[Plain [Str "orange",Space,Str "fruit"]] ,[Plain [Str "bank"]]])] ,Para [Str "Multiple",Space,Str "definitions,",Space,Str "loose:"] ,DefinitionList [([Str "apple"], [[Para [Str "red",Space,Str "fruit"]] ,[Para [Str "computer"]]]) ,([Str "orange"], [[Para [Str "orange",Space,Str "fruit"]] ,[Para [Str "bank"]]])] ,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term,",Space,Str "indented",Space,Str "marker,",Space,Str "alternate",Space,Str "markers:"] ,DefinitionList [([Str "apple"], [[Para [Str "red",Space,Str "fruit"]] ,[Para [Str "computer"]]]) ,([Str "orange"], [[Para [Str "orange",Space,Str "fruit"] ,OrderedList (1,Decimal,Period) [[Plain [Str "sublist"]] ,[Plain [Str "sublist"]]]]])] ,Header 1 ("html-blocks",[],[]) [Str "HTML",Space,Str "Blocks"] ,Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line:"] ,Div ("",[],[]) [Plain [Str "foo"]] ,Para [Str "And",Space,Str "nested",Space,Str "without",Space,Str "indentation:"] ,Div ("",[],[]) [Div ("",[],[]) [Div ("",[],[]) [Plain [Str "foo"]]],Div ("",[],[]) [Plain [Str "bar"]]] ,Para [Str "Interpreted",Space,Str "markdown",Space,Str "in",Space,Str "a",Space,Str "table:"] ,RawBlock (Format "html") "\n\n\n\n\n
" ,Plain [Str "This",Space,Str "is",Space,Emph [Str "emphasized"]] ,RawBlock (Format "html") "" ,Plain [Str "And",Space,Str "this",Space,Str "is",Space,Strong [Str "strong"]] ,RawBlock (Format "html") "
\n\n\n" ,Para [Str "Here\8217s",Space,Str "a",Space,Str "simple",Space,Str "block:"] ,Div ("",[],[]) [Plain [Str "foo"]] ,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "code",Space,Str "block,",Space,Str "though:"] ,CodeBlock ("",[],[]) "
\n foo\n
" ,Para [Str "As",Space,Str "should",Space,Str "this:"] ,CodeBlock ("",[],[]) "
foo
" ,Para [Str "Now,",Space,Str "nested:"] ,Div ("",[],[]) [Div ("",[],[]) [Div ("",[],[]) [Plain [Str "foo"]]]] ,Para [Str "This",Space,Str "should",Space,Str "just",Space,Str "be",Space,Str "an",Space,Str "HTML",Space,Str "comment:"] ,RawBlock (Format "html") "\n" ,Para [Str "Multiline:"] ,RawBlock (Format "html") "\n\n\n" ,Para [Str "Code",Space,Str "block:"] ,CodeBlock ("",[],[]) "" ,Para [Str "Just",Space,Str "plain",Space,Str "comment,",Space,Str "with",Space,Str "trailing",Space,Str "spaces",Space,Str "on",Space,Str "the",Space,Str "line:"] ,RawBlock (Format "html") " \n" ,Para [Str "Code:"] ,CodeBlock ("",[],[]) "
" ,Para [Str "Hr\8217s:"] ,RawBlock (Format "html") "
\n\n
\n\n
\n\n
\n\n
\n\n
\n\n
\n\n
\n\n
\n" ,HorizontalRule ,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"] ,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str "."] ,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str "."] ,Para [Str "An",Space,Emph [Link [Str "emphasized",Space,Str "link"] ("/url","")],Str "."] ,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]] ,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."] ,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]] ,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."] ,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "",Str "."] ,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "strikeout"],Str "."]] ,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Emph [Str "hello"]],Space,Str "a",Superscript [Str "hello\160there"],Str "."] ,Para [Str "Subscripts:",Space,Str "H",Subscript [Str "2"],Str "O,",Space,Str "H",Subscript [Str "23"],Str "O,",Space,Str "H",Subscript [Str "many\160of\160them"],Str "O."] ,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts,",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",Space,Str "spaces:",Space,Str "a^b",Space,Str "c^d,",Space,Str "a~b",Space,Str "c~d."] ,HorizontalRule ,Header 1 ("smart-quotes-ellipses-dashes",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"] ,Para [Quoted DoubleQuote [Str "Hello,"],Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",Space,Str "name."]] ,Para [Quoted SingleQuote [Str "A"],Str ",",Space,Quoted SingleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted SingleQuote [Str "C"],Space,Str "are",Space,Str "letters."] ,Para [Quoted SingleQuote [Str "Oak,"],Space,Quoted SingleQuote [Str "elm,"],Space,Str "and",Space,Quoted SingleQuote [Str "beech"],Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Quoted SingleQuote [Str "pine."]] ,Para [Quoted SingleQuote [Str "He",Space,Str "said,",Space,Quoted DoubleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70\8217s?"] ,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Quoted SingleQuote [Code ("",[],[]) "code"],Space,Str "and",Space,Str "a",Space,Quoted DoubleQuote [Link [Str "quoted",Space,Str "link"] ("http://example.com/?foo=1&bar=2","")],Str "."] ,Para [Str "Some",Space,Str "dashes:",Space,Str "one\8212two",Space,Str "\8212",Space,Str "three\8212four",Space,Str "\8212",Space,Str "five."] ,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5\8211\&7,",Space,Str "255\8211\&66,",Space,Str "1987\8211\&1999."] ,Para [Str "Ellipses\8230and\8230and\8230."] ,HorizontalRule ,Header 1 ("latex",[],[]) [Str "LaTeX"] ,BulletList [[Plain [RawInline (Format "tex") "\\cite[22-23]{smith.1899}"]] ,[Plain [Math InlineMath "2+2=4"]] ,[Plain [Math InlineMath "x \\in y"]] ,[Plain [Math InlineMath "\\alpha \\wedge \\omega"]] ,[Plain [Math InlineMath "223"]] ,[Plain [Math InlineMath "p",Str "-Tree"]] ,[Plain [Str "Here\8217s",Space,Str "some",Space,Str "display",Space,Str "math:",Space,Math DisplayMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]] ,[Plain [Str "Here\8217s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math InlineMath "\\alpha + \\omega \\times x^2",Str "."]]] ,Para [Str "These",Space,Str "shouldn\8217t",Space,Str "be",Space,Str "math:"] ,BulletList [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]] ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized.)"]] ,[Plain [Str "Shoes",Space,Str "($20)",Space,Str "and",Space,Str "socks",Space,Str "($5)."]] ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$."]]] ,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"] ,RawBlock (Format "latex") "\\begin{tabular}{|l|l|}\\hline\nAnimal & Number \\\\ \\hline\nDog & 2 \\\\\nCat & 1 \\\\ \\hline\n\\end{tabular}" ,HorizontalRule ,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"] ,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"] ,BulletList [[Plain [Str "I",Space,Str "hat:",Space,Str "\206"]] ,[Plain [Str "o",Space,Str "umlaut:",Space,Str "\246"]] ,[Plain [Str "section:",Space,Str "\167"]] ,[Plain [Str "set",Space,Str "membership:",Space,Str "\8712"]] ,[Plain [Str "copyright:",Space,Str "\169"]]] ,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."] ,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."] ,Para [Str "This",Space,Str "&",Space,Str "that."] ,Para [Str "4",Space,Str "<",Space,Str "5."] ,Para [Str "6",Space,Str ">",Space,Str "5."] ,Para [Str "Backslash:",Space,Str "\\"] ,Para [Str "Backtick:",Space,Str "`"] ,Para [Str "Asterisk:",Space,Str "*"] ,Para [Str "Underscore:",Space,Str "_"] ,Para [Str "Left",Space,Str "brace:",Space,Str "{"] ,Para [Str "Right",Space,Str "brace:",Space,Str "}"] ,Para [Str "Left",Space,Str "bracket:",Space,Str "["] ,Para [Str "Right",Space,Str "bracket:",Space,Str "]"] ,Para [Str "Left",Space,Str "paren:",Space,Str "("] ,Para [Str "Right",Space,Str "paren:",Space,Str ")"] ,Para [Str "Greater-than:",Space,Str ">"] ,Para [Str "Hash:",Space,Str "#"] ,Para [Str "Period:",Space,Str "."] ,Para [Str "Bang:",Space,Str "!"] ,Para [Str "Plus:",Space,Str "+"] ,Para [Str "Minus:",Space,Str "-"] ,HorizontalRule ,Header 1 ("links",[],[]) [Str "Links"] ,Header 2 ("explicit",[],[]) [Str "Explicit"] ,Para [Str "Just",Space,Str "a",Space,Link [Str "URL"] ("/url/",""),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title"),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by two spaces"),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")] ,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with single quotes")] ,Para [Link [Str "with_underscore"] ("/url/with_underscore","")] ,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")] ,Para [Link [Str "Empty"] ("",""),Str "."] ,Header 2 ("reference",[],[]) [Str "Reference"] ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."] ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."] ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."] ,Para [Str "With",Space,Link [Str "embedded",Space,Str "[brackets]"] ("/url/",""),Str "."] ,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."] ,Para [Str "Indented",Space,Link [Str "once"] ("/url",""),Str "."] ,Para [Str "Indented",Space,Link [Str "twice"] ("/url",""),Str "."] ,Para [Str "Indented",Space,Link [Str "thrice"] ("/url",""),Str "."] ,Para [Str "This",Space,Str "should",Space,Str "[not][]",Space,Str "be",Space,Str "a",Space,Str "link."] ,CodeBlock ("",[],[]) "[not]: /url" ,Para [Str "Foo",Space,Link [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."] ,Para [Str "Foo",Space,Link [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."] ,Header 2 ("with-ampersands",[],[]) [Str "With",Space,Str "ampersands"] ,Para [Str "Here\8217s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."] ,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] ("http://att.com/","AT&T"),Str "."] ,Para [Str "Here\8217s",Space,Str "an",Space,Link [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."] ,Para [Str "Here\8217s",Space,Str "an",Space,Link [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."] ,Header 2 ("autolinks",[],[]) [Str "Autolinks"] ,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")] ,BulletList [[Plain [Str "In",Space,Str "a",Space,Str "list?"]] ,[Plain [Link [Str "http://example.com/"] ("http://example.com/","")]] ,[Plain [Str "It",Space,Str "should."]]] ,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")] ,BlockQuote [Para [Str "Blockquoted:",Space,Link [Str "http://example.com/"] ("http://example.com/","")]] ,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",Space,Code ("",[],[]) ""] ,CodeBlock ("",[],[]) "or here: " ,HorizontalRule ,Header 1 ("images",[],[]) [Str "Images"] ,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"] ,Para [Image [Str "lalune"] ("lalune.jpg","fig:Voyage dans la Lune")] ,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon."] ,HorizontalRule ,Header 1 ("footnotes",[],[]) [Str "Footnotes"] ,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference.",Space,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document."]],Space,Str "and",Space,Str "another.",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "list",Space,Str "items)."],CodeBlock ("",[],[]) " { }",Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line,",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",Space,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space.[^my",Space,Str "note]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note.",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type.",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",Space,Link [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",Space,Str "verbatim",Space,Str "characters,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[bracketed",Space,Str "text]."]]] ,BlockQuote [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes.",Note [Para [Str "In",Space,Str "quote."]]]] ,OrderedList (1,Decimal,Period) [[Plain [Str "And",Space,Str "in",Space,Str "list",Space,Str "items.",Note [Para [Str "In",Space,Str "list."]]]]] ,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented."]] pandoc-1.12.2.1/tests/writer.opendocument000644 000765 000024 00000352776 12251233603 020241 0ustar00jgmstaff000000 000000 Pandoc Test Suite John MacFarlane Anonymous July 17, 2006 This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. Headers Level 2 with an embedded link Level 3 with emphasis Level 4 Level 5 Level 1 Level 2 with emphasis Level 3 with no blank line Level 2 with no blank line Paragraphs Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. * criminey. There should be a hard line breakhere. Block Quotes E-mail style: This is a block quote. It is pretty short. Code in a block quote: sub status { print "working"; } A list: item one item two Nested block quotes: nested nested This should not be a block quote: 2 > 1. And a following paragraph. Code Blocks Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ Lists 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: First Second Third and: One Two Three Loose using tabs: First Second Third and using spaces: One Two Three Multiple paragraphs: Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog’s back. Item 2. Item 3. Nested Tab Tab Tab Here’s another: First Second: Fee Fie Foe Third Same thing but with paragraphs: First Second: Fee Fie Foe Third Tabs and spaces this is a list item indented with tabs this is a list item indented with spaces this is an example list item indented with tabs this is an example list item indented with spaces Fancy list markers begins with 2 and now 3 with a continuation sublist with roman numerals, starting with 4 more items a subsublist a subsublist Nesting: Upper Alpha Upper Roman. Decimal start with 6 Lower alpha with paren Autonumbering: Autonumber. More. Nested. Should not be a list item: M.A. 2007 B. Williams Definition Lists Tight using spaces: apple red fruit orange orange fruit banana yellow fruit Tight using tabs: apple red fruit orange orange fruit banana yellow fruit Loose: apple red fruit orange orange fruit banana yellow fruit Multiple blocks with italics: apple red fruitcontains seeds, crisp, pleasant to taste orange orange fruit{ orange code block }orange block quote Multiple definitions, tight: apple red fruit computer orange orange fruit bank Multiple definitions, loose: apple red fruit computer orange orange fruit bank Blank line after term, indented marker, alternate markers: apple red fruit computer orange orange fruit sublist sublist HTML Blocks Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table: This is emphasized And this is strong Here’s a simple block: foo This should be a code block, though: <div> foo </div> As should this: <div>foo</div> Now, nested: foo This should just be an HTML comment: Multiline: Code block: <!-- Comment --> Just plain comment, with trailing spaces on the line: Code: <hr /> Hr’s: Inline Markup This is emphasized, and so is this. This is strong, and so is this. An emphasized link. This is strong and em. So is this word. This is strong and em. So is this word. This is code: >, $, \, \$, <html>. This is strikeout. Superscripts: abcd ahello ahello there. Subscripts: H2O, H23O, Hmany of themO. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. Smart quotes, ellipses, dashes “Hello,” said the spider. “‘Shelob’ is my name.” ‘A’, ‘B’, and ‘C’ are letters. ‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ ‘He said, “I want to go.”’ Were you alive in the 70’s? Here is some quoted ‘code’ and a “quoted link”. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. LaTeX 2 + 2 = 4 x ∈ y α ∧ ω 223 p-Tree Here’s some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ Here’s one that has a line break in it: α + ω × x2. These shouldn’t be math: To get the famous equation, write $e = mc^2$. $22,000 is a lot of money. So is $34,000. (It worked if “lot” is emphasized.) Shoes ($20) and socks ($5). Escaped $: $73 this should be emphasized 23$. Here’s a LaTeX table: Special Characters Here is some unicode: I hat: Î o umlaut: ö section: § set membership: ∈ copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - Links Explicit Just a URL. URL and title. URL and title. URL and title. URL and title URL and title with_underscore Email link Empty. Reference Foo bar. Foo bar. Foo bar. With embedded [brackets]. b by itself should be a link. Indented once. Indented twice. Indented thrice. This should [not][] be a link. [not]: /url Foo bar. Foo biz. With ampersands Here’s a link with an ampersand in the URL. Here’s a link with an amersand in the link text: AT&T. Here’s an inline link. Here’s an inline link in pointy braces. Autolinks With an ampersand: http://example.com/?foo=1&bar=2 In a list? http://example.com/ It should. An e-mail address: nobody@nowhere.net Blockquoted: http://example.com/ Auto-links should not occur here: <http://example.com/> or here: <http://example.com/> Images From “Voyage dans la Lune” by Georges Melies (1902): Here is a movie icon. Footnotes Here is a footnote reference,1Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. and another.2Here’s the long note. This one contains multiple blocks.Subsequent blocks are indented to show that they belong to the footnote (as with list items).{ <code> }If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. This should not be a footnote reference, because it contains a space.[^my note] Here is an inline note.3This is easier to type. Inline notes may contain links and ] verbatim characters, as well as [bracketed text]. Notes can go in quotes.4In quote. And in list items.5In list. This paragraph should not be part of the note, as it is not indented. pandoc-1.12.2.1/tests/writer.opml000644 000765 000024 00000032644 12251233603 016475 0ustar00jgmstaff000000 000000 Pandoc Test Suite Mon, 17 Jul 2006 00:00:00 UTC John MacFarlane; Anonymous pandoc-1.12.2.1/tests/writer.org000644 000765 000024 00000024252 12251233603 016311 0ustar00jgmstaff000000 000000 #+TITLE: Pandoc Test Suite #+AUTHOR: John MacFarlane; Anonymous #+DATE: July 17, 2006 This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. -------------- * Headers ** Level 2 with an [[/url][embedded link]] *** Level 3 with /emphasis/ **** Level 4 ***** Level 5 * Level 1 ** Level 2 with /emphasis/ *** Level 3 with no blank line ** Level 2 with no blank line -------------- * Paragraphs Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. * criminey. There should be a hard line break here. -------------- * Block Quotes E-mail style: #+BEGIN_QUOTE This is a block quote. It is pretty short. #+END_QUOTE #+BEGIN_QUOTE Code in a block quote: #+BEGIN_EXAMPLE sub status { print "working"; } #+END_EXAMPLE A list: 1. item one 2. item two Nested block quotes: #+BEGIN_QUOTE nested #+END_QUOTE #+BEGIN_QUOTE nested #+END_QUOTE #+END_QUOTE This should not be a block quote: 2 > 1. And a following paragraph. -------------- * Code Blocks Code: #+BEGIN_EXAMPLE ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab #+END_EXAMPLE And: #+BEGIN_EXAMPLE this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ #+END_EXAMPLE -------------- * Lists ** 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 1. 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 ** Tabs and spaces - this is a list item indented with tabs - this is a list item indented with spaces - this is an example list item indented with tabs - this is an example list item indented with spaces ** Fancy list markers 2) begins with 2 3) and now 3 with a continuation 4. sublist with roman numerals, starting with 4 5. more items 1) a subsublist 2) a subsublist Nesting: 1. Upper Alpha 1. Upper Roman. 6) Decimal start with 6 3) Lower alpha with paren Autonumbering: 1. Autonumber. 2. More. 1. Nested. Should not be a list item: M.A. 2007 B. Williams -------------- * Definition Lists Tight using spaces: - apple :: red fruit - orange :: orange fruit - banana :: yellow fruit Tight using tabs: - apple :: red fruit - orange :: orange fruit - banana :: yellow fruit Loose: - apple :: red fruit - orange :: orange fruit - banana :: yellow fruit Multiple blocks with italics: - /apple/ :: red fruit contains seeds, crisp, pleasant to taste - /orange/ :: orange fruit #+BEGIN_EXAMPLE { orange code block } #+END_EXAMPLE #+BEGIN_QUOTE orange block quote #+END_QUOTE Multiple definitions, tight: - apple :: red fruit computer - orange :: orange fruit bank Multiple definitions, loose: - apple :: red fruit computer - orange :: orange fruit bank Blank line after term, indented marker, alternate markers: - apple :: red fruit computer - orange :: orange fruit 1. sublist 2. sublist * HTML Blocks Simple block on one line: #+BEGIN_HTML
#+END_HTML foo #+BEGIN_HTML
#+END_HTML And nested without indentation: #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML foo #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML bar #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML Interpreted markdown in a table: #+BEGIN_HTML
#+END_HTML This is /emphasized/ #+BEGIN_HTML #+END_HTML And this is *strong* #+BEGIN_HTML
#+END_HTML Here's a simple block: #+BEGIN_HTML
#+END_HTML foo #+BEGIN_HTML
#+END_HTML This should be a code block, though: #+BEGIN_EXAMPLE
foo
#+END_EXAMPLE As should this: #+BEGIN_EXAMPLE
foo
#+END_EXAMPLE Now, nested: #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML foo #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML #+BEGIN_HTML
#+END_HTML This should just be an HTML comment: #+BEGIN_HTML #+END_HTML Multiline: #+BEGIN_HTML #+END_HTML Code block: #+BEGIN_EXAMPLE #+END_EXAMPLE Just plain comment, with trailing spaces on the line: #+BEGIN_HTML #+END_HTML Code: #+BEGIN_EXAMPLE
#+END_EXAMPLE Hr's: #+BEGIN_HTML








#+END_HTML -------------- * Inline Markup This is /emphasized/, and so /is this/. This is *strong*, and so *is this*. An /[[/url][emphasized link]]/. */This is strong and em./* So is */this/* word. */This is strong and em./* So is */this/* word. This is code: =>=, =$=, =\=, =\$=, ==. +This is /strikeout/.+ Superscripts: a^{bc}d a^{/hello/} a^{hello there}. Subscripts: H_{2}O, H_{23}O, H_{many of them}O. These should not be superscripts or subscripts, because of the unescaped spaces: a\^b c\^d, a~b c~d. -------------- * Smart quotes, ellipses, dashes "Hello," said the spider. "'Shelob' is my name." 'A', 'B', and 'C' are letters. 'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.' 'He said, "I want to go."' Were you alive in the 70's? Here is some quoted '=code=' and a "[[http://example.com/?foo=1&bar=2][quoted link]]". Some dashes: one---two --- three---four --- five. Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses...and...and.... -------------- * LaTeX - \cite[22-23]{smith.1899} - $2+2=4$ - $x \in y$ - $\alpha \wedge \omega$ - $223$ - $p$-Tree - Here's some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ - Here's one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn't be math: - To get the famous equation, write =$e = mc^2$=. - $22,000 is a /lot/ of money. So is $34,000. (It worked if "lot" is emphasized.) - Shoes ($20) and socks ($5). - Escaped =$=: $73 /this should be emphasized/ 23$. Here's a LaTeX table: \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} -------------- * Special Characters Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: \_ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - -------------- * Links ** Explicit Just a [[/url/][URL]]. [[/url/][URL and title]]. [[/url/][URL and title]]. [[/url/][URL and title]]. [[/url/][URL and title]] [[/url/][URL and title]] [[/url/with_underscore][with\_underscore]] [[mailto:nobody@nowhere.net][Email link]] [[][Empty]]. ** Reference Foo [[/url/][bar]]. Foo [[/url/][bar]]. Foo [[/url/][bar]]. With [[/url/][embedded [brackets]]]. [[/url/][b]] by itself should be a link. Indented [[/url][once]]. Indented [[/url][twice]]. Indented [[/url][thrice]]. This should [not][] be a link. #+BEGIN_EXAMPLE [not]: /url #+END_EXAMPLE Foo [[/url/][bar]]. Foo [[/url/][biz]]. ** With ampersands Here's a [[http://example.com/?foo=1&bar=2][link with an ampersand in the URL]]. Here's a link with an amersand in the link text: [[http://att.com/][AT&T]]. Here's an [[/script?foo=1&bar=2][inline link]]. Here's an [[/script?foo=1&bar=2][inline link in pointy braces]]. ** Autolinks With an ampersand: [[http://example.com/?foo=1&bar=2]] - In a list? - [[http://example.com/]] - It should. An e-mail address: [[mailto:nobody@nowhere.net][nobody@nowhere.net]] #+BEGIN_QUOTE Blockquoted: [[http://example.com/]] #+END_QUOTE Auto-links should not occur here: == #+BEGIN_EXAMPLE or here: #+END_EXAMPLE -------------- * Images From "Voyage dans la Lune" by Georges Melies (1902): #+CAPTION: lalune [[lalune.jpg]] Here is a movie [[movie.jpg]] icon. -------------- * Footnotes Here is a footnote reference, [1] and another. [2] This should /not/ be a footnote reference, because it contains a space.[\^my note] Here is an inline note. [3] #+BEGIN_QUOTE Notes can go in quotes. [4] #+END_QUOTE 1. And in list items. [5] This paragraph should not be part of the note, as it is not indented. [1] Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. [2] Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). #+BEGIN_EXAMPLE { } #+END_EXAMPLE If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. [3] This is /easier/ to type. Inline notes may contain [[http://google.com][links]] and =]= verbatim characters, as well as [bracketed text]. [4] In quote. [5] In list. pandoc-1.12.2.1/tests/writer.plain000644 000765 000024 00000020113 12251233603 016615 0ustar00jgmstaff000000 000000 Pandoc Test Suite John MacFarlane; Anonymous July 17, 2006 This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. * * * * * Headers ======= Level 2 with an embedded link ----------------------------- Level 3 with emphasis Level 4 Level 5 Level 1 ======= Level 2 with emphasis --------------------- Level 3 with no blank line Level 2 ------- with no blank line * * * * * Paragraphs ========== Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. * criminey. There should be a hard line break here. * * * * * Block Quotes ============ E-mail style: This is a block quote. It is pretty short. Code in a block quote: sub status { print "working"; } A list: 1. item one 2. item two Nested block quotes: nested nested This should not be a block quote: 2 > 1. And a following paragraph. * * * * * Code Blocks =========== Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ * * * * * Lists ===== 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 1. 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 Tabs and spaces --------------- - this is a list item indented with tabs - this is a list item indented with spaces - this is an example list item indented with tabs - this is an example list item indented with spaces Fancy list markers ------------------ (2) begins with 2 (3) and now 3 with a continuation iv. sublist with roman numerals, starting with 4 v. more items (A) a subsublist (B) a subsublist Nesting: A. Upper Alpha I. Upper Roman. (6) Decimal start with 6 c) Lower alpha with paren Autonumbering: 1. Autonumber. 2. More. 1. Nested. Should not be a list item: M.A. 2007 B. Williams * * * * * Definition Lists ================ Tight using spaces: apple red fruit orange orange fruit banana yellow fruit Tight using tabs: apple red fruit orange orange fruit banana yellow fruit Loose: apple red fruit orange orange fruit banana yellow fruit Multiple blocks with italics: apple red fruit contains seeds, crisp, pleasant to taste orange orange fruit { orange code block } orange block quote Multiple definitions, tight: apple red fruit computer orange orange fruit bank Multiple definitions, loose: apple red fruit computer orange orange fruit bank Blank line after term, indented marker, alternate markers: apple red fruit computer orange orange fruit 1. sublist 2. sublist HTML Blocks =========== Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table: This is emphasized And this is strong Here’s a simple block: foo This should be a code block, though:
foo
As should this:
foo
Now, nested: foo This should just be an HTML comment: Multiline: Code block: Just plain comment, with trailing spaces on the line: Code:
Hr’s: * * * * * Inline Markup ============= This is emphasized, and so is this. This is strong, and so is this. An emphasized link. This is strong and em. So is this word. This is strong and em. So is this word. This is code: >, $, \, \$, . This is strikeout. Superscripts: abcd ahello ahello there. Subscripts: H2O, H23O, Hmany of themO. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. * * * * * Smart quotes, ellipses, dashes ============================== “Hello,” said the spider. “‘Shelob’ is my name.” ‘A’, ‘B’, and ‘C’ are letters. ‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ ‘He said, “I want to go.”’ Were you alive in the 70’s? Here is some quoted ‘code’ and a “quoted link”. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. * * * * * LaTeX ===== - - 2+2=4 - x \in y - \alpha \wedge \omega - 223 - p-Tree - Here’s some display math: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h} - Here’s one that has a line break in it: \alpha + \omega \times x^2. These shouldn’t be math: - To get the famous equation, write $e = mc^2$. - $22,000 is a lot of money. So is $34,000. (It worked if “lot” is emphasized.) - Shoes ($20) and socks ($5). - Escaped $: $73 this should be emphasized 23$. Here’s a LaTeX table: * * * * * Special Characters ================== Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - * * * * * Links ===== Explicit -------- Just a URL. URL and title. URL and title. URL and title. URL and title URL and title with_underscore Email link Empty. Reference --------- Foo bar. Foo bar. Foo bar. With embedded [brackets]. b by itself should be a link. Indented once. Indented twice. Indented thrice. This should [not][] be a link. [not]: /url Foo bar. Foo biz. With ampersands --------------- Here’s a link with an ampersand in the URL. Here’s a link with an amersand in the link text: AT&T. Here’s an inline link. Here’s an inline link in pointy braces. Autolinks --------- With an ampersand: http://example.com/?foo=1&bar=2 - In a list? - http://example.com/ - It should. An e-mail address: nobody@nowhere.net Blockquoted: http://example.com/ Auto-links should not occur here: or here: * * * * * Images ====== From “Voyage dans la Lune” by Georges Melies (1902): [lalune] Here is a movie [movie] icon. * * * * * Footnotes ========= Here is a footnote reference,[^1] and another.[^2] This should not be a footnote reference, because it contains a space.[^my note] Here is an inline note.[^3] Notes can go in quotes.[^4] 1. And in list items.[^5] This paragraph should not be part of the note, as it is not indented. [^1]: Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. [^2]: Here’s the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). { } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. [^3]: This is easier to type. Inline notes may contain links and ] verbatim characters, as well as [bracketed text]. [^4]: In quote. [^5]: In list. pandoc-1.12.2.1/tests/writer.rst000644 000765 000024 00000024354 12251233603 016335 0ustar00jgmstaff000000 000000 ================= Pandoc Test Suite ================= :Author: John MacFarlane :Author: Anonymous :Date: July 17, 2006 .. role:: math(raw) :format: html latex .. This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. -------------- Headers ======= Level 2 with an `embedded link `__ ---------------------------------------- Level 3 with *emphasis* ~~~~~~~~~~~~~~~~~~~~~~~ Level 4 ^^^^^^^ Level 5 ''''''' Level 1 ======= Level 2 with *emphasis* ----------------------- Level 3 ~~~~~~~ with no blank line Level 2 ------- with no blank line -------------- Paragraphs ========== Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. \* criminey. | There should be a hard line break | here. -------------- Block Quotes ============ E-mail style: This is a block quote. It is pretty short. Code in a block quote: :: sub status { print "working"; } A list: 1. item one 2. item two Nested block quotes: nested nested This should not be a block quote: 2 > 1. And a following paragraph. -------------- Code Blocks =========== Code: :: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: :: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ -------------- Lists ===== 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 1. 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 Tabs and spaces --------------- - this is a list item indented with tabs - this is a list item indented with spaces - this is an example list item indented with tabs - this is an example list item indented with spaces Fancy list markers ------------------ (2) begins with 2 (3) and now 3 with a continuation iv. sublist with roman numerals, starting with 4 v. more items (A) a subsublist (B) a subsublist Nesting: A. Upper Alpha I. Upper Roman. (6) Decimal start with 6 c) Lower alpha with paren Autonumbering: #. Autonumber. #. More. #. Nested. Should not be a list item: M.A. 2007 B. Williams -------------- Definition Lists ================ Tight using spaces: apple red fruit orange orange fruit banana yellow fruit Tight using tabs: apple red fruit orange orange fruit banana yellow fruit Loose: apple red fruit orange orange fruit banana yellow fruit Multiple blocks with italics: *apple* red fruit contains seeds, crisp, pleasant to taste *orange* orange fruit :: { orange code block } orange block quote Multiple definitions, tight: apple red fruit computer orange orange fruit bank Multiple definitions, loose: apple red fruit computer orange orange fruit bank Blank line after term, indented marker, alternate markers: apple red fruit computer orange orange fruit 1. sublist 2. sublist HTML Blocks =========== Simple block on one line: .. raw:: html
foo .. raw:: html
And nested without indentation: .. raw:: html
.. raw:: html
.. raw:: html
foo .. raw:: html
.. raw:: html
.. raw:: html
bar .. raw:: html
.. raw:: html
Interpreted markdown in a table: .. raw:: html
This is *emphasized* .. raw:: html And this is **strong** .. raw:: html
Here’s a simple block: .. raw:: html
foo .. raw:: html
This should be a code block, though: ::
foo
As should this: ::
foo
Now, nested: .. raw:: html
.. raw:: html
.. raw:: html
foo .. raw:: html
.. raw:: html
.. raw:: html
This should just be an HTML comment: .. raw:: html Multiline: .. raw:: html Code block: :: Just plain comment, with trailing spaces on the line: .. raw:: html Code: ::
Hr’s: .. raw:: html








-------------- Inline Markup ============= This is *emphasized*, and so *is this*. This is **strong**, and so **is this**. An *`emphasized link `__*. ***This is strong and em.*** So is ***this*** word. ***This is strong and em.*** So is ***this*** word. This is code: ``>``, ``$``, ``\``, ``\$``, ````. [STRIKEOUT:This is *strikeout*.] Superscripts: a\ :sup:`bc`\ d a\ :sup:`*hello*` a\ :sup:`hello there`. Subscripts: H\ :sub:`2`\ O, H\ :sub:`23`\ O, H\ :sub:`many of them`\ O. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. -------------- Smart quotes, ellipses, dashes ============================== “Hello,” said the spider. “‘Shelob’ is my name.” ‘A’, ‘B’, and ‘C’ are letters. ‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ ‘He said, “I want to go.”’ Were you alive in the 70’s? Here is some quoted ‘``code``’ and a “`quoted link `__”. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. -------------- LaTeX ===== - - :math:`2+2=4` - :math:`x \in y` - :math:`\alpha \wedge \omega` - :math:`223` - :math:`p`-Tree - Here’s some display math: .. math:: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h} - Here’s one that has a line break in it: :math:`\alpha + \omega \times x^2`. These shouldn’t be math: - To get the famous equation, write ``$e = mc^2$``. - $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is emphasized.) - Shoes ($20) and socks ($5). - Escaped ``$``: $73 *this should be emphasized* 23$. Here’s a LaTeX table: .. raw:: latex \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} -------------- Special Characters ================== Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \\ Backtick: \` Asterisk: \* Underscore: \_ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - -------------- Links ===== Explicit -------- Just a `URL `__. `URL and title `__. `URL and title `__. `URL and title `__. `URL and title `__ `URL and title `__ `with\_underscore `__ `Email link `__ `Empty <>`__. Reference --------- Foo `bar `__. Foo `bar `__. Foo `bar `__. With `embedded [brackets] `__. `b `__ by itself should be a link. Indented `once `__. Indented `twice `__. Indented `thrice `__. This should [not][] be a link. :: [not]: /url Foo `bar `__. Foo `biz `__. With ampersands --------------- Here’s a `link with an ampersand in the URL `__. Here’s a link with an amersand in the link text: `AT&T `__. Here’s an `inline link `__. Here’s an `inline link in pointy braces `__. Autolinks --------- With an ampersand: http://example.com/?foo=1&bar=2 - In a list? - http://example.com/ - It should. An e-mail address: nobody@nowhere.net Blockquoted: http://example.com/ Auto-links should not occur here: ```` :: or here: -------------- Images ====== From “Voyage dans la Lune” by Georges Melies (1902): .. figure:: lalune.jpg :alt: Voyage dans la Lune lalune Here is a movie |movie| icon. -------------- Footnotes ========= Here is a footnote reference, [1]_ and another. [2]_ This should *not* be a footnote reference, because it contains a space.[^my note] Here is an inline note. [3]_ Notes can go in quotes. [4]_ 1. And in list items. [5]_ This paragraph should not be part of the note, as it is not indented. .. [1] Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. .. [2] Here’s the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). :: { } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. .. [3] This is *easier* to type. Inline notes may contain `links `__ and ``]`` verbatim characters, as well as [bracketed text]. .. [4] In quote. .. [5] In list. .. |movie| image:: movie.jpg pandoc-1.12.2.1/tests/writer.rtf000644 000765 000024 00000165134 12251233603 016322 0ustar00jgmstaff000000 000000 {\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 Courier;}} {\colortbl;\red255\green0\blue0;\red0\green0\blue255;} \widowctrl\hyphauto {\pard \qc \f0 \sa180 \li0 \fi0 \b \fs36 Pandoc Test Suite\par} {\pard \qc \f0 \sa180 \li0 \fi0 John MacFarlane\par} {\pard \qc \f0 \sa180 \li0 \fi0 Anonymous\par} {\pard \qc \f0 \sa180 \li0 \fi0 July 17, 2006\par} {\pard \ql \f0 \sa180 \li0 \fi0 \par} {\pard \ql \f0 \sa180 \li0 \fi0 This is a set of tests for pandoc. Most of them are adapted from John Gruber\u8217's markdown test suite.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Headers\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Level 2 with an {\field{\*\fldinst{HYPERLINK "/url"}}{\fldrslt{\ul embedded link }}} \par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Level 3 with {\i emphasis}\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 Level 4\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs20 Level 5\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Level 1\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Level 2 with {\i emphasis}\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Level 3\par} {\pard \ql \f0 \sa180 \li0 \fi0 with no blank line\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Level 2\par} {\pard \ql \f0 \sa180 \li0 \fi0 with no blank line\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Paragraphs\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a regular paragraph.\par} {\pard \ql \f0 \sa180 \li0 \fi0 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.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's one with a bullet. * criminey.\par} {\pard \ql \f0 \sa180 \li0 \fi0 There should be a hard line break\line here.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Block Quotes\par} {\pard \ql \f0 \sa180 \li0 \fi0 E-mail style:\par} {\pard \ql \f0 \sa180 \li720 \fi0 This is a block quote. It is pretty short.\par} {\pard \ql \f0 \sa180 \li720 \fi0 Code in a block quote:\par} {\pard \ql \f0 \sa180 \li720 \fi0 \f1 sub status \{\line print "working";\line \}\par} {\pard \ql \f0 \sa180 \li720 \fi0 A list:\par} {\pard \ql \f0 \sa0 \li1080 \fi-360 1.\tx360\tab item one\par} {\pard \ql \f0 \sa0 \li1080 \fi-360 2.\tx360\tab item two\sa180\par} {\pard \ql \f0 \sa180 \li720 \fi0 Nested block quotes:\par} {\pard \ql \f0 \sa180 \li1440 \fi0 nested\par} {\pard \ql \f0 \sa180 \li1440 \fi0 nested\par} {\pard \ql \f0 \sa180 \li0 \fi0 This should not be a block quote: 2 > 1.\par} {\pard \ql \f0 \sa180 \li0 \fi0 And a following paragraph.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Code Blocks\par} {\pard \ql \f0 \sa180 \li0 \fi0 Code:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 ---- (should be four hyphens)\line \line sub status \{\line print "working";\line \}\line \line this code block is indented by one tab\par} {\pard \ql \f0 \sa180 \li0 \fi0 And:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 this code block is indented by two tabs\line \line These should not be escaped: \\$ \\\\ \\> \\[ \\\{\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Lists\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Unordered\par} {\pard \ql \f0 \sa180 \li0 \fi0 Asterisks tight:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab asterisk 1\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab asterisk 2\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab asterisk 3\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Asterisks loose:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab asterisk 1\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab asterisk 2\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab asterisk 3\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Pluses tight:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Plus 1\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Plus 2\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Plus 3\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Pluses loose:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Plus 1\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Plus 2\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Plus 3\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Minuses tight:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Minus 1\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Minus 2\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Minus 3\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Minuses loose:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Minus 1\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Minus 2\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab Minus 3\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Ordered\par} {\pard \ql \f0 \sa180 \li0 \fi0 Tight:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 1.\tx360\tab First\par} {\pard \ql \f0 \sa0 \li360 \fi-360 2.\tx360\tab Second\par} {\pard \ql \f0 \sa0 \li360 \fi-360 3.\tx360\tab Third\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 and:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 1.\tx360\tab One\par} {\pard \ql \f0 \sa0 \li360 \fi-360 2.\tx360\tab Two\par} {\pard \ql \f0 \sa0 \li360 \fi-360 3.\tx360\tab Three\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Loose using tabs:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 1.\tx360\tab First\par} {\pard \ql \f0 \sa180 \li360 \fi-360 2.\tx360\tab Second\par} {\pard \ql \f0 \sa180 \li360 \fi-360 3.\tx360\tab Third\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 and using spaces:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 1.\tx360\tab One\par} {\pard \ql \f0 \sa180 \li360 \fi-360 2.\tx360\tab Two\par} {\pard \ql \f0 \sa180 \li360 \fi-360 3.\tx360\tab Three\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiple paragraphs:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 1.\tx360\tab Item 1, graf one.\par} {\pard \ql \f0 \sa180 \li360 \fi0 Item 1. graf two. The quick brown fox jumped over the lazy dog\u8217's back.\par} {\pard \ql \f0 \sa180 \li360 \fi-360 2.\tx360\tab Item 2.\par} {\pard \ql \f0 \sa180 \li360 \fi-360 3.\tx360\tab Item 3.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Nested\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Tab\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Tab\par} {\pard \ql \f0 \sa0 \li1080 \fi-360 \bullet \tx360\tab Tab\sa180\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's another:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 1.\tx360\tab First\par} {\pard \ql \f0 \sa0 \li360 \fi-360 2.\tx360\tab Second:\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Fee\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Fie\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Foe\sa180\par} {\pard \ql \f0 \sa0 \li360 \fi-360 3.\tx360\tab Third\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Same thing but with paragraphs:\par} {\pard \ql \f0 \sa180 \li360 \fi-360 1.\tx360\tab First\par} {\pard \ql \f0 \sa180 \li360 \fi-360 2.\tx360\tab Second:\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Fee\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Fie\par} {\pard \ql \f0 \sa0 \li720 \fi-360 \endash \tx360\tab Foe\sa180\par} {\pard \ql \f0 \sa180 \li360 \fi-360 3.\tx360\tab Third\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Tabs and spaces\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab this is a list item indented with tabs\par} {\pard \ql \f0 \sa180 \li360 \fi-360 \bullet \tx360\tab this is a list item indented with spaces\par} {\pard \ql \f0 \sa180 \li720 \fi-360 \endash \tx360\tab this is an example list item indented with tabs\par} {\pard \ql \f0 \sa180 \li720 \fi-360 \endash \tx360\tab this is an example list item indented with spaces\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Fancy list markers\par} {\pard \ql \f0 \sa0 \li360 \fi-360 (2)\tx360\tab begins with 2\par} {\pard \ql \f0 \sa180 \li360 \fi-360 (3)\tx360\tab and now 3\par} {\pard \ql \f0 \sa180 \li360 \fi0 with a continuation\par} {\pard \ql \f0 \sa0 \li720 \fi-360 iv.\tx360\tab sublist with roman numerals, starting with 4\par} {\pard \ql \f0 \sa0 \li720 \fi-360 v.\tx360\tab more items\par} {\pard \ql \f0 \sa0 \li1080 \fi-360 (A)\tx360\tab a subsublist\par} {\pard \ql \f0 \sa0 \li1080 \fi-360 (B)\tx360\tab a subsublist\sa180\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Nesting:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 A.\tx360\tab Upper Alpha\par} {\pard \ql \f0 \sa0 \li720 \fi-360 I.\tx360\tab Upper Roman.\par} {\pard \ql \f0 \sa0 \li1080 \fi-360 (6)\tx360\tab Decimal start with 6\par} {\pard \ql \f0 \sa0 \li1440 \fi-360 c)\tx360\tab Lower alpha with paren\sa180\sa180\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Autonumbering:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 1.\tx360\tab Autonumber.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 2.\tx360\tab More.\par} {\pard \ql \f0 \sa0 \li720 \fi-360 a.\tx360\tab Nested.\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Should not be a list item:\par} {\pard \ql \f0 \sa180 \li0 \fi0 M.A.\u160?2007\par} {\pard \ql \f0 \sa180 \li0 \fi0 B. Williams\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Definition Lists\par} {\pard \ql \f0 \sa180 \li0 \fi0 Tight using spaces:\par} {\pard \ql \f0 \sa0 \li0 \fi0 apple\par} {\pard \ql \f0 \sa0 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa0 \li0 \fi0 orange\par} {\pard \ql \f0 \sa0 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa0 \li0 \fi0 banana\par} {\pard \ql \f0 \sa0 \li360 \fi0 yellow fruit\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Tight using tabs:\par} {\pard \ql \f0 \sa0 \li0 \fi0 apple\par} {\pard \ql \f0 \sa0 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa0 \li0 \fi0 orange\par} {\pard \ql \f0 \sa0 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa0 \li0 \fi0 banana\par} {\pard \ql \f0 \sa0 \li360 \fi0 yellow fruit\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Loose:\par} {\pard \ql \f0 \sa0 \li0 \fi0 apple\par} {\pard \ql \f0 \sa180 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa0 \li0 \fi0 orange\par} {\pard \ql \f0 \sa180 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa0 \li0 \fi0 banana\par} {\pard \ql \f0 \sa180 \li360 \fi0 yellow fruit\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiple blocks with italics:\par} {\pard \ql \f0 \sa0 \li0 \fi0 {\i apple}\par} {\pard \ql \f0 \sa180 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa180 \li360 \fi0 contains seeds, crisp, pleasant to taste\par} {\pard \ql \f0 \sa0 \li0 \fi0 {\i orange}\par} {\pard \ql \f0 \sa180 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa180 \li360 \fi0 \f1 \{ orange code block \}\par} {\pard \ql \f0 \sa180 \li1080 \fi0 orange block quote\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiple definitions, tight:\par} {\pard \ql \f0 \sa0 \li0 \fi0 apple\par} {\pard \ql \f0 \sa0 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa0 \li360 \fi0 computer\par} {\pard \ql \f0 \sa0 \li0 \fi0 orange\par} {\pard \ql \f0 \sa0 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa0 \li360 \fi0 bank\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiple definitions, loose:\par} {\pard \ql \f0 \sa0 \li0 \fi0 apple\par} {\pard \ql \f0 \sa180 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa180 \li360 \fi0 computer\par} {\pard \ql \f0 \sa0 \li0 \fi0 orange\par} {\pard \ql \f0 \sa180 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa180 \li360 \fi0 bank\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Blank line after term, indented marker, alternate markers:\par} {\pard \ql \f0 \sa0 \li0 \fi0 apple\par} {\pard \ql \f0 \sa180 \li360 \fi0 red fruit\par} {\pard \ql \f0 \sa180 \li360 \fi0 computer\par} {\pard \ql \f0 \sa0 \li0 \fi0 orange\par} {\pard \ql \f0 \sa180 \li360 \fi0 orange fruit\par} {\pard \ql \f0 \sa0 \li720 \fi-360 1.\tx360\tab sublist\par} {\pard \ql \f0 \sa0 \li720 \fi-360 2.\tx360\tab sublist\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 HTML Blocks\par} {\pard \ql \f0 \sa180 \li0 \fi0 Simple block on one line:\par} {\pard \ql \f0 \sa0 \li0 \fi0 foo\par} {\pard \ql \f0 \sa180 \li0 \fi0 And nested without indentation:\par} {\pard \ql \f0 \sa0 \li0 \fi0 foo\par} {\pard \ql \f0 \sa0 \li0 \fi0 bar\par} {\pard \ql \f0 \sa180 \li0 \fi0 Interpreted markdown in a table:\par} {\pard \ql \f0 \sa0 \li0 \fi0 This is {\i emphasized}\par} {\pard \ql \f0 \sa0 \li0 \fi0 And this is {\b strong}\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a simple block:\par} {\pard \ql \f0 \sa0 \li0 \fi0 foo\par} {\pard \ql \f0 \sa180 \li0 \fi0 This should be a code block, though:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1
\line foo\line
\par} {\pard \ql \f0 \sa180 \li0 \fi0 As should this:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1
foo
\par} {\pard \ql \f0 \sa180 \li0 \fi0 Now, nested:\par} {\pard \ql \f0 \sa0 \li0 \fi0 foo\par} {\pard \ql \f0 \sa180 \li0 \fi0 This should just be an HTML comment:\par} {\pard \ql \f0 \sa180 \li0 \fi0 Multiline:\par} {\pard \ql \f0 \sa180 \li0 \fi0 Code block:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 \par} {\pard \ql \f0 \sa180 \li0 \fi0 Just plain comment, with trailing spaces on the line:\par} {\pard \ql \f0 \sa180 \li0 \fi0 Code:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1
\par} {\pard \ql \f0 \sa180 \li0 \fi0 Hr\u8217's:\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Inline Markup\par} {\pard \ql \f0 \sa180 \li0 \fi0 This is {\i emphasized}, and so {\i is this}.\par} {\pard \ql \f0 \sa180 \li0 \fi0 This is {\b strong}, and so {\b is this}.\par} {\pard \ql \f0 \sa180 \li0 \fi0 An {\i {\field{\*\fldinst{HYPERLINK "/url"}}{\fldrslt{\ul emphasized link }}} }.\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\b {\i This is strong and em.}}\par} {\pard \ql \f0 \sa180 \li0 \fi0 So is {\b {\i this}} word.\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\b {\i This is strong and em.}}\par} {\pard \ql \f0 \sa180 \li0 \fi0 So is {\b {\i this}} word.\par} {\pard \ql \f0 \sa180 \li0 \fi0 This is code: {\f1 >}, {\f1 $}, {\f1 \\}, {\f1 \\$}, {\f1 }.\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\strike This is {\i strikeout}.}\par} {\pard \ql \f0 \sa180 \li0 \fi0 Superscripts: a{\super bc}d a{\super {\i hello}} a{\super hello\u160?there}.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Subscripts: H{\sub 2}O, H{\sub 23}O, H{\sub many\u160?of\u160?them}O.\par} {\pard \ql \f0 \sa180 \li0 \fi0 These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Smart quotes, ellipses, dashes\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8220"Hello,\u8221" said the spider. \u8220"\u8216'Shelob\u8217' is my name.\u8221"\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8216'A\u8217', \u8216'B\u8217', and \u8216'C\u8217' are letters.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8216'Oak,\u8217' \u8216'elm,\u8217' and \u8216'beech\u8217' are names of trees. So is \u8216'pine.\u8217'\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8216'He said, \u8220"I want to go.\u8221"\u8217' Were you alive in the 70\u8217's?\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is some quoted \u8216'{\f1 code}\u8217' and a \u8220"{\field{\*\fldinst{HYPERLINK "http://example.com/?foo=1&bar=2"}}{\fldrslt{\ul quoted link }}} \u8221".\par} {\pard \ql \f0 \sa180 \li0 \fi0 Some dashes: one\u8212-two \u8212- three\u8212-four \u8212- five.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Dashes between numbers: 5\u8211-7, 255\u8211-66, 1987\u8211-1999.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Ellipses\u8230?and\u8230?and\u8230?.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 LaTeX\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 2\u8197?+\u8197?2\u8196?=\u8196?4\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i x}\u8196?\u8712?\u8196?{\i y}\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\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 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} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab $22,000 is a {\i lot} of money. So is $34,000. (It worked if \u8220"lot\u8221" is emphasized.)\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Shoes ($20) and socks ($5).\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Escaped {\f1 $}: $73 {\i this should be emphasized} 23$.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a LaTeX table:\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Special Characters\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is some unicode:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab I hat: \u206?\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab o umlaut: \u246?\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab section: \u167?\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab set membership: \u8712?\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab copyright: \u169?\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 AT&T has an ampersand in their name.\par} {\pard \ql \f0 \sa180 \li0 \fi0 AT&T is another way to write it.\par} {\pard \ql \f0 \sa180 \li0 \fi0 This & that.\par} {\pard \ql \f0 \sa180 \li0 \fi0 4 < 5.\par} {\pard \ql \f0 \sa180 \li0 \fi0 6 > 5.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Backslash: \\\par} {\pard \ql \f0 \sa180 \li0 \fi0 Backtick: `\par} {\pard \ql \f0 \sa180 \li0 \fi0 Asterisk: *\par} {\pard \ql \f0 \sa180 \li0 \fi0 Underscore: _\par} {\pard \ql \f0 \sa180 \li0 \fi0 Left brace: \{\par} {\pard \ql \f0 \sa180 \li0 \fi0 Right brace: \}\par} {\pard \ql \f0 \sa180 \li0 \fi0 Left bracket: [\par} {\pard \ql \f0 \sa180 \li0 \fi0 Right bracket: ]\par} {\pard \ql \f0 \sa180 \li0 \fi0 Left paren: (\par} {\pard \ql \f0 \sa180 \li0 \fi0 Right paren: )\par} {\pard \ql \f0 \sa180 \li0 \fi0 Greater-than: >\par} {\pard \ql \f0 \sa180 \li0 \fi0 Hash: #\par} {\pard \ql \f0 \sa180 \li0 \fi0 Period: .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Bang: !\par} {\pard \ql \f0 \sa180 \li0 \fi0 Plus: +\par} {\pard \ql \f0 \sa180 \li0 \fi0 Minus: -\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Links\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Explicit\par} {\pard \ql \f0 \sa180 \li0 \fi0 Just a {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul URL }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul URL and title }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul URL and title }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul URL and title }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul URL and title }}} \par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul URL and title }}} \par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/with_underscore"}}{\fldrslt{\ul with_underscore }}} \par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "mailto:nobody@nowhere.net"}}{\fldrslt{\ul Email link }}} \par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK ""}}{\fldrslt{\ul Empty }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Reference\par} {\pard \ql \f0 \sa180 \li0 \fi0 Foo {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul bar }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Foo {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul bar }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Foo {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul bar }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 With {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul embedded [brackets] }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul b }}} by itself should be a link.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Indented {\field{\*\fldinst{HYPERLINK "/url"}}{\fldrslt{\ul once }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Indented {\field{\*\fldinst{HYPERLINK "/url"}}{\fldrslt{\ul twice }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Indented {\field{\*\fldinst{HYPERLINK "/url"}}{\fldrslt{\ul thrice }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 This should [not][] be a link.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 [not]: /url\par} {\pard \ql \f0 \sa180 \li0 \fi0 Foo {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul bar }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Foo {\field{\*\fldinst{HYPERLINK "/url/"}}{\fldrslt{\ul biz }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 With ampersands\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a {\field{\*\fldinst{HYPERLINK "http://example.com/?foo=1&bar=2"}}{\fldrslt{\ul link with an ampersand in the URL }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a link with an amersand in the link text: {\field{\*\fldinst{HYPERLINK "http://att.com/"}}{\fldrslt{\ul AT&T }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's an {\field{\*\fldinst{HYPERLINK "/script?foo=1&bar=2"}}{\fldrslt{\ul inline link }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's an {\field{\*\fldinst{HYPERLINK "/script?foo=1&bar=2"}}{\fldrslt{\ul inline link in pointy braces }}} .\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 Autolinks\par} {\pard \ql \f0 \sa180 \li0 \fi0 With an ampersand: {\field{\*\fldinst{HYPERLINK "http://example.com/?foo=1&bar=2"}}{\fldrslt{\ul http://example.com/?foo=1&bar=2 }}} \par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab In a list?\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\field{\*\fldinst{HYPERLINK "http://example.com/"}}{\fldrslt{\ul http://example.com/ }}} \par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab It should.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 An e-mail address: {\field{\*\fldinst{HYPERLINK "mailto:nobody@nowhere.net"}}{\fldrslt{\ul nobody@nowhere.net }}} \par} {\pard \ql \f0 \sa180 \li720 \fi0 Blockquoted: {\field{\*\fldinst{HYPERLINK "http://example.com/"}}{\fldrslt{\ul http://example.com/ }}} \par} {\pard \ql \f0 \sa180 \li0 \fi0 Auto-links should not occur here: {\f1 }\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 or here: \par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Images\par} {\pard \ql \f0 \sa180 \li0 \fi0 From \u8220"Voyage dans la Lune\u8221" by Georges Melies (1902):\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\pict\jpegblip ffd8ffe000104a46494600010101007800780000ffdb00430006040506050406060506070706080a100a0a09090a140e0f0c1017141818171416161a1d251f1a1b231c1616202c20232627292a29191f2d302d283025282928ffdb0043010707070a080a130a0a13281a161a2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828ffc000110800fa00fa03011100021101031101ffc4001c0000000701010000000000000000000000010203040506070008ffc4003e100002010303020404040502050500030001020300041105122106311322415107617181143291a1234252b1c115f016336272d1082443e1f1265382ffc40017010101010100000000000000000000000000010204ffc4001b11010101010003010000000000000000000001110212213141ffda000c03010002110311003f00dadd18a10a704f6a95ccc57e37750782b0d8d9ea0cd32e7c5446e07e9f4ad723119a7b89e61e348f260719278aad613cbb640002938c76a182b264fc87bd13009c0c019c76e3d68a072e1cf6f4cd502d330c28269a61bb39c923923d4fad44c08dccb95cfd28b8280769ee08a263891e1808739e4f1d8d149392172cc714050dbb9fde8960ed8c60b79b1ed44103b05c331dbdb1dc5026ac1946d20ff8140aa631c773ec738a0346a003bf93e9cf02801895e7b9a01886796c923bd0090a06393c76a0142003ce3d86680d8dd9392303f5341ccc1b3cf7a2c812c37e4923d381429757013209fa511c18146c9247a0f6a007900c0c671c6280854e086c673eb45c27c038fd68aedff2fda836ef881f136f25d5e6b7d1262964aa02b03f98fbf153131935edcc97576f35c33349212cc4f39f7ab26186dfce5b200f73451f7600dcb8cf27e7400c0b291914046c9e0718fde81371b8e7273f4ef4007691919240e714097f31f376e7b5008caee27807b0f5a02c8e1b3c6d27d33cd0201d839523144d1a149ae084b78da47638211771fd050d582c3a0faab5119b6d12f8ab1c06788a0fd4e2ac356fd1fe08754ddccaba849696309e598c9e2103fed1dcfdeadc44fea5ff00a7f956366d375e492403ca935bedcf1eea4ff6ac68a55efc1beb3b552574f8e7009ff933a927ec715bc82b3a8f4d6bba5ca1352d22fe061cf9a0383f71dea5119cc6c0baed3eaac0f1fad40897dcc3d81f7a052366c1007df3400f21edefc5008c28f30c9c5170ee4fc37830086395250a7c66770c18e78da31c0c63de8609b41f7c515c5172a30c3b76344a3e377cb2339cf7a242aea89808cce368272b8c1a2e107c672a49f5c1a181c9c7ae7da8a2119e7b1f5068099ffa68258a132062d8f9e0f34059502b61bf2824e681bb297ced2a71efda80f19c47b9c77fdbe74057c13e539cf3c1a0eeeb9c73f33405ddb4f18249c1e28062b79ae242902024465b9214614649e7bd0362a7249eddc513456e5720f38f5a1a98e96e95d6baa6ebc2d1ad1e65521649bb469f563534d6d7d31f04347d2a2fc5f535db6a0e83718906c887cbbe5a9a8bef44dce9f731ca9a2e89169d6d6f2184b1455dc07b11dcfeb4d16f119c649a681285b03d3e5500f87820ff006a0e098191de80ac9b8904647b55d11da9681a56a31f87a869f6970b8ffe4883629a289aefc16e92d441682da5b098f21ed9f033f353914d19b751fc08d66cc16d12fe2bf45ec92ff0df1fdbfb559ec667aff4eeb1a04db359d3ae6d40eccebe53f46ec7f5ab82263da7dcf3eb5174e5181076918c7de869503232491ee4515c1803824f03b51287f30e0e7d803449494832c157278a2e8c71fcb9f9d144639236824d01e142efb1768cfb9c7ef40512a818de78ff00a682518e7cc30ab9e00a02cce9953247bd41e467191ed9a04205ee99da4e4e3d283a524b0427b5026c18a8e082067db8341ce0e39ed409b6502907391edda80f2dfdc496f0c124ac6184b144cf0a4e338fd2894f7a7342d4ba9b568f4fd261f12571966270a8bfd47d8511bae85f02b47b7fc34bac5d5c5dc88a0c90ab6c8d9bedce3ef4d1ad691a6dae976a96d616d15b409f9638d70054a1dbc68ea51d4329f4619a8022b78e04548515117b05000a035c5c4702a995c26e3819f534047bcb68a458cce866719540724d02e41c0f7a012a40f6141cbc8e7bd01719e38e6838af1c0a04ca8206d3cd037bdb082fad9e0bd8a39e0718649141047d0d5d18f759fc0cd3af164b8e9999acae4e4f81236e898f7c0f55fed574615aee83a96817ef67abda3db4ebdb7f66f983d88a061bb8db9e3d45165076db83c1f950a53780d8247c80a2398f182724f1c7ad080c608cfa7a51a0062adc7afbd0130173bb9c5070f071cb37e82826106e8f615e01c9e680d6b35bc534be3c1e3831b2aa962bb188f2b71df1de819ae4b1048c7f57bd01a58268e332642ae0704f7cf6207af6a01b99e17b7b6416e227407c494139909ed9f4c0a04a4e501e0f1eb40d263e53dce7fa682c9d0bd13abf58dd6db18bc2b157c4975270ab8ef8f563f21447a73a03a1f4de8eb031582b497328066b97fcd21ff038edfde88b7e32703bd64188e7e6283864b73400cd804b67ca3268317eacea6d56ff005233592f8b6303f953fa4af7c2fa93417fe98b763e0ea171297bab98558068f695ce0e08fdbd281e5c6a57ba5e9d14d716ef7774f2ec112601da4f27ec2827ada74bab559a20e148fcae36b0f91140283729c77a0e0a7777a01dac68395719e39a029607cb901b19c501480ab9279f4a086ea8d0b48d76c0586b7143224a76c61ce1831fe93e86b43cd1f12fe19ea7d2533dcdbeebcd20b612651e68f9ece3fcf6fa5067cbcf20ff009a051724905411e94032799060723da8406d6c67e7ea68d0e1770fe5cfb5026c37039ef9a02eca098c91e6e01e71c500b1d8a49c12786cf6a06a4e256008e3d050119958007920e2801154e32fb4120927b014017eb1c523ac5209a356215c291b87be28957ef853f0d66eaa99352d515e1d190f947669ce7b0ffa7e74a8f4be996569a5d9c56b6704705b46bb5238d42851f2ac875712bc70b3c30f892019540704d01ad2669a0491936330c95ce7140b2e4939a03638c7e8680ae485e33bbe540d60d3ada162c90a02c7270a39340a4f28b68da4645007a8f6a069a746f73235ddcefc391e12b2e1916824948742c99382473c73404791c617695279dc0640f9502c578c9efeb4095cb4cb0830ba21cf999c6401f4f5a05061d430c8079a02e03b3004311c7d281b5e3cd676c65489ee594e4aafe6c7ae07a9a0a075bbea3a8ea96f047d3935ebc404f04ad29411e08e011d98fed416fd212ee5b05b4d5ad6300c615807f1171eaa49eff5ad418c7c55f8466dd66d57a521f20cbcd66a7247a9283dbe5418a63862479877cf1f6c5008e400bdf1ce684016fe53dfbd1a73794600e08ce3d6800377c8c7d6800a9cf75fd4503d91492460f7ee3d28247a7b459f5fd592d22711c206f9e563858a31f99cfd050583518ba75247b1d134f9aed21396d4669769931dc01c003f7a329c4d17458ac5b55d36c12e040a3f1da75c1cb04ede2447f7f6a94567ad7a66db4fbbb29ba7d65b8b4bd8ccd09c8231eaa07b8ab04a7c2cf87b3f53ea8d77abc72c1a5dabe2452bb5a561fc83e5ee7e541e988218ed2dd22b7855228d76a46a00000ec00a510bd4dd511f4fe84da95cc31f880022da4902b1e7d3e99ac86fd03d631f565b4ee6d4dbbc649009cab2e48c83f514165b8b94b6895c44f279c280839e78ce28178ae6de46748a789e453865570483ec6812d42e85a421fc37918b00a883924d024c6e99b7a2a966c0009e17dc9f9fed40f81c77e28139218e4ff9815b9cf23340a01c907b9140201038ed402fcafd28386464e4fd33c50272bc60032609cf00fbd024f722dc66f24822ddf972f8feff00e280f69b24844919cac9ce7de83a447f30ded823007b50459d6ecacb528349b979127651b1dc795f1f3f7a0990148054823dc5015d491c0a0c3be337c2ff00c489b5ee9c87172016b9b541c49ff5a8f7f71eb560c1fc43e0a47e1aa94277310431f91fa551c1727f29ed409b641c86e31839a3454805739c1f6a026f1fd740f64665fc8c31cfde82db79bb40e9e8f49b62eb7d7e8b717ec832c91ff247fa1dc7df2281bcc9369d671493c422b7911654c1215f92bb8827bf068624ba635392df5eb4b9924558ee5bc19b71cee43c6dc7cf34c657be8db0b0b9d0f51d2afe668934dbf9628ddb8c2b8c0073f3a80da37546a7d25174fd95dc125c69f7313ee5655dfc313bd483cf07b1f6a68d5b48d5ec758b612e9d7293211c8fe653f35ee2a084eb9e8bb1eafb3582fe496278f3e1c919fcb9f97ad03ee8dd017a6741b6d3229dae161057c5750a48249ec3eb4139238568f6a9e7b103b5037934cb3793c610a2cd9277a8da73f5140ee38f6280c4b11c65b934023006d50050030e4647de80c846de3b500fcf9fbd0197273ed4007b91400e580c8e45074a82400e72682b36fd2162b7f25ddc09af2766ceeb872db79cf00f6a0b3229550140e07007a50092db860673de818df473c862686dad6470d9cce3b7b63e740fa1de6252ebb5bd81cd00bee2d800d003a6464004763ce683ce9f1cbe1f1d3a67ea1d1a30b68edffba814708c7f9c63d0fafceaca31e6dc71e1f07daa82608c83819f7a1a11ce149238fd68d0a579ec682cfd27a7c3a86bd10bc38b3b756b8b93c1fe1a8c91f7381f7a034f752ea5aa5c5eb292f732128037619c018f6ec282e5a2cb047abda74d5ce9b6da80f136de4a496219b3e48c92000323ea73467519d3da5bb757dbda410ac90c77c23058f99007ee7ec31416882ee47d23acb5185caf8bab4691b1efe57fff0038a9457ee75a82f6e7429350466b482f2742c0f74241c80c38c64541a9cfa1e89ac0177d33ab3d8de28f2b5bca429f91140e2c7a9b5ae9fb85b6ea9b46b9b3c796fe040768f76ec0fafb1f9505df4ebdb3d4edd6e74db98ee216fe68ce47d280648f75e2485a44da385ddc13f4a025ddbdbea16a633286566ce55f9c8f6c502ad750db2c514f30dec428247e6340bbf04100b73402afb943ed2b9e30683836defe9403bc1e06734020e06280cafe8683a375941d841c77c1a0151b467b50159f00e4127e5402872371040c5046eb5aadbe9b1c02e2f6dad25b89047099c677b7b0140fe3f1010afc803f3018e68160c3041ee2823f5dba92d34db89a1d9e2843b03b6d05bd013560c1748d57aa2797c6b35bab78e6959dc47231580ff336dcfb03c1a58364b5bbb7d7fa7b7427f1f673830c8664285bd1815238fad20f2c7c41e979ba43aa2e2c1cb1b663bede438f3a13c7dc76fb5515e9065b851f7a02950002a09c51a1b83cf14176e90d3645e9ad7752752aac23b3439c066665c827e944d29a6410aea725c4567135bd840d3c88a723728c29c9efe6c50d3ee9545b0bf8ef2e6e3c2fc2c6f72f2920e5f19039ee4938a9a875d03278377acf52ddf867f036ef71923932bfe51fbd3475cdc369df0db4fb389d4ea37970fa9cc0b00511795ce7d4f181eb4cd2451755fc45ac16d637381b14ca36b641dfce723e4053170d6cb52bbb362f6d3cb19241f2b9029862f09f143549ba7e7d2eef6caf2797c66ee17fdfd69862d1a069da7dfdac579d17adcda5ea9e1a992376c4723e39e3b024fd7e94c458ac3e25dee8d31d3bae74e7b79002bf8b8549471db38f5f4ed4c165e943a06a328d4ba605b4b22a1523c420c64fbaf38a82d36f0ce7cf7463790729b53017e940e0b0ceceed8ce0500e1b70daa08f5c9ed41d271cd0132476e7d7ff00aa069797d2411168ed9a41fcc858211f73c5075acb25ca6fb82aa31e58a36c81f561dcd033d42169e158ac64b98151b3981c2966cf639f4a064c7a8ac55e4865b7d493701e1c8e52403ea3cbfda827e390ca3f2c914aa81991bd281cdacc2747215c60e0ee5c67e940cb51b0b2bcbd824bfb08ee1a252d1caea1821cfa67b1fa504982b2283ce08f518a08abb82f6dd0369a5662081e14ce40c7ae1b04fda82275cb0bfd4f4536f7114589a5412461f3e4ce4e0e060f63f6ab2893d3b4b5b5b78e22ed22aae3cc3cc7e64fad3449a22a461500007602a0cd7e3b74c26b5d2ad79147baf34eccca40e4a7f30ff3f6aba3cd0543267eb5427b86f1f4c76ef45d0eca1ad5ef224d13e1cf4fd9b22192fa67bc955f8c8c617fba9fb510d7a6ed3fd43a735e5b54964be658c048fb6cdd9e7eb8a186bac97d174e6d22e23437b7ac26b95e77c68bf950fa7279e2b22dba45b59e97a669fa4ea36aeff89cea9a90451fc355ff0096ad9f4ce3f41570675d4fa8c77da8de5cde5be26bc653171ca47dc1f6c9fed5562b97f70276808da7c24f0c1c63804e33fa8a2928c0e0383c8f7ed41d92a41393f4a2548595c2c37493db4cd04e8a08f139566edfef3445b6e7aeaf65d2df48ea2b11776ae02a93e564c772adef409f4ee8ba9a21d73a36fa579ad9f325afe599171ed9c30a960d5ba0fe2843abb47a6f510fc26a4c36890f9558fcc6783506a1147b510024e30339ce680d2c6ae9861eb9a009178a0205443b989e39cd01d8075e3047ce80563057ca381ed4011c4531e503d85013c91b804a21279c903341131cda8c3abdc8650f6d20c4321232adec3dc504bab2c113c9293bb1963df3408dd4b75e1efb2856463dbc43b4631fad047e9177ad4fe32ea16b1db4b8fe1aa92571f5f5a0916bc8e0895af5c46c17cd8c9ff7da80f6d736f7f6915c59cab35bc837238ed8a072a31c1ef4062870718a06f7702dc5b3c522ee4752ae0fa8230683c75d6ba3b74ef535fe984929149e4278ca9e47edfdab42058003763ed409f88ffd6dfad06b1f12ae612fa0c76e0b471e9916d23f973eb4158d3efeff004a984da5debc1295d8e4018dbf3145d583a2ad96f356bbd7f5d90dc59587f1e79a6392f28fcaa3ee47159444ea3aa5ddfc7acf50dcdc344d7a4dbc317f52641200f6000fdeb41b5ef51d8eab672ffa9e971c97c11638268e431a46000012a3b9a351567db823b11f3ef40948e428048207a8340ab48ae83cb83ee0f3428a982719edf3e68c9cc97d3fe15ad8c9be138f2bf38e7b8f6ef40f7a5f55bdd3f56b46d3649127f1405f08e7249c76f5fa50689d48ba5f545cdcbdb462cba9206411b2b055bb07d4fb1c73528d4fa8f52d62cf47b6b8d2e65fc458c49f8a818795c151939f977a823ba0fe253750eb7fe937b04293f9f6c90be41dbdc7ff006283473c1efc1a06f69776d73bbf0f2aca32572bc80470450284a46dfca19f819f5a04e799614def26c0bdce09cfd85045dc75769d12dc3c3e2491db0dd3c85195235f7c91cfd066ae0cdba9be31f4ec61a386c1ef9d4ee473e45cfb1cf34c101d3ff1ac9d481d46c628ed24751881880833f988e7b0fa5328dfed2f2def2ce2b9b79925b791772ca87208f7a60182ee2b95cc0c48f53823fbd40ac658b30f4f4a086d4ee1d75bb6b78f4e965596366fc5211b23238008fde81f43692da5bc30d97831a0397dc09e3d714087506bf61a2c4cd77324726d2caaec141f9fd2ae0c435bf8c57173ad7876f7a2daca10489121244cdf319ce3dbf5a834fe81f881a6f57bcb6ba7c53c72c11873e28cee1db391dbef4199ff00ea4348116a5a66a8a8a04aad04847a90723f6ad7d18c312ddc02a3815423ba0f63fa541687bd9efe1b533b3c9e0a78473e899e318a09bd0ba6eef543e3b2bd8e9b10064bd9e4da001dc81401aeeb29a984d0ba7d5e1d06d4e6594f06523bc8e7f5c0ac8af752dfc17d7090d9218ec6d9447129ee71fcc4fb9cd6842ab10dc0014f3e5a2c1704b671dfdc734525226dc939e283a362c7f940344a380393df144733e2276e38f5efcd01b4bbbfc3dda4a9298a44395902e4a9c70682660d4265d62de40b1bdc1545054f95c8fe627df141af7c3af8808f3dd68dd5d2a45765884b8908d8c3b6c27b7a77a945d7a5fa474bd2ba8e4d5748b28624955d5d8b13b79ee9e983d8d40a753758c7a46b96f6114725dc92279a2810b3a64f94900763cfafa503fd3b59b79ed84da34713c0cd890f0a158fa1f981de826e1b548959fc4dc5cee24b6467e59ed4101ff19e9f676baa5d6a72c50adb4ad1ac790ccc076200f7ad41e7df881d79a87576a5f87b0f161d381db1c2a36e7e6d8ff3416bf87ff082c6f208ef7a82f22b9761bd6d619785f6dc477fa53705ab57f83bd297ceb1e9caf67708db9c4526723e849e3e94f212dd25d117fd29a8c09a76b534fa39cf8b6b71ced38e36fb73417f52e64548e34007e673e9f21ef590a1c918c90718dc281a69b68f67118d9da5058b798f6fa7fe280daadd1b2d36eae70710c4d263df0a4d583cc7a668fd4bf11b5837d7c93dcd9a3146959822a0e781f4cfa55161e9dd7fa67a4f55b9e9aea3e9f81fc09ca0ba118998fcdb2338c7b528d39f4cd2ba76e2d357d292df4eb391809963420ce1b1b576fa1e7359119f1eb4e17dd033ca172d6b2a4df303383fdeb5c8f2eef3bce4e0e335684cb0c9f354160d36f64b0baf16072b91b5f03391f43c51aab23a5debe91c4fad4d73689e6fc3a290573ff4f03e59f4a3280d67581ce916567f84b58ce0a1fccec3d58fa9a084de08c90464e4d1a8e419059b201f4a05630a176918efc50176293872c17bf14042aa0125b03db14046c60b60123fde6827fa0c68edd5365ff11346ba6292ee64194240c807e59a32b7fc51bfe8bd5ed5db424860beb62b89218422ce09c11c01dbbd0660ae110bf1bf2154838dbebfefeb41a8f4cdac7f117458f4d9ecd2df53b4cf81a822808c47255c0f7c8e7fb54a2ec2cfabba3b4b4b8d3af12eedad40926b0f070a13f9b633649f7a82eba6ea4357d321d4ecad512daf20df26e016507fa4fbfaf3e98f9d067dd2bd2faac9aa4d72d72d1e9510ca46a7631c7a320e18f1dfd7bd059afb7da816d23de4ba5de211346a1e4785f190548e4648c63b64e6b43ce9d5baafe3b539c5b452dbda46c638a167cb281c73ee4ff9340e3a3fa5f5aea4ba58f4bb57dbfcf2b02a8bf7f7a0de3a5fa0b50d2a2d92eb3e048c0a97c867dbedcf6a944e5cf4f6b76d1b3d8ea42795066266c87c81c65b9cfaf15048e83af3cd64abac08edaf01546c38dae4e0657ee6826e5b892de3702292e2545ddb55700fd0fbfca81c4b3bc718716eef9eeaa402280d14ab3c0b2c65c06fe571823ed40df56b217fa6dd5ab9216689a33f2c8c558307e83b8d77a37aaa7d22f2512c28768800c9954671b3d33ebef568d0ef7a7749eb0b5bbbb162d657b32b46d2e1564c8ed9c5644d1b0b9bbd261d2a440af6cb0e2e5b1e7dbc1238e0f7a0375b696daa7496a3a4dac8a92cf078685b271db04d391e40d5ec4586a1716de2a49e0c8c85d3b120f715ba1899173ff305413070abd89cfe9f5a2d3ee9c8639fa874eb6b804c52dc46b20c9f302c3bd11e84d47e1af4d5dc6521d3e3b662c19a58721ff5a9a321f89bd27a374b456d158dccd34d333332c9b4b2afbe47a7cb1f7aa33d2bc0d8c0f1c8f6a2c14b6d501b39cf63450897380c319e3de8065031c038f7ed40d8faf1ce41e4d004876a8dc3cc7e743025c956c818028c904579e7f0e15695c9c0541924f6c00283d0bf07f42d6b48820b8d62d20b2b58d656404959e52f83c8ff00fcfafbd4a35bb06f12391a48dd55cee2b2f3818ed8f6a8158a159890f02242079147623e631c502b0db436d1ecb7458d4738038fb0a087d6eeb508f48bb7d32d95750752b6c26c905b3ddb6f61eb574794f5cb6b9d0fa9678b512b25d24bbe52b8c1638278fbd582c57ff12afaed45b5bc0d0d8a8c08a2731ee3eec5793f40450466a1d59af446293c186cd53ca0c36eab93dc649e49fbd048e89f1675ed35e301e293919dcbf9867b37cbe94a35fe94ea4d33aba6824306dc48015750d86c6e247b0cf63591a40b8dc23fc30f14138dcac3000f9d03687547f12e8dd5af816b13148dddbcd29039c0f6f6f7a0eb5d62caf5636825db70c9bc4328f0dc0271c8a090627d3073ce681acf6505ccf14d35bc2f2c2731bb28254fb8a075144a83ca806792400334049ee6281e2496408656d880ff0031f61fa50446bd76058ea1b9e21025a3bb48afe71df9c7b71de9c8f196a0de23ca7b827d4f7add117e0cbfd4b5059392369663ff004e71c51aa97e8f555eadd258f2bf8a889cff00dc28cbd0bf123a926e96d163bdb74490bca2321c678209ff001591e71eafd7a7d7ef45cde2c20aae144638033fb9ad2e1b5e69d058da431ccf21d4a5c3b4631b62523807feaf5c7a50222f2d648c25f5aeec8c2cd19dae3d3e87e944d3eb7e90d425b49ef2292de38224f1505c3f8724a9eeaa7bd0d57a60406059436306868a7803839c7ad1a158039c13f4a33a716767f8cb9b6b55e1ae2458813e9938cd07a9f42d0b4de99b4b7d1f41b58ff19b03c93ba06607fa8b1f5f619a5b8266d74a65d42da6ba90cce996dcdc8c9fff006a5a2c2635083b05ef83eb5028076341db4b1ed9f7a04651fc41db18ed419d75b744dbea335fcb0db0335f2057901c05da73c8f9d5d18a75174a3f4c47335e35da4ce418a489374254f707d463d33565d1529b569a489a17944b06ec8057d71dcd037b4b6b8bfba31584124b27e62a8a4f1ea68357f83da7ea5a76bfe0912453ccabb49194653cb60f6ce3dfda983d196cd108c2401711f9768e306b2297d73fc6d02773a8b591922693c5004bb9d72542fa2f6efde8314ff867aeeec27500b77bb5670e36ca19b1dff2e7f2fd2837ce8bd5dd348b78b552219022870d9c46e792a4f6c608a0b846c8e03232b29ec41cd0199f1410fd4b24b1e8f712c0a5e4452d851e6c639dbf3238a0afa42ba77475e4ba8470896681da45180b18da76af3c9029c8f26dc1df2b9c606e273e86b743331924f27f4a82c12280e59b008e79f6a2d4d74188ff00e30d203a82ad7519c1ff00b860d11ba7c5e86c9fa3afae6f4091e043e021270b21e01c7dcd6479ab4dd3aeb56be4b7b184cf2b301b57d07bfd2b4bad0fe25e9f6960ba7c7a55ac50cd750335ccaade7723b83b8f6e38a2207a5ba4e7ea3d93780cb616ca53781f99fbff009a0b675a5be9765d43a75a6ad3b25adb4185429b831c70303dfdfd2831eb8954ca48f3827819c71ed406b2b1b9bf9a5fc1c4ce2253238047957dc9345d122b792eee522811a495ce1157b93ed444ff0049f476b1aaf51c761345269d25be269259570c833c6077249e062a68f53e8ef0da69509d4ae225b92a04af232ab16f98cf1f4a5a266d4dbca8af13a329ecca723f51502d14f0cb9f05d1c8ee01c91f6a0393b4edfe63c8a031608859b38f97340d84d04e5846eae50f9829ce3eb400fb24466041f5e3d2823f56d22db57b192d6e61468a41c823ff0035651916bbf04ada7badda5cad6d1b72c09dc33f2a6875d25f0865d06fe2bc6d4c4d3282026cca8cfafcfd29a34cd234a10c768f711a78f1bb392a3001208e3ec69a26a58d640c832091c90706a084ea1d3eeafdadf4f86da3166c0b4b397c18f046140f5ce4d04f4702436e91c28a9122e028ed8a0a9f5a5b6a09a1bc5a135bc72cce048b3c5bc15c638f9d59043fc2db997481aa69dae49e1cb6bb643239211939e467818f97bd305965ebce9a10bc8da9dbaa2679dd9ce3d8530572cfac87566ab05ae9f1490692b9696e1f833738555f96793504df5f25945d2576b7ec16dc46792381c7b7ad5e60f234980e42f6c9c56a82ec3eff00bd4124e49700f1c646e3cd169ce9575f83d52cee324347323f6e3861ff008a23d47d4ba6a75074fdcd8ef317e2e2ff0098bdd4706a60c3f4ae8cd5f44eb8fc3e97248a638cbc73bf90483d463b373e9574685abf42a6b5649fea72bbdeac4a8d3b018cfae31f7a6895b6b29b41d30d8e9f6bbed9213e1b7a994e724fcbb5064bd7835a9752d3af75d8116354778f660788cbd9483dbb0a0cd20b2b8d43528ad2088bdcccf854039cff00e2827a0d34e9da1de896f2182492efc0976f998aa827d3d334113a74aa9a9298628e74570478bc0c7cf1da83724bb8246d3e6416b0384da61b5501c9f5c3704f152c037561a95f5fce61d3ad6db4ab950f34b331dd9f4191db8fdcd406d67a675ab4b6d325d1af248272a43430315ddec7038f6ad4b3f448bf47eb71cb69abddebf21d5e26896203846c30c8603b9c6452d9835901405660376319ac84bf13180779d8bb82827d4fb0a06f777367a75acd7170f1430a9f331200cfceae061a0cf6dac692d7365266191db0578f5edf3a6075a6c9278b3433188a467860d96fbd40fe540471409aa0c1140750001ed8ed4058e15133c983960077edf6a06faade5c5b7822d2d926766cb967da2341dd8f0727d85033d27597d62e2ee3163756915bbf8799d71e2f19dcbf2a092b88dd9a311950a0e5b70ce47fe6ac18af53f5b69da9752dd69da9ca906876e24465d9e69881c6ff005c679c0aa2bfd267a347512c93dbb5d42d90d3c800b68c9ce0ec3cfa528db74ad034db5905ee8be1ac728dc153984f3f980f4fb56453be2de8f647a6aff53796596f0aed46798ec033ce149c0fb0ad71479c9bb9dc3bf3c55a0b95f65a825150b481a407b93c0fda8a29c06671dc93803bd131eafd0af6dffe18d2ee25982a4b04603b7a9c631fad03bbe586381bc5945b96385718c827db3eb5288eb8ba934eb15fc3c535f05427796dcccdec7150637d5bd55d5362b7975aa4d0d919018adec8637807bb60723000e4f7cd58203538aefa8aeb478a7b9beba924547b8774cf8608036a80704639cf1f9855d1a7f4c68b67a03de5e5d59dad8d988c62e1c0f107a1e7fdf7a082ea6d07a6e3e99375a7cb6b3db093c727701e2360f7f53dfb50653d4130d42ee18f48b3f0232a15218936963ebf5fbd06dbf0cfa74855b9d46e04b730c6144691e12307d33ea7de8348ba6b5478a279a004f98c479247b81f5a9438805ac0be2e02e73c9ef8fbd40c2346d43578eefc40da7da1dc8b8eefea4fcb9fef419beabf12a4bcebcb2d2fa7ee0dc58492084b30236bb6467dce383f6a0b87556a67a7f4d95a0bbb5468816f0a69c78b2e072572719ce78357079dfab3af2e7a92c963b88d94abbbf91cedc93edf418aa2c5f0dbe2a6a9a0c90d8de34773a6a8da1186d6403fa48fec682d9adeb7a9b4c9d572dacc9a6c9700456e5ca910e000ecbd8e580352fb1ae7476bd6dd49a325e5a9f3025245fe961dea097523cc0919a032af039a006936c81423104649c703ef40dcce64bc3035a87b6f0c378f9fe7cf2b8fdf340a4b6e25962915d94a67807839f7a043586922b5636ec44c061063f31f6ab079d7fe19b7eb2d4efeef55d5d74f992e9a0fc3a441dcb13927b838c9aa2d4bf042c618e178efee6e18104870172318edf5c1e6945bbe1a748ea7d2315edbea3a99bcb190030c401010e4e783ee0fa56455be3d6b90c1a6268d69e17f1486900ee98ec29ccc183119419e7e55ba11f089f523ef5058363a8059fb8e31e9421b491056c01819e28d3d0ff07eea3d53a1e3b6b8db235aca63c139c0eea68ca47a9fa6ef757b83ff00bf68ad428c2f248c7a8f9fcea518df516adac74e7544f63a2ea172f1800291e6cee19ec78cd5826344e85b6bad25ba8fade5b99dae0ee11efc71e858f7e7d054a2d7d39a75ae8f7b6b00b8917f1516624b78429da327cec493db1db1d8540cf4aea28f58d6aeae2f6dd64b498082d880488d149fcea7d4939ab04175e6850a8d32de3b78e380c8de32c4db4e18e430fef543cf86fd0d691b4fabdf6648b3b2db69ce7dd87be68342d2f4fb9b5b891af1a28a2dc05bc5036d001e0eef7352884b961a2ea9aa7555c885e08d45b5bc52b61b686c120fb939fb541276bd4b61d53624d942e2f6200bc32290633e99f4233416dd3ad3f0d611c0c77b632e71dc9ef41156dd27a45addcb3dbd9c513b1dd941821bdc7b558333b9f873757fd69a85e3f813e9c7723b5d93265d872473c11544a68ff08fa75e290b42ec4e4124e70738fa5048e89f0f745d2aeadd2decedda6525c975121183c77f7a945c754d0e0d563682ed43425369403bff00bcd58308ba7d5fe13f5a05889974a9d8b46aede4914f707d88ff001528ddf4fd7edb54d1a1d56c312dab2e64dbc9418e78f5c541296d70b716d1cd6f8789977230ecc280cb7519b816f212b205de4e0843ce300f6cfcb39a0545c42cee88e0b458ddec33ee680eac92266360debc7b5056fad2d354b9b189745744be121daf27e550548ce3d4d58324d07a725e98ea2b7ff5381f5169a7579d021fe13904ee43ddfbe49038ab46e76cf05cc714f6d309232a4a98ce54fd6b2196bb7f2e9b631b2c427b891b6851db3eff002007341e5bf887aa2ea3d4f77378be381e42fdb711ed5a1554395caf1cd07617dcd04fc85402101da791421b49920331381c60d1a69bf02f56f03a925b12c162b98c955f775e47df19a32d99b518268e4491668704a79d4aeec7b7bd4a30feb7e9144d76e265697c3e2693631674273803e556087d76f35fd49859e9925ccf611141106f2e182e3241f727f5a94681a268f79ad1b1b8b9dd66b1c2b1ce9bb06361c1e7bf3fe6a096b0d3ba57488e485b52b40909c386901607d47bf7a0ae758eb69ac4d15be81a748f0a9c35cc90b2eff4c03c1c638a0b77405c5d5d45f87be5fe359a88b81b401dc1c7d38fb50586fed18ea3015790091591e447c1518c8c7a0a0a5754d8c9d49a8d9f4ee9dba0b3b5224b9692327728f627e7c6682f9a7e996b6b3a8b6b748a348820c7720761412c064e3041ce282b5d4bd73d3bd3f33daea97ac2e540dd0a292dc8cd043c1f15ba2a7923b65bb910371b9a12141f9d02edf13ba2ade56857551e5e77244c54fd0e280746ebfe99bbbd655d56dcdc9ce08465565f4ee3bfca82d53eb3a6dac3e25c5f5ba646402e33fa77a0aff5b74ad8757e9ca972844aa37c520fcca7d3f5ab067bd369a8f467544d626c98e9f7118f0200e4465c903049c8c9e6ad1b24334b6fa6249716cab20037c309dd83db03b5640dddac3764a4f02cb1103863919fa7a1a06d6f600c37162911b7b252b87dc773f1927393f4a079f868edae1ae6328a8b1ed38e30050226e85d5dc1f879011b3c47c2f604719f9d01eff4f4b83e3c6b18bb452b1cac9b8a83de80b16e8208a3b7b58e1407cc061427cc0ff1560ce7a8f592d69a97504cad2dac01a2b53900c3e9e51ea58f727d0551e73bfb86b99a49a46dcf21c96340dc13804f20f6f9501c0e3b8a0963316fcc4607007f57bd084d64dec01200ce483468ff0040d525d1755b4d4206ff0095207c11dc67ff0019a18f56584f6daad9dade4211e39104a8ded9152b235cd8c530613229c8c1c8ef50472e81690ee00322b0c100f0debdbb7ca8111ace856371358cba85aa5cc407891ccf83f2ef4048b4ad2e59bf116769672c72f99dd1437239078e2824a4d3e1b94559234110e781839fa0a0561b38ad532a12319c86c6307e740a9732a3a00cac870cd8e0faf0681be8b6db965bb909df3c85806eeabced5a09523647e6e0fef419a6adf116daf7ac34be9dd1da686e7f1ca2e243b76320ce57df9ff1560cc3e3f470ff00c78255b842b35bc6c4af9b6e323d3e95467b6365f8dbcf062beb68c119595d8aaff6e282422e9899b4f6bb5d46cda2562a76316c1078f4a0859e1b9b762c0bf94f0e84feb4125a57505c58ea70dd5d0174a986d92b1c13f6f5a0de7a5be366877260b5d42dee2d2423124a487507ebdf15289dd3fac7a7bab6feded74d61733473acdb5a162142ff00313d81ed505fa58fc6d809380c1b9f5c502e0e05040ea367a85dea454de2ff00a610375b04c16c7a16ef8340b5f6930dce9375636acf6a278f04c5dd4f1dbf4a084e91d06f3a52dee62bbd4a2b882494ced3c8a448063b63b638fde803ab7ae749b2b3096d792c93c8c109b55dcd18ce3710473ffdd043dc758dc5869044565aa5dda4c3c2b7bc78c1f14e3963db03e7c0ab066bf1327d41ba76ca6bc48ecad24c456f6b0c87cf8e4bbfa138c0fa9aa3297c83dd4e28395811cf2680a5b93c7ed413cd1ff0f3c797b8031406645236b0508406f30e68ba49c051b97d0e0e7d28ad57e19f575c5be8f269515dac772877c11bc464dea7ba8c739ce78f9d3193bb8ebfea2bcbd6b5b6b8b58bb7f13c2f0ce31cf0deb4c0f2dbad6d743d2ee99efae752d6c02a86e0054524f6383c7ff94c0b6af274c75149a46a5a82c46f1e1479fc3190bd8156fbe7f4a960bf74e9d253f1167a3ac09e0856610e3041ec7f6c540f67b892cee7f8d18368232ef2af2508c7047cf340ead5bf130accc9b1186541e723d09ffc5033bbb1b82d74d6b37f1244daa1b38073df3f4a08eeb1d3b50d4fa6a5b4d32f12cef1902ee73e523d476fde8306eb0d3fabfa4ba92c278af67bb7281606472f90bdd58558253a6afb40ea1d62283a8b461a66a6f931cf6a7c2466f7cfb939e7b5515fbed3747b5eb8f06eb78d35080a2ec9719c76f98049a0b4ebdd37d1bad869acbf0b03c5c16b29444adf50ded41995f68564a263a66b31cd02be152505493f51c1a088bab69ad1bc179e320f07c37c8a0692b46c4995f0381db39a0b2fc34e971d57d4705bc8db6c50ef9dd97b81fcbf7381528f5ae97a1d8e996d1db69b0c7648855b10a81b80f43c739c54134147b9a036063279fb5046e957726a0f2cfe04915b06db1788305ffeac7a0a00d72f8d9c491c06337533050ac7185cf2df6a06da2da4293488f34973328c34aea428c9ec3eded40ee7d2ad249448f6b133820ee2833df3fde819ea96897461b05b87815f2ee919e5d47704fa039ab079b3e326b70eafd4ef6d6650d8e9ebf868b69c8247723efebf2aa280eb9193ebedc5002a124e015340018fb8fde82cf32b1603d0678cd02406dce3008e47ce81b499c331383c9c9f5a2e9c69377369f7d6f796a4acf148acb83fb511e91b3b3d0bab745b7d45acedd8e3732b71b1fd73f7a5a19eafd09a56a0a96b1c705b49c48510761ce4fcfbd4d0d752826b2b583476fc3daacb295b79d768de8a32b1e71f989e49f6a7d14dd1af5ba275a45b8b093c054492ea769092373765c1da4679fbd306e36ba9595fe9f0dcdbcc92c33e1579cf27d0d409ea178f68521b6b76926ee8a7853f7ff140bc768d78f6f73748d1cd103b543f0091cf6efc502f7319dac194371d8b6326829f0c501d7ae6fa568d5d4942c806d4db81839f53c8cd59456fae6e628749b5bab8b1865b08e4726588ec11e7f2e49071c93da9a31dd4341d675e9a5bad374f9858162d0b4ac70e18f0573df35a0c759f87bd53a404f174f965dfff00f479b1ef570576e34bd4b4cc0bdb3b9b7258a00e846e3f2a94376475cee4914af7ca9150685f09ba61efb52fc7dd69bf8eb7c158d1d0b47bb38f37efde968d6eeb4eb5e91d6ad25b660aee59974db6881690918e31ce39279e062a5a34bb57b88adedd1e379679065d80036679e6a07e8391bce7e940c659ef5afe1286de3b16f2b8903094b7b2fa7ce81eb380c4260ed193f2a0cd6fa5d4a4ea0fc7bdadcce923158a3039db83c038e3ef41a0e96b2ad8a35e009291b8a939d9f227e43bd590436bbd6fa269202c974b7123602c76e779624e00e29833bf897d493e896525dbcb2a6b5a9c3e1456b91b6d60cf989c7f31f7a60c02490961ebcf3eb541308e39e067b507007b96007a67fb50178f97eb4165ce18165c2927b773fad023202d9c8dbb7818ff003408300b87f2f1c107d0d0c15a4f2e339c90467f6a18bdfc2cea8ff4bd561b4b9ba686d6e64552c4f954e7d7e46a60f4688d240af1b2bc6cbf5047ca960617ba658de1b792f2d94a5ab33461b18524633fa1a81b5c8b5168967369d23c0e0a24622dc981d81c76aba29df0bb48d660d52fceb88d069f04aeb69130037127f37b9c0ed9a8350781240bbc06da72323b1f7a0eb8816e633192ebc8c9472a78fa50349b4c83c068e24f0ddbcc1c13b837be4d055b57e98b996d4db5b4a893dc1e6620b6ccf2c467efc504ce97a38d3f4d874bf09af6d46e2f25cb82724e791db15650a43f878b51fc34f3da8f132b6d6a98c80a39ff007e99aba249631b58b9047239ec3e55368aeeb7d2da6f52c0eb7f16e87f2c6e836ba90724ab7a67b55d115ac7c3e8aed2182def4c56a14096368959a423d77e3229a27b41e9d8343b01069c8a8dc9660aa3713df3c64d4a1c695d3d6b67a8cba94b9b8d4e61869e4e4a8c636a7f4afcaa09a485519caae19b966f7a0435196582c656b74df3e308beec7b50629375775b691ac5bdb6b16d6378779f019b00a31cf391c9c2f1daae0b35ef52f5374de88d77aa45a6cd25ddc0108694ee2188c28007603d6a0d16c92430a4b2ed3230dc401855cfa0a0a07c45d7b5db9d462e9ee960b14b2ee134ef8c850012147ec78ab0670b643a2efae753d72686e6e2da211db42176079c8e768f65e39f7aa332d6f58bbd635096f6fe6692695b24f603d801e82823cb900ee00e68006460051dfd680ed9f0c905b713d8d006d5f5419fa505a18f94e40501b1b81a04186d62402c87be3d6810b81290aea8467201231cd1749dbc437f9f1e201db3de8ba07dc0175c027f28a335b17c26f888d6b6d0e8fabf892a29c453b1e547f49f7a946d6424f08236491c833ee0835073294888894120700f0280813c40a6711bc8843e00fca7d3ef40e41dc081f9a811681c6f7565329185623b7e9de812b3bcf11ff0b74563bd50494cf120071b97e5fda80d7577046c9019d5669dbc340324eec67fb734103d5da96bf67a7cf0e916f6e2765f25ddc4c11107ab1c8c647cce2816d3ec7f0f6564cae6e67da375e6d52cc4af2e4fb13ed4145f899d47b3499f4bb6d46cda49b69b92921565c3648e3dd40c81cd5c0ae89f13ec246d3e379ed2d6da180b5d34849da1780b128e49271c9f4a60ba685d5fa36bc42d95c324ec7090cc9b1d87b81ed50588958977cacaaa3b9341c655f12348d1dcb8dc1946540f99a019e2134454eeda7bed3839cd052fe2136b536b5d3563a1ca53c49da4b9507198940ce7e5c9fbe281c6b7a974cf4ee4ea7242d76dc784a3c595b3e9b464e3f6ad0ac745ccbd4fadcbabea42da56959a382ce7460d6b1a93c01f97272093ebf6a82f1ad6af0e9da5cb3cecf6902216919f82aa3818c7a9f4c530649a9f5269ba7429d472239bc991a1b0d3c3152880f0f23039e7bf3de90635ab6a377aa5ebdcdecef2c9239e59f3827e5ed54302195fcc38cd01245395c1f5f4a05b606538e483c501b6939e3b5077860f3914165754c33e549000dbe87de813b820c27fa7baafb8a04a69c98e281e42618c795338033df1f3a06c03e4e029247007ad010093c35674da71f977640340081a190658e41c820f141b0fc33f8926c218b4ed609366a02249bb2d19ce3ea4528dbece68eead926b7916689c643a9e0d643387521fea2f693c2d6efc786ee46d9bfed3eff2a04669edf5295ff057a60bd865309246d3bbbedc1efef41d63a8dec9ab4fa7dd4510fc3c69234ca186e2d9c003b7a67bd034bad0a5bb96e25d575267889cc1b54446d9bd0a37bfbfbd02925945a72cba8dddc48b3f87b1e58f23c623f292bdb7fa7cf38a0a5750f54ebba56a9a67fc516b6d6fd3970ea9234677c8dc7f38f6e4640ce282d1ac4b16bfa72c1d2bad430cd1ba822061865f5007d3daac19cf547c189357d561bbd3eee683c62cd786e9b73337b8c7bd512bd39f06adedec2de0d5ae639da372e6485363107f97767b505cee755d03a5e58ac228659af123184b7b733322e38c91dbf5a943ab3d52e64b49ee755d2e64950e238e35f10c884e17cbe87dc540e6d7509a4f110e9f7566a471712850abf6ce463e6280bacea36fd33a4497f773cf32c698dcc4beee33938edc7ad05534aea683ae61d64c4d2a69b6b88d16d5ca5c303f3e386cf61db140e27b5e99e96b64bdd562b6b30aa36c6c37cac7dc9eec6b42c1a66a962fa70beb6b516d0cbe76322f86c78f6c66831bf8b5d5d2dfa35a5dce60b1933b6ce3c788769f2b331ec1b8fd2831b79649984b239773c1dc68129725c1c640e73400ec781d8fb1a03c4a85d0c8582640257bd01e51fc42236263c9c67be280429c6037eb405dbf5fd682c2a0bb976cf07d3fc5009279ef8ec4e68193a9902b28e7dc71fb501d95b098e0f6dd9e0d0049131019b047b8390281bb292484e47c8500c4f242c3076bf704704739a0be7c3febfbae9a5daf23cd017c7e19fb107bb67d0f6fd6837cd2757d1fab34f4f05e37dde630b1c3a91edf4f7159103d6eb7da65fdbdf59dadb5e2460ac876ed9e1c8c060f9efe9c8a0a75cfc42d5742d2ee5a7e9dbb494b6d6b9bc930cce4f940e3cd81ed4160e98f88315e689fff0022b57664199cc5196f0c7a164ef8f98cd0589baffa68590985eb15c0db1985839f6c2919340b69d03f5285bdd6f4bf021424db4329cb153fccc3d09c76a090d3340d2f479a7bab3b38e2924e5e451cfd280d7dafe936f6c5e4bd89813b02a36589ce318a0358dc35cc4e17f9bf234cdbb78fa0c607a7340e6cec20b1596610c6934b8323226379edda81da8dcb9ec40a042f50b5bb21645473b58b11dbd7bfca8304f8add5d67a9ea8ba5d8ea72c1a4d8a952f10f2c920e368cf71e99fad5833dd0754d6ed66bdb2e9a91a5babb2a310465a57c1ddc1038e7bd5171d3748b8d46ee1ff005298dc6a764c27d4eeaee7fe1c01795881c9e7804fe940dbe287c4b6d75a1b1d1c986d62277c91bf131f4c0f6fad0663737135d3b497124924871f98e7803007d2811dc5b83903dc0a0333f03be7de8122df2c9a05a11e5f51f7a05ce7071804fca8033e5da0734020b0183bb23e5416269577ed0e5323078ceeefdff6a03dbcd62914c2f629a47c622689800879e4fbd046f9d8a2a03e31385c0e73da8b83ca590947dcaead8208e73da8849b3e19ce704f7c5015586d006431f5cf61f3a04ee586ff002481c8fe6191408f0011eb8e30682774dea9bbb5784492ca6385832e1ca95e3d2834be9df8c312e2db5eb4375080337000f1303d18763591a469baef4d755989ec6f6dae5a23e20b599406dd8e080ddbed41272f4dd8caf1c86d163910f9595882a3d718a035edd695d3b6a926b57d0ac65b10b4e06eedd863bf141077fd7af2782bd3fa26a1a8891d57c630948c0279393dcd04cf5875258f4de9f0cb7b7b6d66d2b81ba752d85f5214724fed41036bd79d2fe319d7a8f4b9c81e58de2f04827b9ce09a07a3acecf54b790685ace8697606009e52c377b7f2e682b097d7d36acf0f55df5edbdc0977412468cb6ce3be10af3c63b9c8a0b0751f505be9690dd5d752436f62a3fe4c6448f3b7b0c64e38f615734651f107e3045ac42b67a7693018633b965bc1bc838ee173807bf7cd33065baaeb1a95f2c11dfcd2bc51fe48880aa3e8a062a8b059f595df4ae9a74de9e9ec499d43c97b1427c6e47e525bb63e4282ad3ea3712893c599dbc4259c1627713c927de81043950df97db1406da8411c92063be280230839627078e79a0390a71b5bb5003a8c1232338e4507025573e9fbd02a0e41dc0e680c3691cf714053bb34160895dc16f291d98d02322aa39f3e14707ffaa06f202a5bb0c7201f4a343aca51090497efdfbfce89840c8db8e46573923ff14410b00490d9f5c1a0425dd8ce4673e873cd0265e4dbe7041ed814009b8cbb8e5863bd07163b7716e0607b6698060b96b7b9478dc8643918247ee39a60b7e97f133a8b4e0c63d4ee597380923970a3ef4c0e13e25dfcfab457ba95bdbddb212016501867b9cfbfda982f907c74b282da34874a9048aa479c83838edc62982b7ac7c42d235cd67f15ac5b40c366418a2cb0c1c81e6f5e31db14c160d035de8cd4a3f18ea96562cc37359dfe9cac887fef039fd6b39446f56ea5d13a9dca4579a922496b1975b8d22dfc3566cf9557230703be715ac1431d4d2275325d7fae6b4f6f182a93ef1e32a9f41938f6a60afeb1a95c5fea53dccf772cf2c8c489240031f627e7565c0d67bbf160487c1801073bc0c31f91f953420f2bc8c7c52cc540032738a809905c0f4fa501940208e73df34028e703938a0577ae013f4a001300db4f03b71407461ce0502dca8c9c7dcf6a003fafcbdcd0070bc1e0fd734070db467b8a04cb9c9e68274b93bcb1daa40200ed4099765249ec476cf340849b8b264823bf34689ee009cb671df1409bc8e8b8e770e3ec68984d9c953cf97be2860b248caaebc107dc67f7a184c31232db88fd451031ce50e76039f5c8045026efb8f93279e0fd680b239504f0483d88ef409ee25bb90c79c0e050151c6e21b39ce783eb40adbcc2cefa17bdb61322387781c950e3dbdf9c8a066f28790b22e013db3dbef54726081e63c6460d34191b1bb0720f634060e7600412c781502409c8e3d7b500ed71dbef8ed40243f181c0a02e5d4e0fad006f644e4819e3b501f7e3049e7b501bc43b4e391da80558003392d40a23305e320d02e64cf998e1bf5a032b0c927b8e68049c8c8e71c6280377043118f4e680bbff00de0504ddbb3128371c1c64668024e59f3cd02521254e4fad1a2107e48fe6a6809ddb9e78a029e1463d05027ffc744a6c3857c7b1a205ff00e637fbf4a02b12b1794e39f4a02024e7249ed409924720906800005173fd7404989698ee39e4f7a04cf723d07a501fff0097ed406ffe36a018ff00281e99a037f4d0731f3bfd28007e53400ff99a810248c0cf140bc60123233cff008a0557f9beb4056eff007a07109243e79a03778b27bfbd02b128c27039a054001b818a06609de793da815006070283ffd9}\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is a movie {\pict\jpegblip ffd8ffe000104a46494600010101004800480000fffe0050546869732061727420697320696e20746865207075626c696320646f6d61696e2e204b6576696e204875676865732c206b6576696e68406569742e636f6d2c2053657074656d6265722031393935ffdb00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffdb00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffc00011080016001403012200021101031101ffc4001a000100020301000000000000000000000000080905060a07ffc400231000010501000300010500000000000000060304050708020001090a11153976b7ffc400160101010100000000000000000000000000060800ffc400261101000102050109000000000000000000010200030405061121b33134365154717475b4ffda000c03010002110311003f00a90cf388f366a62aa720ed6ae07f96901f3831d973452b8cf36fe3570fc908e46d466433e5dd954f2e96992d9e498c7753faa44916e016ca91cc7d88b38fe60a5b97737defcbcc539c98d336a57f4fc2ca9a486bf07ab575ad9a3af4df221d8215e36df86c4504ff0024574551b3d687ee0575757b3ad64e311ee62bd94158d37e24198c43973099f1fc0c41614d950246513a081abf76cfe7061f6863281e6352fd1670949c148dd6dfb0d25f5b3689b1d5c965b0eacbf4e0932ad28e22ab9ae945633f4744bd3c8cee0a7fdf085b9000f449c5f7afa30b83e0b6fd7b0c8429c9467ff9715347c891e25fa24a205861aa715e6a09bd0488237dc2723414d9891381524e8ca7c0894664f835653631ab55ee7e3de433e4ff001b30949124e4c10c8b6ad0a479b3f9c937b2cf5bc0095ad600a0a41a0e9faee174a1c605e161c6c7a313539650b0113190f1a8368e60d5b24f30ff008ea7f0bf867fa6595feeb6978f1fe0f9c26177f4d63a51a9235184750e7d18811339cd000000c75f000e00380380ae390c350def826ed42ad051fa6f501c50f9b699c3b69cbeb76476d202bf3ac985b6e0e968be66572893e6a744540bd9722e5c87956848629bc2559306bd113e8653d3b6aff651dfad7a3ac8b02958cba02a93ccf525757039bae6cff090e1d90688e8aa233ee86a4c4a3e0586d6b2340522e47dcb7d0046d8a5acb05a123ee25d2b230b2ada6e2e2f9ede3c05202520ec2487b0d56562529d8b3393bca76adca4ec1bca508abb001babc007915d84fe3dd14e207e3c62f8379da2a3b861fb6629d28dba53b6ea388ebfed866bf6dfb553455e91ed547ae92e9445253a4fdf3efb4f8ebdfbe7d3c78f1ee0bb9e13e358e942a4ed49e22cff00eeb35fdd7ebfffd9} icon.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Footnotes\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is a footnote reference,{\super\chftn}{\*\footnote\chftn\~\plain\pard {\pard \ql \f0 \sa180 \li0 \fi0 Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.\par} } and another.{\super\chftn}{\*\footnote\chftn\~\plain\pard {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's the long note. This one contains multiple blocks.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Subsequent blocks are indented to show that they belong to the footnote (as with list items).\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 \{ \}\par} {\pard \ql \f0 \sa180 \li0 \fi0 If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.\par} } This should {\i not} be a footnote reference, because it contains a space.[^my note] Here is an inline note.{\super\chftn}{\*\footnote\chftn\~\plain\pard {\pard \ql \f0 \sa180 \li0 \fi0 This is {\i easier} to type. Inline notes may contain {\field{\*\fldinst{HYPERLINK "http://google.com"}}{\fldrslt{\ul links }}} and {\f1 ]} verbatim characters, as well as [bracketed text].\par} }\par} {\pard \ql \f0 \sa180 \li720 \fi0 Notes can go in quotes.{\super\chftn}{\*\footnote\chftn\~\plain\pard {\pard \ql \f0 \sa180 \li0 \fi0 In quote.\par} }\par} {\pard \ql \f0 \sa0 \li360 \fi-360 1.\tx360\tab And in list items.{\super\chftn}{\*\footnote\chftn\~\plain\pard {\pard \ql \f0 \sa180 \li0 \fi0 In list.\par} }\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 This paragraph should not be part of the note, as it is not indented.\par} } pandoc-1.12.2.1/tests/writer.texinfo000644 000765 000024 00000034630 12251233603 017177 0ustar00jgmstaff000000 000000 \input texinfo @documentencoding UTF-8 @macro textstrikeout{text} ~~\text\~~ @end macro @macro textsubscript{text} @iftex @textsubscript{\text\} @end iftex @ifnottex _@{\text\@} @end ifnottex @end macro @macro textsuperscript{text} @iftex @textsuperscript{\text\} @end iftex @ifnottex ^@{\text\@} @end ifnottex @end macro @ifnottex @paragraphindent 0 @end ifnottex @titlepage @title Pandoc Test Suite @author John MacFarlane @author Anonymous July 17, 2006 @end titlepage @node Top @top Pandoc Test Suite This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @menu * Headers:: * Level 1:: * Paragraphs:: * Block Quotes:: * Code Blocks:: * Lists:: * Definition Lists:: * HTML Blocks:: * Inline Markup:: * Smart quotes ellipses dashes:: * LaTeX:: * Special Characters:: * Links:: * Images:: * Footnotes:: @end menu @node Headers @chapter Headers @anchor{#headers} @menu * Level 2 with an embedded link:: @end menu @node Level 2 with an embedded link @section Level 2 with an @uref{/url,embedded link} @anchor{#level-2-with-an-embedded-link} @menu * Level 3 with emphasis:: @end menu @node Level 3 with emphasis @subsection Level 3 with @emph{emphasis} @anchor{#level-3-with-emphasis} @menu * Level 4:: @end menu @node Level 4 @subsubsection Level 4 @anchor{#level-4} Level 5 @node Level 1 @chapter Level 1 @anchor{#level-1} @menu * Level 2 with emphasis:: * Level 2:: @end menu @node Level 2 with emphasis @section Level 2 with @emph{emphasis} @anchor{#level-2-with-emphasis} @menu * Level 3:: @end menu @node Level 3 @subsection Level 3 @anchor{#level-3} with no blank line @node Level 2 @section Level 2 @anchor{#level-2} with no blank line @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Paragraphs @chapter Paragraphs @anchor{#paragraphs} Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. * criminey. There should be a hard line break@*here. @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Block Quotes @chapter Block Quotes @anchor{#block-quotes} E-mail style: @quotation This is a block quote. It is pretty short. @end quotation @quotation Code in a block quote: @verbatim sub status { print "working"; } @end verbatim A list: @enumerate @item item one @item item two @end enumerate Nested block quotes: @quotation nested @end quotation @quotation nested @end quotation @end quotation This should not be a block quote: 2 > 1. And a following paragraph. @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Code Blocks @chapter Code Blocks @anchor{#code-blocks} Code: @verbatim ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab @end verbatim And: @verbatim this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ @end verbatim @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Lists @chapter Lists @anchor{#lists} @menu * Unordered:: * Ordered:: * Nested:: * Tabs and spaces:: * Fancy list markers:: @end menu @node Unordered @section Unordered @anchor{#unordered} Asterisks tight: @itemize @item asterisk 1 @item asterisk 2 @item asterisk 3 @end itemize Asterisks loose: @itemize @item asterisk 1 @item asterisk 2 @item asterisk 3 @end itemize Pluses tight: @itemize @item Plus 1 @item Plus 2 @item Plus 3 @end itemize Pluses loose: @itemize @item Plus 1 @item Plus 2 @item Plus 3 @end itemize Minuses tight: @itemize @item Minus 1 @item Minus 2 @item Minus 3 @end itemize Minuses loose: @itemize @item Minus 1 @item Minus 2 @item Minus 3 @end itemize @node Ordered @section Ordered @anchor{#ordered} Tight: @enumerate @item First @item Second @item Third @end enumerate and: @enumerate @item One @item Two @item Three @end enumerate Loose using tabs: @enumerate @item First @item Second @item Third @end enumerate and using spaces: @enumerate @item One @item Two @item Three @end enumerate Multiple paragraphs: @enumerate @item Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog's back. @item Item 2. @item Item 3. @end enumerate @node Nested @section Nested @anchor{#nested} @itemize @item Tab @itemize @item Tab @itemize @item Tab @end itemize @end itemize @end itemize Here's another: @enumerate @item First @item Second: @itemize @item Fee @item Fie @item Foe @end itemize @item Third @end enumerate Same thing but with paragraphs: @enumerate @item First @item Second: @itemize @item Fee @item Fie @item Foe @end itemize @item Third @end enumerate @node Tabs and spaces @section Tabs and spaces @anchor{#tabs-and-spaces} @itemize @item this is a list item indented with tabs @item this is a list item indented with spaces @itemize @item this is an example list item indented with tabs @item this is an example list item indented with spaces @end itemize @end itemize @node Fancy list markers @section Fancy list markers @anchor{#fancy-list-markers} @enumerate 2 @item begins with 2 @item and now 3 with a continuation @enumerate 4 @item sublist with roman numerals, starting with 4 @item more items @enumerate A @item a subsublist @item a subsublist @end enumerate @end enumerate @end enumerate Nesting: @enumerate A @item Upper Alpha @enumerate @item Upper Roman. @enumerate 6 @item Decimal start with 6 @enumerate c @item Lower alpha with paren @end enumerate @end enumerate @end enumerate @end enumerate Autonumbering: @enumerate @item Autonumber. @item More. @enumerate @item Nested. @end enumerate @end enumerate Should not be a list item: M.A.@ 2007 B. Williams @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Definition Lists @chapter Definition Lists @anchor{#definition-lists} Tight using spaces: @table @asis @item apple red fruit @item orange orange fruit @item banana yellow fruit @end table Tight using tabs: @table @asis @item apple red fruit @item orange orange fruit @item banana yellow fruit @end table Loose: @table @asis @item apple red fruit @item orange orange fruit @item banana yellow fruit @end table Multiple blocks with italics: @table @asis @item @emph{apple} red fruit contains seeds, crisp, pleasant to taste @item @emph{orange} orange fruit @verbatim { orange code block } @end verbatim @quotation orange block quote @end quotation @end table Multiple definitions, tight: @table @asis @item apple red fruit computer @item orange orange fruit bank @end table Multiple definitions, loose: @table @asis @item apple red fruit computer @item orange orange fruit bank @end table Blank line after term, indented marker, alternate markers: @table @asis @item apple red fruit computer @item orange orange fruit @enumerate @item sublist @item sublist @end enumerate @end table @node HTML Blocks @chapter HTML Blocks @anchor{#html-blocks} Simple block on one line: foo And nested without indentation: foo bar Interpreted markdown in a table: This is @emph{emphasized} And this is @strong{strong} Here's a simple block: foo This should be a code block, though: @verbatim
foo
@end verbatim As should this: @verbatim
foo
@end verbatim Now, nested: foo This should just be an HTML comment: Multiline: Code block: @verbatim @end verbatim Just plain comment, with trailing spaces on the line: Code: @verbatim
@end verbatim Hr's: @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Inline Markup @chapter Inline Markup @anchor{#inline-markup} This is @emph{emphasized}, and so @emph{is this}. This is @strong{strong}, and so @strong{is this}. An @emph{@uref{/url,emphasized link}}. @strong{@emph{This is strong and em.}} So is @strong{@emph{this}} word. @strong{@emph{This is strong and em.}} So is @strong{@emph{this}} word. This is code: @code{>}, @code{$}, @code{\}, @code{\$}, @code{}. @textstrikeout{This is @emph{strikeout}.} Superscripts: a@textsuperscript{bc}d a@textsuperscript{@emph{hello}} a@textsuperscript{hello@ there}. Subscripts: H@textsubscript{2}O, H@textsubscript{23}O, H@textsubscript{many@ of@ them}O. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Smart quotes ellipses dashes @chapter Smart quotes, ellipses, dashes @anchor{#smart-quotes-ellipses-dashes} ``Hello,'' said the spider. ```Shelob' is my name.'' `A', `B', and `C' are letters. `Oak,' `elm,' and `beech' are names of trees. So is `pine.' `He said, ``I want to go.''' Were you alive in the 70's? Here is some quoted `@code{code}' and a ``@uref{http://example.com/?foo=1&bar=2,quoted link}''. Some dashes: one---two --- three---four --- five. Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses@dots{}and@dots{}and@dots{}. @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node LaTeX @chapter LaTeX @anchor{#latex} @itemize @item @tex \cite[22-23]{smith.1899} @end tex @item @math{2+2=4} @item @math{x \in y} @item @math{\alpha \wedge \omega} @item @math{223} @item @math{p}-Tree @item Here's some display math: @math{\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}} @item Here's one that has a line break in it: @math{\alpha + \omega \times x^2}. @end itemize These shouldn't be math: @itemize @item To get the famous equation, write @code{$e = mc^2$}. @item $22,000 is a @emph{lot} of money. So is $34,000. (It worked if ``lot'' is emphasized.) @item Shoes ($20) and socks ($5). @item Escaped @code{$}: $73 @emph{this should be emphasized} 23$. @end itemize Here's a LaTeX table: @tex \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} @end tex @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Special Characters @chapter Special Characters @anchor{#special-characters} Here is some unicode: @itemize @item I hat: Î @item o umlaut: ö @item section: § @item set membership: ∈ @item copyright: © @end itemize AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: @{ Right brace: @} Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: - @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Links @chapter Links @anchor{#links} @menu * Explicit:: * Reference:: * With ampersands:: * Autolinks:: @end menu @node Explicit @section Explicit @anchor{#explicit} Just a @uref{/url/,URL}. @uref{/url/,URL and title}. @uref{/url/,URL and title}. @uref{/url/,URL and title}. @uref{/url/,URL and title} @uref{/url/,URL and title} @uref{/url/with_underscore,with_underscore} @uref{mailto:nobody@@nowhere.net,Email link} @uref{,Empty}. @node Reference @section Reference @anchor{#reference} Foo @uref{/url/,bar}. Foo @uref{/url/,bar}. Foo @uref{/url/,bar}. With @uref{/url/,embedded [brackets]}. @uref{/url/,b} by itself should be a link. Indented @uref{/url,once}. Indented @uref{/url,twice}. Indented @uref{/url,thrice}. This should [not][] be a link. @verbatim [not]: /url @end verbatim Foo @uref{/url/,bar}. Foo @uref{/url/,biz}. @node With ampersands @section With ampersands @anchor{#with-ampersands} Here's a @uref{http://example.com/?foo=1&bar=2,link with an ampersand in the URL}. Here's a link with an amersand in the link text: @uref{http://att.com/,AT&T}. Here's an @uref{/script?foo=1&bar=2,inline link}. Here's an @uref{/script?foo=1&bar=2,inline link in pointy braces}. @node Autolinks @section Autolinks @anchor{#autolinks} With an ampersand: @url{http://example.com/?foo=1&bar=2} @itemize @item In a list? @item @url{http://example.com/} @item It should. @end itemize An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowhere.net} @quotation Blockquoted: @url{http://example.com/} @end quotation Auto-links should not occur here: @code{} @verbatim or here: @end verbatim @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Images @chapter Images @anchor{#images} From ``Voyage dans la Lune'' by Georges Melies (1902): @float @image{lalune,,,lalune,jpg} @caption{lalune} @end float Here is a movie @image{movie,,,movie,jpg} icon. @iftex @bigskip@hrule@bigskip @end iftex @ifnottex ------------------------------------------------------------------------ @end ifnottex @node Footnotes @chapter Footnotes @anchor{#footnotes} Here is a footnote reference,@footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.} and another.@footnote{Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). @verbatim { } @end verbatim If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.} This should @emph{not} be a footnote reference, because it contains a space.[^my note] Here is an inline note.@footnote{This is @emph{easier} to type. Inline notes may contain @uref{http://google.com,links} and @code{]} verbatim characters, as well as [bracketed text].} @quotation Notes can go in quotes.@footnote{In quote.} @end quotation @enumerate @item And in list items.@footnote{In list.} @end enumerate This paragraph should not be part of the note, as it is not indented. @bye pandoc-1.12.2.1/tests/writer.textile000644 000765 000024 00000024102 12251233603 017172 0ustar00jgmstaff000000 000000 This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite.
h1(#headers). Headers h2(#level-2-with-an-embedded-link). Level 2 with an "embedded link":/url h3(#level-3-with-emphasis). Level 3 with _emphasis_ h4(#level-4). Level 4 h5(#level-5). Level 5 h1(#level-1). Level 1 h2(#level-2-with-emphasis). Level 2 with _emphasis_ h3(#level-3). Level 3 with no blank line h2(#level-2). Level 2 with no blank line
h1(#paragraphs). Paragraphs Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. * criminey. There should be a hard line break here.
h1(#block-quotes). Block Quotes E-mail style: bq. This is a block quote. It is pretty short.
Code in a block quote: bc. sub status { print "working"; } A list: # item one # item two Nested block quotes: bq. nested bq. nested
This should not be a block quote: 2 > 1. And a following paragraph.
h1(#code-blocks). Code Blocks Code:
---- (should be four hyphens)

sub status {
    print "working";
}

this code block is indented by one tab
And:
    this code block is indented by two tabs

These should not be escaped:  \$ \\ \> \[ \{

h1(#lists). Lists h2(#unordered). 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 h2(#ordered). Ordered Tight: # First # Second # Third and: # One # Two # Three Loose using tabs: # First # Second # Third and using spaces: # One # Two # Three Multiple paragraphs:
  1. Item 1, graf one.

    Item 1. graf two. The quick brown fox jumped over the lazy dog's back.

  2. Item 2.

  3. Item 3.

h2(#nested). Nested * Tab ** Tab *** Tab Here's another: # First # Second: #* Fee #* Fie #* Foe # Third Same thing but with paragraphs: # First # Second: #* Fee #* Fie #* Foe # Third h2(#tabs-and-spaces). Tabs and spaces * this is a list item indented with tabs * this is a list item indented with spaces ** this is an example list item indented with tabs ** this is an example list item indented with spaces h2(#fancy-list-markers). Fancy list markers
  1. begins with 2
  2. and now 3

    with a continuation

    1. sublist with roman numerals, starting with 4
    2. more items
      1. a subsublist
      2. a subsublist
Nesting:
  1. Upper Alpha
    1. Upper Roman.
      1. Decimal start with 6
        1. Lower alpha with paren
Autonumbering: # Autonumber. # More. ## Nested. Should not be a list item: M.A. 2007 B. Williams
h1(#definition-lists). Definition Lists Tight using spaces:
apple
red fruit
orange
orange fruit
banana
yellow fruit
Tight using tabs:
apple
red fruit
orange
orange fruit
banana
yellow fruit
Loose:
apple

red fruit

orange

orange fruit

banana

yellow fruit

Multiple blocks with italics:
_apple_

red fruit

contains seeds, crisp, pleasant to taste

_orange_

orange fruit

bc. { orange code block } bq.

orange block quote

Multiple definitions, tight:
apple
red fruit
computer
orange
orange fruit
bank
Multiple definitions, loose:
apple

red fruit

computer

orange

orange fruit

bank

Blank line after term, indented marker, alternate markers:
apple

red fruit

computer

orange

orange fruit

  1. sublist
  2. sublist
h1(#html-blocks). HTML Blocks Simple block on one line:
foo
And nested without indentation:
foo
bar
Interpreted markdown in a table:
This is _emphasized_ And this is *strong*
Here's a simple block:
foo
This should be a code block, though: bc.
foo
As should this: bc.
foo
Now, nested:
foo
This should just be an HTML comment: Multiline: Code block: bc. Just plain comment, with trailing spaces on the line: Code: bc.
Hr's:









h1(#inline-markup). Inline Markup This is _emphasized_, and so _is this_. This is *strong*, and so *is this*. An _"emphasized link":/url_. *_This is strong and em._* So is *_this_* word. *_This is strong and em._* So is *_this_* word. This is code: @>@, @$@, @\@, @\$@, @@. -This is _strikeout_.- Superscripts: a[^bc^]d a[^_hello_^] a[^hello there^]. Subscripts: H[~2~]O, H[~23~]O, H[~many of them~]O. These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.
h1(#smart-quotes-ellipses-dashes). Smart quotes, ellipses, dashes "Hello," said the spider. "'Shelob' is my name." 'A', 'B', and 'C' are letters. 'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.' 'He said, "I want to go."' Were you alive in the 70's? Here is some quoted '@code@' and a ""quoted link":http://example.com/?foo=1&bar=2". Some dashes: one -- two -- three -- four -- five. Dashes between numbers: 5 - 7, 255 - 66, 1987 - 1999. Ellipses...and...and....
h1(#latex). LaTeX * * 2+2=4 * x \in y * \alpha \wedge \omega * 223 * p-Tree * Here's some display math: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h} * Here's one that has a line break in it: \alpha + \omega \times x^2. These shouldn't be math: * To get the famous equation, write @$e = mc^2$@. * $22,000 is a _lot_ of money. So is $34,000. (It worked if "lot" is emphasized.) * Shoes ($20) and socks ($5). * Escaped @$@: $73 _this should be emphasized_ 23$. Here's a LaTeX table:
h1(#special-characters). Special Characters Here is some unicode: * I hat: Î * o umlaut: ö * section: § * set membership: ∈ * copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 < 5. 6 > 5. Backslash: \ Backtick: ` Asterisk: * Underscore: _ Left brace: { Right brace: } Left bracket: [ Right bracket: ] Left paren: ( Right paren: ) Greater-than: > Hash: # Period: . Bang: ! Plus: + Minus: -
h1(#links). Links h2(#explicit). Explicit Just a "URL":/url/. "URL and title":/url/. "URL and title":/url/. "URL and title":/url/. "URL and title":/url/ "URL and title":/url/ "with_underscore":/url/with_underscore "Email link":mailto:nobody@nowhere.net "Empty":. h2(#reference). Reference Foo "bar":/url/. Foo "bar":/url/. Foo "bar":/url/. With "embedded [brackets]":/url/. "b":/url/ by itself should be a link. Indented "once":/url. Indented "twice":/url. Indented "thrice":/url. This should [not][] be a link. bc. [not]: /url Foo "bar":/url/. Foo "biz":/url/. h2(#with-ampersands). With ampersands Here's a "link with an ampersand in the URL":http://example.com/?foo=1&bar=2. Here's a link with an amersand in the link text: "AT&T":http://att.com/. Here's an "inline link":/script?foo=1&bar=2. Here's an "inline link in pointy braces":/script?foo=1&bar=2. h2(#autolinks). Autolinks With an ampersand: "$":http://example.com/?foo=1&bar=2 * In a list? * "$":http://example.com/ * It should. An e-mail address: "nobody@nowhere.net":mailto:nobody@nowhere.net bq. Blockquoted: "$":http://example.com/ Auto-links should not occur here: @@ bc. or here:
h1(#images). Images From "Voyage dans la Lune" by Georges Melies (1902): !lalune.jpg(Voyage dans la Lune)! lalune Here is a movie !movie.jpg(movie)! icon.
h1(#footnotes). Footnotes Here is a footnote reference,[1] and another.[2] This should _not_ be a footnote reference, because it contains a space.[^my note] Here is an inline note.[3] bq. Notes can go in quotes.[4] # And in list items.[5] This paragraph should not be part of the note, as it is not indented. fn1. Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. fn2. Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). bc. { } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. fn3. This is _easier_ to type. Inline notes may contain "links":http://google.com and @]@ verbatim characters, as well as [bracketed text]. fn4. In quote. fn5. In list. pandoc-1.12.2.1/tests/Tests/Arbitrary.hs000644 000765 000024 00000017775 12251233602 017674 0ustar00jgmstaff000000 000000 {-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables #-} -- provides Arbitrary instance for Pandoc types module Tests.Arbitrary () where import Test.QuickCheck.Gen import Test.QuickCheck.Arbitrary import Control.Monad (liftM, liftM2) import Text.Pandoc.Definition import Text.Pandoc.Shared (normalize, escapeURI) import Text.Pandoc.Builder realString :: Gen String realString = resize 8 $ listOf $ frequency [ (9, elements [' '..'\127']) , (1, elements ['\128'..'\9999']) ] arbAttr :: Gen Attr arbAttr = do id' <- elements ["","loc"] classes <- elements [[],["haskell"],["c","numberLines"]] keyvals <- elements [[],[("start","22")],[("a","11"),("b_2","a b c")]] return (id',classes,keyvals) instance Arbitrary Inlines where arbitrary = liftM (fromList :: [Inline] -> Inlines) arbitrary instance Arbitrary Blocks where arbitrary = liftM (fromList :: [Block] -> Blocks) arbitrary instance Arbitrary Inline where arbitrary = resize 3 $ arbInline 2 arbInlines :: Int -> Gen [Inline] arbInlines n = listOf1 (arbInline n) `suchThat` (not . startsWithSpace) where startsWithSpace (Space:_) = True startsWithSpace _ = False -- restrict to 3 levels of nesting max; otherwise we get -- bogged down in indefinitely large structures arbInline :: Int -> Gen Inline arbInline n = frequency $ [ (60, liftM Str realString) , (60, return Space) , (10, liftM2 Code arbAttr realString) , (5, elements [ RawInline (Format "html") "" , RawInline (Format "latex") "\\my{command}" ]) ] ++ [ x | x <- nesters, n > 1] where nesters = [ (10, liftM Emph $ arbInlines (n-1)) , (10, liftM Strong $ arbInlines (n-1)) , (10, liftM Strikeout $ arbInlines (n-1)) , (10, liftM Superscript $ arbInlines (n-1)) , (10, liftM Subscript $ arbInlines (n-1)) -- , (10, liftM SmallCaps $ arbInlines (n-1)) , (10, do x1 <- arbitrary x2 <- arbInlines (n-1) return $ Quoted x1 x2) , (10, do x1 <- arbitrary x2 <- realString return $ Math x1 x2) , (10, do x1 <- arbInlines (n-1) x3 <- realString x2 <- liftM escapeURI realString return $ Link x1 (x2,x3)) , (10, do x1 <- arbInlines (n-1) x3 <- realString x2 <- liftM escapeURI realString return $ Image x1 (x2,x3)) , (2, liftM Note $ resize 3 $ listOf1 $ arbBlock (n-1)) ] instance Arbitrary Block where arbitrary = resize 3 $ arbBlock 2 arbBlock :: Int -> Gen Block arbBlock n = frequency $ [ (10, liftM Plain $ arbInlines (n-1)) , (15, liftM Para $ arbInlines (n-1)) , (5, liftM2 CodeBlock arbAttr realString) , (2, elements [ RawBlock (Format "html") "
\n*&*\n
" , RawBlock (Format "latex") "\\begin[opt]{env}\nhi\n{\\end{env}" ]) , (5, do x1 <- choose (1 :: Int, 6) x2 <- arbInlines (n-1) return (Header x1 nullAttr x2)) , (2, return HorizontalRule) ] ++ [x | x <- nesters, n > 0] where nesters = [ (5, liftM BlockQuote $ listOf1 $ arbBlock (n-1)) , (5, do x2 <- arbitrary x3 <- arbitrary x1 <- arbitrary `suchThat` (> 0) x4 <- listOf1 $ listOf1 $ arbBlock (n-1) return $ OrderedList (x1,x2,x3) x4 ) , (5, liftM BulletList $ (listOf1 $ listOf1 $ arbBlock (n-1))) , (5, do items <- listOf1 $ do x1 <- listOf1 $ listOf1 $ arbBlock (n-1) x2 <- arbInlines (n-1) return (x2,x1) return $ DefinitionList items) , (2, do rs <- choose (1 :: Int, 4) cs <- choose (1 :: Int, 4) x1 <- arbInlines (n-1) x2 <- vector cs x3 <- vectorOf cs $ elements [0, 0.25] x4 <- vectorOf cs $ listOf $ arbBlock (n-1) x5 <- vectorOf rs $ vectorOf cs $ listOf $ arbBlock (n-1) return (Table x1 x2 x3 x4 x5)) ] instance Arbitrary Pandoc where arbitrary = resize 8 $ liftM normalize $ liftM2 Pandoc arbitrary arbitrary {- instance Arbitrary CitationMode where arbitrary = do x <- choose (0 :: Int, 2) case x of 0 -> return AuthorInText 1 -> return SuppressAuthor 2 -> return NormalCitation _ -> error "FATAL ERROR: Arbitrary instance, logic bug" instance Arbitrary Citation where arbitrary = do x1 <- liftM (filter (`notElem` ",;]@ \t\n")) arbitrary x2 <- arbitrary x3 <- arbitrary x4 <- arbitrary x5 <- arbitrary x6 <- arbitrary return (Citation x1 x2 x3 x4 x5 x6) -} instance Arbitrary MathType where arbitrary = do x <- choose (0 :: Int, 1) case x of 0 -> return DisplayMath 1 -> return InlineMath _ -> error "FATAL ERROR: Arbitrary instance, logic bug" instance Arbitrary QuoteType where arbitrary = do x <- choose (0 :: Int, 1) case x of 0 -> return SingleQuote 1 -> return DoubleQuote _ -> error "FATAL ERROR: Arbitrary instance, logic bug" instance Arbitrary Meta where arbitrary = do (x1 :: Inlines) <- arbitrary (x2 :: [Inlines]) <- liftM (filter (not . isNull)) arbitrary (x3 :: Inlines) <- arbitrary return $ setMeta "title" x1 $ setMeta "author" x2 $ setMeta "date" x3 $ nullMeta instance Arbitrary Alignment where arbitrary = do x <- choose (0 :: Int, 3) case x of 0 -> return AlignLeft 1 -> return AlignRight 2 -> return AlignCenter 3 -> return AlignDefault _ -> error "FATAL ERROR: Arbitrary instance, logic bug" instance Arbitrary ListNumberStyle where arbitrary = do x <- choose (0 :: Int, 6) case x of 0 -> return DefaultStyle 1 -> return Example 2 -> return Decimal 3 -> return LowerRoman 4 -> return UpperRoman 5 -> return LowerAlpha 6 -> return UpperAlpha _ -> error "FATAL ERROR: Arbitrary instance, logic bug" instance Arbitrary ListNumberDelim where arbitrary = do x <- choose (0 :: Int, 3) case x of 0 -> return DefaultDelim 1 -> return Period 2 -> return OneParen 3 -> return TwoParens _ -> error "FATAL ERROR: Arbitrary instance, logic bug" pandoc-1.12.2.1/tests/Tests/Helpers.hs000644 000765 000024 00000004734 12251233602 017326 0ustar00jgmstaff000000 000000 {-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} -- Utility functions for the test suite. module Tests.Helpers ( test , (=?>) , property , ToString(..) , ToPandoc(..) ) where import Text.Pandoc.Definition import Text.Pandoc.Builder (Inlines, Blocks, doc, plain) import Test.Framework import Test.Framework.Providers.HUnit import Test.Framework.Providers.QuickCheck2 import Test.HUnit (assertBool) import Text.Pandoc.Shared (normalize, trimr) import Text.Pandoc.Options import Text.Pandoc.Writers.Native (writeNative) import qualified Test.QuickCheck.Property as QP import Data.Algorithm.Diff import qualified Data.Map as M test :: (ToString a, ToString b, ToString c) => (a -> b) -- ^ function to test -> String -- ^ name of test case -> (a, c) -- ^ (input, expected value) -> Test test fn name (input, expected) = testCase name $ assertBool msg (actual' == expected') where msg = nl ++ dashes "input" ++ nl ++ input' ++ nl ++ dashes "result" ++ nl ++ unlines (map vividize diff) ++ dashes "" nl = "\n" input' = toString input actual' = lines $ toString $ fn input expected' = lines $ toString expected diff = getDiff expected' actual' dashes "" = replicate 72 '-' dashes x = replicate (72 - length x - 5) '-' ++ " " ++ x ++ " ---" vividize :: Diff String -> String vividize (Both s _) = " " ++ s vividize (First s) = "- " ++ s vividize (Second s) = "+ " ++ s property :: QP.Testable a => TestName -> a -> Test property = testProperty infix 5 =?> (=?>) :: a -> b -> (a,b) x =?> y = (x, y) class ToString a where toString :: a -> String instance ToString Pandoc where toString d = writeNative def{ writerStandalone = s } $ toPandoc d where s = case d of (Pandoc (Meta m) _) | M.null m -> False | otherwise -> True instance ToString Blocks where toString = writeNative def . toPandoc instance ToString Inlines where toString = trimr . writeNative def . toPandoc instance ToString String where toString = id class ToPandoc a where toPandoc :: a -> Pandoc instance ToPandoc Pandoc where toPandoc = normalize instance ToPandoc Blocks where toPandoc = normalize . doc instance ToPandoc Inlines where toPandoc = normalize . doc . plain pandoc-1.12.2.1/tests/Tests/Old.hs000644 000765 000024 00000023466 12251233602 016445 0ustar00jgmstaff000000 000000 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 ( (), (<.>) ) import System.Directory import System.Exit import Data.Algorithm.Diff import Text.Pandoc.Shared ( normalize ) import Text.Pandoc.Options import Text.Pandoc.Writers.Native ( writeNative ) import Text.Pandoc.Readers.Native ( readNative ) import Prelude hiding ( readFile ) import qualified Data.ByteString.Lazy as B import Text.Pandoc.UTF8 (toStringLazy) import Text.Printf readFileUTF8 :: FilePath -> IO String readFileUTF8 f = B.readFile f >>= return . toStringLazy data TestResult = TestPassed | TestError ExitCode | TestFailed String FilePath [Diff String] deriving (Eq) instance Show TestResult where show TestPassed = "PASSED" show (TestError ec) = "ERROR " ++ show ec show (TestFailed cmd file d) = '\n' : dash ++ "\n--- " ++ file ++ "\n+++ " ++ cmd ++ "\n" ++ showDiff (1,1) d ++ dash where dash = replicate 72 '-' showDiff :: (Int,Int) -> [Diff String] -> String showDiff _ [] = "" showDiff (l,r) (First ln : ds) = printf "+%4d " l ++ ln ++ "\n" ++ showDiff (l+1,r) ds showDiff (l,r) (Second ln : ds) = printf "-%4d " r ++ ln ++ "\n" ++ showDiff (l,r+1) ds showDiff (l,r) (Both _ _ : ds) = showDiff (l+1,r+1) ds tests :: [Test] tests = [ testGroup "markdown" [ testGroup "writer" $ writerTests "markdown" ++ lhsWriterTests "markdown" , testGroup "reader" [ test "basic" ["-r", "markdown", "-w", "native", "-s", "-S"] "testsuite.txt" "testsuite.native" , test "tables" ["-r", "markdown", "-w", "native", "--columns=80"] "tables.txt" "tables.native" , test "pipe tables" ["-r", "markdown", "-w", "native", "--columns=80"] "pipe-tables.txt" "pipe-tables.native" , test "more" ["-r", "markdown", "-w", "native", "-S"] "markdown-reader-more.txt" "markdown-reader-more.native" , lhsReaderTest "markdown+lhs" ] , testGroup "citations" [ test "citations" ["-r", "markdown", "-w", "native"] "markdown-citations.txt" "markdown-citations.native" ] ] , testGroup "rst" [ testGroup "writer" (writerTests "rst" ++ lhsWriterTests "rst") , testGroup "reader" [ test "basic" ["-r", "rst", "-w", "native", "-s", "-S", "--columns=80"] "rst-reader.rst" "rst-reader.native" , test "tables" ["-r", "rst", "-w", "native", "--columns=80"] "tables.rst" "tables-rstsubset.native" , lhsReaderTest "rst+lhs" ] ] , testGroup "latex" [ testGroup "writer" (writerTests "latex" ++ lhsWriterTests "latex") , testGroup "reader" [ test "basic" ["-r", "latex", "-w", "native", "-s", "-R"] "latex-reader.latex" "latex-reader.native" , lhsReaderTest "latex+lhs" ] ] , testGroup "html" [ testGroup "writer" (writerTests "html" ++ lhsWriterTests "html") , test "reader" ["-r", "html", "-w", "native", "-s"] "html-reader.html" "html-reader.native" ] , testGroup "s5" [ s5WriterTest "basic" ["-s"] "s5" , s5WriterTest "fancy" ["-s","-m","-i"] "s5" , s5WriterTest "fragment" [] "html" , s5WriterTest "inserts" ["-s", "-H", "insert", "-B", "insert", "-A", "insert", "-c", "main.css"] "html" ] , testGroup "textile" [ testGroup "writer" $ writerTests "textile" , test "reader" ["-r", "textile", "-w", "native", "-s"] "textile-reader.textile" "textile-reader.native" ] , testGroup "docbook" [ testGroup "writer" $ writerTests "docbook" , test "reader" ["-r", "docbook", "-w", "native", "-s"] "docbook-reader.docbook" "docbook-reader.native" ] , testGroup "native" [ testGroup "writer" $ writerTests "native" , test "reader" ["-r", "native", "-w", "native", "-s"] "testsuite.native" "testsuite.native" ] , testGroup "fb2" [ fb2WriterTest "basic" [] "fb2.basic.markdown" "fb2.basic.fb2" , fb2WriterTest "titles" [] "fb2.titles.markdown" "fb2.titles.fb2" , fb2WriterTest "images" [] "fb2.images.markdown" "fb2.images.fb2" , fb2WriterTest "images-embedded" [] "fb2.images-embedded.html" "fb2.images-embedded.fb2" , fb2WriterTest "tables" [] "tables.native" "tables.fb2" , fb2WriterTest "math" [] "fb2.math.markdown" "fb2.math.fb2" , fb2WriterTest "testsuite" [] "testsuite.native" "writer.fb2" ] , testGroup "mediawiki" [ testGroup "writer" $ writerTests "mediawiki" , test "reader" ["-r", "mediawiki", "-w", "native", "-s"] "mediawiki-reader.wiki" "mediawiki-reader.native" ] , testGroup "opml" [ test "basic" ["-r", "native", "-w", "opml", "--columns=78", "-s"] "testsuite.native" "writer.opml" , test "reader" ["-r", "opml", "-w", "native", "-s"] "opml-reader.opml" "opml-reader.native" ] , testGroup "haddock" [ test "reader" ["-r", "haddock", "-w", "native", "-s"] "haddock-reader.haddock" "haddock-reader.native" ] , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f) [ "opendocument" , "context" , "texinfo" , "man" , "plain" , "rtf", "org", "asciidoc" ] ] -- makes sure file is fully closed after reading readFile' :: FilePath -> IO String readFile' f = do s <- readFileUTF8 f return $! (length s `seq` s) lhsWriterTests :: String -> [Test] lhsWriterTests format = [ t "lhs to normal" format , t "lhs to lhs" (format ++ "+lhs") ] where t n f = test n ["--columns=78", "-r", "native", "-s", "-w", f] "lhs-test.native" ("lhs-test" <.> f) lhsReaderTest :: String -> Test lhsReaderTest format = testWithNormalize normalizer "lhs" ["-r", format, "-w", "native"] ("lhs-test" <.> format) norm where normalizer = writeNative def . normalize . readNative norm = if format == "markdown+lhs" then "lhs-test-markdown.native" else "lhs-test.native" writerTests :: String -> [Test] writerTests format = [ test "basic" (opts ++ ["-s"]) "testsuite.native" ("writer" <.> format) , test "tables" opts "tables.native" ("tables" <.> format) ] where opts = ["-r", "native", "-w", format, "--columns=78"] s5WriterTest :: String -> [String] -> String -> Test s5WriterTest modifier opts format = test (format ++ " writer (" ++ modifier ++ ")") (["-r", "native", "-w", format] ++ opts) "s5.native" ("s5." ++ modifier <.> "html") fb2WriterTest :: String -> [String] -> String -> String -> Test fb2WriterTest title opts inputfile normfile = testWithNormalize (ignoreBinary . formatXML) title (["-t", "fb2"]++opts) inputfile normfile where formatXML xml = splitTags $ zip xml (drop 1 xml) splitTags [] = [] splitTags [end] = fst end : snd end : [] splitTags (('>','<'):rest) = ">\n" ++ splitTags rest splitTags ((c,_):rest) = c : splitTags rest ignoreBinary = unlines . filter (not . startsWith " [String] -- ^ Options to pass to pandoc -> String -- ^ Input filepath -> FilePath -- ^ Norm (for test results) filepath -> Test test = testWithNormalize id -- | Run a test with normalize function, return True if test passed. testWithNormalize :: (String -> String) -- ^ Normalize function for output -> String -- ^ Title of test -> [String] -- ^ Options to pass to pandoc -> String -- ^ Input filepath -> 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 let options = ["--data-dir", ".." "data"] ++ [inpPath] ++ opts let cmd = pandocPath ++ " " ++ unwords options ph <- runProcess pandocPath options Nothing (Just [("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./")]) Nothing (Just hOut) (Just stderr) ec <- waitForProcess ph result <- if ec == ExitSuccess then do -- filter \r so the tests will work on Windows machines outputContents <- readFile' outputPath >>= return . filter (/='\r') . normalizer normContents <- readFile' normPath >>= return . filter (/='\r') . normalizer if outputContents == normContents then return TestPassed else return $ TestFailed cmd normPath $ getDiff (lines outputContents) (lines normContents) else return $ TestError ec removeFile outputPath assertBool (show result) (result == TestPassed) pandoc-1.12.2.1/tests/Tests/Readers/000755 000765 000024 00000000000 12251233602 016745 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/tests/Tests/Shared.hs000644 000765 000024 00000001526 12251233602 017126 0ustar00jgmstaff000000 000000 module Tests.Shared (tests) where import Text.Pandoc.Definition import Text.Pandoc.Shared import Test.Framework import Tests.Helpers import Tests.Arbitrary() tests :: [Test] tests = [ testGroup "normalize" [ property "p_normalize_blocks_rt" p_normalize_blocks_rt , property "p_normalize_inlines_rt" p_normalize_inlines_rt , property "p_normalize_no_trailing_spaces" p_normalize_no_trailing_spaces ] ] p_normalize_blocks_rt :: [Block] -> Bool p_normalize_blocks_rt bs = normalize bs == normalize (normalize bs) p_normalize_inlines_rt :: [Inline] -> Bool p_normalize_inlines_rt ils = normalize ils == normalize (normalize ils) p_normalize_no_trailing_spaces :: [Inline] -> Bool p_normalize_no_trailing_spaces ils = null ils' || last ils' /= Space where ils' = normalize $ ils ++ [Space] pandoc-1.12.2.1/tests/Tests/Walk.hs000644 000765 000024 00000002506 12251233602 016615 0ustar00jgmstaff000000 000000 {-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-} module Tests.Walk (tests) where import Text.Pandoc.Definition import Text.Pandoc.Walk import Test.Framework import Tests.Helpers import Data.Char (toUpper) import Tests.Arbitrary() import Data.Generics import Data.Monoid tests :: [Test] tests = [ testGroup "Walk" [ property "p_walk inlineTrans" (p_walk inlineTrans) , property "p_walk blockTrans" (p_walk blockTrans) , property "p_query inlineQuery" (p_query inlineQuery) , property "p_query blockQuery" (p_query blockQuery) ] ] p_walk :: (Typeable a, Walkable a Pandoc) => (a -> a) -> Pandoc -> Bool p_walk f = (\(d :: Pandoc) -> 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) inlineTrans :: Inline -> Inline inlineTrans (Str xs) = Str $ map toUpper xs inlineTrans (Emph xs) = Strong xs inlineTrans x = x blockTrans :: Block -> Block blockTrans (Plain xs) = Para xs blockTrans (BlockQuote xs) = Div ("",["special"],[]) xs blockTrans x = x inlineQuery :: Inline -> String inlineQuery (Str xs) = xs inlineQuery _ = "" blockQuery :: Block -> [Int] blockQuery (Header lev _ _) = [lev] blockQuery _ = [] pandoc-1.12.2.1/tests/Tests/Writers/000755 000765 000024 00000000000 12251233602 017017 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/tests/Tests/Writers/ConTeXt.hs000644 000765 000024 00000003721 12251233602 020702 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.ConTeXt (tests) where import Test.Framework import Text.Pandoc.Builder import Text.Pandoc import Tests.Helpers import Tests.Arbitrary() context :: (ToString a, ToPandoc a) => a -> String context = writeConTeXt def . toPandoc context' :: (ToString a, ToPandoc a) => a -> String context' = writeConTeXt def{ writerWrapText = False } . toPandoc {- "my test" =: X =?> Y is shorthand for test context "my test" $ X =?> Y which is in turn shorthand for test context "my test" (X,Y) -} infix 4 =: (=:) :: (ToString a, ToPandoc a) => String -> (a, String) -> Test (=:) = test context tests :: [Test] tests = [ testGroup "inline code" [ "with '}'" =: code "}" =?> "\\mono{\\}}" , "without '}'" =: code "]" =?> "\\type{]}" , property "code property" $ \s -> null s || if '{' `elem` s || '}' `elem` s then (context' $ code s) == "\\mono{" ++ (context' $ str s) ++ "}" else (context' $ code s) == "\\type{" ++ s ++ "}" ] , testGroup "headers" [ "level 1" =: headerWith ("my-header",[],[]) 1 "My header" =?> "\\section[my-header]{My header}" ] , testGroup "bullet lists" [ "nested" =: bulletList [ plain (text "top") <> bulletList [ plain (text "next") <> bulletList [plain (text "bot")] ] ] =?> unlines [ "\\startitemize[packed]" , "\\item" , " top" , " \\startitemize[packed]" , " \\item" , " next" , " \\startitemize[packed]" , " \\item" , " bot" , " \\stopitemize" , " \\stopitemize" , "\\stopitemize" ] ] ] pandoc-1.12.2.1/tests/Tests/Writers/HTML.hs000644 000765 000024 00000002153 12251233602 020120 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.HTML (tests) where import Test.Framework import Text.Pandoc.Builder import Text.Pandoc import Tests.Helpers import Tests.Arbitrary() html :: (ToString a, ToPandoc a) => a -> String html = writeHtmlString def{ writerWrapText = False } . toPandoc {- "my test" =: X =?> Y is shorthand for test html "my test" $ X =?> Y which is in turn shorthand for test html "my test" (X,Y) -} infix 4 =: (=:) :: (ToString a, ToPandoc a) => String -> (a, String) -> Test (=:) = test html tests :: [Test] tests = [ testGroup "inline code" [ "basic" =: code "@&" =?> "@&" , "haskell" =: codeWith ("",["haskell"],[]) ">>=" =?> ">>=" , "nolanguage" =: codeWith ("",["nolanguage"],[]) ">>=" =?> ">>=" ] , testGroup "images" [ "alt with formatting" =: image "/url" "title" ("my " <> emph "image") =?> "\"my" ] ] pandoc-1.12.2.1/tests/Tests/Writers/LaTeX.hs000644 000765 000024 00000003566 12251233602 020342 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.LaTeX (tests) where import Test.Framework import Text.Pandoc.Builder import Text.Pandoc import Tests.Helpers import Tests.Arbitrary() latex :: (ToString a, ToPandoc a) => a -> String latex = writeLaTeX def . toPandoc latexListing :: (ToString a, ToPandoc a) => a -> String latexListing = writeLaTeX def{ writerListings = True } . toPandoc {- "my test" =: X =?> Y is shorthand for test latex "my test" $ X =?> Y which is in turn shorthand for test latex "my test" (X,Y) -} infix 4 =: (=:) :: (ToString a, ToPandoc a) => String -> (a, String) -> Test (=:) = test latex tests :: [Test] tests = [ testGroup "code blocks" [ "in footnotes" =: note (para "hi" <> codeBlock "hi") =?> "\\footnote{hi\n\n\\begin{Verbatim}\nhi\n\\end{Verbatim}\n}" , test latexListing "identifier" $ codeBlockWith ("id",[],[]) "hi" =?> ("\\begin{lstlisting}[label=id]\nhi\n\\end{lstlisting}" :: String) , 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\\}}$" ] , testGroup "headers" [ "unnumbered header" =: headerWith ("foo",["unnumbered"],[]) 1 (text "Header 1" <> note (plain $ text "note")) =?> "\\section*{Header 1\\footnote{note}}\\label{foo}\n\\addcontentsline{toc}{section}{Header 1}\n" ] ] pandoc-1.12.2.1/tests/Tests/Writers/Markdown.hs000644 000765 000024 00000001664 12251233602 021144 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} module Tests.Writers.Markdown (tests) where import Test.Framework import Text.Pandoc.Builder import Text.Pandoc import Tests.Helpers import Tests.Arbitrary() markdown :: (ToString a, ToPandoc a) => a -> String markdown = writeMarkdown def . toPandoc {- "my test" =: X =?> Y is shorthand for test markdown "my test" $ X =?> Y which is in turn shorthand for test markdown "my test" (X,Y) -} infix 4 =: (=:) :: (ToString a, ToPandoc a) => String -> (a, String) -> Test (=:) = test markdown 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" ] pandoc-1.12.2.1/tests/Tests/Writers/Native.hs000644 000765 000024 00000001011 12251233602 020572 0ustar00jgmstaff000000 000000 module Tests.Writers.Native (tests) where import Test.Framework import Text.Pandoc.Builder import Text.Pandoc import Tests.Helpers import Tests.Arbitrary() p_write_rt :: Pandoc -> Bool p_write_rt d = read (writeNative def{ writerStandalone = True } d) == d p_write_blocks_rt :: [Block] -> Bool p_write_blocks_rt bs = length bs > 20 || read (writeNative def (Pandoc nullMeta bs)) == bs tests :: [Test] tests = [ property "p_write_rt" p_write_rt , property "p_write_blocks_rt" p_write_blocks_rt ] pandoc-1.12.2.1/tests/Tests/Readers/LaTeX.hs000644 000765 000024 00000022155 12251233602 020263 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} module Tests.Readers.LaTeX (tests) where import Text.Pandoc.Definition import Test.Framework import Tests.Helpers import Tests.Arbitrary() import Text.Pandoc.Builder import Text.Pandoc latex :: String -> Pandoc latex = readLaTeX def infix 4 =: (=:) :: ToString c => String -> (String, c) -> Test (=:) = test latex tests :: [Test] tests = [ testGroup "basic" [ "simple" =: "word" =?> para "word" , "space" =: "some text" =?> para ("some text") , "emphasized" =: "\\emph{emphasized}" =?> para (emph "emphasized") ] , testGroup "headers" [ "level 1" =: "\\section{header}" =?> headerWith ("header",[],[]) 1 "header" , "level 2" =: "\\subsection{header}" =?> headerWith ("header",[],[]) 2 "header" , "level 3" =: "\\subsubsection{header}" =?> headerWith ("header",[],[]) 3 "header" , "emph" =: "\\section{text \\emph{emph}}" =?> headerWith ("text-emph",[],[]) 1 ("text" <> space <> emph "emph") , "link" =: "\\section{text \\href{/url}{link}}" =?> headerWith ("text-link",[],[]) 1 ("text" <> space <> link "/url" "" "link") ] , testGroup "math" [ "escaped $" =: "$x=\\$4$" =?> para (math "x=\\$4") ] , testGroup "space and comments" [ "blank lines + space at beginning" =: "\n \n hi" =?> para "hi" , "blank lines + space + comments" =: "% my comment\n\n \n % another\n\nhi" =?> para "hi" , "comment in paragraph" =: "hi % this is a comment\nthere\n" =?> para "hi there" ] , testGroup "code blocks" [ "identifier" =: "\\begin{lstlisting}[label=test]\\end{lstlisting}" =?> codeBlockWith ("test", [], [("label","test")]) "" , "no identifier" =: "\\begin{lstlisting}\\end{lstlisting}" =?> codeBlock "" ] , testGroup "citations" [ natbibCitations , biblatexCitations ] ] baseCitation :: Citation baseCitation = Citation{ citationId = "item1" , citationPrefix = [] , citationSuffix = [] , citationMode = AuthorInText , citationNoteNum = 0 , citationHash = 0 } rt :: String -> Inlines rt = rawInline "latex" natbibCitations :: Test natbibCitations = testGroup "natbib" [ "citet" =: "\\citet{item1}" =?> para (cite [baseCitation] (rt "\\citet{item1}")) , "suffix" =: "\\citet[p.~30]{item1}" =?> para (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30" }] (rt "\\citet[p.~30]{item1}")) , "suffix long" =: "\\citet[p.~30, with suffix]{item1}" =?> para (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30, with suffix" }] (rt "\\citet[p.~30, with suffix]{item1}")) , "multiple" =: "\\citeauthor{item1} \\citetext{\\citeyear{item1}; \\citeyear[p.~30]{item2}; \\citealp[see also][]{item3}}" =?> para (cite [baseCitation{ citationMode = AuthorInText } ,baseCitation{ citationMode = SuppressAuthor , citationSuffix = [Str "p.\160\&30"] , citationId = "item2" } ,baseCitation{ citationId = "item3" , citationPrefix = [Str "see",Space,Str "also"] , citationMode = NormalCitation } ] (rt "\\citetext{\\citeyear{item1}; \\citeyear[p.~30]{item2}; \\citealp[see also][]{item3}}")) , "group" =: "\\citetext{\\citealp[see][p.~34--35]{item1}; \\citealp[also][chap. 3]{item3}}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationPrefix = [Str "see"] , citationSuffix = [Str "p.\160\&34\8211\&35"] } ,baseCitation{ citationMode = NormalCitation , citationId = "item3" , citationPrefix = [Str "also"] , citationSuffix = [Str "chap.",Space,Str "3"] } ] (rt "\\citetext{\\citealp[see][p.~34--35]{item1}; \\citealp[also][chap. 3]{item3}}")) , "suffix and locator" =: "\\citep[pp.~33, 35--37, and nowhere else]{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationSuffix = [Str "pp.\160\&33,",Space,Str "35\8211\&37,",Space,Str "and",Space,Str "nowhere",Space, Str "else"] }] (rt "\\citep[pp.~33, 35--37, and nowhere else]{item1}")) , "suffix only" =: "\\citep[and nowhere else]{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationSuffix = toList $ text "and nowhere else" }] (rt "\\citep[and nowhere else]{item1}")) , "no author" =: "\\citeyearpar{item1}, and now Doe with a locator \\citeyearpar[p.~44]{item2}" =?> para (cite [baseCitation{ citationMode = SuppressAuthor }] (rt "\\citeyearpar{item1}") <> text ", and now Doe with a locator " <> cite [baseCitation{ citationMode = SuppressAuthor , citationSuffix = [Str "p.\160\&44"] , citationId = "item2" }] (rt "\\citeyearpar[p.~44]{item2}")) , "markup" =: "\\citep[\\emph{see}][p. \\textbf{32}]{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationPrefix = [Emph [Str "see"]] , citationSuffix = [Str "p.",Space, Strong [Str "32"]] }] (rt "\\citep[\\emph{see}][p. \\textbf{32}]{item1}")) ] biblatexCitations :: Test biblatexCitations = testGroup "biblatex" [ "textcite" =: "\\textcite{item1}" =?> para (cite [baseCitation] (rt "\\textcite{item1}")) , "suffix" =: "\\textcite[p.~30]{item1}" =?> para (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30" }] (rt "\\textcite[p.~30]{item1}")) , "suffix long" =: "\\textcite[p.~30, with suffix]{item1}" =?> para (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30, with suffix" }] (rt "\\textcite[p.~30, with suffix]{item1}")) , "multiple" =: "\\textcites{item1}[p.~30]{item2}[see also][]{item3}" =?> para (cite [baseCitation{ citationMode = AuthorInText } ,baseCitation{ citationMode = NormalCitation , citationSuffix = [Str "p.\160\&30"] , citationId = "item2" } ,baseCitation{ citationId = "item3" , citationPrefix = [Str "see",Space,Str "also"] , citationMode = NormalCitation } ] (rt "\\textcites{item1}[p.~30]{item2}[see also][]{item3}")) , "group" =: "\\autocites[see][p.~34--35]{item1}[also][chap. 3]{item3}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationPrefix = [Str "see"] , citationSuffix = [Str "p.\160\&34\8211\&35"] } ,baseCitation{ citationMode = NormalCitation , citationId = "item3" , citationPrefix = [Str "also"] , citationSuffix = [Str "chap.",Space,Str "3"] } ] (rt "\\autocites[see][p.~34--35]{item1}[also][chap. 3]{item3}")) , "suffix and locator" =: "\\autocite[pp.~33, 35--37, and nowhere else]{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationSuffix = [Str "pp.\160\&33,",Space,Str "35\8211\&37,",Space,Str "and",Space,Str "nowhere",Space, Str "else"] }] (rt "\\autocite[pp.~33, 35--37, and nowhere else]{item1}")) , "suffix only" =: "\\autocite[and nowhere else]{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationSuffix = toList $ text "and nowhere else" }] (rt "\\autocite[and nowhere else]{item1}")) , "no author" =: "\\autocite*{item1}, and now Doe with a locator \\autocite*[p.~44]{item2}" =?> para (cite [baseCitation{ citationMode = SuppressAuthor }] (rt "\\autocite*{item1}") <> text ", and now Doe with a locator " <> cite [baseCitation{ citationMode = SuppressAuthor , citationSuffix = [Str "p.\160\&44"] , citationId = "item2" }] (rt "\\autocite*[p.~44]{item2}")) , "markup" =: "\\autocite[\\emph{see}][p. \\textbf{32}]{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation , citationPrefix = [Emph [Str "see"]] , citationSuffix = [Str "p.",Space, Strong [Str "32"]] }] (rt "\\autocite[\\emph{see}][p. \\textbf{32}]{item1}")) , "parencite" =: "\\parencite{item1}" =?> para (cite [baseCitation{ citationMode = NormalCitation }] (rt "\\parencite{item1}")) ] pandoc-1.12.2.1/tests/Tests/Readers/Markdown.hs000644 000765 000024 00000024102 12251233602 021062 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} module Tests.Readers.Markdown (tests) where import Text.Pandoc.Definition import Test.Framework import Tests.Helpers import Tests.Arbitrary() import Text.Pandoc.Builder import qualified Data.Set as Set -- import Text.Pandoc.Shared ( normalize ) import Text.Pandoc markdown :: String -> Pandoc markdown = readMarkdown def markdownSmart :: String -> Pandoc markdownSmart = readMarkdown def { readerSmart = True } infix 4 =: (=:) :: ToString c => String -> (String, c) -> Test (=:) = test markdown testBareLink :: (String, Inlines) -> Test testBareLink (inp, ils) = test (readMarkdown def{ readerExtensions = Set.fromList [Ext_autolink_bare_uris, Ext_raw_html] }) inp (inp, doc $ para ils) autolink :: String -> Inlines autolink s = link s "" (str s) bareLinkTests :: [(String, Inlines)] bareLinkTests = [ ("http://google.com is a search engine.", autolink "http://google.com" <> " is a search engine.") , ("
http://foo.bar.baz", rawInline "html" "" <> "http://foo.bar.baz" <> rawInline "html" "") , ("Try this query: http://google.com?search=fish&time=hour.", "Try this query: " <> autolink "http://google.com?search=fish&time=hour" <> ".") , ("HTTPS://GOOGLE.COM,", autolink "HTTPS://GOOGLE.COM" <> ",") , ("http://el.wikipedia.org/wiki/Τεχνολογία,", autolink "http://el.wikipedia.org/wiki/Τεχνολογία" <> ",") , ("doi:10.1000/182,", autolink "doi:10.1000/182" <> ",") , ("git://github.com/foo/bar.git,", autolink "git://github.com/foo/bar.git" <> ",") , ("file:///Users/joe/joe.txt, and", autolink "file:///Users/joe/joe.txt" <> ", and") , ("mailto:someone@somedomain.com.", autolink "mailto:someone@somedomain.com" <> ".") , ("Use http: this is not a link!", "Use http: this is not a link!") , ("(http://google.com).", "(" <> autolink "http://google.com" <> ").") , ("http://en.wikipedia.org/wiki/Sprite_(computer_graphics)", autolink "http://en.wikipedia.org/wiki/Sprite_(computer_graphics)") , ("http://en.wikipedia.org/wiki/Sprite_[computer_graphics]", autolink "http://en.wikipedia.org/wiki/Sprite_[computer_graphics]") , ("http://en.wikipedia.org/wiki/Sprite_{computer_graphics}", autolink "http://en.wikipedia.org/wiki/Sprite_{computer_graphics}") , ("http://example.com/Notification_Center-GitHub-20101108-140050.jpg", autolink "http://example.com/Notification_Center-GitHub-20101108-140050.jpg") , ("https://github.com/github/hubot/blob/master/scripts/cream.js#L20-20", autolink "https://github.com/github/hubot/blob/master/scripts/cream.js#L20-20") , ("http://www.rubyonrails.com", autolink "http://www.rubyonrails.com") , ("http://www.rubyonrails.com:80", autolink "http://www.rubyonrails.com:80") , ("http://www.rubyonrails.com/~minam", autolink "http://www.rubyonrails.com/~minam") , ("https://www.rubyonrails.com/~minam", autolink "https://www.rubyonrails.com/~minam") , ("http://www.rubyonrails.com/~minam/url%20with%20spaces", autolink "http://www.rubyonrails.com/~minam/url%20with%20spaces") , ("http://www.rubyonrails.com/foo.cgi?something=here", autolink "http://www.rubyonrails.com/foo.cgi?something=here") , ("http://www.rubyonrails.com/foo.cgi?something=here&and=here", autolink "http://www.rubyonrails.com/foo.cgi?something=here&and=here") , ("http://www.rubyonrails.com/contact;new", autolink "http://www.rubyonrails.com/contact;new") , ("http://www.rubyonrails.com/contact;new%20with%20spaces", autolink "http://www.rubyonrails.com/contact;new%20with%20spaces") , ("http://www.rubyonrails.com/contact;new?with=query&string=params", autolink "http://www.rubyonrails.com/contact;new?with=query&string=params") , ("http://www.rubyonrails.com/~minam/contact;new?with=query&string=params", autolink "http://www.rubyonrails.com/~minam/contact;new?with=query&string=params") , ("http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007", autolink "http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007") , ("http://www.mail-archive.com/rails@lists.rubyonrails.org/", autolink "http://www.mail-archive.com/rails@lists.rubyonrails.org/") , ("http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1", autolink "http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1") , ("http://en.wikipedia.org/wiki/Texas_hold%27em", autolink "http://en.wikipedia.org/wiki/Texas_hold%27em") , ("https://www.google.com/doku.php?id=gps:resource:scs:start", autolink "https://www.google.com/doku.php?id=gps:resource:scs:start") , ("http://www.rubyonrails.com", autolink "http://www.rubyonrails.com") , ("http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281", autolink "http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281") , ("http://foo.example.com/controller/action?parm=value&p2=v2#anchor123", autolink "http://foo.example.com/controller/action?parm=value&p2=v2#anchor123") , ("http://foo.example.com:3000/controller/action", autolink "http://foo.example.com:3000/controller/action") , ("http://foo.example.com:3000/controller/action+pack", autolink "http://foo.example.com:3000/controller/action+pack") , ("http://business.timesonline.co.uk/article/0,,9065-2473189,00.html", autolink "http://business.timesonline.co.uk/article/0,,9065-2473189,00.html") , ("http://www.mail-archive.com/ruby-talk@ruby-lang.org/", autolink "http://www.mail-archive.com/ruby-talk@ruby-lang.org/") ] {- p_markdown_round_trip :: Block -> Bool p_markdown_round_trip b = matches d' d'' where d' = normalize $ Pandoc (Meta [] [] []) [b] d'' = normalize $ readMarkdown def { readerSmart = True } $ writeMarkdown def d' matches (Pandoc _ [Plain []]) (Pandoc _ []) = True matches (Pandoc _ [Para []]) (Pandoc _ []) = True matches (Pandoc _ [Plain xs]) (Pandoc _ [Para xs']) = xs == xs' matches x y = x == y -} tests :: [Test] tests = [ testGroup "inline code" [ "with attribute" =: "`document.write(\"Hello\");`{.javascript}" =?> para (codeWith ("",["javascript"],[]) "document.write(\"Hello\");") , "with attribute space" =: "`*` {.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") ] , "unbalanced brackets" =: "[[[[[[[[[[[[[[[hi" =?> para (text "[[[[[[[[[[[[[[[hi") , testGroup "backslash escapes" [ "in URL" =: "[hi](/there\\))" =?> para (link "/there)" "" "hi") , "in title" =: "[hi](/there \"a\\\"a\")" =?> para (link "/there" "a\"a" "hi") , "in reference link title" =: "[hi]\n\n[hi]: /there (a\\)a)" =?> para (link "/there" "a)a" "hi") , "in reference link URL" =: "[hi]\n\n[hi]: /there\\.0" =?> para (link "/there.0" "" "hi") ] , testGroup "bare URIs" (map testBareLink bareLinkTests) , testGroup "Headers" [ "blank line before header" =: "\n# Header\n" =?> headerWith ("header",[],[]) 1 "Header" ] , testGroup "smart punctuation" [ test markdownSmart "quote before ellipses" ("'...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»")) ] , testGroup "mixed emphasis and strong" [ "emph and strong emph alternating" =: "*xxx* ***xxx*** xxx\n*xxx* ***xxx*** xxx" =?> para (emph "xxx" <> space <> strong (emph "xxx") <> space <> "xxx" <> space <> emph "xxx" <> space <> strong (emph "xxx") <> space <> "xxx") , "emph with spaced strong" =: "*x **xx** x*" =?> para (emph ("x" <> space <> strong "xx" <> space <> "x")) ] , testGroup "footnotes" [ "indent followed by newline and flush-left text" =: "[^1]\n\n[^1]: my note\n\n \nnot in note\n" =?> para (note (para "my note")) <> para "not in note" , "indent followed by newline and indented text" =: "[^1]\n\n[^1]: my note\n \n in note\n" =?> para (note (para "my note" <> para "in note")) , "recursive note" =: "[^1]\n\n[^1]: See [^1]\n" =?> para (note (para "See [^1]")) ] , testGroup "lhs" [ test (readMarkdown def{ readerExtensions = Set.insert Ext_literate_haskell $ readerExtensions def }) "inverse bird tracks and html" $ "> a\n\n< b\n\n
\n" =?> codeBlockWith ("",["sourceCode","literate","haskell"],[]) "a" <> codeBlockWith ("",["sourceCode","haskell"],[]) "b" <> rawBlock "html" "
\n\n" ] -- the round-trip properties frequently fail -- , testGroup "round trip" -- [ property "p_markdown_round_trip" p_markdown_round_trip -- ] ] pandoc-1.12.2.1/tests/Tests/Readers/RST.hs000644 000765 000024 00000005723 12251233602 017760 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-} module Tests.Readers.RST (tests) where import Text.Pandoc.Definition import Test.Framework import Tests.Helpers import Tests.Arbitrary() import Text.Pandoc.Builder import Text.Pandoc import Data.Monoid (mempty) rst :: String -> Pandoc rst = readRST def{ readerStandalone = True } infix 4 =: (=:) :: ToString c => String -> (String, c) -> Test (=:) = test rst tests :: [Test] tests = [ "line block with blank line" =: "| a\n|\n| b" =?> para (str "a") <> para (str "\160b") , "field list" =: unlines [ "para" , "" , ":Hostname: media08" , ":IP address: 10.0.0.19" , ":Size: 3ru" , ":Version: 1" , ":Indentation: Since the field marker may be quite long, the second" , " and subsequent lines of the field body do not have to line up" , " with the first line, but they must be indented relative to the" , " field name marker, and they must line up with each other." , ":Parameter i: integer" , ":Final: item" , " on two lines" ] =?> ( doc $ para "para" <> definitionList [ (str "Hostname", [para "media08"]) , (str "IP address", [para "10.0.0.19"]) , (str "Size", [para "3ru"]) , (str "Version", [para "1"]) , (str "Indentation", [para "Since the field marker may be quite long, the second and subsequent lines of the field body do not have to line up with the first line, but they must be indented relative to the field name marker, and they must line up with each other."]) , (str "Parameter i", [para "integer"]) , (str "Final", [para "item on two lines"]) ]) , "initial field list" =: unlines [ "=====" , "Title" , "=====" , "--------" , "Subtitle" , "--------" , "" , ":Version: 1" ] =?> ( setMeta "version" (para "1") $ setMeta "title" ("Title" :: Inlines) $ setMeta "subtitle" ("Subtitle" :: Inlines) $ doc mempty ) , "URLs with following punctuation" =: ("http://google.com, http://yahoo.com; http://foo.bar.baz.\n" ++ "http://foo.bar/baz_(bam) (http://foo.bar)") =?> para (link "http://google.com" "" "http://google.com" <> ", " <> link "http://yahoo.com" "" "http://yahoo.com" <> "; " <> link "http://foo.bar.baz" "" "http://foo.bar.baz" <> ". " <> link "http://foo.bar/baz_(bam)" "" "http://foo.bar/baz_(bam)" <> " (" <> link "http://foo.bar" "" "http://foo.bar" <> ")") ] pandoc-1.12.2.1/src/Text/000755 000765 000024 00000000000 12251233602 014627 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/src/Text/Pandoc/000755 000765 000024 00000000000 12251233602 016033 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/src/Text/Pandoc.hs000644 000765 000024 00000031025 12251233602 016370 0ustar00jgmstaff000000 000000 {-# LANGUAGE ScopedTypeVariables, FlexibleInstances #-} {- Copyright (C) 2006-2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable This helper module exports the main writers, readers, and data structure definitions from the Pandoc libraries. A typical application will chain together a reader and a writer to convert strings from one format to another. For example, the following simple program will act as a filter converting markdown fragments to reStructuredText, using reference-style links instead of inline links: > module Main where > import Text.Pandoc > > markdownToRST :: String -> String > markdownToRST = > (writeRST def {writerReferenceLinks = True}) . readMarkdown def > > main = getContents >>= putStrLn . markdownToRST Note: all of the readers assume that the input text has @'\n'@ line endings. So if you get your input text from a web form, you should remove @'\r'@ characters using @filter (/='\r')@. -} module Text.Pandoc ( -- * Definitions module Text.Pandoc.Definition -- * Generics , module Text.Pandoc.Generic -- * Options , module Text.Pandoc.Options -- * Lists of readers and writers , readers , writers -- * Readers: converting /to/ Pandoc format , readMarkdown , readMediaWiki , readRST , readLaTeX , readHtml , readTextile , readDocBook , readOPML , readHaddock , readNative , readJSON -- * Writers: converting /from/ Pandoc format , Writer (..) , writeNative , writeJSON , writeMarkdown , writePlain , writeRST , writeLaTeX , writeConTeXt , writeTexinfo , writeHtml , writeHtmlString , writeDocbook , writeOPML , writeOpenDocument , writeMan , writeMediaWiki , writeTextile , writeRTF , writeODT , writeDocx , writeEPUB , writeFB2 , writeOrg , writeAsciiDoc , writeCustom -- * Rendering templates and default templates , module Text.Pandoc.Templates -- * Version , pandocVersion -- * Miscellaneous , getReader , getWriter , ToJsonFilter(..) ) where import Text.Pandoc.Definition import Text.Pandoc.Generic import Text.Pandoc.JSON import Text.Pandoc.Readers.Markdown import Text.Pandoc.Readers.MediaWiki import Text.Pandoc.Readers.RST import Text.Pandoc.Readers.DocBook import Text.Pandoc.Readers.OPML import Text.Pandoc.Readers.LaTeX import Text.Pandoc.Readers.HTML import Text.Pandoc.Readers.Textile import Text.Pandoc.Readers.Native import Text.Pandoc.Readers.Haddock import Text.Pandoc.Writers.Native import Text.Pandoc.Writers.Markdown import Text.Pandoc.Writers.RST import Text.Pandoc.Writers.LaTeX import Text.Pandoc.Writers.ConTeXt import Text.Pandoc.Writers.Texinfo import Text.Pandoc.Writers.HTML import Text.Pandoc.Writers.ODT import Text.Pandoc.Writers.Docx import Text.Pandoc.Writers.EPUB import Text.Pandoc.Writers.FB2 import Text.Pandoc.Writers.Docbook import Text.Pandoc.Writers.OPML import Text.Pandoc.Writers.OpenDocument import Text.Pandoc.Writers.Man import Text.Pandoc.Writers.RTF import Text.Pandoc.Writers.MediaWiki import Text.Pandoc.Writers.Textile import Text.Pandoc.Writers.Org import Text.Pandoc.Writers.AsciiDoc import Text.Pandoc.Writers.Custom import Text.Pandoc.Templates import Text.Pandoc.Options import Text.Pandoc.Shared (safeRead, warn) import Data.Aeson import qualified Data.ByteString.Lazy as BL import Data.List (intercalate, isSuffixOf) import Data.Version (showVersion) import Data.Set (Set) import qualified Data.Set as Set import Text.Parsec import Text.Parsec.Error import qualified Text.Pandoc.UTF8 as UTF8 import Paths_pandoc (version) -- | Version number of pandoc library. pandocVersion :: String pandocVersion = showVersion version parseFormatSpec :: String -> Either ParseError (String, Set Extension -> Set Extension) parseFormatSpec = parse formatSpec "" where formatSpec = do name <- formatName extMods <- many extMod return (name, foldl (.) id extMods) formatName = many1 $ noneOf "-+" extMod = do polarity <- oneOf "-+" name <- many $ noneOf "-+" ext <- case safeRead ("Ext_" ++ name) of Just n -> return n Nothing | name == "lhs" -> return Ext_literate_haskell | otherwise -> fail $ "Unknown extension: " ++ name return $ case polarity of '-' -> Set.delete ext _ -> Set.insert ext -- auxiliary function for readers: markdown :: ReaderOptions -> String -> IO Pandoc markdown o s = do let (doc, warnings) = readMarkdownWithWarnings o s mapM_ warn warnings return doc -- | Association list of formats and readers. readers :: [(String, ReaderOptions -> String -> IO Pandoc)] readers = [ ("native" , \_ s -> return $ readNative s) ,("json" , \o s -> return $ readJSON o s) ,("markdown" , markdown) ,("markdown_strict" , markdown) ,("markdown_phpextra" , markdown) ,("markdown_github" , markdown) ,("markdown_mmd", markdown) ,("rst" , \o s -> return $ readRST o s) ,("mediawiki" , \o s -> return $ readMediaWiki o s) ,("docbook" , \o s -> return $ readDocBook o s) ,("opml" , \o s -> return $ readOPML o s) ,("textile" , \o s -> return $ readTextile o s) -- TODO : textile+lhs ,("html" , \o s -> return $ readHtml o s) ,("latex" , \o s -> return $ readLaTeX o s) ,("haddock" , \o s -> return $ readHaddock o s) ] data Writer = PureStringWriter (WriterOptions -> Pandoc -> String) | IOStringWriter (WriterOptions -> Pandoc -> IO String) | IOByteStringWriter (WriterOptions -> Pandoc -> IO BL.ByteString) -- | Association list of formats and writers. writers :: [ ( String, Writer ) ] writers = [ ("native" , PureStringWriter writeNative) ,("json" , PureStringWriter writeJSON) ,("docx" , IOByteStringWriter writeDocx) ,("odt" , IOByteStringWriter writeODT) ,("epub" , IOByteStringWriter $ \o -> writeEPUB o{ writerEpubVersion = Just EPUB2 }) ,("epub3" , IOByteStringWriter $ \o -> writeEPUB o{ writerEpubVersion = Just EPUB3 }) ,("fb2" , IOStringWriter writeFB2) ,("html" , PureStringWriter writeHtmlString) ,("html5" , PureStringWriter $ \o -> writeHtmlString o{ writerHtml5 = True }) ,("s5" , PureStringWriter $ \o -> writeHtmlString o{ writerSlideVariant = S5Slides , writerTableOfContents = False }) ,("slidy" , PureStringWriter $ \o -> writeHtmlString o{ writerSlideVariant = SlidySlides }) ,("slideous" , PureStringWriter $ \o -> writeHtmlString o{ writerSlideVariant = SlideousSlides }) ,("dzslides" , PureStringWriter $ \o -> writeHtmlString o{ writerSlideVariant = DZSlides , writerHtml5 = True }) ,("revealjs" , PureStringWriter $ \o -> writeHtmlString o{ writerSlideVariant = RevealJsSlides , writerHtml5 = True }) ,("docbook" , PureStringWriter writeDocbook) ,("opml" , PureStringWriter writeOPML) ,("opendocument" , PureStringWriter writeOpenDocument) ,("latex" , PureStringWriter writeLaTeX) ,("beamer" , PureStringWriter $ \o -> writeLaTeX o{ writerBeamer = True }) ,("context" , PureStringWriter writeConTeXt) ,("texinfo" , PureStringWriter writeTexinfo) ,("man" , PureStringWriter writeMan) ,("markdown" , PureStringWriter writeMarkdown) ,("markdown_strict" , PureStringWriter writeMarkdown) ,("markdown_phpextra" , PureStringWriter writeMarkdown) ,("markdown_github" , PureStringWriter writeMarkdown) ,("markdown_mmd" , PureStringWriter writeMarkdown) ,("plain" , PureStringWriter writePlain) ,("rst" , PureStringWriter writeRST) ,("mediawiki" , PureStringWriter writeMediaWiki) ,("textile" , PureStringWriter writeTextile) ,("rtf" , IOStringWriter writeRTFWithEmbeddedImages) ,("org" , PureStringWriter writeOrg) ,("asciidoc" , PureStringWriter writeAsciiDoc) ] getDefaultExtensions :: String -> Set Extension getDefaultExtensions "markdown_strict" = strictExtensions getDefaultExtensions "markdown_phpextra" = phpMarkdownExtraExtensions getDefaultExtensions "markdown_mmd" = multimarkdownExtensions getDefaultExtensions "markdown_github" = githubMarkdownExtensions 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) getReader s = case parseFormatSpec s of Left e -> Left $ intercalate "\n" $ [m | Message m <- errorMessages e] Right (readerName, setExts) -> case lookup readerName readers of Nothing -> Left $ "Unknown reader: " ++ readerName Just r -> Right $ \o -> r o{ readerExtensions = setExts $ getDefaultExtensions readerName } -- | Retrieve writer based on formatSpec (format+extensions). getWriter :: String -> Either String Writer getWriter s = case parseFormatSpec s of Left e -> Left $ intercalate "\n" $ [m | Message m <- errorMessages e] Right (writerName, setExts) -> case lookup writerName writers of Nothing | ".lua" `isSuffixOf` s -> Right $ IOStringWriter $ writeCustom s | otherwise -> Left $ "Unknown writer: " ++ writerName Just (PureStringWriter r) -> Right $ PureStringWriter $ \o -> r o{ writerExtensions = setExts $ getDefaultExtensions writerName } Just (IOStringWriter r) -> Right $ IOStringWriter $ \o -> r o{ writerExtensions = setExts $ getDefaultExtensions writerName } Just (IOByteStringWriter r) -> Right $ IOByteStringWriter $ \o -> r o{ writerExtensions = setExts $ getDefaultExtensions writerName } {-# DEPRECATED toJsonFilter "Use 'toJSONFilter' from 'Text.Pandoc.JSON' instead" #-} -- | Deprecated. Use @toJSONFilter@ from @Text.Pandoc.JSON@ instead. class ToJSONFilter a => ToJsonFilter a where toJsonFilter :: a -> IO () toJsonFilter = toJSONFilter readJSON :: ReaderOptions -> String -> Pandoc readJSON _ = either error id . eitherDecode' . UTF8.fromStringLazy writeJSON :: WriterOptions -> Pandoc -> String writeJSON _ = UTF8.toStringLazy . encode pandoc-1.12.2.1/src/Text/Pandoc/Asciify.hs000644 000765 000024 00000016712 12251233602 017765 0ustar00jgmstaff000000 000000 {- Copyright (C) 2013 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.SelfContained Copyright : Copyright (C) 2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Function to convert accented latin letters to their unaccented ascii equivalents (used in constructing HTML identifiers). -} module Text.Pandoc.Asciify (toAsciiChar) where import qualified Data.Map as M import Data.Char (isAscii) toAsciiChar :: Char -> Maybe Char toAsciiChar c | isAscii c = Just c | otherwise = M.lookup c asciiMap asciiMap :: M.Map Char Char asciiMap = M.fromList [('\192','A') ,('\193','A') ,('\194','A') ,('\195','A') ,('\196','A') ,('\197','A') ,('\199','C') ,('\200','E') ,('\201','E') ,('\202','E') ,('\203','E') ,('\204','I') ,('\205','I') ,('\206','I') ,('\207','I') ,('\209','N') ,('\210','O') ,('\211','O') ,('\212','O') ,('\213','O') ,('\214','O') ,('\217','U') ,('\218','U') ,('\219','U') ,('\220','U') ,('\221','Y') ,('\224','a') ,('\225','a') ,('\226','a') ,('\227','a') ,('\228','a') ,('\229','a') ,('\231','c') ,('\232','e') ,('\233','e') ,('\234','e') ,('\235','e') ,('\236','i') ,('\237','i') ,('\238','i') ,('\239','i') ,('\241','n') ,('\242','o') ,('\243','o') ,('\244','o') ,('\245','o') ,('\246','o') ,('\249','u') ,('\250','u') ,('\251','u') ,('\252','u') ,('\253','y') ,('\255','y') ,('\256','A') ,('\257','a') ,('\258','A') ,('\259','a') ,('\260','A') ,('\261','a') ,('\262','C') ,('\263','c') ,('\264','C') ,('\265','c') ,('\266','C') ,('\267','c') ,('\268','C') ,('\269','c') ,('\270','D') ,('\271','d') ,('\274','E') ,('\275','e') ,('\276','E') ,('\277','e') ,('\278','E') ,('\279','e') ,('\280','E') ,('\281','e') ,('\282','E') ,('\283','e') ,('\284','G') ,('\285','g') ,('\286','G') ,('\287','g') ,('\288','G') ,('\289','g') ,('\290','G') ,('\291','g') ,('\292','H') ,('\293','h') ,('\296','I') ,('\297','i') ,('\298','I') ,('\299','i') ,('\300','I') ,('\301','i') ,('\302','I') ,('\303','i') ,('\304','I') ,('\308','J') ,('\309','j') ,('\310','K') ,('\311','k') ,('\313','L') ,('\314','l') ,('\315','L') ,('\316','l') ,('\317','L') ,('\318','l') ,('\323','N') ,('\324','n') ,('\325','N') ,('\326','n') ,('\327','N') ,('\328','n') ,('\332','O') ,('\333','o') ,('\334','O') ,('\335','o') ,('\336','O') ,('\337','o') ,('\340','R') ,('\341','r') ,('\342','R') ,('\343','r') ,('\344','R') ,('\345','r') ,('\346','S') ,('\347','s') ,('\348','S') ,('\349','s') ,('\350','S') ,('\351','s') ,('\352','S') ,('\353','s') ,('\354','T') ,('\355','t') ,('\356','T') ,('\357','t') ,('\360','U') ,('\361','u') ,('\362','U') ,('\363','u') ,('\364','U') ,('\365','u') ,('\366','U') ,('\367','u') ,('\368','U') ,('\369','u') ,('\370','U') ,('\371','u') ,('\372','W') ,('\373','w') ,('\374','Y') ,('\375','y') ,('\376','Y') ,('\377','Z') ,('\378','z') ,('\379','Z') ,('\380','z') ,('\381','Z') ,('\382','z') ,('\416','O') ,('\417','o') ,('\431','U') ,('\432','u') ,('\461','A') ,('\462','a') ,('\463','I') ,('\464','i') ,('\465','O') ,('\466','o') ,('\467','U') ,('\468','u') ,('\486','G') ,('\487','g') ,('\488','K') ,('\489','k') ,('\490','O') ,('\491','o') ,('\496','j') ,('\500','G') ,('\501','g') ,('\504','N') ,('\505','n') ,('\512','A') ,('\513','a') ,('\514','A') ,('\515','a') ,('\516','E') ,('\517','e') ,('\518','E') ,('\519','e') ,('\520','I') ,('\521','i') ,('\522','I') ,('\523','i') ,('\524','O') ,('\525','o') ,('\526','O') ,('\527','o') ,('\528','R') ,('\529','r') ,('\530','R') ,('\531','r') ,('\532','U') ,('\533','u') ,('\534','U') ,('\535','u') ,('\536','S') ,('\537','s') ,('\538','T') ,('\539','t') ,('\542','H') ,('\543','h') ,('\550','A') ,('\551','a') ,('\552','E') ,('\553','e') ,('\558','O') ,('\559','o') ,('\562','Y') ,('\563','y') ,('\894',';') ,('\7680','A') ,('\7681','a') ,('\7682','B') ,('\7683','b') ,('\7684','B') ,('\7685','b') ,('\7686','B') ,('\7687','b') ,('\7690','D') ,('\7691','d') ,('\7692','D') ,('\7693','d') ,('\7694','D') ,('\7695','d') ,('\7696','D') ,('\7697','d') ,('\7698','D') ,('\7699','d') ,('\7704','E') ,('\7705','e') ,('\7706','E') ,('\7707','e') ,('\7710','F') ,('\7711','f') ,('\7712','G') ,('\7713','g') ,('\7714','H') ,('\7715','h') ,('\7716','H') ,('\7717','h') ,('\7718','H') ,('\7719','h') ,('\7720','H') ,('\7721','h') ,('\7722','H') ,('\7723','h') ,('\7724','I') ,('\7725','i') ,('\7728','K') ,('\7729','k') ,('\7730','K') ,('\7731','k') ,('\7732','K') ,('\7733','k') ,('\7734','L') ,('\7735','l') ,('\7738','L') ,('\7739','l') ,('\7740','L') ,('\7741','l') ,('\7742','M') ,('\7743','m') ,('\7744','M') ,('\7745','m') ,('\7746','M') ,('\7747','m') ,('\7748','N') ,('\7749','n') ,('\7750','N') ,('\7751','n') ,('\7752','N') ,('\7753','n') ,('\7754','N') ,('\7755','n') ,('\7764','P') ,('\7765','p') ,('\7766','P') ,('\7767','p') ,('\7768','R') ,('\7769','r') ,('\7770','R') ,('\7771','r') ,('\7774','R') ,('\7775','r') ,('\7776','S') ,('\7777','s') ,('\7778','S') ,('\7779','s') ,('\7786','T') ,('\7787','t') ,('\7788','T') ,('\7789','t') ,('\7790','T') ,('\7791','t') ,('\7792','T') ,('\7793','t') ,('\7794','U') ,('\7795','u') ,('\7796','U') ,('\7797','u') ,('\7798','U') ,('\7799','u') ,('\7804','V') ,('\7805','v') ,('\7806','V') ,('\7807','v') ,('\7808','W') ,('\7809','w') ,('\7810','W') ,('\7811','w') ,('\7812','W') ,('\7813','w') ,('\7814','W') ,('\7815','w') ,('\7816','W') ,('\7817','w') ,('\7818','X') ,('\7819','x') ,('\7820','X') ,('\7821','x') ,('\7822','Y') ,('\7823','y') ,('\7824','Z') ,('\7825','z') ,('\7826','Z') ,('\7827','z') ,('\7828','Z') ,('\7829','z') ,('\7830','h') ,('\7831','t') ,('\7832','w') ,('\7833','y') ,('\7840','A') ,('\7841','a') ,('\7842','A') ,('\7843','a') ,('\7864','E') ,('\7865','e') ,('\7866','E') ,('\7867','e') ,('\7868','E') ,('\7869','e') ,('\7880','I') ,('\7881','i') ,('\7882','I') ,('\7883','i') ,('\7884','O') ,('\7885','o') ,('\7886','O') ,('\7887','o') ,('\7908','U') ,('\7909','u') ,('\7910','U') ,('\7911','u') ,('\7922','Y') ,('\7923','y') ,('\7924','Y') ,('\7925','y') ,('\7926','Y') ,('\7927','y') ,('\7928','Y') ,('\7929','y') ,('\8175','`') ,('\8490','K') ,('\8800','=') ,('\8814','<') ,('\8815','>') ] pandoc-1.12.2.1/src/Text/Pandoc/Compat/000755 000765 000024 00000000000 12251233602 017256 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/src/Text/Pandoc/Data.hsb000644 000765 000024 00000000326 12251233602 017403 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} -- to be processed using hsb2hs module Text.Pandoc.Data (dataFiles) where import qualified Data.ByteString as B dataFiles :: [(FilePath, B.ByteString)] dataFiles = %blobs "data" pandoc-1.12.2.1/src/Text/Pandoc/Highlighting.hs000644 000765 000024 00000013527 12251233602 021004 0ustar00jgmstaff000000 000000 {- Copyright (C) 2008 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Highlighting Copyright : Copyright (C) 2008 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Exports functions for syntax highlighting. -} module Text.Pandoc.Highlighting ( languages , languagesByExtension , highlight , formatLaTeXInline , formatLaTeXBlock , styleToLaTeX , formatHtmlInline , formatHtmlBlock , styleToCss , pygments , espresso , zenburn , tango , kate , monochrome , haddock , Style , fromListingsLanguage , toListingsLanguage ) where import Text.Pandoc.Definition import Text.Pandoc.Shared (safeRead) import Text.Highlighting.Kate import Data.List (find) import Data.Maybe (fromMaybe) import Data.Char (toLower) import qualified Data.Map as M import Control.Applicative ((<|>)) lcLanguages :: [String] lcLanguages = map (map toLower) languages highlight :: (FormatOptions -> [SourceLine] -> a) -- ^ Formatter -> Attr -- ^ Attributes of the CodeBlock -> String -- ^ Raw contents of the CodeBlock -> Maybe a -- ^ Maybe the formatted result highlight formatter (_, classes, keyvals) rawCode = let firstNum = case safeRead (fromMaybe "1" $ lookup "startFrom" keyvals) of Just n -> n Nothing -> 1 fmtOpts = defaultFormatOpts{ startNumber = firstNum, numberLines = any (`elem` ["number","numberLines", "number-lines"]) classes } lcclasses = map (map toLower) classes in case find (`elem` lcLanguages) lcclasses of Nothing -> Nothing Just language -> Just $ formatter fmtOpts{ codeClasses = [language], containerClasses = classes } $ highlightAs language rawCode -- Functions for correlating latex listings package's language names -- with highlighting-kate language names: langToListingsMap :: M.Map String String langToListingsMap = M.fromList langsList listingsToLangMap :: M.Map String String listingsToLangMap = M.fromList $ map switch langsList where switch (a,b) = (b,a) langsList :: [(String, String)] langsList = [("ada","Ada") ,("java","Java") ,("prolog","Prolog") ,("python","Python") ,("gnuassembler","Assembler") ,("commonlisp","Lisp") ,("r","R") ,("awk","Awk") ,("bash","bash") ,("makefile","make") ,("c","C") ,("matlab","Matlab") ,("ruby","Ruby") ,("cpp","C++") ,("ocaml","Caml") ,("modula2","Modula-2") ,("sql","SQL") ,("eiffel","Eiffel") ,("tcl","tcl") ,("erlang","erlang") ,("verilog","Verilog") ,("fortran","Fortran") ,("vhdl","VHDL") ,("pascal","Pascal") ,("perl","Perl") ,("xml","XML") ,("haskell","Haskell") ,("php","PHP") ,("xslt","XSLT") ,("html","HTML") ] listingsLangs :: [String] listingsLangs = ["Ada","Java","Prolog","Algol","JVMIS","Promela", "Ant","ksh","Python","Assembler","Lisp","R","Awk", "Logo","Reduce","bash","make","Rexx","Basic", "Mathematica","RSL","C","Matlab","Ruby","C++", "Mercury","S","Caml","MetaPost","SAS","Clean", "Miranda","Scilab","Cobol","Mizar","sh","Comal", "ML","SHELXL","csh","Modula-2","Simula","Delphi", "MuPAD","SQL","Eiffel","NASTRAN","tcl","Elan", "Oberon-2","TeX","erlang","OCL","VBScript","Euphoria", "Octave","Verilog","Fortran","Oz","VHDL","GCL", "Pascal","VRML","Gnuplot","Perl","XML","Haskell", "PHP","XSLT","HTML","PL/I"] -- Determine listings language name from highlighting-kate language name. toListingsLanguage :: String -> Maybe String toListingsLanguage lang = (if lang `elem` listingsLangs then Just lang else Nothing) <|> M.lookup (map toLower lang) langToListingsMap -- Determine highlighting-kate language name from listings language name. fromListingsLanguage :: String -> Maybe String fromListingsLanguage lang = M.lookup lang listingsToLangMap pandoc-1.12.2.1/src/Text/Pandoc/ImageSize.hs000644 000765 000024 00000015067 12251233602 020255 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-} {- Copyright (C) 2011 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.ImageSize Copyright : Copyright (C) 2011 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Functions for determining the size of a PNG, JPEG, or GIF image. -} module Text.Pandoc.ImageSize ( ImageType(..), imageType, imageSize, sizeInPixels, sizeInPoints ) where import Data.ByteString (ByteString, unpack) import qualified Data.ByteString.Char8 as B import Control.Monad import Data.Bits import Text.Pandoc.Shared (safeRead) -- quick and dirty functions to get image sizes -- algorithms borrowed from wwwis.pl data ImageType = Png | Gif | Jpeg | Pdf | Eps deriving Show data ImageSize = ImageSize{ pxX :: Integer , pxY :: Integer , dpiX :: Integer , dpiY :: Integer } deriving (Read, Show, Eq) 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 "%PDF" -> return Pdf "%!PS" | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF" -> return Eps _ -> fail "Unknown image type" imageSize :: ByteString -> Maybe ImageSize imageSize img = do t <- imageType img case t of Png -> pngSize img Gif -> gifSize img Jpeg -> jpegSize img Eps -> epsSize img Pdf -> Nothing -- TODO sizeInPixels :: ImageSize -> (Integer, Integer) sizeInPixels s = (pxX s, pxY s) sizeInPoints :: ImageSize -> (Integer, Integer) sizeInPoints s = (pxX s * 72 `div` dpiX s, pxY s * 72 `div` dpiY s) epsSize :: ByteString -> Maybe ImageSize epsSize img = do let ls = takeWhile ("%" `B.isPrefixOf`) $ B.lines img let ls' = dropWhile (not . ("%%BoundingBox:" `B.isPrefixOf`)) ls case ls' of [] -> mzero (x:_) -> case B.words x of (_:_:_:ux:uy:[]) -> do ux' <- safeRead $ B.unpack ux uy' <- safeRead $ B.unpack uy return ImageSize{ pxX = ux' , pxY = uy' , dpiX = 72 , dpiY = 72 } _ -> mzero pngSize :: ByteString -> Maybe ImageSize pngSize img = do let (h, rest) = B.splitAt 8 img guard $ h == "\x8a\x4d\x4e\x47\x0d\x0a\x1a\x0a" || h == "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" let (i, rest') = B.splitAt 4 $ B.drop 4 rest guard $ i == "MHDR" || i == "IHDR" let (sizes, rest'') = B.splitAt 8 rest' (x,y) <- case map fromIntegral $ unpack $ sizes of ([w1,w2,w3,w4,h1,h2,h3,h4] :: [Integer]) -> return ((shift w1 24) + (shift w2 16) + (shift w3 8) + w4, (shift h1 24) + (shift h2 16) + (shift h3 8) + h4) _ -> fail "PNG parse error" let (dpix, dpiy) = findpHYs rest'' return $ ImageSize { pxX = x, pxY = y, dpiX = dpix, dpiY = dpiy } findpHYs :: ByteString -> (Integer, Integer) findpHYs x = if B.null x || "IDAT" `B.isPrefixOf` x then (72,72) -- default, no pHYs else if "pHYs" `B.isPrefixOf` x then let [x1,x2,x3,x4,y1,y2,y3,y4,u] = map fromIntegral $ unpack $ B.take 9 $ B.drop 4 x factor = if u == 1 -- dots per meter then \z -> z * 254 `div` 10000 else const 72 in ( factor $ (shift x1 24) + (shift x2 16) + (shift x3 8) + x4, factor $ (shift y1 24) + (shift y2 16) + (shift y3 8) + y4 ) else findpHYs $ B.drop 1 x -- read another byte gifSize :: ByteString -> Maybe ImageSize gifSize img = do let (h, rest) = B.splitAt 6 img guard $ h == "GIF87a" || h == "GIF89a" case map fromIntegral $ unpack $ B.take 4 rest of [w2,w1,h2,h1] -> return ImageSize { pxX = shift w1 8 + w2, pxY = shift h1 8 + h2, dpiX = 72, dpiY = 72 } _ -> fail "GIF parse error" 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 let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral $ unpack $ B.take 5 $ B.drop 9 $ rest let factor = case dpiDensity of 1 -> id 2 -> \x -> (x * 254 `div` 10) _ -> const 72 let dpix = factor (shift dpix1 8 + dpix2) let dpiy = factor (shift dpiy1 8 + dpiy2) (w,h) <- findJpegSize rest return $ ImageSize { pxX = w, pxY = h, dpiX = dpix, dpiY = dpiy } findJpegSize :: ByteString -> Maybe (Integer,Integer) findJpegSize bs = do let bs' = B.dropWhile (=='\xff') $ B.dropWhile (/='\xff') bs case B.uncons bs' of Just (c,bs'') | c >= '\xc0' && c <= '\xc3' -> do case map fromIntegral $ unpack $ B.take 4 $ B.drop 3 bs'' of [h1,h2,w1,w2] -> return (shift w1 8 + w2, shift h1 8 + h2) _ -> fail "JPEG parse error" Just (_,bs'') -> do case map fromIntegral $ unpack $ B.take 2 bs'' of [c1,c2] -> do let len = shift c1 8 + c2 -- skip variables findJpegSize $ B.drop len bs'' _ -> fail "JPEG parse error" Nothing -> fail "Did not find length record" pandoc-1.12.2.1/src/Text/Pandoc/MIME.hs000644 000765 000024 00000051201 12251233602 017115 0ustar00jgmstaff000000 000000 {- Copyright (C) 2011 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.MIME Copyright : Copyright (C) 2011 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Mime type lookup for ODT writer. -} module Text.Pandoc.MIME ( getMimeType, extensionFromMimeType ) where import System.FilePath import Data.Char ( toLower ) import qualified Data.Map as M -- | Determine mime type appropriate for file path. getMimeType :: FilePath -> Maybe String getMimeType "layout-cache" = Just "application/binary" -- in ODT getMimeType f = M.lookup (map toLower $ drop 1 $ takeExtension f) mimeTypes where mimeTypes = M.fromList mimeTypesList extensionFromMimeType :: String -> Maybe String 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)] mimeTypesList = -- List borrowed from happstack-server. [("gz","application/x-gzip") ,("cabal","application/x-cabal") ,("%","application/x-trash") ,("323","text/h323") ,("3gp","video/3gpp") ,("7z","application/x-7z-compressed") ,("abw","application/x-abiword") ,("ai","application/postscript") ,("aif","audio/x-aiff") ,("aifc","audio/x-aiff") ,("aiff","audio/x-aiff") ,("alc","chemical/x-alchemy") ,("art","image/x-jg") ,("asc","text/plain") ,("asf","video/x-ms-asf") ,("asn","chemical/x-ncbi-asn1") ,("aso","chemical/x-ncbi-asn1-binary") ,("asx","video/x-ms-asf") ,("atom","application/atom") ,("atomcat","application/atomcat+xml") ,("atomsrv","application/atomserv+xml") ,("au","audio/basic") ,("avi","video/x-msvideo") ,("b","chemical/x-molconn-Z") ,("bak","application/x-trash") ,("bat","application/x-msdos-program") ,("bcpio","application/x-bcpio") ,("bib","text/x-bibtex") ,("bin","application/octet-stream") ,("bmp","image/x-ms-bmp") ,("boo","text/x-boo") ,("book","application/x-maker") ,("bsd","chemical/x-crossfire") ,("c","text/x-csrc") ,("c++","text/x-c++src") ,("c3d","chemical/x-chem3d") ,("cab","application/x-cab") ,("cac","chemical/x-cache") ,("cache","chemical/x-cache") ,("cap","application/cap") ,("cascii","chemical/x-cactvs-binary") ,("cat","application/vnd.ms-pki.seccat") ,("cbin","chemical/x-cactvs-binary") ,("cbr","application/x-cbr") ,("cbz","application/x-cbz") ,("cc","text/x-c++src") ,("cdf","application/x-cdf") ,("cdr","image/x-coreldraw") ,("cdt","image/x-coreldrawtemplate") ,("cdx","chemical/x-cdx") ,("cdy","application/vnd.cinderella") ,("cef","chemical/x-cxf") ,("cer","chemical/x-cerius") ,("chm","chemical/x-chemdraw") ,("chrt","application/x-kchart") ,("cif","chemical/x-cif") ,("class","application/java-vm") ,("cls","text/x-tex") ,("cmdf","chemical/x-cmdf") ,("cml","chemical/x-cml") ,("cod","application/vnd.rim.cod") ,("com","application/x-msdos-program") ,("cpa","chemical/x-compass") ,("cpio","application/x-cpio") ,("cpp","text/x-c++src") ,("cpt","application/mac-compactpro") ,("crl","application/x-pkcs7-crl") ,("crt","application/x-x509-ca-cert") ,("csf","chemical/x-cache-csf") ,("csh","application/x-csh") ,("csm","chemical/x-csml") ,("csml","chemical/x-csml") ,("css","text/css") ,("csv","text/csv") ,("ctab","chemical/x-cactvs-binary") ,("ctx","chemical/x-ctx") ,("cu","application/cu-seeme") ,("cub","chemical/x-gaussian-cube") ,("cxf","chemical/x-cxf") ,("cxx","text/x-c++src") ,("d","text/x-dsrc") ,("dat","chemical/x-mopac-input") ,("dcr","application/x-director") ,("deb","application/x-debian-package") ,("dif","video/dv") ,("diff","text/x-diff") ,("dir","application/x-director") ,("djv","image/vnd.djvu") ,("djvu","image/vnd.djvu") ,("dl","video/dl") ,("dll","application/x-msdos-program") ,("dmg","application/x-apple-diskimage") ,("dms","application/x-dms") ,("doc","application/msword") ,("dot","application/msword") ,("dv","video/dv") ,("dvi","application/x-dvi") ,("dx","chemical/x-jcamp-dx") ,("dxr","application/x-director") ,("emb","chemical/x-embl-dl-nucleotide") ,("embl","chemical/x-embl-dl-nucleotide") ,("eml","message/rfc822") ,("ent","chemical/x-ncbi-asn1-ascii") ,("eot","application/vnd.ms-fontobject") ,("eps","application/postscript") ,("etx","text/x-setext") ,("exe","application/x-msdos-program") ,("ez","application/andrew-inset") ,("fb","application/x-maker") ,("fbdoc","application/x-maker") ,("fch","chemical/x-gaussian-checkpoint") ,("fchk","chemical/x-gaussian-checkpoint") ,("fig","application/x-xfig") ,("flac","application/x-flac") ,("fli","video/fli") ,("fm","application/x-maker") ,("frame","application/x-maker") ,("frm","application/x-maker") ,("fs","text/plain") ,("gal","chemical/x-gaussian-log") ,("gam","chemical/x-gamess-input") ,("gamin","chemical/x-gamess-input") ,("gau","chemical/x-gaussian-input") ,("gcd","text/x-pcs-gcd") ,("gcf","application/x-graphing-calculator") ,("gcg","chemical/x-gcg8-sequence") ,("gen","chemical/x-genbank") ,("gf","application/x-tex-gf") ,("gif","image/gif") ,("gjc","chemical/x-gaussian-input") ,("gjf","chemical/x-gaussian-input") ,("gl","video/gl") ,("gnumeric","application/x-gnumeric") ,("gpt","chemical/x-mopac-graph") ,("gsf","application/x-font") ,("gsm","audio/x-gsm") ,("gtar","application/x-gtar") ,("h","text/x-chdr") ,("h++","text/x-c++hdr") ,("hdf","application/x-hdf") ,("hh","text/x-c++hdr") ,("hin","chemical/x-hin") ,("hpp","text/x-c++hdr") ,("hqx","application/mac-binhex40") ,("hs","text/x-haskell") ,("hta","application/hta") ,("htc","text/x-component") ,("htm","text/html") ,("html","text/html") ,("hxx","text/x-c++hdr") ,("ica","application/x-ica") ,("ice","x-conference/x-cooltalk") ,("ico","image/x-icon") ,("ics","text/calendar") ,("icz","text/calendar") ,("ief","image/ief") ,("iges","model/iges") ,("igs","model/iges") ,("iii","application/x-iphone") ,("inp","chemical/x-gamess-input") ,("ins","application/x-internet-signup") ,("iso","application/x-iso9660-image") ,("isp","application/x-internet-signup") ,("ist","chemical/x-isostar") ,("istr","chemical/x-isostar") ,("jad","text/vnd.sun.j2me.app-descriptor") ,("jar","application/java-archive") ,("java","text/x-java") ,("jdx","chemical/x-jcamp-dx") ,("jmz","application/x-jmol") ,("jng","image/x-jng") ,("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") ,("key","application/pgp-keys") ,("kil","application/x-killustrator") ,("kin","chemical/x-kinemage") ,("kml","application/vnd.google-earth.kml+xml") ,("kmz","application/vnd.google-earth.kmz") ,("kpr","application/x-kpresenter") ,("kpt","application/x-kpresenter") ,("ksp","application/x-kspread") ,("kwd","application/x-kword") ,("kwt","application/x-kword") ,("latex","application/x-latex") ,("lha","application/x-lha") ,("lhs","text/x-literate-haskell") ,("lsf","video/x-la-asf") ,("lsx","video/x-la-asf") ,("ltx","text/x-tex") ,("lyx","application/x-lyx") ,("lzh","application/x-lzh") ,("lzx","application/x-lzx") ,("m3u","audio/mpegurl") ,("m4a","audio/mpeg") ,("maker","application/x-maker") ,("man","application/x-troff-man") ,("mcif","chemical/x-mmcif") ,("mcm","chemical/x-macmolecule") ,("mdb","application/msaccess") ,("me","application/x-troff-me") ,("mesh","model/mesh") ,("mid","audio/midi") ,("midi","audio/midi") ,("mif","application/x-mif") ,("mm","application/x-freemind") ,("mmd","chemical/x-macromodel-input") ,("mmf","application/vnd.smaf") ,("mml","text/mathml") ,("mmod","chemical/x-macromodel-input") ,("mng","video/x-mng") ,("moc","text/x-moc") ,("mol","chemical/x-mdl-molfile") ,("mol2","chemical/x-mol2") ,("moo","chemical/x-mopac-out") ,("mop","chemical/x-mopac-input") ,("mopcrt","chemical/x-mopac-input") ,("mov","video/quicktime") ,("movie","video/x-sgi-movie") ,("mp2","audio/mpeg") ,("mp3","audio/mpeg") ,("mp4","video/mp4") ,("mpc","chemical/x-mopac-input") ,("mpe","video/mpeg") ,("mpeg","video/mpeg") ,("mpega","audio/mpeg") ,("mpg","video/mpeg") ,("mpga","audio/mpeg") ,("ms","application/x-troff-ms") ,("msh","model/mesh") ,("msi","application/x-msi") ,("mvb","chemical/x-mopac-vib") ,("mxu","video/vnd.mpegurl") ,("nb","application/mathematica") ,("nc","application/x-netcdf") ,("nwc","application/x-nwc") ,("o","application/x-object") ,("oda","application/oda") ,("odb","application/vnd.oasis.opendocument.database") ,("odc","application/vnd.oasis.opendocument.chart") ,("odf","application/vnd.oasis.opendocument.formula") ,("odg","application/vnd.oasis.opendocument.graphics") ,("odi","application/vnd.oasis.opendocument.image") ,("odm","application/vnd.oasis.opendocument.text-master") ,("odp","application/vnd.oasis.opendocument.presentation") ,("ods","application/vnd.oasis.opendocument.spreadsheet") ,("odt","application/vnd.oasis.opendocument.text") ,("oga","audio/ogg") ,("ogg","application/ogg") ,("ogv","video/ogg") ,("ogx","application/ogg") ,("old","application/x-trash") ,("otg","application/vnd.oasis.opendocument.graphics-template") ,("oth","application/vnd.oasis.opendocument.text-web") ,("otp","application/vnd.oasis.opendocument.presentation-template") ,("ots","application/vnd.oasis.opendocument.spreadsheet-template") ,("otf","application/x-font-opentype") ,("ott","application/vnd.oasis.opendocument.text-template") ,("oza","application/x-oz-application") ,("p","text/x-pascal") ,("p7r","application/x-pkcs7-certreqresp") ,("pac","application/x-ns-proxy-autoconfig") ,("pas","text/x-pascal") ,("pat","image/x-coreldrawpattern") ,("patch","text/x-diff") ,("pbm","image/x-portable-bitmap") ,("pcap","application/cap") ,("pcf","application/x-font") ,("pcf.Z","application/x-font") ,("pcx","image/pcx") ,("pdb","chemical/x-pdb") ,("pdf","application/pdf") ,("pfa","application/x-font") ,("pfb","application/x-font") ,("pgm","image/x-portable-graymap") ,("pgn","application/x-chess-pgn") ,("pgp","application/pgp-signature") ,("php","application/x-httpd-php") ,("php3","application/x-httpd-php3") ,("php3p","application/x-httpd-php3-preprocessed") ,("php4","application/x-httpd-php4") ,("phps","application/x-httpd-php-source") ,("pht","application/x-httpd-php") ,("phtml","application/x-httpd-php") ,("pk","application/x-tex-pk") ,("pl","text/x-perl") ,("pls","audio/x-scpls") ,("pm","text/x-perl") ,("png","image/png") ,("pnm","image/x-portable-anymap") ,("pot","text/plain") ,("ppm","image/x-portable-pixmap") ,("pps","application/vnd.ms-powerpoint") ,("ppt","application/vnd.ms-powerpoint") ,("prf","application/pics-rules") ,("prt","chemical/x-ncbi-asn1-ascii") ,("ps","application/postscript") ,("psd","image/x-photoshop") ,("py","text/x-python") ,("pyc","application/x-python-code") ,("pyo","application/x-python-code") ,("qt","video/quicktime") ,("qtl","application/x-quicktimeplayer") ,("ra","audio/x-pn-realaudio") ,("ram","audio/x-pn-realaudio") ,("rar","application/rar") ,("ras","image/x-cmu-raster") ,("rd","chemical/x-mdl-rdfile") ,("rdf","application/rdf+xml") ,("rgb","image/x-rgb") ,("rhtml","application/x-httpd-eruby") ,("rm","audio/x-pn-realaudio") ,("roff","application/x-troff") ,("ros","chemical/x-rosdal") ,("rpm","application/x-redhat-package-manager") ,("rss","application/rss+xml") ,("rtf","application/rtf") ,("rtx","text/richtext") ,("rxn","chemical/x-mdl-rxnfile") ,("sct","text/scriptlet") ,("sd","chemical/x-mdl-sdfile") ,("sd2","audio/x-sd2") ,("sda","application/vnd.stardivision.draw") ,("sdc","application/vnd.stardivision.calc") ,("sdd","application/vnd.stardivision.impress") ,("sdf","application/vnd.stardivision.math") ,("sds","application/vnd.stardivision.chart") ,("sdw","application/vnd.stardivision.writer") ,("ser","application/java-serialized-object") ,("sgf","application/x-go-sgf") ,("sgl","application/vnd.stardivision.writer-global") ,("sh","application/x-sh") ,("shar","application/x-shar") ,("shtml","text/html") ,("sid","audio/prs.sid") ,("sik","application/x-trash") ,("silo","model/mesh") ,("sis","application/vnd.symbian.install") ,("sisx","x-epoc/x-sisx-app") ,("sit","application/x-stuffit") ,("sitx","application/x-stuffit") ,("skd","application/x-koan") ,("skm","application/x-koan") ,("skp","application/x-koan") ,("skt","application/x-koan") ,("smi","application/smil") ,("smil","application/smil") ,("snd","audio/basic") ,("spc","chemical/x-galactic-spc") ,("spl","application/futuresplash") ,("spx","audio/ogg") ,("src","application/x-wais-source") ,("stc","application/vnd.sun.xml.calc.template") ,("std","application/vnd.sun.xml.draw.template") ,("sti","application/vnd.sun.xml.impress.template") ,("stl","application/vnd.ms-pki.stl") ,("stw","application/vnd.sun.xml.writer.template") ,("sty","text/x-tex") ,("sv4cpio","application/x-sv4cpio") ,("sv4crc","application/x-sv4crc") ,("svg","image/svg+xml") ,("svgz","image/svg+xml") ,("sw","chemical/x-swissprot") ,("swf","application/x-shockwave-flash") ,("swfl","application/x-shockwave-flash") ,("sxc","application/vnd.sun.xml.calc") ,("sxd","application/vnd.sun.xml.draw") ,("sxg","application/vnd.sun.xml.writer.global") ,("sxi","application/vnd.sun.xml.impress") ,("sxm","application/vnd.sun.xml.math") ,("sxw","application/vnd.sun.xml.writer") ,("t","application/x-troff") ,("tar","application/x-tar") ,("taz","application/x-gtar") ,("tcl","application/x-tcl") ,("tex","text/x-tex") ,("texi","application/x-texinfo") ,("texinfo","application/x-texinfo") ,("text","text/plain") ,("tgf","chemical/x-mdl-tgf") ,("tgz","application/x-gtar") ,("tif","image/tiff") ,("tiff","image/tiff") ,("tk","text/x-tcl") ,("tm","text/texmacs") ,("torrent","application/x-bittorrent") ,("tr","application/x-troff") ,("ts","text/texmacs") ,("tsp","application/dsptype") ,("tsv","text/tab-separated-values") ,("ttf","application/x-font-truetype") ,("txt","text/plain") ,("udeb","application/x-debian-package") ,("uls","text/iuls") ,("ustar","application/x-ustar") ,("val","chemical/x-ncbi-asn1-binary") ,("vcd","application/x-cdlink") ,("vcf","text/x-vcard") ,("vcs","text/x-vcalendar") ,("vmd","chemical/x-vmd") ,("vms","chemical/x-vamas-iso14976") ,("vrm","x-world/x-vrml") ,("vrml","model/vrml") ,("vs","text/plain") ,("vsd","application/vnd.visio") ,("wad","application/x-doom") ,("wav","audio/x-wav") ,("wax","audio/x-ms-wax") ,("wbmp","image/vnd.wap.wbmp") ,("wbxml","application/vnd.wap.wbxml") ,("webm","video/webm") ,("wk","application/x-123") ,("wm","video/x-ms-wm") ,("wma","audio/x-ms-wma") ,("wmd","application/x-ms-wmd") ,("wml","text/vnd.wap.wml") ,("wmlc","application/vnd.wap.wmlc") ,("wmls","text/vnd.wap.wmlscript") ,("wmlsc","application/vnd.wap.wmlscriptc") ,("wmv","video/x-ms-wmv") ,("wmx","video/x-ms-wmx") ,("wmz","application/x-ms-wmz") ,("woff","application/x-font-woff") ,("wp5","application/wordperfect5.1") ,("wpd","application/wordperfect") ,("wrl","model/vrml") ,("wsc","text/scriptlet") ,("wvx","video/x-ms-wvx") ,("wz","application/x-wingz") ,("xbm","image/x-xbitmap") ,("xcf","application/x-xcf") ,("xht","application/xhtml+xml") ,("xhtml","application/xhtml+xml") ,("xlb","application/vnd.ms-excel") ,("xls","application/vnd.ms-excel") ,("xlt","application/vnd.ms-excel") ,("xml","application/xml") ,("xpi","application/x-xpinstall") ,("xpm","image/x-xpixmap") ,("xsl","application/xml") ,("xtel","chemical/x-xtel") ,("xul","application/vnd.mozilla.xul+xml") ,("xwd","image/x-xwindowdump") ,("xyz","chemical/x-xyz") ,("zip","application/zip") ,("zmt","chemical/x-mopac-input") ] pandoc-1.12.2.1/src/Text/Pandoc/Options.hs000644 000765 000024 00000040166 12251233602 020031 0ustar00jgmstaff000000 000000 {- Copyright (C) 2012 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Options Copyright : Copyright (C) 2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Data structures and functions for representing parser and writer options. -} module Text.Pandoc.Options ( Extension(..) , pandocExtensions , strictExtensions , phpMarkdownExtraExtensions , githubMarkdownExtensions , multimarkdownExtensions , ReaderOptions(..) , HTMLMathMethod (..) , CiteMethod (..) , ObfuscationMethod (..) , HTMLSlideVariant (..) , EPUBVersion (..) , WriterOptions (..) , def , isEnabled ) where import Data.Set (Set) import qualified Data.Set as Set import Data.Default import Text.Pandoc.Highlighting (Style, pygments) -- | Individually selectable syntax extensions. data Extension = Ext_footnotes -- ^ Pandoc/PHP/MMD style footnotes | Ext_inline_notes -- ^ Pandoc-style inline notes | Ext_pandoc_title_block -- ^ Pandoc title block | Ext_yaml_metadata_block -- ^ YAML metadata block | Ext_mmd_title_block -- ^ Multimarkdown metadata block | Ext_table_captions -- ^ Pandoc-style table captions | Ext_implicit_figures -- ^ A paragraph with just an image is a figure | Ext_simple_tables -- ^ Pandoc-style simple tables | Ext_multiline_tables -- ^ Pandoc-style multiline tables | Ext_grid_tables -- ^ Grid tables (pandoc, reST) | Ext_pipe_tables -- ^ Pipe tables (as in PHP markdown extra) | Ext_citations -- ^ Pandoc/citeproc citations | Ext_raw_tex -- ^ Allow raw TeX (other than math) | Ext_raw_html -- ^ Allow raw HTML | Ext_tex_math_dollars -- ^ TeX math between $..$ or $$..$$ | Ext_tex_math_single_backslash -- ^ TeX math btw \(..\) \[..\] | Ext_tex_math_double_backslash -- ^ TeX math btw \\(..\\) \\[..\\] | Ext_latex_macros -- ^ Parse LaTeX macro definitions (for math only) | Ext_fenced_code_blocks -- ^ Parse fenced code blocks | Ext_fenced_code_attributes -- ^ Allow attributes on fenced code blocks | Ext_backtick_code_blocks -- ^ Github style ``` code blocks | Ext_inline_code_attributes -- ^ Allow attributes on inline code | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks | Ext_markdown_attribute -- ^ Interpret text inside HTML as markdown -- iff container has attribute 'markdown' | Ext_escaped_line_breaks -- ^ Treat a backslash at EOL as linebreak | Ext_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 | Ext_all_symbols_escapable -- ^ Make all non-alphanumerics escapable | Ext_intraword_underscores -- ^ Treat underscore inside word as literal | Ext_blank_before_blockquote -- ^ Require blank line before a blockquote | Ext_blank_before_header -- ^ Require blank line before a header | Ext_strikeout -- ^ Strikeout using ~~this~~ syntax | Ext_superscript -- ^ Superscript using ^this^ syntax | Ext_subscript -- ^ Subscript using ~this~ syntax | Ext_hard_line_breaks -- ^ All newlines become hard line breaks | Ext_ignore_line_breaks -- ^ Newlines in paragraphs are ignored | Ext_literate_haskell -- ^ Enable literate Haskell conventions | Ext_abbreviations -- ^ PHP markdown extra abbreviation definitions | Ext_auto_identifiers -- ^ Automatic identifiers for headers | Ext_ascii_identifiers -- ^ ascii-only identifiers for headers | Ext_header_attributes -- ^ Explicit header attributes {#id .class k=v} | Ext_mmd_header_identifiers -- ^ Multimarkdown style header identifiers [myid] | Ext_implicit_header_references -- ^ Implicit reference links for headers | Ext_line_blocks -- ^ RST style line blocks deriving (Show, Read, Enum, Eq, Ord, Bounded) pandocExtensions :: Set Extension pandocExtensions = Set.fromList [ Ext_footnotes , Ext_inline_notes , Ext_pandoc_title_block , Ext_yaml_metadata_block , Ext_table_captions , Ext_implicit_figures , Ext_simple_tables , Ext_multiline_tables , Ext_grid_tables , Ext_pipe_tables , Ext_citations , Ext_raw_tex , Ext_raw_html , Ext_tex_math_dollars , Ext_latex_macros , Ext_fenced_code_blocks , Ext_fenced_code_attributes , Ext_backtick_code_blocks , Ext_inline_code_attributes , Ext_markdown_in_html_blocks , Ext_escaped_line_breaks , Ext_fancy_lists , Ext_startnum , Ext_definition_lists , Ext_example_lists , Ext_all_symbols_escapable , Ext_intraword_underscores , Ext_blank_before_blockquote , Ext_blank_before_header , Ext_strikeout , Ext_superscript , Ext_subscript , Ext_auto_identifiers , Ext_header_attributes , Ext_implicit_header_references , Ext_line_blocks ] phpMarkdownExtraExtensions :: Set Extension phpMarkdownExtraExtensions = Set.fromList [ Ext_footnotes , Ext_pipe_tables , Ext_raw_html , Ext_markdown_attribute , Ext_fenced_code_blocks , Ext_definition_lists , Ext_intraword_underscores , Ext_header_attributes , Ext_abbreviations ] githubMarkdownExtensions :: Set Extension githubMarkdownExtensions = Set.fromList [ Ext_pipe_tables , Ext_raw_html , Ext_tex_math_single_backslash , Ext_fenced_code_blocks , Ext_fenced_code_attributes , Ext_auto_identifiers , Ext_ascii_identifiers , Ext_backtick_code_blocks , Ext_autolink_bare_uris , Ext_intraword_underscores , Ext_strikeout , Ext_hard_line_breaks , Ext_lists_without_preceding_blankline ] multimarkdownExtensions :: Set Extension multimarkdownExtensions = Set.fromList [ Ext_pipe_tables , Ext_raw_html , Ext_markdown_attribute , Ext_link_attributes , Ext_raw_tex , Ext_tex_math_double_backslash , Ext_intraword_underscores , Ext_mmd_title_block , Ext_footnotes , Ext_definition_lists , Ext_all_symbols_escapable , Ext_implicit_header_references , Ext_auto_identifiers , Ext_mmd_header_identifiers ] strictExtensions :: Set Extension strictExtensions = Set.fromList [ Ext_raw_html ] data ReaderOptions = ReaderOptions{ readerExtensions :: Set Extension -- ^ Syntax extensions , readerSmart :: Bool -- ^ Smart punctuation , readerStrict :: Bool -- ^ FOR TRANSITION ONLY , readerStandalone :: Bool -- ^ Standalone document with header , readerParseRaw :: Bool -- ^ Parse raw HTML, LaTeX , readerColumns :: Int -- ^ Number of columns in terminal , readerTabStop :: Int -- ^ Tab stop , readerOldDashes :: Bool -- ^ Use pandoc <= 1.8.2.1 behavior -- in parsing dashes; -- is em-dash; -- - before numerial is en-dash , readerApplyMacros :: Bool -- ^ Apply macros to TeX math , readerIndentedCodeClasses :: [String] -- ^ Default classes for -- indented code blocks , readerDefaultImageExtension :: String -- ^ Default extension for images } deriving (Show, Read) instance Default ReaderOptions where def = ReaderOptions{ readerExtensions = pandocExtensions , readerSmart = False , readerStrict = False , readerStandalone = False , readerParseRaw = False , readerColumns = 80 , readerTabStop = 4 , readerOldDashes = False , readerApplyMacros = True , readerIndentedCodeClasses = [] , readerDefaultImageExtension = "" } -- -- Writer options -- data EPUBVersion = EPUB2 | EPUB3 deriving (Eq, Show, Read) data HTMLMathMethod = PlainMath | LaTeXMathML (Maybe String) -- url of LaTeXMathML.js | JsMath (Maybe String) -- url of jsMath load script | GladTeX | WebTeX String -- url of TeX->image script. | MathML (Maybe String) -- url of MathMLinHTML.js | MathJax String -- url of MathJax.js deriving (Show, Read, Eq) data CiteMethod = Citeproc -- use citeproc to render them | Natbib -- output natbib cite commands | Biblatex -- output biblatex cite commands deriving (Show, Read, Eq) -- | Methods for obfuscating email addresses in HTML. data ObfuscationMethod = NoObfuscation | ReferenceObfuscation | JavascriptObfuscation deriving (Show, Read, Eq) -- | Varieties of HTML slide shows. data HTMLSlideVariant = S5Slides | SlidySlides | SlideousSlides | DZSlides | RevealJsSlides | NoSlides deriving (Show, Read, Eq) -- | Options for writers data WriterOptions = WriterOptions { writerStandalone :: Bool -- ^ Include header and footer , writerTemplate :: String -- ^ Template to use in standalone mode , writerVariables :: [(String, String)] -- ^ Variables to set in template , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs , writerTableOfContents :: Bool -- ^ Include table of contents , writerSlideVariant :: HTMLSlideVariant -- ^ Are we writing S5, Slidy or Slideous? , writerIncremental :: Bool -- ^ True if lists should be incremental , writerHTMLMathMethod :: HTMLMathMethod -- ^ How to print math in HTML , writerIgnoreNotes :: Bool -- ^ Ignore footnotes (used in making toc) , writerNumberSections :: Bool -- ^ Number sections in LaTeX , writerNumberOffset :: [Int] -- ^ Starting number for section, subsection, ... , writerSectionDivs :: Bool -- ^ Put sections in div tags in HTML , writerExtensions :: Set Extension -- ^ Markdown extensions that can be used , writerReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst , writerWrapText :: Bool -- ^ Wrap text to line length , writerColumns :: Int -- ^ Characters in a line (for text wrapping) , writerEmailObfuscation :: ObfuscationMethod -- ^ How to obfuscate emails , writerIdentifierPrefix :: String -- ^ Prefix for section & note ids in HTML -- and for footnote marks in markdown , writerSourceURL :: Maybe String -- ^ Absolute URL + directory of 1st source file , writerUserDataDir :: Maybe FilePath -- ^ Path of user data directory , writerCiteMethod :: CiteMethod -- ^ How to print cites , writerHtml5 :: Bool -- ^ Produce HTML5 , writerHtmlQTags :: Bool -- ^ Use @@ tags for quotes in HTML , writerBeamer :: Bool -- ^ Produce beamer LaTeX slide show , writerSlideLevel :: Maybe Int -- ^ Force header level of slides , writerChapters :: Bool -- ^ Use "chapter" for top-level sects , writerListings :: Bool -- ^ Use listings package for code , writerHighlight :: Bool -- ^ Highlight source code , writerHighlightStyle :: Style -- ^ Style to use for highlighting , writerSetextHeaders :: Bool -- ^ Use setext headers for levels 1-2 in markdown , writerTeXLigatures :: Bool -- ^ Use tex ligatures quotes, dashes in latex , writerEpubVersion :: Maybe EPUBVersion -- ^ Nothing or EPUB version , writerEpubMetadata :: String -- ^ Metadata to include in EPUB , writerEpubStylesheet :: Maybe String -- ^ EPUB stylesheet specified at command line , writerEpubFonts :: [FilePath] -- ^ Paths to fonts to embed , writerEpubChapterLevel :: Int -- ^ Header level for chapters (separate files) , writerTOCDepth :: Int -- ^ Number of levels to include in TOC , writerReferenceODT :: Maybe FilePath -- ^ Path to reference ODT if specified , writerReferenceDocx :: Maybe FilePath -- ^ Ptah to reference DOCX if specified } deriving Show instance Default WriterOptions where def = WriterOptions { writerStandalone = False , writerTemplate = "" , writerVariables = [] , writerTabStop = 4 , writerTableOfContents = False , writerSlideVariant = NoSlides , writerIncremental = False , writerHTMLMathMethod = PlainMath , writerIgnoreNotes = False , writerNumberSections = False , writerNumberOffset = [0,0,0,0,0,0] , writerSectionDivs = False , writerExtensions = pandocExtensions , writerReferenceLinks = False , writerWrapText = True , writerColumns = 72 , writerEmailObfuscation = JavascriptObfuscation , writerIdentifierPrefix = "" , writerSourceURL = Nothing , writerUserDataDir = Nothing , writerCiteMethod = Citeproc , writerHtml5 = False , writerHtmlQTags = False , writerBeamer = False , writerSlideLevel = Nothing , writerChapters = False , writerListings = False , writerHighlight = False , writerHighlightStyle = pygments , writerSetextHeaders = True , writerTeXLigatures = True , writerEpubVersion = Nothing , writerEpubMetadata = "" , writerEpubStylesheet = Nothing , writerEpubFonts = [] , writerEpubChapterLevel = 1 , writerTOCDepth = 3 , writerReferenceODT = Nothing , writerReferenceDocx = Nothing } -- | Returns True if the given extension is enabled. isEnabled :: Extension -> WriterOptions -> Bool isEnabled ext opts = ext `Set.member` (writerExtensions opts) pandoc-1.12.2.1/src/Text/Pandoc/Parsing.hs000644 000765 000024 00000127576 12251233602 020014 0ustar00jgmstaff000000 000000 {-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances#-} {- Copyright (C) 2006-2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Parsing Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable A utility library with parsers used in pandoc readers. -} module Text.Pandoc.Parsing ( (>>~), anyLine, many1Till, notFollowedBy', oneOfStrings, oneOfStringsCI, spaceChar, nonspaceChar, skipSpaces, blankline, blanklines, enclosed, stringAnyCase, parseFromString, lineClump, charsInBalanced, romanNumeral, emailAddress, uri, mathInline, mathDisplay, withHorizDisplacement, withRaw, escaped, characterReference, updateLastStrPos, anyOrderedListMarker, orderedListMarker, charRef, lineBlockLines, tableWith, widthsFromIndices, gridTableWith, readWith, testStringWith, getOption, guardEnabled, guardDisabled, ParserState (..), HasReaderOptions (..), HasHeaderMap (..), HasIdentifierList (..), defaultParserState, HeaderType (..), ParserContext (..), QuoteContext (..), NoteTable, NoteTable', KeyTable, SubstTable, Key (..), toKey, registerHeader, smartPunctuation, withQuoteContext, singleQuoteStart, singleQuoteEnd, doubleQuoteStart, doubleQuoteEnd, ellipses, apostrophe, dash, nested, macro, applyMacros', Parser, F(..), runF, askF, asksF, -- * Re-exports from Text.Pandoc.Parsec runParser, parse, anyToken, getInput, setInput, unexpected, char, letter, digit, alphaNum, skipMany, skipMany1, spaces, space, anyChar, satisfy, newline, string, count, eof, noneOf, oneOf, lookAhead, notFollowedBy, many, many1, manyTill, (<|>), (), choice, try, sepBy, sepBy1, sepEndBy, sepEndBy1, endBy, endBy1, option, optional, optionMaybe, getState, setState, updateState, SourcePos, getPosition, setPosition, sourceColumn, sourceLine, setSourceColumn, setSourceLine, newPos, token ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Builder (Blocks, Inlines, rawBlock, HasMeta(..)) import qualified Text.Pandoc.Builder as B import Text.Pandoc.XML (fromEntities) import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn) import Text.Parsec import Text.Parsec.Pos (newPos) import Data.Char ( toLower, toUpper, ord, chr, isAscii, isAlphaNum, isDigit, isHexDigit, isSpace ) import Data.List ( intercalate, transpose ) import Text.Pandoc.Shared import qualified Data.Map as M import Text.TeXMath.Macros (applyMacros, Macro, parseMacroDefinitions) import Text.Pandoc.Compat.TagSoupEntity ( lookupEntity ) import Text.Pandoc.Asciify (toAsciiChar) import Data.Default import qualified Data.Set as Set import Control.Monad.Reader import Control.Applicative ((*>), (<*), (<$), liftA2) import Data.Monoid import Data.Maybe (catMaybes) type Parser t s = Parsec t s newtype F a = F { unF :: Reader ParserState a } deriving (Monad, Functor) runF :: F a -> ParserState -> a runF = runReader . unF askF :: F ParserState askF = F ask asksF :: (ParserState -> a) -> F a asksF f = F $ asks f instance Monoid a => Monoid (F a) where mempty = return mempty mappend = liftM2 mappend mconcat = liftM mconcat . sequence -- | Like >>, but returns the operation on the left. -- (Suggested by Tillmann Rendel on Haskell-cafe list.) (>>~) :: (Monad m) => m a -> m b -> m a a >>~ b = a >>= \x -> b >> return x -- | Parse any line of text anyLine :: Parser [Char] st [Char] anyLine = do -- This is much faster than: -- manyTill anyChar newline inp <- getInput pos <- getPosition case break (=='\n') inp of (this, '\n':rest) -> do -- needed to persuade parsec that this won't match an empty string: anyChar setInput rest setPosition $ incSourceLine (setSourceColumn pos 1) 1 return this _ -> mzero -- | Like @manyTill@, but reads at least one item. many1Till :: Parser [tok] st a -> Parser [tok] st end -> Parser [tok] st [a] many1Till p end = do first <- p rest <- manyTill p end return (first:rest) -- | A more general form of @notFollowedBy@. This one allows any -- type of parser to be specified, and succeeds only if that parser fails. -- It does not consume any input. notFollowedBy' :: Show b => Parser [a] st b -> Parser [a] st () notFollowedBy' p = try $ join $ do a <- try p return (unexpected (show a)) <|> return (return ()) -- (This version due to Andrew Pimlott on the Haskell mailing list.) oneOfStrings' :: (Char -> Char -> Bool) -> [String] -> Parser [Char] st String oneOfStrings' _ [] = fail "no strings" oneOfStrings' matches strs = try $ do c <- anyChar let strs' = [xs | (x:xs) <- strs, x `matches` c] case strs' of [] -> fail "not found" _ -> (c:) `fmap` oneOfStrings' matches strs' <|> if "" `elem` strs' then return [c] else fail "not found" -- | Parses one of a list of strings. If the list contains -- two strings one of which is a prefix of the other, the longer -- string will be matched if possible. oneOfStrings :: [String] -> Parser [Char] st String oneOfStrings = oneOfStrings' (==) -- | Parses one of a list of strings (tried in order), case insensitive. oneOfStringsCI :: [String] -> Parser [Char] st String oneOfStringsCI = oneOfStrings' ciMatch where ciMatch x y = toLower' x == toLower' y -- this optimizes toLower by checking common ASCII case -- first, before calling the expensive unicode-aware -- function: toLower' c | c >= 'A' && c <= 'Z' = chr (ord c + 32) | isAscii c = c | otherwise = toLower c -- | Parses a space or tab. spaceChar :: Parser [Char] st Char 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' -- | Skips zero or more spaces or tabs. skipSpaces :: Parser [Char] st () skipSpaces = skipMany spaceChar -- | Skips zero or more spaces or tabs, then reads a newline. blankline :: Parser [Char] st Char blankline = try $ skipSpaces >> newline -- | Parses one or more blank lines and returns a string of newlines. blanklines :: Parser [Char] st [Char] blanklines = many1 blankline -- | Parses material enclosed between start and end parsers. enclosed :: Parser [Char] st t -- ^ start parser -> Parser [Char] st end -- ^ end parser -> Parser [Char] st a -- ^ content parser (to be used repeatedly) -> Parser [Char] st [a] enclosed start end parser = try $ start >> notFollowedBy space >> many1Till parser end -- | Parse string, case insensitive. stringAnyCase :: [Char] -> Parser [Char] st String stringAnyCase [] = string "" stringAnyCase (x:xs) = do firstChar <- char (toUpper x) <|> char (toLower x) rest <- stringAnyCase xs return (firstChar:rest) -- | Parse contents of 'str' using 'parser' and return result. parseFromString :: Parser [tok] st a -> [tok] -> Parser [tok] st a parseFromString parser str = do oldPos <- getPosition oldInput <- getInput setInput str result <- parser setInput oldInput setPosition oldPos return result -- | Parse raw line block up to and including blank lines. lineClump :: Parser [Char] st String lineClump = blanklines <|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines) -- | Parse a string of characters between an open character -- and a close character, including text between balanced -- pairs of open and close, which must be different. For example, -- @charsInBalanced '(' ')' anyChar@ will parse "(hello (there))" -- and return "hello (there)". charsInBalanced :: Char -> Char -> Parser [Char] st Char -> Parser [Char] st String charsInBalanced open close parser = try $ do char open let isDelim c = c == open || c == close raw <- many $ many1 (notFollowedBy (satisfy isDelim) >> parser) <|> (do res <- charsInBalanced open close parser return $ [open] ++ res ++ [close]) char close return $ concat raw -- old charsInBalanced would be: -- charsInBalanced open close (noneOf "\n" <|> char '\n' >> notFollowedBy blankline) -- old charsInBalanced' would be: -- charsInBalanced open close anyChar -- Auxiliary functions for romanNumeral: lowercaseRomanDigits :: [Char] lowercaseRomanDigits = ['i','v','x','l','c','d','m'] uppercaseRomanDigits :: [Char] uppercaseRomanDigits = map toUpper lowercaseRomanDigits -- | Parses a roman numeral (uppercase or lowercase), returns number. romanNumeral :: Bool -- ^ Uppercase if true -> Parser [Char] st Int romanNumeral upperCase = do let romanDigits = if upperCase then uppercaseRomanDigits else lowercaseRomanDigits lookAhead $ oneOf romanDigits let [one, five, ten, fifty, hundred, fivehundred, thousand] = map char romanDigits thousands <- many thousand >>= (return . (1000 *) . length) ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900 fivehundreds <- many fivehundred >>= (return . (500 *) . length) fourhundreds <- option 0 $ try $ hundred >> fivehundred >> return 400 hundreds <- many hundred >>= (return . (100 *) . length) nineties <- option 0 $ try $ ten >> hundred >> return 90 fifties <- many fifty >>= (return . (50 *) . length) forties <- option 0 $ try $ ten >> fifty >> return 40 tens <- many ten >>= (return . (10 *) . length) nines <- option 0 $ try $ one >> ten >> return 9 fives <- many five >>= (return . (5 *) . length) fours <- option 0 $ try $ one >> five >> return 4 ones <- many one >>= (return . length) let total = thousands + ninehundreds + fivehundreds + fourhundreds + hundreds + nineties + fifties + forties + tens + nines + fives + fours + ones if total == 0 then fail "not a roman numeral" else return total -- Parsers for email addresses and URIs -- | Parses an email address; returns original and corresponding -- escaped mailto: URI. emailAddress :: Parser [Char] st (String, String) emailAddress = try $ liftA2 toResult mailbox (char '@' *> domain) where toResult mbox dom = let full = fromEntities $ mbox ++ '@':dom in (full, escapeURI $ "mailto:" ++ full) mailbox = intercalate "." `fmap` (emailWord `sepby1` dot) domain = intercalate "." `fmap` (subdomain `sepby1` dot) dot = char '.' subdomain = many1 $ alphaNum <|> innerPunct innerPunct = try (satisfy (\c -> isEmailPunct c || c == '@') <* notFollowedBy space) emailWord = many1 $ satisfy isEmailChar isEmailChar c = isAlphaNum c || isEmailPunct c isEmailPunct c = c `elem` "!\"#$%&'*+-/=?^_{|}~;" -- note: sepBy1 from parsec consumes input when sep -- succeeds and p fails, so we use this variant here. sepby1 p sep = liftA2 (:) p (many (try $ sep >> p)) -- Schemes from http://www.iana.org/assignments/uri-schemes.html plus -- the unofficial schemes coap, doi, javascript. schemes :: [String] schemes = ["coap","doi","javascript","aaa","aaas","about","acap","cap","cid", "crid","data","dav","dict","dns","file","ftp","geo","go","gopher", "h323","http","https","iax","icap","im","imap","info","ipp","iris", "iris.beep","iris.xpc","iris.xpcs","iris.lwz","ldap","mailto","mid", "msrp","msrps","mtqp","mupdate","news","nfs","ni","nih","nntp", "opaquelocktoken","pop","pres","rtsp","service","session","shttp","sieve", "sip","sips","sms","snmp","soap.beep","soap.beeps","tag","tel","telnet", "tftp","thismessage","tn3270","tip","tv","urn","vemmi","ws","wss","xcon", "xcon-userid","xmlrpc.beep","xmlrpc.beeps","xmpp","z39.50r","z39.50s", "adiumxtra","afp","afs","aim","apt","attachment","aw","beshare","bitcoin", "bolo","callto","chrome","chrome-extension","com-eventbrite-attendee", "content", "cvs","dlna-playsingle","dlna-playcontainer","dtn","dvb", "ed2k","facetime","feed","finger","fish","gg","git","gizmoproject", "gtalk","hcp","icon","ipn","irc","irc6","ircs","itms","jar","jms", "keyparc","lastfm","ldaps","magnet","maps","market","message","mms", "ms-help","msnim","mumble","mvn","notes","oid","palm","paparazzi", "platform","proxy","psyc","query","res","resource","rmi","rsync", "rtmp","secondlife","sftp","sgn","skype","smb","soldat","spotify", "ssh","steam","svn","teamspeak","things","udp","unreal","ut2004", "ventrilo","view-source","webcal","wtai","wyciwyg","xfire","xri", "ymsgr"] uriScheme :: Parser [Char] st String uriScheme = oneOfStringsCI schemes -- | Parses a URI. Returns pair of original and URI-escaped version. uri :: Parser [Char] st (String, String) uri = try $ do scheme <- uriScheme char ':' -- We allow punctuation except at the end, since -- we don't want the trailing '.' in 'http://google.com.' We want to allow -- http://en.wikipedia.org/wiki/State_of_emergency_(disambiguation) -- as a URL, while NOT picking up the closing paren in -- (http://wikipedia.org). So we include balanced parens in the URL. let isWordChar c = isAlphaNum c || c == '_' || c == '/' || c == '+' || not (isAscii c) let wordChar = satisfy isWordChar let percentEscaped = try $ char '%' >> skipMany1 (satisfy isHexDigit) let entity = () <$ characterReference let punct = skipMany1 (char ',') <|> () <$ (satisfy (\c -> not (isSpace c) && c /= '<')) let uriChunk = skipMany1 wordChar <|> percentEscaped <|> entity <|> (try $ punct >> lookAhead (void (satisfy isWordChar) <|> percentEscaped)) str <- snd `fmap` withRaw (skipMany1 ( () <$ (enclosed (char '(') (char ')') uriChunk <|> enclosed (char '{') (char '}') uriChunk <|> enclosed (char '[') (char ']') uriChunk) <|> uriChunk)) str' <- option str $ char '/' >> return (str ++ "/") 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 -- (source row) is ignored. withHorizDisplacement :: Parser [Char] st a -- ^ Parser to apply -> Parser [Char] st (a, Int) -- ^ (result, displacement) withHorizDisplacement parser = do pos1 <- getPosition result <- parser pos2 <- getPosition return (result, sourceColumn pos2 - sourceColumn pos1) -- | Applies a parser and returns the raw string that was parsed, -- along with the value produced by the parser. withRaw :: Parser [Char] st a -> Parser [Char] st (a, [Char]) withRaw parser = do pos1 <- getPosition inp <- getInput result <- parser pos2 <- getPosition let (l1,c1) = (sourceLine pos1, sourceColumn pos1) let (l2,c2) = (sourceLine pos2, sourceColumn pos2) let inplines = take ((l2 - l1) + 1) $ lines inp let raw = case inplines of [] -> "" [l] -> take (c2 - c1) l ls -> unlines (init ls) ++ take (c2 - 1) (last ls) return (result, raw) -- | Parses backslash, then applies character parser. escaped :: Parser [Char] st Char -- ^ Parser for character to escape -> Parser [Char] st Char escaped parser = try $ char '\\' >> parser -- | Parse character entity. characterReference :: Parser [Char] st Char characterReference = try $ do char '&' ent <- many1Till nonspaceChar (char ';') case lookupEntity ent of Just c -> return c Nothing -> fail "entity not found" -- | Parses an uppercase roman numeral and returns (UpperRoman, number). upperRoman :: Parser [Char] st (ListNumberStyle, Int) upperRoman = do num <- romanNumeral True return (UpperRoman, num) -- | Parses a lowercase roman numeral and returns (LowerRoman, number). lowerRoman :: Parser [Char] st (ListNumberStyle, Int) lowerRoman = do num <- romanNumeral False return (LowerRoman, num) -- | Parses a decimal numeral and returns (Decimal, number). decimal :: Parser [Char] st (ListNumberStyle, Int) decimal = do num <- many1 digit return (Decimal, read num) -- | Parses a '@' and optional label and -- returns (DefaultStyle, [next example number]). The next -- example number is incremented in parser state, and the label -- (if present) is added to the label table. exampleNum :: Parser [Char] ParserState (ListNumberStyle, Int) exampleNum = do char '@' lab <- many (alphaNum <|> satisfy (\c -> c == '_' || c == '-')) st <- getState let num = stateNextExample st let newlabels = if null lab then stateExamples st else M.insert lab num $ stateExamples st updateState $ \s -> s{ stateNextExample = num + 1 , stateExamples = newlabels } return (Example, num) -- | Parses a '#' returns (DefaultStyle, 1). defaultNum :: Parser [Char] st (ListNumberStyle, Int) defaultNum = do char '#' return (DefaultStyle, 1) -- | Parses a lowercase letter and returns (LowerAlpha, number). lowerAlpha :: Parser [Char] st (ListNumberStyle, Int) lowerAlpha = do ch <- oneOf ['a'..'z'] return (LowerAlpha, ord ch - ord 'a' + 1) -- | Parses an uppercase letter and returns (UpperAlpha, number). upperAlpha :: Parser [Char] st (ListNumberStyle, Int) upperAlpha = do ch <- oneOf ['A'..'Z'] return (UpperAlpha, ord ch - ord 'A' + 1) -- | Parses a roman numeral i or I romanOne :: Parser [Char] st (ListNumberStyle, Int) romanOne = (char 'i' >> return (LowerRoman, 1)) <|> (char 'I' >> return (UpperRoman, 1)) -- | Parses an ordered list marker and returns list attributes. anyOrderedListMarker :: Parser [Char] ParserState ListAttributes anyOrderedListMarker = choice $ [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens], numParser <- [decimal, exampleNum, defaultNum, romanOne, lowerAlpha, lowerRoman, upperAlpha, upperRoman]] -- | Parses a list number (num) followed by a period, returns list attributes. inPeriod :: Parser [Char] st (ListNumberStyle, Int) -> Parser [Char] st ListAttributes inPeriod num = try $ do (style, start) <- num char '.' let delim = if style == DefaultStyle then DefaultDelim else Period return (start, style, delim) -- | Parses a list number (num) followed by a paren, returns list attributes. inOneParen :: Parser [Char] st (ListNumberStyle, Int) -> Parser [Char] st ListAttributes inOneParen num = try $ do (style, start) <- num char ')' return (start, style, OneParen) -- | Parses a list number (num) enclosed in parens, returns list attributes. inTwoParens :: Parser [Char] st (ListNumberStyle, Int) -> Parser [Char] st ListAttributes inTwoParens num = try $ do char '(' (style, start) <- num char ')' return (start, style, TwoParens) -- | Parses an ordered list marker with a given style and delimiter, -- returns number. orderedListMarker :: ListNumberStyle -> ListNumberDelim -> Parser [Char] ParserState Int orderedListMarker style delim = do let num = defaultNum <|> -- # can continue any kind of list case style of DefaultStyle -> decimal Example -> exampleNum Decimal -> decimal UpperRoman -> upperRoman LowerRoman -> lowerRoman UpperAlpha -> upperAlpha LowerAlpha -> lowerAlpha let context = case delim of DefaultDelim -> inPeriod Period -> inPeriod OneParen -> inOneParen TwoParens -> inTwoParens (start, _, _) <- context num return start -- | Parses a character reference and returns a Str element. charRef :: Parser [Char] st Inline charRef = do c <- characterReference return $ Str [c] lineBlockLine :: Parser [Char] st String lineBlockLine = try $ do char '|' char ' ' white <- many (spaceChar >> return '\160') notFollowedBy newline line <- anyLine continuations <- many (try $ char ' ' >> anyLine) return $ white ++ unwords (line : continuations) -- | Parses an RST-style line block and returns a list of strings. lineBlockLines :: Parser [Char] st [String] lineBlockLines = try $ do lines' <- many1 lineBlockLine skipMany1 $ blankline <|> try (char '|' >> blankline) return lines' -- | Parse a table using 'headerParser', 'rowParser', -- 'lineParser', and 'footerParser'. tableWith :: Parser [Char] ParserState ([[Block]], [Alignment], [Int]) -> ([Int] -> Parser [Char] ParserState [[Block]]) -> Parser [Char] ParserState sep -> Parser [Char] ParserState end -> Parser [Char] ParserState Block tableWith headerParser rowParser lineParser footerParser = try $ do (heads, aligns, indices) <- headerParser lines' <- rowParser indices `sepEndBy1` lineParser footerParser numColumns <- getOption readerColumns let widths = if (indices == []) then replicate (length aligns) 0.0 else widthsFromIndices numColumns indices return $ Table [] aligns widths heads lines' -- Calculate relative widths of table columns, based on indices widthsFromIndices :: Int -- Number of columns on terminal -> [Int] -- Indices -> [Double] -- Fractional relative sizes of columns widthsFromIndices _ [] = [] widthsFromIndices numColumns' indices = let numColumns = max numColumns' (if null indices then 0 else last indices) lengths' = zipWith (-) indices (0:indices) lengths = reverse $ case reverse lengths' of [] -> [] [x] -> [x] -- compensate for the fact that intercolumn -- spaces are counted in widths of all columns -- but the last... (x:y:zs) -> if x < y && y - x <= 2 then y:y:zs else x:y:zs totLength = sum lengths quotient = if totLength > numColumns then fromIntegral totLength else fromIntegral numColumns fracs = map (\l -> (fromIntegral l) / quotient) lengths in tail fracs --- -- Parse a grid table: starts with row of '-' on top, then header -- (which may be grid), then the rows, -- which may be grid, separated by blank lines, and -- ending with a footer (dashed line followed by blank line). gridTableWith :: Parser [Char] ParserState [Block] -- ^ Block list parser -> Bool -- ^ Headerless table -> Parser [Char] ParserState Block gridTableWith blocks headless = tableWith (gridTableHeader headless blocks) (gridTableRow blocks) (gridTableSep '-') gridTableFooter gridTableSplitLine :: [Int] -> String -> [String] gridTableSplitLine indices line = map removeFinalBar $ tail $ splitStringByIndices (init indices) $ trimr line gridPart :: Char -> Parser [Char] st (Int, Int) gridPart ch = do dashes <- many1 (char ch) char '+' return (length dashes, length dashes + 1) gridDashedLines :: Char -> Parser [Char] st [(Int,Int)] gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline removeFinalBar :: String -> String removeFinalBar = reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse -- | Separator between rows of grid table. gridTableSep :: Char -> Parser [Char] ParserState Char gridTableSep ch = try $ gridDashedLines ch >> return '\n' -- | Parse header for a grid table. gridTableHeader :: Bool -- ^ Headerless table -> Parser [Char] ParserState [Block] -> Parser [Char] ParserState ([[Block]], [Alignment], [Int]) gridTableHeader headless blocks = try $ do optional blanklines dashes <- gridDashedLines '-' rawContent <- if headless then return $ repeat "" else many1 (notFollowedBy (gridTableSep '=') >> char '|' >> many1Till anyChar newline) if headless then return () else gridTableSep '=' >> return () let lines' = map snd dashes let indices = scanl (+) 0 lines' let aligns = replicate (length lines') AlignDefault -- RST does not have a notion of alignments let rawHeads = if headless then replicate (length dashes) "" else map (intercalate " ") $ transpose $ map (gridTableSplitLine indices) rawContent heads <- mapM (parseFromString blocks) $ map trim rawHeads return (heads, aligns, indices) gridTableRawLine :: [Int] -> Parser [Char] ParserState [String] gridTableRawLine indices = do char '|' line <- many1Till anyChar newline return (gridTableSplitLine indices line) -- | Parse row of grid table. gridTableRow :: Parser [Char] ParserState [Block] -> [Int] -> Parser [Char] ParserState [[Block]] gridTableRow blocks indices = do colLines <- many1 (gridTableRawLine indices) let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $ transpose colLines mapM (liftM compactifyCell . parseFromString blocks) cols removeOneLeadingSpace :: [String] -> [String] removeOneLeadingSpace xs = if all startsWithSpace xs then map (drop 1) xs else xs where startsWithSpace "" = True startsWithSpace (y:_) = y == ' ' compactifyCell :: [Block] -> [Block] compactifyCell bs = head $ compactify [bs] -- | Parse footer for a grid table. gridTableFooter :: Parser [Char] ParserState [Char] gridTableFooter = blanklines --- -- | Parse a string with a given parser and state. readWith :: Parser [Char] st a -- ^ parser -> st -- ^ initial state -> [Char] -- ^ input -> a readWith parser state input = case runParser parser state "source" input of Left err' -> let errPos = errorPos err' errLine = sourceLine errPos errColumn = sourceColumn errPos theline = (lines input ++ [""]) !! (errLine - 1) in error $ "\nError at " ++ show err' ++ "\n" ++ theline ++ "\n" ++ replicate (errColumn - 1) ' ' ++ "^" Right result -> result -- | Parse a string with @parser@ (for testing). testStringWith :: (Show a) => Parser [Char] ParserState a -> String -> IO () testStringWith parser str = UTF8.putStrLn $ show $ readWith parser defaultParserState str -- | Parsing options. data ParserState = ParserState { stateOptions :: ReaderOptions, -- ^ User options stateParserContext :: ParserContext, -- ^ Inside list? stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment? stateAllowLinks :: Bool, -- ^ Allow parsing of links stateMaxNestingLevel :: Int, -- ^ Max # of nested Strong/Emph stateLastStrPos :: Maybe SourcePos, -- ^ Position after last str parsed stateKeys :: KeyTable, -- ^ List of reference keys (with fallbacks) stateSubstitutions :: SubstTable, -- ^ List of substitution references stateNotes :: NoteTable, -- ^ List of notes (raw bodies) stateNotes' :: NoteTable', -- ^ List of notes (parsed bodies) stateMeta :: Meta, -- ^ Document metadata stateMeta' :: F Meta, -- ^ Document metadata stateHeaderTable :: [HeaderType], -- ^ Ordered list of header types used stateHeaders :: M.Map Inlines String, -- ^ List of headers and ids (used for implicit ref links) stateIdentifiers :: [String], -- ^ List of header identifiers used stateNextExample :: Int, -- ^ Number of next example stateExamples :: M.Map String Int, -- ^ Map from example labels to numbers stateHasChapters :: Bool, -- ^ True if \chapter encountered stateMacros :: [Macro], -- ^ List of macros defined so far stateRstDefaultRole :: String, -- ^ Current rST default interpreted text role stateWarnings :: [String] -- ^ Warnings generated by the parser } instance Default ParserState where def = defaultParserState instance HasMeta ParserState where setMeta field val st = st{ stateMeta = setMeta field val $ stateMeta st } 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, stateParserContext = NullState, stateQuoteContext = NoQuote, stateAllowLinks = True, stateMaxNestingLevel = 6, stateLastStrPos = Nothing, stateKeys = M.empty, stateSubstitutions = M.empty, stateNotes = [], stateNotes' = [], stateMeta = nullMeta, stateMeta' = return nullMeta, stateHeaderTable = [], stateHeaders = M.empty, stateIdentifiers = [], stateNextExample = 1, stateExamples = M.empty, stateHasChapters = False, stateMacros = [], stateRstDefaultRole = "title-reference", stateWarnings = []} getOption :: (ReaderOptions -> a) -> Parser s ParserState a getOption f = (f . stateOptions) `fmap` getState -- | Succeed only if the extension is enabled. guardEnabled :: Extension -> Parser s ParserState () guardEnabled ext = getOption readerExtensions >>= guard . Set.member ext -- | Succeed only if the extension is disabled. guardDisabled :: Extension -> Parser s ParserState () guardDisabled ext = getOption readerExtensions >>= guard . not . Set.member ext data HeaderType = SingleHeader Char -- ^ Single line of characters underneath | DoubleHeader Char -- ^ Lines of characters above and below deriving (Eq, Show) data ParserContext = ListItemState -- ^ Used when running parser on list item contents | NullState -- ^ Default state deriving (Eq, Show) data QuoteContext = InSingleQuote -- ^ Used when parsing inside single quotes | InDoubleQuote -- ^ Used when parsing inside double quotes | NoQuote -- ^ Used when not parsing inside quotes deriving (Eq, Show) type NoteTable = [(String, String)] type NoteTable' = [(String, F Blocks)] -- used in markdown reader newtype Key = Key String deriving (Show, Read, Eq, Ord) toKey :: String -> Key toKey = Key . map toLower . unwords . words type KeyTable = M.Map Key Target type SubstTable = M.Map Key Inlines -- | Add header to the list of headers in state, together -- with its associated identifier. If the identifier is null -- and the auto_identifers extension is set, generate a new -- unique identifier, and update the list of identifiers -- in state. registerHeader :: (HasReaderOptions m, HasHeaderMap m, HasIdentifierList m) => Attr -> Inlines -> m Attr registerHeader (ident,classes,kvs) header' = do ids <- getIdentifierList exts <- askReaderOption readerExtensions let insert' = M.insertWith (\_new old -> old) if null ident && Ext_auto_identifiers `Set.member` exts then do let id' = uniqueIdent (B.toList header') ids let id'' = if Ext_ascii_identifiers `Set.member` exts then catMaybes $ map toAsciiChar id' else id' putIdentifierList $ if id' == id'' then id' : ids else id' : id'' : ids modifyHeaderMap $ insert' header' id' return (id'',classes,kvs) else do unless (null ident) $ modifyHeaderMap $ insert' header' ident return (ident,classes,kvs) -- | Fail unless we're in "smart typography" mode. failUnlessSmart :: Parser [tok] ParserState () failUnlessSmart = getOption readerSmart >>= guard smartPunctuation :: Parser [Char] ParserState Inline -> Parser [Char] ParserState Inline smartPunctuation inlineParser = do failUnlessSmart choice [ quoted inlineParser, apostrophe, dash, ellipses ] apostrophe :: Parser [Char] ParserState Inline apostrophe = (char '\'' <|> char '\8217') >> return (Str "\x2019") quoted :: Parser [Char] ParserState Inline -> Parser [Char] ParserState Inline quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser withQuoteContext :: QuoteContext -> Parser [tok] ParserState a -> Parser [tok] ParserState a withQuoteContext context parser = do oldState <- getState let oldQuoteContext = stateQuoteContext oldState setState oldState { stateQuoteContext = context } result <- parser newState <- getState setState newState { stateQuoteContext = oldQuoteContext } return result singleQuoted :: Parser [Char] ParserState Inline -> Parser [Char] ParserState Inline singleQuoted inlineParser = try $ do singleQuoteStart withQuoteContext InSingleQuote $ many1Till inlineParser singleQuoteEnd >>= return . Quoted SingleQuote . normalizeSpaces doubleQuoted :: Parser [Char] ParserState Inline -> Parser [Char] ParserState Inline doubleQuoted inlineParser = try $ do doubleQuoteStart withQuoteContext InDoubleQuote $ do contents <- manyTill inlineParser doubleQuoteEnd return . Quoted DoubleQuote . normalizeSpaces $ contents failIfInQuoteContext :: QuoteContext -> Parser [tok] ParserState () failIfInQuoteContext context = do st <- getState if stateQuoteContext st == context then fail "already inside quotes" else return () charOrRef :: [Char] -> Parser [Char] st Char charOrRef cs = oneOf cs <|> try (do c <- characterReference guard (c `elem` cs) return c) updateLastStrPos :: Parser [Char] ParserState () updateLastStrPos = getPosition >>= \p -> updateState $ \s -> s{ stateLastStrPos = Just p } singleQuoteStart :: Parser [Char] ParserState () singleQuoteStart = do failIfInQuoteContext InSingleQuote pos <- getPosition st <- getState -- single quote start can't be right after str guard $ stateLastStrPos st /= Just pos () <$ charOrRef "'\8216\145" singleQuoteEnd :: Parser [Char] st () singleQuoteEnd = try $ do charOrRef "'\8217\146" notFollowedBy alphaNum doubleQuoteStart :: Parser [Char] ParserState () doubleQuoteStart = do failIfInQuoteContext InDoubleQuote try $ do charOrRef "\"\8220\147" notFollowedBy (satisfy (\c -> c == ' ' || c == '\t' || c == '\n')) doubleQuoteEnd :: Parser [Char] st () doubleQuoteEnd = do charOrRef "\"\8221\148" return () ellipses :: Parser [Char] st Inline ellipses = do try (charOrRef "\8230\133") <|> try (string "..." >> return '…') return (Str "\8230") dash :: Parser [Char] ParserState Inline dash = do oldDashes <- getOption readerOldDashes if oldDashes then emDashOld <|> enDashOld else Str `fmap` (hyphenDash <|> emDash <|> enDash) -- Two hyphens = en-dash, three = em-dash hyphenDash :: Parser [Char] st String hyphenDash = do try $ string "--" option "\8211" (char '-' >> return "\8212") emDash :: Parser [Char] st String emDash = do try (charOrRef "\8212\151") return "\8212" enDash :: Parser [Char] st String enDash = do try (charOrRef "\8212\151") return "\8211" enDashOld :: Parser [Char] st Inline enDashOld = do try (charOrRef "\8211\150") <|> try (char '-' >> lookAhead (satisfy isDigit) >> return '–') return (Str "\8211") emDashOld :: Parser [Char] st Inline emDashOld = do try (charOrRef "\8212\151") <|> (try $ string "--" >> optional (char '-') >> return '-') return (Str "\8212") -- This is used to prevent exponential blowups for things like: -- a**a*a**a*a**a*a**a*a**a*a**a*a** nested :: Parser s ParserState a -> Parser s ParserState a nested p = do nestlevel <- stateMaxNestingLevel `fmap` getState guard $ nestlevel > 0 updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 } res <- p updateState $ \st -> st{ stateMaxNestingLevel = nestlevel } return res -- -- Macros -- -- | Parse a \newcommand or \renewcommand macro definition. macro :: Parser [Char] ParserState Blocks macro = do apply <- getOption readerApplyMacros inp <- getInput case parseMacroDefinitions inp of ([], _) -> mzero (ms, rest) -> do def' <- count (length inp - length rest) anyChar if apply then do updateState $ \st -> st { stateMacros = ms ++ stateMacros st } return mempty else return $ rawBlock "latex" def' -- | Apply current macros to string. applyMacros' :: String -> Parser [Char] ParserState String applyMacros' target = do apply <- getOption readerApplyMacros if apply then do macros <- liftM stateMacros getState return $ applyMacros macros target else return target pandoc-1.12.2.1/src/Text/Pandoc/PDF.hs000644 000765 000024 00000014240 12251233602 017001 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings, CPP #-} {- Copyright (C) 2012 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.PDF Copyright : Copyright (C) 2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of LaTeX documents to PDF. -} module Text.Pandoc.PDF ( makePDF ) where import System.IO.Temp import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.Char8 as BC import qualified Data.ByteString as BS import System.Exit (ExitCode (..)) import System.FilePath import System.Directory import System.Environment import Control.Monad (unless) import Data.List (isInfixOf) import qualified Data.ByteString.Base64 as B64 import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Definition import Text.Pandoc.Walk (walkM) import Text.Pandoc.Shared (fetchItem, warn) import Text.Pandoc.Options (WriterOptions(..)) import Text.Pandoc.MIME (extensionFromMimeType) import Text.Pandoc.Process (pipeProcess) import qualified Data.ByteString.Lazy as BL withTempDir :: String -> (FilePath -> IO a) -> IO a withTempDir = #ifdef _WINDOWS withTempDirectory "." #else withSystemTempDirectory #endif makePDF :: String -- ^ pdf creator (pdflatex, lualatex, xelatex) -> (WriterOptions -> Pandoc -> String) -- ^ writer -> WriterOptions -- ^ options -> Pandoc -- ^ document -> IO (Either ByteString ByteString) makePDF program writer opts doc = withTempDir "tex2pdf." $ \tmpdir -> do doc' <- handleImages (writerSourceURL opts) tmpdir doc let source = writer opts doc' tex2pdf' tmpdir program source handleImages :: Maybe String -- ^ source base URL -> FilePath -- ^ temp dir to store images -> Pandoc -- ^ document -> IO Pandoc handleImages baseURL tmpdir = walkM (handleImage' baseURL tmpdir) handleImage' :: Maybe String -> FilePath -> Inline -> IO Inline handleImage' baseURL tmpdir (Image ils (src,tit)) = do exists <- doesFileExist src if exists then return $ Image ils (src,tit) else do res <- fetchItem baseURL src case res of Right (contents, Just mime) -> do let ext = maybe (takeExtension src) id $ extensionFromMimeType mime let basename = UTF8.toString $ B64.encode $ UTF8.fromString src let fname = tmpdir basename <.> ext BS.writeFile fname contents return $ Image ils (fname,tit) _ -> do warn $ "Could not find image `" ++ src ++ "', skipping..." return $ Image ils (src,tit) handleImage' _ _ x = return x tex2pdf' :: FilePath -- ^ temp directory for output -> String -- ^ tex program -> String -- ^ tex source -> IO (Either ByteString ByteString) tex2pdf' tmpDir program source = do let numruns = if "\\tableofcontents" `isInfixOf` source 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.\n" case (exit, mbPdf) of (ExitFailure _, _) -> do let logmsg = extractMsg log' let extramsg = case logmsg of x | "! Package inputenc Error" `BC.isPrefixOf` x -> "\nTry running pandoc with --latex-engine=xelatex." _ -> "" return $ Left $ msg <> logmsg <> extramsg (ExitSuccess, Nothing) -> return $ Left msg (ExitSuccess, Just pdf) -> return $ Right pdf (<>) :: ByteString -> ByteString -> ByteString (<>) = B.append -- parsing output extractMsg :: ByteString -> ByteString extractMsg log' = do let msg' = dropWhile (not . ("!" `BC.isPrefixOf`)) $ BC.lines log' let (msg'',rest) = break ("l." `BC.isPrefixOf`) msg' let lineno = take 1 rest if null msg' then log' else BC.unlines (msg'' ++ lineno) -- running tex programs -- Run a TeX program on an input bytestring and return (exit code, -- contents of stdout, contents of produced PDF if any). Rerun -- a fixed number of times to resolve references. runTeXProgram :: String -> Int -> FilePath -> String -> IO (ExitCode, ByteString, Maybe ByteString) runTeXProgram program runsLeft tmpDir source = do let file = tmpDir "input.tex" exists <- doesFileExist file unless exists $ UTF8.writeFile file source let programArgs = ["-halt-on-error", "-interaction", "nonstopmode", "-output-directory", tmpDir, file] env' <- getEnvironment let texinputs = maybe (tmpDir ++ ":") ((tmpDir ++ ":") ++) $ lookup "TEXINPUTS" env' let env'' = ("TEXINPUTS", texinputs) : [(k,v) | (k,v) <- env', k /= "TEXINPUTS"] (exit, out, err) <- pipeProcess (Just env'') program programArgs BL.empty if runsLeft > 1 then runTeXProgram program (runsLeft - 1) tmpDir source else do let pdfFile = replaceDirectory (replaceExtension file ".pdf") tmpDir pdfExists <- doesFileExist pdfFile pdf <- if pdfExists then Just `fmap` B.readFile pdfFile else return Nothing return (exit, out <> err, pdf) pandoc-1.12.2.1/src/Text/Pandoc/Pretty.hs000644 000765 000024 00000037550 12251233602 017670 0ustar00jgmstaff000000 000000 {-# LANGUAGE GeneralizedNewtypeDeriving, CPP #-} {- Copyright (C) 2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111(-1)307 USA -} {- | Module : Text.Pandoc.Pretty Copyright : Copyright (C) 2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable A prettyprinting library for the production of text documents, including wrapped text, indentated blocks, and tables. -} module Text.Pandoc.Pretty ( Doc , render , cr , blankline , space , text , char , prefixed , flush , nest , hang , beforeNonBlank , nowrap , offset , height , lblock , cblock , rblock , (<>) , (<+>) , ($$) , ($+$) , isEmpty , empty , cat , hcat , hsep , vcat , vsep , chomp , inside , braces , brackets , parens , quotes , doubleQuotes , charWidth , realLength ) where import Data.Sequence (Seq, fromList, (<|), singleton, mapWithIndex) import Data.Foldable (toList) import Data.List (intercalate) import Data.Monoid import Data.String import Control.Monad.State import Data.Char (isSpace) data Monoid a => RenderState a = RenderState{ output :: [a] -- ^ In reverse order , prefix :: String , usePrefix :: Bool , lineLength :: Maybe Int -- ^ 'Nothing' means no wrapping , column :: Int , newlines :: Int -- ^ Number of preceding newlines } type DocState a = State (RenderState a) () data D = Text Int String | Block Int [String] | Prefixed String Doc | BeforeNonBlank Doc | Flush Doc | BreakingSpace | CarriageReturn | NewLine | BlankLine deriving (Show) newtype Doc = Doc { unDoc :: Seq D } deriving (Monoid, Show) instance IsString Doc where fromString = text isBlank :: D -> Bool isBlank BreakingSpace = True isBlank CarriageReturn = True isBlank NewLine = True isBlank BlankLine = True isBlank (Text _ (c:_)) = isSpace c isBlank _ = False -- | True if the document is empty. isEmpty :: Doc -> Bool isEmpty = null . toList . unDoc -- | The empty document. empty :: Doc empty = mempty #if MIN_VERSION_base(4,5,0) -- (<>) is defined in Data.Monoid #else infixr 6 <> -- | An infix synonym for 'mappend'. -- @a <> b@ is the result of concatenating @a@ with @b@. (<>) :: Monoid m => m -> m -> m (<>) = mappend {-# INLINE (<>) #-} #endif -- | Concatenate a list of 'Doc's. cat :: [Doc] -> Doc cat = mconcat -- | Same as 'cat'. hcat :: [Doc] -> Doc hcat = mconcat -- | Concatenate a list of 'Doc's, putting breakable spaces -- between them. infixr 6 <+> (<+>) :: Doc -> Doc -> Doc (<+>) x y = if isEmpty x then y else if isEmpty y then x else x <> space <> y -- | Same as 'cat', but putting breakable spaces between the -- 'Doc's. hsep :: [Doc] -> Doc hsep = foldr (<+>) empty infixr 5 $$ -- | @a $$ b@ puts @a@ above @b@. ($$) :: Doc -> Doc -> Doc ($$) x y = if isEmpty x then y else if isEmpty y then x else x <> cr <> y infixr 5 $+$ -- | @a $$ b@ puts @a@ above @b@, with a blank line between. ($+$) :: Doc -> Doc -> Doc ($+$) x y = if isEmpty x then y else if isEmpty y then x else x <> blankline <> y -- | List version of '$$'. vcat :: [Doc] -> Doc vcat = foldr ($$) empty -- | List version of '$+$'. vsep :: [Doc] -> Doc vsep = foldr ($+$) empty -- | Chomps trailing blank space off of a 'Doc'. chomp :: Doc -> Doc chomp d = Doc (fromList dl') where dl = toList (unDoc d) dl' = reverse $ go $ reverse dl go [] = [] go (BreakingSpace : xs) = go xs go (CarriageReturn : xs) = go xs go (NewLine : xs) = go xs go (BlankLine : xs) = go xs go (Prefixed s d' : xs) = Prefixed s (chomp d') : xs go xs = xs outp :: (IsString a, Monoid a) => Int -> String -> DocState a outp off s | off < 0 = do -- offset < 0 means newline characters st' <- get let rawpref = prefix st' when (column st' == 0 && usePrefix st' && not (null rawpref)) $ do let pref = reverse $ dropWhile isSpace $ reverse rawpref modify $ \st -> st{ output = fromString pref : output st , column = column st + realLength pref } modify $ \st -> st { output = fromString s : output st , column = 0 , newlines = newlines st + 1 } outp off s = do -- offset >= 0 (0 might be combining char) st' <- get let pref = prefix st' when (column st' == 0 && usePrefix st' && not (null pref)) $ do modify $ \st -> st{ output = fromString pref : output st , column = column st + realLength pref } modify $ \st -> st{ output = fromString s : output st , column = column st + off , newlines = 0 } -- | Renders a 'Doc'. @render (Just n)@ will use -- a line length of @n@ to reflow text on breakable spaces. -- @render Nothing@ will not reflow text. render :: (Monoid a, IsString a) => Maybe Int -> Doc -> a render linelen doc = fromString . mconcat . reverse . output $ execState (renderDoc doc) startingState where startingState = RenderState{ output = mempty , prefix = "" , usePrefix = True , lineLength = linelen , column = 0 , newlines = 2 } renderDoc :: (IsString a, Monoid a) => Doc -> DocState a renderDoc = renderList . toList . unDoc renderList :: (IsString a, Monoid a) => [D] -> DocState a renderList [] = return () renderList (Text off s : xs) = do outp off s renderList xs renderList (Prefixed pref d : xs) = do st <- get let oldPref = prefix st put st{ prefix = prefix st ++ pref } renderDoc d modify $ \s -> s{ prefix = oldPref } renderList xs renderList (Flush d : xs) = do st <- get let oldUsePrefix = usePrefix st put st{ usePrefix = False } renderDoc d modify $ \s -> s{ usePrefix = oldUsePrefix } renderList xs renderList (BeforeNonBlank d : xs) = case xs of (x:_) | isBlank x -> renderList xs | otherwise -> renderDoc d >> renderList xs [] -> renderList xs renderList (BlankLine : xs) = do st <- get case output st of _ | newlines st > 1 || null xs -> return () _ | column st == 0 -> do outp (-1) "\n" _ -> do outp (-1) "\n" outp (-1) "\n" renderList xs renderList (CarriageReturn : xs) = do st <- get if newlines st > 0 || null xs then renderList xs else do outp (-1) "\n" renderList xs renderList (NewLine : xs) = do outp (-1) "\n" renderList xs renderList (BreakingSpace : CarriageReturn : xs) = renderList (CarriageReturn:xs) renderList (BreakingSpace : NewLine : xs) = renderList (NewLine:xs) renderList (BreakingSpace : BlankLine : xs) = renderList (BlankLine:xs) renderList (BreakingSpace : BreakingSpace : xs) = renderList (BreakingSpace:xs) renderList (BreakingSpace : xs) = do let isText (Text _ _) = True isText (Block _ _) = True isText _ = False let isBreakingSpace BreakingSpace = True isBreakingSpace _ = False let xs' = dropWhile isBreakingSpace xs let next = takeWhile isText xs' st <- get let off = sum $ map offsetOf next case lineLength st of Just l | column st + 1 + off > l -> do outp (-1) "\n" renderList xs' _ -> do outp 1 " " renderList xs' renderList (b1@Block{} : b2@Block{} : xs) = renderList (mergeBlocks False b1 b2 : xs) renderList (b1@Block{} : BreakingSpace : b2@Block{} : xs) = renderList (mergeBlocks True b1 b2 : xs) renderList (Block width lns : xs) = do st <- get let oldPref = prefix st case column st - realLength oldPref of n | n > 0 -> modify $ \s -> s{ prefix = oldPref ++ replicate n ' ' } _ -> return () renderDoc $ blockToDoc width lns modify $ \s -> s{ prefix = oldPref } renderList xs mergeBlocks :: Bool -> D -> D -> D mergeBlocks addSpace (Block w1 lns1) (Block w2 lns2) = Block (w1 + w2 + if addSpace then 1 else 0) $ zipWith (\l1 l2 -> pad w1 l1 ++ l2) (lns1 ++ empties) (map sp lns2 ++ empties) where empties = replicate (abs $ length lns1 - length lns2) "" pad n s = s ++ replicate (n - realLength s) ' ' sp "" = "" sp xs = if addSpace then (' ' : xs) else xs mergeBlocks _ _ _ = error "mergeBlocks tried on non-Block!" blockToDoc :: Int -> [String] -> Doc blockToDoc _ lns = text $ intercalate "\n" lns offsetOf :: D -> Int offsetOf (Text o _) = o offsetOf (Block w _) = w offsetOf BreakingSpace = 1 offsetOf _ = 0 -- | A literal string. text :: String -> Doc text = Doc . toChunks where toChunks :: String -> Seq D toChunks [] = mempty toChunks s = case break (=='\n') s of ([], _:ys) -> NewLine <| toChunks ys (xs, _:ys) -> Text (realLength xs) xs <| (NewLine <| toChunks ys) (xs, []) -> singleton $ Text (realLength xs) xs -- | A character. char :: Char -> Doc char c = text [c] -- | A breaking (reflowable) space. space :: Doc space = Doc $ singleton BreakingSpace -- | A carriage return. Does nothing if we're at the beginning of -- a line; otherwise inserts a newline. cr :: Doc cr = Doc $ singleton CarriageReturn -- | Inserts a blank line unless one exists already. -- (@blankline <> blankline@ has the same effect as @blankline@. -- If you want multiple blank lines, use @text "\\n\\n"@. blankline :: Doc blankline = Doc $ singleton BlankLine -- | Uses the specified string as a prefix for every line of -- the inside document (except the first, if not at the beginning -- of the line). prefixed :: String -> Doc -> Doc prefixed pref doc = Doc $ singleton $ Prefixed pref doc -- | Makes a 'Doc' flush against the left margin. flush :: Doc -> Doc flush doc = Doc $ singleton $ Flush doc -- | Indents a 'Doc' by the specified number of spaces. nest :: Int -> Doc -> Doc nest ind = prefixed (replicate ind ' ') -- | A hanging indent. @hang ind start doc@ prints @start@, -- then @doc@, leaving an indent of @ind@ spaces on every -- line but the first. hang :: Int -> Doc -> Doc -> Doc hang ind start doc = start <> nest ind doc -- | @beforeNonBlank d@ conditionally includes @d@ unless it is -- followed by blank space. beforeNonBlank :: Doc -> Doc beforeNonBlank d = Doc $ singleton (BeforeNonBlank d) -- | Makes a 'Doc' non-reflowable. nowrap :: Doc -> Doc nowrap doc = Doc $ mapWithIndex replaceSpace $ unDoc doc where replaceSpace _ BreakingSpace = Text 1 " " replaceSpace _ x = x -- | Returns the width of a 'Doc'. offset :: Doc -> Int offset d = case map realLength . lines . render Nothing $ d of [] -> 0 os -> maximum os block :: (String -> String) -> Int -> Doc -> Doc block filler width = Doc . singleton . Block width . map filler . chop width . render (Just width) -- | @lblock n d@ is a block of width @n@ characters, with -- text derived from @d@ and aligned to the left. lblock :: Int -> Doc -> Doc lblock = block id -- | Like 'lblock' but aligned to the right. rblock :: Int -> Doc -> Doc rblock w = block (\s -> replicate (w - realLength s) ' ' ++ s) w -- | Like 'lblock' but aligned centered. cblock :: Int -> Doc -> Doc cblock w = block (\s -> replicate ((w - realLength s) `div` 2) ' ' ++ s) w -- | Returns the height of a block or other 'Doc'. height :: Doc -> Int height = length . lines . render Nothing chop :: Int -> String -> [String] chop _ [] = [] chop n cs = case break (=='\n') cs of (xs, ys) -> if len <= n then case ys of [] -> [xs] (_:[]) -> [xs, ""] (_:zs) -> xs : chop n zs else take n xs : chop n (drop n xs ++ ys) where len = realLength xs -- | Encloses a 'Doc' inside a start and end 'Doc'. inside :: Doc -> Doc -> Doc -> Doc inside start end contents = start <> contents <> end -- | Puts a 'Doc' in curly braces. braces :: Doc -> Doc braces = inside (char '{') (char '}') -- | Puts a 'Doc' in square brackets. brackets :: Doc -> Doc brackets = inside (char '[') (char ']') -- | Puts a 'Doc' in parentheses. parens :: Doc -> Doc parens = inside (char '(') (char ')') -- | Wraps a 'Doc' in single quotes. quotes :: Doc -> Doc quotes = inside (char '\'') (char '\'') -- | Wraps a 'Doc' in double quotes. doubleQuotes :: Doc -> Doc doubleQuotes = inside (char '"') (char '"') -- | Returns width of a character in a monospace font: 0 for a combining -- character, 1 for a regular character, 2 for an East Asian wide character. charWidth :: Char -> Int charWidth c = case c of _ | c < '\x0300' -> 1 | c >= '\x0300' && c <= '\x036F' -> 0 -- combining | c >= '\x0370' && c <= '\x10FC' -> 1 | c >= '\x1100' && c <= '\x115F' -> 2 | c >= '\x1160' && c <= '\x11A2' -> 1 | c >= '\x11A3' && c <= '\x11A7' -> 2 | c >= '\x11A8' && c <= '\x11F9' -> 1 | c >= '\x11FA' && c <= '\x11FF' -> 2 | c >= '\x1200' && c <= '\x2328' -> 1 | c >= '\x2329' && c <= '\x232A' -> 2 | c >= '\x232B' && c <= '\x2E31' -> 1 | c >= '\x2E80' && c <= '\x303E' -> 2 | c == '\x303F' -> 1 | c >= '\x3041' && c <= '\x3247' -> 2 | c >= '\x3248' && c <= '\x324F' -> 1 -- ambiguous | c >= '\x3250' && c <= '\x4DBF' -> 2 | c >= '\x4DC0' && c <= '\x4DFF' -> 1 | c >= '\x4E00' && c <= '\xA4C6' -> 2 | c >= '\xA4D0' && c <= '\xA95F' -> 1 | c >= '\xA960' && c <= '\xA97C' -> 2 | c >= '\xA980' && c <= '\xABF9' -> 1 | c >= '\xAC00' && c <= '\xD7FB' -> 2 | c >= '\xD800' && c <= '\xDFFF' -> 1 | c >= '\xE000' && c <= '\xF8FF' -> 1 -- ambiguous | c >= '\xF900' && c <= '\xFAFF' -> 2 | c >= '\xFB00' && c <= '\xFDFD' -> 1 | c >= '\xFE00' && c <= '\xFE0F' -> 1 -- ambiguous | c >= '\xFE10' && c <= '\xFE19' -> 2 | c >= '\xFE20' && c <= '\xFE26' -> 1 | c >= '\xFE30' && c <= '\xFE6B' -> 2 | c >= '\xFE70' && c <= '\xFEFF' -> 1 | c >= '\xFF01' && c <= '\xFF60' -> 2 | c >= '\xFF61' && c <= '\x16A38' -> 1 | c >= '\x1B000' && c <= '\x1B001' -> 2 | c >= '\x1D000' && c <= '\x1F1FF' -> 1 | c >= '\x1F200' && c <= '\x1F251' -> 2 | c >= '\x1F300' && c <= '\x1F773' -> 1 | c >= '\x20000' && c <= '\x3FFFD' -> 2 | otherwise -> 1 -- | Get real length of string, taking into account combining and double-wide -- characters. realLength :: String -> Int realLength = sum . map charWidth pandoc-1.12.2.1/src/Text/Pandoc/Process.hs000644 000765 000024 00000007321 12251233602 020010 0ustar00jgmstaff000000 000000 {- Copyright (C) 2013 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Process Copyright : Copyright (C) 2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable ByteString variant of 'readProcessWithExitCode'. -} module Text.Pandoc.Process (pipeProcess) where import System.Process import System.Exit (ExitCode (..)) import Control.Exception import System.IO (hClose, hFlush) import Control.Concurrent (putMVar, takeMVar, newEmptyMVar, forkIO) import Control.Monad (unless) import qualified Data.ByteString.Lazy as BL {- | Version of 'System.Process.readProcessWithExitCode' that uses lazy bytestrings instead of strings and allows setting environment variables. @readProcessWithExitCode@ creates an external process, reads its standard output and standard error strictly, waits until the process terminates, and then returns the 'ExitCode' of the process, the standard output, and the standard error. If an asynchronous exception is thrown to the thread executing @readProcessWithExitCode@. The forked process will be terminated and @readProcessWithExitCode@ will wait (block) until the process has been terminated. -} pipeProcess :: Maybe [(String, String)] -- ^ environment variables -> FilePath -- ^ Filename of the executable (see 'proc' for details) -> [String] -- ^ any arguments -> BL.ByteString -- ^ standard input -> IO (ExitCode,BL.ByteString,BL.ByteString) -- ^ exitcode, stdout, stderr pipeProcess mbenv cmd args input = mask $ \restore -> do (Just inh, Just outh, Just errh, pid) <- createProcess (proc cmd args) { env = mbenv, std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe } flip onException (do hClose inh; hClose outh; hClose errh; terminateProcess pid; waitForProcess pid) $ restore $ do -- fork off a thread to start consuming stdout out <- BL.hGetContents outh waitOut <- forkWait $ evaluate $ BL.length out -- fork off a thread to start consuming stderr err <- BL.hGetContents errh waitErr <- forkWait $ evaluate $ BL.length err -- now write and flush any input let writeInput = do unless (BL.null input) $ do BL.hPutStr inh input hFlush inh hClose inh writeInput -- wait on the output waitOut waitErr hClose outh hClose errh -- wait on the process ex <- waitForProcess pid return (ex, out, err) forkWait :: IO a -> IO (IO a) forkWait a = do res <- newEmptyMVar _ <- mask $ \restore -> forkIO $ try (restore a) >>= putMVar res return (takeMVar res >>= either (\ex -> throwIO (ex :: SomeException)) return) pandoc-1.12.2.1/src/Text/Pandoc/Readers/000755 000765 000024 00000000000 12251233602 017420 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/src/Text/Pandoc/SelfContained.hs000644 000765 000024 00000014260 12251233602 021110 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2011 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.SelfContained Copyright : Copyright (C) 2011 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Functions for converting an HTML file into one that can be viewed offline, by incorporating linked images, CSS, and scripts into the HTML using data URIs. -} module Text.Pandoc.SelfContained ( makeSelfContained ) where import Text.HTML.TagSoup import Network.URI (isURI, escapeURIString) import Data.ByteString.Base64 import qualified Data.ByteString.Char8 as B import Data.ByteString (ByteString) import System.FilePath (takeExtension, dropExtension, takeDirectory, ()) import Data.Char (toLower, isAscii, isAlphaNum) import Codec.Compression.GZip as Gzip import qualified Data.ByteString.Lazy as L import Text.Pandoc.Shared (renderTags', openURL, readDataFile, err) import Text.Pandoc.UTF8 (toString, fromString) import Text.Pandoc.MIME (getMimeType) import System.Directory (doesFileExist) isOk :: Char -> Bool isOk c = isAscii c && isAlphaNum c convertTag :: Maybe FilePath -> Tag String -> IO (Tag String) convertTag userdata t@(TagOpen tagname as) | tagname `elem` ["img", "embed", "video", "input", "audio", "source"] = case fromAttrib "src" t of [] -> return t src -> do (raw, mime) <- getRaw userdata (fromAttrib "type" t) src let enc = "data:" ++ mime ++ ";base64," ++ toString (encode raw) return $ TagOpen tagname (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"]) convertTag userdata t@(TagOpen "script" as) = case fromAttrib "src" t of [] -> return t src -> do (raw, mime) <- getRaw userdata (fromAttrib "type" t) src let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw) return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"]) convertTag userdata t@(TagOpen "link" as) = case fromAttrib "href" t of [] -> return t src -> do (raw, mime) <- getRaw userdata (fromAttrib "type" t) src let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw) return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"]) convertTag _ t = return t -- NOTE: This is really crude, it doesn't respect CSS comments. cssURLs :: Maybe FilePath -> FilePath -> ByteString -> IO ByteString cssURLs userdata d orig = case B.breakSubstring "url(" orig of (x,y) | B.null y -> return orig | otherwise -> do let (u,v) = B.breakSubstring ")" $ B.drop 4 y let url = toString $ case B.take 1 u of "\"" -> B.takeWhile (/='"') $ B.drop 1 u "'" -> B.takeWhile (/='\'') $ B.drop 1 u _ -> u let url' = if isURI url then url else d url (raw, mime) <- getRaw userdata "" url' rest <- cssURLs userdata d v let enc = "data:" `B.append` fromString mime `B.append` ";base64," `B.append` (encode raw) return $ x `B.append` "url(" `B.append` enc `B.append` rest getItem :: Maybe FilePath -> String -> IO (ByteString, Maybe String) getItem userdata f = if isURI f then openURL f >>= either handleErr return else do -- strip off trailing query or fragment part, if relative URL. -- this is needed for things like cmunrm.eot?#iefix, -- which is used to get old versions of IE to work with web fonts. let f' = takeWhile (\c -> c /= '?' && c /= '#') f let mime = case takeExtension f' of ".gz" -> getMimeType $ dropExtension f' x -> getMimeType x exists <- doesFileExist f' cont <- if exists then B.readFile f' else readDataFile userdata f' return (cont, mime) where handleErr e = err 61 $ "Failed to retrieve " ++ f ++ "\n" ++ show e getRaw :: Maybe FilePath -> String -> String -> IO (ByteString, String) getRaw userdata mimetype src = do let ext = map toLower $ takeExtension src (raw, respMime) <- getItem userdata src let raw' = if ext == ".gz" then B.concat $ L.toChunks $ Gzip.decompress $ L.fromChunks $ [raw] else raw let mime = case (mimetype, respMime) of ("",Nothing) -> error $ "Could not determine mime type for `" ++ src ++ "'" (x, Nothing) -> x (_, Just x ) -> x result <- if mime == "text/css" then cssURLs userdata (takeDirectory src) raw' else return raw' return (result, mime) -- | Convert HTML into self-contained HTML, incorporating images, -- scripts, and CSS using data: URIs. Items specified using absolute -- URLs will be downloaded; those specified using relative URLs will -- be sought first relative to the working directory, then relative -- to the user data directory (if the first parameter is 'Just' -- a directory), and finally relative to pandoc's default data -- directory. makeSelfContained :: Maybe FilePath -> String -> IO String makeSelfContained userdata inp = do let tags = parseTags inp out' <- mapM (convertTag userdata) tags return $ renderTags' out' pandoc-1.12.2.1/src/Text/Pandoc/Shared.hs000644 000765 000024 00000063502 12251233602 017603 0ustar00jgmstaff000000 000000 {-# LANGUAGE DeriveDataTypeable, CPP, MultiParamTypeClasses, FlexibleContexts #-} {- Copyright (C) 2006-2013 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Shared Copyright : Copyright (C) 2006-2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Utility functions and definitions used by the various Pandoc modules. -} module Text.Pandoc.Shared ( -- * List processing splitBy, splitByIndices, splitStringByIndices, substitute, -- * Text processing backslashEscapes, escapeStringUsing, stripTrailingNewlines, trim, triml, trimr, stripFirstAndLast, camelCaseToHyphenated, toRomanNumeral, escapeURI, tabFilter, -- * Date/time normalizeDate, -- * Pandoc block and inline list processing orderedListMarkers, normalizeSpaces, normalize, stringify, compactify, compactify', Element (..), hierarchicalize, uniqueIdent, isHeaderBlock, headerShift, isTightList, addMetaField, makeMeta, -- * TagSoup HTML handling renderTags', -- * File handling inDirectory, readDataFile, readDataFileUTF8, fetchItem, openURL, -- * Error handling err, warn, -- * Safe read safeRead ) where import Text.Pandoc.Definition import Text.Pandoc.Walk import Text.Pandoc.Generic import Text.Pandoc.Builder (Blocks, ToMetaValue(..)) import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.UTF8 as UTF8 import System.Environment (getProgName) import System.Exit (exitWith, ExitCode(..)) 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, isURI, unEscapeString ) import System.Directory import Text.Pandoc.MIME (getMimeType) import System.FilePath ( (), takeExtension, dropExtension ) import Data.Generics (Typeable, Data) import qualified Control.Monad.State as S import qualified Control.Exception as E import Control.Monad (msum, unless) import Text.Pandoc.Pretty (charWidth) import System.Locale (defaultTimeLocale) import Data.Time import System.IO (stderr) import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..), renderOptions) 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) import System.FilePath ( joinPath, splitDirectories ) #else import Paths_pandoc (getDataFileName) #endif #ifdef HTTP_CONDUIT import Data.ByteString.Lazy (toChunks) import Network.HTTP.Conduit (httpLbs, parseUrl, withManager, responseBody, responseHeaders) import Network.HTTP.Types.Header ( hContentType) #else import Network.URI (parseURI) import Network.HTTP (findHeader, rspBody, RequestMethod(..), HeaderName(..), mkRequest) import Network.Browser (browse, setAllowRedirects, setOutHandler, request) #endif -- -- List processing -- -- | Split list by groups of one or more sep. splitBy :: (a -> Bool) -> [a] -> [[a]] splitBy _ [] = [] splitBy isSep lst = let (first, rest) = break isSep lst rest' = dropWhile isSep rest in first:(splitBy isSep rest') splitByIndices :: [Int] -> [a] -> [[a]] splitByIndices [] lst = [lst] splitByIndices (x:xs) lst = first:(splitByIndices (map (\y -> y - x) xs) rest) where (first, rest) = splitAt x lst -- | Split string into chunks divided at specified indices. splitStringByIndices :: [Int] -> [Char] -> [[Char]] splitStringByIndices [] lst = [lst] splitStringByIndices (x:xs) lst = let (first, rest) = splitAt' x lst in first : (splitStringByIndices (map (\y -> y - x) xs) rest) splitAt' :: Int -> [Char] -> ([Char],[Char]) splitAt' _ [] = ([],[]) splitAt' n xs | n <= 0 = ([],xs) splitAt' n (x:xs) = (x:ys,zs) where (ys,zs) = splitAt' (n - charWidth x) xs -- | Replace each occurrence of one sublist in a list with another. substitute :: (Eq a) => [a] -> [a] -> [a] -> [a] substitute _ _ [] = [] substitute [] _ xs = xs substitute target replacement lst@(x:xs) = if target `isPrefixOf` lst then replacement ++ substitute target replacement (drop (length target) lst) else x : substitute target replacement xs -- -- Text processing -- -- | Returns an association list of backslash escapes for the -- designated characters. backslashEscapes :: [Char] -- ^ list of special characters to escape -> [(Char, String)] backslashEscapes = map (\ch -> (ch, ['\\',ch])) -- | Escape a string of characters, using an association list of -- characters and strings. escapeStringUsing :: [(Char, String)] -> String -> String escapeStringUsing _ [] = "" escapeStringUsing escapeTable (x:xs) = case (lookup x escapeTable) of Just str -> str ++ rest Nothing -> x:rest where rest = escapeStringUsing escapeTable xs -- | Strip trailing newlines from string. stripTrailingNewlines :: String -> String stripTrailingNewlines = reverse . dropWhile (== '\n') . reverse -- | Remove leading and trailing space (including newlines) from string. trim :: String -> String trim = triml . trimr -- | Remove leading space (including newlines) from string. triml :: String -> String triml = dropWhile (`elem` " \r\n\t") -- | Remove trailing space (including newlines) from string. trimr :: String -> String trimr = reverse . triml . reverse -- | Strip leading and trailing characters from string stripFirstAndLast :: String -> String stripFirstAndLast str = drop 1 $ take ((length str) - 1) str -- | Change CamelCase word to hyphenated lowercase (e.g., camel-case). camelCaseToHyphenated :: String -> String camelCaseToHyphenated [] = "" camelCaseToHyphenated (a:b:rest) | isLower a && isUpper b = a:'-':(toLower b):(camelCaseToHyphenated rest) camelCaseToHyphenated (a:rest) = (toLower a):(camelCaseToHyphenated rest) -- | Convert number < 4000 to uppercase roman numeral. toRomanNumeral :: Int -> String toRomanNumeral x = if x >= 4000 || x < 0 then "?" else case x of _ | x >= 1000 -> "M" ++ toRomanNumeral (x - 1000) _ | x >= 900 -> "CM" ++ toRomanNumeral (x - 900) _ | x >= 500 -> "D" ++ toRomanNumeral (x - 500) _ | x >= 400 -> "CD" ++ toRomanNumeral (x - 400) _ | x >= 100 -> "C" ++ toRomanNumeral (x - 100) _ | x >= 90 -> "XC" ++ toRomanNumeral (x - 90) _ | x >= 50 -> "L" ++ toRomanNumeral (x - 50) _ | x >= 40 -> "XL" ++ toRomanNumeral (x - 40) _ | x >= 10 -> "X" ++ toRomanNumeral (x - 10) _ | x >= 9 -> "IX" ++ toRomanNumeral (x - 5) _ | x >= 5 -> "V" ++ toRomanNumeral (x - 5) _ | x >= 4 -> "IV" ++ toRomanNumeral (x - 4) _ | x >= 1 -> "I" ++ toRomanNumeral (x - 1) _ -> "" -- | Escape whitespace in URI. escapeURI :: String -> String escapeURI = escapeURIString (not . isSpace) -- | Convert tabs to spaces and filter out DOS line endings. -- Tabs will be preserved if tab stop is set to 0. tabFilter :: Int -- ^ Tab stop -> String -- ^ Input -> String tabFilter tabStop = let go _ [] = "" go _ ('\n':xs) = '\n' : go tabStop xs go _ ('\r':'\n':xs) = '\n' : go tabStop xs go _ ('\r':xs) = '\n' : go tabStop xs go spsToNextStop ('\t':xs) = if tabStop == 0 then '\t' : go tabStop xs else replicate spsToNextStop ' ' ++ go tabStop xs go 1 (x:xs) = x : go tabStop xs go spsToNextStop (x:xs) = x : go (spsToNextStop - 1) xs in go tabStop -- -- Date/time -- -- | Parse a date and convert (if possible) to "YYYY-MM-DD" format. normalizeDate :: String -> Maybe String 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", "%Y"] -- -- Pandoc block and inline list processing -- -- | Generate infinite lazy list of markers for an ordered list, -- depending on list attributes. orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [String] orderedListMarkers (start, numstyle, numdelim) = let singleton c = [c] nums = case numstyle of DefaultStyle -> map show [start..] Example -> map show [start..] Decimal -> map show [start..] UpperAlpha -> drop (start - 1) $ cycle $ map singleton ['A'..'Z'] LowerAlpha -> drop (start - 1) $ cycle $ map singleton ['a'..'z'] UpperRoman -> map toRomanNumeral [start..] LowerRoman -> map (map toLower . toRomanNumeral) [start..] inDelim str = case numdelim of DefaultDelim -> str ++ "." Period -> str ++ "." OneParen -> str ++ ")" TwoParens -> "(" ++ str ++ ")" in map inDelim nums -- | Normalize a list of inline elements: remove leading and trailing -- @Space@ elements, collapse double @Space@s into singles, and -- remove empty Str elements. normalizeSpaces :: [Inline] -> [Inline] normalizeSpaces = cleanup . dropWhile isSpaceOrEmpty where cleanup [] = [] cleanup (Space:rest) = case dropWhile isSpaceOrEmpty rest of [] -> [] (x:xs) -> Space : x : cleanup xs cleanup ((Str ""):rest) = cleanup rest cleanup (x:rest) = x : cleanup rest isSpaceOrEmpty :: Inline -> Bool isSpaceOrEmpty Space = True isSpaceOrEmpty (Str "") = True isSpaceOrEmpty _ = False -- | Normalize @Pandoc@ document, consolidating doubled 'Space's, -- combining adjacent 'Str's and 'Emph's, remove 'Null's and -- empty elements, etc. normalize :: (Eq a, Data a) => a -> a normalize = topDown removeEmptyBlocks . topDown consolidateInlines . bottomUp (removeEmptyInlines . removeTrailingInlineSpaces) removeEmptyBlocks :: [Block] -> [Block] removeEmptyBlocks (Null : xs) = removeEmptyBlocks xs removeEmptyBlocks (BulletList [] : xs) = removeEmptyBlocks xs removeEmptyBlocks (OrderedList _ [] : xs) = removeEmptyBlocks xs removeEmptyBlocks (DefinitionList [] : xs) = removeEmptyBlocks xs removeEmptyBlocks (RawBlock _ [] : xs) = removeEmptyBlocks xs removeEmptyBlocks (x:xs) = x : removeEmptyBlocks xs removeEmptyBlocks [] = [] removeEmptyInlines :: [Inline] -> [Inline] removeEmptyInlines (Emph [] : zs) = removeEmptyInlines zs removeEmptyInlines (Strong [] : zs) = removeEmptyInlines zs removeEmptyInlines (Subscript [] : zs) = removeEmptyInlines zs removeEmptyInlines (Superscript [] : zs) = removeEmptyInlines zs removeEmptyInlines (SmallCaps [] : zs) = removeEmptyInlines zs removeEmptyInlines (Strikeout [] : zs) = removeEmptyInlines zs removeEmptyInlines (RawInline _ [] : zs) = removeEmptyInlines zs removeEmptyInlines (Code _ [] : zs) = removeEmptyInlines zs removeEmptyInlines (Str "" : zs) = removeEmptyInlines zs removeEmptyInlines (x : xs) = x : removeEmptyInlines xs removeEmptyInlines [] = [] removeTrailingInlineSpaces :: [Inline] -> [Inline] removeTrailingInlineSpaces = reverse . removeLeadingInlineSpaces . reverse removeLeadingInlineSpaces :: [Inline] -> [Inline] removeLeadingInlineSpaces = dropWhile isSpaceOrEmpty consolidateInlines :: [Inline] -> [Inline] consolidateInlines (Str x : ys) = case concat (x : map fromStr strs) of "" -> consolidateInlines rest n -> Str n : consolidateInlines rest where (strs, rest) = span isStr ys isStr (Str _) = True isStr _ = False fromStr (Str z) = z fromStr _ = error "consolidateInlines - fromStr - not a Str" consolidateInlines (Space : ys) = Space : rest where isSp Space = True isSp _ = False rest = consolidateInlines $ dropWhile isSp ys consolidateInlines (Emph xs : Emph ys : zs) = consolidateInlines $ Emph (xs ++ ys) : zs consolidateInlines (Strong xs : Strong ys : zs) = consolidateInlines $ Strong (xs ++ ys) : zs consolidateInlines (Subscript xs : Subscript ys : zs) = consolidateInlines $ Subscript (xs ++ ys) : zs consolidateInlines (Superscript xs : Superscript ys : zs) = consolidateInlines $ Superscript (xs ++ ys) : zs consolidateInlines (SmallCaps xs : SmallCaps ys : zs) = consolidateInlines $ SmallCaps (xs ++ ys) : zs consolidateInlines (Strikeout xs : Strikeout ys : zs) = consolidateInlines $ Strikeout (xs ++ ys) : zs consolidateInlines (RawInline f x : RawInline f' y : zs) | f == f' = consolidateInlines $ RawInline f (x ++ y) : zs consolidateInlines (Code a1 x : Code a2 y : zs) | a1 == a2 = consolidateInlines $ Code a1 (x ++ y) : zs consolidateInlines (x : xs) = x : consolidateInlines xs consolidateInlines [] = [] -- | Convert pandoc structure to a string with formatting removed. -- Footnotes are skipped (since we don't want their contents in link -- labels). stringify :: Walkable Inline a => a -> String stringify = query go . walk deNote where go :: Inline -> [Char] go Space = " " go (Str x) = x go (Code _ x) = x go (Math _ x) = x go LineBreak = " " go _ = "" deNote (Note _) = Str "" deNote x = x -- | Change final list item from @Para@ to @Plain@ if the list contains -- no other @Para@ blocks. compactify :: [[Block]] -- ^ List of list items (each a list of blocks) -> [[Block]] compactify [] = [] compactify items = case (init items, last items) of (_,[]) -> items (others, final) -> case last final of Para a -> case (filter isPara $ concat items) of -- if this is only Para, change to Plain [_] -> others ++ [init final ++ [Plain a]] _ -> items _ -> items -- | Change final list item from @Para@ to @Plain@ if the list contains -- no other @Para@ blocks. Like compactify, but operates on @Blocks@ rather -- than @[Block]@. compactify' :: [Blocks] -- ^ List of list items (each a list of blocks) -> [Blocks] compactify' [] = [] compactify' items = let (others, final) = (init items, last items) in case reverse (B.toList final) of (Para a:xs) -> case [Para x | Para x <- concatMap B.toList items] of -- if this is only Para, change to Plain [_] -> others ++ [B.fromList (reverse $ Plain a : xs)] _ -> items _ -> items isPara :: Block -> Bool isPara (Para _) = True isPara _ = False -- | Data structure for defining hierarchical Pandoc documents data Element = Blk Block | Sec Int [Int] Attr [Inline] [Element] -- lvl num attributes label contents deriving (Eq, Read, Show, Typeable, Data) instance Walkable Inline Element where walk f (Blk x) = Blk (walk f x) walk f (Sec lev nums attr ils elts) = Sec lev nums attr (walk f ils) (walk f elts) walkM f (Blk x) = Blk `fmap` walkM f x walkM f (Sec lev nums attr ils elts) = do ils' <- walkM f ils elts' <- walkM f elts return $ Sec lev nums attr ils' elts' query f (Blk x) = query f x query f (Sec _ _ _ ils elts) = query f ils <> query f elts instance Walkable Block Element where walk f (Blk x) = Blk (walk f x) walk f (Sec lev nums attr ils elts) = Sec lev nums attr (walk f ils) (walk f elts) walkM f (Blk x) = Blk `fmap` walkM f x walkM f (Sec lev nums attr ils elts) = do ils' <- walkM f ils elts' <- walkM f elts return $ Sec lev nums attr ils' elts' query f (Blk x) = query f x query f (Sec _ _ _ ils elts) = query f ils <> query f elts -- | Convert Pandoc inline list to plain text identifier. HTML -- identifiers must start with a letter, and may contain only -- letters, digits, and the characters _-. inlineListToIdentifier :: [Inline] -> String inlineListToIdentifier = dropWhile (not . isAlpha) . intercalate "-" . words . map (nbspToSp . toLower) . filter (\c -> isLetter c || isDigit c || c `elem` "_-. ") . stringify where nbspToSp '\160' = ' ' nbspToSp x = x -- | Convert list of Pandoc blocks into (hierarchical) list of Elements hierarchicalize :: [Block] -> [Element] hierarchicalize blocks = S.evalState (hierarchicalizeWithIds blocks) [] hierarchicalizeWithIds :: [Block] -> S.State [Int] [Element] hierarchicalizeWithIds [] = return [] hierarchicalizeWithIds ((Header level attr@(_,classes,_) title'):xs) = do lastnum <- S.get let lastnum' = take level lastnum let newnum = case length lastnum' of x | "unnumbered" `elem` classes -> [] | x >= level -> init lastnum' ++ [last lastnum' + 1] | otherwise -> lastnum ++ replicate (level - length lastnum - 1) 0 ++ [1] unless (null newnum) $ S.put newnum let (sectionContents, rest) = break (headerLtEq level) xs sectionContents' <- hierarchicalizeWithIds sectionContents rest' <- hierarchicalizeWithIds rest return $ Sec level newnum attr title' sectionContents' : rest' hierarchicalizeWithIds (x:rest) = do rest' <- hierarchicalizeWithIds rest return $ (Blk x) : rest' headerLtEq :: Int -> Block -> Bool headerLtEq level (Header l _ _) = l <= level headerLtEq _ _ = False -- | Generate a unique identifier from a list of inlines. -- Second argument is a list of already used identifiers. uniqueIdent :: [Inline] -> [String] -> String uniqueIdent title' usedIdents = let baseIdent = case inlineListToIdentifier title' of "" -> "section" x -> x numIdent n = baseIdent ++ "-" ++ show n in if baseIdent `elem` usedIdents then case find (\x -> numIdent x `notElem` usedIdents) ([1..60000] :: [Int]) of Just x -> numIdent x Nothing -> baseIdent -- if we have more than 60,000, allow repeats else baseIdent -- | True if block is a Header block. isHeaderBlock :: Block -> Bool isHeaderBlock (Header _ _ _) = True isHeaderBlock _ = False -- | Shift header levels up or down. headerShift :: Int -> Pandoc -> Pandoc headerShift n = walk shift where shift :: Block -> Block shift (Header level attr inner) = Header (level + n) attr inner shift x = x -- | Detect if a list is tight. isTightList :: [[Block]] -> Bool isTightList = and . map firstIsPlain where firstIsPlain (Plain _ : _) = True firstIsPlain _ = False -- | Set a field of a 'Meta' object. If the field already has a value, -- convert it into a list with the new value appended to the old value(s). addMetaField :: ToMetaValue a => String -> a -> Meta -> Meta addMetaField key val (Meta meta) = Meta $ M.insertWith combine key (toMetaValue val) meta where combine newval (MetaList xs) = MetaList (xs ++ [newval]) combine newval x = MetaList [x, newval] -- | Create 'Meta' from old-style title, authors, date. This is -- provided to ease the transition from the old API. makeMeta :: [Inline] -> [[Inline]] -> [Inline] -> Meta makeMeta title authors date = addMetaField "title" (B.fromList title) $ addMetaField "author" (map B.fromList authors) $ addMetaField "date" (B.fromList date) $ nullMeta -- -- TagSoup HTML handling -- -- | Render HTML tags. renderTags' :: [Tag String] -> String renderTags' = renderTagsOptions renderOptions{ optMinimize = \x -> let y = map toLower x in y == "hr" || y == "br" || y == "img" || y == "meta" || y == "link" , optRawTag = \x -> let y = map toLower x in y == "script" || y == "style" } -- -- File handling -- -- | Perform an IO action in a directory, returning to starting directory. inDirectory :: FilePath -> IO a -> IO a inDirectory path action = do oldDir <- getCurrentDirectory setCurrentDirectory path result <- action setCurrentDirectory oldDir return result readDefaultDataFile :: FilePath -> IO BS.ByteString readDefaultDataFile fname = #ifdef EMBED_DATA_FILES case lookup (makeCanonical fname) dataFiles of Nothing -> err 97 $ "Could not find data file " ++ fname Just contents -> return contents where makeCanonical = joinPath . transformPathParts . splitDirectories transformPathParts = reverse . foldl go [] go as "." = as go (_:as) ".." = as go as x = x : as #else getDataFileName ("data" fname) >>= checkExistence >>= BS.readFile where checkExistence fn = do exists <- doesFileExist fn if exists then return fn else err 97 ("Could not find data file " ++ fname) #endif -- | Read file from specified user data directory or, if not found there, from -- Cabal data directory. readDataFile :: Maybe FilePath -> FilePath -> IO BS.ByteString readDataFile Nothing fname = readDefaultDataFile fname readDataFile (Just userDir) fname = do exists <- doesFileExist (userDir fname) if exists then BS.readFile (userDir fname) else readDefaultDataFile fname -- | Same as 'readDataFile' but returns a String instead of a ByteString. readDataFileUTF8 :: Maybe FilePath -> FilePath -> IO String readDataFileUTF8 userDir fname = UTF8.toString `fmap` readDataFile userDir fname -- | Fetch an image or other item from the local filesystem or the net. -- Returns raw content and maybe mime type. fetchItem :: Maybe String -> String -> IO (Either E.SomeException (BS.ByteString, Maybe String)) fetchItem sourceURL s | isURI s = openURL s | otherwise = case sourceURL of Just u -> openURL (u ++ "/" ++ s) Nothing -> E.try readLocalFile where readLocalFile = do let mime = case takeExtension s of ".gz" -> getMimeType $ dropExtension s x -> getMimeType x cont <- BS.readFile s return (cont, mime) -- | Read from a URL and return raw data and maybe mime type. openURL :: String -> IO (Either E.SomeException (BS.ByteString, Maybe String)) openURL u | "data:" `isPrefixOf` u = let mime = takeWhile (/=',') $ drop 5 u contents = B8.pack $ unEscapeString $ drop 1 $ dropWhile (/=',') u in return $ Right (decodeLenient contents, Just mime) #ifdef HTTP_CONDUIT | otherwise = E.try $ do req <- parseUrl u resp <- withManager $ httpLbs req return (BS.concat $ toChunks $ responseBody resp, UTF8.toString `fmap` lookup hContentType (responseHeaders resp)) #else | otherwise = E.try $ getBodyAndMimeType `fmap` browse (do S.liftIO $ UTF8.hPutStrLn stderr $ "Fetching " ++ u ++ "..." setOutHandler $ const (return ()) setAllowRedirects True request (getRequest' u')) where getBodyAndMimeType (_, r) = (rspBody r, findHeader HdrContentType r) getRequest' uriString = case parseURI uriString of Nothing -> error ("Not a valid URL: " ++ uriString) Just v -> mkRequest GET v u' = escapeURIString (/= '|') u -- pipes are rejected by Network.URI #endif -- -- Error reporting -- err :: Int -> String -> IO a err exitCode msg = do name <- getProgName UTF8.hPutStrLn stderr $ name ++ ": " ++ msg exitWith $ ExitFailure exitCode return undefined warn :: String -> IO () warn msg = do name <- getProgName UTF8.hPutStrLn stderr $ name ++ ": " ++ msg -- -- Safe read -- safeRead :: (Monad m, Read a) => String -> m a safeRead s = case reads s of (d,x):_ | all isSpace x -> return d _ -> fail $ "Could not read `" ++ s ++ "'" pandoc-1.12.2.1/src/Text/Pandoc/Slides.hs000644 000765 000024 00000005250 12251233602 017614 0ustar00jgmstaff000000 000000 {- Copyright (C) 2012 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Slides Copyright : Copyright (C) 2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Utility functions for splitting documents into slides for slide show formats (dzslides, revealjs, s5, slidy, slideous, beamer). -} module Text.Pandoc.Slides ( getSlideLevel, prepSlides ) where import Text.Pandoc.Definition -- | Find level of header that starts slides (defined as the least header -- level that occurs before a non-header/non-hrule in the blocks). getSlideLevel :: [Block] -> Int getSlideLevel = go 6 where go least (Header n _ _ : x : xs) | n < least && nonHOrHR x = go n xs | otherwise = go least (x:xs) go least (_ : xs) = go least xs go least [] = least nonHOrHR (Header _ _ _) = False nonHOrHR (HorizontalRule) = False nonHOrHR _ = True -- | Prepare a block list to be passed to hierarchicalize. prepSlides :: Int -> [Block] -> [Block] 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 pandoc-1.12.2.1/src/Text/Pandoc/Templates.hs000644 000765 000024 00000025761 12251233602 020340 0ustar00jgmstaff000000 000000 {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, CPP, OverloadedStrings, GeneralizedNewtypeDeriving #-} {- Copyright (C) 2009-2013 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Templates Copyright : Copyright (C) 2009-2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable A simple templating system with variable substitution and conditionals. The following program illustrates its use: > {-# LANGUAGE OverloadedStrings #-} > import Data.Text > import Data.Aeson > import Text.Pandoc.Templates > > data Employee = Employee { firstName :: String > , lastName :: String > , salary :: Maybe Int } > instance ToJSON Employee where > toJSON e = object [ "name" .= object [ "first" .= firstName e > , "last" .= lastName e ] > , "salary" .= salary e ] > > employees :: [Employee] > employees = [ Employee "John" "Doe" Nothing > , Employee "Omar" "Smith" (Just 30000) > , Employee "Sara" "Chen" (Just 60000) ] > > template :: Template > template = either error id $ compileTemplate > "$for(employee)$Hi, $employee.name.first$. $if(employee.salary)$You make $employee.salary$.$else$No salary data.$endif$$sep$\n$endfor$" > > main = putStrLn $ renderTemplate template $ object ["employee" .= employees ] A slot for an interpolated variable is a variable name surrounded by dollar signs. To include a literal @$@ in your template, use @$$@. Variable names must begin with a letter and can contain letters, numbers, @_@, @-@, and @.@. The values of variables are determined by a JSON object that is passed as a parameter to @renderTemplate@. So, for example, @title@ will return the value of the @title@ field, and @employee.salary@ will return the value of the @salary@ field of the object that is the value of the @employee@ field. The value of a variable will be indented to the same level as the variable. A conditional begins with @$if(variable_name)$@ and ends with @$endif$@. It may optionally contain an @$else$@ section. The if section is used if @variable_name@ has a non-null value, otherwise the else section is used. Conditional keywords should not be indented, or unexpected spacing problems may occur. The @$for$@ keyword can be used to iterate over an array. If the value of the associated variable is not an array, a single iteration will be performed on its value. You may optionally specify separators using @$sep$@, as in the example above. -} module Text.Pandoc.Templates ( renderTemplate , renderTemplate' , TemplateTarget(..) , varListToJSON , compileTemplate , Template , getDefaultTemplate ) where import Data.Char (isAlphaNum) import Control.Monad (guard, when) import Data.Aeson (ToJSON(..), Value(..)) import qualified Data.Attoparsec.Text as A import Data.Attoparsec.Text (Parser) import Control.Applicative import qualified Data.Text as T import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) import Text.Pandoc.Compat.Monoid ((<>), Monoid(..)) import Data.List (intersperse, nub) import System.FilePath ((), (<.>)) import qualified Data.Map as M import qualified Data.HashMap.Strict as H import Data.Foldable (toList) import qualified Control.Exception.Extensible as E (try, IOException) #if MIN_VERSION_blaze_html(0,5,0) import Text.Blaze.Html (Html) import Text.Blaze.Internal (preEscapedText) #else 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 -> String -- ^ Name of writer -> IO (Either E.IOException String) getDefaultTemplate user writer = do let format = takeWhile (`notElem` "+-") writer -- strip off extensions case format of "native" -> return $ Right "" "json" -> return $ Right "" "docx" -> return $ Right "" "odt" -> getDefaultTemplate user "opendocument" "markdown_strict" -> getDefaultTemplate user "markdown" "multimarkdown" -> getDefaultTemplate user "markdown" "markdown_github" -> getDefaultTemplate user "markdown" "markdown_mmd" -> getDefaultTemplate user "markdown" "markdown_phpextra" -> getDefaultTemplate user "markdown" _ -> let fname = "templates" "default" <.> format in E.try $ readDataFileUTF8 user fname newtype Template = Template { unTemplate :: Value -> Text } deriving Monoid type Variable = [Text] class TemplateTarget a where toTarget :: Text -> a instance TemplateTarget Text where toTarget = id instance TemplateTarget String where toTarget = T.unpack instance TemplateTarget ByteString where toTarget = fromChunks . (:[]) . encodeUtf8 instance TemplateTarget Html where toTarget = preEscapedText varListToJSON :: [(String, String)] -> Value varListToJSON assoc = toJSON $ M.fromList assoc' where assoc' = [(T.pack k, toVal [T.pack z | (y,z) <- assoc, not (null z), y == k]) | k <- nub $ map fst assoc ] toVal [x] = toJSON x toVal [] = Null toVal xs = toJSON xs renderTemplate :: (ToJSON a, TemplateTarget b) => Template -> a -> b renderTemplate (Template f) context = toTarget $ f $ toJSON context compileTemplate :: Text -> Either String Template compileTemplate template = A.parseOnly pTemplate template -- | Like 'renderTemplate', but compiles the template first, -- raising an error if compilation fails. renderTemplate' :: (ToJSON a, TemplateTarget b) => String -> a -> b renderTemplate' template = renderTemplate (either error id $ compileTemplate $ T.pack template) var :: Variable -> Template var = Template . resolveVar resolveVar :: Variable -> Value -> Text resolveVar var' val = case multiLookup var' val of 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" Just _ -> mempty Nothing -> mempty multiLookup :: [Text] -> Value -> Maybe Value multiLookup [] x = Just x multiLookup (v:vs) (Object o) = H.lookup v o >>= multiLookup vs multiLookup _ _ = Nothing lit :: Text -> Template lit = Template . const cond :: Variable -> Template -> Template -> Template cond var' (Template ifyes) (Template ifno) = Template $ \val -> case resolveVar var' val of "" -> ifno val _ -> ifyes val iter :: Variable -> Template -> Template -> Template iter var' template sep = Template $ \val -> unTemplate (case multiLookup var' val of Just (Array vec) -> mconcat $ intersperse sep $ map (setVar template var') $ toList vec Just x -> cond var' (setVar template var' x) mempty Nothing -> mempty) val setVar :: Template -> Variable -> Value -> Template setVar (Template f) var' val = Template $ f . replaceVar var' val replaceVar :: Variable -> Value -> Value -> Value replaceVar [] new _ = new replaceVar (v:vs) new (Object o) = Object $ H.adjust (\x -> replaceVar vs new x) v o replaceVar _ _ old = old --- parsing pTemplate :: Parser Template pTemplate = do sp <- A.option mempty pInitialSpace rest <- mconcat <$> many (pConditional <|> pFor <|> pNewline <|> pVar <|> pLit <|> pEscapedDollar) return $ sp <> rest pLit :: Parser Template pLit = lit <$> A.takeWhile1 (\x -> x /='$' && x /= '\n') pNewline :: Parser Template pNewline = do A.char '\n' sp <- A.option mempty pInitialSpace return $ lit "\n" <> sp pInitialSpace :: Parser Template pInitialSpace = do sps <- A.takeWhile1 (==' ') let indentVar = if T.null sps then id else indent (T.length sps) v <- A.option mempty $ indentVar <$> pVar return $ lit sps <> v pEscapedDollar :: Parser Template pEscapedDollar = lit "$" <$ A.string "$$" pVar :: Parser Template pVar = var <$> (A.char '$' *> pIdent <* A.char '$') pIdent :: Parser [Text] pIdent = do first <- pIdentPart rest <- many (A.char '.' *> pIdentPart) return (first:rest) pIdentPart :: Parser Text pIdentPart = do first <- A.letter rest <- A.takeWhile (\c -> isAlphaNum c || c == '_' || c == '-') let id' = T.singleton first <> rest guard $ id' `notElem` reservedWords return id' reservedWords :: [Text] reservedWords = ["else","endif","for","endfor","sep"] skipEndline :: Parser () skipEndline = A.skipWhile (`elem` " \t") >> A.char '\n' >> return () pConditional :: Parser Template pConditional = do A.string "$if(" id' <- pIdent A.string ")$" -- if newline after the "if", then a newline after "endif" will be swallowed multiline <- A.option False (True <$ skipEndline) ifContents <- pTemplate elseContents <- A.option mempty $ do A.string "$else$" when multiline $ A.option () skipEndline pTemplate A.string "$endif$" when multiline $ A.option () skipEndline return $ cond id' ifContents elseContents pFor :: Parser Template pFor = do A.string "$for(" id' <- pIdent A.string ")$" -- if newline after the "for", then a newline after "endfor" will be swallowed multiline <- A.option False $ skipEndline >> return True contents <- pTemplate sep <- A.option mempty $ do A.string "$sep$" when multiline $ A.option () skipEndline pTemplate A.string "$endfor$" when multiline $ A.option () skipEndline return $ iter id' contents sep indent :: Int -> Template -> Template indent 0 x = x indent ind (Template f) = Template $ \val -> indent' (f val) where indent' t = T.concat $ intersperse ("\n" <> T.replicate ind " ") $ T.lines t pandoc-1.12.2.1/src/Text/Pandoc/UTF8.hs000644 000765 000024 00000007766 12251233602 017135 0ustar00jgmstaff000000 000000 {-# LANGUAGE CPP #-} {- Copyright (C) 2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.UTF8 Copyright : Copyright (C) 2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable UTF-8 aware string IO functions that will work with GHC 6.10, 6.12, or 7. -} module Text.Pandoc.UTF8 ( readFile , writeFile , getContents , putStr , putStrLn , hPutStr , hPutStrLn , hGetContents , toString , fromString , toStringLazy , fromStringLazy , encodePath , decodeArg ) where import System.IO hiding (readFile, writeFile, getContents, putStr, putStrLn, hPutStr, hPutStrLn, hGetContents) #if MIN_VERSION_base(4,6,0) import Prelude hiding (readFile, writeFile, getContents, putStr, putStrLn) #else import Prelude hiding (readFile, writeFile, getContents, putStr, putStrLn, catch) #endif import qualified System.IO as IO import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy as BL import qualified Data.Text.Encoding as T import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TL readFile :: FilePath -> IO String readFile f = do h <- openFile (encodePath f) ReadMode hGetContents h writeFile :: FilePath -> String -> IO () writeFile f s = withFile (encodePath f) WriteMode $ \h -> hPutStr h s getContents :: IO String getContents = hGetContents stdin putStr :: String -> IO () putStr s = hPutStr stdout s putStrLn :: String -> IO () putStrLn s = hPutStrLn stdout s hPutStr :: Handle -> String -> IO () hPutStr h s = hSetEncoding h utf8 >> IO.hPutStr h s hPutStrLn :: Handle -> String -> IO () hPutStrLn h s = hSetEncoding h utf8 >> IO.hPutStrLn h s hGetContents :: Handle -> IO String hGetContents = fmap toString . B.hGetContents -- hGetContents h = hSetEncoding h utf8_bom -- >> hSetNewlineMode h universalNewlineMode -- >> IO.hGetContents h -- | Drop BOM (byte order marker) if present at beginning of string. -- Note that Data.Text converts the BOM to code point FEFF, zero-width -- no-break space, so if the string begins with this we strip it off. dropBOM :: String -> String dropBOM ('\xFEFF':xs) = xs dropBOM xs = xs -- | Convert UTF8-encoded ByteString to String, also -- removing '\r' characters. toString :: B.ByteString -> String toString = filter (/='\r') . dropBOM . T.unpack . T.decodeUtf8 fromString :: String -> B.ByteString fromString = T.encodeUtf8 . T.pack -- | Convert UTF8-encoded ByteString to String, also -- removing '\r' characters. toStringLazy :: BL.ByteString -> String toStringLazy = filter (/='\r') . dropBOM . TL.unpack . TL.decodeUtf8 fromStringLazy :: String -> BL.ByteString fromStringLazy = TL.encodeUtf8 . TL.pack encodePath :: FilePath -> FilePath decodeArg :: String -> String #if MIN_VERSION_base(4,4,0) encodePath = id decodeArg = id #else encodePath = B.unpack . fromString decodeArg = toString . B.pack #endif pandoc-1.12.2.1/src/Text/Pandoc/UUID.hs000644 000765 000024 00000004405 12251233602 017140 0ustar00jgmstaff000000 000000 {- Copyright (C) 2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.UUID Copyright : Copyright (C) 2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable UUID generation using Version 4 (random method) described in RFC4122. See http://tools.ietf.org/html/rfc4122 -} module Text.Pandoc.UUID ( UUID, getRandomUUID ) where import Text.Printf ( printf ) import System.Random ( randomIO ) import Data.Word import Data.Bits ( setBit, clearBit ) import Control.Monad ( liftM ) data UUID = UUID Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 instance Show UUID where show (UUID a b c d e f g h i j k l m n o p) = "urn:uuid:" ++ printf "%02x" a ++ printf "%02x" b ++ printf "%02x" c ++ printf "%02x" d ++ "-" ++ printf "%02x" e ++ printf "%02x" f ++ "-" ++ printf "%02x" g ++ printf "%02x" h ++ "-" ++ printf "%02x" i ++ printf "%02x" j ++ "-" ++ printf "%02x" k ++ printf "%02x" l ++ printf "%02x" m ++ printf "%02x" n ++ printf "%02x" o ++ printf "%02x" p getRandomUUID :: IO UUID getRandomUUID = do let getRN :: a -> IO Word8 getRN _ = liftM fromIntegral (randomIO :: IO Int) [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] <- mapM getRN ([1..16] :: [Int]) -- set variant let i' = i `setBit` 7 `clearBit` 6 -- set version (0100 for random) let g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4 return $ UUID a b c d e f g' h i' j k l m n o p pandoc-1.12.2.1/src/Text/Pandoc/Writers/000755 000765 000024 00000000000 12251233602 017472 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/src/Text/Pandoc/XML.hs000644 000765 000024 00000007767 12251233602 017050 0ustar00jgmstaff000000 000000 {- Copyright (C) 2006-2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.XML Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Functions for escaping and formatting XML. -} module Text.Pandoc.XML ( escapeCharForXML, escapeStringForXML, inTags, selfClosingTag, inTagsSimple, inTagsIndented, toEntities, fromEntities ) where import Text.Pandoc.Pretty import Data.Char (ord, isAscii, isSpace) import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) -- | Escape one character as needed for XML. escapeCharForXML :: Char -> String escapeCharForXML x = case x of '&' -> "&" '<' -> "<" '>' -> ">" '"' -> """ c -> [c] -- | Escape string as needed for XML. Entity references are not preserved. escapeStringForXML :: String -> String escapeStringForXML = concatMap escapeCharForXML -- | Escape newline characters as escapeNls :: String -> String escapeNls (x:xs) | x == '\n' = " " ++ escapeNls xs | otherwise = x : escapeNls xs escapeNls [] = [] -- | Return a text object with a string of formatted XML attributes. attributeList :: [(String, String)] -> Doc attributeList = hcat . map (\(a, b) -> text (' ' : escapeStringForXML a ++ "=\"" ++ escapeNls (escapeStringForXML b) ++ "\"")) -- | Put the supplied contents between start and end tags of tagType, -- with specified attributes and (if specified) indentation. inTags:: Bool -> String -> [(String, String)] -> Doc -> Doc inTags isIndented tagType attribs contents = let openTag = char '<' <> text tagType <> attributeList attribs <> char '>' closeTag = text " text tagType <> char '>' in if isIndented then openTag $$ nest 2 contents $$ closeTag else openTag <> contents <> closeTag -- | Return a self-closing tag of tagType with specified attributes selfClosingTag :: String -> [(String, String)] -> Doc selfClosingTag tagType attribs = char '<' <> text tagType <> attributeList attribs <> text " />" -- | Put the supplied contents between start and end tags of tagType. inTagsSimple :: String -> Doc -> Doc inTagsSimple tagType = inTags False tagType [] -- | Put the supplied contents in indented block btw start and end tags. inTagsIndented :: String -> Doc -> Doc inTagsIndented tagType = inTags True tagType [] -- | Escape all non-ascii characters using numerical entities. toEntities :: String -> String toEntities [] = "" toEntities (c:cs) | isAscii c = c : toEntities cs | otherwise = "&#" ++ show (ord c) ++ ";" ++ toEntities cs -- Unescapes XML entities fromEntities :: String -> String fromEntities ('&':xs) = case lookupEntity ent of Just c -> c : fromEntities rest Nothing -> '&' : fromEntities xs where (ent, rest) = case break (\c -> isSpace c || c == ';') xs of (zs,';':ys) -> (zs,ys) _ -> ("",xs) fromEntities (x:xs) = x : fromEntities xs fromEntities [] = [] pandoc-1.12.2.1/src/Text/Pandoc/Writers/AsciiDoc.hs000644 000765 000024 00000042130 12251233602 021504 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2006-2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.AsciiDoc Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of 'Pandoc' documents to asciidoc. Note that some information may be lost in conversion, due to expressive limitations of asciidoc. Footnotes and table cells with paragraphs (or other block items) are not possible in asciidoc. If pandoc encounters one of these, it will insert a message indicating that it has omitted the construct. AsciiDoc: -} module Text.Pandoc.Writers.AsciiDoc (writeAsciiDoc) where import Text.Pandoc.Definition import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, space) import Data.List ( isPrefixOf, intersperse, intercalate ) import Text.Pandoc.Pretty import Control.Monad.State import qualified Data.Map as M import Data.Aeson (Value(String), fromJSON, toJSON, Result(..)) import qualified Data.Text as T data WriterState = WriterState { defListMarker :: String , orderedListLevel :: Int , bulletListLevel :: Int } -- | Convert Pandoc to AsciiDoc. writeAsciiDoc :: WriterOptions -> Pandoc -> String writeAsciiDoc opts document = evalState (pandocToAsciiDoc opts document) WriterState{ defListMarker = "::" , orderedListLevel = 1 , bulletListLevel = 1 } -- | Return asciidoc representation of document. pandocToAsciiDoc :: WriterOptions -> Pandoc -> State WriterState String pandocToAsciiDoc opts (Pandoc meta blocks) = do let titleblock = not $ null (docTitle meta) && null (docAuthors meta) && null (docDate meta) let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing metadata <- metaToJSON opts (fmap (render colwidth) . blockListToAsciiDoc opts) (fmap (render colwidth) . inlineListToAsciiDoc opts) meta let addTitleLine (String t) = String $ t <> "\n" <> T.replicate (T.length t) "=" addTitleLine x = x let metadata' = case fromJSON metadata of Success m -> toJSON $ M.adjust addTitleLine ("title" :: T.Text) m _ -> metadata body <- blockListToAsciiDoc opts blocks let main = render colwidth body let context = defField "body" main $ defField "toc" (writerTableOfContents opts && writerStandalone opts) $ defField "titleblock" titleblock $ metadata' if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main -- | Escape special characters for AsciiDoc. escapeString :: String -> String escapeString = escapeStringUsing escs where escs = backslashEscapes "{" -- | Ordered list start parser for use in Para below. olMarker :: Parser [Char] ParserState Char olMarker = do (start, style', delim) <- anyOrderedListMarker if delim == Period && (style' == UpperAlpha || (style' == UpperRoman && start `elem` [1, 5, 10, 50, 100, 500, 1000])) then spaceChar >> spaceChar else spaceChar -- | True if string begins with an ordered list marker beginsWithOrderedListMarker :: String -> Bool beginsWithOrderedListMarker str = case runParser olMarker defaultParserState "para start" (take 10 str) of Left _ -> False Right _ -> True -- | Convert Pandoc block element to asciidoc. blockToAsciiDoc :: WriterOptions -- ^ Options -> Block -- ^ Block element -> State WriterState Doc blockToAsciiDoc _ Null = return empty blockToAsciiDoc opts (Plain inlines) = do contents <- inlineListToAsciiDoc opts inlines return $ contents <> cr blockToAsciiDoc opts (Para [Image alt (src,'f':'i':'g':':':tit)]) = blockToAsciiDoc opts (Para [Image alt (src,tit)]) blockToAsciiDoc opts (Para inlines) = do contents <- inlineListToAsciiDoc opts inlines -- escape if para starts with ordered list marker let esc = if beginsWithOrderedListMarker (render Nothing contents) then text "\\" else empty return $ esc <> contents <> blankline blockToAsciiDoc _ (RawBlock f s) | f == "asciidoc" = return $ text s | otherwise = return empty blockToAsciiDoc _ HorizontalRule = return $ blankline <> text "'''''" <> blankline blockToAsciiDoc opts (Header level (ident,_,_) inlines) = do contents <- inlineListToAsciiDoc opts inlines let len = offset contents -- ident seem to be empty most of the time and asciidoc will generate them automatically -- so lets make them not show up when null let identifier = if (null ident) then empty else ("[[" <> text ident <> "]]") let setext = writerSetextHeaders opts return $ (if setext then identifier $$ contents $$ (case level of 1 -> text $ replicate len '-' 2 -> text $ replicate len '~' 3 -> text $ replicate len '^' 4 -> text $ replicate len '+' _ -> empty) <> blankline else identifier $$ text (replicate level '=') <> space <> contents <> blankline) blockToAsciiDoc _ (CodeBlock (_,classes,_) str) = return $ flush (attrs <> dashes <> space <> attrs <> cr <> text str <> cr <> dashes) <> blankline where dashes = text $ replicate (maximum $ map length $ lines str) '-' attrs = if null classes then empty else text $ intercalate "," $ "code" : classes blockToAsciiDoc opts (BlockQuote blocks) = do contents <- blockListToAsciiDoc opts blocks let isBlock (BlockQuote _) = True isBlock _ = False -- if there are nested block quotes, put in an open block let contents' = if any isBlock blocks then "--" $$ contents $$ "--" else contents let cols = offset contents' let bar = text $ replicate cols '_' return $ bar $$ chomp contents' $$ bar <> blankline blockToAsciiDoc opts (Table caption aligns widths headers rows) = do caption' <- inlineListToAsciiDoc opts caption let caption'' = if null caption then empty else "." <> caption' <> cr let isSimple = all (== 0) widths let relativePercentWidths = if isSimple then widths else map (/ (sum widths)) widths let widths'' :: [Integer] widths'' = map (floor . (* 100)) relativePercentWidths -- ensure that the widths sum to 100 let widths' = case widths'' of _ | isSimple -> widths'' (w:ws) | sum (w:ws) < 100 -> (100 - sum ws) : ws ws -> ws let totalwidth :: Integer totalwidth = floor $ sum widths * 100 let colspec al wi = (case al of AlignLeft -> "<" AlignCenter -> "^" AlignRight -> ">" AlignDefault -> "") ++ if wi == 0 then "" else (show wi ++ "%") let headerspec = if all null headers then empty else text "options=\"header\"," let widthspec = if totalwidth == 0 then empty else text "width=" <> doubleQuotes (text $ show totalwidth ++ "%") <> text "," let tablespec = text "[" <> widthspec <> text "cols=" <> doubleQuotes (text $ intercalate "," $ zipWith colspec aligns widths') <> text "," <> headerspec <> text "]" let makeCell [Plain x] = do d <- blockListToAsciiDoc opts [Plain x] return $ text "|" <> chomp d makeCell [Para x] = makeCell [Plain x] makeCell _ = return $ text "|" <> "[multiblock cell omitted]" let makeRow cells = hsep `fmap` mapM makeCell cells rows' <- mapM makeRow rows head' <- makeRow headers let head'' = if all null headers then empty else head' let colwidth = if writerWrapText opts then writerColumns opts else 100000 let maxwidth = maximum $ map offset (head':rows') let body = if maxwidth > colwidth then vsep rows' else vcat rows' let border = text $ "|" ++ replicate ((min maxwidth colwidth) - 1) '=' return $ caption'' $$ tablespec $$ border $$ head'' $$ body $$ border $$ blankline blockToAsciiDoc opts (BulletList items) = do contents <- mapM (bulletListItemToAsciiDoc opts) items return $ cat contents <> blankline blockToAsciiDoc opts (OrderedList (_start, sty, _delim) items) = do let sty' = case sty of UpperRoman -> UpperAlpha LowerRoman -> LowerAlpha x -> x let markers = orderedListMarkers (1, sty', Period) -- start num not used let markers' = map (\m -> if length m < 3 then m ++ replicate (3 - length m) ' ' else m) markers contents <- mapM (\(item, num) -> orderedListItemToAsciiDoc opts item num) $ zip markers' items return $ cat contents <> blankline blockToAsciiDoc opts (DefinitionList items) = do contents <- mapM (definitionListItemToAsciiDoc opts) items return $ cat contents <> blankline blockToAsciiDoc opts (Div _ bs) = blockListToAsciiDoc opts bs -- | Convert bullet list item (list of blocks) to asciidoc. bulletListItemToAsciiDoc :: WriterOptions -> [Block] -> State WriterState Doc bulletListItemToAsciiDoc opts blocks = do let addBlock :: Doc -> Block -> State WriterState Doc addBlock d b | isEmpty d = chomp `fmap` blockToAsciiDoc opts b addBlock d b@(BulletList _) = do x <- blockToAsciiDoc opts b return $ d <> cr <> chomp x addBlock d b@(OrderedList _ _) = do x <- blockToAsciiDoc opts b return $ d <> cr <> chomp x addBlock d b = do x <- blockToAsciiDoc opts b return $ d <> cr <> text "+" <> cr <> chomp x lev <- bulletListLevel `fmap` get modify $ \s -> s{ bulletListLevel = lev + 1 } contents <- foldM addBlock empty blocks modify $ \s -> s{ bulletListLevel = lev } let marker = text (replicate lev '*') return $ marker <> space <> contents <> cr -- | Convert ordered list item (a list of blocks) to asciidoc. orderedListItemToAsciiDoc :: WriterOptions -- ^ options -> String -- ^ list item marker -> [Block] -- ^ list item (list of blocks) -> State WriterState Doc orderedListItemToAsciiDoc opts marker blocks = do let addBlock :: Doc -> Block -> State WriterState Doc addBlock d b | isEmpty d = chomp `fmap` blockToAsciiDoc opts b addBlock d b@(BulletList _) = do x <- blockToAsciiDoc opts b return $ d <> cr <> chomp x addBlock d b@(OrderedList _ _) = do x <- blockToAsciiDoc opts b return $ d <> cr <> chomp x addBlock d b = do x <- blockToAsciiDoc opts b return $ d <> cr <> text "+" <> cr <> chomp x lev <- orderedListLevel `fmap` get modify $ \s -> s{ orderedListLevel = lev + 1 } contents <- foldM addBlock empty blocks modify $ \s -> s{ orderedListLevel = lev } return $ text marker <> space <> contents <> cr -- | Convert definition list item (label, list of blocks) to asciidoc. definitionListItemToAsciiDoc :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState Doc definitionListItemToAsciiDoc opts (label, defs) = do labelText <- inlineListToAsciiDoc opts label marker <- defListMarker `fmap` get if marker == "::" then modify (\st -> st{ defListMarker = ";;"}) else modify (\st -> st{ defListMarker = "::"}) let divider = cr <> text "+" <> cr let defsToAsciiDoc :: [Block] -> State WriterState Doc defsToAsciiDoc ds = (vcat . intersperse divider . map chomp) `fmap` mapM (blockToAsciiDoc opts) ds defs' <- mapM defsToAsciiDoc defs modify (\st -> st{ defListMarker = marker }) let contents = nest 2 $ vcat $ intersperse divider $ map chomp defs' return $ labelText <> text marker <> cr <> contents <> cr -- | Convert list of Pandoc block elements to asciidoc. blockListToAsciiDoc :: WriterOptions -- ^ Options -> [Block] -- ^ List of block elements -> State WriterState Doc blockListToAsciiDoc opts blocks = cat `fmap` mapM (blockToAsciiDoc opts) blocks -- | Convert list of Pandoc inline elements to asciidoc. inlineListToAsciiDoc :: WriterOptions -> [Inline] -> State WriterState Doc inlineListToAsciiDoc opts lst = mapM (inlineToAsciiDoc opts) lst >>= return . cat -- | Convert Pandoc inline element to asciidoc. inlineToAsciiDoc :: WriterOptions -> Inline -> State WriterState Doc inlineToAsciiDoc opts (Emph lst) = do contents <- inlineListToAsciiDoc opts lst return $ "_" <> contents <> "_" inlineToAsciiDoc opts (Strong lst) = do contents <- inlineListToAsciiDoc opts lst return $ "*" <> contents <> "*" inlineToAsciiDoc opts (Strikeout lst) = do contents <- inlineListToAsciiDoc opts lst return $ "[line-through]*" <> contents <> "*" inlineToAsciiDoc opts (Superscript lst) = do contents <- inlineListToAsciiDoc opts lst return $ "^" <> contents <> "^" inlineToAsciiDoc opts (Subscript lst) = do contents <- inlineListToAsciiDoc opts lst return $ "~" <> contents <> "~" inlineToAsciiDoc opts (SmallCaps lst) = inlineListToAsciiDoc opts lst inlineToAsciiDoc opts (Quoted SingleQuote lst) = do contents <- inlineListToAsciiDoc opts lst return $ "`" <> contents <> "'" inlineToAsciiDoc opts (Quoted DoubleQuote lst) = do contents <- inlineListToAsciiDoc opts lst return $ "``" <> contents <> "''" inlineToAsciiDoc _ (Code _ str) = return $ text "`" <> text (escapeStringUsing (backslashEscapes "`") str) <> "`" inlineToAsciiDoc _ (Str str) = return $ text $ escapeString str inlineToAsciiDoc _ (Math InlineMath str) = return $ "latexmath:[$" <> text str <> "$]" inlineToAsciiDoc _ (Math DisplayMath str) = return $ "latexmath:[\\[" <> text str <> "\\]]" inlineToAsciiDoc _ (RawInline f s) | f == "asciidoc" = return $ text s | otherwise = return empty inlineToAsciiDoc _ (LineBreak) = return $ " +" <> cr inlineToAsciiDoc _ Space = return space inlineToAsciiDoc opts (Cite _ lst) = inlineListToAsciiDoc opts lst inlineToAsciiDoc opts (Link txt (src, _tit)) = do -- relative: link:downloads/foo.zip[download foo.zip] -- abs: http://google.cod[Google] -- or my@email.com[email john] linktext <- inlineListToAsciiDoc opts txt let isRelative = ':' `notElem` src let prefix = if isRelative then text "link:" else empty let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src let useAuto = case txt of [Str s] | escapeURI s == srcSuffix -> True _ -> False return $ if useAuto then text srcSuffix else prefix <> text src <> "[" <> linktext <> "]" inlineToAsciiDoc opts (Image alternate (src, tit)) = do -- image:images/logo.png[Company logo, title="blah"] let txt = if (null alternate) || (alternate == [Str ""]) then [Str "image"] else alternate linktext <- inlineListToAsciiDoc opts txt let linktitle = if null tit then empty else text $ ",title=\"" ++ tit ++ "\"" return $ "image:" <> text src <> "[" <> linktext <> linktitle <> "]" inlineToAsciiDoc opts (Note [Para inlines]) = inlineToAsciiDoc opts (Note [Plain inlines]) inlineToAsciiDoc opts (Note [Plain inlines]) = do contents <- inlineListToAsciiDoc opts inlines return $ text "footnote:[" <> contents <> "]" -- asciidoc can't handle blank lines in notes inlineToAsciiDoc _ (Note _) = return "[multiblock footnote omitted]" inlineToAsciiDoc opts (Span _ ils) = inlineListToAsciiDoc opts ils pandoc-1.12.2.1/src/Text/Pandoc/Writers/ConTeXt.hs000644 000765 000024 00000035675 12251233602 021372 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2007-2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.ConTeXt Copyright : Copyright (C) 2007-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of 'Pandoc' format into ConTeXt. -} module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where import Text.Pandoc.Definition import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Walk (query) import Text.Printf ( printf ) import Data.List ( intercalate, isPrefixOf ) import Control.Monad.State import Text.Pandoc.Pretty import Text.Pandoc.Templates ( renderTemplate' ) import Network.URI ( isURI, unEscapeString ) data WriterState = WriterState { stNextRef :: Int -- number of next URL reference , stOrderedListLevel :: Int -- level of ordered list , stOptions :: WriterOptions -- writer options } orderedListStyles :: [Char] orderedListStyles = cycle "narg" -- | Convert Pandoc to ConTeXt. writeConTeXt :: WriterOptions -> Pandoc -> String writeConTeXt options document = let defaultWriterState = WriterState { stNextRef = 1 , stOrderedListLevel = 0 , stOptions = options } in evalState (pandocToConTeXt options document) defaultWriterState pandocToConTeXt :: WriterOptions -> Pandoc -> State WriterState String pandocToConTeXt options (Pandoc meta blocks) = do let colwidth = if writerWrapText options then Just $ writerColumns options else Nothing metadata <- metaToJSON options (fmap (render colwidth) . blockListToConTeXt) (fmap (render colwidth) . inlineListToConTeXt) meta body <- mapM (elementToConTeXt options) $ hierarchicalize blocks let main = (render colwidth . vcat) body let context = defField "toc" (writerTableOfContents options) $ defField "placelist" (intercalate ("," :: String) $ take (writerTOCDepth options + if writerChapters options then 0 else 1) ["chapter","section","subsection","subsubsection", "subsubsubsection","subsubsubsubsection"]) $ defField "body" main $ defField "number-sections" (writerNumberSections options) $ defField "mainlang" (maybe "" (reverse . takeWhile (/=',') . reverse) (lookup "lang" $ writerVariables options)) $ metadata return $ if writerStandalone options then renderTemplate' (writerTemplate options) context else main -- escape things as needed for ConTeXt escapeCharForConTeXt :: WriterOptions -> Char -> String escapeCharForConTeXt opts ch = let ligatures = writerTeXLigatures opts in case ch of '{' -> "\\{" '}' -> "\\}" '\\' -> "\\letterbackslash{}" '$' -> "\\$" '|' -> "\\letterbar{}" '%' -> "\\letterpercent{}" '~' -> "\\lettertilde{}" '#' -> "\\#" '[' -> "{[}" ']' -> "{]}" '\160' -> "~" '\x2014' | ligatures -> "---" '\x2013' | ligatures -> "--" '\x2019' | ligatures -> "'" '\x2026' -> "\\ldots{}" x -> [x] -- | Escape string for ConTeXt stringToConTeXt :: WriterOptions -> String -> String stringToConTeXt opts = concatMap (escapeCharForConTeXt opts) -- | Convert Elements to ConTeXt elementToConTeXt :: WriterOptions -> Element -> State WriterState Doc elementToConTeXt _ (Blk block) = blockToConTeXt block elementToConTeXt opts (Sec level _ attr title' elements) = do header' <- sectionHeader attr level title' innerContents <- mapM (elementToConTeXt opts) elements return $ vcat (header' : innerContents) -- | Convert Pandoc block element to ConTeXt. blockToConTeXt :: Block -> State WriterState Doc blockToConTeXt Null = return empty 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" <> braces capt <> braces ("\\externalfigure" <> brackets (text src)) <> blankline blockToConTeXt (Para lst) = do contents <- inlineListToConTeXt lst return $ contents <> blankline blockToConTeXt (BlockQuote lst) = do contents <- blockListToConTeXt lst return $ "\\startblockquote" $$ nest 0 contents $$ "\\stopblockquote" <> blankline blockToConTeXt (CodeBlock _ str) = return $ flush ("\\starttyping" <> cr <> text str <> cr <> "\\stoptyping") $$ blankline -- blankline because \stoptyping can't have anything after it, inc. '}' blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline blockToConTeXt (RawBlock _ _ ) = return empty blockToConTeXt (Div _ bs) = blockListToConTeXt bs blockToConTeXt (BulletList lst) = do contents <- mapM listItemToConTeXt lst return $ ("\\startitemize" <> if isTightList lst then brackets "packed" else empty) $$ vcat contents $$ text "\\stopitemize" <> blankline blockToConTeXt (OrderedList (start, style', delim) lst) = do st <- get let level = stOrderedListLevel st put $ st {stOrderedListLevel = level + 1} contents <- mapM listItemToConTeXt lst put $ st {stOrderedListLevel = level} let start' = if start == 1 then "" else "start=" ++ show start let delim' = case delim of DefaultDelim -> "" Period -> "stopper=." OneParen -> "stopper=)" TwoParens -> "left=(,stopper=)" let width = maximum $ map length $ take (length contents) (orderedListMarkers (start, style', delim)) let width' = (toEnum width + 1) / 2 let width'' = if width' > (1.5 :: Double) then "width=" ++ show width' ++ "em" else "" let specs2Items = filter (not . null) [start', delim', width''] let specs2 = if null specs2Items then "" else "[" ++ intercalate "," specs2Items ++ "]" let style'' = '[': (case style' of DefaultStyle -> orderedListStyles !! level Decimal -> 'n' Example -> 'n' LowerRoman -> 'r' UpperRoman -> 'R' LowerAlpha -> 'a' UpperAlpha -> 'A') : if isTightList lst then ",packed]" else "]" let specs = style'' ++ specs2 return $ "\\startitemize" <> text specs $$ vcat contents $$ "\\stopitemize" <> blankline blockToConTeXt (DefinitionList lst) = liftM vcat $ mapM defListItemToConTeXt lst blockToConTeXt HorizontalRule = return $ "\\thinrule" <> blankline -- If this is ever executed, provide a default for the reference identifier. blockToConTeXt (Header level attr lst) = sectionHeader attr level lst blockToConTeXt (Table caption aligns widths heads rows) = do let colDescriptor colWidth alignment = (case alignment of AlignLeft -> 'l' AlignRight -> 'r' AlignCenter -> 'c' AlignDefault -> 'l'): if colWidth == 0 then "|" else ("p(" ++ printf "%.2f" colWidth ++ "\\textwidth)|") let colDescriptors = "|" ++ (concat $ zipWith colDescriptor widths aligns) headers <- if all null heads then return empty else liftM ($$ "\\HL") $ tableRowToConTeXt heads captionText <- inlineListToConTeXt caption rows' <- mapM tableRowToConTeXt rows return $ "\\placetable" <> (if null caption then brackets "none" else empty) <> braces captionText $$ "\\starttable" <> brackets (text colDescriptors) $$ "\\HL" $$ headers $$ vcat rows' $$ "\\HL" $$ "\\stoptable" <> blankline tableRowToConTeXt :: [[Block]] -> State WriterState Doc tableRowToConTeXt cols = do cols' <- mapM blockListToConTeXt cols return $ (vcat (map ("\\NC " <>) cols')) $$ "\\NC\\AR" listItemToConTeXt :: [Block] -> State WriterState Doc listItemToConTeXt list = blockListToConTeXt list >>= return . ("\\item" $$) . (nest 2) defListItemToConTeXt :: ([Inline], [[Block]]) -> State WriterState Doc defListItemToConTeXt (term, defs) = do term' <- inlineListToConTeXt term def' <- liftM vsep $ mapM blockListToConTeXt defs return $ "\\startdescription" <> braces term' $$ nest 2 def' $$ "\\stopdescription" <> blankline -- | Convert list of block elements to ConTeXt. blockListToConTeXt :: [Block] -> State WriterState Doc blockListToConTeXt lst = liftM vcat $ mapM blockToConTeXt lst -- | Convert list of inline elements to ConTeXt. inlineListToConTeXt :: [Inline] -- ^ Inlines to convert -> State WriterState Doc inlineListToConTeXt lst = liftM hcat $ mapM inlineToConTeXt lst -- | Convert inline element to ConTeXt inlineToConTeXt :: Inline -- ^ Inline to convert -> State WriterState Doc inlineToConTeXt (Emph lst) = do contents <- inlineListToConTeXt lst return $ braces $ "\\em " <> contents inlineToConTeXt (Strong lst) = do contents <- inlineListToConTeXt lst return $ braces $ "\\bf " <> contents inlineToConTeXt (Strikeout lst) = do contents <- inlineListToConTeXt lst return $ "\\overstrikes" <> braces contents inlineToConTeXt (Superscript lst) = do contents <- inlineListToConTeXt lst return $ "\\high" <> braces contents inlineToConTeXt (Subscript lst) = do contents <- inlineListToConTeXt lst return $ "\\low" <> braces contents inlineToConTeXt (SmallCaps lst) = do contents <- inlineListToConTeXt lst return $ braces $ "\\sc " <> contents inlineToConTeXt (Code _ str) | not ('{' `elem` str || '}' `elem` str) = return $ "\\type" <> braces (text str) inlineToConTeXt (Code _ str) = do opts <- gets stOptions return $ "\\mono" <> braces (text $ stringToConTeXt opts str) inlineToConTeXt (Quoted SingleQuote lst) = do contents <- inlineListToConTeXt lst return $ "\\quote" <> braces contents inlineToConTeXt (Quoted DoubleQuote lst) = do contents <- inlineListToConTeXt lst return $ "\\quotation" <> braces contents inlineToConTeXt (Cite _ lst) = inlineListToConTeXt lst inlineToConTeXt (Str str) = do opts <- gets stOptions return $ text $ stringToConTeXt opts str inlineToConTeXt (Math InlineMath str) = return $ char '$' <> text str <> char '$' inlineToConTeXt (Math DisplayMath str) = return $ text "\\startformula " <> text str <> text " \\stopformula" <> space inlineToConTeXt (RawInline "context" str) = return $ text str inlineToConTeXt (RawInline "tex" str) = return $ text str inlineToConTeXt (RawInline _ _) = return empty inlineToConTeXt (LineBreak) = return $ text "\\crlf" <> cr inlineToConTeXt Space = return space -- autolink inlineToConTeXt (Link [Str str] (src, tit)) | if "mailto:" `isPrefixOf` src then src == escapeURI ("mailto:" ++ str) else src == escapeURI str = inlineToConTeXt (Link [RawInline "context" "\\hyphenatedurl{", Str str, RawInline "context" "}"] (src, tit)) -- Handle HTML-like internal document references to sections inlineToConTeXt (Link txt (('#' : ref), _)) = do opts <- gets stOptions label <- inlineListToConTeXt txt return $ text "\\in" <> braces (if writerNumberSections opts then label <+> text "(\\S" else label) -- prefix <> braces (if writerNumberSections opts then text ")" else empty) -- suffix <> brackets (text ref) inlineToConTeXt (Link txt (src, _)) = do st <- get let next = stNextRef st put $ st {stNextRef = next + 1} let ref = "url" ++ show next label <- inlineListToConTeXt txt return $ "\\useURL" <> brackets (text ref) <> brackets (text $ escapeStringUsing [('#',"\\#"),('%',"\\%")] src) <> brackets empty <> brackets label <> "\\from" <> brackets (text ref) inlineToConTeXt (Image _ (src, _)) = do let src' = if isURI src then src else unEscapeString src return $ braces $ "\\externalfigure" <> brackets (text src') inlineToConTeXt (Note contents) = do contents' <- blockListToConTeXt contents let codeBlock x@(CodeBlock _ _) = [x] codeBlock _ = [] let codeBlocks = query codeBlock contents return $ if null codeBlocks then text "\\footnote{" <> nest 2 contents' <> char '}' else text "\\startbuffer " <> nest 2 contents' <> text "\\stopbuffer\\footnote{\\getbuffer}" inlineToConTeXt (Span _ ils) = inlineListToConTeXt ils -- | Craft the section header, inserting the secton reference, if supplied. sectionHeader :: Attr -> Int -> [Inline] -> State WriterState Doc sectionHeader (ident,classes,_) hdrLevel lst = do contents <- inlineListToConTeXt lst st <- get let opts = stOptions st let level' = if writerChapters opts then hdrLevel - 1 else hdrLevel let (section, chapter) = if "unnumbered" `elem` classes then (text "subject", text "title") else (text "section", text "chapter") return $ if level' >= 1 && level' <= 5 then char '\\' <> text (concat (replicate (level' - 1) "sub")) <> section <> (if (not . null) ident then brackets (text ident) else empty) <> braces contents <> blankline else if level' == 0 then char '\\' <> chapter <> braces contents else contents <> blankline pandoc-1.12.2.1/src/Text/Pandoc/Writers/Custom.hs000644 000765 000024 00000020512 12251233602 021300 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverlappingInstances, FlexibleInstances, OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {- Copyright (C) 2012 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Custom Copyright : Copyright (C) 2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of 'Pandoc' documents to custom markup using a lua writer. -} module Text.Pandoc.Writers.Custom ( writeCustom ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Data.List ( intersperse ) import Data.Char ( toLower ) import Scripting.Lua (LuaState, StackValue, callfunc) import qualified Scripting.Lua as Lua import Text.Pandoc.UTF8 (fromString, toString) import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as C8 import Data.Monoid import qualified Data.Map as M attrToMap :: Attr -> M.Map ByteString ByteString attrToMap (id',classes,keyvals) = M.fromList $ ("id", fromString id') : ("class", fromString $ unwords classes) : map (\(x,y) -> (fromString x, fromString y)) keyvals getList :: StackValue a => LuaState -> Int -> IO [a] getList lua i' = do continue <- Lua.next lua i' if continue then do next <- Lua.peek lua (-1) Lua.pop lua 1 x <- maybe (fail "peek returned Nothing") return next rest <- getList lua i' return (x : rest) else return [] instance StackValue ByteString where push l x = Lua.push l $ C8.unpack x peek l n = (fmap . fmap) C8.pack (Lua.peek l n) valuetype _ = Lua.TSTRING instance StackValue a => StackValue [a] where push lua xs = do Lua.createtable lua (length xs + 1) 0 let addValue (i, x) = Lua.push lua x >> Lua.rawseti lua (-2) i mapM_ addValue $ zip [1..] xs peek lua i = do top <- Lua.gettop lua let i' = if i < 0 then top + i + 1 else i Lua.pushnil lua lst <- getList lua i' Lua.pop lua 1 return (Just lst) valuetype _ = Lua.TTABLE instance StackValue Format where push lua (Format f) = Lua.push lua (map toLower f) peek l n = fmap Format `fmap` Lua.peek l n valuetype _ = Lua.TSTRING instance (StackValue a, StackValue b) => StackValue (M.Map a b) where push lua m = do let xs = M.toList m Lua.createtable lua (length xs + 1) 0 let addValue (k, v) = Lua.push lua k >> Lua.push lua v >> Lua.rawset lua (-3) mapM_ addValue xs peek _ _ = undefined -- not needed for our purposes valuetype _ = Lua.TTABLE instance (StackValue a, StackValue b) => StackValue (a,b) where push lua (k,v) = do Lua.createtable lua 2 0 Lua.push lua k Lua.push lua v Lua.rawset lua (-3) peek _ _ = undefined -- not needed for our purposes valuetype _ = Lua.TTABLE instance StackValue [Inline] where push l ils = Lua.push l . C8.unpack =<< inlineListToCustom l ils peek _ _ = undefined valuetype _ = Lua.TSTRING instance StackValue [Block] where push l ils = Lua.push l . C8.unpack =<< blockListToCustom l ils peek _ _ = undefined valuetype _ = Lua.TSTRING instance StackValue MetaValue where push l (MetaMap m) = Lua.push l m push l (MetaList xs) = Lua.push l xs push l (MetaBool x) = Lua.push l x push l (MetaString s) = Lua.push l s push l (MetaInlines ils) = Lua.push l ils push l (MetaBlocks bs) = Lua.push l bs peek _ _ = undefined valuetype (MetaMap _) = Lua.TTABLE valuetype (MetaList _) = Lua.TTABLE valuetype (MetaBool _) = Lua.TBOOLEAN valuetype (MetaString _) = Lua.TSTRING valuetype (MetaInlines _) = Lua.TSTRING valuetype (MetaBlocks _) = Lua.TSTRING -- | Convert Pandoc to custom markup. writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO String writeCustom luaFile opts doc = do luaScript <- readFile luaFile lua <- Lua.newstate Lua.openlibs lua Lua.loadstring lua luaScript "custom" Lua.call lua 0 0 -- TODO - call hierarchicalize, so we have that info rendered <- docToCustom lua opts doc Lua.close lua return $ toString rendered docToCustom :: LuaState -> WriterOptions -> Pandoc -> IO ByteString docToCustom lua opts (Pandoc (Meta metamap) blocks) = do body <- blockListToCustom lua blocks callfunc lua "Doc" body metamap (writerVariables opts) -- | Convert Pandoc block element to Custom. blockToCustom :: LuaState -- ^ Lua state -> Block -- ^ Block element -> IO ByteString blockToCustom _ Null = return "" blockToCustom lua (Plain inlines) = callfunc lua "Plain" inlines blockToCustom lua (Para [Image txt (src,tit)]) = callfunc lua "CaptionedImage" src tit txt blockToCustom lua (Para inlines) = callfunc lua "Para" inlines blockToCustom lua (RawBlock format str) = callfunc lua "RawBlock" format (fromString str) blockToCustom lua HorizontalRule = callfunc lua "HorizontalRule" blockToCustom lua (Header level attr inlines) = callfunc lua "Header" level inlines (attrToMap attr) blockToCustom lua (CodeBlock attr str) = callfunc lua "CodeBlock" (fromString str) (attrToMap attr) blockToCustom lua (BlockQuote blocks) = callfunc lua "BlockQuote" blocks blockToCustom lua (Table capt aligns widths headers rows') = callfunc lua "Table" capt (map show aligns) widths headers rows' blockToCustom lua (BulletList items) = callfunc lua "BulletList" items blockToCustom lua (OrderedList (num,sty,delim) items) = callfunc lua "OrderedList" items num (show sty) (show delim) blockToCustom lua (DefinitionList items) = callfunc lua "DefinitionList" items blockToCustom lua (Div attr items) = callfunc lua "Div" items (attrToMap attr) -- | Convert list of Pandoc block elements to Custom. blockListToCustom :: LuaState -- ^ Options -> [Block] -- ^ List of block elements -> IO ByteString blockListToCustom lua xs = do blocksep <- callfunc lua "Blocksep" bs <- mapM (blockToCustom lua) xs return $ mconcat $ intersperse blocksep bs -- | Convert list of Pandoc inline elements to Custom. inlineListToCustom :: LuaState -> [Inline] -> IO ByteString inlineListToCustom lua lst = do xs <- mapM (inlineToCustom lua) lst return $ C8.concat xs -- | Convert Pandoc inline element to Custom. inlineToCustom :: LuaState -> Inline -> IO ByteString inlineToCustom lua (Str str) = callfunc lua "Str" $ fromString str inlineToCustom lua Space = callfunc lua "Space" inlineToCustom lua (Emph lst) = callfunc lua "Emph" lst inlineToCustom lua (Strong lst) = callfunc lua "Strong" lst inlineToCustom lua (Strikeout lst) = callfunc lua "Strikeout" lst inlineToCustom lua (Superscript lst) = callfunc lua "Superscript" lst inlineToCustom lua (Subscript lst) = callfunc lua "Subscript" lst inlineToCustom lua (SmallCaps lst) = callfunc lua "SmallCaps" lst inlineToCustom lua (Quoted SingleQuote lst) = callfunc lua "SingleQuoted" lst inlineToCustom lua (Quoted DoubleQuote lst) = callfunc lua "DoubleQuoted" lst inlineToCustom lua (Cite _ lst) = callfunc lua "Cite" lst inlineToCustom lua (Code attr str) = callfunc lua "Code" (fromString str) (attrToMap attr) inlineToCustom lua (Math DisplayMath str) = callfunc lua "DisplayMath" (fromString str) inlineToCustom lua (Math InlineMath str) = callfunc lua "InlineMath" (fromString str) inlineToCustom lua (RawInline format str) = callfunc lua "RawInline" format (fromString str) inlineToCustom lua (LineBreak) = callfunc lua "LineBreak" inlineToCustom lua (Link txt (src,tit)) = callfunc lua "Link" txt (fromString src) (fromString tit) inlineToCustom lua (Image alt (src,tit)) = callfunc lua "Image" alt (fromString src) (fromString tit) inlineToCustom lua (Note contents) = callfunc lua "Note" contents inlineToCustom lua (Span attr items) = callfunc lua "Span" items (attrToMap attr) pandoc-1.12.2.1/src/Text/Pandoc/Writers/Docbook.hs000644 000765 000024 00000034543 12251233602 021417 0ustar00jgmstaff000000 000000 {-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2006-2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Docbook Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of 'Pandoc' documents to Docbook XML. -} module Text.Pandoc.Writers.Docbook ( writeDocbook) where import Text.Pandoc.Definition import Text.Pandoc.XML import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Readers.TeXMath import Data.List ( isPrefixOf, intercalate, isSuffixOf ) import Data.Char ( toLower ) import Text.Pandoc.Highlighting ( languages, languagesByExtension ) import Text.Pandoc.Pretty import qualified Text.Pandoc.Builder as B import Text.TeXMath import qualified Text.XML.Light as Xml import Data.Generics (everywhere, mkT) -- | Convert list of authors to a docbook section authorToDocbook :: WriterOptions -> [Inline] -> B.Inlines authorToDocbook opts name' = let name = render Nothing $ inlinesToDocbook opts name' colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing in B.rawInline "docbook" $ render colwidth $ if ',' `elem` name then -- last name first let (lastname, rest) = break (==',') name firstname = triml rest in inTagsSimple "firstname" (text $ escapeStringForXML firstname) <> inTagsSimple "surname" (text $ escapeStringForXML lastname) else -- last name last let namewords = words name lengthname = length namewords (firstname, lastname) = case lengthname of 0 -> ("","") 1 -> ("", name) n -> (intercalate " " (take (n-1) namewords), last namewords) in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$ inTagsSimple "surname" (text $ escapeStringForXML lastname) -- | Convert Pandoc document to string in Docbook format. writeDocbook :: WriterOptions -> Pandoc -> String writeDocbook opts (Pandoc meta blocks) = let elements = hierarchicalize blocks colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing render' = render colwidth opts' = if "/book>" `isSuffixOf` (trimr $ writerTemplate opts) then opts{ writerChapters = True } else opts startLvl = if writerChapters opts' then 0 else 1 auths' = map (authorToDocbook opts) $ docAuthors meta meta' = B.setMeta "author" auths' meta Just metadata = metaToJSON 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 $ defField "mathml" (case writerHTMLMathMethod opts of MathML _ -> True _ -> False) $ metadata in if writerStandalone opts then renderTemplate' (writerTemplate opts) context else main -- | Convert an Element to Docbook. elementToDocbook :: WriterOptions -> Int -> Element -> Doc elementToDocbook opts _ (Blk block) = blockToDocbook opts block elementToDocbook opts lvl (Sec _ _num (id',_,_) title elements) = -- Docbook doesn't allow sections with no content, so insert some if needed let elements' = if null elements then [Blk (Para [])] else elements tag = case lvl of n | n == 0 -> "chapter" | n >= 1 && n <= 5 -> "sect" ++ show n | otherwise -> "simplesect" in inTags True tag [("id", writerIdentifierPrefix opts ++ id')] $ inTagsSimple "title" (inlinesToDocbook opts title) $$ vcat (map (elementToDocbook opts (lvl + 1)) elements') -- | Convert a list of Pandoc blocks to Docbook. blocksToDocbook :: WriterOptions -> [Block] -> Doc blocksToDocbook opts = vcat . map (blockToDocbook opts) -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block plainToPara (Plain x) = Para x plainToPara x = x -- | Convert a list of pairs of terms and definitions into a list of -- Docbook varlistentrys. deflistItemsToDocbook :: WriterOptions -> [([Inline],[[Block]])] -> Doc deflistItemsToDocbook opts items = vcat $ map (\(term, defs) -> deflistItemToDocbook opts term defs) items -- | Convert a term and a list of blocks into a Docbook varlistentry. deflistItemToDocbook :: WriterOptions -> [Inline] -> [[Block]] -> Doc deflistItemToDocbook opts term defs = let def' = concatMap (map plainToPara) defs in inTagsIndented "varlistentry" $ inTagsIndented "term" (inlinesToDocbook opts term) $$ inTagsIndented "listitem" (blocksToDocbook opts def') -- | Convert a list of lists of blocks to a list of Docbook list items. listItemsToDocbook :: WriterOptions -> [[Block]] -> Doc listItemsToDocbook opts items = vcat $ map (listItemToDocbook opts) items -- | Convert a list of blocks into a Docbook list item. listItemToDocbook :: WriterOptions -> [Block] -> Doc listItemToDocbook opts item = inTagsIndented "listitem" $ blocksToDocbook opts $ map plainToPara item -- | Convert a Pandoc block element to Docbook. blockToDocbook :: WriterOptions -> Block -> Doc blockToDocbook _ Null = empty blockToDocbook opts (Div _ bs) = blocksToDocbook opts $ map plainToPara bs blockToDocbook _ (Header _ _ _) = empty -- should not occur after hierarchicalize blockToDocbook opts (Plain lst) = inlinesToDocbook opts lst -- title beginning with fig: indicates that the image is a figure blockToDocbook opts (Para [Image txt (src,'f':'i':'g':':':_)]) = let alt = inlinesToDocbook opts txt capt = if null txt then empty else inTagsSimple "title" alt in inTagsIndented "figure" $ capt $$ (inTagsIndented "mediaobject" $ (inTagsIndented "imageobject" (selfClosingTag "imagedata" [("fileref",src)])) $$ inTagsSimple "textobject" (inTagsSimple "phrase" alt)) blockToDocbook opts (Para lst) = inTagsIndented "para" $ inlinesToDocbook opts lst blockToDocbook opts (BlockQuote blocks) = inTagsIndented "blockquote" $ blocksToDocbook opts blocks blockToDocbook _ (CodeBlock (_,classes,_) str) = text ("") <> cr <> flush (text (escapeStringForXML str) <> cr <> text "") where lang = if null langs then "" else " language=\"" ++ escapeStringForXML (head langs) ++ "\"" isLang l = map toLower l `elem` map (map toLower) languages langsFrom s = if isLang s then [s] else languagesByExtension . map toLower $ s langs = concatMap langsFrom classes blockToDocbook opts (BulletList lst) = inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst blockToDocbook _ (OrderedList _ []) = empty blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) = let attribs = case numstyle of DefaultStyle -> [] Decimal -> [("numeration", "arabic")] Example -> [("numeration", "arabic")] UpperAlpha -> [("numeration", "upperalpha")] LowerAlpha -> [("numeration", "loweralpha")] UpperRoman -> [("numeration", "upperroman")] LowerRoman -> [("numeration", "lowerroman")] items = if start == 1 then listItemsToDocbook opts (first:rest) else (inTags True "listitem" [("override",show start)] (blocksToDocbook opts $ map plainToPara first)) $$ listItemsToDocbook opts rest in inTags True "orderedlist" attribs items blockToDocbook opts (DefinitionList lst) = inTagsIndented "variablelist" $ deflistItemsToDocbook opts lst blockToDocbook _ (RawBlock f str) | f == "docbook" = text str -- raw XML block | f == "html" = text str -- allow html for backwards compatibility | otherwise = empty blockToDocbook _ HorizontalRule = empty -- not semantic blockToDocbook opts (Table caption aligns widths headers rows) = let captionDoc = if null caption then empty else inTagsIndented "title" (inlinesToDocbook opts caption) tableType = if isEmpty captionDoc then "informaltable" else "table" percent w = show (truncate (100*w) :: Integer) ++ "*" coltags = vcat $ zipWith (\w al -> selfClosingTag "colspec" ([("colwidth", percent w) | w > 0] ++ [("align", alignmentToString al)])) widths aligns head' = if all null headers then empty else inTagsIndented "thead" $ tableRowToDocbook opts headers body' = inTagsIndented "tbody" $ vcat $ map (tableRowToDocbook opts) rows in inTagsIndented tableType $ captionDoc $$ (inTags True "tgroup" [("cols", show (length headers))] $ coltags $$ head' $$ body') alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center" AlignDefault -> "left" tableRowToDocbook :: WriterOptions -> [[Block]] -> Doc tableRowToDocbook opts cols = inTagsIndented "row" $ vcat $ map (tableItemToDocbook opts) cols tableItemToDocbook :: WriterOptions -> [Block] -> Doc tableItemToDocbook opts item = inTags True "entry" [] $ vcat $ map (blockToDocbook opts) item -- | Convert a list of inline elements to Docbook. inlinesToDocbook :: WriterOptions -> [Inline] -> Doc inlinesToDocbook opts lst = hcat $ map (inlineToDocbook opts) lst -- | Convert an inline element to Docbook. inlineToDocbook :: WriterOptions -> Inline -> Doc inlineToDocbook _ (Str str) = text $ escapeStringForXML str inlineToDocbook opts (Emph lst) = inTagsSimple "emphasis" $ inlinesToDocbook opts lst inlineToDocbook opts (Strong lst) = inTags False "emphasis" [("role", "strong")] $ inlinesToDocbook opts lst inlineToDocbook opts (Strikeout lst) = inTags False "emphasis" [("role", "strikethrough")] $ inlinesToDocbook opts lst inlineToDocbook opts (Superscript lst) = inTagsSimple "superscript" $ inlinesToDocbook opts lst inlineToDocbook opts (Subscript lst) = inTagsSimple "subscript" $ inlinesToDocbook opts lst inlineToDocbook opts (SmallCaps lst) = inTags False "emphasis" [("role", "smallcaps")] $ inlinesToDocbook opts lst inlineToDocbook opts (Quoted _ lst) = inTagsSimple "quote" $ inlinesToDocbook opts lst inlineToDocbook opts (Cite _ lst) = inlinesToDocbook opts lst inlineToDocbook opts (Span _ ils) = inlinesToDocbook opts ils inlineToDocbook _ (Code _ str) = inTagsSimple "literal" $ text (escapeStringForXML str) inlineToDocbook opts (Math t str) | isMathML (writerHTMLMathMethod opts) = case texMathToMathML dt str of Right r -> inTagsSimple tagtype $ text $ Xml.ppcElement conf $ fixNS $ removeAttr r Left _ -> inlinesToDocbook opts $ readTeXMath' t str | otherwise = inlinesToDocbook opts $ readTeXMath' t str where (dt, tagtype) = case t of InlineMath -> (DisplayInline,"inlineequation") DisplayMath -> (DisplayBlock,"informalequation") conf = Xml.useShortEmptyTags (const False) Xml.defaultConfigPP removeAttr e = e{ Xml.elAttribs = [] } fixNS' qname = qname{ Xml.qPrefix = Just "mml" } fixNS = everywhere (mkT fixNS') inlineToDocbook _ (RawInline f x) | f == "html" || f == "docbook" = text x | otherwise = empty inlineToDocbook _ LineBreak = flush $ inTagsSimple "literallayout" (text "\n") inlineToDocbook _ Space = space inlineToDocbook opts (Link txt (src, _)) = if isPrefixOf "mailto:" src then let src' = drop 7 src emailLink = inTagsSimple "email" $ text $ escapeStringForXML $ src' in case txt of [Str s] | escapeURI s == src' -> emailLink _ -> inlinesToDocbook opts txt <+> char '(' <> emailLink <> char ')' else (if isPrefixOf "#" src then inTags False "link" [("linkend", drop 1 src)] else inTags False "ulink" [("url", src)]) $ inlinesToDocbook opts txt inlineToDocbook _ (Image _ (src, tit)) = let titleDoc = if null tit then empty else inTagsIndented "objectinfo" $ inTagsIndented "title" (text $ escapeStringForXML tit) in inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $ titleDoc $$ selfClosingTag "imagedata" [("fileref", src)] inlineToDocbook opts (Note contents) = inTagsIndented "footnote" $ blocksToDocbook opts contents isMathML :: HTMLMathMethod -> Bool isMathML (MathML _) = True isMathML _ = False pandoc-1.12.2.1/src/Text/Pandoc/Writers/Docx.hs000644 000765 000024 00000114377 12251233602 020740 0ustar00jgmstaff000000 000000 {-# LANGUAGE ScopedTypeVariables #-} {- Copyright (C) 2012 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Docx Copyright : Copyright (C) 2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of 'Pandoc' documents to docx. -} module Text.Pandoc.Writers.Docx ( writeDocx ) where import Data.List ( intercalate, groupBy ) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BL8 import qualified Data.Map as M import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Compat.Monoid ((<>)) import Codec.Archive.Zip import Data.Time.Clock.POSIX import Text.Pandoc.Definition import Text.Pandoc.Generic import Text.Pandoc.ImageSize import Text.Pandoc.Shared hiding (Element) import Text.Pandoc.Options import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Highlighting ( highlight ) import Text.Pandoc.Walk import Text.Highlighting.Kate.Types () import Text.XML.Light import Text.TeXMath import Control.Monad.State import Text.Highlighting.Kate import Data.Unique (hashUnique, newUnique) import System.Random (randomRIO) import Text.Printf (printf) import qualified Control.Exception as E import Text.Pandoc.MIME (getMimeType, extensionFromMimeType) import Control.Applicative ((<|>)) data WriterState = WriterState{ stTextProperties :: [Element] , stParaProperties :: [Element] , stFootnotes :: [Element] , stSectionIds :: [String] , stExternalLinks :: M.Map String String , stImages :: M.Map FilePath (String, String, Maybe String, Element, B.ByteString) , stListLevel :: Int , stListNumId :: Int , stNumStyles :: M.Map ListMarker Int , stLists :: [ListMarker] } data ListMarker = NoMarker | BulletMarker | NumberMarker ListNumberStyle ListNumberDelim Int deriving (Show, Read, Eq, Ord) defaultWriterState :: WriterState defaultWriterState = WriterState{ stTextProperties = [] , stParaProperties = [] , stFootnotes = [] , stSectionIds = [] , stExternalLinks = M.empty , stImages = M.empty , stListLevel = -1 , stListNumId = 1 , stNumStyles = M.fromList [(NoMarker, 0)] , stLists = [NoMarker] } type WS a = StateT WriterState IO a mknode :: Node t => String -> [(String,String)] -> t -> Element mknode s attrs = add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) . node (unqual s) toLazy :: B.ByteString -> BL.ByteString toLazy = BL.fromChunks . (:[]) renderXml :: Element -> BL.ByteString renderXml elt = BL8.pack "\n" <> UTF8.fromStringLazy (showElement elt) -- | Produce an Docx file from a Pandoc document. writeDocx :: WriterOptions -- ^ Writer options -> Pandoc -- ^ Document to convert -> IO BL.ByteString writeDocx opts doc@(Pandoc meta _) = do let datadir = writerUserDataDir opts let doc' = walk fixDisplayMath doc refArchive <- liftM (toArchive . toLazy) $ case writerReferenceDocx opts of Just f -> B.readFile f Nothing -> readDataFile datadir "reference.docx" ((contents, footnotes), st) <- runStateT (writeOpenXML opts{writerWrapText = False} doc') defaultWriterState epochtime <- floor `fmap` getPOSIXTime let imgs = M.elems $ stImages st -- we create [Content_Types].xml and word/_rels/document.xml.rels -- from scratch rather than reading from reference.docx, -- because Word sometimes changes these files when a reference.docx is modified, -- e.g. deleting the reference to footnotes.xml or removing default entries -- for image content types. -- [Content_Types].xml let mkOverrideNode (part', contentType') = mknode "Override" [("PartName",part'),("ContentType",contentType')] () let mkImageOverride (_, imgpath, mbMimeType, _, _) = mkOverrideNode ("/word/" ++ imgpath, maybe "application/octet-stream" id mbMimeType) let overrides = map mkOverrideNode [("/word/webSettings.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml") ,("/word/numbering.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml") ,("/word/settings.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml") ,("/word/theme/theme1.xml", "application/vnd.openxmlformats-officedocument.theme+xml") ,("/word/fontTable.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml") ,("/docProps/app.xml", "application/vnd.openxmlformats-officedocument.extended-properties+xml") ,("/docProps/core.xml", "application/vnd.openxmlformats-package.core-properties+xml") ,("/word/styles.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml") ,("/word/document.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml") ,("/word/footnotes.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml") ] ++ map mkImageOverride imgs let defaultnodes = [mknode "Default" [("Extension","xml"),("ContentType","application/xml")] (), mknode "Default" [("Extension","rels"),("ContentType","application/vnd.openxmlformats-package.relationships+xml")] ()] let contentTypesDoc = mknode "Types" [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")] $ defaultnodes ++ overrides let contentTypesEntry = toEntry "[Content_Types].xml" epochtime $ renderXml contentTypesDoc -- word/_rels/document.xml.rels let toBaseRel (url', id', target') = mknode "Relationship" [("Type",url') ,("Id",id') ,("Target",target')] () let baserels = map toBaseRel [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", "rId1", "numbering.xml") ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", "rId2", "styles.xml") ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings", "rId3", "settings.xml") ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings", "rId4", "webSettings.xml") ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", "rId5", "fontTable.xml") ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "rId6", "theme/theme1.xml") ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", "rId7", "footnotes.xml")] let toImgRel (ident,path,_,_,_) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",ident),("Target",path)] () let imgrels = map toImgRel imgs let toLinkRel (src,ident) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] () let linkrels = map toLinkRel $ M.toList $ stExternalLinks st let reldoc = mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ baserels ++ imgrels ++ linkrels let relEntry = toEntry "word/_rels/document.xml.rels" epochtime $ renderXml reldoc -- create entries for images in word/media/... let toImageEntry (_,path,_,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img let imageEntries = map toImageEntry imgs -- word/document.xml let contentEntry = toEntry "word/document.xml" epochtime $ renderXml contents -- footnotes let footnotesEntry = toEntry "word/footnotes.xml" epochtime $ renderXml footnotes -- footnote rels let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime $ renderXml $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ linkrels -- styles let newstyles = styleToOpenXml $ writerHighlightStyle opts let stylepath = "word/styles.xml" styledoc <- parseXml refArchive stylepath let styledoc' = styledoc{ elContent = elContent styledoc ++ [Elem x | x <- newstyles, writerHighlight opts] } let styleEntry = toEntry stylepath epochtime $ renderXml styledoc' -- construct word/numbering.xml let numpath = "word/numbering.xml" numEntry <- (toEntry numpath epochtime . renderXml) `fmap` mkNumbering (stNumStyles st) (stLists st) let docPropsPath = "docProps/core.xml" let docProps = mknode "cp:coreProperties" [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties") ,("xmlns:dc","http://purl.org/dc/elements/1.1/") ,("xmlns:dcterms","http://purl.org/dc/terms/") ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/") ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")] $ mknode "dc:title" [] (stringify $ docTitle 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" let rels = mknode "Relationships" [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")] $ map (\attrs -> mknode "Relationship" attrs ()) [ [("Id","rId1") ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") ,("Target","word/document.xml")] , [("Id","rId4") ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties") ,("Target","docProps/app.xml")] , [("Id","rId3") ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties") ,("Target","docProps/core.xml")] ] let relsEntry = toEntry relsPath epochtime $ renderXml rels let entryFromArchive path = (toEntry path epochtime . renderXml) `fmap` parseXml refArchive path 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" -- Create archive let archive = foldr addEntryToArchive emptyArchive $ contentTypesEntry : relsEntry : contentEntry : relEntry : footnoteRelEntry : numEntry : styleEntry : footnotesEntry : docPropsEntry : docPropsAppEntry : themeEntry : fontTableEntry : settingsEntry : webSettingsEntry : imageEntries return $ fromArchive archive styleToOpenXml :: Style -> [Element] styleToOpenXml style = parStyle : map toStyle alltoktypes where alltoktypes = enumFromTo KeywordTok NormalTok toStyle toktype = mknode "w:style" [("w:type","character"), ("w:customStyle","1"),("w:styleId",show toktype)] [ mknode "w:name" [("w:val",show toktype)] () , mknode "w:basedOn" [("w:val","VerbatimChar")] () , mknode "w:rPr" [] $ [ mknode "w:color" [("w:val",tokCol toktype)] () | tokCol toktype /= "auto" ] ++ [ mknode "w:shd" [("w:val","clear"),("w:fill",tokBg toktype)] () | tokBg toktype /= "auto" ] ++ [ mknode "w:b" [] () | tokFeature tokenBold toktype ] ++ [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] ++ [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ] ] tokStyles = tokenStyles style tokFeature f toktype = maybe False f $ lookup toktype tokStyles tokCol toktype = maybe "auto" (drop 1 . fromColor) $ (tokenColor =<< lookup toktype tokStyles) `mplus` defaultColor style tokBg toktype = maybe "auto" (drop 1 . fromColor) $ (tokenBackground =<< lookup toktype tokStyles) `mplus` backgroundColor style parStyle = mknode "w:style" [("w:type","paragraph"), ("w:customStyle","1"),("w:styleId","SourceCode")] [ mknode "w:name" [("w:val","Source Code")] () , mknode "w:basedOn" [("w:val","Normal")] () , mknode "w:link" [("w:val","VerbatimChar")] () , mknode "w:pPr" [] $ mknode "w:wordWrap" [("w:val","off")] () : ( maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill",drop 1 $ fromColor col)] ()]) $ backgroundColor style ) ] mkNumbering :: M.Map ListMarker Int -> [ListMarker] -> IO Element mkNumbering markers lists = do elts <- mapM mkAbstractNum (M.toList markers) return $ mknode "w:numbering" [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")] $ elts ++ zipWith (mkNum markers) lists [1..(length lists)] mkNum :: M.Map ListMarker Int -> ListMarker -> Int -> Element mkNum markers marker numid = mknode "w:num" [("w:numId",show numid)] $ mknode "w:abstractNumId" [("w:val",show absnumid)] () : case marker of NoMarker -> [] BulletMarker -> [] 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 mkAbstractNum :: (ListMarker,Int) -> IO Element mkAbstractNum (marker,numid) = do nsid <- randomRIO (0x10000000 :: Integer, 0xFFFFFFFF :: Integer) return $ mknode "w:abstractNum" [("w:abstractNumId",show numid)] $ mknode "w:nsid" [("w:val", printf "%8x" nsid)] () : mknode "w:multiLevelType" [("w:val","multilevel")] () : map (mkLvl marker) [0..6] mkLvl :: ListMarker -> Int -> Element mkLvl marker lvl = mknode "w:lvl" [("w:ilvl",show lvl)] $ [ mknode "w:start" [("w:val",start)] () | marker /= NoMarker && marker /= BulletMarker ] ++ [ mknode "w:numFmt" [("w:val",fmt)] () , mknode "w:lvlText" [("w:val",lvltxt)] () , mknode "w:lvlJc" [("w:val","left")] () , mknode "w:pPr" [] [ mknode "w:tabs" [] $ mknode "w:tab" [("w:val","num"),("w:pos",show $ lvl * step)] () , mknode "w:ind" [("w:left",show $ lvl * step + hang),("w:hanging",show hang)] () ] ] where (fmt, lvltxt, start) = case marker of NoMarker -> ("bullet"," ","1") BulletMarker -> ("bullet",bulletFor lvl,"1") NumberMarker st de n -> (styleFor st lvl ,patternFor de ("%" ++ show (lvl + 1)) ,show n) step = 720 hang = 480 bulletFor 0 = "\x2022" -- filled circle bulletFor 1 = "\x2013" -- en dash bulletFor 2 = "\x2022" -- hyphen bullet bulletFor 3 = "\x2013" bulletFor 4 = "\x2022" bulletFor 5 = "\x2013" bulletFor _ = "\x2022" styleFor UpperAlpha _ = "upperLetter" styleFor LowerAlpha _ = "lowerLetter" styleFor UpperRoman _ = "upperRoman" styleFor LowerRoman _ = "lowerRoman" styleFor Decimal _ = "decimal" styleFor DefaultStyle 1 = "decimal" styleFor DefaultStyle 2 = "lowerLetter" styleFor DefaultStyle 3 = "lowerRoman" styleFor DefaultStyle 4 = "decimal" styleFor DefaultStyle 5 = "lowerLetter" styleFor DefaultStyle 6 = "lowerRoman" styleFor _ _ = "decimal" patternFor OneParen s = s ++ ")" patternFor TwoParens s = "(" ++ s ++ ")" patternFor _ s = s ++ "." getNumId :: WS Int getNumId = length `fmap` gets stLists -- | Convert Pandoc document to two OpenXML elements (the main document and footnotes). writeOpenXML :: WriterOptions -> Pandoc -> WS (Element, Element) writeOpenXML opts (Pandoc meta blocks) = do let tit = docTitle meta ++ case lookupMeta "subtitle" meta of Just (MetaBlocks [Plain xs]) -> LineBreak : xs _ -> [] let auths = docAuthors meta let dat = docDate meta title <- withParaProp (pStyle "Title") $ blocksToOpenXML opts [Para tit | not (null tit)] authors <- withParaProp (pStyle "Authors") $ blocksToOpenXML opts [Para (intercalate [LineBreak] auths) | not (null auths)] date <- withParaProp (pStyle "Date") $ blocksToOpenXML opts [Para dat | not (null dat)] let convertSpace (Str x : Space : Str y : xs) = Str (x ++ " " ++ y) : xs convertSpace (Str x : Str y : xs) = Str (x ++ y) : xs convertSpace xs = xs let blocks' = bottomUp convertSpace $ blocks doc' <- blocksToOpenXML opts blocks' notes' <- reverse `fmap` gets stFootnotes let meta' = title ++ authors ++ date let stdAttributes = [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main") ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math") ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships") ,("xmlns:o","urn:schemas-microsoft-com:office:office") ,("xmlns:v","urn:schemas-microsoft-com:vml") ,("xmlns:w10","urn:schemas-microsoft-com:office:word") ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main") ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture") ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")] let doc = mknode "w:document" stdAttributes $ mknode "w:body" [] (meta' ++ doc') let notes = mknode "w:footnotes" stdAttributes notes' return (doc, notes) -- | Convert a list of Pandoc blocks to OpenXML. blocksToOpenXML :: WriterOptions -> [Block] -> WS [Element] blocksToOpenXML opts bls = concat `fmap` mapM (blockToOpenXML opts) bls pStyle :: String -> Element pStyle sty = mknode "w:pStyle" [("w:val",sty)] () rStyle :: String -> Element rStyle sty = mknode "w:rStyle" [("w:val",sty)] () getUniqueId :: MonadIO m => m String -- the + 20 is to ensure that there are no clashes with the rIds -- already in word/document.xml.rel getUniqueId = liftIO $ (show . (+ 20) . hashUnique) `fmap` newUnique -- | Convert a Pandoc block element to OpenXML. blockToOpenXML :: WriterOptions -> Block -> WS [Element] blockToOpenXML _ Null = return [] blockToOpenXML opts (Div _ bs) = blocksToOpenXML opts bs blockToOpenXML opts (Header lev (ident,_,_) lst) = do contents <- withParaProp (pStyle $ "Heading" ++ show lev) $ blockToOpenXML opts (Para lst) usedIdents <- gets stSectionIds let bookmarkName = if null ident then uniqueIdent lst usedIdents else ident modify $ \s -> s{ stSectionIds = bookmarkName : stSectionIds s } id' <- getUniqueId let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id') ,("w:name",bookmarkName)] () let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] () return $ [bookmarkStart] ++ contents ++ [bookmarkEnd] blockToOpenXML opts (Plain lst) = withParaProp (pStyle "Compact") $ blockToOpenXML opts (Para lst) -- title beginning with fig: indicates that the image is a figure blockToOpenXML opts (Para [Image alt (src,'f':'i':'g':':':tit)]) = do paraProps <- getParaProps False contents <- inlinesToOpenXML opts [Image alt (src,tit)] captionNode <- withParaProp (pStyle "ImageCaption") $ blockToOpenXML opts (Para alt) return $ mknode "w:p" [] (paraProps ++ contents) : captionNode -- fixDisplayMath sometimes produces a Para [] as artifact blockToOpenXML _ (Para []) = return [] blockToOpenXML opts (Para lst) = do paraProps <- getParaProps $ case lst of [Math DisplayMath _] -> True _ -> False contents <- inlinesToOpenXML opts lst return [mknode "w:p" [] (paraProps ++ contents)] blockToOpenXML _ (RawBlock format str) | format == Format "openxml" = return [ x | Elem x <- parseXML str ] | otherwise = return [] blockToOpenXML opts (BlockQuote blocks) = withParaProp (pStyle "BlockQuote") $ blocksToOpenXML opts blocks blockToOpenXML opts (CodeBlock attrs str) = withParaProp (pStyle "SourceCode") $ blockToOpenXML opts $ Para [Code attrs str] blockToOpenXML _ HorizontalRule = return [ mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" [] $ mknode "v:rect" [("style","width:0;height:1.5pt"), ("o:hralign","center"), ("o:hrstd","t"),("o:hr","t")] () ] blockToOpenXML opts (Table caption aligns widths headers rows) = do let captionStr = stringify caption caption' <- if null caption then return [] else withParaProp (pStyle "TableCaption") $ blockToOpenXML opts (Para caption) let alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] () let cellToOpenXML (al, cell) = withParaProp (alignmentFor al) $ blocksToOpenXML opts cell headers' <- mapM cellToOpenXML $ zip aligns headers rows' <- mapM (\cells -> mapM cellToOpenXML $ zip aligns cells) $ rows let borderProps = mknode "w:tcPr" [] [ mknode "w:tcBorders" [] $ mknode "w:bottom" [("w:val","single")] () , mknode "w:vAlign" [("w:val","bottom")] () ] let mkcell border contents = mknode "w:tc" [] $ [ borderProps | border ] ++ if null contents then [mknode "w:p" [] ()] else contents let mkrow border cells = mknode "w:tr" [] $ map (mkcell border) cells let textwidth = 7920 -- 5.5 in in twips, 1/20 pt let mkgridcol w = mknode "w:gridCol" [("w:w", show $ (floor (textwidth * w) :: Integer))] () return $ [ mknode "w:tbl" [] ( mknode "w:tblPr" [] ( [ mknode "w:tblStyle" [("w:val","TableNormal")] () ] ++ [ mknode "w:tblCaption" [("w:val", captionStr)] () | not (null caption) ] ) : mknode "w:tblGrid" [] (if all (==0) widths then [] else map mkgridcol widths) : [ mkrow True headers' | not (all null headers) ] ++ map (mkrow False) rows' ) ] ++ caption' blockToOpenXML opts (BulletList lst) = do let marker = BulletMarker addList marker numid <- getNumId asList $ concat `fmap` mapM (listItemToOpenXML opts numid) lst blockToOpenXML opts (OrderedList (start, numstyle, numdelim) lst) = do let marker = NumberMarker numstyle numdelim start addList marker numid <- getNumId asList $ concat `fmap` mapM (listItemToOpenXML opts numid) lst blockToOpenXML opts (DefinitionList items) = concat `fmap` mapM (definitionListItemToOpenXML opts) items definitionListItemToOpenXML :: WriterOptions -> ([Inline],[[Block]]) -> WS [Element] definitionListItemToOpenXML opts (term,defs) = do term' <- withParaProp (pStyle "DefinitionTerm") $ blockToOpenXML opts (Para term) defs' <- withParaProp (pStyle "Definition") $ concat `fmap` mapM (blocksToOpenXML opts) defs return $ term' ++ defs' addList :: ListMarker -> WS () addList marker = do lists <- gets stLists modify $ \st -> st{ stLists = lists ++ [marker] } numStyles <- gets stNumStyles case M.lookup marker numStyles of Just _ -> return () Nothing -> modify $ \st -> st{ stNumStyles = M.insert marker (M.size numStyles + 1) numStyles } listItemToOpenXML :: WriterOptions -> Int -> [Block] -> WS [Element] listItemToOpenXML _ _ [] = return [] listItemToOpenXML opts numid (first:rest) = do first' <- withNumId numid $ blockToOpenXML opts first rest' <- withNumId 1 $ blocksToOpenXML opts rest return $ first' ++ rest' alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center" AlignDefault -> "left" -- | Convert a list of inline elements to OpenXML. inlinesToOpenXML :: WriterOptions -> [Inline] -> WS [Element] inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) lst withNumId :: Int -> WS a -> WS a withNumId numid p = do origNumId <- gets stListNumId modify $ \st -> st{ stListNumId = numid } result <- p modify $ \st -> st{ stListNumId = origNumId } return result asList :: WS a -> WS a asList p = do origListLevel <- gets stListLevel modify $ \st -> st{ stListLevel = stListLevel st + 1 } result <- p modify $ \st -> st{ stListLevel = origListLevel } return result getTextProps :: WS [Element] getTextProps = do props <- gets stTextProperties return $ if null props then [] else [mknode "w:rPr" [] $ props] pushTextProp :: Element -> WS () pushTextProp d = modify $ \s -> s{ stTextProperties = d : stTextProperties s } popTextProp :: WS () popTextProp = modify $ \s -> s{ stTextProperties = drop 1 $ stTextProperties s } withTextProp :: Element -> WS a -> WS a withTextProp d p = do pushTextProp d res <- p popTextProp return res getParaProps :: Bool -> WS [Element] getParaProps displayMathPara = do props <- gets stParaProperties listLevel <- gets stListLevel numid <- gets stListNumId let listPr = if listLevel >= 0 && not displayMathPara then [ mknode "w:numPr" [] [ mknode "w:numId" [("w:val",show numid)] () , mknode "w:ilvl" [("w:val",show listLevel)] () ] ] else [] return $ case props ++ listPr of [] -> [] ps -> [mknode "w:pPr" [] ps] pushParaProp :: Element -> WS () pushParaProp d = modify $ \s -> s{ stParaProperties = d : stParaProperties s } popParaProp :: WS () popParaProp = modify $ \s -> s{ stParaProperties = drop 1 $ stParaProperties s } withParaProp :: Element -> WS a -> WS a withParaProp d p = do pushParaProp d res <- p popParaProp return res formattedString :: String -> WS [Element] formattedString str = do props <- getTextProps return [ mknode "w:r" [] $ props ++ [ mknode "w:t" [("xml:space","preserve")] str ] ] -- | Convert an inline element to OpenXML. inlineToOpenXML :: WriterOptions -> Inline -> WS [Element] inlineToOpenXML _ (Str str) = formattedString str inlineToOpenXML opts Space = inlineToOpenXML opts (Str " ") 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) = withTextProp (mknode "w:i" [] ()) $ inlinesToOpenXML opts lst inlineToOpenXML opts (Subscript lst) = withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ()) $ inlinesToOpenXML opts lst inlineToOpenXML opts (Superscript lst) = withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ()) $ inlinesToOpenXML opts lst inlineToOpenXML opts (SmallCaps lst) = withTextProp (mknode "w:smallCaps" [] ()) $ inlinesToOpenXML opts lst inlineToOpenXML opts (Strikeout lst) = withTextProp (mknode "w:strike" [] ()) $ inlinesToOpenXML opts lst inlineToOpenXML _ LineBreak = return [br] inlineToOpenXML _ (RawInline f str) | f == Format "openxml" = return [ x | Elem x <- parseXML str ] | otherwise = return [] inlineToOpenXML opts (Quoted quoteType lst) = inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close] where (open, close) = case quoteType of SingleQuote -> ("\x2018", "\x2019") DoubleQuote -> ("\x201C", "\x201D") inlineToOpenXML opts (Math mathType str) = do let displayType = if mathType == DisplayMath then DisplayBlock else DisplayInline case texMathToOMML displayType str of Right r -> return [r] Left _ -> inlinesToOpenXML opts (readTeXMath' mathType str) inlineToOpenXML opts (Cite _ lst) = inlinesToOpenXML opts lst inlineToOpenXML opts (Code attrs str) = withTextProp (rStyle "VerbatimChar") $ if writerHighlight opts then case highlight formatOpenXML attrs str of Nothing -> unhighlighted Just h -> return h else unhighlighted where unhighlighted = intercalate [br] `fmap` (mapM formattedString $ lines str) formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok) toHlTok (toktype,tok) = mknode "w:r" [] [ mknode "w:rPr" [] [ rStyle $ show toktype ] , mknode "w:t" [("xml:space","preserve")] tok ] inlineToOpenXML opts (Note bs) = do notes <- gets stFootnotes notenum <- getUniqueId let notemarker = mknode "w:r" [] [ mknode "w:rPr" [] (rStyle "FootnoteRef") , mknode "w:footnoteRef" [] () ] let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : ils) : xs insertNoteRef (Para ils : xs) = Para (notemarkerXml : ils) : xs insertNoteRef xs = Para [notemarkerXml] : xs oldListLevel <- gets stListLevel oldParaProperties <- gets stParaProperties oldTextProperties <- gets stTextProperties modify $ \st -> st{ stListLevel = -1, stParaProperties = [], stTextProperties = [] } contents <- withParaProp (pStyle "FootnoteText") $ blocksToOpenXML opts $ insertNoteRef bs modify $ \st -> st{ stListLevel = oldListLevel, stParaProperties = oldParaProperties, stTextProperties = oldTextProperties } let newnote = mknode "w:footnote" [("w:id", notenum)] $ contents modify $ \s -> s{ stFootnotes = newnote : notes } return [ mknode "w:r" [] [ mknode "w:rPr" [] (rStyle "FootnoteRef") , mknode "w:footnoteReference" [("w:id", notenum)] () ] ] -- internal link: inlineToOpenXML opts (Link txt ('#':xs,_)) = do contents <- withTextProp (rStyle "Link") $ inlinesToOpenXML opts txt return [ mknode "w:hyperlink" [("w:anchor",xs)] contents ] -- external link: inlineToOpenXML opts (Link txt (src,_)) = do contents <- withTextProp (rStyle "Link") $ inlinesToOpenXML opts txt extlinks <- gets stExternalLinks id' <- case M.lookup src extlinks of Just i -> return i Nothing -> do i <- ("rId"++) `fmap` getUniqueId modify $ \st -> st{ stExternalLinks = M.insert src i extlinks } return i return [ mknode "w:hyperlink" [("r:id",id')] contents ] inlineToOpenXML opts (Image alt (src, tit)) = do -- first, check to see if we've already done this image imgs <- gets stImages case M.lookup src imgs of Just (_,_,_,elt,_) -> return [elt] Nothing -> do res <- liftIO $ fetchItem (writerSourceURL opts) src case res of Left (_ :: E.SomeException) -> do liftIO $ warn $ "Could not find image `" ++ src ++ "', skipping..." -- emit alt text inlinesToOpenXML opts alt Right (img, mt) -> do ident <- ("rId"++) `fmap` getUniqueId let size = imageSize img let (xpt,ypt) = maybe (120,120) sizeInPoints size -- 12700 emu = 1 pt let (xemu,yemu) = (xpt * 12700, ypt * 12700) let cNvPicPr = mknode "pic:cNvPicPr" [] $ mknode "a:picLocks" [("noChangeArrowheads","1"),("noChangeAspect","1")] () let nvPicPr = mknode "pic:nvPicPr" [] [ mknode "pic:cNvPr" [("descr",src),("id","0"),("name","Picture")] () , cNvPicPr ] let blipFill = mknode "pic:blipFill" [] [ mknode "a:blip" [("r:embed",ident)] () , mknode "a:stretch" [] $ mknode "a:fillRect" [] () ] let xfrm = mknode "a:xfrm" [] [ mknode "a:off" [("x","0"),("y","0")] () , mknode "a:ext" [("cx",show xemu),("cy",show yemu)] () ] let prstGeom = mknode "a:prstGeom" [("prst","rect")] $ mknode "a:avLst" [] () let ln = mknode "a:ln" [("w","9525")] [ mknode "a:noFill" [] () , mknode "a:headEnd" [] () , mknode "a:tailEnd" [] () ] let spPr = mknode "pic:spPr" [("bwMode","auto")] [xfrm, prstGeom, mknode "a:noFill" [] (), ln] let graphic = mknode "a:graphic" [] $ mknode "a:graphicData" [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")] [ mknode "pic:pic" [] [ nvPicPr , blipFill , spPr ] ] let imgElt = mknode "w:r" [] $ mknode "w:drawing" [] $ mknode "wp:inline" [] [ mknode "wp:extent" [("cx",show xemu),("cy",show yemu)] () , mknode "wp:effectExtent" [("b","0"),("l","0"),("r","0"),("t","0")] () , mknode "wp:docPr" [("descr",tit),("id","1"),("name","Picture")] () , graphic ] 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 = 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) $ stImages st } return [imgElt] br :: Element 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 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 pandoc-1.12.2.1/src/Text/Pandoc/Writers/EPUB.hs000644 000765 000024 00000133557 12251233602 020577 0ustar00jgmstaff000000 000000 {-# LANGUAGE PatternGuards, CPP, ScopedTypeVariables #-} {- Copyright (C) 2010 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.EPUB Copyright : Copyright (C) 2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane Stability : alpha Portability : portable Conversion of 'Pandoc' documents to EPUB. -} module Text.Pandoc.Writers.EPUB ( writeEPUB ) where import Data.IORef 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 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 import Text.Pandoc.Shared hiding ( Element ) import qualified Text.Pandoc.Shared as Shared import Text.Pandoc.Builder (fromList, setMeta) import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Walk import Control.Monad.State 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, isDigit ) import Network.URI ( unEscapeString ) import Text.Pandoc.MIME (getMimeType) #if MIN_VERSION_base(4,6,0) #else import Prelude hiding (catch) #endif import Control.Exception (catch, SomeException) import Text.Blaze.Html.Renderer.Utf8 (renderHtml) -- A Chapter includes a list of blocks and maybe a section -- number offset. Note, some chapters are unnumbered. The section -- number is different from the index number, which will be used -- 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 t] 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 = maybe "" id $ 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 = maybe "" id $ (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 <$> lookup "epub-stylesheet" (writerVariables 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 epub3 = version == EPUB3 epochtime <- floor `fmap` getPOSIXTime let mkEntry path content = toEntry path epochtime content let vars = ("epub3", if epub3 then "true" else "false") : ("css", "stylesheet.css") : writerVariables opts let opts' = opts{ writerEmailObfuscation = NoObfuscation , writerStandalone = True , writerSectionDivs = True , writerHtml5 = epub3 , writerTableOfContents = False -- we always have one in epub , writerVariables = vars , writerHTMLMathMethod = if epub3 then MathML Nothing else writerHTMLMathMethod opts , writerWrapText = False } metadata <- getEPUBMetadata opts' meta -- cover page (cpgEntry, cpicEntry) <- case epubCoverImage metadata of Nothing -> return ([],[]) Just img -> do let coverImage = "cover-image" ++ takeExtension img let cpContent = renderHtml $ writeHtml opts' (Pandoc meta [RawBlock (Format "html") $ "
\n\"cover\n
"]) imgContent <- B.readFile img return ( [mkEntry "cover.xhtml" cpContent] , [mkEntry coverImage imgContent] ) -- title page let tpContent = renderHtml $ writeHtml opts'{ writerVariables = ("titlepage","true"):vars } (Pandoc meta []) let tpEntry = mkEntry "title_page.xhtml" tpContent -- handle pictures picsRef <- newIORef [] Pandoc _ blocks <- walkM (transformInline opts' picsRef) doc pics <- readIORef picsRef let readPicEntry entries (oldsrc, newsrc) = do res <- fetchItem (writerSourceURL opts') oldsrc case res of Left _ -> do warn $ "Could not find image `" ++ oldsrc ++ "', skipping..." return entries Right (img,_) -> return $ (toEntry newsrc epochtime $ B.fromChunks . (:[]) $ img) : entries picEntries <- foldM readPicEntry [] pics -- handle fonts let mkFontEntry f = mkEntry (takeFileName f) `fmap` B.readFile f fontEntries <- mapM mkFontEntry $ writerEpubFonts opts' -- body pages -- add level 1 header to beginning if none there let blocks' = addIdentifiers $ case blocks of (Header 1 _ _ : _) -> blocks _ -> Header 1 ("",["unnumbered"],[]) (docTitle meta) : blocks let chapterHeaderLevel = writerEpubChapterLevel opts -- internal reference IDs change when we chunk the file, -- so that '#my-header-1' might turn into 'chap004.xhtml#my-header'. -- the next two lines fix that: let reftable = correlateRefs chapterHeaderLevel blocks' let blocks'' = replaceRefs reftable blocks' let isChapterHeader (Header n _ _) = n <= chapterHeaderLevel isChapterHeader _ = False let toChapters :: [Block] -> State [Int] [Chapter] toChapters [] = return [] toChapters (Header n attr@(_,classes,_) ils : bs) = do nums <- get mbnum <- if "unnumbered" `elem` classes then return Nothing else case splitAt (n - 1) nums of (ks, (m:_)) -> do let nums' = ks ++ [m+1] put nums' return $ Just (ks ++ [m]) -- note, this is the offset not the sec number (ks, []) -> do let nums' = ks ++ [1] put nums' return $ Just ks let (xs,ys) = break isChapterHeader bs (Chapter mbnum (Header n attr ils : xs) :) `fmap` toChapters ys toChapters (b:bs) = do let (xs,ys) = break isChapterHeader bs (Chapter Nothing (b:xs) :) `fmap` toChapters ys let chapters = evalState (toChapters blocks'') [] let chapToEntry :: Int -> Chapter -> Entry chapToEntry num (Chapter mbnum bs) = mkEntry (showChapter num) $ renderHtml $ writeHtml opts'{ writerNumberOffset = maybe [] id mbnum } $ case bs of (Header _ _ xs : _) -> Pandoc (setMeta "title" (fromList xs) nullMeta) bs _ -> Pandoc nullMeta bs let chapterEntries = zipWith chapToEntry [1..] chapters -- incredibly inefficient (TODO): let containsMathML ent = epub3 && " [] xs -> [("properties", unwords xs)]) $ () let chapterRefNode ent = unode "itemref" ! [("idref", takeBaseName $ eRelativePath ent)] $ () let pictureNode ent = unode "item" ! [("id", takeBaseName $ eRelativePath ent), ("href", eRelativePath ent), ("media-type", fromMaybe "application/octet-stream" $ imageTypeOf $ eRelativePath ent)] $ () let fontNode ent = unode "item" ! [("id", takeBaseName $ eRelativePath ent), ("href", eRelativePath ent), ("media-type", maybe "" id $ 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 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","epub-id-1")] $ [ metadataElement version metadata currentTime , unode "manifest" $ [ unode "item" ! [("id","ncx"), ("href","toc.ncx") ,("media-type","application/x-dtbncx+xml")] $ () , unode "item" ! [("id","style"), ("href","stylesheet.css") ,("media-type","text/css")] $ () , unode "item" ! ([("id","nav") ,("href","nav.xhtml") ,("media-type","application/xhtml+xml")] ++ [("properties","nav") | epub3 ]) $ () ] ++ map chapterNode (cpgEntry ++ (tpEntry : chapterEntries)) ++ (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 epubCoverImage metadata of Nothing -> [] Just _ -> [ unode "itemref" ! [("idref", "cover"),("linear","no")] $ () ] ++ ((unode "itemref" ! [("idref", "title_page") ,("linear", if null (docTitle meta) then "no" else "yes")] $ ()) : (unode "itemref" ! [("idref", "nav") ,("linear", if writerTableOfContents opts then "yes" else "no")] $ ()) : map chapterRefNode chapterEntries) , unode "guide" $ [ 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 -- toc.ncx let secs = hierarchicalize blocks'' let tocLevel = writerTOCDepth opts let navPointNode :: (Int -> String -> String -> [Element] -> Element) -> Shared.Element -> State Int Element navPointNode formatter (Sec _ nums (ident,_,_) ils children) = do n <- get modify (+1) let showNums :: [Int] -> String showNums = intercalate "." . map show let tit' = plainify ils let tit = if writerNumberSections opts && not (null nums) then showNums nums ++ " " ++ tit' else tit' let src = case lookup ident reftable of Just x -> x Nothing -> error (ident ++ " not found in reftable") let isSec (Sec lev _ _ _ _) = lev <= tocLevel isSec _ = False let subsecs = filter isSec children subs <- mapM (navPointNode formatter) subsecs return $ formatter n tit src subs navPointNode _ (Blk _) = error "navPointNode encountered Blk" let navMapFormatter :: Int -> String -> String -> [Element] -> Element navMapFormatter n tit src subs = unode "navPoint" ! [("id", "navPoint-" ++ show n) ,("playOrder", show n)] $ [ unode "navLabel" $ unode "text" tit , unode "content" ! [("src", src)] $ () ] ++ subs let tpNode = unode "navPoint" ! [("id", "navPoint-0")] $ [ unode "navLabel" $ unode "text" (plainify $ docTitle meta) , unode "content" ! [("src","title_page.xhtml")] $ () ] 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", uuid)] $ () , unode "meta" ! [("name","dtb:depth") ,("content", "1")] $ () , unode "meta" ! [("name","dtb:totalPageCount") ,("content", "0")] $ () , unode "meta" ! [("name","dtb:maxPageNumber") ,("content", "0")] $ () ] ++ case epubCoverImage metadata of Nothing -> [] Just _ -> [unode "meta" ! [("name","cover"), ("content","cover-image")] $ ()] , unode "docTitle" $ unode "text" $ plainTitle , unode "navMap" $ tpNode : evalState (mapM (navPointNode navMapFormatter) secs) 1 ] let tocEntry = mkEntry "toc.ncx" tocData let navXhtmlFormatter :: Int -> String -> String -> [Element] -> Element navXhtmlFormatter n tit src subs = unode "li" ! [("id", "toc-li-" ++ show n)] $ (unode "a" ! [("href",src)] $ (unode "span" tit)) : case subs of [] -> [] (_:_) -> [unode "ol" ! [("class","toc")] $ subs] let navtag = if epub3 then "nav" else "div" let navData = UTF8.fromStringLazy $ ppTopElement $ unode "html" ! [("xmlns","http://www.w3.org/1999/xhtml") ,("xmlns:epub","http://www.idpf.org/2007/ops")] $ [ unode "head" $ [ unode "title" plainTitle , unode "link" ! [("rel","stylesheet"),("type","text/css"),("href","stylesheet.css")] $ () ] , unode "body" $ unode navtag ! [("epub:type","toc") | epub3] $ [ unode "h1" ! [("id","toc-title")] $ plainTitle , unode "ol" ! [("class","toc")] $ evalState (mapM (navPointNode navXhtmlFormatter) secs) 1] ] let navEntry = mkEntry "nav.xhtml" navData -- mimetype let mimetypeEntry = mkEntry "mimetype" $ UTF8.fromStringLazy "application/epub+zip" -- container.xml let containerData = UTF8.fromStringLazy $ ppTopElement $ unode "container" ! [("version","1.0") ,("xmlns","urn:oasis:names:tc:opendocument:xmlns:container")] $ unode "rootfiles" $ unode "rootfile" ! [("full-path","content.opf") ,("media-type","application/oebps-package+xml")] $ () let containerEntry = mkEntry "META-INF/container.xml" containerData -- com.apple.ibooks.display-options.xml 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 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" $ UTF8.fromStringLazy stylesheet -- construct archive let archive = foldr addEntryToArchive emptyArchive (mimetypeEntry : containerEntry : appleEntry : stylesheetEntry : tpEntry : contentsEntry : tocEntry : navEntry : (picEntries ++ cpicEntry ++ cpgEntry ++ chapterEntries ++ fontEntries)) return $ fromArchive archive 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" transformInline :: WriterOptions -> IORef [(FilePath, FilePath)] -- ^ (oldpath, newpath) images -> Inline -> IO Inline transformInline opts picsRef (Image lab (src,tit)) = do let src' = unEscapeString src pics <- readIORef picsRef let oldsrc = maybe src' ( src) $ writerSourceURL opts let ext = takeExtension src' newsrc <- case lookup oldsrc pics of Just n -> return n Nothing -> do let new = "images/img" ++ show (length pics) ++ ext modifyIORef picsRef ( (oldsrc, new): ) return new return $ Image lab (newsrc, tit) transformInline opts _ (x@(Math _ _)) | WebTeX _ <- writerHTMLMathMethod opts = do raw <- makeSelfContained Nothing $ writeHtmlInline opts x return $ RawInline (Format "html") raw transformInline _ _ x = return x writeHtmlInline :: WriterOptions -> Inline -> String writeHtmlInline opts z = trimr $ writeHtmlString opts{ writerStandalone = False } $ Pandoc nullMeta [Plain [z]] (!) :: Node t => (t -> Element) -> [(String, String)] -> t -> Element (!) f attrs n = add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) (f n) -- | Version of 'ppTopElement' that specifies UTF-8 encoding. ppTopElement :: Element -> String ppTopElement = ("\n" ++) . unEntity . ppElement -- unEntity removes numeric entities introduced by ppElement -- (kindlegen seems to choke on these). where unEntity [] = "" unEntity ('&':'#':xs) = let (ds,ys) = break (==';') xs rest = drop 1 ys in case safeRead ('\'':'\\':ds ++ "'") of Just x -> x : unEntity rest Nothing -> '&':'#':unEntity xs unEntity (x:xs) = x : unEntity xs imageTypeOf :: FilePath -> Maybe String imageTypeOf x = case getMimeType x of Just y@('i':'m':'a':'g':'e':_) -> Just y _ -> Nothing data IdentState = IdentState{ chapterNumber :: Int, identTable :: [(String,String)] } deriving (Read, Show) -- Returns filename for chapter number. showChapter :: Int -> String showChapter = printf "ch%03d.xhtml" -- Add identifiers to any headers without them. addIdentifiers :: [Block] -> [Block] addIdentifiers bs = evalState (mapM go bs) [] where go (Header n (ident,classes,kvs) ils) = do ids <- get let ident' = if null ident then uniqueIdent ils ids else ident put $ ident' : ids return $ Header n (ident',classes,kvs) ils go x = return x -- Go through a block list and construct a table -- correlating the automatically constructed references -- that would be used in a normal pandoc document with -- new URLs to be used in the EPUB. For example, what -- was "header-1" might turn into "ch006.xhtml#header". correlateRefs :: Int -> [Block] -> [(String,String)] correlateRefs chapterHeaderLevel bs = identTable $ execState (mapM_ go bs) IdentState{ chapterNumber = 0 , identTable = [] } where go :: Block -> State IdentState () go (Header n (ident,_,_) _) = do when (n <= chapterHeaderLevel) $ modify $ \s -> s{ chapterNumber = chapterNumber s + 1 } st <- get let chapterid = showChapter (chapterNumber st) ++ if n <= chapterHeaderLevel then "" else '#' : ident modify $ \s -> s{ identTable = (ident, chapterid) : identTable st } go _ = return () -- Replace internal link references using the table produced -- by correlateRefs. replaceRefs :: [(String,String)] -> [Block] -> [Block] replaceRefs refTable = walk replaceOneRef where replaceOneRef x@(Link lab ('#':xs,tit)) = case lookup xs refTable of 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") ] pandoc-1.12.2.1/src/Text/Pandoc/Writers/FB2.hs000644 000765 000024 00000056724 12251233602 020415 0ustar00jgmstaff000000 000000 {- Copyright (c) 2011-2012, Sergey Astanin All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Conversion of 'Pandoc' documents to FB2 (FictionBook2) format. FictionBook is an XML-based e-book format. For more information see: -} module Text.Pandoc.Writers.FB2 (writeFB2) where import Control.Monad.State (StateT, evalStateT, get, modify) import Control.Monad.State (liftM, liftM2, liftIO) import Data.ByteString.Base64 (encode) import Data.Char (toUpper, toLower, isSpace, isAscii, isControl) import Data.List (intersperse, intercalate, isPrefixOf) import Data.Either (lefts, rights) import Network.Browser (browse, request, setAllowRedirects, setOutHandler) import Network.HTTP (catchIO_, getRequest, getHeaders, getResponseBody) import Network.HTTP (lookupHeader, HeaderName(..), urlEncode) import Network.URI (isURI, unEscapeString) import System.FilePath (takeExtension) import Text.XML.Light import qualified Control.Exception as E import qualified Data.ByteString as B import qualified Text.XML.Light as X import qualified Text.XML.Light.Cursor as XC import Text.Pandoc.Definition import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def) import Text.Pandoc.Shared (orderedListMarkers) import Text.Pandoc.Walk -- | Data to be written at the end of the document: -- (foot)notes, URLs, references, images. data FbRenderState = FbRenderState { footnotes :: [ (Int, String, [Content]) ] -- ^ #, ID, text , imagesToFetch :: [ (String, String) ] -- ^ filename, URL or path , parentListMarker :: String -- ^ list marker of the parent ordered list , parentBulletLevel :: Int -- ^ nesting level of the unordered list , writerOptions :: WriterOptions } deriving (Show) -- | FictionBook building monad. type FBM = StateT FbRenderState IO newFB :: FbRenderState newFB = FbRenderState { footnotes = [], imagesToFetch = [] , parentListMarker = "", parentBulletLevel = 0 , writerOptions = def } data ImageMode = NormalImage | InlineImage deriving (Eq) instance Show ImageMode where show NormalImage = "imageType" show InlineImage = "inlineImageType" -- | Produce an FB2 document from a 'Pandoc' document. writeFB2 :: WriterOptions -- ^ conversion options -> Pandoc -- ^ document to convert -> IO String -- ^ FictionBook2 document (not encoded yet) writeFB2 opts (Pandoc meta blocks) = flip evalStateT newFB $ do modify (\s -> s { writerOptions = opts { writerStandalone = True } }) desc <- description meta fp <- frontpage meta secs <- renderSections 1 blocks let body = el "body" $ fp ++ secs notes <- renderFootnotes (imgs,missing) <- liftM imagesToFetch get >>= \s -> liftIO (fetchImages s) let body' = replaceImagesWithAlt missing body let fb2_xml = el "FictionBook" (fb2_attrs, [desc, body'] ++ notes ++ imgs) return $ xml_head ++ (showContent fb2_xml) where xml_head = "\n" fb2_attrs = let xmlns = "http://www.gribuser.ru/xml/fictionbook/2.0" xlink = "http://www.w3.org/1999/xlink" in [ uattr "xmlns" xmlns , attr ("xmlns", "l") xlink ] -- frontpage :: Meta -> FBM [Content] frontpage meta' = do t <- cMapM toXml . docTitle $ meta' return $ [ el "title" (el "p" t) , el "annotation" (map (el "p" . cMap plain) (docAuthors meta' ++ [docDate meta'])) ] description :: Meta -> FBM Content description meta' = do bt <- booktitle meta' let as = authors meta' dd <- docdate meta' return $ el "description" [ el "title-info" (bt ++ as ++ dd) , el "document-info" [ el "program-used" "pandoc" ] -- FIXME: +version ] booktitle :: Meta -> FBM [Content] booktitle meta' = do t <- cMapM toXml . docTitle $ meta' return $ if null t then [] else [ el "book-title" t ] authors :: Meta -> [Content] authors meta' = cMap author (docAuthors meta') author :: [Inline] -> [Content] author ss = let ws = words . cMap plain $ ss email = (el "email") `fmap` (take 1 $ filter ('@' `elem`) ws) ws' = filter ('@' `notElem`) ws names = case ws' of (nickname:[]) -> [ el "nickname" nickname ] (fname:lname:[]) -> [ el "first-name" fname , el "last-name" lname ] (fname:rest) -> [ el "first-name" fname , el "middle-name" (concat . init $ rest) , el "last-name" (last rest) ] ([]) -> [] in list $ el "author" (names ++ email) docdate :: Meta -> FBM [Content] docdate meta' = do let ss = docDate meta' d <- cMapM toXml ss return $ if null d then [] else [el "date" d] -- | Divide the stream of blocks into sections and convert to XML -- representation. renderSections :: Int -> [Block] -> FBM [Content] renderSections level blocks = do let secs = splitSections level blocks mapM (renderSection level) secs renderSection :: Int -> ([Inline], [Block]) -> FBM Content renderSection level (ttl, body) = do title <- if null ttl then return [] else return . list . el "title" . formatTitle $ ttl content <- if (hasSubsections body) then renderSections (level + 1) body else cMapM blockToXml body return $ el "section" (title ++ content) where hasSubsections = any isHeader isHeader (Header _ _ _) = True isHeader _ = False -- | Only

and are allowed within in FB2. formatTitle :: [Inline] -> [Content] formatTitle inlines = let lns = split isLineBreak inlines lns' = map (el "p" . cMap plain) lns in intersperse (el "empty-line" ()) lns' split :: (a -> Bool) -> [a] -> [[a]] split _ [] = [] split cond xs = let (b,a) = break cond xs in (b:split cond (drop 1 a)) isLineBreak :: Inline -> Bool isLineBreak LineBreak = True isLineBreak _ = False -- | Divide the stream of block elements into sections: [(title, blocks)]. splitSections :: Int -> [Block] -> [([Inline], [Block])] splitSections level blocks = reverse $ revSplit (reverse blocks) where revSplit [] = [] revSplit rblocks = let (lastsec, before) = break sameLevel rblocks (header, prevblocks) = case before of ((Header n _ title):prevblocks') -> if n == level then (title, prevblocks') else ([], before) _ -> ([], before) in (header, reverse lastsec) : revSplit prevblocks sameLevel (Header n _ _) = n == level sameLevel _ = False -- | Make another FictionBook body with footnotes. renderFootnotes :: FBM [Content] renderFootnotes = do fns <- footnotes `liftM` get if null fns then return [] -- no footnotes else return . list $ el "body" ([uattr "name" "notes"], map renderFN (reverse fns)) where renderFN (n, idstr, cs) = let fn_texts = (el "title" (el "p" (show n))) : cs in el "section" ([uattr "id" idstr], fn_texts) -- | Fetch images and encode them for the FictionBook XML. -- Return image data and a list of hrefs of the missing images. fetchImages :: [(String,String)] -> IO ([Content],[String]) fetchImages links = do imgs <- mapM (uncurry fetchImage) links return $ (rights imgs, lefts imgs) -- | Fetch image data from disk or from network and make a <binary> XML section. -- Return either (Left hrefOfMissingImage) or (Right xmlContent). fetchImage :: String -> String -> IO (Either String Content) fetchImage href link = do mbimg <- case (isURI link, readDataURI link) of (True, Just (mime,_,True,base64)) -> let mime' = map toLower mime in if mime' == "image/png" || mime' == "image/jpeg" then return (Just (mime',base64)) else return Nothing (True, Just _) -> return Nothing -- not base64-encoded (True, Nothing) -> fetchURL link (False, _) -> do d <- nothingOnError $ B.readFile (unEscapeString link) let t = case map toLower (takeExtension link) of ".png" -> Just "image/png" ".jpg" -> Just "image/jpeg" ".jpeg" -> Just "image/jpeg" ".jpe" -> Just "image/jpeg" _ -> Nothing -- only PNG and JPEG are supported in FB2 return $ liftM2 (,) t (liftM (toStr . encode) d) case mbimg of Just (imgtype, imgdata) -> do return . Right $ el "binary" ( [uattr "id" href , uattr "content-type" imgtype] , txt imgdata ) _ -> return (Left ('#':href)) where nothingOnError :: (IO B.ByteString) -> (IO (Maybe B.ByteString)) nothingOnError action = liftM Just action `E.catch` omnihandler omnihandler :: E.SomeException -> IO (Maybe B.ByteString) omnihandler _ = return Nothing -- | Extract mime type and encoded data from the Data URI. readDataURI :: String -- ^ URI -> Maybe (String,String,Bool,String) -- ^ Maybe (mime,charset,isBase64,data) readDataURI uri = let prefix = "data:" in if not (prefix `isPrefixOf` uri) then Nothing else let rest = drop (length prefix) uri meta = takeWhile (/= ',') rest -- without trailing ',' uridata = drop (length meta + 1) rest parts = split (== ';') meta (mime,cs,enc)=foldr upd ("text/plain","US-ASCII",False) parts in Just (mime,cs,enc,uridata) where upd str m@(mime,cs,enc) | isMimeType str = (str,cs,enc) | "charset=" `isPrefixOf` str = (mime,drop (length "charset=") str,enc) | str == "base64" = (mime,cs,True) | otherwise = m -- Without parameters like ;charset=...; see RFC 2045, 5.1 isMimeType :: String -> Bool isMimeType s = case split (=='/') s of [mtype,msubtype] -> ((map toLower mtype) `elem` types || "x-" `isPrefixOf` (map toLower mtype)) && all valid mtype && all valid msubtype _ -> False where types = ["text","image","audio","video","application","message","multipart"] valid c = isAscii c && not (isControl c) && not (isSpace c) && c `notElem` "()<>@,;:\\\"/[]?=" -- | Fetch URL, return its Content-Type and binary data on success. fetchURL :: String -> IO (Maybe (String, String)) fetchURL url = do flip catchIO_ (return Nothing) $ do r <- browse $ do setOutHandler (const (return ())) setAllowRedirects True liftM snd . request . getRequest $ url let content_type = lookupHeader HdrContentType (getHeaders r) content <- liftM (Just . toStr . encode . toBS) . getResponseBody $ Right r return $ liftM2 (,) content_type content where toBS :: String -> B.ByteString toBS = B.pack . map (toEnum . fromEnum) toStr :: B.ByteString -> String toStr = map (toEnum . fromEnum) . B.unpack footnoteID :: Int -> String footnoteID i = "n" ++ (show i) linkID :: Int -> String linkID i = "l" ++ (show i) -- | Convert a block-level Pandoc's element to FictionBook XML representation. blockToXml :: Block -> FBM [Content] blockToXml (Plain ss) = cMapM toXml ss -- FIXME: can lead to malformed FB2 blockToXml (Para [Math DisplayMath formula]) = insertMath NormalImage formula -- title beginning with fig: indicates that the image is a figure blockToXml (Para [Image alt (src,'f':'i':'g':':':tit)]) = insertImage NormalImage (Image alt (src,tit)) blockToXml (Para ss) = liftM (list . el "p") $ cMapM toXml ss blockToXml (CodeBlock _ s) = return . spaceBeforeAfter . map (el "p" . el "code") . lines $ s blockToXml (RawBlock _ s) = return . spaceBeforeAfter . map (el "p" . el "code") . lines $ s blockToXml (Div _ bs) = cMapM blockToXml bs blockToXml (BlockQuote bs) = liftM (list . el "cite") $ cMapM blockToXml bs blockToXml (OrderedList a bss) = do state <- get let pmrk = parentListMarker state let markers = map ((pmrk ++ " ") ++) $ orderedListMarkers a let mkitem mrk bs = do modify (\s -> s { parentListMarker = mrk }) itemtext <- cMapM blockToXml . paraToPlain $ bs modify (\s -> s { parentListMarker = pmrk }) -- old parent marker return . el "p" $ [ txt mrk, txt " " ] ++ itemtext mapM (uncurry mkitem) (zip markers bss) blockToXml (BulletList bss) = do state <- get let level = parentBulletLevel state let pmrk = parentListMarker state let prefix = replicate (length pmrk) ' ' let bullets = ["\x2022", "\x25e6", "*", "\x2043", "\x2023"] let mrk = prefix ++ bullets !! (level `mod` (length bullets)) let mkitem bs = do modify (\s -> s { parentBulletLevel = (level+1) }) itemtext <- cMapM blockToXml . paraToPlain $ bs modify (\s -> s { parentBulletLevel = level }) -- restore bullet level return $ el "p" $ [ txt (mrk ++ " ") ] ++ itemtext mapM mkitem bss blockToXml (DefinitionList defs) = cMapM mkdef defs where mkdef (term, bss) = do def' <- cMapM (cMapM blockToXml . sep . paraToPlain . map indent) bss t <- wrap "strong" term return [ el "p" t, el "p" def' ] sep blocks = if all needsBreak blocks then blocks ++ [Plain [LineBreak]] else blocks needsBreak (Para _) = False needsBreak (Plain ins) = LineBreak `notElem` ins needsBreak _ = True blockToXml (Header _ _ _) = -- should never happen, see renderSections error "unexpected header in section text" blockToXml HorizontalRule = return [ el "empty-line" () , el "p" (txt (replicate 10 '—')) , el "empty-line" () ] blockToXml (Table caption aligns _ headers rows) = do hd <- mkrow "th" headers aligns bd <- mapM (\r -> mkrow "td" r aligns) rows c <- return . el "emphasis" =<< cMapM toXml caption return [el "table" (hd : bd), el "p" c] where mkrow :: String -> [TableCell] -> [Alignment] -> FBM Content mkrow tag cells aligns' = (el "tr") `liftM` (mapM (mkcell tag) (zip cells aligns')) -- mkcell :: String -> (TableCell, Alignment) -> FBM Content mkcell tag (cell, align) = do cblocks <- cMapM blockToXml cell return $ el tag ([align_attr align], cblocks) -- align_attr a = Attr (QName "align" Nothing Nothing) (align_str a) align_str AlignLeft = "left" align_str AlignCenter = "center" align_str AlignRight = "right" align_str AlignDefault = "left" blockToXml Null = return [] -- Replace paragraphs with plain text and line break. -- Necessary to simulate multi-paragraph lists in FB2. paraToPlain :: [Block] -> [Block] paraToPlain [] = [] paraToPlain (Para inlines : rest) = let p = (Plain (inlines ++ [LineBreak])) in p : paraToPlain rest paraToPlain (p:rest) = p : paraToPlain rest -- Simulate increased indentation level. Will not really work -- for multi-line paragraphs. indent :: Block -> Block indent = indentBlock where -- indentation space spacer :: String spacer = replicate 4 ' ' -- indentBlock (Plain ins) = Plain ((Str spacer):ins) indentBlock (Para ins) = Para ((Str spacer):ins) indentBlock (CodeBlock a s) = let s' = unlines . map (spacer++) . lines $ s in CodeBlock a s' indentBlock (BlockQuote bs) = BlockQuote (map indent bs) indentBlock (Header l attr' ins) = Header l attr' (indentLines ins) indentBlock everythingElse = everythingElse -- indent every (explicit) line indentLines :: [Inline] -> [Inline] indentLines ins = let lns = split isLineBreak ins :: [[Inline]] in intercalate [LineBreak] $ map ((Str spacer):) lns capitalize :: Inline -> Inline capitalize (Str xs) = Str $ map toUpper xs capitalize x = x -- | Convert a Pandoc's Inline element to FictionBook XML representation. toXml :: Inline -> FBM [Content] toXml (Str s) = return [txt s] toXml (Span _ ils) = cMapM toXml ils toXml (Emph ss) = list `liftM` wrap "emphasis" ss toXml (Strong ss) = list `liftM` wrap "strong" ss toXml (Strikeout ss) = list `liftM` wrap "strikethrough" ss toXml (Superscript ss) = list `liftM` wrap "sup" ss toXml (Subscript ss) = list `liftM` wrap "sub" ss toXml (SmallCaps ss) = cMapM toXml $ walk capitalize ss toXml (Quoted SingleQuote ss) = do -- FIXME: should be language-specific inner <- cMapM toXml ss return $ [txt "‘"] ++ inner ++ [txt "’"] toXml (Quoted DoubleQuote ss) = do inner <- cMapM toXml ss return $ [txt "“"] ++ inner ++ [txt "”"] toXml (Cite _ ss) = cMapM toXml ss -- FIXME: support citation styles toXml (Code _ s) = return [el "code" s] toXml Space = return [txt " "] toXml LineBreak = return [el "empty-line" ()] toXml (Math _ formula) = insertMath InlineImage formula toXml (RawInline _ _) = return [] -- raw TeX and raw HTML are suppressed toXml (Link text (url,ttl)) = do fns <- footnotes `liftM` get let n = 1 + length fns let ln_id = linkID n let ln_ref = list . el "sup" . txt $ "[" ++ show n ++ "]" ln_text <- cMapM toXml text let ln_desc = let ttl' = dropWhile isSpace ttl in if null ttl' then list . el "p" $ el "code" url else list . el "p" $ [ txt (ttl' ++ ": "), el "code" url ] modify (\s -> s { footnotes = (n, ln_id, ln_desc) : fns }) return $ ln_text ++ [ el "a" ( [ attr ("l","href") ('#':ln_id) , uattr "type" "note" ] , ln_ref) ] toXml img@(Image _ _) = insertImage InlineImage img toXml (Note bs) = do fns <- footnotes `liftM` get let n = 1 + length fns let fn_id = footnoteID n fn_desc <- cMapM blockToXml bs modify (\s -> s { footnotes = (n, fn_id, fn_desc) : fns }) let fn_ref = el "sup" . txt $ "[" ++ show n ++ "]" return . list $ el "a" ( [ attr ("l","href") ('#':fn_id) , uattr "type" "note" ] , fn_ref ) insertMath :: ImageMode -> String -> FBM [Content] insertMath immode formula = do htmlMath <- return . writerHTMLMathMethod . writerOptions =<< get case htmlMath of WebTeX url -> do let alt = [Code nullAttr formula] let imgurl = url ++ urlEncode formula let img = Image alt (imgurl, "") insertImage immode img _ -> return [el "code" formula] insertImage :: ImageMode -> Inline -> FBM [Content] insertImage immode (Image alt (url,ttl)) = do images <- imagesToFetch `liftM` get let n = 1 + length images let fname = "image" ++ show n modify (\s -> s { imagesToFetch = (fname, url) : images }) let ttlattr = case (immode, null ttl) of (NormalImage, False) -> [ uattr "title" ttl ] _ -> [] return . list $ el "image" $ [ attr ("l","href") ('#':fname) , attr ("l","type") (show immode) , uattr "alt" (cMap plain alt) ] ++ ttlattr insertImage _ _ = error "unexpected inline instead of image" replaceImagesWithAlt :: [String] -> Content -> Content replaceImagesWithAlt missingHrefs body = let cur = XC.fromContent body cur' = replaceAll cur in XC.toTree . XC.root $ cur' where -- replaceAll :: XC.Cursor -> XC.Cursor replaceAll c = let n = XC.current c c' = if isImage n && isMissing n then XC.modifyContent replaceNode c else c in case XC.nextDF c' of (Just cnext) -> replaceAll cnext Nothing -> c' -- end of document -- isImage :: Content -> Bool isImage (Elem e) = (elName e) == (uname "image") isImage _ = False -- isMissing (Elem img@(Element _ _ _ _)) = let imgAttrs = elAttribs img badAttrs = map (attr ("l","href")) missingHrefs in any (`elem` imgAttrs) badAttrs isMissing _ = False -- replaceNode :: Content -> Content replaceNode n@(Elem img@(Element _ _ _ _)) = let attrs = elAttribs img alt = getAttrVal attrs (uname "alt") imtype = getAttrVal attrs (qname "l" "type") in case (alt, imtype) of (Just alt', Just imtype') -> if imtype' == show NormalImage then el "p" alt' else txt alt' (Just alt', Nothing) -> txt alt' -- no type attribute _ -> n -- don't replace if alt text is not found replaceNode n = n -- getAttrVal :: [X.Attr] -> QName -> Maybe String getAttrVal attrs name = case filter ((name ==) . attrKey) attrs of (a:_) -> Just (attrVal a) _ -> Nothing -- | Wrap all inlines with an XML tag (given its unqualified name). wrap :: String -> [Inline] -> FBM Content wrap tagname inlines = el tagname `liftM` cMapM toXml inlines -- " Create a singleton list. list :: a -> [a] list = (:[]) -- | Convert an 'Inline' to plaintext. plain :: Inline -> String plain (Str s) = s plain (Emph ss) = concat (map plain ss) plain (Span _ ss) = concat (map plain ss) plain (Strong ss) = concat (map plain ss) plain (Strikeout ss) = concat (map plain ss) plain (Superscript ss) = concat (map plain ss) plain (Subscript ss) = concat (map plain ss) plain (SmallCaps ss) = concat (map plain ss) plain (Quoted _ ss) = concat (map plain ss) plain (Cite _ ss) = concat (map plain ss) -- FIXME plain (Code _ s) = s plain Space = " " plain LineBreak = "\n" plain (Math _ s) = s plain (RawInline _ s) = s plain (Link text (url,_)) = concat (map plain text ++ [" <", url, ">"]) plain (Image alt _) = concat (map plain alt) plain (Note _) = "" -- FIXME -- | Create an XML element. el :: (Node t) => String -- ^ unqualified element name -> t -- ^ node contents -> Content -- ^ XML content el name cs = Elem $ unode name cs -- | Put empty lines around content spaceBeforeAfter :: [Content] -> [Content] spaceBeforeAfter cs = let emptyline = el "empty-line" () in [emptyline] ++ cs ++ [emptyline] -- | Create a plain-text XML content. txt :: String -> Content txt s = Text $ CData CDataText s Nothing -- | Create an XML attribute with an unqualified name. uattr :: String -> String -> Text.XML.Light.Attr uattr name val = Attr (uname name) val -- | Create an XML attribute with a qualified name from given namespace. attr :: (String, String) -> String -> Text.XML.Light.Attr attr (ns, name) val = Attr (qname ns name) val -- | Unqualified name uname :: String -> QName uname name = QName name Nothing Nothing -- | Qualified name qname :: String -> String -> QName qname ns name = QName name Nothing (Just ns) -- | Abbreviation for 'concatMap'. cMap :: (a -> [b]) -> [a] -> [b] cMap = concatMap -- | Monadic equivalent of 'concatMap'. cMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b] cMapM f xs = concat `liftM` mapM f xs ��������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/HTML.hs�����������������������������������������������������000644 �000765 �000024 �00000116310 12251233602 020574� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings, CPP #-} {-# OPTIONS_GHC -fno-warn-deprecations #-} {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.HTML Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to HTML. -} module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where import Text.Pandoc.Definition import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Templates import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Slides import Text.Pandoc.Highlighting ( highlight, styleToCss, formatHtmlInline, formatHtmlBlock ) 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 Control.Monad.State import Text.Blaze.Html hiding(contents) import Text.Blaze.Internal(preEscapedString) #if MIN_VERSION_blaze_html(0,5,1) import qualified Text.Blaze.XHtml5 as H5 #else import qualified Text.Blaze.Html5 as H5 #endif import qualified Text.Blaze.XHtml1.Transitional as H import qualified Text.Blaze.XHtml1.Transitional.Attributes as A import Text.Blaze.Renderer.String (renderHtml) import Text.TeXMath import Text.XML.Light.Output import System.FilePath (takeExtension) import Data.Monoid import Data.Aeson (Value) data WriterState = WriterState { stNotes :: [Html] -- ^ List of notes , stMath :: Bool -- ^ Math is used in document , stQuotes :: Bool -- ^ <q> tag is used , stHighlighting :: Bool -- ^ Syntax highlighting is used , stSecNum :: [Int] -- ^ Number of current section } defaultWriterState :: WriterState defaultWriterState = WriterState {stNotes= [], stMath = False, stQuotes = False, stHighlighting = False, stSecNum = []} -- Helpers to render HTML with the appropriate function. strToHtml :: String -> Html strToHtml ('\'':xs) = preEscapedString "\'" `mappend` strToHtml xs strToHtml xs@(_:_) = case break (=='\'') xs of (_ ,[]) -> toHtml xs (ys,zs) -> toHtml ys `mappend` strToHtml zs strToHtml [] = "" -- | Hard linebreak. nl :: WriterOptions -> Html nl opts = if writerWrapText opts then preEscapedString "\n" else mempty -- | Convert Pandoc document to Html string. writeHtmlString :: WriterOptions -> Pandoc -> String writeHtmlString opts d = let (body, context) = evalState (pandocToHtml opts d) defaultWriterState in if writerStandalone opts then inTemplate opts context body else renderHtml body -- | Convert Pandoc document to Html structure. writeHtml :: WriterOptions -> Pandoc -> Html writeHtml opts d = let (body, context) = evalState (pandocToHtml opts d) defaultWriterState in if writerStandalone opts then inTemplate opts context body else body -- result is (title, authors, date, toc, body, new variables) pandocToHtml :: WriterOptions -> Pandoc -> State WriterState (Html, Value) pandocToHtml opts (Pandoc meta blocks) = do metadata <- metaToJSON opts (fmap renderHtml . blockListToHtml opts) (fmap renderHtml . inlineListToHtml opts) meta let stringifyHTML = escapeStringForXML . stringify let authsMeta = map stringifyHTML $ docAuthors meta let dateMeta = stringifyHTML $ docDate meta let slideLevel = maybe (getSlideLevel blocks) id $ writerSlideLevel opts let sects = hierarchicalize $ if writerSlideVariant opts == NoSlides then blocks else prepSlides slideLevel blocks toc <- if writerTableOfContents opts then tableOfContents opts sects else return Nothing blocks' <- liftM (mconcat . intersperse (nl opts)) $ mapM (elementToHtml slideLevel opts) sects st <- get let notes = reverse (stNotes st) let thebody = blocks' >> footnoteSection opts notes let math = if stMath st then case writerHTMLMathMethod opts of LaTeXMathML (Just url) -> H.script ! A.src (toValue url) ! A.type_ "text/javascript" $ mempty MathML (Just url) -> H.script ! A.src (toValue url) ! A.type_ "text/javascript" $ mempty MathJax url -> H.script ! A.src (toValue url) ! A.type_ "text/javascript" $ 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" $ mempty _ -> case lookup "mathml-script" (writerVariables opts) of Just s | not (writerHtml5 opts) -> H.script ! A.type_ "text/javascript" $ preEscapedString ("/*<![CDATA[*/\n" ++ s ++ "/*]]>*/\n") | otherwise -> mempty Nothing -> mempty else mempty let context = (if stHighlighting st then defField "highlighting-css" (styleToCss $ writerHighlightStyle opts) else id) $ (if stMath st then defField "math" (renderHtml math) else id) $ defField "quotes" (stQuotes st) $ maybe id (defField "toc" . renderHtml) toc $ defField "author-meta" authsMeta $ maybe id (defField "date-meta") (normalizeDate dateMeta) $ defField "pagetitle" (stringifyHTML $ docTitle meta) $ defField "idprefix" (writerIdentifierPrefix opts) $ -- these should maybe be set in pandoc.hs defField "slidy-url" ("http://www.w3.org/Talks/Tools/Slidy2" :: String) $ defField "slideous-url" ("slideous" :: String) $ defField "revealjs-url" ("reveal.js" :: String) $ defField "s5-url" ("s5/default" :: String) $ defField "html5" (writerHtml5 opts) $ metadata return (thebody, context) inTemplate :: TemplateTarget a => WriterOptions -> Value -> Html -> a inTemplate opts context body = renderTemplate' (writerTemplate opts) $ defField "body" (renderHtml body) context -- | Like Text.XHtml's identifier, but adds the writerIdentifierPrefix prefixedId :: WriterOptions -> String -> Attribute prefixedId opts s = case s of "" -> mempty _ -> A.id $ toValue $ writerIdentifierPrefix opts ++ s toList :: (Html -> Html) -> WriterOptions -> ([Html] -> Html) toList listop opts items = do if (writerIncremental opts) then if (writerSlideVariant opts /= RevealJsSlides) then (listop $ mconcat items) ! A.class_ "incremental" else listop $ mconcat $ map (! A.class_ "fragment") items else listop $ mconcat items unordList :: WriterOptions -> [Html] -> Html unordList opts = toList H.ul opts . toListItems opts ordList :: WriterOptions -> [Html] -> Html ordList opts = toList H.ol opts . toListItems opts defList :: WriterOptions -> [Html] -> Html defList opts items = toList H.dl opts (items ++ [nl opts]) -- | Construct table of contents from list of elements. tableOfContents :: WriterOptions -> [Element] -> State WriterState (Maybe Html) tableOfContents _ [] = return Nothing tableOfContents opts sects = do let opts' = opts { writerIgnoreNotes = True } contents <- mapM (elementToListItem opts') sects let tocList = catMaybes contents return $ if null tocList then Nothing else Just $ unordList opts tocList -- | Convert section number to string showSecNum :: [Int] -> String showSecNum = concat . intersperse "." . map show -- | Converts an Element to a list item for a table of contents, -- retrieving the appropriate identifier from state. elementToListItem :: WriterOptions -> Element -> State WriterState (Maybe Html) elementToListItem opts (Sec lev num (id',classes,_) headerText subsecs) | lev <= writerTOCDepth opts = do let num' = zipWith (+) num (writerNumberOffset opts ++ repeat 0) let sectnum = if writerNumberSections opts && not (null num) && "unnumbered" `notElem` classes then (H.span ! A.class_ "toc-section-number" $ toHtml $ showSecNum num') >> preEscapedString " " else mempty txt <- liftM (sectnum >>) $ inlineListToHtml opts headerText subHeads <- mapM (elementToListItem opts) subsecs >>= return . catMaybes let subList = if null subHeads then mempty else unordList opts subHeads -- in reveal.js, we need #/apples, not #apples: let revealSlash = ['/' | writerSlideVariant opts == RevealJsSlides] return $ Just $ if null id' then (H.a $ toHtml txt) >> subList else (H.a ! A.href (toValue $ "#" ++ revealSlash ++ writerIdentifierPrefix opts ++ id') $ toHtml txt) >> subList elementToListItem _ _ = return Nothing -- | Convert an Element to Html. elementToHtml :: Int -> WriterOptions -> Element -> State WriterState Html elementToHtml _slideLevel opts (Blk block) = blockToHtml opts block elementToHtml slideLevel opts (Sec level num (id',classes,keyvals) title' elements) = do let slide = writerSlideVariant opts /= NoSlides && level <= slideLevel let num' = zipWith (+) num (writerNumberOffset opts ++ repeat 0) modify $ \st -> st{stSecNum = num'} -- update section number -- always use level 1 for slide titles let level' = if slide then 1 else level let titleSlide = slide && level < slideLevel header' <- if title' == [Str "\0"] -- marker for hrule then return mempty 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 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) && not (writerHtml5 opts) ] ++ ["level" ++ show level | slide || writerSectionDivs opts ] ++ classes let secttag = if writerHtml5 opts then H5.section else H.div let attr = (id',classes',keyvals) return $ if titleSlide then (if writerSlideVariant opts == RevealJsSlides then H5.section else id) $ mconcat $ (addAttrs opts attr $ secttag $ header') : innerContents else if writerSectionDivs opts || slide then addAttrs opts attr $ secttag $ inNl $ header' : innerContents else mconcat $ intersperse (nl opts) $ addAttrs opts attr header' : innerContents -- | Convert list of Note blocks to a footnote <div>. -- Assumes notes are sorted. footnoteSection :: WriterOptions -> [Html] -> Html footnoteSection opts notes = if null notes then mempty else nl opts >> (container $ nl opts >> hrtag >> nl opts >> H.ol (mconcat notes >> nl opts) >> nl opts) where container x = if writerHtml5 opts then H5.section ! A.class_ "footnotes" $ x else if writerSlideVariant opts /= NoSlides then H.div ! A.class_ "footnotes slide" $ x else H.div ! A.class_ "footnotes" $ x hrtag = if writerHtml5 opts then H5.hr else H.hr -- | Parse a mailto link; return Just (name, domain) or Nothing. parseMailto :: String -> Maybe (String, String) parseMailto s = do case break (==':') s of (xs,':':addr) | map toLower xs == "mailto" -> do let (name', rest) = span (/='@') addr let domain = drop 1 rest return (name', domain) _ -> fail "not a mailto: URL" -- | Obfuscate a "mailto:" link. obfuscateLink :: WriterOptions -> String -> String -> Html obfuscateLink opts txt s | writerEmailObfuscation opts == NoObfuscation = H.a ! A.href (toValue s) $ toHtml txt obfuscateLink opts txt s = let meth = writerEmailObfuscation opts s' = map toLower (take 7 s) ++ drop 7 s in case parseMailto s' of (Just (name', domain)) -> let domain' = substitute "." " dot " domain at' = obfuscateChar '@' (linkText, altText) = if txt == drop 7 s' -- autolink then ("e", name' ++ " at " ++ domain') else ("'" ++ txt ++ "'", txt ++ " (" ++ name' ++ " at " ++ domain' ++ ")") in case meth of ReferenceObfuscation -> -- need to use preEscapedString or &'s are escaped to & in URL preEscapedString $ "<a href=\"" ++ (obfuscateString s') ++ "\">" ++ (obfuscateString txt) ++ "</a>" JavascriptObfuscation -> (H.script ! A.type_ "text/javascript" $ preEscapedString ("\n<!--\nh='" ++ obfuscateString domain ++ "';a='" ++ at' ++ "';n='" ++ obfuscateString name' ++ "';e=n+a+h;\n" ++ "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\">'+" ++ linkText ++ "+'<\\/'+'a'+'>');\n// -->\n")) >> H.noscript (preEscapedString $ obfuscateString altText) _ -> error $ "Unknown obfuscation method: " ++ show meth _ -> H.a ! A.href (toValue s) $ toHtml txt -- malformed email -- | Obfuscate character as entity. obfuscateChar :: Char -> String obfuscateChar char = let num = ord char numstr = if even num then show num else "x" ++ showHex num "" in "&#" ++ numstr ++ ";" -- | Obfuscate string using entities. obfuscateString :: String -> String obfuscateString = concatMap obfuscateChar . fromEntities addAttrs :: WriterOptions -> Attr -> Html -> Html addAttrs opts attr h = foldl (!) h (attrsToHtml opts attr) attrsToHtml :: WriterOptions -> Attr -> [Attribute] attrsToHtml opts (id',classes',keyvals) = [prefixedId opts id' | not (null id')] ++ [A.class_ (toValue $ unwords classes') | not (null classes')] ++ map (\(x,y) -> customAttribute (fromString x) (toValue y)) keyvals imageExts :: [String] imageExts = [ "art", "bmp", "cdr", "cdt", "cpt", "cr2", "crw", "djvu", "erf", "gif", "ico", "ief", "jng", "jpg", "jpeg", "nef", "orf", "pat", "pbm", "pcx", "pgm", "png", "pnm", "ppm", "psd", "ras", "rgb", "svg", "tiff", "wbmp", "xbm", "xpm", "xwd" ] treatAsImage :: FilePath -> Bool treatAsImage fp = let ext = map toLower $ drop 1 $ takeExtension fp in null ext || ext `elem` imageExts -- | Convert Pandoc block element to HTML. blockToHtml :: WriterOptions -> Block -> State WriterState Html blockToHtml _ Null = return mempty blockToHtml opts (Plain lst) = inlineListToHtml opts lst -- title beginning with fig: indicates that the image is a figure blockToHtml opts (Para [Image txt (s,'f':'i':'g':':':tit)]) = do img <- inlineToHtml opts (Image txt (s,tit)) let tocapt = if writerHtml5 opts then H5.figcaption else H.p ! A.class_ "caption" capt <- if null txt then return mempty else tocapt `fmap` inlineListToHtml opts txt return $ if writerHtml5 opts then H5.figure $ mconcat [nl opts, img, capt, nl opts] else H.div ! A.class_ "figure" $ mconcat [nl opts, img, capt, nl opts] blockToHtml opts (Para lst) = do contents <- inlineListToHtml opts lst return $ H.p contents blockToHtml opts (Div attr@(_,classes,_) bs) = do contents <- blockListToHtml opts bs 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 blockToHtml opts (HorizontalRule) = return $ if writerHtml5 opts then H5.hr else H.hr blockToHtml opts (CodeBlock (id',classes,keyvals) rawCode) = do let tolhs = isEnabled Ext_literate_haskell opts && any (\c -> map toLower c == "haskell") classes && any (\c -> map toLower c == "literate") classes classes' = if tolhs then map (\c -> if map toLower c == "haskell" then "literatehaskell" else c) classes else classes adjCode = if tolhs then unlines . map ("> " ++) . lines $ rawCode else rawCode hlCode = if writerHighlight opts -- check highlighting options then highlight formatHtmlBlock (id',classes',keyvals) adjCode else Nothing case hlCode of Nothing -> return $ addAttrs opts (id',classes,keyvals) $ H.pre $ H.code $ toHtml adjCode Just h -> modify (\st -> st{ stHighlighting = True }) >> return (addAttrs opts (id',[],keyvals) h) blockToHtml opts (BlockQuote blocks) = -- in S5, treat list in blockquote specially -- if default is incremental, make it nonincremental; -- otherwise incremental if writerSlideVariant opts /= NoSlides then let inc = not (writerIncremental opts) in case blocks of [BulletList lst] -> blockToHtml (opts {writerIncremental = inc}) (BulletList lst) [OrderedList attribs lst] -> blockToHtml (opts {writerIncremental = inc}) (OrderedList attribs lst) [DefinitionList lst] -> blockToHtml (opts {writerIncremental = inc}) (DefinitionList lst) _ -> do contents <- blockListToHtml opts blocks return $ H.blockquote $ nl opts >> contents >> nl opts else do contents <- blockListToHtml opts blocks return $ H.blockquote $ nl opts >> contents >> nl opts blockToHtml opts (Header level (ident,_,_) 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'' blockToHtml opts (BulletList lst) = do contents <- mapM (blockListToHtml opts) lst return $ unordList opts contents blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do contents <- mapM (blockListToHtml opts) lst let numstyle' = camelCaseToHyphenated $ show numstyle let attribs = (if startnum /= 1 then [A.start $ toValue startnum] else []) ++ (if numstyle /= DefaultStyle then if writerHtml5 opts then [A.type_ $ case numstyle of Decimal -> "1" LowerAlpha -> "a" UpperAlpha -> "A" LowerRoman -> "i" UpperRoman -> "I" _ -> "1"] else [A.style $ toValue $ "list-style-type: " ++ numstyle'] else []) return $ foldl (!) (ordList opts contents) attribs blockToHtml opts (DefinitionList lst) = do contents <- mapM (\(term, defs) -> do term' <- if null term then return mempty else liftM (H.dt) $ inlineListToHtml opts term defs' <- mapM ((liftM (\x -> H.dd $ (x >> nl opts))) . blockListToHtml opts) defs return $ mconcat $ nl opts : term' : nl opts : intersperse (nl opts) defs') lst return $ defList opts contents blockToHtml opts (Table capt aligns widths headers rows') = do captionDoc <- if null capt then return mempty else do cs <- inlineListToHtml opts capt return $ H.caption cs >> nl opts let percent w = show (truncate (100*w) :: Integer) ++ "%" let coltags = if all (== 0.0) widths then mempty else mconcat $ map (\w -> if writerHtml5 opts then H.col ! A.style (toValue $ "width: " ++ percent w) else H.col ! A.width (toValue $ percent w) >> nl opts) widths head' <- if all null headers then return mempty else do contents <- tableRowToHtml opts aligns 0 headers return $ H.thead (nl opts >> contents) >> nl opts body' <- liftM (\x -> H.tbody (nl opts >> mconcat x)) $ zipWithM (tableRowToHtml opts aligns) [1..] rows' return $ H.table $ nl opts >> captionDoc >> coltags >> head' >> body' >> nl opts tableRowToHtml :: WriterOptions -> [Alignment] -> Int -> [[Block]] -> State WriterState Html tableRowToHtml opts aligns rownum cols' = do let mkcell = if rownum == 0 then H.th else H.td let rowclass = case rownum of 0 -> "header" x | x `rem` 2 == 1 -> "odd" _ -> "even" cols'' <- sequence $ zipWith (\alignment item -> tableItemToHtml opts mkcell alignment item) aligns cols' return $ (H.tr ! A.class_ rowclass $ nl opts >> mconcat cols'') >> nl opts alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center" AlignDefault -> "left" tableItemToHtml :: WriterOptions -> (Html -> Html) -> Alignment -> [Block] -> State WriterState Html tableItemToHtml opts tag' align' item = do contents <- blockListToHtml opts item let alignStr = alignmentToString align' let attribs = if writerHtml5 opts then A.style (toValue $ "text-align: " ++ alignStr ++ ";") else A.align (toValue alignStr) return $ (tag' ! attribs $ contents) >> nl opts toListItems :: WriterOptions -> [Html] -> [Html] toListItems opts items = map (toListItem opts) items ++ [nl opts] toListItem :: WriterOptions -> Html -> Html toListItem opts item = nl opts >> H.li item blockListToHtml :: WriterOptions -> [Block] -> State WriterState Html blockListToHtml opts lst = fmap (mconcat . intersperse (nl opts)) $ mapM (blockToHtml opts) lst -- | Convert list of Pandoc inline elements to HTML. inlineListToHtml :: WriterOptions -> [Inline] -> State WriterState Html inlineListToHtml opts lst = mapM (inlineToHtml opts) lst >>= return . mconcat -- | Convert Pandoc inline element to HTML. inlineToHtml :: WriterOptions -> Inline -> State WriterState Html inlineToHtml opts inline = case inline of (Str str) -> return $ strToHtml str (Space) -> return $ strToHtml " " (LineBreak) -> return $ if writerHtml5 opts then H5.br else H.br (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 Nothing -> return $ addAttrs opts attr $ H.code $ strToHtml str Just h -> do modify $ \st -> st{ stHighlighting = True } return $ addAttrs opts (id',[],keyvals) h where (id',_,keyvals) = attr hlCode = if writerHighlight opts then highlight formatHtmlInline attr str else Nothing (Strikeout lst) -> inlineListToHtml opts lst >>= return . H.del (SmallCaps lst) -> inlineListToHtml opts lst >>= return . (H.span ! A.style "font-variant: small-caps;") (Superscript lst) -> inlineListToHtml opts lst >>= return . H.sup (Subscript lst) -> inlineListToHtml opts lst >>= return . H.sub (Quoted quoteType lst) -> let (leftQuote, rightQuote) = case quoteType of SingleQuote -> (strToHtml "‘", strToHtml "’") DoubleQuote -> (strToHtml "“", strToHtml "”") in if writerHtmlQTags opts then do modify $ \st -> st{ stQuotes = True } H.q `fmap` inlineListToHtml opts lst else (\x -> leftQuote >> x >> rightQuote) `fmap` inlineListToHtml opts lst (Math t str) -> modify (\st -> st {stMath = True}) >> (case writerHTMLMathMethod opts of LaTeXMathML _ -> -- putting LaTeXMathML in container with class "LaTeX" prevents -- non-math elements on the page from being treated as math by -- the javascript return $ H.span ! A.class_ "LaTeX" $ case t of InlineMath -> toHtml ("$" ++ str ++ "$") DisplayMath -> toHtml ("$$" ++ str ++ "$$") JsMath _ -> do let m = preEscapedString str return $ case t of InlineMath -> H.span ! A.class_ "math" $ m DisplayMath -> H.div ! A.class_ "math" $ m WebTeX url -> do let imtag = if writerHtml5 opts then H5.img else H.img let m = imtag ! A.style "vertical-align:middle" ! A.src (toValue $ url ++ urlEncode str) ! A.alt (toValue str) ! A.title (toValue str) let brtag = if writerHtml5 opts then H5.br else H.br return $ case t of InlineMath -> m DisplayMath -> brtag >> m >> brtag GladTeX -> return $ case t of InlineMath -> preEscapedString $ "<EQ ENV=\"math\">" ++ str ++ "</EQ>" DisplayMath -> preEscapedString $ "<EQ ENV=\"displaymath\">" ++ str ++ "</EQ>" MathML _ -> do let dt = if t == InlineMath then DisplayInline else DisplayBlock let conf = useShortEmptyTags (const False) defaultConfigPP case texMathToMathML dt str of Right r -> return $ preEscapedString $ ppcElement conf r Left _ -> inlineListToHtml opts (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' 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 InlineMath -> m DisplayMath -> brtag >> m >> brtag ) (RawInline f str) | f == Format "latex" -> case writerHTMLMathMethod opts of LaTeXMathML _ -> do modify (\st -> st {stMath = True}) return $ toHtml str _ -> return mempty | f == Format "html" -> return $ preEscapedString str | otherwise -> return mempty (Link [Str str] (s,_)) | "mailto:" `isPrefixOf` s && s == escapeURI ("mailto" ++ str) -> -- autolink return $ obfuscateLink opts str s (Link txt (s,_)) | "mailto:" `isPrefixOf` s -> do linkText <- inlineListToHtml opts txt return $ obfuscateLink opts (renderHtml linkText) s (Link txt (s,tit)) -> do linkText <- inlineListToHtml opts txt let s' = case s of '#':xs | writerSlideVariant opts == RevealJsSlides -> '#':'/':xs _ -> s let link = H.a ! A.href (toValue s') $ linkText return $ if null tit then link else link ! A.title (toValue tit) (Image txt (s,tit)) | treatAsImage s -> do let alternate' = stringify txt let attributes = [A.src $ toValue s] ++ (if null tit then [] else [A.title $ toValue tit]) ++ if null txt then [] else [A.alt $ toValue alternate'] let tag = if writerHtml5 opts then H5.img else H.img return $ foldl (!) tag attributes -- note: null title included, as in Markdown.pl (Image _ (s,tit)) -> do let attributes = [A.src $ toValue s] ++ (if null tit then [] else [A.title $ toValue tit]) return $ foldl (!) H5.embed attributes -- note: null title included, as in Markdown.pl (Note contents) -> do st <- get let notes = stNotes st let number = (length notes) + 1 let ref = show number htmlContents <- blockListToNote opts ref contents -- push contents onto front of notes put $ st {stNotes = (htmlContents:notes)} let revealSlash = ['/' | writerSlideVariant opts == RevealJsSlides] let link = H.a ! A.href (toValue $ "#" ++ revealSlash ++ writerIdentifierPrefix opts ++ "fn" ++ ref) ! A.class_ "footnoteRef" ! prefixedId opts ("fnref" ++ ref) $ H.sup $ toHtml ref 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 return $ if writerHtml5 opts then result ! customAttribute "data-cites" (toValue citationIds) else result blockListToNote :: WriterOptions -> String -> [Block] -> State WriterState Html blockListToNote opts ref blocks = -- If last block is Para or Plain, include the backlink at the end of -- that block. Otherwise, insert a new Plain block with the backlink. let backlink = [Link [Str "↩"] ("#" ++ writerIdentifierPrefix opts ++ "fnref" ++ ref,[])] blocks' = if null blocks then [] else let lastBlock = last blocks otherBlocks = init blocks in case lastBlock of (Para lst) -> otherBlocks ++ [Para (lst ++ backlink)] (Plain lst) -> otherBlocks ++ [Plain (lst ++ backlink)] _ -> otherBlocks ++ [lastBlock, Plain backlink] in do contents <- blockListToHtml opts blocks' let noteItem = H.li ! (prefixedId opts ("fn" ++ ref)) $ contents let noteItem' = case writerEpubVersion opts of Just EPUB3 -> noteItem ! customAttribute "epub:type" "footnote" _ -> noteItem return $ nl opts >> noteItem' ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/LaTeX.hs����������������������������������������������������000644 �000765 �000024 �00000107214 12251233602 021010� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-} {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.LaTeX Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' format into LaTeX. -} module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where import Text.Pandoc.Definition import Text.Pandoc.Walk import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Templates import Text.Printf ( printf ) import Network.URI ( isURI, unEscapeString ) import Data.List ( (\\), isSuffixOf, isInfixOf, isPrefixOf, intercalate, intersperse ) import Data.Char ( toLower, isPunctuation, isAscii, isLetter, isDigit, ord ) import Control.Applicative ((<|>)) import Control.Monad.State import Text.Pandoc.Pretty import Text.Pandoc.Slides import Text.Pandoc.Highlighting (highlight, styleToLaTeX, formatLaTeXInline, formatLaTeXBlock, toListingsLanguage) data WriterState = WriterState { stInNote :: Bool -- true if we're in a note , 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 , stTable :: Bool -- true if document has a table , stStrikeout :: Bool -- true if document has strikeout , stUrl :: Bool -- true if document has visible URL link , stGraphics :: Bool -- true if document contains images , stLHS :: Bool -- true if document has literate haskell code , stBook :: Bool -- true if document uses book or memoir class , stCsquotes :: Bool -- true if document uses csquotes , stHighlighting :: Bool -- true if document has highlighted code , stIncremental :: Bool -- true if beamer lists should be displayed bit by bit , stInternalLinks :: [String] -- list of internal link targets , stUsesEuro :: Bool -- true if euro symbol used } -- | Convert Pandoc to LaTeX. writeLaTeX :: WriterOptions -> Pandoc -> String writeLaTeX options document = evalState (pandocToLaTeX options document) $ WriterState { stInNote = False, stOLLevel = 1, stOptions = options, stVerbInNote = False, stTable = False, stStrikeout = False, stUrl = False, stGraphics = False, stLHS = False, stBook = writerChapters options, stCsquotes = False, stHighlighting = False, stIncremental = writerIncremental options, stInternalLinks = [], stUsesEuro = False } 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' } let template = writerTemplate options -- set stBook depending on documentclass let bookClasses = ["memoir","book","report","scrreprt","scrbook"] case lookup "documentclass" (writerVariables options) of Just x | x `elem` bookClasses -> modify $ \s -> s{stBook = True} | otherwise -> return () Nothing | any (\x -> "\\documentclass" `isPrefixOf` x && (any (`isSuffixOf` x) bookClasses)) (lines template) -> modify $ \s -> s{stBook = True} | otherwise -> return () -- check for \usepackage...{csquotes}; if present, we'll use -- \enquote{...} for smart quotes: when ("{csquotes}" `isInfixOf` template) $ modify $ \s -> s{stCsquotes = True} let colwidth = if writerWrapText options then Just $ writerColumns options else Nothing metadata <- metaToJSON options (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''' (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" titleMeta $ defField "author-meta" (intercalate "; " authorsMeta) $ defField "documentclass" (if writerBeamer options then ("beamer" :: String) else if writerChapters options then "book" else "article") $ defField "verbatim-in-note" (stVerbInNote st) $ defField "tables" (stTable st) $ defField "strikeout" (stStrikeout st) $ defField "url" (stUrl st) $ defField "numbersections" (writerNumberSections options) $ defField "lhs" (stLHS st) $ defField "graphics" (stGraphics st) $ defField "book-class" (stBook st) $ defField "euro" (stUsesEuro st) $ defField "listings" (writerListings options || stLHS st) $ defField "beamer" (writerBeamer options) $ defField "mainlang" (maybe "" (reverse . takeWhile (/=',') . reverse) (lookup "lang" $ writerVariables options)) $ (if stHighlighting st then defField "highlighting-macros" (styleToLaTeX $ writerHighlightStyle options ) else id) $ (case writerCiteMethod options of Natbib -> defField "biblio-title" biblioTitle . defField "natbib" True Biblatex -> defField "biblio-title" biblioTitle . defField "biblatex" True _ -> id) $ metadata return $ if writerStandalone options then renderTemplate' template context else main -- | Convert Elements to LaTeX elementToLaTeX :: WriterOptions -> Element -> State WriterState Doc elementToLaTeX _ (Blk block) = blockToLaTeX block elementToLaTeX opts (Sec level _ (id',classes,_) title' elements) = do header' <- sectionHeader ("unnumbered" `elem` classes) id' level title' innerContents <- mapM (elementToLaTeX opts) elements return $ vsep (header' : innerContents) data StringContext = TextString | URLString | CodeString deriving (Eq) -- escape things as needed for LaTeX stringToLaTeX :: StringContext -> String -> State WriterState String stringToLaTeX _ [] = return "" stringToLaTeX ctx (x:xs) = do opts <- gets stOptions rest <- stringToLaTeX ctx xs let ligatures = writerTeXLigatures opts && not (ctx == CodeString) let isUrl = ctx == URLString when (x == '€') $ modify $ \st -> st{ stUsesEuro = True } return $ case x of '€' -> "\\euro{}" ++ rest '{' -> "\\{" ++ rest '}' -> "\\}" ++ rest '$' -> "\\$" ++ rest '%' -> "\\%" ++ rest '&' -> "\\&" ++ rest '_' | not isUrl -> "\\_" ++ rest '#' -> "\\#" ++ rest '-' -> case xs of -- prevent adjacent hyphens from forming ligatures ('-':_) -> "-{}" ++ rest _ -> '-' : rest '~' | not isUrl -> "\\textasciitilde{}" ++ rest '^' -> "\\^{}" ++ rest '\\'| isUrl -> '/' : rest -- NB. / works as path sep even on Windows | otherwise -> "\\textbackslash{}" ++ rest '|' -> "\\textbar{}" ++ rest '<' -> "\\textless{}" ++ rest '>' -> "\\textgreater{}" ++ rest '[' -> "{[}" ++ rest -- to avoid interpretation as ']' -> "{]}" ++ rest -- optional arguments '\160' -> "~" ++ rest '\x2026' -> "\\ldots{}" ++ rest '\x2018' | ligatures -> "`" ++ rest '\x2019' | ligatures -> "'" ++ rest '\x201C' | ligatures -> "``" ++ rest '\x201D' | ligatures -> "''" ++ rest '\x2014' | ligatures -> "---" ++ rest '\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 toSlides :: [Block] -> State WriterState [Block] toSlides bs = do opts <- gets stOptions let slideLevel = maybe (getSlideLevel bs) id $ writerSlideLevel opts let bs' = prepSlides slideLevel bs concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs') elementToBeamer :: Int -> Element -> State WriterState [Block] elementToBeamer _slideLevel (Blk b) = return [b] elementToBeamer slideLevel (Sec lvl _num (ident,classes,kvs) tit elts) | lvl > slideLevel = do bs <- concat `fmap` mapM (elementToBeamer slideLevel) elts return $ Para ( RawInline "latex" "\\begin{block}{" : tit ++ [RawInline "latex" "}"] ) : bs ++ [RawBlock "latex" "\\end{block}"] | lvl < slideLevel = do bs <- concat `fmap` mapM (elementToBeamer slideLevel) elts return $ (Header lvl (ident,classes,kvs) tit) : bs | otherwise = do -- lvl == slideLevel -- note: [fragile] is required or verbatim breaks let hasCodeBlock (CodeBlock _ _) = [True] hasCodeBlock _ = [] let hasCode (Code _ _) = [True] hasCode _ = [] opts <- gets stOptions let fragile = not $ null $ query hasCodeBlock elts ++ if writerListings opts then query hasCode elts else [] let allowframebreaks = "allowframebreaks" `elem` classes let optionslist = ["fragile" | fragile] ++ ["allowframebreaks" | allowframebreaks] let options = if null optionslist then "" else "[" ++ intercalate "," optionslist ++ "]" let slideStart = Para $ RawInline "latex" ("\\begin{frame}" ++ options) : if tit == [Str "\0"] -- marker for hrule then [] else (RawInline "latex" "{") : tit ++ [RawInline "latex" "}"] let slideEnd = RawBlock "latex" "\\end{frame}" -- now carve up slide into blocks if there are sections inside bs <- concat `fmap` mapM (elementToBeamer slideLevel) elts return $ slideStart : bs ++ [slideEnd] isListBlock :: Block -> Bool isListBlock (BulletList _) = True isListBlock (OrderedList _ _) = True isListBlock (DefinitionList _) = True isListBlock _ = False isLineBreakOrSpace :: Inline -> Bool isLineBreakOrSpace LineBreak = True isLineBreakOrSpace Space = True isLineBreakOrSpace _ = False -- | Convert Pandoc block element to LaTeX. blockToLaTeX :: Block -- ^ Block to convert -> State WriterState Doc blockToLaTeX Null = return empty 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 blockToLaTeX (Para [Image txt (src,'f':'i':'g':':':tit)]) = do capt <- if null txt then return empty else (\c -> "\\caption" <> braces c) `fmap` inlineListToLaTeX txt img <- inlineToLaTeX (Image txt (src,tit)) return $ "\\begin{figure}[htbp]" $$ "\\centering" $$ img $$ capt $$ "\\end{figure}" -- . . . indicates pause in beamer slides blockToLaTeX (Para [Str ".",Space,Str ".",Space,Str "."]) = do beamer <- writerBeamer `fmap` gets stOptions if beamer then blockToLaTeX (RawBlock "latex" "\\pause") else inlineListToLaTeX [Str ".",Space,Str ".",Space,Str "."] blockToLaTeX (Para lst) = inlineListToLaTeX $ dropWhile isLineBreakOrSpace lst blockToLaTeX (BlockQuote lst) = do beamer <- writerBeamer `fmap` gets stOptions case lst of [b] | beamer && isListBlock b -> do oldIncremental <- gets stIncremental modify $ \s -> s{ stIncremental = not oldIncremental } result <- blockToLaTeX b modify $ \s -> s{ stIncremental = oldIncremental } return result _ -> do contents <- blockListToLaTeX lst return $ "\\begin{quote}" $$ contents $$ "\\end{quote}" blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do opts <- gets stOptions case () of _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes && "literate" `elem` classes -> lhsCodeBlock | writerListings opts -> listingsCodeBlock | writerHighlight opts && not (null classes) -> highlightedCodeBlock | otherwise -> rawCodeBlock 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 (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 (linkAnchor $$ text ("\\begin{" ++ env ++ "}") $$ text str $$ text ("\\end{" ++ env ++ "}")) <> cr listingsCodeBlock = do st <- get let params = if writerListings (stOptions st) then (case getListingsLanguage classes of Just l -> [ "language=" ++ l ] Nothing -> []) ++ [ "numbers=left" | "numberLines" `elem` classes || "number" `elem` classes || "number-lines" `elem` classes ] ++ [ (if key == "startFrom" then "firstnumber" else key) ++ "=" ++ attr | (key,attr) <- keyvalAttr ] ++ (if identifier == "" then [] else [ "label=" ++ toLabel identifier ]) else [] printParams | null params = empty | otherwise = brackets $ hcat (intersperse ", " (map text params)) return $ flush ("\\begin{lstlisting}" <> printParams $$ text str $$ "\\end{lstlisting}") $$ cr highlightedCodeBlock = case highlight formatLaTeXBlock ("",classes,keyvalAttr) str of Nothing -> rawCodeBlock Just h -> modify (\st -> st{ stHighlighting = True }) >> return (flush $ linkAnchor $$ text h) blockToLaTeX (RawBlock f x) | f == Format "latex" || f == Format "tex" = return $ text x | otherwise = return empty blockToLaTeX (BulletList []) = return empty -- otherwise latex error blockToLaTeX (BulletList lst) = do incremental <- gets stIncremental let inc = if incremental then "[<+->]" else "" items <- mapM listItemToLaTeX lst let spacing = if isTightList lst then text "\\itemsep1pt\\parskip0pt\\parsep0pt" else empty return $ text ("\\begin{itemize}" ++ inc) $$ spacing $$ vcat items $$ "\\end{itemize}" blockToLaTeX (OrderedList _ []) = return empty -- otherwise latex error blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do st <- get let inc = if stIncremental st then "[<+->]" else "" let oldlevel = stOLLevel st put $ st {stOLLevel = oldlevel + 1} items <- mapM listItemToLaTeX lst modify (\s -> s {stOLLevel = oldlevel}) let tostyle x = case numstyle of Decimal -> "\\arabic" <> braces x UpperRoman -> "\\Roman" <> braces x LowerRoman -> "\\roman" <> braces x UpperAlpha -> "\\Alph" <> braces x LowerAlpha -> "\\alph" <> braces x Example -> "\\arabic" <> braces x DefaultStyle -> "\\arabic" <> braces x let todelim x = case numdelim of OneParen -> x <> ")" TwoParens -> parens x Period -> x <> "." _ -> x <> "." let enum = text $ "enum" ++ map toLower (toRomanNumeral oldlevel) let stylecommand = if numstyle == DefaultStyle && numdelim == DefaultDelim then empty else "\\def" <> "\\label" <> enum <> braces (todelim $ tostyle enum) let resetcounter = if start == 1 || oldlevel > 4 then empty else "\\setcounter" <> braces enum <> braces (text $ show $ start - 1) let spacing = if isTightList lst then text "\\itemsep1pt\\parskip0pt\\parsep0pt" else empty return $ text ("\\begin{enumerate}" ++ inc) $$ stylecommand $$ resetcounter $$ spacing $$ vcat items $$ "\\end{enumerate}" blockToLaTeX (DefinitionList []) = return empty 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) then text "\\itemsep1pt\\parskip0pt\\parsep0pt" else empty return $ text ("\\begin{description}" ++ inc) $$ spacing $$ vcat items $$ "\\end{description}" blockToLaTeX HorizontalRule = return $ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}" blockToLaTeX (Header level (id',classes,_) lst) = sectionHeader ("unnumbered" `elem` classes) id' level lst blockToLaTeX (Table caption aligns widths heads rows) = do headers <- if all null heads then return empty else ($$ "\\midrule\\endhead") `fmap` (tableRowToLaTeX True aligns widths) heads captionText <- inlineListToLaTeX caption let capt = if isEmpty captionText then empty else text "\\addlinespace" $$ text "\\caption" <> braces captionText rows' <- mapM (tableRowToLaTeX False aligns widths) rows let colDescriptors = text $ concat $ map toColDescriptor aligns modify $ \s -> s{ stTable = True } return $ "\\begin{longtable}[c]" <> braces ("@{}" <> colDescriptors <> "@{}") -- the @{} removes extra space at beginning and end $$ "\\toprule\\addlinespace" $$ headers $$ vcat rows' $$ "\\bottomrule" $$ capt $$ "\\end{longtable}" toColDescriptor :: Alignment -> String toColDescriptor align = case align of AlignLeft -> "l" AlignRight -> "r" AlignCenter -> "c" AlignDefault -> "l" blockListToLaTeX :: [Block] -> State WriterState Doc blockListToLaTeX lst = vsep `fmap` mapM blockToLaTeX lst tableRowToLaTeX :: Bool -> [Alignment] -> [Double] -> [[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) $$ "\\\\\\addlinespace" listItemToLaTeX :: [Block] -> State WriterState Doc listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item" $$) . (nest 2) 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' -- | Craft the section header, inserting the secton reference, if supplied. sectionHeader :: Bool -- True for unnumbered -> [Char] -> Int -> [Inline] -> State WriterState Doc sectionHeader unnumbered ref level lst = do txt <- inlineListToLaTeX lst let noNote (Note _) = Str "" noNote x = x let lstNoNotes = walk noNote lst txtNoNotes <- inlineListToLaTeX lstNoNotes let star = if unnumbered then text "*" else empty -- footnotes in sections don't work (except for starred variants) -- unless you specify an optional argument: -- \section[mysec]{mysec\footnote{blah}} optional <- if unnumbered || lstNoNotes == lst then return empty else do return $ brackets txtNoNotes let stuffing = star <> optional <> braces txt book <- gets stBook opts <- gets stOptions let level' = if book || writerChapters opts then level - 1 else level internalLinks <- gets stInternalLinks let refLabel x = (if ref `elem` internalLinks then text "\\hyperdef" <> braces empty <> 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 $ toLabel r) let sectionType = case level' of 0 | writerBeamer opts -> "part" | otherwise -> "chapter" 1 -> "section" 2 -> "subsection" 3 -> "subsubsection" 4 -> "paragraph" 5 -> "subparagraph" _ -> "" return $ if level' > 5 then txt else headerWith ('\\':sectionType) stuffing ref $$ if unnumbered then "\\addcontentsline{toc}" <> braces (text sectionType) <> braces txtNoNotes else empty -- | Convert list of inline elements to LaTeX. inlineListToLaTeX :: [Inline] -- ^ Inlines to convert -> State WriterState Doc inlineListToLaTeX lst = mapM inlineToLaTeX (fixLineInitialSpaces lst) >>= return . hcat -- nonbreaking spaces (~) in LaTeX don't work after line breaks, -- so we turn nbsps after hard breaks to \hspace commands. -- this is mostly used in verse. where fixLineInitialSpaces [] = [] fixLineInitialSpaces (LineBreak : Str s@('\160':_) : xs) = LineBreak : fixNbsps s ++ fixLineInitialSpaces xs fixLineInitialSpaces (x:xs) = x : fixLineInitialSpaces xs fixNbsps s = let (ys,zs) = span (=='\160') s in replicate (length ys) hspace ++ [Str zs] hspace = RawInline "latex" "\\hspace*{0.333em}" isQuoted :: Inline -> Bool isQuoted (Quoted _ _) = True isQuoted _ = False -- | Convert inline element to LaTeX inlineToLaTeX :: Inline -- ^ Inline to convert -> State WriterState Doc 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) = inlineListToLaTeX lst >>= return . inCmd "textbf" inlineToLaTeX (Strikeout lst) = do contents <- inlineListToLaTeX lst modify $ \s -> s{ stStrikeout = True } return $ inCmd "sout" contents inlineToLaTeX (Superscript lst) = inlineListToLaTeX lst >>= return . inCmd "textsuperscript" inlineToLaTeX (Subscript lst) = do inlineListToLaTeX lst >>= return . inCmd "textsubscript" inlineToLaTeX (SmallCaps lst) = inlineListToLaTeX lst >>= return . inCmd "textsc" inlineToLaTeX (Cite cits lst) = do st <- get let opts = stOptions st case writerCiteMethod opts of Natbib -> citationsToNatbib cits Biblatex -> citationsToBiblatex cits _ -> inlineListToLaTeX lst inlineToLaTeX (Code (_,classes,_) str) = do opts <- gets stOptions case () of _ | writerListings opts -> listingsCode | writerHighlight opts && not (null classes) -> highlightCode | otherwise -> rawCode where listingsCode = do inNote <- gets stInNote when inNote $ modify $ \s -> s{ stVerbInNote = True } let chr = ((enumFromTo '!' '~') \\ str) !! 0 return $ text $ "\\lstinline" ++ [chr] ++ str ++ [chr] highlightCode = do case highlight formatLaTeXInline ("",classes,[]) str of Nothing -> rawCode Just h -> modify (\st -> st{ stHighlighting = True }) >> return (text h) rawCode = liftM (text . (\s -> "\\texttt{" ++ s ++ "}")) $ stringToLaTeX CodeString str inlineToLaTeX (Quoted qt lst) = do contents <- inlineListToLaTeX lst csquotes <- liftM stCsquotes get opts <- gets stOptions if csquotes then return $ "\\enquote" <> braces contents else do let s1 = if (not (null lst)) && (isQuoted (head lst)) then "\\," else empty let s2 = if (not (null lst)) && (isQuoted (last lst)) then "\\," else empty let inner = s1 <> contents <> s2 return $ case qt of DoubleQuote -> if writerTeXLigatures opts then text "``" <> inner <> text "''" else char '\x201C' <> inner <> char '\x201D' SingleQuote -> if writerTeXLigatures opts then char '`' <> inner <> char '\'' else char '\x2018' <> inner <> char '\x2019' inlineToLaTeX (Str str) = liftM text $ stringToLaTeX TextString str inlineToLaTeX (Math InlineMath str) = return $ char '$' <> text str <> char '$' inlineToLaTeX (Math DisplayMath str) = return $ "\\[" <> text str <> "\\]" inlineToLaTeX (RawInline f str) | f == Format "latex" || f == Format "tex" = return $ text str | otherwise = return empty inlineToLaTeX (LineBreak) = return "\\\\" inlineToLaTeX Space = return space inlineToLaTeX (Link txt ('#':ident, _)) = do contents <- inlineListToLaTeX txt ident' <- stringToLaTeX URLString ident return $ text "\\hyperref" <> brackets (text $ toLabel ident') <> braces contents inlineToLaTeX (Link txt (src, _)) = case txt of [Str x] | x == src -> -- autolink do modify $ \s -> s{ stUrl = True } src' <- stringToLaTeX URLString x return $ text $ "\\url{" ++ src' ++ "}" _ -> do contents <- inlineListToLaTeX txt src' <- stringToLaTeX URLString src return $ text ("\\href{" ++ src' ++ "}{") <> contents <> char '}' inlineToLaTeX (Image _ (source, _)) = do modify $ \s -> s{ stGraphics = True } let source' = if isURI source then source else unEscapeString source source'' <- stringToLaTeX URLString source' return $ "\\includegraphics" <> braces (text source'') inlineToLaTeX (Note contents) = do 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 citationsToNatbib :: [Citation] -> State WriterState Doc citationsToNatbib (one:[]) = citeCommand c p s k where Citation { citationId = k , citationPrefix = p , citationSuffix = s , citationMode = m } = one c = case m of AuthorInText -> "citet" SuppressAuthor -> "citeyearpar" NormalCitation -> "citep" 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) p = citationPrefix $ head $ cits s = citationSuffix $ last $ cits ks = intercalate ", " $ map citationId cits citationsToNatbib (c:cs) | citationMode c == AuthorInText = do author <- citeCommand "citeauthor" [] [] (citationId c) cits <- citationsToNatbib (c { citationMode = SuppressAuthor } : cs) return $ author <+> cits citationsToNatbib cits = do cits' <- mapM convertOne cits return $ text "\\citetext{" <> foldl combineTwo empty cits' <> text "}" where combineTwo a b | isEmpty a = b | otherwise = a <> text "; " <> b convertOne Citation { citationId = k , citationPrefix = p , citationSuffix = s , citationMode = m } = case m of AuthorInText -> citeCommand "citealt" p s k SuppressAuthor -> citeCommand "citeyear" p s k NormalCitation -> citeCommand "citealp" p s k citeCommand :: String -> [Inline] -> [Inline] -> String -> State WriterState Doc citeCommand c p s k = do args <- citeArguments p s k return $ text ("\\" ++ c) <> args citeArguments :: [Inline] -> [Inline] -> String -> State WriterState Doc citeArguments p s k = do let s' = case s of (Str (x:[]) : r) | isPunctuation x -> dropWhile (== Space) r (Str (x:xs) : r) | isPunctuation x -> Str xs : r _ -> s pdoc <- inlineListToLaTeX p sdoc <- inlineListToLaTeX s' let optargs = case (isEmpty pdoc, isEmpty sdoc) of (True, True ) -> empty (True, False) -> brackets sdoc (_ , _ ) -> brackets pdoc <> brackets sdoc return $ optargs <> braces (text k) citationsToBiblatex :: [Citation] -> State WriterState Doc citationsToBiblatex (one:[]) = citeCommand cmd p s k where Citation { citationId = k , citationPrefix = p , citationSuffix = s , citationMode = m } = one cmd = case m of SuppressAuthor -> "autocite*" AuthorInText -> "textcite" NormalCitation -> "autocite" citationsToBiblatex (c:cs) = do args <- mapM convertOne (c:cs) return $ text cmd <> foldl (<>) empty args where cmd = case citationMode c of AuthorInText -> "\\textcites" _ -> "\\autocites" convertOne Citation { citationId = k , citationPrefix = p , citationSuffix = s } = citeArguments p s k citationsToBiblatex _ = return empty -- Determine listings language from list of class attributes. getListingsLanguage :: [String] -> Maybe String getListingsLanguage [] = Nothing getListingsLanguage (x:xs) = toListingsLanguage x <|> getListingsLanguage xs ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Man.hs������������������������������������������������������000644 �000765 �000024 �00000036112 12251233602 020544� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2007-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Man Copyright : Copyright (C) 2007-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to groff man page format. -} module Text.Pandoc.Writers.Man ( writeMan) where import Text.Pandoc.Definition import Text.Pandoc.Templates import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Readers.TeXMath import Text.Printf ( printf ) import Data.List ( isPrefixOf, intersperse, intercalate ) import Text.Pandoc.Pretty import Text.Pandoc.Builder (deleteMeta) import Control.Monad.State import Data.Char ( isDigit ) type Notes = [[Block]] data WriterState = WriterState { stNotes :: Notes , stHasTables :: Bool } -- | Convert Pandoc to Man. writeMan :: WriterOptions -> Pandoc -> String writeMan opts document = evalState (pandocToMan opts document) (WriterState [] False) -- | Return groff man representation of document. pandocToMan :: WriterOptions -> Pandoc -> State WriterState String pandocToMan opts (Pandoc meta blocks) = do let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing let render' = render colwidth titleText <- inlineListToMan opts $ docTitle meta let title' = render' titleText let setFieldsFromTitle = case break (== ' ') title' of (cmdName, rest) -> case reverse cmdName of (')':d:'(':xs) | isDigit d -> defField "title" (reverse xs) . defField "section" [d] . case splitBy (=='|') rest of (ft:hds) -> defField "footer" (trim ft) . defField "header" (trim $ concat hds) [] -> id _ -> defField "title" title' metadata <- metaToJSON opts (fmap (render colwidth) . blockListToMan opts) (fmap (render colwidth) . inlineListToMan opts) $ deleteMeta "title" meta body <- blockListToMan opts blocks notes <- liftM stNotes get notes' <- notesToMan opts (reverse notes) let main = render' $ body $$ notes' $$ text "" hasTables <- liftM stHasTables get let context = defField "body" main $ setFieldsFromTitle $ defField "has-tables" hasTables $ metadata if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main -- | Return man representation of notes. notesToMan :: WriterOptions -> [[Block]] -> State WriterState Doc notesToMan opts notes = if null notes then return empty else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>= return . (text ".SH NOTES" $$) . vcat -- | Return man representation of a note. noteToMan :: WriterOptions -> Int -> [Block] -> State WriterState Doc noteToMan opts num note = do contents <- blockListToMan opts note let marker = cr <> text ".SS " <> brackets (text (show num)) return $ marker $$ contents -- | Association list of characters to escape. manEscapes :: [(Char, String)] manEscapes = [ ('\160', "\\ ") , ('\'', "\\[aq]") , ('’', "'") , ('\x2014', "\\[em]") , ('\x2013', "\\[en]") , ('\x2026', "\\&...") ] ++ backslashEscapes "-@\\" -- | Escape special characters for Man. escapeString :: String -> String escapeString = escapeStringUsing manEscapes -- | Escape a literal (code) section for Man. escapeCode :: String -> String escapeCode = concat . intersperse "\n" . map escapeLine . lines where escapeLine codeline = case escapeStringUsing (manEscapes ++ backslashEscapes "\t ") codeline of a@('.':_) -> "\\&" ++ a b -> b -- We split inline lists into sentences, and print one sentence per -- line. groff/troff treats the line-ending period differently. -- See http://code.google.com/p/pandoc/issues/detail?id=148. -- | Returns the first sentence in a list of inlines, and the rest. breakSentence :: [Inline] -> ([Inline], [Inline]) breakSentence [] = ([],[]) breakSentence xs = let isSentenceEndInline (Str ys@(_:_)) | last ys == '.' = True isSentenceEndInline (Str ys@(_:_)) | last ys == '?' = True isSentenceEndInline (LineBreak) = True isSentenceEndInline _ = False (as, bs) = break isSentenceEndInline xs in case bs of [] -> (as, []) [c] -> (as ++ [c], []) (c:Space:cs) -> (as ++ [c], cs) (Str ".":Str (')':ys):cs) -> (as ++ [Str ".", Str (')':ys)], cs) (x@(Str ('.':')':_)):cs) -> (as ++ [x], cs) (LineBreak:x@(Str ('.':_)):cs) -> (as ++[LineBreak], x:cs) (c:cs) -> (as ++ [c] ++ ds, es) where (ds, es) = breakSentence cs -- | Split a list of inlines into sentences. splitSentences :: [Inline] -> [[Inline]] splitSentences xs = let (sent, rest) = breakSentence xs in if null rest then [sent] else sent : splitSentences rest -- | Convert Pandoc block element to man. blockToMan :: WriterOptions -- ^ Options -> Block -- ^ Block element -> State WriterState Doc blockToMan _ Null = return empty blockToMan opts (Div _ bs) = blockListToMan opts bs blockToMan opts (Plain inlines) = liftM vcat $ mapM (inlineListToMan opts) $ splitSentences inlines blockToMan opts (Para inlines) = do contents <- liftM vcat $ mapM (inlineListToMan opts) $ splitSentences inlines return $ text ".PP" $$ contents blockToMan _ (RawBlock f str) | f == Format "man" = return $ text str | otherwise = return empty blockToMan _ HorizontalRule = return $ text ".PP" $$ text " * * * * *" blockToMan opts (Header level _ inlines) = do contents <- inlineListToMan opts inlines let heading = case level of 1 -> ".SH " _ -> ".SS " return $ text heading <> contents blockToMan _ (CodeBlock _ str) = return $ text ".IP" $$ text ".nf" $$ text "\\f[C]" $$ text (escapeCode str) $$ text "\\f[]" $$ text ".fi" blockToMan opts (BlockQuote blocks) = do contents <- blockListToMan opts blocks return $ text ".RS" $$ contents $$ text ".RE" blockToMan opts (Table caption alignments widths headers rows) = let aligncode AlignLeft = "l" aligncode AlignRight = "r" aligncode AlignCenter = "c" aligncode AlignDefault = "l" in do caption' <- inlineListToMan opts caption modify $ \st -> st{ stHasTables = True } let iwidths = if all (== 0) widths then repeat "" else map (printf "w(%0.1fn)" . (70 *)) widths -- 78n default width - 8n indent = 70n let coldescriptions = text $ intercalate " " (zipWith (\align width -> aligncode align ++ width) alignments iwidths) ++ "." colheadings <- mapM (blockListToMan opts) headers let makeRow cols = text "T{" $$ (vcat $ intersperse (text "T}@T{") cols) $$ text "T}" let colheadings' = if all null headers then empty else makeRow colheadings $$ char '_' body <- mapM (\row -> do cols <- mapM (blockListToMan opts) row return $ makeRow cols) rows return $ text ".PP" $$ caption' $$ text ".TS" $$ text "tab(@);" $$ coldescriptions $$ colheadings' $$ vcat body $$ text ".TE" blockToMan opts (BulletList items) = do contents <- mapM (bulletListItemToMan opts) items return (vcat contents) blockToMan opts (OrderedList attribs items) = do let markers = take (length items) $ orderedListMarkers attribs let indent = 1 + (maximum $ map length markers) contents <- mapM (\(num, item) -> orderedListItemToMan opts num indent item) $ zip markers items return (vcat contents) blockToMan opts (DefinitionList items) = do contents <- mapM (definitionListItemToMan opts) items return (vcat contents) -- | Convert bullet list item (list of blocks) to man. bulletListItemToMan :: WriterOptions -> [Block] -> State WriterState Doc bulletListItemToMan _ [] = return empty bulletListItemToMan opts ((Para first):rest) = bulletListItemToMan opts ((Plain first):rest) bulletListItemToMan opts ((Plain first):rest) = do first' <- blockToMan opts (Plain first) rest' <- blockListToMan opts rest let first'' = text ".IP \\[bu] 2" $$ first' let rest'' = if null rest then empty else text ".RS 2" $$ rest' $$ text ".RE" return (first'' $$ rest'') bulletListItemToMan opts (first:rest) = do first' <- blockToMan opts first rest' <- blockListToMan opts rest return $ text "\\[bu] .RS 2" $$ first' $$ rest' $$ text ".RE" -- | Convert ordered list item (a list of blocks) to man. orderedListItemToMan :: WriterOptions -- ^ options -> String -- ^ order marker for list item -> Int -- ^ number of spaces to indent -> [Block] -- ^ list item (list of blocks) -> State WriterState Doc orderedListItemToMan _ _ _ [] = return empty orderedListItemToMan opts num indent ((Para first):rest) = orderedListItemToMan opts num indent ((Plain first):rest) orderedListItemToMan opts num indent (first:rest) = do first' <- blockToMan opts first rest' <- blockListToMan opts rest let num' = printf ("%" ++ show (indent - 1) ++ "s") num let first'' = text (".IP \"" ++ num' ++ "\" " ++ show indent) $$ first' let rest'' = if null rest then empty else text ".RS 4" $$ rest' $$ text ".RE" return $ first'' $$ rest'' -- | Convert definition list item (label, list of blocks) to man. definitionListItemToMan :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState Doc definitionListItemToMan opts (label, defs) = do labelText <- inlineListToMan opts label contents <- if null defs then return empty else liftM vcat $ forM defs $ \blocks -> do let (first, rest) = case blocks of ((Para x):y) -> (Plain x,y) (x:y) -> (x,y) [] -> error "blocks is null" rest' <- liftM vcat $ mapM (\item -> blockToMan opts item) rest first' <- blockToMan opts first return $ first' $$ text ".RS" $$ rest' $$ text ".RE" return $ text ".TP" $$ text ".B " <> labelText $$ contents -- | Convert list of Pandoc block elements to man. blockListToMan :: WriterOptions -- ^ Options -> [Block] -- ^ List of block elements -> State WriterState Doc blockListToMan opts blocks = mapM (blockToMan opts) blocks >>= (return . vcat) -- | Convert list of Pandoc inline elements to man. inlineListToMan :: WriterOptions -> [Inline] -> State WriterState Doc -- if list starts with ., insert a zero-width character \& so it -- won't be interpreted as markup if it falls at the beginning of a line. inlineListToMan opts lst@(Str ('.':_) : _) = mapM (inlineToMan opts) lst >>= (return . (text "\\&" <>) . hcat) inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat) -- | Convert Pandoc inline element to man. inlineToMan :: WriterOptions -> Inline -> State WriterState Doc inlineToMan opts (Span _ ils) = inlineListToMan opts ils inlineToMan opts (Emph lst) = do contents <- inlineListToMan opts lst return $ text "\\f[I]" <> contents <> text "\\f[]" inlineToMan opts (Strong lst) = do contents <- inlineListToMan opts lst return $ text "\\f[B]" <> contents <> text "\\f[]" inlineToMan opts (Strikeout lst) = do contents <- inlineListToMan opts lst return $ text "[STRIKEOUT:" <> contents <> char ']' inlineToMan opts (Superscript lst) = do contents <- inlineListToMan opts lst return $ char '^' <> contents <> char '^' inlineToMan opts (Subscript lst) = do contents <- inlineListToMan opts lst return $ char '~' <> contents <> char '~' inlineToMan opts (SmallCaps lst) = inlineListToMan opts lst -- not supported inlineToMan opts (Quoted SingleQuote lst) = do contents <- inlineListToMan opts lst return $ char '`' <> contents <> char '\'' inlineToMan opts (Quoted DoubleQuote lst) = do contents <- inlineListToMan opts lst return $ text "\\[lq]" <> contents <> text "\\[rq]" inlineToMan opts (Cite _ lst) = inlineListToMan opts 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' InlineMath str inlineToMan opts (Math DisplayMath str) = do contents <- inlineListToMan opts $ readTeXMath' DisplayMath str return $ cr <> text ".RS" $$ contents $$ text ".RE" inlineToMan _ (RawInline f str) | f == Format "man" = return $ text str | otherwise = return empty inlineToMan _ (LineBreak) = return $ cr <> text ".PD 0" $$ text ".P" $$ text ".PD" <> cr inlineToMan _ Space = return space inlineToMan opts (Link txt (src, _)) = do linktext <- inlineListToMan opts txt let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src return $ case txt of [Str s] | escapeURI s == srcSuffix -> char '<' <> text srcSuffix <> char '>' _ -> linktext <> text " (" <> text src <> char ')' inlineToMan opts (Image alternate (source, tit)) = do let txt = if (null alternate) || (alternate == [Str ""]) || (alternate == [Str source]) -- to prevent autolinks then [Str "image"] else alternate linkPart <- inlineToMan opts (Link txt (source, tit)) return $ char '[' <> text "IMAGE: " <> linkPart <> char ']' inlineToMan _ (Note contents) = do -- add to notes in state modify $ \st -> st{ stNotes = contents : stNotes st } notes <- liftM stNotes get let ref = show $ (length notes) return $ char '[' <> text ref <> char ']' ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Markdown.hs�������������������������������������������������000644 �000765 �000024 �00000107040 12251233602 021612� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings, TupleSections, ScopedTypeVariables #-} {- Copyright (C) 2006-2013 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Markdown Copyright : Copyright (C) 2006-2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to markdown-formatted plain text. Markdown: <http://daringfireball.net/projects/markdown/> -} module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where import Text.Pandoc.Definition import Text.Pandoc.Walk import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, char, space) import Data.List ( group, isPrefixOf, find, intersperse, transpose, sortBy ) import Data.Char ( isSpace, isPunctuation ) import Data.Ord ( comparing ) import Text.Pandoc.Pretty import Control.Monad.State import qualified Data.Set as Set import Text.Pandoc.Writers.HTML (writeHtmlString) import Text.Pandoc.Readers.TeXMath (readTeXMath') import Text.HTML.TagSoup (renderTags, parseTags, isTagText, Tag(..)) import Network.URI (isURI) import Data.Default import Data.Yaml (Value(Object,String,Array,Bool,Number)) import qualified Data.HashMap.Strict as H import qualified Data.Vector as V import qualified Data.Text as T type Notes = [[Block]] type Refs = [([Inline], Target)] data WriterState = WriterState { stNotes :: Notes , stRefs :: Refs , stIds :: [String] , stPlain :: Bool } instance Default WriterState where def = WriterState{ stNotes = [], stRefs = [], stIds = [], stPlain = False } -- | Convert Pandoc to Markdown. writeMarkdown :: WriterOptions -> Pandoc -> String writeMarkdown opts document = evalState (pandocToMarkdown opts{ writerWrapText = writerWrapText opts && not (isEnabled Ext_hard_line_breaks opts) } document) def -- | Convert Pandoc to plain text (like markdown, but without links, -- pictures, or inline formatting). writePlain :: WriterOptions -> Pandoc -> String writePlain opts document = evalState (pandocToMarkdown opts{ writerExtensions = Set.delete Ext_escaped_line_breaks $ writerExtensions opts } document') def{ stPlain = True } where document' = plainify document plainify :: Pandoc -> Pandoc plainify = walk go where go :: Inline -> Inline go (Emph xs) = SmallCaps xs go (Strong xs) = SmallCaps xs go (Strikeout xs) = SmallCaps xs go (Superscript xs) = SmallCaps xs go (Subscript xs) = SmallCaps xs go (SmallCaps xs) = SmallCaps xs go (Code _ s) = Str s go (Math _ s) = Str s go (RawInline _ _) = Str "" go (Link xs _) = SmallCaps xs go (Image xs _) = SmallCaps $ [Str "["] ++ xs ++ [Str "]"] go (Cite _ cits) = SmallCaps cits go x = x pandocTitleBlock :: Doc -> [Doc] -> Doc -> Doc pandocTitleBlock tit auths dat = hang 2 (text "% ") tit <> cr <> hang 2 (text "% ") (vcat $ map nowrap auths) <> cr <> hang 2 (text "% ") dat <> cr mmdTitleBlock :: Value -> Doc mmdTitleBlock (Object hashmap) = vcat $ map go $ sortBy (comparing fst) $ H.toList hashmap where go (k,v) = case (text (T.unpack k), v) of (k', Array vec) | V.null vec -> empty | otherwise -> k' <> ":" <> space <> hcat (intersperse "; " (map fromstr $ V.toList vec)) (_, String "") -> empty (k', x) -> k' <> ":" <> space <> nest 2 (fromstr x) fromstr (String s) = text (removeBlankLines $ T.unpack s) fromstr (Bool b) = text (show b) fromstr (Number n) = text (show n) fromstr _ = empty -- blank lines not allowed in MMD metadata - we replace with . removeBlankLines = trimr . unlines . map (\x -> if all isSpace x then "." else x) . lines mmdTitleBlock _ = empty plainTitleBlock :: Doc -> [Doc] -> Doc -> Doc plainTitleBlock tit auths dat = tit <> cr <> (hcat (intersperse (text "; ") auths)) <> cr <> dat <> cr yamlMetadataBlock :: Value -> Doc yamlMetadataBlock v = "---" $$ (jsonToYaml v) $$ "..." jsonToYaml :: Value -> Doc jsonToYaml (Object hashmap) = vcat $ map (\(k,v) -> case (text (T.unpack k), v, jsonToYaml v) of (k', Array vec, x) | V.null vec -> empty | otherwise -> (k' <> ":") $$ x (k', Object _, x) -> (k' <> ":") $$ nest 2 x (_, String "", _) -> empty (k', _, x) -> k' <> ":" <> space <> hang 2 "" x) $ sortBy (comparing fst) $ H.toList hashmap jsonToYaml (Array vec) = vcat $ map (\v -> hang 2 "- " (jsonToYaml v)) $ V.toList vec jsonToYaml (String "") = empty jsonToYaml (String s) = case T.unpack s of x | '\n' `elem` x -> hang 2 ("|" <> cr) $ text x | not (any isPunctuation x) -> text x | otherwise -> text $ "'" ++ substitute "'" "''" x ++ "'" jsonToYaml (Bool b) = text $ show b jsonToYaml (Number n) = text $ show n jsonToYaml _ = empty -- | Return markdown representation of document. pandocToMarkdown :: WriterOptions -> Pandoc -> State WriterState String pandocToMarkdown opts (Pandoc meta blocks) = do let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing isPlain <- gets stPlain metadata <- metaToJSON opts (fmap (render colwidth) . blockListToMarkdown opts) (fmap (render colwidth) . inlineListToMarkdown opts) meta let title' = maybe empty text $ getField "title" metadata let authors' = maybe [] (map text) $ getField "author" metadata let date' = maybe empty text $ getField "date" metadata let titleblock = case writerStandalone opts of True | isPlain -> plainTitleBlock title' authors' date' | isEnabled Ext_yaml_metadata_block opts -> yamlMetadataBlock metadata | isEnabled Ext_pandoc_title_block opts -> pandocTitleBlock title' authors' date' | isEnabled Ext_mmd_title_block opts -> mmdTitleBlock metadata | otherwise -> empty False -> empty let headerBlocks = filter isHeaderBlock blocks let toc = if writerTableOfContents opts then tableOfContents opts headerBlocks else empty -- Strip off final 'references' header if markdown citations enabled 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) st' <- get -- note that the notes may contain refs refs' <- refsToMarkdown opts (reverse $ stRefs st') let render' :: Doc -> String render' = render colwidth let main = render' $ body <> (if isEmpty notes' then empty else blankline <> notes') <> (if isEmpty refs' then empty else blankline <> refs') let context = defField "toc" (render' toc) $ defField "body" main $ (if isNullMeta meta then id else defField "titleblock" (render' titleblock)) $ metadata if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main -- | Return markdown representation of reference key table. refsToMarkdown :: WriterOptions -> Refs -> State WriterState Doc refsToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat -- | Return markdown representation of a reference key. keyToMarkdown :: WriterOptions -> ([Inline], (String, String)) -> State WriterState Doc keyToMarkdown opts (label, (src, tit)) = do label' <- inlineListToMarkdown opts label let tit' = if null tit then empty else space <> "\"" <> text tit <> "\"" return $ nest 2 $ hang 2 ("[" <> label' <> "]:" <> space) (text src <> tit') -- | Return markdown representation of notes. notesToMarkdown :: WriterOptions -> [[Block]] -> State WriterState Doc notesToMarkdown opts notes = mapM (\(num, note) -> noteToMarkdown opts num note) (zip [1..] notes) >>= return . vsep -- | Return markdown representation of a note. noteToMarkdown :: WriterOptions -> Int -> [Block] -> State WriterState Doc noteToMarkdown opts num blocks = do contents <- blockListToMarkdown opts blocks let num' = text $ writerIdentifierPrefix opts ++ show num let marker = if isEnabled Ext_footnotes opts then text "[^" <> num' <> text "]:" else text "[" <> num' <> text "]" let markerSize = 4 + offset num' let spacer = case writerTabStop opts - markerSize of n | n > 0 -> text $ replicate n ' ' _ -> text " " return $ if isEnabled Ext_footnotes opts then hang (writerTabStop opts) (marker <> spacer) contents else marker <> spacer <> contents -- | Escape special characters for Markdown. escapeString :: String -> String escapeString = escapeStringUsing markdownEscapes where markdownEscapes = backslashEscapes "\\`*_$<>#~^" -- | Construct table of contents from list of header blocks. tableOfContents :: WriterOptions -> [Block] -> Doc tableOfContents opts headers = let opts' = opts { writerIgnoreNotes = True } contents = BulletList $ map (elementToListItem opts) $ hierarchicalize headers in evalState (blockToMarkdown opts' contents) def -- | Converts an Element to a list item for a table of contents, elementToListItem :: WriterOptions -> Element -> [Block] elementToListItem opts (Sec lev _ _ headerText subsecs) = Plain headerText : [ BulletList (map (elementToListItem opts) subsecs) | not (null subsecs) && lev < writerTOCDepth opts ] elementToListItem _ (Blk _) = [] attrsToMarkdown :: Attr -> Doc attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys] where attribId = case attribs of ([],_,_) -> empty (i,_,_) -> "#" <> text i attribClasses = case attribs of (_,[],_) -> empty (_,cs,_) -> hsep $ map (text . ('.':)) cs attribKeys = case attribs of (_,_,[]) -> empty (_,_,ks) -> hsep $ map (\(k,v) -> text k <> "=\"" <> text v <> "\"") ks -- | Ordered list start parser for use in Para below. olMarker :: Parser [Char] ParserState Char olMarker = do (start, style', delim) <- anyOrderedListMarker if delim == Period && (style' == UpperAlpha || (style' == UpperRoman && start `elem` [1, 5, 10, 50, 100, 500, 1000])) then spaceChar >> spaceChar else spaceChar -- | True if string begins with an ordered list marker beginsWithOrderedListMarker :: String -> Bool beginsWithOrderedListMarker str = case runParser olMarker defaultParserState "para start" (take 10 str) of Left _ -> False Right _ -> True -- | Convert Pandoc block element to markdown. blockToMarkdown :: WriterOptions -- ^ Options -> Block -- ^ Block element -> State WriterState Doc blockToMarkdown _ Null = return empty blockToMarkdown opts (Div attrs ils) = do isPlain <- gets stPlain contents <- blockListToMarkdown opts ils return $ if isPlain || not (isEnabled Ext_markdown_in_html_blocks opts) then contents <> blankline else tagWithAttrs "div" attrs <> blankline <> contents <> blankline <> "</div>" <> blankline blockToMarkdown opts (Plain inlines) = do contents <- inlineListToMarkdown opts inlines return $ contents <> cr -- title beginning with fig: indicates figure blockToMarkdown opts (Para [Image alt (src,'f':'i':'g':':':tit)]) = blockToMarkdown opts (Para [Image alt (src,tit)]) blockToMarkdown opts (Para inlines) = do contents <- inlineListToMarkdown opts inlines -- escape if para starts with ordered list marker st <- get let esc = if isEnabled Ext_all_symbols_escapable opts && not (stPlain st) && beginsWithOrderedListMarker (render Nothing contents) then text "\x200B" -- zero-width space, a hack else empty return $ esc <> contents <> blankline blockToMarkdown opts (RawBlock f str) | f == "html" = do st <- get if stPlain st then return empty else return $ if isEnabled Ext_markdown_attribute opts then text (addMarkdownAttribute str) <> text "\n" else text str <> text "\n" | f == "latex" || f == "tex" || f == "markdown" = do st <- get if stPlain st then return empty else return $ text str <> text "\n" blockToMarkdown _ (RawBlock _ _) = return empty blockToMarkdown _ HorizontalRule = return $ blankline <> text "* * * * *" <> blankline blockToMarkdown opts (Header level attr inlines) = do -- we calculate the id that would be used by auto_identifiers -- so we know whether to print an explicit identifier ids <- gets stIds let autoId = uniqueIdent inlines ids modify $ \st -> st{ stIds = autoId : ids } let attr' = case attr of ("",[],[]) -> empty (id',[],[]) | isEnabled Ext_auto_identifiers opts && id' == autoId -> empty (id',_,_) | isEnabled Ext_mmd_header_identifiers opts -> space <> brackets (text id') _ | isEnabled Ext_header_attributes opts -> space <> attrsToMarkdown attr | otherwise -> empty contents <- inlineListToMarkdown opts inlines st <- get let setext = writerSetextHeaders opts return $ nowrap $ case level of 1 | setext -> contents <> attr' <> cr <> text (replicate (offset contents) '=') <> blankline 2 | setext -> contents <> attr' <> cr <> text (replicate (offset contents) '-') <> blankline -- ghc interprets '#' characters in column 1 as linenum specifiers. _ | stPlain st || isEnabled Ext_literate_haskell opts -> contents <> blankline _ -> text (replicate level '#') <> space <> contents <> attr' <> blankline blockToMarkdown opts (CodeBlock (_,classes,_) str) | "haskell" `elem` classes && "literate" `elem` classes && 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 _ -> nest (writerTabStop opts) (text str) <> blankline where tildes = text $ case [ln | ln <- lines str, all (=='~') ln] of [] -> "~~~~" xs -> case maximum $ map length xs of n | n < 3 -> "~~~~" | otherwise -> replicate (n+1) '~' backticks = text "```" attrs = if isEnabled Ext_fenced_code_attributes opts then nowrap $ attrsToMarkdown attribs else empty blockToMarkdown opts (BlockQuote blocks) = do st <- get -- if we're writing literate haskell, put a space before the bird tracks -- so they won't be interpreted as lhs... let leader = if isEnabled Ext_literate_haskell opts then " > " else if stPlain st then " " else "> " contents <- blockListToMarkdown opts blocks return $ (prefixed leader contents) <> blankline blockToMarkdown opts t@(Table caption aligns widths headers rows) = do caption' <- inlineListToMarkdown opts caption let caption'' = if null caption || not (isEnabled Ext_table_captions opts) then empty else blankline <> ": " <> caption' <> blankline rawHeaders <- mapM (blockListToMarkdown opts) headers rawRows <- mapM (mapM (blockListToMarkdown opts)) rows let isSimple = all (==0) widths let isPlainBlock (Plain _) = True isPlainBlock _ = False let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows) (nst,tbl) <- case True of _ | isSimple && isEnabled Ext_simple_tables opts -> fmap (nest 2,) $ pandocTable opts (all null headers) aligns widths rawHeaders rawRows | isSimple && isEnabled Ext_pipe_tables opts -> fmap (id,) $ pipeTable (all null headers) aligns rawHeaders rawRows | not hasBlocks && isEnabled Ext_multiline_tables opts -> fmap (nest 2,) $ pandocTable opts (all null headers) aligns widths rawHeaders rawRows | isEnabled Ext_grid_tables opts -> fmap (id,) $ gridTable opts (all null headers) aligns widths rawHeaders rawRows | otherwise -> fmap (id,) $ return $ text $ writeHtmlString def $ Pandoc nullMeta [t] return $ nst $ tbl $$ blankline $$ caption'' $$ blankline blockToMarkdown opts (BulletList items) = do contents <- mapM (bulletListItemToMarkdown opts) items return $ cat contents <> blankline blockToMarkdown opts (OrderedList (start,sty,delim) items) = do let start' = if isEnabled Ext_startnum opts then start else 1 let sty' = if isEnabled Ext_fancy_lists opts then sty else DefaultStyle let delim' = if isEnabled Ext_fancy_lists opts then delim else DefaultDelim let attribs = (start', sty', delim') let markers = orderedListMarkers attribs let markers' = map (\m -> if length m < 3 then m ++ replicate (3 - length m) ' ' else m) markers contents <- mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $ zip markers' items return $ cat contents <> blankline blockToMarkdown opts (DefinitionList items) = do contents <- mapM (definitionListItemToMarkdown opts) items return $ cat contents <> blankline addMarkdownAttribute :: String -> String addMarkdownAttribute s = case span isTagText $ reverse $ parseTags s of (xs,(TagOpen t attrs:rest)) -> renderTags $ reverse rest ++ (TagOpen t attrs' : reverse xs) where attrs' = ("markdown","1"):[(x,y) | (x,y) <- attrs, x /= "markdown"] _ -> s pipeTable :: Bool -> [Alignment] -> [Doc] -> [[Doc]] -> State WriterState Doc pipeTable headless aligns rawHeaders rawRows = do let torow cs = nowrap $ text "|" <> hcat (intersperse (text "|") $ map chomp cs) <> text "|" let toborder (a, h) = let wid = max (offset h) 3 in text $ case a of AlignLeft -> ':':replicate (wid - 1) '-' AlignCenter -> ':':replicate (wid - 2) '-' ++ ":" AlignRight -> replicate (wid - 1) '-' ++ ":" AlignDefault -> replicate wid '-' let header = if headless then empty else torow rawHeaders let border = torow $ map toborder $ zip aligns rawHeaders let body = vcat $ map torow rawRows return $ header $$ border $$ body pandocTable :: WriterOptions -> Bool -> [Alignment] -> [Double] -> [Doc] -> [[Doc]] -> State WriterState Doc pandocTable opts headless aligns widths rawHeaders rawRows = do let isSimple = all (==0) widths let alignHeader alignment = case alignment of AlignLeft -> lblock AlignCenter -> cblock AlignRight -> rblock AlignDefault -> lblock let numChars = maximum . map offset let widthsInChars = if isSimple then map ((+2) . numChars) $ transpose (rawHeaders : rawRows) else map (floor . (fromIntegral (writerColumns opts) *)) widths let makeRow = hcat . intersperse (lblock 1 (text " ")) . (zipWith3 alignHeader aligns widthsInChars) let rows' = map makeRow rawRows let head' = makeRow rawHeaders let maxRowHeight = maximum $ map height (head':rows') let underline = cat $ intersperse (text " ") $ map (\width -> text (replicate width '-')) widthsInChars let border = if maxRowHeight > 1 then text (replicate (sum widthsInChars + length widthsInChars - 1) '-') else if headless then underline else empty let head'' = if headless then empty else border <> cr <> head' let body = if maxRowHeight > 1 then vsep rows' else vcat rows' let bottom = if headless then underline else border return $ head'' $$ underline $$ body $$ bottom gridTable :: WriterOptions -> Bool -> [Alignment] -> [Double] -> [Doc] -> [[Doc]] -> State WriterState Doc gridTable opts headless _aligns widths headers' rawRows = do let numcols = length headers' let widths' = if all (==0) widths then replicate numcols (1.0 / fromIntegral numcols) else widths let widthsInChars = map (floor . (fromIntegral (writerColumns opts) *)) widths' let hpipeBlocks blocks = hcat [beg, middle, end] where h = maximum (map height blocks) sep' = lblock 3 $ vcat (map text $ replicate h " | ") beg = lblock 2 $ vcat (map text $ replicate h "| ") end = lblock 2 $ vcat (map text $ replicate h " |") middle = chomp $ hcat $ intersperse sep' blocks let makeRow = hpipeBlocks . zipWith lblock widthsInChars let head' = makeRow headers' let rows' = map (makeRow . map chomp) rawRows let border ch = char '+' <> char ch <> (hcat $ intersperse (char ch <> char '+' <> char ch) $ map (\l -> text $ replicate l ch) widthsInChars) <> char ch <> char '+' let body = vcat $ intersperse (border '-') rows' let head'' = if headless then empty else head' $$ border '=' return $ border '-' $$ head'' $$ body $$ border '-' -- | Convert bullet list item (list of blocks) to markdown. bulletListItemToMarkdown :: WriterOptions -> [Block] -> State WriterState Doc bulletListItemToMarkdown opts items = do contents <- blockListToMarkdown opts items let sps = replicate (writerTabStop opts - 2) ' ' let start = text ('-' : ' ' : sps) -- 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 -> String -- ^ list item marker -> [Block] -- ^ list item (list of blocks) -> State WriterState Doc orderedListItemToMarkdown opts marker items = do contents <- blockListToMarkdown opts items let sps = case length marker - writerTabStop opts of n | n > 0 -> text $ replicate n ' ' _ -> text " " let start = text marker <> sps return $ hang (writerTabStop opts) start $ contents <> cr -- | Convert definition list item (label, list of blocks) to markdown. definitionListItemToMarkdown :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState Doc definitionListItemToMarkdown opts (label, defs) = do labelText <- inlineListToMarkdown opts label defs' <- mapM (mapM (blockToMarkdown opts)) defs if isEnabled Ext_definition_lists opts then do let tabStop = writerTabStop opts st <- get let leader = if stPlain st then " " else ": " let sps = case writerTabStop opts - 3 of n | n > 0 -> text $ replicate n ' ' _ -> text " " let contents = vcat $ map (\d -> hang tabStop (leader <> sps) $ vcat d <> cr) defs' return $ nowrap labelText <> cr <> contents <> cr else do return $ nowrap labelText <> text " " <> cr <> vsep (map vsep defs') <> blankline -- | Convert list of Pandoc block elements to markdown. blockListToMarkdown :: WriterOptions -- ^ Options -> [Block] -- ^ List of block elements -> State WriterState Doc blockListToMarkdown opts blocks = mapM (blockToMarkdown opts) (fixBlocks blocks) >>= return . cat -- insert comment between list and indented code block, or the -- code block will be treated as a list continuation paragraph where fixBlocks (b : CodeBlock attr x : rest) | (not (isEnabled Ext_fenced_code_blocks opts) || attr == nullAttr) && isListBlock b = b : RawBlock "html" "<!-- -->\n" : CodeBlock attr x : fixBlocks rest fixBlocks (x : xs) = x : fixBlocks xs fixBlocks [] = [] isListBlock (BulletList _) = True isListBlock (OrderedList _ _) = True isListBlock (DefinitionList _) = True isListBlock _ = False -- | Get reference for target; if none exists, create unique one and return. -- Prefer label if possible; otherwise, generate a unique key. getReference :: [Inline] -> Target -> State WriterState [Inline] getReference label (src, tit) = do st <- get case find ((== (src, tit)) . snd) (stRefs st) of Just (ref, _) -> return ref 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" Nothing -> label modify (\s -> s{ stRefs = (label', (src,tit)) : stRefs st }) return label' -- | Convert list of Pandoc inline elements to markdown. inlineListToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc inlineListToMarkdown opts lst = mapM (inlineToMarkdown opts) lst >>= return . cat escapeSpaces :: Inline -> Inline escapeSpaces (Str s) = Str $ substitute " " "\\ " s escapeSpaces Space = Str "\\ " 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 $ if stPlain st then contents else tagWithAttrs "span" attrs <> contents <> text "</span>" inlineToMarkdown opts (Emph lst) = do contents <- inlineListToMarkdown opts lst return $ "*" <> contents <> "*" inlineToMarkdown opts (Strong lst) = do contents <- inlineListToMarkdown opts lst return $ "**" <> contents <> "**" inlineToMarkdown opts (Strikeout lst) = do contents <- inlineListToMarkdown opts lst return $ if isEnabled Ext_strikeout opts then "~~" <> contents <> "~~" else "<s>" <> contents <> "</s>" inlineToMarkdown opts (Superscript lst) = do let lst' = walk escapeSpaces lst contents <- inlineListToMarkdown opts lst' return $ if isEnabled Ext_superscript opts then "^" <> contents <> "^" else "<sup>" <> contents <> "</sup>" inlineToMarkdown opts (Subscript lst) = do let lst' = walk escapeSpaces lst contents <- inlineListToMarkdown opts lst' return $ if isEnabled Ext_subscript opts then "~" <> contents <> "~" else "<sub>" <> contents <> "</sub>" inlineToMarkdown opts (SmallCaps lst) = inlineListToMarkdown opts lst inlineToMarkdown opts (Quoted SingleQuote lst) = do contents <- inlineListToMarkdown opts lst return $ "‘" <> contents <> "’" inlineToMarkdown opts (Quoted DoubleQuote lst) = do contents <- inlineListToMarkdown opts lst return $ "“" <> contents <> "”" inlineToMarkdown opts (Code attr str) = let tickGroups = filter (\s -> '`' `elem` s) $ group str longest = if null tickGroups then 0 else maximum $ map length tickGroups marker = replicate (longest + 1) '`' spacer = if (longest == 0) then "" else " " attrs = if isEnabled Ext_inline_code_attributes opts && attr /= nullAttr then attrsToMarkdown attr else empty in return $ text (marker ++ spacer ++ str ++ spacer ++ marker) <> attrs inlineToMarkdown _ (Str str) = do st <- get if stPlain st then return $ text str else return $ text $ escapeString str inlineToMarkdown opts (Math InlineMath str) | isEnabled Ext_tex_math_dollars opts = return $ "$" <> text str <> "$" | isEnabled Ext_tex_math_single_backslash opts = return $ "\\(" <> text str <> "\\)" | isEnabled Ext_tex_math_double_backslash opts = return $ "\\\\(" <> text str <> "\\\\)" | otherwise = inlineListToMarkdown opts $ readTeXMath' InlineMath str inlineToMarkdown opts (Math DisplayMath str) | isEnabled Ext_tex_math_dollars opts = return $ "$$" <> text str <> "$$" | isEnabled Ext_tex_math_single_backslash opts = return $ "\\[" <> text str <> "\\]" | isEnabled Ext_tex_math_double_backslash opts = return $ "\\\\[" <> text str <> "\\\\]" | otherwise = (\x -> cr <> x <> cr) `fmap` inlineListToMarkdown opts (readTeXMath' DisplayMath str) inlineToMarkdown opts (RawInline f str) | f == "html" || f == "markdown" || (isEnabled Ext_raw_tex opts && (f == "latex" || f == "tex")) = return $ text str inlineToMarkdown _ (RawInline _ _) = return empty inlineToMarkdown opts (LineBreak) | isEnabled Ext_hard_line_breaks opts = return cr | isEnabled Ext_escaped_line_breaks opts = return $ "\\" <> cr | otherwise = return $ " " <> cr inlineToMarkdown _ Space = return space inlineToMarkdown opts (Cite [] lst) = inlineListToMarkdown opts lst inlineToMarkdown opts (Cite (c:cs) lst) | not (isEnabled Ext_citations opts) = inlineListToMarkdown opts lst | otherwise = if citationMode c == AuthorInText then do suffs <- inlineListToMarkdown opts $ citationSuffix c rest <- mapM convertOne cs let inbr = suffs <+> joincits rest br = if isEmpty inbr then empty else char '[' <> inbr <> char ']' return $ text ("@" ++ citationId c) <+> br else do cits <- mapM convertOne (c:cs) return $ text "[" <> joincits cits <> text "]" where joincits = hcat . intersperse (text "; ") . filter (not . isEmpty) convertOne Citation { citationId = k , citationPrefix = pinlines , citationSuffix = sinlines , citationMode = m } = do pdoc <- inlineListToMarkdown opts pinlines sdoc <- inlineListToMarkdown opts sinlines let k' = text (modekey m ++ "@" ++ k) r = case sinlines of Str (y:_):_ | y `elem` ",;]@" -> k' <> sdoc _ -> k' <+> sdoc return $ pdoc <+> r modekey SuppressAuthor = "-" modekey _ = "" inlineToMarkdown opts (Link txt (src, tit)) = do linktext <- inlineListToMarkdown opts txt let linktitle = if null tit then empty else text $ " \"" ++ tit ++ "\"" let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src let useAuto = isURI src && case txt of [Str s] | escapeURI s == srcSuffix -> True _ -> False let useRefLinks = writerReferenceLinks opts && not useAuto ref <- if useRefLinks then getReference txt (src, tit) else return [] reftext <- inlineListToMarkdown opts ref return $ if useAuto then "<" <> text srcSuffix <> ">" else if useRefLinks then let first = "[" <> linktext <> "]" second = if txt == ref then "[]" else "[" <> reftext <> "]" in first <> second else "[" <> linktext <> "](" <> text src <> linktitle <> ")" inlineToMarkdown opts (Image alternate (source, tit)) = do let txt = if null alternate || alternate == [Str source] -- to prevent autolinks then [Str ""] else alternate linkPart <- inlineToMarkdown opts (Link txt (source, tit)) return $ "!" <> linkPart inlineToMarkdown opts (Note contents) = do modify (\st -> st{ stNotes = contents : stNotes st }) st <- get let ref = text $ writerIdentifierPrefix opts ++ show (length $ stNotes st) if isEnabled Ext_footnotes opts then return $ "[^" <> ref <> "]" else return $ "[" <> ref <> "]" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/MediaWiki.hs������������������������������������������������000644 �000765 �000024 �00000041100 12251233602 021665� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2008-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.MediaWiki Copyright : Copyright (C) 2008-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to MediaWiki markup. MediaWiki: <http://www.mediawiki.org/wiki/MediaWiki> -} module Text.Pandoc.Writers.MediaWiki ( writeMediaWiki ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Pretty (render) import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.XML ( escapeStringForXML ) import Data.List ( intersect, intercalate, intersperse ) import Network.URI ( isURI ) import Control.Monad.State data WriterState = WriterState { stNotes :: Bool -- True if there are notes , stListLevel :: [Char] -- String at beginning of list items, e.g. "**" , stUseTags :: Bool -- True if we should use HTML tags because we're in a complex list } -- | Convert Pandoc to MediaWiki. writeMediaWiki :: WriterOptions -> Pandoc -> String writeMediaWiki opts document = evalState (pandocToMediaWiki opts document) (WriterState { stNotes = False, stListLevel = [], stUseTags = False }) -- | Return MediaWiki representation of document. pandocToMediaWiki :: WriterOptions -> Pandoc -> State WriterState String pandocToMediaWiki opts (Pandoc meta blocks) = do metadata <- metaToJSON opts (fmap trimr . blockListToMediaWiki opts) (inlineListToMediaWiki opts) meta body <- blockListToMediaWiki opts blocks notesExist <- get >>= return . stNotes let notes = if notesExist then "\n<references />" else "" let main = body ++ notes let context = defField "body" main $ defField "toc" (writerTableOfContents opts) $ metadata if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main -- | Escape special characters for MediaWiki. escapeString :: String -> String escapeString = escapeStringForXML -- | Convert Pandoc block element to MediaWiki. blockToMediaWiki :: WriterOptions -- ^ Options -> Block -- ^ Block element -> State WriterState String blockToMediaWiki _ Null = return "" blockToMediaWiki opts (Div attrs bs) = do contents <- blockListToMediaWiki opts bs return $ render Nothing (tagWithAttrs "div" attrs) ++ "\n\n" ++ contents ++ "\n\n" ++ "</div>" blockToMediaWiki opts (Plain inlines) = inlineListToMediaWiki opts inlines -- title beginning with fig: indicates that the image is a figure blockToMediaWiki opts (Para [Image txt (src,'f':'i':'g':':':tit)]) = do capt <- if null txt then return "" else ("|caption " ++) `fmap` inlineListToMediaWiki opts txt let opt = if null txt then "" else "|alt=" ++ if null tit then capt else tit ++ capt return $ "[[Image:" ++ src ++ "|frame|none" ++ opt ++ "]]\n" blockToMediaWiki opts (Para inlines) = do useTags <- get >>= return . stUseTags listLevel <- get >>= return . stListLevel contents <- inlineListToMediaWiki opts inlines return $ if useTags then "<p>" ++ contents ++ "</p>" else contents ++ if null listLevel then "\n" else "" blockToMediaWiki _ (RawBlock f str) | f == Format "mediawiki" = return str | f == Format "html" = return str | otherwise = return "" blockToMediaWiki _ HorizontalRule = return "\n-----\n" blockToMediaWiki opts (Header level _ inlines) = do contents <- inlineListToMediaWiki opts inlines let eqs = replicate level '=' return $ eqs ++ " " ++ contents ++ " " ++ eqs ++ "\n" blockToMediaWiki _ (CodeBlock (_,classes,_) str) = do let at = classes `intersect` ["actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp", "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl", "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas", "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty", "sql", "tcl", "", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80"] let (beg, end) = if null at then ("<pre" ++ if null classes then ">" else " class=\"" ++ unwords classes ++ "\">", "</pre>") else ("<source lang=\"" ++ head at ++ "\">", "</source>") return $ beg ++ escapeString str ++ end blockToMediaWiki opts (BlockQuote blocks) = do contents <- blockListToMediaWiki opts blocks return $ "<blockquote>" ++ contents ++ "</blockquote>" blockToMediaWiki opts (Table capt aligns widths headers rows') = do caption <- if null capt then return "" else do c <- inlineListToMediaWiki opts capt return $ "|+ " ++ trimr c ++ "\n" let headless = all null headers let allrows = if headless then rows' else headers:rows' tableBody <- (concat . intersperse "|-\n") `fmap` mapM (tableRowToMediaWiki opts headless aligns widths) (zip [1..] allrows) return $ "{|\n" ++ caption ++ tableBody ++ "|}\n" blockToMediaWiki opts x@(BulletList items) = do oldUseTags <- get >>= return . stUseTags listLevel <- get >>= return . stListLevel let useTags = oldUseTags || not (isSimpleList x) if useTags then do modify $ \s -> s { stUseTags = True } contents <- mapM (listItemToMediaWiki opts) items modify $ \s -> s { stUseTags = oldUseTags } return $ "<ul>\n" ++ vcat contents ++ "</ul>\n" else do modify $ \s -> s { stListLevel = stListLevel s ++ "*" } contents <- mapM (listItemToMediaWiki opts) items modify $ \s -> s { stListLevel = init (stListLevel s) } return $ vcat contents ++ if null listLevel then "\n" else "" blockToMediaWiki opts x@(OrderedList attribs items) = do oldUseTags <- get >>= return . stUseTags listLevel <- get >>= return . stListLevel let useTags = oldUseTags || not (isSimpleList x) if useTags then do modify $ \s -> s { stUseTags = True } contents <- mapM (listItemToMediaWiki opts) items modify $ \s -> s { stUseTags = oldUseTags } return $ "<ol" ++ listAttribsToString attribs ++ ">\n" ++ vcat contents ++ "</ol>\n" else do modify $ \s -> s { stListLevel = stListLevel s ++ "#" } contents <- mapM (listItemToMediaWiki opts) items modify $ \s -> s { stListLevel = init (stListLevel s) } return $ vcat contents ++ if null listLevel then "\n" else "" blockToMediaWiki opts x@(DefinitionList items) = do oldUseTags <- get >>= return . stUseTags listLevel <- get >>= return . stListLevel let useTags = oldUseTags || not (isSimpleList x) if useTags then do modify $ \s -> s { stUseTags = True } contents <- mapM (definitionListItemToMediaWiki opts) items modify $ \s -> s { stUseTags = oldUseTags } return $ "<dl>\n" ++ vcat contents ++ "</dl>\n" else do modify $ \s -> s { stListLevel = stListLevel s ++ ";" } contents <- mapM (definitionListItemToMediaWiki opts) items modify $ \s -> s { stListLevel = init (stListLevel s) } return $ vcat contents ++ if null listLevel then "\n" else "" -- Auxiliary functions for lists: -- | Convert ordered list attributes to HTML attribute string listAttribsToString :: ListAttributes -> String listAttribsToString (startnum, numstyle, _) = let numstyle' = camelCaseToHyphenated $ show numstyle in (if startnum /= 1 then " start=\"" ++ show startnum ++ "\"" else "") ++ (if numstyle /= DefaultStyle then " style=\"list-style-type: " ++ numstyle' ++ ";\"" else "") -- | Convert bullet or ordered list item (list of blocks) to MediaWiki. listItemToMediaWiki :: WriterOptions -> [Block] -> State WriterState String listItemToMediaWiki opts items = do contents <- blockListToMediaWiki opts items useTags <- get >>= return . stUseTags if useTags then return $ "<li>" ++ contents ++ "</li>" else do marker <- get >>= return . stListLevel return $ marker ++ " " ++ contents -- | Convert definition list item (label, list of blocks) to MediaWiki. definitionListItemToMediaWiki :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState String definitionListItemToMediaWiki opts (label, items) = do labelText <- inlineListToMediaWiki opts label contents <- mapM (blockListToMediaWiki opts) items useTags <- get >>= return . stUseTags if useTags then return $ "<dt>" ++ labelText ++ "</dt>\n" ++ (intercalate "\n" $ map (\d -> "<dd>" ++ d ++ "</dd>") contents) else do marker <- get >>= return . stListLevel return $ marker ++ " " ++ labelText ++ "\n" ++ (intercalate "\n" $ map (\d -> init marker ++ ": " ++ d) contents) -- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed. isSimpleList :: Block -> Bool isSimpleList x = case x of BulletList items -> all isSimpleListItem items OrderedList (num, sty, _) items -> all isSimpleListItem items && num == 1 && sty `elem` [DefaultStyle, Decimal] DefinitionList items -> all isSimpleListItem $ concatMap snd items _ -> False -- | True if list item can be handled with the simple wiki syntax. False if -- HTML tags will be needed. isSimpleListItem :: [Block] -> Bool isSimpleListItem [] = True isSimpleListItem [x] = case x of Plain _ -> True Para _ -> True BulletList _ -> isSimpleList x OrderedList _ _ -> isSimpleList x DefinitionList _ -> isSimpleList x _ -> False isSimpleListItem [x, y] | isPlainOrPara x = case y of BulletList _ -> isSimpleList y OrderedList _ _ -> isSimpleList y DefinitionList _ -> isSimpleList y _ -> False isSimpleListItem _ = False isPlainOrPara :: Block -> Bool isPlainOrPara (Plain _) = True isPlainOrPara (Para _) = True isPlainOrPara _ = False -- | Concatenates strings with line breaks between them. vcat :: [String] -> String vcat = intercalate "\n" -- Auxiliary functions for tables: tableRowToMediaWiki :: WriterOptions -> Bool -> [Alignment] -> [Double] -> (Int, [[Block]]) -> State WriterState String tableRowToMediaWiki opts headless alignments widths (rownum, cells) = do cells' <- mapM (\cellData -> tableCellToMediaWiki opts headless rownum cellData) $ zip3 alignments widths cells return $ unlines cells' tableCellToMediaWiki :: WriterOptions -> Bool -> Int -> (Alignment, Double, [Block]) -> State WriterState String tableCellToMediaWiki opts headless rownum (alignment, width, bs) = do contents <- blockListToMediaWiki opts bs let marker = if rownum == 1 && not headless then "!" else "|" let percent w = show (truncate (100*w) :: Integer) ++ "%" let attrs = ["align=" ++ show (alignmentToString alignment) | alignment /= AlignDefault && alignment /= AlignLeft] ++ ["width=\"" ++ percent width ++ "\"" | width /= 0.0 && rownum == 1] let attr = if null attrs then "" else unwords attrs ++ "|" return $ marker ++ attr ++ trimr contents alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center" AlignDefault -> "left" -- | Convert list of Pandoc block elements to MediaWiki. blockListToMediaWiki :: WriterOptions -- ^ Options -> [Block] -- ^ List of block elements -> State WriterState String blockListToMediaWiki opts blocks = mapM (blockToMediaWiki opts) blocks >>= return . vcat -- | Convert list of Pandoc inline elements to MediaWiki. inlineListToMediaWiki :: WriterOptions -> [Inline] -> State WriterState String inlineListToMediaWiki opts lst = mapM (inlineToMediaWiki opts) lst >>= return . concat -- | Convert Pandoc inline element to MediaWiki. inlineToMediaWiki :: WriterOptions -> Inline -> State WriterState String inlineToMediaWiki opts (Span attrs ils) = do contents <- inlineListToMediaWiki opts ils return $ render Nothing (tagWithAttrs "span" attrs) ++ contents ++ "</span>" inlineToMediaWiki opts (Emph lst) = do contents <- inlineListToMediaWiki opts lst return $ "''" ++ contents ++ "''" inlineToMediaWiki opts (Strong lst) = do contents <- inlineListToMediaWiki opts lst return $ "'''" ++ contents ++ "'''" inlineToMediaWiki opts (Strikeout lst) = do contents <- inlineListToMediaWiki opts lst return $ "<s>" ++ contents ++ "</s>" inlineToMediaWiki opts (Superscript lst) = do contents <- inlineListToMediaWiki opts lst return $ "<sup>" ++ contents ++ "</sup>" inlineToMediaWiki opts (Subscript lst) = do contents <- inlineListToMediaWiki opts lst return $ "<sub>" ++ contents ++ "</sub>" inlineToMediaWiki opts (SmallCaps lst) = inlineListToMediaWiki opts lst inlineToMediaWiki opts (Quoted SingleQuote lst) = do contents <- inlineListToMediaWiki opts lst return $ "\8216" ++ contents ++ "\8217" inlineToMediaWiki opts (Quoted DoubleQuote lst) = do contents <- inlineListToMediaWiki opts lst return $ "\8220" ++ contents ++ "\8221" inlineToMediaWiki opts (Cite _ lst) = inlineListToMediaWiki opts lst inlineToMediaWiki _ (Code _ str) = return $ "<code>" ++ (escapeString str) ++ "</code>" inlineToMediaWiki _ (Str str) = return $ escapeString str inlineToMediaWiki _ (Math _ str) = return $ "<math>" ++ str ++ "</math>" -- note: str should NOT be escaped inlineToMediaWiki _ (RawInline f str) | f == Format "mediawiki" = return str | f == Format "html" = return str | otherwise = return "" inlineToMediaWiki _ (LineBreak) = return "<br />" inlineToMediaWiki _ Space = return " " inlineToMediaWiki opts (Link txt (src, _)) = do label <- inlineListToMediaWiki opts txt case txt of [Str s] | escapeURI s == src -> return src _ -> if isURI src then return $ "[" ++ src ++ " " ++ label ++ "]" else return $ "[[" ++ src' ++ "|" ++ label ++ "]]" where src' = case src of '/':xs -> xs -- with leading / it's a _ -> src -- link to a help page inlineToMediaWiki opts (Image alt (source, tit)) = do alt' <- inlineListToMediaWiki opts alt let txt = if (null tit) then if null alt then "" else "|" ++ alt' else "|" ++ tit return $ "[[Image:" ++ source ++ txt ++ "]]" inlineToMediaWiki opts (Note contents) = do contents' <- blockListToMediaWiki opts contents modify (\s -> s { stNotes = True }) return $ "<ref>" ++ contents' ++ "</ref>" -- note - may not work for notes with multiple blocks ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Native.hs���������������������������������������������������000644 �000765 �000024 �00000005772 12251233602 021267� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Native Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of a 'Pandoc' document to a string representation. Note: If @writerStandalone@ is @False@, only the document body is represented; otherwise, the full 'Pandoc' document, including the metadata. -} module Text.Pandoc.Writers.Native ( writeNative ) where import Text.Pandoc.Options ( WriterOptions(..) ) import Data.List ( intersperse ) import Text.Pandoc.Definition import Text.Pandoc.Pretty prettyList :: [Doc] -> Doc prettyList ds = "[" <> (cat $ intersperse (cr <> ",") $ map (nest 1) ds) <> "]" -- | Prettyprint Pandoc block element. prettyBlock :: Block -> Doc prettyBlock (BlockQuote blocks) = "BlockQuote" $$ prettyList (map prettyBlock blocks) prettyBlock (OrderedList attribs blockLists) = "OrderedList" <> space <> text (show attribs) $$ (prettyList $ map (prettyList . map prettyBlock) blockLists) prettyBlock (BulletList blockLists) = "BulletList" $$ (prettyList $ map (prettyList . map prettyBlock) blockLists) prettyBlock (DefinitionList items) = "DefinitionList" $$ (prettyList $ map deflistitem items) where deflistitem (term, defs) = "(" <> text (show term) <> "," <> cr <> nest 1 (prettyList $ map (prettyList . map prettyBlock) defs) <> ")" prettyBlock (Table caption aligns widths header rows) = "Table " <> text (show caption) <> " " <> text (show aligns) <> " " <> text (show widths) $$ prettyRow header $$ prettyList (map prettyRow rows) where prettyRow cols = prettyList (map (prettyList . map prettyBlock) cols) prettyBlock block = text $ show block -- | Prettyprint Pandoc document. writeNative :: WriterOptions -> Pandoc -> String writeNative opts (Pandoc meta blocks) = let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing withHead = if writerStandalone opts then \bs -> text ("Pandoc (" ++ show meta ++ ")") $$ bs $$ cr else id in render colwidth $ withHead $ prettyList $ map prettyBlock blocks ������pandoc-1.12.2.1/src/Text/Pandoc/Writers/ODT.hs������������������������������������������������������000644 �000765 �000024 �00000013572 12251233602 020464� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE ScopedTypeVariables #-} {- Copyright (C) 2008-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.ODT Copyright : Copyright (C) 2008-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to ODT. -} module Text.Pandoc.Writers.ODT ( writeODT ) where import Data.IORef import Data.List ( isPrefixOf ) import qualified Data.ByteString.Lazy as B import Text.Pandoc.UTF8 ( fromStringLazy ) import Codec.Archive.Zip import Text.Pandoc.Options ( WriterOptions(..) ) import Text.Pandoc.Shared ( stringify, readDataFile, fetchItem, warn ) import Text.Pandoc.ImageSize ( imageSize, sizeInPoints ) import Text.Pandoc.MIME ( getMimeType ) import Text.Pandoc.Definition import Text.Pandoc.Walk 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 ) -- | Produce an ODT file from a Pandoc document. writeODT :: WriterOptions -- ^ Writer options -> Pandoc -- ^ Document to convert -> IO B.ByteString writeODT opts doc@(Pandoc meta _) = do let datadir = writerUserDataDir opts let title = docTitle meta refArchive <- liftM toArchive $ case writerReferenceODT opts of Just f -> B.readFile f Nothing -> (B.fromChunks . (:[])) `fmap` readDataFile datadir "reference.odt" -- handle pictures picEntriesRef <- newIORef ([] :: [Entry]) doc' <- walkM (transformPic opts picEntriesRef) doc let newContents = writeOpenDocument opts{writerWrapText = False} doc' epochtime <- floor `fmap` getPOSIXTime let contentEntry = toEntry "content.xml" epochtime $ fromStringLazy newContents picEntries <- readIORef picEntriesRef let archive = foldr addEntryToArchive refArchive $ contentEntry : picEntries -- construct META-INF/manifest.xml based on archive let toFileEntry fp = case getMimeType fp of Nothing -> empty Just m -> selfClosingTag "manifest:file-entry" [("manifest:media-type", m) ,("manifest:full-path", fp) ,("manifest:version", "1.2") ] let files = [ ent | ent <- filesInArchive archive, not ("META-INF" `isPrefixOf` ent) ] let manifestEntry = toEntry "META-INF/manifest.xml" epochtime $ fromStringLazy $ render Nothing $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>" $$ ( inTags True "manifest:manifest" [("xmlns:manifest","urn:oasis:names:tc:opendocument:xmlns:manifest:1.0") ,("manifest:version","1.2")] $ ( selfClosingTag "manifest:file-entry" [("manifest:media-type","application/vnd.oasis.opendocument.text") ,("manifest:full-path","/")] $$ vcat ( map toFileEntry $ files ) ) ) let archive' = addEntryToArchive manifestEntry archive let metaEntry = toEntry "meta.xml" epochtime $ fromStringLazy $ render Nothing $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>" $$ ( inTags True "office:document-meta" [("xmlns:office","urn:oasis:names:tc:opendocument:xmlns:office: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:ooo","http://openoffice.org/2004/office") ,("xmlns:grddl","http://www.w3.org/2003/g/data-view#") ,("office:version","1.2")] $ ( inTagsSimple "office:meta" $ ( inTagsSimple "dc:title" (text $ escapeStringForXML (stringify title)) ) ) ) -- make sure mimetype is first let mimetypeEntry = toEntry "mimetype" epochtime $ fromStringLazy "application/vnd.oasis.opendocument.text" let archive'' = addEntryToArchive mimetypeEntry $ addEntryToArchive metaEntry archive' return $ fromArchive archive'' transformPic :: WriterOptions -> IORef [Entry] -> Inline -> IO Inline transformPic opts entriesRef (Image lab (src,_)) = do res <- fetchItem (writerSourceURL opts) src case res of Left (_ :: E.SomeException) -> do warn $ "Could not find image `" ++ src ++ "', skipping..." return $ Emph lab Right (img, _) -> do let size = imageSize img let (w,h) = maybe (0,0) id $ sizeInPoints `fmap` size let tit' = show w ++ "x" ++ show h entries <- readIORef entriesRef let newsrc = "Pictures/" ++ show (length entries) ++ takeExtension src let toLazy = B.fromChunks . (:[]) epochtime <- floor `fmap` getPOSIXTime let entry = toEntry newsrc epochtime $ toLazy img modifyIORef entriesRef (entry:) return $ Image lab (newsrc, tit') transformPic _ _ x = return x ��������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/OpenDocument.hs���������������������������������������������000644 �000765 �000024 �00000063163 12251233602 022437� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE PatternGuards, OverloadedStrings #-} {- Copyright (C) 2008-2010 Andrea Rossato <andrea.rossato@ing.unitn.it> and John MacFarlane. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.OpenDocument Copyright : Copyright (C) 2008-2010 Andrea Rossato and John MacFarlane License : GNU GPL, version 2 or above Maintainer : Andrea Rossato <andrea.rossato@ing.unitn.it> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to OpenDocument XML. -} module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.XML import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Pretty import Text.Printf ( printf ) import Control.Applicative ( (<$>) ) import Control.Arrow ( (***), (>>>) ) import Control.Monad.State hiding ( when ) import Data.Char (chr, isDigit) import qualified Data.Map as Map import Text.Pandoc.Writers.Shared -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block plainToPara (Plain x) = Para x plainToPara x = x -- -- OpenDocument writer -- data WriterState = WriterState { stNotes :: [Doc] , stTableStyles :: [Doc] , stParaStyles :: [Doc] , stListStyles :: [(Int, [Doc])] , stTextStyles :: [Doc] , stTextStyleAttr :: Map.Map TextStyle [(String,String)] , stIndentPara :: Int , stInDefinition :: Bool , stTight :: Bool , stFirstPara :: Bool , stImageId :: Int } defaultWriterState :: WriterState defaultWriterState = WriterState { stNotes = [] , stTableStyles = [] , stParaStyles = [] , stListStyles = [] , stTextStyles = [] , stTextStyleAttr = Map.empty , stIndentPara = 0 , stInDefinition = False , stTight = False , stFirstPara = False , stImageId = 1 } when :: Bool -> Doc -> Doc when p a = if p then a else empty addTableStyle :: Doc -> State WriterState () addTableStyle i = modify $ \s -> s { stTableStyles = i : stTableStyles s } addNote :: Doc -> State WriterState () addNote i = modify $ \s -> s { stNotes = i : stNotes s } addParaStyle :: Doc -> State WriterState () addParaStyle i = modify $ \s -> s { stParaStyles = i : stParaStyles s } addTextStyle :: Doc -> State WriterState () addTextStyle i = modify $ \s -> s { stTextStyles = i : stTextStyles s } addTextStyleAttr :: (TextStyle, [(String,String)]) -> State WriterState () addTextStyleAttr (ts, xs) = modify $ \s -> s { stTextStyleAttr = Map.insert ts xs (stTextStyleAttr s) } rmTextStyleAttr :: TextStyle -> State WriterState () rmTextStyleAttr ts = modify $ \s -> s { stTextStyleAttr = Map.delete ts (stTextStyleAttr s) } increaseIndent :: State WriterState () increaseIndent = modify $ \s -> s { stIndentPara = 1 + stIndentPara s } resetIndent :: State WriterState () resetIndent = modify $ \s -> s { stIndentPara = (stIndentPara s) - 1 } inTightList :: State WriterState a -> State WriterState a inTightList f = modify (\s -> s { stTight = True }) >> f >>= \r -> modify (\s -> s { stTight = False }) >> return r setInDefinitionList :: Bool -> State WriterState () setInDefinitionList b = modify $ \s -> s { stInDefinition = b } setFirstPara :: State WriterState () setFirstPara = modify $ \s -> s { stFirstPara = True } inParagraphTags :: Doc -> State WriterState Doc inParagraphTags d | isEmpty d = return empty inParagraphTags d = do b <- gets stFirstPara a <- if b then do modify $ \st -> st { stFirstPara = False } return $ [("text:style-name", "First_20_paragraph")] else return [("text:style-name", "Text_20_body")] return $ inTags False "text:p" a d inParagraphTagsWithStyle :: String -> Doc -> Doc inParagraphTagsWithStyle sty = inTags False "text:p" [("text:style-name", sty)] inSpanTags :: String -> Doc -> Doc inSpanTags s = inTags False "text:span" [("text:style-name",s)] withTextStyle :: TextStyle -> State WriterState a -> State WriterState a withTextStyle s f = addTextStyleAttr (s,textStyleAttr s) >> f >>= \r -> rmTextStyleAttr s >> return r inTextStyle :: Doc -> State WriterState Doc inTextStyle d = do at <- gets stTextStyleAttr if Map.null at then return d else do tn <- (+) 1 . length <$> gets stTextStyles addTextStyle $ inTags False "style:style" [("style:name" , "T" ++ show tn) ,("style:family", "text" )] $ selfClosingTag "style:text-properties" (concatMap snd $ Map.toList at) return $ inTags False "text:span" [("text:style-name","T" ++ show tn)] d inHeaderTags :: Int -> Doc -> State WriterState Doc inHeaderTags i d = return $ inTags False "text:h" [ ("text:style-name", "Heading_20_" ++ show i) , ("text:outline-level", show i)] d inQuotes :: QuoteType -> Doc -> Doc inQuotes SingleQuote s = char '\8216' <> s <> char '\8217' inQuotes DoubleQuote s = char '\8220' <> s <> char '\8221' handleSpaces :: String -> Doc handleSpaces s | ( ' ':_) <- s = genTag s | ('\t':x) <- s = selfClosingTag "text:tab" [] <> rm x | otherwise = rm s where genTag = span (==' ') >>> tag . length *** rm >>> uncurry (<>) tag n = when (n /= 0) $ selfClosingTag "text:s" [("text:c", show n)] rm ( ' ':xs) = char ' ' <> genTag xs rm ('\t':xs) = selfClosingTag "text:tab" [] <> genTag xs rm ( x:xs) = char x <> rm xs rm [] = empty -- | Convert Pandoc document to string in OpenDocument format. writeOpenDocument :: WriterOptions -> Pandoc -> String writeOpenDocument opts (Pandoc meta blocks) = let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing render' = render colwidth ((body, metadata),s) = flip runState defaultWriterState $ do m <- metaToJSON opts (fmap (render colwidth) . blocksToOpenDocument opts) (fmap (render colwidth) . inlinesToOpenDocument opts) meta b <- render' `fmap` blocksToOpenDocument opts blocks return (b, m) styles = stTableStyles s ++ stParaStyles s ++ stTextStyles s listStyle (n,l) = inTags True "text:list-style" [("style:name", "L" ++ show n)] (vcat l) listStyles = map listStyle (stListStyles s) automaticStyles = inTagsIndented "office:automatic-styles" $ vcat $ reverse $ styles ++ listStyles context = defField "body" body $ defField "automatic-styles" (render' automaticStyles) $ metadata in if writerStandalone opts then renderTemplate' (writerTemplate opts) context else body withParagraphStyle :: WriterOptions -> String -> [Block] -> State WriterState Doc withParagraphStyle o s (b:bs) | Para l <- b = go =<< inParagraphTagsWithStyle s <$> inlinesToOpenDocument o l | otherwise = go =<< blockToOpenDocument o b where go i = (<>) i <$> withParagraphStyle o s bs withParagraphStyle _ _ [] = return empty inPreformattedTags :: String -> State WriterState Doc inPreformattedTags s = do n <- paraStyle "Preformatted_20_Text" [] return . inParagraphTagsWithStyle ("P" ++ show n) . handleSpaces $ s orderedListToOpenDocument :: WriterOptions -> Int -> [[Block]] -> State WriterState Doc orderedListToOpenDocument o pn bs = vcat . map (inTagsIndented "text:list-item") <$> mapM (orderedItemToOpenDocument o pn . map plainToPara) bs orderedItemToOpenDocument :: WriterOptions -> Int -> [Block] -> State WriterState Doc orderedItemToOpenDocument o n (b:bs) | OrderedList a l <- b = newLevel a l | Para l <- b = go =<< inParagraphTagsWithStyle ("P" ++ show n) <$> inlinesToOpenDocument o l | otherwise = go =<< blockToOpenDocument o b where go i = ($$) i <$> orderedItemToOpenDocument o n bs newLevel a l = do nn <- length <$> gets stParaStyles ls <- head <$> gets stListStyles modify $ \s -> s { stListStyles = orderedListLevelStyle a ls : tail (stListStyles s) } inTagsIndented "text:list" <$> orderedListToOpenDocument o nn l orderedItemToOpenDocument _ _ [] = return empty isTightList :: [[Block]] -> Bool isTightList [] = False isTightList (b:_) | Plain {} : _ <- b = True | otherwise = False newOrderedListStyle :: Bool -> ListAttributes -> State WriterState (Int,Int) newOrderedListStyle b a = do ln <- (+) 1 . length <$> gets stListStyles let nbs = orderedListLevelStyle a (ln, []) pn <- if b then inTightList (paraListStyle ln) else paraListStyle ln modify $ \s -> s { stListStyles = nbs : stListStyles s } return (ln,pn) bulletListToOpenDocument :: WriterOptions -> [[Block]] -> State WriterState Doc bulletListToOpenDocument o b = do ln <- (+) 1 . length <$> gets stListStyles (pn,ns) <- if isTightList b then inTightList (bulletListStyle ln) else bulletListStyle ln modify $ \s -> s { stListStyles = ns : stListStyles s } is <- listItemsToOpenDocument ("P" ++ show pn) o b return $ inTags True "text:list" [("text:style-name", "L" ++ show ln)] is listItemsToOpenDocument :: String -> WriterOptions -> [[Block]] -> State WriterState Doc listItemsToOpenDocument s o is = vcat . map (inTagsIndented "text:list-item") <$> mapM (withParagraphStyle o s . map plainToPara) is deflistItemToOpenDocument :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState Doc deflistItemToOpenDocument o (t,d) = do let ts = if isTightList d then "Definition_20_Term_20_Tight" else "Definition_20_Term" ds = if isTightList d then "Definition_20_Definition_20_Tight" else "Definition_20_Definition" t' <- withParagraphStyle o ts [Para t] d' <- liftM vcat $ mapM (withParagraphStyle o ds . (map plainToPara)) d return $ t' $$ d' inBlockQuote :: WriterOptions -> Int -> [Block] -> State WriterState Doc inBlockQuote o i (b:bs) | BlockQuote l <- b = do increaseIndent ni <- paraStyle "Quotations" [] go =<< inBlockQuote o ni (map plainToPara l) | Para l <- b = do go =<< inParagraphTagsWithStyle ("P" ++ show i) <$> inlinesToOpenDocument o l | otherwise = do go =<< blockToOpenDocument o b where go block = ($$) block <$> inBlockQuote o i bs inBlockQuote _ _ [] = resetIndent >> return empty -- | Convert a list of Pandoc blocks to OpenDocument. blocksToOpenDocument :: WriterOptions -> [Block] -> State WriterState Doc 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 | Div _ xs <- bs = blocksToOpenDocument o xs | Header i _ b <- bs = setFirstPara >> (inHeaderTags i =<< inlinesToOpenDocument o b) | BlockQuote b <- bs = setFirstPara >> mkBlockQuote b | DefinitionList b <- bs = setFirstPara >> defList b | BulletList b <- bs = setFirstPara >> bulletListToOpenDocument o b | OrderedList a b <- bs = setFirstPara >> orderedList a b | CodeBlock _ s <- bs = setFirstPara >> preformatted s | 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 else return empty | Null <- bs = return empty | otherwise = return empty where defList b = do setInDefinitionList True r <- vcat <$> mapM (deflistItemToOpenDocument o) b setInDefinitionList False return r preformatted s = (flush . vcat) <$> mapM (inPreformattedTags . escapeStringForXML) (lines s) mkBlockQuote b = do increaseIndent i <- paraStyle "Quotations" [] inBlockQuote o i (map plainToPara b) orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a inTags True "text:list" [ ("text:style-name", "L" ++ show ln)] <$> orderedListToOpenDocument o pn b table c a w h r = do tn <- length <$> gets stTableStyles pn <- length <$> gets stParaStyles let genIds = map chr [65..] name = "Table" ++ show (tn + 1) columnIds = zip genIds w mkColumn n = selfClosingTag "table:table-column" [("table:style-name", name ++ "." ++ [fst n])] columns = map mkColumn columnIds paraHStyles = paraTableStyles "Heading" pn a paraStyles = paraTableStyles "Contents" (pn + length (newPara paraHStyles)) a newPara = map snd . filter (not . isEmpty . snd) addTableStyle $ tableStyle tn columnIds mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles captionDoc <- if null c then return empty else withParagraphStyle o "Caption" [Para c] th <- if all null h then return empty else colHeadsToOpenDocument o name (map fst paraHStyles) h tr <- mapM (tableRowToOpenDocument o name (map fst paraStyles)) r return $ inTags True "table:table" [ ("table:name" , name) , ("table:style-name", name) ] (vcat columns $$ th $$ vcat tr) $$ captionDoc colHeadsToOpenDocument :: WriterOptions -> String -> [String] -> [[Block]] -> State WriterState Doc colHeadsToOpenDocument o tn ns hs = inTagsIndented "table:table-header-rows" . inTagsIndented "table:table-row" . vcat <$> mapM (tableItemToOpenDocument o tn) (zip ns hs) tableRowToOpenDocument :: WriterOptions -> String -> [String] -> [[Block]] -> State WriterState Doc tableRowToOpenDocument o tn ns cs = inTagsIndented "table:table-row" . vcat <$> mapM (tableItemToOpenDocument o tn) (zip ns cs) tableItemToOpenDocument :: WriterOptions -> String -> (String,[Block])-> State WriterState Doc tableItemToOpenDocument o tn (n,i) = let a = [ ("table:style-name" , tn ++ ".A1" ) , ("office:value-type", "string" ) ] in inTags True "table:table-cell" a <$> withParagraphStyle o n (map plainToPara i) -- | Convert a list of inline elements to OpenDocument. inlinesToOpenDocument :: WriterOptions -> [Inline] -> State WriterState Doc inlinesToOpenDocument o l = hcat <$> mapM (inlineToOpenDocument o) l -- | Convert an inline element to OpenDocument. inlineToOpenDocument :: WriterOptions -> Inline -> State WriterState Doc inlineToOpenDocument o ils | Space <- ils = inTextStyle space | Span _ xs <- ils = inlinesToOpenDocument o xs | LineBreak <- ils = return $ selfClosingTag "text:line-break" [] | Str s <- ils = inTextStyle $ handleSpaces $ escapeStringForXML s | Emph l <- ils = withTextStyle Italic $ inlinesToOpenDocument o l | Strong l <- ils = withTextStyle Bold $ inlinesToOpenDocument o l | Strikeout l <- ils = withTextStyle Strike $ inlinesToOpenDocument o l | Superscript l <- ils = withTextStyle Sup $ inlinesToOpenDocument o l | 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 = 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" then return $ preformatted s else return empty | Link l (s,t) <- ils = mkLink s t <$> inlinesToOpenDocument o l | Image _ (s,t) <- ils = mkImg s t | Note l <- ils = mkNote l | otherwise = return empty where 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 = 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" ) , ("xlink:actuate", "onLoad")] mkNote l = do n <- length <$> gets stNotes let footNote t = inTags False "text:note" [ ("text:id" , "ftn" ++ show n) , ("text:note-class", "footnote" )] $ inTagsSimple "text:note-citation" (text . show $ n + 1) <> inTagsSimple "text:note-body" t nn <- footNote <$> withParagraphStyle o "Footnote" l addNote nn return nn -- a title of the form "120x140" will be interpreted as image -- size in points. attrsFromTitle :: String -> [(String,String)] attrsFromTitle s = if null xs || null ys then [] else [("svg:width",xs ++ "pt"),("svg:height",ys ++ "pt")] where (xs,rest) = span isDigit s ys = case rest of ('x':zs) | all isDigit zs -> zs _ -> "" bulletListStyle :: Int -> State WriterState (Int,(Int,[Doc])) bulletListStyle l = let doStyles i = inTags True "text:list-level-style-bullet" [ ("text:level" , show (i + 1) ) , ("text:style-name" , "Bullet_20_Symbols") , ("style:num-suffix", "." ) , ("text:bullet-char", [bulletList !! i] ) ] (listLevelStyle (1 + i)) bulletList = map chr $ cycle [8226,8227,8259] listElStyle = map doStyles [0..9] in do pn <- paraListStyle l return (pn, (l, listElStyle)) orderedListLevelStyle :: ListAttributes -> (Int, [Doc]) -> (Int,[Doc]) orderedListLevelStyle (s,n, d) (l,ls) = let suffix = case d of OneParen -> [("style:num-suffix", ")")] TwoParens -> [("style:num-prefix", "(") ,("style:num-suffix", ")")] _ -> [("style:num-suffix", ".")] format = case n of UpperAlpha -> "A" LowerAlpha -> "a" UpperRoman -> "I" LowerRoman -> "i" _ -> "1" listStyle = inTags True "text:list-level-style-number" ([ ("text:level" , show $ 1 + length ls ) , ("text:style-name" , "Numbering_20_Symbols") , ("style:num-format", format ) , ("text:start-value", show s ) ] ++ suffix) (listLevelStyle (1 + length ls)) in (l, ls ++ [listStyle]) listLevelStyle :: Int -> Doc listLevelStyle i = let indent = show (0.25 * fromIntegral i :: Double) in selfClosingTag "style:list-level-properties" [ ("text:space-before" , indent ++ "in") , ("text:min-label-width", "0.25in")] tableStyle :: Int -> [(Char,Double)] -> Doc tableStyle num wcs = let tableId = "Table" ++ show (num + 1) table = inTags True "style:style" [("style:name", tableId) ,("style:family", "table")] $ selfClosingTag "style:table-properties" [("table:align" , "center")] colStyle (c,0) = selfClosingTag "style:style" [ ("style:name" , tableId ++ "." ++ [c]) , ("style:family", "table-column" )] colStyle (c,w) = inTags True "style:style" [ ("style:name" , tableId ++ "." ++ [c]) , ("style:family", "table-column" )] $ selfClosingTag "style:table-column-properties" [("style:rel-column-width", printf "%d*" $ (floor $ w * 65535 :: Integer))] cellStyle = inTags True "style:style" [ ("style:name" , tableId ++ ".A1") , ("style:family", "table-cell" )] $ selfClosingTag "style:table-cell-properties" [ ("fo:border", "none")] columnStyles = map colStyle wcs in table $$ vcat columnStyles $$ cellStyle paraStyle :: String -> [(String,String)] -> State WriterState Int paraStyle parent attrs = do pn <- (+) 1 . length <$> gets stParaStyles i <- (*) 0.5 . fromIntegral <$> gets stIndentPara :: State WriterState Double b <- gets stInDefinition t <- gets stTight let styleAttr = [ ("style:name" , "P" ++ show pn) , ("style:family" , "paragraph" ) , ("style:parent-style-name", parent )] indentVal = flip (++) "in" . show $ if b then (max 0.5 i) else i tight = if t then [ ("fo:margin-top" , "0in" ) , ("fo:margin-bottom" , "0in" )] else [] indent = if (i /= 0 || b) then [ ("fo:margin-left" , indentVal) , ("fo:margin-right" , "0in" ) , ("fo:text-indent" , "0in" ) , ("style:auto-text-indent" , "false" )] else [] attributes = indent ++ tight paraProps = when (not $ null attributes) $ selfClosingTag "style:paragraph-properties" attributes addParaStyle $ inTags True "style:style" (styleAttr ++ attrs) paraProps return pn paraListStyle :: Int -> State WriterState Int paraListStyle l = paraStyle "Text_20_body" [("style:list-style-name", "L" ++ show l )] paraTableStyles :: String -> Int -> [Alignment] -> [(String, Doc)] paraTableStyles _ _ [] = [] paraTableStyles t s (a:xs) | AlignRight <- a = ( pName s, res s "end" ) : paraTableStyles t (s + 1) xs | AlignCenter <- a = ( pName s, res s "center") : paraTableStyles t (s + 1) xs | otherwise = ("Table_20_" ++ t, empty ) : paraTableStyles t s xs where pName sn = "P" ++ show (sn + 1) res sn x = inTags True "style:style" [ ("style:name" , pName sn ) , ("style:family" , "paragraph" ) , ("style:parent-style-name", "Table_20_" ++ t)] $ selfClosingTag "style:paragraph-properties" [ ("fo:text-align", x) , ("style:justify-single-word", "false")] data TextStyle = Italic | Bold | Strike | Sub | Sup | SmallC | Pre deriving ( Eq,Ord ) textStyleAttr :: TextStyle -> [(String,String)] textStyleAttr s | Italic <- s = [("fo:font-style" ,"italic" ) ,("style:font-style-asian" ,"italic" ) ,("style:font-style-complex" ,"italic" )] | Bold <- s = [("fo:font-weight" ,"bold" ) ,("style:font-weight-asian" ,"bold" ) ,("style:font-weight-complex" ,"bold" )] | Strike <- s = [("style:text-line-through-style", "solid" )] | 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 = [] �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/OPML.hs�����������������������������������������������������000644 �000765 �000024 �00000006604 12251233602 020603� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2013 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.OPML Copyright : Copyright (C) 2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to OPML XML. -} module Text.Pandoc.Writers.OPML ( writeOPML) where import Text.Pandoc.Definition import Text.Pandoc.XML import Text.Pandoc.Writers.Shared import Text.Pandoc.Shared import Text.Pandoc.Options import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Writers.HTML (writeHtmlString) import Text.Pandoc.Writers.Markdown (writeMarkdown) import Text.Pandoc.Pretty import Data.Time import System.Locale (defaultTimeLocale) import qualified Text.Pandoc.Builder as B -- | Convert Pandoc document to string in OPML format. writeOPML :: WriterOptions -> Pandoc -> String writeOPML opts (Pandoc meta blocks) = let elements = hierarchicalize blocks colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing meta' = B.setMeta "date" (B.str $ convertDate $ docDate meta) meta Just metadata = metaToJSON opts (Just . writeMarkdown def . Pandoc nullMeta) (Just . trimr . writeMarkdown def . Pandoc nullMeta . (\ils -> [Plain ils])) meta' main = render colwidth $ vcat (map (elementToOPML opts) elements) context = defField "body" main metadata in if writerStandalone opts then renderTemplate' (writerTemplate opts) context else main writeHtmlInlines :: [Inline] -> String writeHtmlInlines ils = trim $ writeHtmlString def $ Pandoc nullMeta [Plain ils] -- date format: RFC 822: Thu, 14 Jul 2005 23:41:05 GMT showDateTimeRFC822 :: UTCTime -> String showDateTimeRFC822 = formatTime defaultTimeLocale "%a, %d %b %Y %X %Z" convertDate :: [Inline] -> String convertDate ils = maybe "" showDateTimeRFC822 $ parseTime defaultTimeLocale "%F" =<< (normalizeDate $ stringify ils) -- | Convert an Element to OPML. elementToOPML :: WriterOptions -> Element -> Doc elementToOPML _ (Blk _) = empty elementToOPML opts (Sec _ _num _ title elements) = let isBlk (Blk _) = True isBlk _ = False fromBlk (Blk x) = x fromBlk _ = error "fromBlk called on non-block" (blocks, rest) = span isBlk elements attrs = [("text", writeHtmlInlines title)] ++ [("_note", writeMarkdown def (Pandoc nullMeta (map fromBlk blocks))) | not (null blocks)] in inTags True "outline" attrs $ vcat (map (elementToOPML opts) rest) ����������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Org.hs������������������������������������������������������000644 �000765 �000024 �00000027462 12251233602 020570� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2006-2010 Puneeth Chaganti <punchagan@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Org Copyright : Copyright (C) 2010 Puneeth Chaganti License : GNU GPL, version 2 or above Maintainer : Puneeth Chaganti <punchagan@gmail.com> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to Emacs Org-Mode. Org-Mode: <http://orgmode.org> -} module Text.Pandoc.Writers.Org ( writeOrg) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Pretty import Text.Pandoc.Templates (renderTemplate') import Data.List ( intersect, intersperse, transpose ) import Control.Monad.State import Control.Applicative ( (<$>) ) data WriterState = WriterState { stNotes :: [[Block]] , stLinks :: Bool , stImages :: Bool , stHasMath :: Bool , stOptions :: WriterOptions } -- | Convert Pandoc to Org. writeOrg :: WriterOptions -> Pandoc -> String writeOrg opts document = let st = WriterState { stNotes = [], stLinks = False, stImages = False, stHasMath = False, stOptions = opts } in evalState (pandocToOrg document) st -- | Return Org representation of document. pandocToOrg :: Pandoc -> State WriterState String pandocToOrg (Pandoc meta blocks) = do opts <- liftM stOptions get let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing metadata <- metaToJSON opts (fmap (render colwidth) . blockListToOrg) (fmap (render colwidth) . inlineListToOrg) meta body <- blockListToOrg blocks notes <- liftM (reverse . stNotes) get >>= notesToOrg -- note that the notes may contain refs, so we do them first hasMath <- liftM stHasMath get let main = render colwidth $ foldl ($+$) empty $ [body, notes] let context = defField "body" main $ defField "math" hasMath $ metadata if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main -- | Return Org representation of notes. notesToOrg :: [[Block]] -> State WriterState Doc notesToOrg notes = mapM (\(num, note) -> noteToOrg num note) (zip [1..] notes) >>= return . vsep -- | Return Org representation of a note. noteToOrg :: Int -> [Block] -> State WriterState Doc noteToOrg num note = do contents <- blockListToOrg note let marker = "[" ++ show num ++ "] " return $ hang (length marker) (text marker) contents -- | Escape special characters for Org. escapeString :: String -> String escapeString = escapeStringUsing $ [ ('\x2014',"---") , ('\x2013',"--") , ('\x2019',"'") , ('\x2026',"...") ] ++ backslashEscapes "^_" -- | Convert Pandoc block element to Org. blockToOrg :: Block -- ^ Block element -> State WriterState Doc blockToOrg Null = return empty blockToOrg (Div attrs bs) = do contents <- blockListToOrg bs let startTag = tagWithAttrs "div" attrs let endTag = text "</div>" return $ blankline $$ "#+BEGIN_HTML" $$ nest 2 startTag $$ "#+END_HTML" $$ blankline $$ contents $$ blankline $$ "#+BEGIN_HTML" $$ nest 2 endTag $$ "#+END_HTML" $$ blankline blockToOrg (Plain inlines) = inlineListToOrg inlines -- title beginning with fig: indicates that the image is a figure blockToOrg (Para [Image txt (src,'f':'i':'g':':':tit)]) = do capt <- if null txt then return empty else (\c -> "#+CAPTION: " <> c <> blankline) `fmap` inlineListToOrg txt img <- inlineToOrg (Image txt (src,tit)) return $ capt <> img blockToOrg (Para inlines) = do contents <- inlineListToOrg inlines return $ contents <> blankline 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" = return $ text str blockToOrg (RawBlock _ _) = return empty blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline blockToOrg (Header level _ inlines) = do contents <- inlineListToOrg inlines let headerStr = text $ if level > 999 then " " else replicate level '*' return $ headerStr <> " " <> contents <> blankline blockToOrg (CodeBlock (_,classes,_) str) = do opts <- stOptions <$> get let tabstop = writerTabStop opts let at = classes `intersect` ["asymptote", "C", "clojure", "css", "ditaa", "dot", "emacs-lisp", "gnuplot", "haskell", "js", "latex", "ledger", "lisp", "matlab", "mscgen", "ocaml", "octave", "oz", "perl", "plantuml", "python", "R", "ruby", "sass", "scheme", "screen", "sh", "sql", "sqlite"] let (beg, end) = case at of [] -> ("#+BEGIN_EXAMPLE", "#+END_EXAMPLE") (x:_) -> ("#+BEGIN_SRC " ++ x, "#+END_SRC") return $ text beg $$ nest tabstop (text str) $$ text end $$ blankline blockToOrg (BlockQuote blocks) = do contents <- blockListToOrg blocks return $ blankline $$ "#+BEGIN_QUOTE" $$ nest 2 contents $$ "#+END_QUOTE" $$ blankline blockToOrg (Table caption' _ _ headers rows) = do caption'' <- inlineListToOrg caption' let caption = if null caption' then empty else ("#+CAPTION: " <> caption'') headers' <- mapM blockListToOrg headers rawRows <- mapM (mapM blockListToOrg) rows let numChars = maximum . map offset -- FIXME: width is not being used. let widthsInChars = map ((+2) . numChars) $ transpose (headers' : rawRows) -- FIXME: Org doesn't allow blocks with height more than 1. let hpipeBlocks blocks = hcat [beg, middle, end] where h = maximum (map height blocks) sep' = lblock 3 $ vcat (map text $ replicate h " | ") beg = lblock 2 $ vcat (map text $ replicate h "| ") end = lblock 2 $ vcat (map text $ replicate h " |") middle = hcat $ intersperse sep' blocks let makeRow = hpipeBlocks . zipWith lblock widthsInChars let head' = makeRow headers' rows' <- mapM (\row -> do cols <- mapM blockListToOrg row return $ makeRow cols) rows let border ch = char '|' <> char ch <> (hcat $ intersperse (char ch <> char '+' <> char ch) $ map (\l -> text $ replicate l ch) widthsInChars) <> char ch <> char '|' let body = vcat rows' let head'' = if all null headers then empty else head' $$ border '-' return $ head'' $$ body $$ caption $$ blankline blockToOrg (BulletList items) = do contents <- mapM bulletListItemToOrg items -- ensure that sublists have preceding blank line return $ blankline $+$ vcat contents $$ blankline blockToOrg (OrderedList (start, _, delim) items) = do let delim' = case delim of TwoParens -> OneParen x -> x let markers = take (length items) $ orderedListMarkers (start, Decimal, delim') let maxMarkerLength = maximum $ map length markers let markers' = map (\m -> let s = maxMarkerLength - length m in m ++ replicate s ' ') markers contents <- mapM (\(item, num) -> orderedListItemToOrg item num) $ zip markers' items -- ensure that sublists have preceding blank line return $ blankline $$ vcat contents $$ blankline blockToOrg (DefinitionList items) = do contents <- mapM definitionListItemToOrg items return $ vcat contents $$ blankline -- | Convert bullet list item (list of blocks) to Org. bulletListItemToOrg :: [Block] -> State WriterState Doc bulletListItemToOrg items = do contents <- blockListToOrg items return $ hang 3 "- " (contents <> cr) -- | Convert ordered list item (a list of blocks) to Org. orderedListItemToOrg :: String -- ^ marker for list item -> [Block] -- ^ list item (list of blocks) -> State WriterState Doc orderedListItemToOrg marker items = do contents <- blockListToOrg items return $ hang (length marker + 1) (text marker <> space) (contents <> cr) -- | Convert defintion list item (label, list of blocks) to Org. definitionListItemToOrg :: ([Inline], [[Block]]) -> State WriterState Doc definitionListItemToOrg (label, defs) = do label' <- inlineListToOrg label contents <- liftM vcat $ mapM blockListToOrg defs return $ hang 3 "- " $ label' <> " :: " <> (contents <> cr) -- | Convert list of Pandoc block elements to Org. blockListToOrg :: [Block] -- ^ List of block elements -> State WriterState Doc blockListToOrg blocks = mapM blockToOrg blocks >>= return . vcat -- | Convert list of Pandoc inline elements to Org. inlineListToOrg :: [Inline] -> State WriterState Doc inlineListToOrg lst = mapM inlineToOrg lst >>= return . hcat -- | Convert Pandoc inline element to Org. inlineToOrg :: Inline -> State WriterState Doc inlineToOrg (Span _ lst) = inlineListToOrg lst inlineToOrg (Emph lst) = do contents <- inlineListToOrg lst return $ "/" <> contents <> "/" inlineToOrg (Strong lst) = do contents <- inlineListToOrg lst return $ "*" <> contents <> "*" inlineToOrg (Strikeout lst) = do contents <- inlineListToOrg lst return $ "+" <> contents <> "+" inlineToOrg (Superscript lst) = do contents <- inlineListToOrg lst return $ "^{" <> contents <> "}" inlineToOrg (Subscript lst) = do contents <- inlineListToOrg lst return $ "_{" <> contents <> "}" inlineToOrg (SmallCaps lst) = inlineListToOrg lst inlineToOrg (Quoted SingleQuote lst) = do contents <- inlineListToOrg lst return $ "'" <> contents <> "'" inlineToOrg (Quoted DoubleQuote lst) = do contents <- inlineListToOrg lst return $ "\"" <> contents <> "\"" inlineToOrg (Cite _ lst) = inlineListToOrg lst inlineToOrg (Code _ str) = return $ "=" <> text str <> "=" inlineToOrg (Str str) = return $ text $ escapeString str inlineToOrg (Math t str) = do modify $ \st -> st{ stHasMath = True } return $ if t == InlineMath then "$" <> text str <> "$" else "$$" <> text str <> "$$" inlineToOrg (RawInline f str) | f == "tex" || f == "latex" = return $ text str inlineToOrg (RawInline _ _) = return empty inlineToOrg (LineBreak) = return cr -- there's no line break in Org inlineToOrg Space = return space inlineToOrg (Link txt (src, _)) = do case txt of [Str x] | escapeURI x == src -> -- autolink do modify $ \s -> s{ stLinks = True } return $ "[[" <> text x <> "]]" _ -> do contents <- inlineListToOrg txt modify $ \s -> s{ stLinks = True } return $ "[[" <> text src <> "][" <> contents <> "]]" inlineToOrg (Image _ (source, _)) = do modify $ \s -> s{ stImages = True } return $ "[[" <> text source <> "]]" inlineToOrg (Note contents) = do -- add to notes in state notes <- get >>= (return . stNotes) modify $ \st -> st { stNotes = contents:notes } let ref = show $ (length notes) + 1 return $ " [" <> text ref <> "]" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/RST.hs������������������������������������������������������000644 �000765 �000024 �00000044607 12251233602 020511� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.RST Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to reStructuredText. reStructuredText: <http://docutils.sourceforge.net/rst.html> -} module Text.Pandoc.Writers.RST ( writeRST ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Builder (deleteMeta) import Data.List ( isPrefixOf, intersperse, transpose ) import Network.URI (isURI) import Text.Pandoc.Pretty import Control.Monad.State import Control.Applicative ( (<$>) ) import Data.Char (isSpace, toLower) type Refs = [([Inline], Target)] data WriterState = WriterState { stNotes :: [[Block]] , stLinks :: Refs , stImages :: [([Inline], (String, String, Maybe String))] , stHasMath :: Bool , stOptions :: WriterOptions } -- | Convert Pandoc to RST. writeRST :: WriterOptions -> Pandoc -> String writeRST opts document = let st = WriterState { stNotes = [], stLinks = [], stImages = [], stHasMath = False, stOptions = opts } in evalState (pandocToRST document) st -- | Return RST representation of document. pandocToRST :: Pandoc -> State WriterState String pandocToRST (Pandoc meta blocks) = do opts <- liftM stOptions get let colwidth = if writerWrapText opts then Just $ writerColumns opts else Nothing let subtit = case lookupMeta "subtitle" meta of Just (MetaBlocks [Plain xs]) -> xs _ -> [] title <- titleToRST (docTitle meta) subtit metadata <- metaToJSON opts (fmap (render colwidth) . blockListToRST) (fmap (trimr . render colwidth) . inlineListToRST) $ deleteMeta "title" $ deleteMeta "subtitle" meta body <- blockListToRST blocks notes <- liftM (reverse . stNotes) get >>= notesToRST -- note that the notes may contain refs, so we do them first refs <- liftM (reverse . stLinks) get >>= refsToRST pics <- liftM (reverse . stImages) get >>= pictRefsToRST hasMath <- liftM stHasMath get let main = render colwidth $ foldl ($+$) empty $ [body, notes, refs, pics] let context = defField "body" main $ defField "toc" (writerTableOfContents opts) $ defField "toc-depth" (writerTOCDepth opts) $ defField "math" hasMath $ defField "title" (render Nothing title :: String) $ defField "math" hasMath $ metadata if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main -- | Return RST representation of reference key table. refsToRST :: Refs -> State WriterState Doc refsToRST refs = mapM keyToRST refs >>= return . vcat -- | Return RST representation of a reference key. keyToRST :: ([Inline], (String, String)) -> State WriterState Doc keyToRST (label, (src, _)) = do label' <- inlineListToRST label let label'' = if ':' `elem` (render Nothing label') then char '`' <> label' <> char '`' else label' return $ nowrap $ ".. _" <> label'' <> ": " <> text src -- | Return RST representation of notes. notesToRST :: [[Block]] -> State WriterState Doc notesToRST notes = mapM (\(num, note) -> noteToRST num note) (zip [1..] notes) >>= return . vsep -- | Return RST representation of a note. noteToRST :: Int -> [Block] -> State WriterState Doc noteToRST num note = do contents <- blockListToRST note let marker = ".. [" <> text (show num) <> "]" return $ nowrap $ marker $$ nest 3 contents -- | Return RST representation of picture reference table. pictRefsToRST :: [([Inline], (String, String, Maybe String))] -> State WriterState Doc pictRefsToRST refs = mapM pictToRST refs >>= return . vcat -- | Return RST representation of a picture substitution reference. pictToRST :: ([Inline], (String, String,Maybe String)) -> State WriterState Doc pictToRST (label, (src, _, mbtarget)) = do label' <- inlineListToRST label return $ nowrap $ ".. |" <> label' <> "| image:: " <> text src $$ case mbtarget of Nothing -> empty Just t -> " :target: " <> text t -- | Escape special characters for RST. escapeString :: String -> String escapeString = escapeStringUsing (backslashEscapes "`\\|*_") titleToRST :: [Inline] -> [Inline] -> State WriterState Doc titleToRST [] _ = return empty titleToRST tit subtit = do title <- inlineListToRST tit subtitle <- inlineListToRST subtit return $ bordered title '=' $$ bordered subtitle '-' bordered :: Doc -> Char -> Doc bordered contents c = if len > 0 then border $$ contents $$ border else empty where len = offset contents border = text (replicate len c) -- | Convert Pandoc block element to RST. blockToRST :: Block -- ^ Block element -> State WriterState Doc blockToRST Null = return empty blockToRST (Div attr bs) = do contents <- blockListToRST bs let startTag = ".. raw:: html" $+$ nest 3 (tagWithAttrs "div" attr) let endTag = ".. raw:: html" $+$ nest 3 "</div>" return $ blankline <> startTag $+$ contents $+$ endTag $$ blankline blockToRST (Plain inlines) = inlineListToRST inlines -- title beginning with fig: indicates that the image is a figure blockToRST (Para [Image txt (src,'f':'i':'g':':':tit)]) = do capt <- inlineListToRST txt let fig = "figure:: " <> text src let alt = ":alt: " <> if null tit then capt else text tit return $ hang 3 ".. " $ fig $$ alt $+$ capt $$ blankline blockToRST (Para inlines) | LineBreak `elem` inlines = do -- use line block if LineBreaks lns <- mapM inlineListToRST $ splitBy (==LineBreak) inlines return $ (vcat $ map (text "| " <>) lns) <> blankline | otherwise = do contents <- inlineListToRST inlines return $ contents <> blankline blockToRST (RawBlock f@(Format f') str) | f == "rst" = return $ text str | otherwise = return $ blankline <> ".. raw:: " <> text (map toLower f') $+$ (nest 3 $ text str) $$ blankline blockToRST HorizontalRule = return $ blankline $$ "--------------" $$ blankline blockToRST (Header level _ inlines) = do contents <- inlineListToRST inlines let headerChar = if level > 5 then ' ' else "=-~^'" !! (level - 1) let border = text $ replicate (offset contents) headerChar return $ nowrap $ contents $$ border $$ blankline blockToRST (CodeBlock (_,classes,kvs) str) = do opts <- stOptions <$> get let tabstop = writerTabStop opts let startnum = maybe "" (\x -> " " <> text x) $ lookup "startFrom" kvs let numberlines = if "numberLines" `elem` classes then " :number-lines:" <> startnum else empty if "haskell" `elem` classes && "literate" `elem` classes && isEnabled Ext_literate_haskell opts then return $ prefixed "> " (text str) $$ blankline else return $ (case [c | c <- classes, c `notElem` ["sourceCode","literate","numberLines"]] of [] -> "::" (lang:_) -> (".. code:: " <> text lang) $$ numberlines) $+$ nest tabstop (text str) $$ blankline blockToRST (BlockQuote blocks) = do tabstop <- get >>= (return . writerTabStop . stOptions) contents <- blockListToRST blocks return $ (nest tabstop contents) <> blankline blockToRST (Table caption _ widths headers rows) = do caption' <- inlineListToRST caption let caption'' = if null caption then empty else blankline <> text "Table: " <> caption' headers' <- mapM blockListToRST headers rawRows <- mapM (mapM blockListToRST) rows let isSimple = all (==0) widths && all (all (\bs -> length bs <= 1)) rows let numChars = maximum . map offset opts <- get >>= return . stOptions let widthsInChars = if isSimple then map ((+2) . numChars) $ transpose (headers' : rawRows) else map (floor . (fromIntegral (writerColumns opts) *)) widths let hpipeBlocks blocks = hcat [beg, middle, end] where h = maximum (map height blocks) sep' = lblock 3 $ vcat (map text $ replicate h " | ") beg = lblock 2 $ vcat (map text $ replicate h "| ") end = lblock 2 $ vcat (map text $ replicate h " |") middle = hcat $ intersperse sep' blocks let makeRow = hpipeBlocks . zipWith lblock widthsInChars let head' = makeRow headers' rows' <- mapM (\row -> do cols <- mapM blockListToRST row return $ makeRow cols) rows let border ch = char '+' <> char ch <> (hcat $ intersperse (char ch <> char '+' <> char ch) $ map (\l -> text $ replicate l ch) widthsInChars) <> char ch <> char '+' let body = vcat $ intersperse (border '-') rows' let head'' = if all null headers then empty else head' $$ border '=' return $ border '-' $$ head'' $$ body $$ border '-' $$ caption'' $$ blankline blockToRST (BulletList items) = do contents <- mapM bulletListItemToRST items -- ensure that sublists have preceding blank line return $ blankline $$ vcat contents $$ blankline blockToRST (OrderedList (start, style', delim) items) = do let markers = if start == 1 && style' == DefaultStyle && delim == DefaultDelim then take (length items) $ repeat "#." else take (length items) $ orderedListMarkers (start, style', delim) let maxMarkerLength = maximum $ map length markers let markers' = map (\m -> let s = maxMarkerLength - length m in m ++ replicate s ' ') markers contents <- mapM (\(item, num) -> orderedListItemToRST item num) $ zip markers' items -- ensure that sublists have preceding blank line return $ blankline $$ vcat contents $$ blankline blockToRST (DefinitionList items) = do contents <- mapM definitionListItemToRST items -- ensure that sublists have preceding blank line return $ blankline $$ vcat contents $$ blankline -- | Convert bullet list item (list of blocks) to RST. bulletListItemToRST :: [Block] -> State WriterState Doc bulletListItemToRST items = do contents <- blockListToRST items return $ hang 3 "- " $ contents <> cr -- | Convert ordered list item (a list of blocks) to RST. orderedListItemToRST :: String -- ^ marker for list item -> [Block] -- ^ list item (list of blocks) -> State WriterState Doc orderedListItemToRST marker items = do contents <- blockListToRST items let marker' = marker ++ " " return $ hang (length marker') (text marker') $ contents <> cr -- | Convert defintion list item (label, list of blocks) to RST. definitionListItemToRST :: ([Inline], [[Block]]) -> State WriterState Doc definitionListItemToRST (label, defs) = do label' <- inlineListToRST label contents <- liftM vcat $ mapM blockListToRST defs tabstop <- get >>= (return . writerTabStop . stOptions) return $ label' $$ nest tabstop (contents <> cr) -- | Convert list of Pandoc block elements to RST. blockListToRST :: [Block] -- ^ List of block elements -> State WriterState Doc blockListToRST blocks = mapM blockToRST blocks >>= return . vcat -- | Convert list of Pandoc inline elements to RST. inlineListToRST :: [Inline] -> State WriterState Doc 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) insertBS (x:y:zs) | isComplex x && not (okAfterComplex y) = x : RawInline "rst" "\\ " : insertBS (y : zs) | isComplex y && not (okBeforeComplex x) = x : RawInline "rst" "\\ " : insertBS (y : zs) | otherwise = x : insertBS (y : zs) insertBS (x:ys) = x : insertBS ys insertBS [] = [] surroundComplex :: Inline -> Inline -> Bool surroundComplex (Str s@(_:_)) (Str s'@(_:_)) = case (last s, head s') of ('\'','\'') -> True ('"','"') -> True ('<','>') -> True ('[',']') -> True ('{','}') -> True _ -> False surroundComplex _ _ = False okAfterComplex :: Inline -> Bool okAfterComplex Space = True okAfterComplex LineBreak = True okAfterComplex (Str (c:_)) = isSpace c || c `elem` "-.,:;!?\\/'\")]}>–—" okAfterComplex _ = False okBeforeComplex :: Inline -> Bool okBeforeComplex Space = True okBeforeComplex LineBreak = True okBeforeComplex (Str (c:_)) = isSpace c || c `elem` "-:/'\"<([{–—" okBeforeComplex _ = False isComplex :: Inline -> Bool isComplex (Emph _) = True isComplex (Strong _) = True isComplex (SmallCaps _) = True isComplex (Strikeout _) = True isComplex (Superscript _) = True isComplex (Subscript _) = True isComplex (Link _ _) = True isComplex (Image _ _) = True isComplex (Code _ _) = True isComplex (Math _ _) = True isComplex _ = False -- | Convert Pandoc inline element to RST. inlineToRST :: Inline -> State WriterState Doc inlineToRST (Span _ ils) = inlineListToRST ils inlineToRST (Emph lst) = do contents <- inlineListToRST lst return $ "*" <> contents <> "*" inlineToRST (Strong lst) = do contents <- inlineListToRST lst return $ "**" <> contents <> "**" inlineToRST (Strikeout lst) = do contents <- inlineListToRST lst return $ "[STRIKEOUT:" <> contents <> "]" inlineToRST (Superscript lst) = do contents <- inlineListToRST lst return $ ":sup:`" <> contents <> "`" inlineToRST (Subscript lst) = do contents <- inlineListToRST lst return $ ":sub:`" <> contents <> "`" inlineToRST (SmallCaps lst) = inlineListToRST lst inlineToRST (Quoted SingleQuote lst) = do contents <- inlineListToRST lst return $ "‘" <> contents <> "’" inlineToRST (Quoted DoubleQuote lst) = do contents <- inlineListToRST lst return $ "“" <> contents <> "”" inlineToRST (Cite _ lst) = inlineListToRST lst inlineToRST (Code _ str) = return $ "``" <> text str <> "``" inlineToRST (Str str) = return $ text $ escapeString str inlineToRST (Math t str) = do modify $ \st -> st{ stHasMath = True } return $ if t == InlineMath then ":math:`" <> text str <> "`" else if '\n' `elem` str then blankline $$ ".. math::" $$ blankline $$ nest 3 (text str) $$ blankline else blankline $$ (".. math:: " <> text str) $$ blankline inlineToRST (RawInline f x) | f == "rst" = return $ text x | otherwise = return empty inlineToRST (LineBreak) = return cr -- there's no line break in RST (see Para) inlineToRST Space = return space -- autolink inlineToRST (Link [Str str] (src, _)) | isURI src && if "mailto:" `isPrefixOf` src then src == escapeURI ("mailto:" ++ str) else src == escapeURI str = do let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src return $ text srcSuffix inlineToRST (Link [Image alt (imgsrc,imgtit)] (src, _tit)) = do label <- registerImage alt (imgsrc,imgtit) (Just src) return $ "|" <> label <> "|" inlineToRST (Link txt (src, tit)) = do useReferenceLinks <- get >>= return . writerReferenceLinks . stOptions linktext <- inlineListToRST $ normalizeSpaces txt if useReferenceLinks then do refs <- get >>= return . stLinks case lookup txt refs of Just (src',tit') -> if src == src' && tit == tit' then return $ "`" <> linktext <> "`_" else do -- duplicate label, use non-reference link return $ "`" <> linktext <> " <" <> text src <> ">`__" Nothing -> do modify $ \st -> st { stLinks = (txt,(src,tit)):refs } return $ "`" <> linktext <> "`_" else return $ "`" <> linktext <> " <" <> text src <> ">`__" inlineToRST (Image alternate (source, tit)) = do label <- registerImage alternate (source,tit) Nothing return $ "|" <> label <> "|" inlineToRST (Note contents) = do -- add to notes in state notes <- get >>= return . stNotes modify $ \st -> st { stNotes = contents:notes } let ref = show $ (length notes) + 1 return $ " [" <> text ref <> "]_" registerImage :: [Inline] -> Target -> Maybe String -> State WriterState Doc registerImage alt (src,tit) mbtarget = do pics <- get >>= return . stImages txt <- case lookup alt pics of Just (s,t,mbt) | (s,t,mbt) == (src,tit,mbtarget) -> return alt _ -> do let alt' = if null alt || alt == [Str ""] then [Str $ "image" ++ show (length pics)] else alt modify $ \st -> st { stImages = (alt', (src,tit, mbtarget)):stImages st } return alt' inlineListToRST txt �������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/RTF.hs������������������������������������������������������000644 �000765 �000024 �00000034156 12251233602 020472� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.RTF Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to RTF (rich text format). -} module Text.Pandoc.Writers.RTF ( writeRTF, writeRTFWithEmbeddedImages ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Walk import Data.List ( isSuffixOf, intercalate ) import Data.Char ( ord, chr, isDigit, toLower ) import System.FilePath ( takeExtension ) import qualified Data.ByteString as B import Text.Printf ( printf ) import Network.URI ( isURI, unEscapeString ) import qualified Control.Exception as E -- | Convert Image inlines into a raw RTF embedded image, read from a file. -- If file not found or filetype not jpeg or png, leave the inline unchanged. rtfEmbedImage :: Inline -> IO Inline rtfEmbedImage x@(Image _ (src,_)) = do let ext = map toLower (takeExtension src) if ext `elem` [".jpg",".jpeg",".png"] && not (isURI src) then do let src' = unEscapeString src imgdata <- E.catch (B.readFile src') (\e -> let _ = (e :: E.SomeException) in return B.empty) let bytes = map (printf "%02x") $ B.unpack imgdata let filetype = case ext of ".jpg" -> "\\jpegblip" ".jpeg" -> "\\jpegblip" ".png" -> "\\pngblip" _ -> error "Unknown file type" let raw = "{\\pict" ++ filetype ++ " " ++ concat bytes ++ "}" return $ if B.null imgdata then x else RawInline (Format "rtf") raw else return x rtfEmbedImage x = return x -- | Convert Pandoc to a string in rich text format, with -- images embedded as encoded binary data. writeRTFWithEmbeddedImages :: WriterOptions -> Pandoc -> IO String writeRTFWithEmbeddedImages options doc = writeRTF options `fmap` walkM rtfEmbedImage doc -- | Convert Pandoc to a string in rich text format. writeRTF :: WriterOptions -> Pandoc -> String writeRTF options (Pandoc meta blocks) = let spacer = not $ all null $ docTitle meta : docDate meta : docAuthors meta Just metadata = metaToJSON options (Just . concatMap (blockToRTF 0 AlignDefault)) (Just . inlineListToRTF) meta body = concatMap (blockToRTF 0 AlignDefault) blocks isTOCHeader (Header lev _ _) = lev <= writerTOCDepth options isTOCHeader _ = False context = defField "body" body $ defField "spacer" spacer $ (if writerTableOfContents options then defField "toc" (tableOfContents $ filter isTOCHeader blocks) else id) $ metadata in if writerStandalone options then renderTemplate' (writerTemplate options) context else body -- | Construct table of contents from list of header blocks. tableOfContents :: [Block] -> String tableOfContents headers = let contentsTree = hierarchicalize headers in concatMap (blockToRTF 0 AlignDefault) $ [Header 1 nullAttr [Str "Contents"], BulletList (map elementToListItem contentsTree)] elementToListItem :: Element -> [Block] elementToListItem (Blk _) = [] elementToListItem (Sec _ _ _ sectext subsecs) = [Plain sectext] ++ if null subsecs then [] else [BulletList (map elementToListItem subsecs)] -- | Convert unicode characters (> 127) into rich text format representation. handleUnicode :: String -> String handleUnicode [] = [] handleUnicode (c:cs) = if ord c > 127 then if surrogate c then let x = ord c - 0x10000 (q, r) = x `divMod` 0x400 upper = q + 0xd800 lower = r + 0xDC00 in enc (chr upper) ++ enc (chr lower) ++ handleUnicode cs else enc c ++ handleUnicode cs else c:(handleUnicode cs) where surrogate x = not ( (0x0000 <= ord x && ord x <= 0xd7ff) || (0xe000 <= ord x && ord x <= 0xffff) ) enc x = '\\':'u':(show (ord x)) ++ "?" -- | Escape special characters. escapeSpecial :: String -> String escapeSpecial = escapeStringUsing $ [ ('\t',"\\tab ") , ('\8216',"\\u8216'") , ('\8217',"\\u8217'") , ('\8220',"\\u8220\"") , ('\8221',"\\u8221\"") , ('\8211',"\\u8211-") , ('\8212',"\\u8212-") ] ++ backslashEscapes "{\\}" -- | Escape strings as needed for rich text format. stringToRTF :: String -> String stringToRTF = handleUnicode . escapeSpecial -- | Escape things as needed for code block in RTF. codeStringToRTF :: String -> String codeStringToRTF str = intercalate "\\line\n" $ lines (stringToRTF str) -- | Make a paragraph with first-line indent, block indent, and space after. rtfParSpaced :: Int -- ^ space after (in twips) -> Int -- ^ block indent (in twips) -> Int -- ^ first line indent (relative to block) (in twips) -> Alignment -- ^ alignment -> String -- ^ string with content -> String rtfParSpaced spaceAfter indent firstLineIndent alignment content = let alignString = case alignment of AlignLeft -> "\\ql " AlignRight -> "\\qr " AlignCenter -> "\\qc " AlignDefault -> "\\ql " in "{\\pard " ++ alignString ++ "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++ " \\fi" ++ (show firstLineIndent) ++ " " ++ content ++ "\\par}\n" -- | Default paragraph. rtfPar :: Int -- ^ block indent (in twips) -> Int -- ^ first line indent (relative to block) (in twips) -> Alignment -- ^ alignment -> String -- ^ string with content -> String rtfPar = rtfParSpaced 180 -- | Compact paragraph (e.g. for compact list items). rtfCompact :: Int -- ^ block indent (in twips) -> Int -- ^ first line indent (relative to block) (in twips) -> Alignment -- ^ alignment -> String -- ^ string with content -> String rtfCompact = rtfParSpaced 0 -- number of twips to indent indentIncrement :: Int indentIncrement = 720 listIncrement :: Int listIncrement = 360 -- | Returns appropriate bullet list marker for indent level. bulletMarker :: Int -> String bulletMarker indent = case indent `mod` 720 of 0 -> "\\bullet " _ -> "\\endash " -- | Returns appropriate (list of) ordered list markers for indent level. orderedMarkers :: Int -> ListAttributes -> [String] orderedMarkers indent (start, style, delim) = if style == DefaultStyle && delim == DefaultDelim then case indent `mod` 720 of 0 -> orderedListMarkers (start, Decimal, Period) _ -> orderedListMarkers (start, LowerAlpha, Period) else orderedListMarkers (start, style, delim) -- | Convert Pandoc block element to RTF. blockToRTF :: Int -- ^ indent level -> Alignment -- ^ alignment -> Block -- ^ block to convert -> String blockToRTF _ _ Null = "" blockToRTF indent alignment (Div _ bs) = concatMap (blockToRTF indent alignment) bs blockToRTF indent alignment (Plain lst) = rtfCompact indent 0 alignment $ inlineListToRTF lst blockToRTF indent alignment (Para lst) = rtfPar indent 0 alignment $ inlineListToRTF lst blockToRTF indent alignment (BlockQuote lst) = concatMap (blockToRTF (indent + indentIncrement) alignment) lst blockToRTF indent _ (CodeBlock _ str) = rtfPar indent 0 AlignLeft ("\\f1 " ++ (codeStringToRTF str)) blockToRTF _ _ (RawBlock f str) | f == Format "rtf" = str | otherwise = "" blockToRTF indent alignment (BulletList lst) = spaceAtEnd $ concatMap (listItemToRTF alignment indent (bulletMarker indent)) lst blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $ zipWith (listItemToRTF alignment indent) (orderedMarkers indent attribs) lst blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $ concatMap (definitionListItemToRTF alignment indent) lst blockToRTF indent _ HorizontalRule = rtfPar indent 0 AlignCenter "\\emdash\\emdash\\emdash\\emdash\\emdash" blockToRTF indent alignment (Header level _ lst) = rtfPar indent 0 alignment $ "\\b \\fs" ++ (show (40 - (level * 4))) ++ " " ++ inlineListToRTF lst blockToRTF indent alignment (Table caption aligns sizes headers rows) = (if all null headers then "" else tableRowToRTF True indent aligns sizes headers) ++ concatMap (tableRowToRTF False indent aligns sizes) rows ++ rtfPar indent 0 alignment (inlineListToRTF caption) tableRowToRTF :: Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> String tableRowToRTF header indent aligns sizes' cols = let totalTwips = 6 * 1440 -- 6 inches sizes = if all (== 0) sizes' then take (length cols) $ repeat (1.0 / fromIntegral (length cols)) else sizes' columns = concat $ zipWith (tableItemToRTF indent) aligns cols rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips)) (0 :: Integer) sizes cellDefs = map (\edge -> (if header then "\\clbrdrb\\brdrs" else "") ++ "\\cellx" ++ show edge) rightEdges start = "{\n\\trowd \\trgaph120\n" ++ concat cellDefs ++ "\n" ++ "\\trkeep\\intbl\n{\n" end = "}\n\\intbl\\row}\n" in start ++ columns ++ end tableItemToRTF :: Int -> Alignment -> [Block] -> String tableItemToRTF indent alignment item = let contents = concatMap (blockToRTF indent alignment) item in "{\\intbl " ++ contents ++ "\\cell}\n" -- | Ensure that there's the same amount of space after compact -- lists as after regular lists. spaceAtEnd :: String -> String spaceAtEnd str = if isSuffixOf "\\par}\n" str then (take ((length str) - 6) str) ++ "\\sa180\\par}\n" else str -- | Convert list item (list of blocks) to RTF. listItemToRTF :: Alignment -- ^ alignment -> Int -- ^ indent level -> String -- ^ list start marker -> [Block] -- ^ list item (list of blocks) -> [Char] listItemToRTF alignment indent marker [] = rtfCompact (indent + listIncrement) (0 - listIncrement) alignment (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ") listItemToRTF alignment indent marker list = let (first:rest) = map (blockToRTF (indent + listIncrement) alignment) list listMarker = "\\fi" ++ show (0 - listIncrement) ++ " " ++ marker ++ "\\tx" ++ show listIncrement ++ "\\tab" insertListMarker ('\\':'f':'i':'-':d:xs) | isDigit d = listMarker ++ dropWhile isDigit xs insertListMarker ('\\':'f':'i':d:xs) | isDigit d = listMarker ++ dropWhile isDigit xs insertListMarker (x:xs) = x : insertListMarker xs insertListMarker [] = [] -- insert the list marker into the (processed) first block in insertListMarker first ++ concat rest -- | Convert definition list item (label, list of blocks) to RTF. definitionListItemToRTF :: Alignment -- ^ alignment -> Int -- ^ indent level -> ([Inline],[[Block]]) -- ^ list item (list of blocks) -> [Char] definitionListItemToRTF alignment indent (label, defs) = let labelText = blockToRTF indent alignment (Plain label) itemsText = concatMap (blockToRTF (indent + listIncrement) alignment) $ concat defs in labelText ++ itemsText -- | Convert list of inline items to RTF. inlineListToRTF :: [Inline] -- ^ list of inlines to convert -> String inlineListToRTF lst = concatMap inlineToRTF lst -- | Convert inline item to RTF. inlineToRTF :: Inline -- ^ inline to convert -> String inlineToRTF (Span _ lst) = inlineListToRTF lst inlineToRTF (Emph lst) = "{\\i " ++ (inlineListToRTF lst) ++ "}" inlineToRTF (Strong lst) = "{\\b " ++ (inlineListToRTF lst) ++ "}" inlineToRTF (Strikeout lst) = "{\\strike " ++ (inlineListToRTF lst) ++ "}" inlineToRTF (Superscript lst) = "{\\super " ++ (inlineListToRTF lst) ++ "}" inlineToRTF (Subscript lst) = "{\\sub " ++ (inlineListToRTF lst) ++ "}" inlineToRTF (SmallCaps lst) = "{\\scaps " ++ (inlineListToRTF lst) ++ "}" inlineToRTF (Quoted SingleQuote lst) = "\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'" inlineToRTF (Quoted DoubleQuote lst) = "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\"" inlineToRTF (Code _ str) = "{\\f1 " ++ (codeStringToRTF str) ++ "}" inlineToRTF (Str str) = stringToRTF str inlineToRTF (Math t str) = inlineListToRTF $ readTeXMath' t str inlineToRTF (Cite _ lst) = inlineListToRTF lst inlineToRTF (RawInline f str) | f == Format "rtf" = str | otherwise = "" inlineToRTF (LineBreak) = "\\line " inlineToRTF Space = " " inlineToRTF (Link text (src, _)) = "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++ "\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n" inlineToRTF (Image _ (source, _)) = "{\\cf1 [image: " ++ source ++ "]\\cf0}" inlineToRTF (Note contents) = "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++ (concatMap (blockToRTF 0 AlignDefault) contents) ++ "}" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Shared.hs���������������������������������������������������000644 �000765 �000024 �00000012115 12251233602 021234� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2013 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Shared Copyright : Copyright (C) 2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Shared utility functions for pandoc writers. -} module Text.Pandoc.Writers.Shared ( metaToJSON , getField , setField , defField , tagWithAttrs ) where import Text.Pandoc.Definition import Text.Pandoc.Pretty import Text.Pandoc.XML (escapeStringForXML) import Control.Monad (liftM) import Text.Pandoc.Options (WriterOptions(..)) import qualified Data.HashMap.Strict as H 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 -- | Create JSON value for template from a 'Meta' and an association list -- of variables, specified at the command line or in the writer. -- Variables overwrite metadata fields with the same names. -- If multiple variables are set with the same name, a list is -- assigned. metaToJSON :: Monad m => WriterOptions -> ([Block] -> m String) -> ([Inline] -> m String) -> Meta -> m Value metaToJSON opts blockWriter inlineWriter (Meta metamap) | writerStandalone opts = do let baseContext = foldl (\acc (x,y) -> setField x y acc) (Object H.empty) $ writerVariables opts renderedMap <- Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap return $ M.foldWithKey (\key val obj -> defField key val obj) baseContext renderedMap | otherwise = return (Object H.empty) metaValueToJSON :: Monad m => ([Block] -> m String) -> ([Inline] -> m String) -> MetaValue -> m Value metaValueToJSON blockWriter inlineWriter (MetaMap metamap) = liftM toJSON $ Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap metaValueToJSON blockWriter inlineWriter (MetaList xs) = liftM toJSON $ Traversable.mapM (metaValueToJSON blockWriter inlineWriter) xs metaValueToJSON _ _ (MetaBool b) = return $ toJSON b metaValueToJSON _ _ (MetaString s) = return $ toJSON s metaValueToJSON blockWriter _ (MetaBlocks bs) = liftM toJSON $ blockWriter bs metaValueToJSON _ inlineWriter (MetaInlines bs) = liftM toJSON $ inlineWriter bs -- | Retrieve a field value from a JSON object. getField :: FromJSON a => String -> Value -> Maybe a getField field (Object hashmap) = do result <- H.lookup (T.pack field) hashmap case fromJSON result of Success x -> return x _ -> fail "Could not convert from JSON" getField _ _ = fail "Not a JSON object" setField :: ToJSON a => String -> a -> Value -> Value -- | Set a field of a JSON object. If the field already has a value, -- convert it into a list with the new value appended to the old value(s). -- This is a utility function to be used in preparing template contexts. setField field val (Object hashmap) = Object $ H.insertWith combine (T.pack field) (toJSON val) hashmap where combine newval oldval = case fromJSON oldval of Success xs -> toJSON $ xs ++ [newval] _ -> toJSON [oldval, newval] setField _ _ x = x defField :: ToJSON a => String -> a -> Value -> Value -- | Set a field of a JSON object if it currently has no value. -- If it has a value, do nothing. -- This is a utility function to be used in preparing template contexts. defField field val (Object hashmap) = Object $ H.insertWith f (T.pack field) (toJSON val) hashmap where f _newval oldval = oldval defField _ _ x = x -- Produce an HTML tag with the given pandoc attributes. tagWithAttrs :: String -> Attr -> Doc tagWithAttrs tag (ident,classes,kvs) = hsep ["<" <> text tag ,if null ident then empty else "id=" <> doubleQuotes (text ident) ,if null classes then empty else "class=" <> doubleQuotes (text (unwords classes)) ,hsep (map (\(k,v) -> text k <> "=" <> doubleQuotes (text (escapeStringForXML v))) kvs) ] <> ">" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Texinfo.hs��������������������������������������������������000644 �000765 �000024 �00000040273 12251233602 021450� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2008-2010 John MacFarlane and Peter Wang This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Texinfo Copyright : Copyright (C) 2008-2010 John MacFarlane and Peter Wang License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' format into Texinfo. -} module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Templates (renderTemplate') import Text.Printf ( printf ) import Data.List ( transpose, maximumBy ) import Data.Ord ( comparing ) import Data.Char ( chr, ord ) import Control.Monad.State import Text.Pandoc.Pretty import Network.URI ( isURI, unEscapeString ) import System.FilePath data WriterState = WriterState { stStrikeout :: Bool -- document contains strikeout , stSuperscript :: Bool -- document contains superscript , stSubscript :: Bool -- document contains subscript , stEscapeComma :: Bool -- in a context where we need @comma , stIdentifiers :: [String] -- header ids used already } {- TODO: - internal cross references a la HTML - generated .texi files don't work when run through texi2dvi -} -- | Convert Pandoc to Texinfo. writeTexinfo :: WriterOptions -> Pandoc -> String writeTexinfo options document = evalState (pandocToTexinfo options $ wrapTop document) $ WriterState { stStrikeout = False, stSuperscript = False, stEscapeComma = False, stSubscript = False, stIdentifiers = [] } -- | Add a "Top" node around the document, needed by Texinfo. wrapTop :: Pandoc -> Pandoc wrapTop (Pandoc meta blocks) = Pandoc meta (Header 0 nullAttr (docTitle meta) : blocks) pandocToTexinfo :: WriterOptions -> Pandoc -> State WriterState String pandocToTexinfo options (Pandoc meta blocks) = do let titlePage = not $ all null $ docTitle meta : docDate meta : docAuthors meta let colwidth = if writerWrapText options then Just $ writerColumns options else Nothing metadata <- metaToJSON options (fmap (render colwidth) . blockListToTexinfo) (fmap (render colwidth) . inlineListToTexinfo) meta main <- blockListToTexinfo blocks st <- get let body = render colwidth main let context = defField "body" body $ defField "toc" (writerTableOfContents options) $ defField "titlepage" titlePage $ defField "subscript" (stSubscript st) $ defField "superscript" (stSuperscript st) $ defField "strikeout" (stStrikeout st) $ metadata if writerStandalone options then return $ renderTemplate' (writerTemplate options) context else return body -- | Escape things as needed for Texinfo. stringToTexinfo :: String -> String stringToTexinfo = escapeStringUsing texinfoEscapes where texinfoEscapes = [ ('{', "@{") , ('}', "@}") , ('@', "@@") , ('\160', "@ ") , ('\x2014', "---") , ('\x2013', "--") , ('\x2026', "@dots{}") , ('\x2019', "'") ] escapeCommas :: State WriterState Doc -> State WriterState Doc escapeCommas parser = do oldEscapeComma <- gets stEscapeComma modify $ \st -> st{ stEscapeComma = True } res <- parser modify $ \st -> st{ stEscapeComma = oldEscapeComma } return res -- | Puts contents into Texinfo command. inCmd :: String -> Doc -> Doc inCmd cmd contents = char '@' <> text cmd <> braces contents -- | Convert Pandoc block element to Texinfo. blockToTexinfo :: Block -- ^ Block to convert -> State WriterState Doc blockToTexinfo Null = return empty blockToTexinfo (Div _ bs) = blockListToTexinfo bs blockToTexinfo (Plain lst) = inlineListToTexinfo lst -- title beginning with fig: indicates that the image is a figure blockToTexinfo (Para [Image txt (src,'f':'i':'g':':':tit)]) = do capt <- if null txt then return empty else (\c -> text "@caption" <> braces c) `fmap` inlineListToTexinfo txt img <- inlineToTexinfo (Image txt (src,tit)) return $ text "@float" $$ img $$ capt $$ text "@end float" blockToTexinfo (Para lst) = inlineListToTexinfo lst -- this is handled differently from Plain in blockListToTexinfo blockToTexinfo (BlockQuote lst) = do contents <- blockListToTexinfo lst return $ text "@quotation" $$ contents $$ text "@end quotation" blockToTexinfo (CodeBlock _ str) = do return $ blankline $$ text "@verbatim" $$ flush (text str) $$ text "@end verbatim" <> blankline blockToTexinfo (RawBlock f str) | f == "texinfo" = return $ text str | f == "latex" || f == "tex" = return $ text "@tex" $$ text str $$ text "@end tex" | otherwise = return empty blockToTexinfo (BulletList lst) = do items <- mapM listItemToTexinfo lst return $ text "@itemize" $$ vcat items $$ text "@end itemize" <> blankline blockToTexinfo (OrderedList (start, numstyle, _) lst) = do items <- mapM listItemToTexinfo lst return $ text "@enumerate " <> exemplar $$ vcat items $$ text "@end enumerate" <> blankline where exemplar = case numstyle of DefaultStyle -> decimal Decimal -> decimal Example -> decimal UpperRoman -> decimal -- Roman numerals not supported LowerRoman -> decimal UpperAlpha -> upperAlpha LowerAlpha -> lowerAlpha decimal = if start == 1 then empty else text (show start) upperAlpha = text [chr $ ord 'A' + start - 1] lowerAlpha = text [chr $ ord 'a' + start - 1] blockToTexinfo (DefinitionList lst) = do items <- mapM defListItemToTexinfo lst return $ text "@table @asis" $$ vcat items $$ text "@end table" <> blankline blockToTexinfo HorizontalRule = -- XXX can't get the equivalent from LaTeX.hs to work return $ text "@iftex" $$ text "@bigskip@hrule@bigskip" $$ text "@end iftex" $$ text "@ifnottex" $$ text (take 72 $ repeat '-') $$ text "@end ifnottex" blockToTexinfo (Header 0 _ lst) = do txt <- if null lst then return $ text "Top" else inlineListToTexinfo lst return $ text "@node Top" $$ text "@top " <> txt <> blankline blockToTexinfo (Header level _ lst) = do node <- inlineListForNode lst txt <- inlineListToTexinfo lst idsUsed <- gets stIdentifiers let id' = uniqueIdent lst idsUsed modify $ \st -> st{ stIdentifiers = id' : idsUsed } return $ if (level > 0) && (level <= 4) then blankline <> text "@node " <> node $$ text (seccmd level) <> txt $$ text "@anchor" <> braces (text $ '#':id') else txt where seccmd 1 = "@chapter " seccmd 2 = "@section " seccmd 3 = "@subsection " seccmd 4 = "@subsubsection " seccmd _ = error "illegal seccmd level" blockToTexinfo (Table caption aligns widths heads rows) = do headers <- if all null heads then return empty else tableHeadToTexinfo aligns heads captionText <- inlineListToTexinfo caption rowsText <- mapM (tableRowToTexinfo aligns) rows colDescriptors <- if all (== 0) widths then do -- use longest entry instead of column widths cols <- mapM (mapM (liftM (render Nothing . hcat) . mapM blockToTexinfo)) $ transpose $ heads : rows return $ concatMap ((\x -> "{"++x++"} ") . maximumBy (comparing length)) cols else return $ "@columnfractions " ++ concatMap (printf "%.2f ") widths let tableBody = text ("@multitable " ++ colDescriptors) $$ headers $$ vcat rowsText $$ text "@end multitable" return $ if isEmpty captionText then tableBody <> blankline else text "@float" $$ tableBody $$ inCmd "caption" captionText $$ text "@end float" tableHeadToTexinfo :: [Alignment] -> [[Block]] -> State WriterState Doc tableHeadToTexinfo = tableAnyRowToTexinfo "@headitem " tableRowToTexinfo :: [Alignment] -> [[Block]] -> State WriterState Doc tableRowToTexinfo = tableAnyRowToTexinfo "@item " tableAnyRowToTexinfo :: String -> [Alignment] -> [[Block]] -> State WriterState Doc tableAnyRowToTexinfo itemtype aligns cols = zipWithM alignedBlock aligns cols >>= return . (text itemtype $$) . foldl (\row item -> row $$ (if isEmpty row then empty else text " @tab ") <> item) empty alignedBlock :: Alignment -> [Block] -> State WriterState Doc -- XXX @flushleft and @flushright text won't get word wrapped. Since word -- wrapping is more important than alignment, we ignore the alignment. alignedBlock _ = blockListToTexinfo {- alignedBlock AlignLeft col = do b <- blockListToTexinfo col return $ text "@flushleft" $$ b $$ text "@end flushleft" alignedBlock AlignRight col = do b <- blockListToTexinfo col return $ text "@flushright" $$ b $$ text "@end flushright" alignedBlock _ col = blockListToTexinfo col -} -- | Convert Pandoc block elements to Texinfo. blockListToTexinfo :: [Block] -> State WriterState Doc blockListToTexinfo [] = return empty blockListToTexinfo (x:xs) = do x' <- blockToTexinfo x case x of Header level _ _ -> do -- We need need to insert a menu for this node. let (before, after) = break isHeader xs before' <- blockListToTexinfo before let menu = if level < 4 then collectNodes (level + 1) after else [] lines' <- mapM makeMenuLine menu let menu' = if null lines' then empty else text "@menu" $$ vcat lines' $$ text "@end menu" after' <- blockListToTexinfo after return $ x' $$ before' $$ menu' $$ after' Para _ -> do xs' <- blockListToTexinfo xs case xs of ((CodeBlock _ _):_) -> return $ x' $$ xs' _ -> return $ 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) = case x of (Header hl _ _) -> if hl < level then [] else if hl == level then x : collectNodes level xs else collectNodes level xs _ -> collectNodes level xs makeMenuLine :: Block -> State WriterState Doc makeMenuLine (Header _ _ lst) = do txt <- inlineListForNode lst return $ text "* " <> txt <> text "::" makeMenuLine _ = error "makeMenuLine called with non-Header block" listItemToTexinfo :: [Block] -> State WriterState Doc listItemToTexinfo lst = do contents <- blockListToTexinfo lst let spacer = case reverse lst of (Para{}:_) -> blankline _ -> empty return $ text "@item" $$ contents <> spacer defListItemToTexinfo :: ([Inline], [[Block]]) -> State WriterState Doc defListItemToTexinfo (term, defs) = do term' <- inlineListToTexinfo term let defToTexinfo bs = do d <- blockListToTexinfo bs case reverse bs of (Para{}:_) -> return $ d <> blankline _ -> return d defs' <- mapM defToTexinfo defs return $ text "@item " <> term' $+$ vcat defs' -- | Convert list of inline elements to Texinfo. inlineListToTexinfo :: [Inline] -- ^ Inlines to convert -> State WriterState Doc inlineListToTexinfo lst = mapM inlineToTexinfo lst >>= return . hcat -- | Convert list of inline elements to Texinfo acceptable for a node name. inlineListForNode :: [Inline] -- ^ Inlines to convert -> State WriterState Doc inlineListForNode = return . text . stringToTexinfo . filter (not . disallowedInNode) . stringify -- periods, commas, colons, and parentheses are disallowed in node names disallowedInNode :: Char -> Bool disallowedInNode c = c `elem` ".,:()" -- | Convert inline element to Texinfo inlineToTexinfo :: Inline -- ^ Inline to convert -> State WriterState Doc inlineToTexinfo (Span _ lst) = inlineListToTexinfo lst inlineToTexinfo (Emph lst) = inlineListToTexinfo lst >>= return . inCmd "emph" inlineToTexinfo (Strong lst) = inlineListToTexinfo lst >>= return . inCmd "strong" inlineToTexinfo (Strikeout lst) = do modify $ \st -> st{ stStrikeout = True } contents <- inlineListToTexinfo lst return $ text "@textstrikeout{" <> contents <> text "}" inlineToTexinfo (Superscript lst) = do modify $ \st -> st{ stSuperscript = True } contents <- inlineListToTexinfo lst return $ text "@textsuperscript{" <> contents <> char '}' inlineToTexinfo (Subscript lst) = do modify $ \st -> st{ stSubscript = True } contents <- inlineListToTexinfo lst return $ text "@textsubscript{" <> contents <> char '}' inlineToTexinfo (SmallCaps lst) = inlineListToTexinfo lst >>= return . inCmd "sc" inlineToTexinfo (Code _ str) = do return $ text $ "@code{" ++ stringToTexinfo str ++ "}" inlineToTexinfo (Quoted SingleQuote lst) = do contents <- inlineListToTexinfo lst return $ char '`' <> contents <> char '\'' inlineToTexinfo (Quoted DoubleQuote lst) = do contents <- inlineListToTexinfo lst return $ text "``" <> contents <> text "''" inlineToTexinfo (Cite _ lst) = inlineListToTexinfo lst inlineToTexinfo (Str str) = return $ text (stringToTexinfo str) inlineToTexinfo (Math _ str) = return $ inCmd "math" $ text str inlineToTexinfo (RawInline f str) | f == "latex" || f == "tex" = return $ text "@tex" $$ text str $$ text "@end tex" | f == "texinfo" = return $ text str | otherwise = return empty inlineToTexinfo (LineBreak) = return $ text "@*" inlineToTexinfo Space = return $ char ' ' inlineToTexinfo (Link txt (src@('#':_), _)) = do contents <- escapeCommas $ inlineListToTexinfo txt return $ text "@ref" <> braces (text (stringToTexinfo src) <> text "," <> contents) inlineToTexinfo (Link txt (src, _)) = do case txt of [Str x] | escapeURI x == src -> -- autolink do return $ text $ "@url{" ++ x ++ "}" _ -> do contents <- escapeCommas $ inlineListToTexinfo txt let src1 = stringToTexinfo src return $ text ("@uref{" ++ src1 ++ ",") <> contents <> char '}' inlineToTexinfo (Image alternate (source, _)) = do content <- escapeCommas $ inlineListToTexinfo alternate return $ text ("@image{" ++ base ++ ",,,") <> content <> text "," <> text (ext ++ "}") where ext = drop 1 $ takeExtension source' base = dropExtension source' source' = if isURI source then source else unEscapeString source inlineToTexinfo (Note contents) = do contents' <- blockListToTexinfo contents return $ text "@footnote" <> braces contents' �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Writers/Textile.hs��������������������������������������������������000644 �000765 �000024 �00000041650 12251233602 021452� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Writers.Textile Copyright : Copyright (C) 2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of 'Pandoc' documents to Textile markup. Textile: <http://thresholdstate.com/articles/4312/the-textile-reference-manual> -} module Text.Pandoc.Writers.Textile ( writeTextile ) where import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.Pretty (render) import Text.Pandoc.Writers.Shared import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.XML ( escapeStringForXML ) import Data.List ( intercalate ) import Control.Monad.State import Data.Char ( isSpace ) data WriterState = WriterState { stNotes :: [String] -- Footnotes , stListLevel :: [Char] -- String at beginning of list items, e.g. "**" , stUseTags :: Bool -- True if we should use HTML tags because we're in a complex list } -- | Convert Pandoc to Textile. writeTextile :: WriterOptions -> Pandoc -> String writeTextile opts document = evalState (pandocToTextile opts document) (WriterState { stNotes = [], stListLevel = [], stUseTags = False }) -- | Return Textile representation of document. pandocToTextile :: WriterOptions -> Pandoc -> State WriterState String pandocToTextile opts (Pandoc meta blocks) = do metadata <- metaToJSON opts (blockListToTextile opts) (inlineListToTextile opts) meta body <- blockListToTextile opts blocks notes <- liftM (unlines . reverse . stNotes) get let main = body ++ if null notes then "" else ("\n\n" ++ notes) let context = defField "body" main metadata if writerStandalone opts then return $ renderTemplate' (writerTemplate opts) context else return main withUseTags :: State WriterState a -> State WriterState a withUseTags action = do oldUseTags <- liftM stUseTags get modify $ \s -> s { stUseTags = True } result <- action modify $ \s -> s { stUseTags = oldUseTags } return result -- | Escape one character as needed for Textile. escapeCharForTextile :: Char -> String escapeCharForTextile x = case x of '&' -> "&" '<' -> "<" '>' -> ">" '"' -> """ '*' -> "*" '_' -> "_" '@' -> "@" '|' -> "|" '\x2014' -> " -- " '\x2013' -> " - " '\x2019' -> "'" '\x2026' -> "..." c -> [c] -- | Escape string as needed for Textile. escapeStringForTextile :: String -> String escapeStringForTextile = concatMap escapeCharForTextile -- | Convert Pandoc block element to Textile. blockToTextile :: WriterOptions -- ^ Options -> Block -- ^ Block element -> State WriterState String blockToTextile _ Null = return "" blockToTextile opts (Div attr bs) = do let startTag = render Nothing $ tagWithAttrs "div" attr let endTag = "</div>" contents <- blockListToTextile opts bs return $ startTag ++ "\n\n" ++ contents ++ "\n\n" ++ endTag ++ "\n" blockToTextile opts (Plain inlines) = inlineListToTextile opts inlines -- title beginning with fig: indicates that the image is a figure blockToTextile opts (Para [Image txt (src,'f':'i':'g':':':tit)]) = do capt <- blockToTextile opts (Para txt) im <- inlineToTextile opts (Image txt (src,tit)) return $ im ++ "\n" ++ capt blockToTextile opts (Para inlines) = do useTags <- liftM stUseTags get listLevel <- liftM stListLevel get contents <- inlineListToTextile opts inlines return $ if useTags then "<p>" ++ contents ++ "</p>" else contents ++ if null listLevel then "\n" else "" blockToTextile _ (RawBlock f str) | f == Format "html" || f == Format "textile" = return str | otherwise = return "" blockToTextile _ HorizontalRule = return "<hr />\n" blockToTextile opts (Header level (ident,classes,keyvals) inlines) = do contents <- inlineListToTextile opts inlines let identAttr = if null ident then "" else ('#':ident) let attribs = if null identAttr && null classes then "" else "(" ++ unwords classes ++ identAttr ++ ")" let lang = maybe "" (\x -> "[" ++ x ++ "]") $ lookup "lang" keyvals let styles = maybe "" (\x -> "{" ++ x ++ "}") $ lookup "style" keyvals let prefix = 'h' : show level ++ attribs ++ styles ++ lang ++ ". " return $ prefix ++ contents ++ "\n" blockToTextile _ (CodeBlock (_,classes,_) str) | any (all isSpace) (lines str) = return $ "<pre" ++ classes' ++ ">\n" ++ escapeStringForXML str ++ "\n</pre>\n" where classes' = if null classes then "" else " class=\"" ++ unwords classes ++ "\"" blockToTextile _ (CodeBlock (_,classes,_) str) = return $ "bc" ++ classes' ++ ". " ++ str ++ "\n\n" where classes' = if null classes then "" else "(" ++ unwords classes ++ ")" blockToTextile opts (BlockQuote bs@[Para _]) = do contents <- blockListToTextile opts bs return $ "bq. " ++ contents ++ "\n\n" blockToTextile opts (BlockQuote blocks) = do contents <- blockListToTextile opts blocks return $ "<blockquote>\n\n" ++ contents ++ "\n</blockquote>\n" blockToTextile opts (Table [] aligns widths headers rows') | all (==0) widths && all (`elem` [AlignLeft,AlignDefault]) aligns = do hs <- mapM (liftM (("_. " ++) . stripTrailingNewlines) . blockListToTextile opts) headers let cellsToRow cells = "|" ++ intercalate "|" cells ++ "|" let header = if all null headers then "" else cellsToRow hs let rowToCells = mapM (liftM stripTrailingNewlines . blockListToTextile opts) bs <- mapM rowToCells rows' let body = unlines $ map cellsToRow bs return $ header ++ "\n" ++ body ++ "\n" blockToTextile opts (Table capt aligns widths headers rows') = do let alignStrings = map alignmentToString aligns captionDoc <- if null capt then return "" else do c <- inlineListToTextile opts capt return $ "<caption>" ++ c ++ "</caption>\n" let percent w = show (truncate (100*w) :: Integer) ++ "%" let coltags = if all (== 0.0) widths then "" else unlines $ map (\w -> "<col width=\"" ++ percent w ++ "\" />") widths head' <- if all null headers then return "" else do hs <- tableRowToTextile opts alignStrings 0 headers return $ "<thead>\n" ++ hs ++ "\n</thead>\n" body' <- zipWithM (tableRowToTextile opts alignStrings) [1..] rows' return $ "<table>\n" ++ captionDoc ++ coltags ++ head' ++ "<tbody>\n" ++ unlines body' ++ "</tbody>\n</table>\n" blockToTextile opts x@(BulletList items) = do oldUseTags <- liftM stUseTags get let useTags = oldUseTags || not (isSimpleList x) if useTags then do contents <- withUseTags $ mapM (listItemToTextile opts) items return $ "<ul>\n" ++ vcat contents ++ "\n</ul>\n" else do modify $ \s -> s { stListLevel = stListLevel s ++ "*" } level <- get >>= return . length . stListLevel contents <- mapM (listItemToTextile opts) items modify $ \s -> s { stListLevel = init (stListLevel s) } return $ vcat contents ++ (if level > 1 then "" else "\n") blockToTextile opts x@(OrderedList attribs items) = do oldUseTags <- liftM stUseTags get let useTags = oldUseTags || not (isSimpleList x) if useTags then do contents <- withUseTags $ mapM (listItemToTextile opts) items return $ "<ol" ++ listAttribsToString attribs ++ ">\n" ++ vcat contents ++ "\n</ol>\n" else do modify $ \s -> s { stListLevel = stListLevel s ++ "#" } level <- get >>= return . length . stListLevel contents <- mapM (listItemToTextile opts) items modify $ \s -> s { stListLevel = init (stListLevel s) } return $ vcat contents ++ (if level > 1 then "" else "\n") blockToTextile opts (DefinitionList items) = do contents <- withUseTags $ mapM (definitionListItemToTextile opts) items return $ "<dl>\n" ++ vcat contents ++ "\n</dl>\n" -- Auxiliary functions for lists: -- | Convert ordered list attributes to HTML attribute string listAttribsToString :: ListAttributes -> String listAttribsToString (startnum, numstyle, _) = let numstyle' = camelCaseToHyphenated $ show numstyle in (if startnum /= 1 then " start=\"" ++ show startnum ++ "\"" else "") ++ (if numstyle /= DefaultStyle then " style=\"list-style-type: " ++ numstyle' ++ ";\"" else "") -- | Convert bullet or ordered list item (list of blocks) to Textile. listItemToTextile :: WriterOptions -> [Block] -> State WriterState String listItemToTextile opts items = do contents <- blockListToTextile opts items useTags <- get >>= return . stUseTags if useTags then return $ "<li>" ++ contents ++ "</li>" else do marker <- get >>= return . stListLevel return $ marker ++ " " ++ contents -- | Convert definition list item (label, list of blocks) to Textile. definitionListItemToTextile :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState String definitionListItemToTextile opts (label, items) = do labelText <- inlineListToTextile opts label contents <- mapM (blockListToTextile opts) items return $ "<dt>" ++ labelText ++ "</dt>\n" ++ (intercalate "\n" $ map (\d -> "<dd>" ++ d ++ "</dd>") contents) -- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed. isSimpleList :: Block -> Bool isSimpleList x = case x of BulletList items -> all isSimpleListItem items OrderedList (num, sty, _) items -> all isSimpleListItem items && num == 1 && sty `elem` [DefaultStyle, Decimal] _ -> False -- | True if list item can be handled with the simple wiki syntax. False if -- HTML tags will be needed. isSimpleListItem :: [Block] -> Bool isSimpleListItem [] = True isSimpleListItem [x] = case x of Plain _ -> True Para _ -> True BulletList _ -> isSimpleList x OrderedList _ _ -> isSimpleList x _ -> False isSimpleListItem [x, y] | isPlainOrPara x = case y of BulletList _ -> isSimpleList y OrderedList _ _ -> isSimpleList y _ -> False isSimpleListItem _ = False isPlainOrPara :: Block -> Bool isPlainOrPara (Plain _) = True isPlainOrPara (Para _) = True isPlainOrPara _ = False -- | Concatenates strings with line breaks between them. vcat :: [String] -> String vcat = intercalate "\n" -- Auxiliary functions for tables. (TODO: these are common to HTML, MediaWiki, -- and Textile writers, and should be abstracted out.) tableRowToTextile :: WriterOptions -> [String] -> Int -> [[Block]] -> State WriterState String tableRowToTextile opts alignStrings rownum cols' = do let celltype = if rownum == 0 then "th" else "td" let rowclass = case rownum of 0 -> "header" x | x `rem` 2 == 1 -> "odd" _ -> "even" cols'' <- sequence $ zipWith (\alignment item -> tableItemToTextile opts celltype alignment item) alignStrings cols' return $ "<tr class=\"" ++ rowclass ++ "\">\n" ++ unlines cols'' ++ "</tr>" alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center" AlignDefault -> "left" tableItemToTextile :: WriterOptions -> String -> String -> [Block] -> State WriterState String tableItemToTextile opts celltype align' item = do let mkcell x = "<" ++ celltype ++ " align=\"" ++ align' ++ "\">" ++ x ++ "</" ++ celltype ++ ">" contents <- blockListToTextile opts item return $ mkcell contents -- | Convert list of Pandoc block elements to Textile. blockListToTextile :: WriterOptions -- ^ Options -> [Block] -- ^ List of block elements -> State WriterState String blockListToTextile opts blocks = mapM (blockToTextile opts) blocks >>= return . vcat -- | Convert list of Pandoc inline elements to Textile. inlineListToTextile :: WriterOptions -> [Inline] -> State WriterState String inlineListToTextile opts lst = mapM (inlineToTextile opts) lst >>= return . concat -- | Convert Pandoc inline element to Textile. inlineToTextile :: WriterOptions -> Inline -> State WriterState String inlineToTextile opts (Span _ lst) = inlineListToTextile opts lst inlineToTextile opts (Emph lst) = do contents <- inlineListToTextile opts lst return $ if '_' `elem` contents then "<em>" ++ contents ++ "</em>" else "_" ++ contents ++ "_" inlineToTextile opts (Strong lst) = do contents <- inlineListToTextile opts lst return $ if '*' `elem` contents then "<strong>" ++ contents ++ "</strong>" else "*" ++ contents ++ "*" inlineToTextile opts (Strikeout lst) = do contents <- inlineListToTextile opts lst return $ if '-' `elem` contents then "<del>" ++ contents ++ "</del>" else "-" ++ contents ++ "-" inlineToTextile opts (Superscript lst) = do contents <- inlineListToTextile opts lst return $ if '^' `elem` contents then "<sup>" ++ contents ++ "</sup>" else "[^" ++ contents ++ "^]" inlineToTextile opts (Subscript lst) = do contents <- inlineListToTextile opts lst return $ if '~' `elem` contents then "<sub>" ++ contents ++ "</sub>" else "[~" ++ contents ++ "~]" inlineToTextile opts (SmallCaps lst) = inlineListToTextile opts lst inlineToTextile opts (Quoted SingleQuote lst) = do contents <- inlineListToTextile opts lst return $ "'" ++ contents ++ "'" inlineToTextile opts (Quoted DoubleQuote lst) = do contents <- inlineListToTextile opts lst return $ "\"" ++ contents ++ "\"" inlineToTextile opts (Cite _ lst) = inlineListToTextile opts lst inlineToTextile _ (Code _ str) = return $ if '@' `elem` str then "<tt>" ++ escapeStringForXML str ++ "</tt>" else "@" ++ str ++ "@" inlineToTextile _ (Str str) = return $ escapeStringForTextile str inlineToTextile _ (Math _ str) = return $ "<span class=\"math\">" ++ escapeStringForXML str ++ "</math>" inlineToTextile _ (RawInline f str) | f == Format "html" || f == Format "textile" = return str | otherwise = return "" inlineToTextile _ (LineBreak) = return "\n" inlineToTextile _ Space = return " " inlineToTextile opts (Link txt (src, _)) = do label <- case txt of [Code _ s] | s == src -> return "$" [Str s] | s == src -> return "$" _ -> inlineListToTextile opts txt return $ "\"" ++ label ++ "\":" ++ src inlineToTextile opts (Image alt (source, tit)) = do alt' <- inlineListToTextile opts alt let txt = if null tit then if null alt' then "" else "(" ++ alt' ++ ")" else "(" ++ tit ++ ")" return $ "!" ++ source ++ txt ++ "!" inlineToTextile opts (Note contents) = do curNotes <- liftM stNotes get let newnum = length curNotes + 1 contents' <- blockListToTextile opts contents let thisnote = "fn" ++ show newnum ++ ". " ++ contents' ++ "\n" modify $ \s -> s { stNotes = thisnote : curNotes } return $ "[" ++ show newnum ++ "]" -- note - may not work for notes with multiple blocks ����������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/DocBook.hs��������������������������������������������������000644 �000765 �000024 �00000133774 12251233602 021313� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������module Text.Pandoc.Readers.DocBook ( readDocBook ) where import Data.Char (toUpper) import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Builder import Text.XML.Light import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) import Data.Generics import Data.Monoid import Data.Char (isSpace) import Control.Monad.State import Control.Applicative ((<$>)) import Data.List (intersperse) {- List of all DocBook tags, with [x] indicating implemented, [o] meaning intentionally left unimplemented (pass through): [o] abbrev - An abbreviation, especially one followed by a period [x] abstract - A summary [o] accel - A graphical user interface (GUI) keyboard shortcut [x] ackno - Acknowledgements in an Article [o] acronym - An often pronounceable word made from the initial [o] action - A response to a user event [o] address - A real-world address, generally a postal address [ ] affiliation - The institutional affiliation of an individual [ ] alt - Text representation for a graphical element [o] anchor - A spot in the document [x] answer - An answer to a question posed in a QandASet [x] appendix - An appendix in a Book or Article [x] appendixinfo - Meta-information for an Appendix [o] application - The name of a software program [x] area - A region defined for a Callout in a graphic or code example [x] areaset - A set of related areas in a graphic or code example [x] areaspec - A collection of regions in a graphic or code example [ ] arg - An argument in a CmdSynopsis [x] article - An article [x] articleinfo - Meta-information for an Article [ ] artpagenums - The page numbers of an article as published [x] attribution - The source of a block quote or epigraph [ ] audiodata - Pointer to external audio data [ ] audioobject - A wrapper for audio data and its associated meta-information [x] author - The name of an individual author [ ] authorblurb - A short description or note about an author [ ] authorgroup - Wrapper for author information when a document has multiple authors or collabarators [x] authorinitials - The initials or other short identifier for an author [o] beginpage - The location of a page break in a print version of the document [ ] bibliocoverage - The spatial or temporal coverage of a document [x] bibliodiv - A section of a Bibliography [x] biblioentry - An entry in a Bibliography [x] bibliography - A bibliography [ ] bibliographyinfo - Meta-information for a Bibliography [ ] biblioid - An identifier for a document [o] bibliolist - A wrapper for a set of bibliography entries [ ] bibliomisc - Untyped bibliographic information [x] bibliomixed - An entry in a Bibliography [ ] bibliomset - A cooked container for related bibliographic information [ ] biblioref - A cross reference to a bibliographic entry [ ] bibliorelation - The relationship of a document to another [ ] biblioset - A raw container for related bibliographic information [ ] bibliosource - The source of a document [ ] blockinfo - Meta-information for a block element [x] blockquote - A quotation set off from the main text [x] book - A book [x] bookinfo - Meta-information for a Book [x] bridgehead - A free-floating heading [ ] callout - A “called out” description of a marked Area [ ] calloutlist - A list of Callouts [x] caption - A caption [x] caution - A note of caution [x] chapter - A chapter, as of a book [x] chapterinfo - Meta-information for a Chapter [ ] citation - An inline bibliographic reference to another published work [ ] citebiblioid - A citation of a bibliographic identifier [ ] citerefentry - A citation to a reference page [ ] citetitle - The title of a cited work [ ] city - The name of a city in an address [ ] classname - The name of a class, in the object-oriented programming sense [ ] classsynopsis - The syntax summary for a class definition [ ] classsynopsisinfo - Information supplementing the contents of a ClassSynopsis [ ] cmdsynopsis - A syntax summary for a software command [ ] co - The location of a callout embedded in text [x] code - An inline code fragment [x] col - Specifications for a column in an HTML table [x] colgroup - A group of columns in an HTML table [ ] collab - Identifies a collaborator [ ] collabname - The name of a collaborator [ ] colophon - Text at the back of a book describing facts about its production [x] colspec - Specifications for a column in a table [x] command - The name of an executable program or other software command [x] computeroutput - Data, generally text, displayed or presented by a computer [ ] confdates - The dates of a conference for which a document was written [ ] confgroup - A wrapper for document meta-information about a conference [ ] confnum - An identifier, frequently numerical, associated with a conference for which a document was written [ ] confsponsor - The sponsor of a conference for which a document was written [ ] conftitle - The title of a conference for which a document was written [x] constant - A programming or system constant [ ] constraint - A constraint in an EBNF production [ ] constraintdef - The definition of a constraint in an EBNF production [ ] constructorsynopsis - A syntax summary for a constructor [ ] contractnum - The contract number of a document [ ] contractsponsor - The sponsor of a contract [ ] contrib - A summary of the contributions made to a document by a credited source [ ] copyright - Copyright information about a document [ ] coref - A cross reference to a co [ ] corpauthor - A corporate author, as opposed to an individual [ ] corpcredit - A corporation or organization credited in a document [ ] corpname - The name of a corporation [ ] country - The name of a country [ ] database - The name of a database, or part of a database [x] date - The date of publication or revision of a document [ ] dedication - A wrapper for the dedication section of a book [ ] destructorsynopsis - A syntax summary for a destructor [ ] edition - The name or number of an edition of a document [ ] editor - The name of the editor of a document [x] email - An email address [x] emphasis - Emphasized text [x] entry - A cell in a table [ ] entrytbl - A subtable appearing in place of an Entry in a table [ ] envar - A software environment variable [x] epigraph - A short inscription at the beginning of a document or component note: also handle embedded attribution tag [ ] equation - A displayed mathematical equation [ ] errorcode - An error code [ ] errorname - An error name [ ] errortext - An error message. [ ] errortype - The classification of an error message [ ] example - A formal example, with a title [ ] exceptionname - The name of an exception [ ] fax - A fax number [ ] fieldsynopsis - The name of a field in a class definition [x] figure - A formal figure, generally an illustration, with a title [x] filename - The name of a file [ ] firstname - The first name of a person [ ] firstterm - The first occurrence of a term [x] footnote - A footnote [ ] footnoteref - A cross reference to a footnote (a footnote mark) [x] foreignphrase - A word or phrase in a language other than the primary language of the document [x] formalpara - A paragraph with a title [ ] funcdef - A function (subroutine) name and its return type [ ] funcparams - Parameters for a function referenced through a function pointer in a synopsis [ ] funcprototype - The prototype of a function [ ] funcsynopsis - The syntax summary for a function definition [ ] funcsynopsisinfo - Information supplementing the FuncDefs of a FuncSynopsis [x] function - The name of a function or subroutine, as in a programming language [x] glossary - A glossary [x] glossaryinfo - Meta-information for a Glossary [x] glossdef - A definition in a GlossEntry [x] glossdiv - A division in a Glossary [x] glossentry - An entry in a Glossary or GlossList [x] glosslist - A wrapper for a set of GlossEntrys [x] glosssee - A cross-reference from one GlossEntry to another [x] glossseealso - A cross-reference from one GlossEntry to another [x] glossterm - A glossary term [ ] graphic - A displayed graphical object (not an inline) [ ] graphicco - A graphic that contains callout areas [ ] group - A group of elements in a CmdSynopsis [ ] guibutton - The text on a button in a GUI [ ] guiicon - Graphic and/or text appearing as a icon in a GUI [ ] guilabel - The text of a label in a GUI [ ] guimenu - The name of a menu in a GUI [ ] guimenuitem - The name of a terminal menu item in a GUI [ ] guisubmenu - The name of a submenu in a GUI [ ] hardware - A physical part of a computer system [ ] highlights - A summary of the main points of the discussed component [ ] holder - The name of the individual or organization that holds a copyright [o] honorific - The title of a person [ ] html:form - An HTML form [ ] imagedata - Pointer to external image data [ ] imageobject - A wrapper for image data and its associated meta-information [ ] imageobjectco - A wrapper for an image object with callouts [x] important - An admonition set off from the text [x] index - An index [x] indexdiv - A division in an index [x] indexentry - An entry in an index [x] indexinfo - Meta-information for an Index [x] indexterm - A wrapper for terms to be indexed [x] info - A wrapper for information about a component or other block. (DocBook v5) [ ] informalequation - A displayed mathematical equation without a title [ ] informalexample - A displayed example without a title [ ] informalfigure - A untitled figure [ ] informaltable - A table without a title [ ] initializer - The initializer for a FieldSynopsis [ ] inlineequation - A mathematical equation or expression occurring inline [ ] inlinegraphic - An object containing or pointing to graphical data that will be rendered inline [x] inlinemediaobject - An inline media object (video, audio, image, and so on) [ ] interface - An element of a GUI [ ] interfacename - The name of an interface [ ] invpartnumber - An inventory part number [ ] isbn - The International Standard Book Number of a document [ ] issn - The International Standard Serial Number of a periodical [ ] issuenum - The number of an issue of a journal [x] itemizedlist - A list in which each entry is marked with a bullet or other dingbat [ ] itermset - A set of index terms in the meta-information of a document [ ] jobtitle - The title of an individual in an organization [ ] keycap - The text printed on a key on a keyboard [ ] keycode - The internal, frequently numeric, identifier for a key on a keyboard [ ] keycombo - A combination of input actions [ ] keysym - The symbolic name of a key on a keyboard [ ] keyword - One of a set of keywords describing the content of a document [ ] keywordset - A set of keywords describing the content of a document [ ] label - A label on a Question or Answer [ ] legalnotice - A statement of legal obligations or requirements [ ] lhs - The left-hand side of an EBNF production [ ] lineage - The portion of a person's name indicating a relationship to ancestors [ ] lineannotation - A comment on a line in a verbatim listing [x] link - A hypertext link [x] listitem - A wrapper for the elements of a list item [x] literal - Inline text that is some literal value [x] literallayout - A block of text in which line breaks and white space are to be reproduced faithfully [ ] lot - A list of the titles of formal objects (as tables or figures) in a document [ ] lotentry - An entry in a list of titles [ ] manvolnum - A reference volume number [x] markup - A string of formatting markup in text that is to be represented literally [ ] mathphrase - A mathematical phrase, an expression that can be represented with ordinary text and a small amount of markup [ ] medialabel - A name that identifies the physical medium on which some information resides [x] mediaobject - A displayed media object (video, audio, image, etc.) [ ] mediaobjectco - A media object that contains callouts [x] member - An element of a simple list [ ] menuchoice - A selection or series of selections from a menu [ ] methodname - The name of a method [ ] methodparam - Parameters to a method [ ] methodsynopsis - A syntax summary for a method [ ] mml:math - A MathML equation [ ] modespec - Application-specific information necessary for the completion of an OLink [ ] modifier - Modifiers in a synopsis [ ] mousebutton - The conventional name of a mouse button [ ] msg - A message in a message set [ ] msgaud - The audience to which a message in a message set is relevant [ ] msgentry - A wrapper for an entry in a message set [ ] msgexplan - Explanatory material relating to a message in a message set [ ] msginfo - Information about a message in a message set [ ] msglevel - The level of importance or severity of a message in a message set [ ] msgmain - The primary component of a message in a message set [ ] msgorig - The origin of a message in a message set [ ] msgrel - A related component of a message in a message set [ ] msgset - A detailed set of messages, usually error messages [ ] msgsub - A subcomponent of a message in a message set [ ] msgtext - The actual text of a message component in a message set [ ] nonterminal - A non-terminal in an EBNF production [x] note - A message set off from the text [ ] objectinfo - Meta-information for an object [ ] olink - A link that addresses its target indirectly, through an entity [ ] ooclass - A class in an object-oriented programming language [ ] ooexception - An exception in an object-oriented programming language [ ] oointerface - An interface in an object-oriented programming language [x] option - An option for a software command [x] optional - Optional information [x] orderedlist - A list in which each entry is marked with a sequentially incremented label [ ] orgdiv - A division of an organization [ ] orgname - The name of an organization other than a corporation [ ] otheraddr - Uncategorized information in address [ ] othercredit - A person or entity, other than an author or editor, credited in a document [ ] othername - A component of a persons name that is not a first name, surname, or lineage [ ] package - A package [ ] pagenums - The numbers of the pages in a book, for use in a bibliographic entry [x] para - A paragraph [ ] paramdef - Information about a function parameter in a programming language [x] parameter - A value or a symbolic reference to a value [ ] part - A division in a book [ ] partinfo - Meta-information for a Part [ ] partintro - An introduction to the contents of a part [ ] personblurb - A short description or note about a person [ ] personname - The personal name of an individual [ ] phone - A telephone number [ ] phrase - A span of text [ ] pob - A post office box in an address [ ] postcode - A postal code in an address [x] preface - Introductory matter preceding the first chapter of a book [ ] prefaceinfo - Meta-information for a Preface [ ] primary - The primary word or phrase under which an index term should be sorted [ ] primaryie - A primary term in an index entry, not in the text [ ] printhistory - The printing history of a document [ ] procedure - A list of operations to be performed in a well-defined sequence [ ] production - A production in a set of EBNF productions [ ] productionrecap - A cross-reference to an EBNF production [ ] productionset - A set of EBNF productions [ ] productname - The formal name of a product [ ] productnumber - A number assigned to a product [x] programlisting - A literal listing of all or part of a program [ ] programlistingco - A program listing with associated areas used in callouts [x] prompt - A character or string indicating the start of an input field in a computer display [ ] property - A unit of data associated with some part of a computer system [ ] pubdate - The date of publication of a document [ ] publisher - The publisher of a document [ ] publishername - The name of the publisher of a document [ ] pubsnumber - A number assigned to a publication other than an ISBN or ISSN or inventory part number [x] qandadiv - A titled division in a QandASet [o] qandaentry - A question/answer set within a QandASet [o] qandaset - A question-and-answer set [x] question - A question in a QandASet [x] quote - An inline quotation [ ] refclass - The scope or other indication of applicability of a reference entry [ ] refdescriptor - A description of the topic of a reference page [ ] refentry - A reference page (originally a UNIX man-style reference page) [ ] refentryinfo - Meta-information for a Refentry [ ] refentrytitle - The title of a reference page [ ] reference - A collection of reference entries [ ] referenceinfo - Meta-information for a Reference [ ] refmeta - Meta-information for a reference entry [ ] refmiscinfo - Meta-information for a reference entry other than the title and volume number [ ] refname - The name of (one of) the subject(s) of a reference page [ ] refnamediv - The name, purpose, and classification of a reference page [ ] refpurpose - A short (one sentence) synopsis of the topic of a reference page [x] refsect1 - A major subsection of a reference entry [x] refsect1info - Meta-information for a RefSect1 [x] refsect2 - A subsection of a RefSect1 [x] refsect2info - Meta-information for a RefSect2 [x] refsect3 - A subsection of a RefSect2 [x] refsect3info - Meta-information for a RefSect3 [x] refsection - A recursive section in a refentry [x] refsectioninfo - Meta-information for a refsection [ ] refsynopsisdiv - A syntactic synopsis of the subject of the reference page [ ] refsynopsisdivinfo - Meta-information for a RefSynopsisDiv [ ] releaseinfo - Information about a particular release of a document [ ] remark - A remark (or comment) intended for presentation in a draft manuscript [ ] replaceable - Content that may or must be replaced by the user [ ] returnvalue - The value returned by a function [ ] revdescription - A extended description of a revision to a document [ ] revhistory - A history of the revisions to a document [ ] revision - An entry describing a single revision in the history of the revisions to a document [ ] revnumber - A document revision number [ ] revremark - A description of a revision to a document [ ] rhs - The right-hand side of an EBNF production [x] row - A row in a table [ ] sbr - An explicit line break in a command synopsis [x] screen - Text that a user sees or might see on a computer screen [o] screenco - A screen with associated areas used in callouts [o] screeninfo - Information about how a screen shot was produced [ ] screenshot - A representation of what the user sees or might see on a computer screen [ ] secondary - A secondary word or phrase in an index term [ ] secondaryie - A secondary term in an index entry, rather than in the text [x] sect1 - A top-level section of document [x] sect1info - Meta-information for a Sect1 [x] sect2 - A subsection within a Sect1 [x] sect2info - Meta-information for a Sect2 [x] sect3 - A subsection within a Sect2 [x] sect3info - Meta-information for a Sect3 [x] sect4 - A subsection within a Sect3 [x] sect4info - Meta-information for a Sect4 [x] sect5 - A subsection within a Sect4 [x] sect5info - Meta-information for a Sect5 [x] section - A recursive section [x] sectioninfo - Meta-information for a recursive section [x] see - Part of an index term directing the reader instead to another entry in the index [x] seealso - Part of an index term directing the reader also to another entry in the index [ ] seealsoie - A See also entry in an index, rather than in the text [ ] seeie - A See entry in an index, rather than in the text [x] seg - An element of a list item in a segmented list [x] seglistitem - A list item in a segmented list [x] segmentedlist - A segmented list, a list of sets of elements [x] segtitle - The title of an element of a list item in a segmented list [ ] seriesvolnums - Numbers of the volumes in a series of books [ ] set - A collection of books [ ] setindex - An index to a set of books [ ] setindexinfo - Meta-information for a SetIndex [ ] setinfo - Meta-information for a Set [ ] sgmltag - A component of SGML markup [ ] shortaffil - A brief description of an affiliation [ ] shortcut - A key combination for an action that is also accessible through a menu [ ] sidebar - A portion of a document that is isolated from the main narrative flow [ ] sidebarinfo - Meta-information for a Sidebar [x] simpara - A paragraph that contains only text and inline markup, no block elements [x] simplelist - An undecorated list of single words or short phrases [ ] simplemsgentry - A wrapper for a simpler entry in a message set [ ] simplesect - A section of a document with no subdivisions [ ] spanspec - Formatting information for a spanned column in a table [ ] state - A state or province in an address [ ] step - A unit of action in a procedure [ ] stepalternatives - Alternative steps in a procedure [ ] street - A street address in an address [ ] structfield - A field in a structure (in the programming language sense) [ ] structname - The name of a structure (in the programming language sense) [ ] subject - One of a group of terms describing the subject matter of a document [ ] subjectset - A set of terms describing the subject matter of a document [ ] subjectterm - A term in a group of terms describing the subject matter of a document [x] subscript - A subscript (as in H2O, the molecular formula for water) [ ] substeps - A wrapper for steps that occur within steps in a procedure [x] subtitle - The subtitle of a document [x] superscript - A superscript (as in x2, the mathematical notation for x multiplied by itself) [ ] surname - A family name; in western cultures the last name [ ] svg:svg - An SVG graphic [x] symbol - A name that is replaced by a value before processing [ ] synopfragment - A portion of a CmdSynopsis broken out from the main body of the synopsis [ ] synopfragmentref - A reference to a fragment of a command synopsis [ ] synopsis - A general-purpose element for representing the syntax of commands or functions [ ] systemitem - A system-related item or term [ ] table - A formal table in a document [ ] task - A task to be completed [ ] taskprerequisites - The prerequisites for a task [ ] taskrelated - Information related to a task [ ] tasksummary - A summary of a task [x] tbody - A wrapper for the rows of a table or informal table [x] td - A table entry in an HTML table [x] term - The word or phrase being defined or described in a variable list [ ] termdef - An inline term definition [ ] tertiary - A tertiary word or phrase in an index term [ ] tertiaryie - A tertiary term in an index entry, rather than in the text [ ] textdata - Pointer to external text data [ ] textobject - A wrapper for a text description of an object and its associated meta-information [ ] tfoot - A table footer consisting of one or more rows [x] tgroup - A wrapper for the main content of a table, or part of a table [x] th - A table header entry in an HTML table [x] thead - A table header consisting of one or more rows [x] tip - A suggestion to the user, set off from the text [x] title - The text of the title of a section of a document or of a formal block-level element [x] titleabbrev - The abbreviation of a Title [x] toc - A table of contents [x] tocback - An entry in a table of contents for a back matter component [x] tocchap - An entry in a table of contents for a component in the body of a document [x] tocentry - A component title in a table of contents [x] tocfront - An entry in a table of contents for a front matter component [x] toclevel1 - A top-level entry within a table of contents entry for a chapter-like component [x] toclevel2 - A second-level entry within a table of contents entry for a chapter-like component [x] toclevel3 - A third-level entry within a table of contents entry for a chapter-like component [x] toclevel4 - A fourth-level entry within a table of contents entry for a chapter-like component [x] toclevel5 - A fifth-level entry within a table of contents entry for a chapter-like component [x] tocpart - An entry in a table of contents for a part of a book [ ] token - A unit of information [x] tr - A row in an HTML table [ ] trademark - A trademark [ ] type - The classification of a value [x] ulink - A link that addresses its target by means of a URL (Uniform Resource Locator) [x] uri - A Uniform Resource Identifier [x] userinput - Data entered by the user [x] varargs - An empty element in a function synopsis indicating a variable number of arguments [x] variablelist - A list in which each entry is composed of a set of one or more terms and an associated description [x] varlistentry - A wrapper for a set of terms and the associated description in a variable list [x] varname - The name of a variable [ ] videodata - Pointer to external video data [ ] videoobject - A wrapper for video data and its associated meta-information [ ] void - An empty element in a function synopsis indicating that the function in question takes no arguments [ ] volumenum - The volume number of a document in a set (as of books in a set or articles in a journal) [x] warning - An admonition set off from the text [x] wordasword - A word meant specifically as a word and not representing anything else [ ] xref - A cross reference to another part of the document [ ] year - The year of publication of a document -} type DB = State DBState data DBState = DBState{ dbSectionLevel :: Int , dbQuoteType :: QuoteType , dbDocTitle :: Inlines , dbDocAuthors :: [Inlines] , dbDocDate :: Inlines , dbBook :: Bool , dbFigureTitle :: Inlines } deriving Show readDocBook :: ReaderOptions -> String -> Pandoc readDocBook _ inp = setTitle (dbDocTitle st') $ setAuthors (dbDocAuthors st') $ setDate (dbDocDate st') $ doc $ mconcat bs where (bs, st') = runState (mapM parseBlock $ normalizeTree $ parseXML inp) DBState{ dbSectionLevel = 0 , dbQuoteType = DoubleQuote , dbDocTitle = mempty , dbDocAuthors = [] , dbDocDate = mempty , dbBook = False , dbFigureTitle = mempty } getFigure :: Element -> DB Blocks getFigure e = do tit <- case filterChild (named "title") e of Just t -> getInlines t Nothing -> return mempty modify $ \st -> st{ dbFigureTitle = tit } res <- getBlocks e modify $ \st -> st{ dbFigureTitle = mempty } return res -- normalize input, consolidating adjacent Text and CRef elements normalizeTree :: [Content] -> [Content] normalizeTree = everywhere (mkT go) where go :: [Content] -> [Content] go (Text (CData CDataRaw _ _):xs) = xs go (Text (CData CDataText s1 z):Text (CData CDataText s2 _):xs) = Text (CData CDataText (s1 ++ s2) z):xs go (Text (CData CDataText s1 z):CRef r:xs) = Text (CData CDataText (s1 ++ convertEntity r) z):xs go (CRef r:Text (CData CDataText s1 z):xs) = Text (CData CDataText (convertEntity r ++ s1) z):xs go (CRef r1:CRef r2:xs) = Text (CData CDataText (convertEntity r1 ++ convertEntity r2) Nothing):xs go xs = xs convertEntity :: String -> String convertEntity e = maybe (map toUpper e) (:[]) (lookupEntity e) -- convenience function to get an attribute value, defaulting to "" attrValue :: String -> Element -> String attrValue attr elt = case lookupAttrBy (\x -> qName x == attr) (elAttribs elt) of Just z -> z Nothing -> "" -- convenience function named :: String -> Element -> Bool named s e = qName (elName e) == s isBlockElement :: Content -> Bool isBlockElement (Elem e) = qName (elName e) `elem` blocktags where blocktags = ["toc","index","para","formalpara","simpara", "ackno","epigraph","blockquote","bibliography","bibliodiv", "biblioentry","glossee","glosseealso","glossary", "glossdiv","glosslist","chapter","appendix","preface", "bridgehead","sect1","sect2","sect3","sect4","sect5","section", "refsect1","refsect2","refsect3","refsection", "important","caution","note","tip","warning","qandadiv", "question","answer","abstract","itemizedlist","orderedlist", "variablelist","article","book","table","informaltable", "screen","programlisting","example"] isBlockElement _ = False -- Trim leading and trailing newline characters trimNl :: String -> String trimNl = reverse . go . reverse . go where go ('\n':xs) = xs go xs = xs -- meld text into beginning of first paragraph of Blocks. -- assumes Blocks start with a Para; if not, does nothing. addToStart :: Inlines -> Blocks -> Blocks addToStart toadd bs = case toList bs of (Para xs : rest) -> para (toadd <> fromList xs) <> fromList rest _ -> bs -- function that is used by both mediaobject (in parseBlock) -- and inlinemediaobject (in parseInline) getImage :: Element -> DB Inlines getImage e = do imageUrl <- case filterChild (named "imageobject") e of Nothing -> return mempty Just z -> case filterChild (named "imagedata") z of Nothing -> return mempty Just i -> return $ attrValue "fileref" i caption <- case filterChild (\x -> named "caption" x || named "textobject" x) e of Nothing -> gets dbFigureTitle Just z -> mconcat <$> (mapM parseInline $ elContent z) return $ image imageUrl "" caption getBlocks :: Element -> DB Blocks getBlocks e = mconcat <$> (mapM parseBlock $ elContent e) parseBlock :: Content -> DB Blocks parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE parseBlock (Text (CData _ s _)) = if all isSpace s then return mempty else return $ plain $ trimInlines $ text s parseBlock (CRef x) = return $ plain $ str $ map toUpper x parseBlock (Elem e) = case qName (elName e) of "toc" -> return mempty -- skip TOC, since in pandoc it's autogenerated "index" -> return mempty -- skip index, since page numbers meaningless "para" -> parseMixed para (elContent e) "formalpara" -> do tit <- case filterChild (named "title") e of Just t -> (<> str "." <> linebreak) <$> emph <$> getInlines t Nothing -> return mempty addToStart tit <$> parseMixed para (elContent e) "simpara" -> parseMixed para (elContent e) "ackno" -> parseMixed para (elContent e) "epigraph" -> parseBlockquote "blockquote" -> parseBlockquote "attribution" -> return mempty "titleabbrev" -> return mempty "authorinitials" -> return mempty "title" -> return mempty -- handled by getTitle or sect or figure "bibliography" -> sect 0 "bibliodiv" -> sect 1 "biblioentry" -> parseMixed para (elContent e) "bibliomixed" -> parseMixed para (elContent e) "glosssee" -> para . (\ils -> text "See " <> ils <> str ".") <$> getInlines e "glossseealso" -> para . (\ils -> text "See also " <> ils <> str ".") <$> getInlines e "glossary" -> sect 0 "glossdiv" -> definitionList <$> mapM parseGlossEntry (filterChildren (named "glossentry") e) "glosslist" -> definitionList <$> mapM parseGlossEntry (filterChildren (named "glossentry") e) "chapter" -> sect 0 "appendix" -> sect 0 "preface" -> sect 0 "bridgehead" -> para . strong <$> getInlines e "sect1" -> sect 1 "sect2" -> sect 2 "sect3" -> sect 3 "sect4" -> sect 4 "sect5" -> sect 5 "section" -> gets dbSectionLevel >>= sect . (+1) "refsect1" -> sect 1 "refsect2" -> sect 2 "refsect3" -> sect 3 "refsection" -> gets dbSectionLevel >>= sect . (+1) "important" -> blockQuote . (para (strong $ str "Important") <>) <$> getBlocks e "caution" -> blockQuote . (para (strong $ str "Caution") <>) <$> getBlocks e "note" -> blockQuote . (para (strong $ str "Note") <>) <$> getBlocks e "tip" -> blockQuote . (para (strong $ str "Tip") <>) <$> getBlocks e "warning" -> blockQuote . (para (strong $ str "Warning") <>) <$> getBlocks e "area" -> return mempty "areaset" -> return mempty "areaspec" -> return mempty "qandadiv" -> gets dbSectionLevel >>= sect . (+1) "question" -> addToStart (strong (str "Q:") <> str " ") <$> getBlocks e "answer" -> addToStart (strong (str "A:") <> str " ") <$> getBlocks e "abstract" -> blockQuote <$> getBlocks e "itemizedlist" -> bulletList <$> listitems "orderedlist" -> do let listStyle = case attrValue "numeration" e of "arabic" -> Decimal "loweralpha" -> LowerAlpha "upperalpha" -> UpperAlpha "lowerroman" -> LowerRoman "upperroman" -> UpperRoman _ -> Decimal let start = maybe 1 id $ (attrValue "override" <$> filterElement (named "listitem") e) >>= safeRead orderedListWith (start,listStyle,DefaultDelim) <$> listitems "variablelist" -> definitionList <$> deflistitems "figure" -> getFigure e "mediaobject" -> para <$> getImage e "caption" -> return mempty "info" -> getTitle >> getAuthors >> getDate >> return mempty "articleinfo" -> getTitle >> getAuthors >> getDate >> return mempty "sectioninfo" -> return mempty -- keywords & other metadata "refsectioninfo" -> return mempty -- keywords & other metadata "refsect1info" -> return mempty -- keywords & other metadata "refsect2info" -> return mempty -- keywords & other metadata "refsect3info" -> return mempty -- keywords & other metadata "sect1info" -> return mempty -- keywords & other metadata "sect2info" -> return mempty -- keywords & other metadata "sect3info" -> return mempty -- keywords & other metadata "sect4info" -> return mempty -- keywords & other metadata "sect5info" -> return mempty -- keywords & other metadata "chapterinfo" -> return mempty -- keywords & other metadata "glossaryinfo" -> return mempty -- keywords & other metadata "appendixinfo" -> return mempty -- keywords & other metadata "bookinfo" -> getTitle >> getAuthors >> getDate >> return mempty "article" -> modify (\st -> st{ dbBook = False }) >> getTitle >> getBlocks e "book" -> modify (\st -> st{ dbBook = True }) >> getTitle >> getBlocks e "table" -> parseTable "informaltable" -> parseTable "literallayout" -> codeBlockWithLang "screen" -> codeBlockWithLang "programlisting" -> codeBlockWithLang "?xml" -> return mempty _ -> getBlocks e where parseMixed container conts = do let (ils,rest) = break isBlockElement conts ils' <- (trimInlines . mconcat) <$> mapM parseInline ils let p = if ils' == mempty then mempty else container ils' case rest of [] -> return p (r:rs) -> do b <- parseBlock r x <- parseMixed container rs return $ p <> b <> x codeBlockWithLang = do let classes' = case attrValue "language" e of "" -> [] x -> [x] return $ codeBlockWith (attrValue "id" e, classes', []) $ trimNl $ strContent e parseBlockquote = do attrib <- case filterChild (named "attribution") e of Nothing -> return mempty Just z -> (para . (str "— " <>) . mconcat) <$> (mapM parseInline $ elContent z) contents <- getBlocks e return $ blockQuote (contents <> attrib) listitems = mapM getBlocks $ filterChildren (named "listitem") e deflistitems = mapM parseVarListEntry $ filterChildren (named "varlistentry") e parseVarListEntry e' = do let terms = filterChildren (named "term") e' let items = filterChildren (named "listitem") e' terms' <- mapM getInlines terms items' <- mapM getBlocks items return (mconcat $ intersperse (str "; ") terms', items') parseGlossEntry e' = do let terms = filterChildren (named "glossterm") e' let items = filterChildren (named "glossdef") e' terms' <- mapM getInlines terms items' <- mapM getBlocks items return (mconcat $ intersperse (str "; ") terms', items') getTitle = case filterChild (named "title") e of Just t -> do tit <- getInlines t subtit <- case filterChild (named "subtitle") e of Just s -> (text ": " <>) <$> getInlines s Nothing -> return mempty modify $ \st -> st{dbDocTitle = tit <> subtit} Nothing -> return () getAuthors = do auths <- mapM getInlines $ filterChildren (named "author") e modify $ \st -> st{dbDocAuthors = auths} getDate = case filterChild (named "date") e of Just t -> do dat <- getInlines t modify $ \st -> st{dbDocDate = dat} Nothing -> return () parseTable = do let isCaption x = named "title" x || named "caption" x caption <- case filterChild isCaption e of Just t -> getInlines t Nothing -> return mempty let e' = maybe e id $ 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 _ -> filterChildren isColspec e' let isRow x = named "row" x || named "tr" x headrows <- case filterChild (named "thead") e' of Just h -> case filterChild isRow h of Just x -> parseRow x Nothing -> return [] Nothing -> return [] bodyrows <- case filterChild (named "tbody") e' of Just b -> mapM parseRow $ filterChildren isRow b Nothing -> mapM parseRow $ filterChildren isRow e' let toAlignment c = case findAttr (unqual "align") c of Just "left" -> AlignLeft Just "right" -> AlignRight Just "center" -> AlignCenter _ -> AlignDefault let toWidth c = case findAttr (unqual "colwidth") c of Just w -> maybe 0 id $ safeRead $ '0': filter (\x -> (x >= '0' && x <= '9') || x == '.') w Nothing -> 0 :: Double let numrows = maximum $ map length bodyrows let aligns = case colspecs of [] -> replicate numrows AlignDefault cs -> map toAlignment cs let widths = case colspecs of [] -> replicate numrows 0 cs -> let ws = map toWidth cs tot = sum ws in if all (> 0) ws then map (/ tot) ws else replicate numrows 0 let headrows' = if null headrows then replicate numrows mempty else headrows return $ table caption (zip aligns widths) headrows' bodyrows isEntry x = named "entry" x || named "td" x || named "th" x parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry sect n = do isbook <- gets dbBook let n' = if isbook || n == 0 then n + 1 else n headerText <- case filterChild (named "title") e of Just t -> getInlines t Nothing -> return mempty modify $ \st -> st{ dbSectionLevel = n } b <- getBlocks e modify $ \st -> st{ dbSectionLevel = n - 1 } return $ header n' headerText <> b getInlines :: Element -> DB Inlines getInlines e' = (trimInlines . mconcat) <$> (mapM parseInline $ elContent e') parseInline :: Content -> DB Inlines parseInline (Text (CData _ s _)) = return $ text s parseInline (CRef ref) = return $ maybe (text $ map toUpper ref) (text . (:[])) $ lookupEntity ref parseInline (Elem e) = case qName (elName e) of "subscript" -> subscript <$> innerInlines "superscript" -> superscript <$> innerInlines "inlinemediaobject" -> getImage e "quote" -> do qt <- gets dbQuoteType let qt' = if qt == SingleQuote then DoubleQuote else SingleQuote modify $ \st -> st{ dbQuoteType = qt' } contents <- innerInlines modify $ \st -> st{ dbQuoteType = qt } return $ if qt == SingleQuote then singleQuoted contents else doubleQuoted contents "simplelist" -> simpleList "segmentedlist" -> segmentedList "code" -> codeWithLang "filename" -> codeWithLang "literal" -> codeWithLang "computeroutput" -> codeWithLang "prompt" -> codeWithLang "parameter" -> codeWithLang "option" -> codeWithLang "optional" -> do x <- getInlines e return $ str "[" <> x <> str "]" "markup" -> codeWithLang "wordasword" -> emph <$> innerInlines "command" -> codeWithLang "varname" -> codeWithLang "function" -> codeWithLang "type" -> codeWithLang "symbol" -> codeWithLang "constant" -> codeWithLang "userinput" -> codeWithLang "varargs" -> return $ code "(...)" "xref" -> return $ str "?" -- so at least you know something is there "email" -> return $ link ("mailto:" ++ strContent e) "" $ str $ strContent e "uri" -> return $ link (strContent e) "" $ str $ strContent e "ulink" -> link (attrValue "url" e) "" <$> innerInlines "link" -> do ils <- innerInlines let href = case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of Just h -> h _ -> ('#' : attrValue "linkend" e) let ils' = if ils == mempty then str href else ils return $ link href "" ils' "foreignphrase" -> emph <$> innerInlines "emphasis" -> case attrValue "role" e of "bold" -> strong <$> innerInlines "strong" -> strong <$> innerInlines "strikethrough" -> strikeout <$> innerInlines _ -> emph <$> innerInlines "footnote" -> (note . mconcat) <$> (mapM parseBlock $ elContent e) "title" -> return mempty _ -> innerInlines where innerInlines = (trimInlines . mconcat) <$> (mapM parseInline $ elContent e) codeWithLang = do let classes' = case attrValue "language" e of "" -> [] l -> [l] return $ codeWith (attrValue "id" e,classes',[]) $ strContent e simpleList = (mconcat . intersperse (str "," <> space)) <$> mapM getInlines (filterChildren (named "member") e) segmentedList = do tit <- maybe (return mempty) getInlines $ filterChild (named "title") e segtits <- mapM getInlines $ filterChildren (named "segtitle") e segitems <- mapM (mapM getInlines . filterChildren (named "seg")) $ filterChildren (named "seglistitem") e let toSeg = mconcat . zipWith (\x y -> strong (x <> str ":") <> space <> y <> linebreak) segtits let segs = mconcat $ map toSeg segitems let tit' = if tit == mempty then mempty else strong tit <> linebreak return $ linebreak <> tit' <> segs ����pandoc-1.12.2.1/src/Text/Pandoc/Readers/Haddock/����������������������������������������������������000755 �000765 �000024 �00000000000 12251233602 020755� 5����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/Haddock.hs��������������������������������������������������000644 �000765 �000024 �00000002660 12251233602 021315� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- | Module : Text.Pandoc.Readers.Haddock Copyright : Copyright (C) 2013 David Lazar License : GNU GPL, version 2 or above Maintainer : David Lazar <lazar6@illinois.edu> Stability : alpha Conversion of Haddock markup to 'Pandoc' document. -} module Text.Pandoc.Readers.Haddock ( readHaddock ) where import Text.Pandoc.Builder import Text.Pandoc.Options import Text.Pandoc.Readers.Haddock.Lex import Text.Pandoc.Readers.Haddock.Parse -- | Parse Haddock markup and return a 'Pandoc' document. readHaddock :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse -> Pandoc readHaddock _ s = Pandoc nullMeta blocks where blocks = case parseParas (tokenise s (0,0)) of Left [] -> error "parse failure" Left (tok:_) -> error $ "parse failure " ++ pos (tokenPos tok) where pos (l, c) = "(line " ++ show l ++ ", column " ++ show c ++ ")" Right x -> mergeLists (toList x) -- similar to 'docAppend' in Haddock.Doc mergeLists :: [Block] -> [Block] mergeLists (BulletList xs : BulletList ys : blocks) = mergeLists (BulletList (xs ++ ys) : blocks) mergeLists (OrderedList _ xs : OrderedList a ys : blocks) = mergeLists (OrderedList a (xs ++ ys) : blocks) mergeLists (DefinitionList xs : DefinitionList ys : blocks) = mergeLists (DefinitionList (xs ++ ys) : blocks) mergeLists (x : blocks) = x : mergeLists blocks mergeLists [] = [] ��������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/HTML.hs�����������������������������������������������������000644 �000765 �000024 �00000056401 12251233602 020526� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.HTML Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of HTML to 'Pandoc' document. -} module Text.Pandoc.Readers.HTML ( readHtml , htmlTag , htmlInBalanced , isInlineTag , isBlockTag , isTextTag , isCommentTag ) where import Text.HTML.TagSoup import Text.HTML.TagSoup.Match import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Shared import Text.Pandoc.Options import Text.Pandoc.Parsing import Data.Maybe ( fromMaybe, isJust ) import Data.List ( intercalate ) import Data.Char ( isDigit ) import Control.Monad ( liftM, guard, when, mzero ) import Control.Applicative ( (<$>), (<$), (<*) ) isSpace :: Char -> Bool isSpace ' ' = True isSpace '\t' = True isSpace '\n' = True isSpace _ = False -- | Convert HTML-formatted string to 'Pandoc' document. readHtml :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assumes @'\n'@ line endings) -> Pandoc readHtml opts inp = case runParser parseDoc def{ stateOptions = opts } "source" tags of Left err' -> error $ "\nError at " ++ show err' Right result -> result where tags = canonicalizeTags $ parseTagsOptions parseOptions{ optTagPosition = True } inp parseDoc = do blocks <- (fixPlains False . concat) <$> manyTill block eof meta <- stateMeta <$> getState return $ Pandoc meta blocks type TagParser = Parser [Tag String] ParserState pBody :: TagParser [Block] pBody = pInTags "body" block pHead :: TagParser [Block] pHead = pInTags "head" $ pTitle <|> ([] <$ pAnyTag) where pTitle = pInTags "title" inline >>= setTitle . normalizeSpaces setTitle t = [] <$ (updateState $ B.setMeta "title" (B.fromList t)) block :: TagParser [Block] block = choice [ pPara , pHeader , pBlockQuote , pCodeBlock , pList , pHrule , pTable , pHead , pBody , pPlain , pDiv , pRawHtmlBlock ] pList :: TagParser [Block] pList = pBulletList <|> pOrderedList <|> pDefinitionList pBulletList :: TagParser [Block] pBulletList = try $ do pSatisfy (~== TagOpen "ul" []) let nonItem = pSatisfy (\t -> not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) && not (t ~== TagClose "ul")) -- note: if they have an <ol> or <ul> not in scope of a <li>, -- treat it as a list item, though it's not valid xhtml... skipMany nonItem items <- manyTill (pInTags "li" block >>~ skipMany nonItem) (pCloses "ul") return [BulletList $ map (fixPlains True) items] pOrderedList :: TagParser [Block] pOrderedList = try $ do TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" []) let (start, style) = (sta', sty') where sta = fromMaybe "1" $ lookup "start" attribs sta' = if all isDigit sta then read sta else 1 sty = fromMaybe (fromMaybe "" $ lookup "style" attribs) $ lookup "class" attribs sty' = case sty of "lower-roman" -> LowerRoman "upper-roman" -> UpperRoman "lower-alpha" -> LowerAlpha "upper-alpha" -> UpperAlpha "decimal" -> Decimal _ -> DefaultStyle let nonItem = pSatisfy (\t -> not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) && not (t ~== TagClose "ol")) -- note: if they have an <ol> or <ul> not in scope of a <li>, -- treat it as a list item, though it's not valid xhtml... skipMany nonItem items <- manyTill (pInTags "li" block >>~ skipMany nonItem) (pCloses "ol") return [OrderedList (start, style, DefaultDelim) $ map (fixPlains True) items] pDefinitionList :: TagParser [Block] pDefinitionList = try $ do pSatisfy (~== TagOpen "dl" []) items <- manyTill pDefListItem (pCloses "dl") return [DefinitionList items] pDefListItem :: TagParser ([Inline],[[Block]]) pDefListItem = try $ do let nonItem = pSatisfy (\t -> not (t ~== TagOpen "dt" []) && not (t ~== TagOpen "dd" []) && not (t ~== TagClose "dl")) terms <- many1 (try $ skipMany nonItem >> pInTags "dt" inline) defs <- many1 (try $ skipMany nonItem >> pInTags "dd" block) skipMany nonItem let term = intercalate [LineBreak] terms return (term, map (fixPlains True) defs) fixPlains :: Bool -> [Block] -> [Block] fixPlains inList bs = if any isParaish bs then map plainToPara bs else bs where isParaish (Para _) = True isParaish (CodeBlock _ _) = True isParaish (Header _ _ _) = True isParaish (BlockQuote _) = True isParaish (BulletList _) = not inList isParaish (OrderedList _ _) = not inList isParaish (DefinitionList _) = not inList isParaish _ = False plainToPara (Plain xs) = Para xs plainToPara x = x pRawTag :: TagParser String pRawTag = do tag <- pAnyTag let ignorable x = x `elem` ["html","head","body"] if tagOpen ignorable (const True) tag || tagClose ignorable tag 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 parseRaw <- getOption readerParseRaw if parseRaw && not (null raw) then return [RawBlock (Format "html") raw] else return [] pHtmlBlock :: String -> TagParser String pHtmlBlock t = try $ do open <- pSatisfy (~== TagOpen t []) contents <- manyTill pAnyTag (pSatisfy (~== TagClose t)) return $ renderTags' $ [open] ++ contents ++ [TagClose t] pHeader :: TagParser [Block] pHeader = try $ do TagOpen tagtype attr <- pSatisfy $ tagOpen (`elem` ["h1","h2","h3","h4","h5","h6"]) (const True) 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 classes = maybe [] words $ lookup "class" attr let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"] return $ if bodyTitle then [] -- skip a representation of the title in the body else [Header level (ident, classes, keyvals) $ normalizeSpaces contents] pHrule :: TagParser [Block] pHrule = do pSelfClosing (=="hr") (const True) return [HorizontalRule] pTable :: TagParser [Block] pTable = try $ do TagOpen _ _ <- pSatisfy (~== TagOpen "table" []) skipMany pBlank caption <- option [] $ pInTags "caption" inline >>~ skipMany pBlank -- TODO actually read these and take width information from them widths' <- pColgroup <|> many pCol head' <- option [] $ pOptInTag "thead" $ pInTags "tr" (pCell "th") skipMany pBlank rows <- pOptInTag "tbody" $ many1 $ try $ skipMany pBlank >> pInTags "tr" (pCell "td") skipMany pBlank TagClose _ <- pSatisfy (~== TagClose "table") let isSinglePlain [] = True isSinglePlain [Plain _] = True isSinglePlain _ = False let isSimple = all isSinglePlain $ concat (head':rows) let cols = length $ if null head' then head rows else head' -- fail if there are colspans or rowspans guard $ all (\r -> length r == cols) rows let aligns = replicate cols AlignLeft let widths = if null widths' then if isSimple then replicate cols 0 else replicate cols (1.0 / fromIntegral cols) else widths' return [Table caption aligns widths head' rows] pCol :: TagParser Double pCol = try $ do TagOpen _ attribs <- pSatisfy (~== TagOpen "col" []) optional $ pSatisfy (~== TagClose "col") skipMany pBlank return $ case lookup "width" attribs of Just x | not (null x) && last x == '%' -> maybe 0.0 id $ safeRead ('0':'.':init x) _ -> 0.0 pColgroup :: TagParser [Double] pColgroup = try $ do pSatisfy (~== TagOpen "colgroup" []) skipMany pBlank manyTill pCol (pCloses "colgroup" <|> eof) <* skipMany pBlank pCell :: String -> TagParser [TableCell] pCell celltype = try $ do skipMany pBlank res <- pInTags celltype block skipMany pBlank return [res] pBlockQuote :: TagParser [Block] pBlockQuote = do contents <- pInTags "blockquote" block return [BlockQuote $ fixPlains False contents] pPlain :: TagParser [Block] pPlain = do contents <- liftM (normalizeSpaces . concat) $ many1 inline if null contents then return [] else return [Plain contents] pPara :: TagParser [Block] pPara = do contents <- pInTags "p" inline return [Para $ normalizeSpaces contents] pCodeBlock :: TagParser [Block] pCodeBlock = try $ do TagOpen _ attr <- pSatisfy (~== TagOpen "pre" []) contents <- manyTill pAnyTag (pCloses "pre" <|> eof) let rawText = concatMap fromTagText $ filter isTagText contents -- drop leading newline if any let result' = case rawText of '\n':xs -> xs _ -> rawText -- drop trailing newline if any let result = case reverse result' of '\n':_ -> init result' _ -> result' return [CodeBlock (mkAttr attr) result] inline :: TagParser [Inline] inline = choice [ pTagText , pQ , pEmph , pStrong , pSuperscript , pSubscript , pStrikeout , pLineBreak , pLink , pImage , pCode , pSpan , pRawHtmlInline ] pLocation :: TagParser () pLocation = do (TagPosition r c) <- pSat isTagPosition setPosition $ newPos "input" r c pSat :: (Tag String -> Bool) -> TagParser (Tag String) pSat f = do pos <- getPosition token show (const pos) (\x -> if f x then Just x else Nothing) pSatisfy :: (Tag String -> Bool) -> TagParser (Tag String) pSatisfy f = try $ optional pLocation >> pSat f pAnyTag :: TagParser (Tag String) pAnyTag = pSatisfy (const True) pSelfClosing :: (String -> Bool) -> ([Attribute String] -> Bool) -> TagParser (Tag String) pSelfClosing f g = do open <- pSatisfy (tagOpen f g) optional $ pSatisfy (tagClose f) return open pQ :: TagParser [Inline] pQ = do quoteContext <- stateQuoteContext `fmap` getState let quoteType = case quoteContext of InDoubleQuote -> SingleQuote _ -> DoubleQuote let innerQuoteContext = if quoteType == SingleQuote then InSingleQuote else InDoubleQuote withQuoteContext innerQuoteContext $ pInlinesInTags "q" (Quoted quoteType) pEmph :: TagParser [Inline] pEmph = pInlinesInTags "em" Emph <|> pInlinesInTags "i" Emph pStrong :: TagParser [Inline] pStrong = pInlinesInTags "strong" Strong <|> pInlinesInTags "b" Strong pSuperscript :: TagParser [Inline] pSuperscript = pInlinesInTags "sup" Superscript pSubscript :: TagParser [Inline] pSubscript = pInlinesInTags "sub" Subscript pStrikeout :: TagParser [Inline] pStrikeout = do pInlinesInTags "s" Strikeout <|> pInlinesInTags "strike" Strikeout <|> pInlinesInTags "del" Strikeout <|> try (do pSatisfy (~== TagOpen "span" [("class","strikeout")]) contents <- liftM concat $ manyTill inline (pCloses "span") return [Strikeout contents]) pLineBreak :: TagParser [Inline] pLineBreak = do pSelfClosing (=="br") (const True) return [LineBreak] pLink :: TagParser [Inline] pLink = try $ do tag <- pSatisfy (tagOpenLit "a" (isJust . lookup "href")) let url = fromAttrib "href" tag let title = fromAttrib "title" tag lab <- liftM concat $ manyTill inline (pCloses "a") return [Link (normalizeSpaces lab) (escapeURI url, title)] pImage :: TagParser [Inline] pImage = do tag <- pSelfClosing (=="img") (isJust . lookup "src") let url = fromAttrib "src" tag let title = fromAttrib "title" tag let alt = fromAttrib "alt" tag return [Image (B.toList $ B.text alt) (escapeURI url, title)] pCode :: TagParser [Inline] pCode = try $ do (TagOpen open attr) <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True) result <- manyTill pAnyTag (pCloses open) 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 result <- pSatisfy (tagComment (const True)) <|> pSatisfy isInlineTag parseRaw <- getOption readerParseRaw if parseRaw then return [RawInline (Format "html") $ renderTags' [result]] else return [] pInlinesInTags :: String -> ([Inline] -> Inline) -> TagParser [Inline] pInlinesInTags tagtype f = do contents <- pInTags tagtype inline return [f $ normalizeSpaces contents] pInTags :: String -> TagParser [a] -> TagParser [a] pInTags tagtype parser = try $ do pSatisfy (~== TagOpen tagtype []) liftM concat $ manyTill parser (pCloses tagtype <|> eof) pOptInTag :: String -> TagParser a -> TagParser a pOptInTag tagtype parser = try $ do open <- option False (pSatisfy (~== TagOpen tagtype []) >> return True) skipMany pBlank x <- parser skipMany pBlank when open $ pCloses tagtype return x pCloses :: String -> TagParser () pCloses tagtype = try $ do t <- lookAhead $ pSatisfy $ \tag -> isTagClose tag || isTagOpen tag case t of (TagClose t') | t' == tagtype -> pAnyTag >> return () (TagOpen t' _) | t' `closes` tagtype -> return () (TagClose "ul") | tagtype == "li" -> return () (TagClose "ol") | tagtype == "li" -> return () (TagClose "dl") | tagtype == "li" -> return () _ -> mzero pTagText :: TagParser [Inline] pTagText = try $ do (TagText str) <- pSatisfy isTagText st <- getState case runParser (many pTagContents) st "text" str of Left _ -> fail $ "Could not parse `" ++ str ++ "'" Right result -> return result pBlank :: TagParser () pBlank = try $ do (TagText str) <- pSatisfy isTagText guard $ all isSpace str pTagContents :: Parser [Char] ParserState Inline pTagContents = Math InlineMath `fmap` mathInline <|> Math DisplayMath `fmap` mathDisplay <|> pStr <|> pSpace <|> smartPunctuation pTagContents <|> pSymbol <|> pBad pStr :: Parser [Char] ParserState Inline pStr = do result <- many1 $ satisfy $ \c -> not (isSpace c) && not (isSpecial c) && not (isBad c) pos <- getPosition updateState $ \s -> s{ stateLastStrPos = Just pos } return $ Str result isSpecial :: Char -> Bool isSpecial '"' = True isSpecial '\'' = True isSpecial '.' = True isSpecial '-' = True isSpecial '$' = True isSpecial '\8216' = True isSpecial '\8217' = True isSpecial '\8220' = True isSpecial '\8221' = True isSpecial _ = False pSymbol :: Parser [Char] ParserState Inline pSymbol = satisfy isSpecial >>= return . Str . (:[]) isBad :: Char -> Bool isBad c = c >= '\128' && c <= '\159' -- not allowed in HTML pBad :: Parser [Char] ParserState Inline pBad = do c <- satisfy isBad let c' = case c of '\128' -> '\8364' '\130' -> '\8218' '\131' -> '\402' '\132' -> '\8222' '\133' -> '\8230' '\134' -> '\8224' '\135' -> '\8225' '\136' -> '\710' '\137' -> '\8240' '\138' -> '\352' '\139' -> '\8249' '\140' -> '\338' '\142' -> '\381' '\145' -> '\8216' '\146' -> '\8217' '\147' -> '\8220' '\148' -> '\8221' '\149' -> '\8226' '\150' -> '\8211' '\151' -> '\8212' '\152' -> '\732' '\153' -> '\8482' '\154' -> '\353' '\155' -> '\8250' '\156' -> '\339' '\158' -> '\382' '\159' -> '\376' _ -> '?' return $ Str [c'] pSpace :: Parser [Char] ParserState Inline pSpace = many1 (satisfy isSpace) >> return Space -- -- Constants -- eitherBlockOrInline :: [String] eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins", "map", "area", "object"] {- inlineHtmlTags :: [[Char]] inlineHtmlTags = ["a", "abbr", "acronym", "b", "basefont", "bdo", "big", "br", "cite", "code", "dfn", "em", "font", "i", "img", "input", "kbd", "label", "q", "s", "samp", "select", "small", "span", "strike", "strong", "sub", "sup", "textarea", "tt", "u", "var"] -} blockHtmlTags :: [String] blockHtmlTags = ["address", "article", "aside", "blockquote", "body", "button", "canvas", "caption", "center", "col", "colgroup", "dd", "dir", "div", "dl", "dt", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "isindex", "map", "menu", "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", "svg", "video"] -- We want to allow raw docbook in markdown documents, so we -- include docbook block tags here too. blockDocBookTags :: [String] blockDocBookTags = ["calloutlist", "bibliolist", "glosslist", "itemizedlist", "orderedlist", "segmentedlist", "simplelist", "variablelist", "caution", "important", "note", "tip", "warning", "address", "literallayout", "programlisting", "programlistingco", "screen", "screenco", "screenshot", "synopsis", "example", "informalexample", "figure", "informalfigure", "table", "informaltable", "para", "simpara", "formalpara", "equation", "informalequation", "figure", "screenshot", "mediaobject", "qandaset", "procedure", "task", "cmdsynopsis", "funcsynopsis", "classsynopsis", "blockquote", "epigraph", "msgset", "sidebar", "title"] blockTags :: [String] blockTags = blockHtmlTags ++ blockDocBookTags isInlineTag :: Tag String -> Bool isInlineTag t = tagOpen (`notElem` blockTags) (const True) t || tagClose (`notElem` blockTags) t || tagComment (const True) t isBlockTag :: Tag String -> Bool isBlockTag t = tagOpen (`elem` blocktags) (const True) t || tagClose (`elem` blocktags) t || tagComment (const True) t where blocktags = blockTags ++ eitherBlockOrInline isTextTag :: Tag String -> Bool isTextTag = tagText (const True) isCommentTag :: Tag String -> Bool isCommentTag = tagComment (const True) -- taken from HXT and extended closes :: String -> String -> Bool _ `closes` "body" = False _ `closes` "html" = False "a" `closes` "a" = True "li" `closes` "li" = True "th" `closes` t | t `elem` ["th","td"] = True "tr" `closes` t | t `elem` ["th","td","tr"] = True "dt" `closes` t | t `elem` ["dt","dd"] = True "hr" `closes` "p" = True "p" `closes` "p" = True "meta" `closes` "meta" = True "colgroup" `closes` "colgroup" = True "form" `closes` "form" = True "label" `closes` "label" = True "map" `closes` "map" = True "object" `closes` "object" = True _ `closes` t | t `elem` ["option","style","script","textarea","title"] = True t `closes` "select" | t /= "option" = True "thead" `closes` t | t `elem` ["colgroup"] = True "tfoot" `closes` t | t `elem` ["thead","colgroup"] = True "tbody" `closes` t | t `elem` ["tbody","tfoot","thead","colgroup"] = True t `closes` t2 | t `elem` ["h1","h2","h3","h4","h5","h6","dl","ol","ul","table","div","p"] && t2 `elem` ["h1","h2","h3","h4","h5","h6","p" ] = True -- not "div" t1 `closes` t2 | t1 `elem` blockTags && t2 `notElem` (blockTags ++ eitherBlockOrInline) = True _ `closes` _ = False --- parsers for use in markdown, textile readers -- | Matches a stretch of HTML in balanced tags. htmlInBalanced :: (Tag String -> Bool) -> Parser [Char] ParserState String htmlInBalanced f = try $ do (TagOpen t _, tag) <- htmlTag f guard $ '/' `notElem` tag -- not a self-closing tag let stopper = htmlTag (~== TagClose t) let anytag = liftM snd $ htmlTag (const True) contents <- many $ notFollowedBy' stopper >> (htmlInBalanced f <|> anytag <|> count 1 anyChar) endtag <- liftM snd stopper return $ tag ++ concat contents ++ endtag -- | Matches a tag meeting a certain condition. htmlTag :: (Tag String -> Bool) -> Parser [Char] st (Tag String, String) htmlTag f = try $ do lookAhead $ char '<' >> (oneOf "/!?" <|> letter) (next : _) <- getInput >>= return . canonicalizeTags . parseTags guard $ f next -- advance the parser case next of TagComment s -> do count (length s + 4) anyChar skipMany (satisfy (/='>')) char '>' return (next, "<!--" ++ s ++ "-->") _ -> 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/LaTeX.hs����������������������������������������������������000644 �000765 �000024 �00000116000 12251233602 020727� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} {- Copyright (C) 2006-2012 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.LaTeX Copyright : Copyright (C) 2006-2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of LaTeX to 'Pandoc' document. -} module Text.Pandoc.Readers.LaTeX ( readLaTeX, rawLaTeXInline, rawLaTeXBlock, handleIncludes ) where import Text.Pandoc.Definition import Text.Pandoc.Walk import Text.Pandoc.Shared import Text.Pandoc.Options 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, isAlphaNum) import Control.Applicative import Data.Monoid import Data.Maybe (fromMaybe) import System.Environment (getEnv) import System.FilePath (replaceExtension, (</>)) import Data.List (intercalate, intersperse) import qualified Data.Map as M import qualified Control.Exception as E import System.FilePath (takeExtension, addExtension) import Text.Pandoc.Highlighting (fromListingsLanguage) -- | Parse LaTeX from string and return 'Pandoc' document. readLaTeX :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assumes @'\n'@ line endings) -> Pandoc readLaTeX opts = readWith parseLaTeX def{ stateOptions = opts } parseLaTeX :: LP Pandoc parseLaTeX = do bs <- blocks eof st <- getState let meta = stateMeta st let (Pandoc _ bs') = doc bs return $ Pandoc meta bs' type LP = Parser [Char] ParserState anyControlSeq :: LP String anyControlSeq = do char '\\' next <- option '\n' anyChar name <- case next of '\n' -> return "" c | isLetter c -> (c:) <$> (many letter <* optional sp) | otherwise -> return [c] return name controlSeq :: String -> LP String controlSeq name = try $ do char '\\' case name of "" -> mzero [c] | not (isLetter c) -> string [c] cs -> string cs <* notFollowedBy letter <* optional sp return name dimenarg :: LP String dimenarg = try $ do ch <- option "" $ string "=" num <- many1 digit dim <- oneOfStrings ["pt","pc","in","bp","cm","mm","dd","cc","sp"] return $ ch ++ num ++ dim sp :: LP () sp = skipMany1 $ satisfy (\c -> c == ' ' || c == '\t') <|> (try $ newline >>~ lookAhead anyChar >>~ notFollowedBy blankline) isLowerHex :: Char -> Bool isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f' tildeEscape :: LP Char tildeEscape = try $ do string "^^" c <- satisfy (\x -> x >= '\0' && x <= '\128') d <- if isLowerHex c then option "" $ count 1 (satisfy isLowerHex) else return "" if null d then case ord c of x | x >= 64 && x <= 127 -> return $ chr (x - 64) | otherwise -> return $ chr (x + 64) else return $ chr $ read ('0':'x':c:d) comment :: LP () comment = do char '%' skipMany (satisfy (/='\n')) newline return () bgroup :: LP () bgroup = () <$ char '{' <|> () <$ controlSeq "bgroup" <|> () <$ controlSeq "begingroup" egroup :: LP () egroup = () <$ char '}' <|> () <$ controlSeq "egroup" <|> () <$ controlSeq "endgroup" grouped :: Monoid a => LP a -> LP a grouped parser = try $ bgroup *> (mconcat <$> manyTill parser egroup) braced :: LP String braced = bgroup *> (concat <$> manyTill ( many1 (satisfy (\c -> c /= '\\' && c /= '}' && c /= '{')) <|> try (string "\\}") <|> try (string "\\{") <|> try (string "\\\\") <|> ((\x -> "{" ++ x ++ "}") <$> braced) <|> count 1 anyChar ) egroup) bracketed :: Monoid a => LP a -> LP a bracketed parser = try $ char '[' *> (mconcat <$> manyTill parser (char ']')) mathDisplay :: LP String -> LP Inlines mathDisplay p = displayMath <$> (try p >>= applyMacros' . trim) mathInline :: LP String -> LP Inlines mathInline p = math <$> (try p >>= applyMacros') mathChars :: LP String mathChars = concat <$> many ( many1 (satisfy (\c -> c /= '$' && c /='\\')) <|> (\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 = ( quoted' doubleQuoted (try $ string "``") (void $ try $ string "''") <|> quoted' doubleQuoted (string "“") (void $ char '”') <|> quoted' doubleQuoted (string "\"") (void $ char '"') ) single_quote :: LP Inlines 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 <|> inlineGroup <|> (char '-' *> option (str "-") ((char '-') *> option (str "–") (str "—" <$ char '-'))) <|> double_quote <|> single_quote <|> (str "”" <$ try (string "''")) <|> (str "”" <$ char '”') <|> (str "’" <$ char '\'') <|> (str "’" <$ char '’') <|> (str "\160" <$ char '~') <|> (mathDisplay $ string "$$" *> mathChars <* string "$$") <|> (mathInline $ char '$' *> mathChars <* char '$') <|> (superscript <$> (char '^' *> tok)) <|> (subscript <$> (char '_' *> tok)) <|> (guardEnabled Ext_literate_haskell *> char '|' *> doLHSverb) <|> (str . (:[]) <$> tildeEscape) <|> (str . (:[]) <$> oneOf "[]") <|> (str . (:[]) <$> oneOf "#&") -- TODO print warning? -- <|> (str <$> count 1 (satisfy (\c -> c /= '\\' && c /='\n' && c /='}' && c /='{'))) -- eat random leftover characters 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)) <|> environment <|> macro <|> blockCommand <|> paragraph <|> grouped block <|> (mempty <$ char '&') -- loose & in table environment blocks :: LP Blocks blocks = mconcat <$> many block blockCommand :: LP Blocks blockCommand = try $ do name <- anyControlSeq guard $ name /= "begin" && name /= "end" star <- option "" (string "*" <* optional sp) let name' = name ++ star case M.lookup name' blockCommands of Just p -> p Nothing -> case M.lookup name blockCommands of Just p -> p Nothing -> mzero inBrackets :: Inlines -> Inlines inBrackets x = (str "[") <> x <> (str "]") -- eat an optional argument and one or more arguments in braces ignoreInlines :: String -> (String, LP Inlines) ignoreInlines name = (name, doraw <|> (mempty <$ optargs)) where optargs = skipopts *> skipMany (try $ optional sp *> braced) contseq = '\\':name doraw = (rawInline "latex" . (contseq ++) . snd) <$> (getOption readerParseRaw >>= guard >> (withRaw optargs)) ignoreBlocks :: String -> (String, LP Blocks) ignoreBlocks name = (name, doraw <|> (mempty <$ optargs)) where optargs = skipopts *> skipMany (try $ optional sp *> braced) contseq = '\\':name doraw = (rawBlock "latex" . (contseq ++) . snd) <$> (getOption readerParseRaw >>= guard >> (withRaw optargs)) blockCommands :: M.Map String (LP Blocks) blockCommands = M.fromList $ [ ("par", mempty <$ skipopts) , ("title", mempty <$ (skipopts *> tok >>= addMeta "title")) , ("subtitle", mempty <$ (skipopts *> tok >>= addMeta "subtitle")) , ("author", mempty <$ (skipopts *> authors)) -- -- in letter class, temp. store address & sig as title, author , ("address", mempty <$ (skipopts *> tok >>= addMeta "address")) , ("signature", mempty <$ (skipopts *> authors)) , ("date", mempty <$ (skipopts *> tok >>= addMeta "date")) -- sectioning , ("chapter", updateState (\s -> s{ stateHasChapters = True }) *> section nullAttr 0) , ("chapter*", updateState (\s -> s{ stateHasChapters = True }) *> section ("",["unnumbered"],[]) 0) , ("section", section nullAttr 1) , ("section*", section ("",["unnumbered"],[]) 1) , ("subsection", section nullAttr 2) , ("subsection*", section ("",["unnumbered"],[]) 2) , ("subsubsection", section nullAttr 3) , ("subsubsection*", section ("",["unnumbered"],[]) 3) , ("paragraph", section nullAttr 4) , ("paragraph*", section ("",["unnumbered"],[]) 4) , ("subparagraph", section nullAttr 5) , ("subparagraph*", section ("",["unnumbered"],[]) 5) -- beamer slides , ("frametitle", section nullAttr 3) , ("framesubtitle", section nullAttr 4) -- letters , ("opening", (para . trimInlines) <$> (skipopts *> tok)) , ("closing", skipopts *> closing) -- , ("hrule", pure horizontalRule) , ("rule", skipopts *> tok *> tok *> pure horizontalRule) , ("item", skipopts *> loose_item) , ("documentclass", skipopts *> braced *> preamble) , ("centerline", (para . trimInlines) <$> (skipopts *> tok)) ] ++ map ignoreBlocks -- these commands will be ignored unless --parse-raw is specified, -- in which case they will appear as raw latex blocks [ "newcommand", "renewcommand", "newenvironment", "renewenvironment" -- newcommand, etc. should be parsed by macro, but we need this -- here so these aren't parsed as inline commands to ignore , "special", "pdfannot", "pdfstringdef" , "bibliography", "bibliographystyle" , "maketitle", "makeindex", "makeglossary" , "addcontentsline", "addtocontents", "addtocounter" -- \ignore{} is used conventionally in literate haskell for definitions -- that are to be processed by the compiler but not printed. , "ignore" , "hyperdef" , "markboth", "markright", "markleft" , "hspace", "vspace" ] addMeta :: ToMetaValue a => String -> a -> LP () addMeta field val = updateState $ setMeta field val authors :: LP () authors = try $ do char '{' let oneAuthor = mconcat <$> many1 (notFollowedBy' (controlSeq "and") >> (inline <|> mempty <$ blockCommand)) -- skip e.g. \vspace{10pt} auths <- sepBy oneAuthor (controlSeq "and") char '}' addMeta "authors" (map trimInlines auths) section :: Attr -> Int -> LP Blocks section (ident, classes, kvs) lvl = do hasChapters <- stateHasChapters `fmap` getState let lvl' = if hasChapters then lvl + 1 else lvl skipopts contents <- grouped inline lab <- option ident $ try (spaces >> controlSeq "label" >> spaces >> braced) attr' <- registerHeader (lab, classes, kvs) contents return $ headerWith attr' lvl' contents inlineCommand :: LP Inlines inlineCommand = try $ do name <- anyControlSeq guard $ name /= "begin" && name /= "end" guard $ not $ isBlockCommand name parseRaw <- getOption readerParseRaw star <- option "" (string "*") let name' = name ++ star let raw = do rawargs <- withRaw (skipopts *> option "" dimenarg *> many braced) let rawcommand = '\\' : name ++ star ++ snd rawargs transformed <- applyMacros' rawcommand if transformed /= rawcommand then parseFromString inlines transformed else if parseRaw then return $ rawInline "latex" rawcommand else return mempty case M.lookup name' inlineCommands of Just p -> p <|> raw Nothing -> case M.lookup name inlineCommands of Just p -> p <|> raw Nothing -> raw unlessParseRaw :: LP () unlessParseRaw = getOption readerParseRaw >>= guard . not isBlockCommand :: String -> Bool isBlockCommand s = maybe False (const True) $ M.lookup s blockCommands inlineCommands :: M.Map String (LP Inlines) inlineCommands = M.fromList $ [ ("emph", emph <$> tok) , ("textit", emph <$> tok) , ("textsl", emph <$> tok) , ("textsc", smallcaps <$> tok) , ("sout", strikeout <$> tok) , ("textsuperscript", superscript <$> tok) , ("textsubscript", subscript <$> tok) , ("textbackslash", lit "\\") , ("backslash", lit "\\") , ("slash", lit "/") , ("textbf", strong <$> tok) , ("textnormal", spanWith ("",["nodecor"],[]) <$> tok) , ("ldots", lit "…") , ("dots", lit "…") , ("mdots", lit "…") , ("sim", lit "~") , ("label", unlessParseRaw >> (inBrackets <$> tok)) , ("ref", unlessParseRaw >> (inBrackets <$> tok)) , ("(", mathInline $ manyTill anyChar (try $ string "\\)")) , ("[", mathDisplay $ manyTill anyChar (try $ string "\\]")) , ("ensuremath", mathInline $ braced) , ("P", lit "¶") , ("S", lit "§") , ("$", lit "$") , ("%", lit "%") , ("&", lit "&") , ("#", lit "#") , ("_", lit "_") , ("{", lit "{") , ("}", lit "}") -- old TeX commands , ("em", emph <$> inlines) , ("it", emph <$> inlines) , ("sl", emph <$> inlines) , ("bf", strong <$> inlines) , ("rm", inlines) , ("itshape", emph <$> inlines) , ("slshape", emph <$> inlines) , ("scshape", smallcaps <$> inlines) , ("bfseries", strong <$> inlines) , ("/", pure mempty) -- italic correction , ("aa", lit "å") , ("AA", lit "Å") , ("ss", lit "ß") , ("o", lit "ø") , ("O", lit "Ø") , ("L", lit "Ł") , ("l", lit "ł") , ("ae", lit "æ") , ("AE", lit "Æ") , ("oe", lit "œ") , ("OE", lit "Œ") , ("pounds", lit "£") , ("euro", lit "€") , ("copyright", lit "©") , ("textasciicircum", lit "^") , ("textasciitilde", lit "~") , ("`", option (str "`") $ try $ tok >>= accent grave) , ("'", option (str "'") $ try $ tok >>= accent acute) , ("^", option (str "^") $ try $ tok >>= accent circ) , ("~", option (str "~") $ try $ tok >>= accent tilde) , ("\"", option (str "\"") $ try $ tok >>= accent umlaut) , (".", option (str ".") $ try $ tok >>= accent dot) , ("=", option (str "=") $ try $ tok >>= accent macron) , ("c", option (str "c") $ try $ tok >>= accent cedilla) , ("v", option (str "v") $ try $ tok >>= accent hacek) , ("u", option (str "u") $ try $ tok >>= accent breve) , ("i", lit "i") , ("\\", linebreak <$ (optional (bracketed inline) *> optional sp)) , (",", pure mempty) , ("@", pure mempty) , (" ", lit "\160") , ("ps", pure $ str "PS." <> space) , ("TeX", lit "TeX") , ("LaTeX", lit "LaTeX") , ("bar", lit "|") , ("textless", lit "<") , ("textgreater", lit ">") , ("thanks", (note . mconcat) <$> (char '{' *> manyTill block (char '}'))) , ("footnote", (note . mconcat) <$> (char '{' *> manyTill block (char '}'))) , ("verb", doverb) , ("lstinline", doverb) , ("texttt", (code . stringify . toList) <$> tok) , ("url", (unescapeURL <$> braced) >>= \url -> pure (link url "" (str url))) , ("href", (unescapeURL <$> braced <* optional sp) >>= \url -> tok >>= \lab -> pure (link url "" lab)) , ("includegraphics", skipopts *> (unescapeURL <$> braced) >>= mkImage) , ("enquote", enquote) , ("cite", citation "cite" AuthorInText False) , ("citep", citation "citep" NormalCitation False) , ("citep*", citation "citep*" NormalCitation False) , ("citeal", citation "citeal" NormalCitation False) , ("citealp", citation "citealp" NormalCitation False) , ("citealp*", citation "citealp*" NormalCitation False) , ("autocite", citation "autocite" NormalCitation False) , ("footcite", inNote <$> citation "footcite" NormalCitation False) , ("parencite", citation "parencite" NormalCitation False) , ("supercite", citation "supercite" NormalCitation False) , ("footcitetext", inNote <$> citation "footcitetext" NormalCitation False) , ("citeyearpar", citation "citeyearpar" SuppressAuthor False) , ("citeyear", citation "citeyear" SuppressAuthor False) , ("autocite*", citation "autocite*" SuppressAuthor False) , ("cite*", citation "cite*" SuppressAuthor False) , ("parencite*", citation "parencite*" SuppressAuthor False) , ("textcite", citation "textcite" AuthorInText False) , ("citet", citation "citet" AuthorInText False) , ("citet*", citation "citet*" AuthorInText False) , ("citealt", citation "citealt" AuthorInText False) , ("citealt*", citation "citealt*" AuthorInText False) , ("textcites", citation "textcites" AuthorInText True) , ("cites", citation "cites" NormalCitation True) , ("autocites", citation "autocites" NormalCitation True) , ("footcites", inNote <$> citation "footcites" NormalCitation True) , ("parencites", citation "parencites" NormalCitation True) , ("supercites", citation "supercites" NormalCitation True) , ("footcitetexts", inNote <$> citation "footcitetexts" NormalCitation True) , ("Autocite", citation "Autocite" NormalCitation False) , ("Footcite", citation "Footcite" NormalCitation False) , ("Parencite", citation "Parencite" NormalCitation False) , ("Supercite", citation "Supercite" NormalCitation False) , ("Footcitetext", inNote <$> citation "Footcitetext" NormalCitation False) , ("Citeyearpar", citation "Citeyearpar" SuppressAuthor False) , ("Citeyear", citation "Citeyear" SuppressAuthor False) , ("Autocite*", citation "Autocite*" SuppressAuthor False) , ("Cite*", citation "Cite*" SuppressAuthor False) , ("Parencite*", citation "Parencite*" SuppressAuthor False) , ("Textcite", citation "Textcite" AuthorInText False) , ("Textcites", citation "Textcites" AuthorInText True) , ("Cites", citation "Cites" NormalCitation True) , ("Autocites", citation "Autocites" NormalCitation True) , ("Footcites", citation "Footcites" NormalCitation True) , ("Parencites", citation "Parencites" NormalCitation True) , ("Supercites", citation "Supercites" NormalCitation True) , ("Footcitetexts", inNote <$> citation "Footcitetexts" NormalCitation True) , ("citetext", complexNatbibCitation NormalCitation) , ("citeauthor", (try (tok *> optional sp *> controlSeq "citetext") *> complexNatbibCitation AuthorInText) <|> citation "citeauthor" AuthorInText False) ] ++ map ignoreInlines -- these commands will be ignored unless --parse-raw is specified, -- in which case they will appear as raw latex blocks: [ "noindent", "index", "nocite" ] mkImage :: String -> LP Inlines mkImage src = do -- try for a caption (alt, tit) <- option (str "image", "") $ try $ do spaces controlSeq "caption" optional (char '*') ils <- grouped inline return (ils, "fig:") case takeExtension src of "" -> do defaultExt <- getOption readerDefaultImageExtension return $ image (addExtension src defaultExt) tit alt _ -> return $ image src tit alt inNote :: Inlines -> Inlines inNote ils = note $ para $ ils <> str "." unescapeURL :: String -> String unescapeURL ('\\':x:xs) | isEscapable x = x:unescapeURL xs where isEscapable c = c `elem` "#$%&~_^\\{}" unescapeURL (x:xs) = x:unescapeURL xs unescapeURL [] = "" enquote :: LP Inlines enquote = do skipopts context <- stateQuoteContext <$> getState if context == InDoubleQuote then singleQuoted <$> withQuoteContext InSingleQuote tok else doubleQuoted <$> withQuoteContext InDoubleQuote tok doverb :: LP Inlines doverb = do marker <- anyChar code <$> manyTill (satisfy (/='\n')) (char marker) doLHSverb :: LP Inlines doLHSverb = codeWith ("",["haskell"],[]) <$> manyTill (satisfy (/='\n')) (char '|') lit :: String -> LP Inlines lit = pure . str accent :: (Char -> String) -> Inlines -> LP Inlines accent f ils = case toList ils of (Str (x:xs) : ys) -> return $ fromList $ (Str (f x ++ xs) : ys) [] -> mzero _ -> return ils grave :: Char -> String grave 'A' = "À" grave 'E' = "È" grave 'I' = "Ì" grave 'O' = "Ò" grave 'U' = "Ù" grave 'a' = "à" grave 'e' = "è" grave 'i' = "ì" grave 'o' = "ò" grave 'u' = "ù" grave c = [c] acute :: Char -> String acute 'A' = "Á" acute 'E' = "É" acute 'I' = "Í" acute 'O' = "Ó" acute 'U' = "Ú" acute 'Y' = "Ý" acute 'a' = "á" acute 'e' = "é" acute 'i' = "í" acute 'o' = "ó" acute 'u' = "ú" acute 'y' = "ý" acute 'C' = "Ć" acute 'c' = "ć" acute 'L' = "Ĺ" acute 'l' = "ĺ" acute 'N' = "Ń" acute 'n' = "ń" acute 'R' = "Ŕ" acute 'r' = "ŕ" acute 'S' = "Ś" acute 's' = "ś" acute 'Z' = "Ź" acute 'z' = "ź" acute c = [c] circ :: Char -> String circ 'A' = "Â" circ 'E' = "Ê" circ 'I' = "Î" circ 'O' = "Ô" circ 'U' = "Û" circ 'a' = "â" circ 'e' = "ê" circ 'i' = "î" circ 'o' = "ô" circ 'u' = "û" circ 'C' = "Ĉ" circ 'c' = "ĉ" circ 'G' = "Ĝ" circ 'g' = "ĝ" circ 'H' = "Ĥ" circ 'h' = "ĥ" circ 'J' = "Ĵ" circ 'j' = "ĵ" circ 'S' = "Ŝ" circ 's' = "ŝ" circ 'W' = "Ŵ" circ 'w' = "ŵ" circ 'Y' = "Ŷ" circ 'y' = "ŷ" circ c = [c] tilde :: Char -> String tilde 'A' = "Ã" tilde 'a' = "ã" tilde 'O' = "Õ" tilde 'o' = "õ" tilde 'I' = "Ĩ" tilde 'i' = "ĩ" tilde 'U' = "Ũ" tilde 'u' = "ũ" tilde 'N' = "Ñ" tilde 'n' = "ñ" tilde c = [c] umlaut :: Char -> String umlaut 'A' = "Ä" umlaut 'E' = "Ë" umlaut 'I' = "Ï" umlaut 'O' = "Ö" umlaut 'U' = "Ü" umlaut 'a' = "ä" umlaut 'e' = "ë" umlaut 'i' = "ï" umlaut 'o' = "ö" umlaut 'u' = "ü" umlaut c = [c] dot :: Char -> String dot 'C' = "Ċ" dot 'c' = "ċ" dot 'E' = "Ė" dot 'e' = "ė" dot 'G' = "Ġ" dot 'g' = "ġ" dot 'I' = "İ" dot 'Z' = "Ż" dot 'z' = "ż" dot c = [c] macron :: Char -> String macron 'A' = "Ā" macron 'E' = "Ē" macron 'I' = "Ī" macron 'O' = "Ō" macron 'U' = "Ū" macron 'a' = "ā" macron 'e' = "ē" macron 'i' = "ī" macron 'o' = "ō" macron 'u' = "ū" macron c = [c] cedilla :: Char -> String cedilla 'c' = "ç" cedilla 'C' = "Ç" cedilla 's' = "ş" cedilla 'S' = "Ş" cedilla 't' = "ţ" cedilla 'T' = "Ţ" cedilla 'e' = "ȩ" cedilla 'E' = "Ȩ" cedilla 'h' = "ḩ" cedilla 'H' = "Ḩ" cedilla 'o' = "o̧" cedilla 'O' = "O̧" cedilla c = [c] hacek :: Char -> String hacek 'A' = "Ǎ" hacek 'a' = "ǎ" hacek 'C' = "Č" hacek 'c' = "č" hacek 'D' = "Ď" hacek 'd' = "ď" hacek 'E' = "Ě" hacek 'e' = "ě" hacek 'G' = "Ǧ" hacek 'g' = "ǧ" hacek 'H' = "Ȟ" hacek 'h' = "ȟ" hacek 'I' = "Ǐ" hacek 'i' = "ǐ" hacek 'j' = "ǰ" hacek 'K' = "Ǩ" hacek 'k' = "ǩ" hacek 'L' = "Ľ" hacek 'l' = "ľ" hacek 'N' = "Ň" hacek 'n' = "ň" hacek 'O' = "Ǒ" hacek 'o' = "ǒ" hacek 'R' = "Ř" hacek 'r' = "ř" hacek 'S' = "Š" hacek 's' = "š" hacek 'T' = "Ť" hacek 't' = "ť" hacek 'U' = "Ǔ" hacek 'u' = "ǔ" hacek 'Z' = "Ž" hacek 'z' = "ž" hacek c = [c] breve :: Char -> String breve 'A' = "Ă" breve 'a' = "ă" breve 'E' = "Ĕ" breve 'e' = "ĕ" breve 'G' = "Ğ" breve 'g' = "ğ" breve 'I' = "Ĭ" breve 'i' = "ĭ" breve 'O' = "Ŏ" breve 'o' = "ŏ" breve 'U' = "Ŭ" breve 'u' = "ŭ" breve c = [c] tok :: LP Inlines tok = try $ grouped inline <|> inlineCommand <|> str <$> (count 1 $ inlineChar) opt :: LP Inlines opt = bracketed inline <* optional sp skipopts :: LP () skipopts = skipMany opt inlineText :: LP Inlines inlineText = str <$> many1 inlineChar inlineChar :: LP Char inlineChar = noneOf "\\$%^_&~#{}^'`\"‘’“”-[] \t\n" environment :: LP Blocks environment = do controlSeq "begin" name <- braced case M.lookup name environments of Just p -> p <|> rawEnv name Nothing -> rawEnv name rawEnv :: String -> LP Blocks rawEnv name = do let addBegin x = "\\begin{" ++ name ++ "}" ++ x parseRaw <- getOption readerParseRaw if parseRaw then (rawBlock "latex" . addBegin) <$> (withRaw (env name blocks) >>= applyMacros' . snd) else env name blocks -- | Replace "include" commands with file contents. handleIncludes :: String -> IO String handleIncludes = handleIncludes' [] -- parents parameter prevents infinite include loops handleIncludes' :: [FilePath] -> String -> IO String handleIncludes' _ [] = return [] handleIncludes' parents ('\\':'%':xs) = ("\\%"++) `fmap` handleIncludes' parents xs handleIncludes' parents ('%':xs) = handleIncludes' parents $ drop 1 $ dropWhile (/='\n') xs handleIncludes' parents ('\\':xs) = case runParser include defaultParserState "input" ('\\':xs) of Right (fs, rest) -> do yss <- mapM (\f -> if f `elem` parents then "" <$ warn ("Include file loop in '" ++ f ++ "'.") else readTeXFile f >>= handleIncludes' (f:parents)) fs rest' <- handleIncludes' parents rest return $ intercalate "\n" yss ++ rest' _ -> case runParser (verbCmd <|> verbatimEnv) defaultParserState "input" ('\\':xs) of Right (r, rest) -> (r ++) `fmap` handleIncludes' parents rest _ -> ('\\':) `fmap` handleIncludes' parents xs handleIncludes' parents (x:xs) = (x:) `fmap` handleIncludes' parents xs readTeXFile :: FilePath -> IO String readTeXFile f = do texinputs <- E.catch (getEnv "TEXINPUTS") $ \(_ :: E.SomeException) -> return "." let ds = splitBy (==':') texinputs readFileFromDirs ds f readFileFromDirs :: [FilePath] -> FilePath -> IO String readFileFromDirs [] _ = return "" readFileFromDirs (d:ds) f = E.catch (UTF8.readFile $ d </> f) $ \(_ :: E.SomeException) -> readFileFromDirs ds f include :: LP ([FilePath], String) include = do name <- controlSeq "include" <|> controlSeq "input" <|> controlSeq "usepackage" skipopts fs <- (splitBy (==',')) <$> braced rest <- getInput let fs' = if name == "usepackage" then map (flip replaceExtension ".sty") fs else map (flip replaceExtension ".tex") fs return (fs', rest) verbCmd :: LP (String, String) verbCmd = do (_,r) <- withRaw $ do controlSeq "verb" c <- anyChar manyTill anyChar (char c) rest <- getInput return (r, rest) keyval :: LP (String, String) keyval = try $ do key <- many1 alphaNum val <- option "" $ char '=' >> many1 alphaNum skipMany spaceChar optional (char ',') skipMany spaceChar return (key, val) keyvals :: LP [(String, String)] keyvals = try $ char '[' *> manyTill keyval (char ']') alltt :: String -> LP Blocks alltt t = walk strToCode <$> parseFromString blocks (substitute " " "\\ " $ substitute "%" "\\%" $ concat $ intersperse "\\\\\n" $ lines t) where strToCode (Str s) = Code nullAttr s strToCode x = x verbatimEnv :: LP (String, String) verbatimEnv = do (_,r) <- withRaw $ do controlSeq "begin" name <- braced guard $ name == "verbatim" || name == "Verbatim" || name == "lstlisting" || name == "minted" || name == "alltt" verbEnv name rest <- getInput return (r,rest) rawLaTeXBlock :: Parser [Char] ParserState String rawLaTeXBlock = snd <$> try (withRaw (environment <|> blockCommand)) rawLaTeXInline :: Parser [Char] ParserState Inline rawLaTeXInline = do raw <- (snd <$> withRaw inlineCommand) <|> (snd <$> withRaw blockCommand) RawInline "latex" <$> applyMacros' raw environments :: M.Map String (LP Blocks) environments = M.fromList [ ("document", env "document" blocks <* skipMany anyChar) , ("letter", env "letter" letter_contents) , ("figure", env "figure" $ skipopts *> blocks) , ("center", env "center" blocks) , ("tabular", env "tabular" simpTable) , ("quote", blockQuote <$> env "quote" blocks) , ("quotation", blockQuote <$> env "quotation" blocks) , ("verse", blockQuote <$> env "verse" blocks) , ("itemize", bulletList <$> listenv "itemize" (many item)) , ("description", definitionList <$> listenv "description" (many descItem)) , ("enumerate", ordered_list) , ("alltt", alltt =<< verbEnv "alltt") , ("code", guardEnabled Ext_literate_haskell *> (codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$> verbEnv "code")) , ("verbatim", codeBlock <$> (verbEnv "verbatim")) , ("Verbatim", do options <- option [] keyvals let kvs = [ (if k == "firstnumber" then "startFrom" else k, v) | (k,v) <- options ] let classes = [ "numberLines" | lookup "numbers" options == Just "left" ] let attr = ("",classes,kvs) codeBlockWith attr <$> (verbEnv "Verbatim")) , ("lstlisting", do options <- option [] keyvals let kvs = [ (if k == "firstnumber" then "startFrom" else k, v) | (k,v) <- options ] let classes = [ "numberLines" | lookup "numbers" options == Just "left" ] ++ maybe [] (:[]) (lookup "language" options >>= fromListingsLanguage) let attr = (fromMaybe "" (lookup "label" options),classes,kvs) codeBlockWith attr <$> (verbEnv "lstlisting")) , ("minted", do options <- option [] keyvals lang <- grouped (many1 $ satisfy (/='}')) let kvs = [ (if k == "firstnumber" then "startFrom" else k, v) | (k,v) <- options ] let classes = [ lang | not (null lang) ] ++ [ "numberLines" | lookup "linenos" options == Just "true" ] let attr = ("",classes,kvs) codeBlockWith attr <$> (verbEnv "minted")) , ("obeylines", parseFromString (para . trimInlines . mconcat <$> many inline) =<< intercalate "\\\\\n" . lines <$> verbEnv "obeylines") , ("displaymath", mathEnv Nothing "displaymath") , ("equation", mathEnv Nothing "equation") , ("equation*", mathEnv Nothing "equation*") , ("gather", mathEnv (Just "gathered") "gather") , ("gather*", mathEnv (Just "gathered") "gather*") , ("multline", mathEnv (Just "gathered") "multline") , ("multline*", mathEnv (Just "gathered") "multline*") , ("eqnarray", mathEnv (Just "aligned") "eqnarray") , ("eqnarray*", mathEnv (Just "aligned") "eqnarray*") , ("align", mathEnv (Just "aligned") "align") , ("align*", mathEnv (Just "aligned") "align*") , ("alignat", mathEnv (Just "aligned") "alignat") , ("alignat*", mathEnv (Just "aligned") "alignat*") ] letter_contents :: LP Blocks letter_contents = do bs <- blocks st <- getState -- add signature (author) and address (title) let addr = case lookupMeta "address" (stateMeta st) of Just (MetaBlocks [Plain xs]) -> para $ trimInlines $ fromList xs _ -> mempty return $ addr <> bs -- sig added by \closing closing :: LP Blocks closing = do contents <- tok st <- getState let extractInlines (MetaBlocks [Plain ys]) = ys extractInlines (MetaBlocks [Para ys ]) = ys extractInlines _ = [] let sigs = case lookupMeta "author" (stateMeta st) of Just (MetaList xs) -> para $ trimInlines $ fromList $ intercalate [LineBreak] $ map extractInlines xs _ -> mempty return $ para (trimInlines contents) <> sigs item :: LP Blocks item = blocks *> controlSeq "item" *> skipopts *> blocks loose_item :: LP Blocks loose_item = do ctx <- stateParserContext `fmap` getState if ctx == ListItemState then mzero else return mempty descItem :: LP (Inlines, [Blocks]) descItem = do blocks -- skip blocks before item controlSeq "item" optional sp ils <- opt bs <- blocks return (ils, [bs]) env :: String -> LP a -> LP a env name p = p <* (try (controlSeq "end" *> braced >>= guard . (== name)) <?> ("\\end{" ++ name ++ "}")) listenv :: String -> LP a -> LP a listenv name p = try $ do oldCtx <- stateParserContext `fmap` getState updateState $ \st -> st{ stateParserContext = ListItemState } res <- env name p updateState $ \st -> st{ stateParserContext = oldCtx } return res mathEnv :: Maybe String -> String -> LP Blocks mathEnv innerEnv name = para <$> mathDisplay (inner <$> verbEnv name) where inner x = case innerEnv of Nothing -> x Just y -> "\\begin{" ++ y ++ "}\n" ++ x ++ "\\end{" ++ y ++ "}" verbEnv :: String -> LP String verbEnv name = do skipopts optional blankline let endEnv = try $ controlSeq "end" *> braced >>= guard . (== name) res <- manyTill anyChar endEnv return $ stripTrailingNewlines res ordered_list :: LP Blocks ordered_list = do optional sp (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) $ try $ char '[' *> anyOrderedListMarker <* char ']' spaces optional $ try $ controlSeq "setlength" *> grouped (controlSeq "itemindent") *> braced spaces start <- option 1 $ try $ do controlSeq "setcounter" grouped (string "enum" *> many1 (oneOf "iv")) optional sp num <- grouped (many1 digit) spaces return $ (read num + 1 :: Int) bs <- listenv "enumerate" (many item) return $ orderedListWith (start, style, delim) bs paragraph :: LP Blocks paragraph = do x <- trimInlines . mconcat <$> many1 inline if x == mempty then return mempty else return $ para x preamble :: LP Blocks preamble = mempty <$> manyTill preambleBlock beginDoc where beginDoc = lookAhead $ controlSeq "begin" *> string "{document}" preambleBlock = (void comment) <|> (void sp) <|> (void blanklines) <|> (void macro) <|> (void blockCommand) <|> (void anyControlSeq) <|> (void braced) <|> (void anyChar) ------- -- citations addPrefix :: [Inline] -> [Citation] -> [Citation] addPrefix p (k:ks) = k {citationPrefix = p ++ citationPrefix k} : ks addPrefix _ _ = [] addSuffix :: [Inline] -> [Citation] -> [Citation] addSuffix s ks@(_:_) = let k = last ks in init ks ++ [k {citationSuffix = citationSuffix k ++ s}] addSuffix _ _ = [] simpleCiteArgs :: LP [Citation] 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 ) (Just s , Just t ) -> (s , t ) _ -> (mempty, mempty) conv k = Citation { citationId = k , citationPrefix = [] , citationSuffix = [] , citationMode = NormalCitation , citationHash = 0 , citationNoteNum = 0 } return $ addPrefix pre $ addSuffix suf $ map conv keys citationLabel :: LP String 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 cs = concat cits return $ case mode of 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 (c,raw) <- withRaw $ cites mode multi return $ cite c (rawInline "latex" $ "\\" ++ name ++ raw) complexNatbibCitation :: CitationMode -> LP Inlines complexNatbibCitation mode = try $ do let ils = (toList . trimInlines . mconcat) <$> many (notFollowedBy (oneOf "\\};") >> inline) let parseOne = try $ do skipSpaces pref <- ils cit' <- inline -- expect a citation let citlist = toList cit' cits' <- case citlist of [Cite cs _] -> return cs _ -> mzero suff <- ils skipSpaces optional $ char ';' return $ addPrefix pref $ addSuffix suff $ cits' (c:cits, raw) <- withRaw $ grouped parseOne return $ cite (c{ citationMode = mode }:cits) (rawInline "latex" $ "\\citetext" ++ raw) -- tables parseAligns :: LP [Alignment] parseAligns = try $ do char '{' let maybeBar = try $ spaces >> optional (char '|') maybeBar let cAlign = AlignCenter <$ char 'c' let lAlign = AlignLeft <$ char 'l' let rAlign = AlignRight <$ char 'r' let alignChar = optional sp *> (cAlign <|> lAlign <|> rAlign) aligns' <- sepEndBy alignChar maybeBar spaces char '}' spaces return aligns' hline :: LP () hline = () <$ (try $ spaces >> controlSeq "hline") lbreak :: LP () lbreak = () <$ (try $ spaces *> controlSeq "\\") amp :: LP () amp = () <$ (try $ spaces *> char '&') parseTableRow :: Int -- ^ number of columns -> LP [Blocks] parseTableRow cols = try $ do let tableCellInline = notFollowedBy (amp <|> lbreak) >> inline let tableCell = (plain . trimInlines . mconcat) <$> many tableCellInline cells' <- sepBy tableCell amp guard $ length cells' == cols spaces return cells' simpTable :: LP Blocks simpTable = try $ do spaces aligns <- parseAligns let cols = length aligns optional hline header' <- option [] $ try (parseTableRow cols <* lbreak <* hline) rows <- sepEndBy (parseTableRow cols) (lbreak <* optional hline) spaces let header'' = if null header' then replicate cols mempty else header' lookAhead $ controlSeq "end" -- make sure we're at end return $ table mempty (zip aligns (repeat 0)) header'' rows pandoc-1.12.2.1/src/Text/Pandoc/Readers/Markdown.hs�������������������������������������������������000644 �000765 �000024 �00000205161 12251233602 021543� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7 {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.Markdown Copyright : Copyright (C) 2006-2013 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of markdown-formatted plain text to 'Pandoc' document. -} module Text.Pandoc.Readers.Markdown ( readMarkdown, readMarkdownWithWarnings ) where import Data.List ( transpose, sortBy, findIndex, intersperse, intercalate ) import qualified Data.Map as M import Data.Ord ( comparing ) import Data.Char ( isAlphaNum, toLower ) import Data.Maybe import Text.Pandoc.Definition import qualified Data.Text as T import Data.Text (Text) import qualified Data.Yaml as Yaml import Data.Yaml (ParseException(..), YamlException(..), YamlMark(..)) import qualified Data.HashMap.Strict as H import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.UTF8 as UTF8 import qualified Data.Vector as V import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>)) import Text.Pandoc.Options import Text.Pandoc.Shared import Text.Pandoc.XML (fromEntities) import Text.Pandoc.Parsing hiding (tableWith) import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock ) import Text.Pandoc.Readers.HTML ( htmlTag, htmlInBalanced, isInlineTag, isBlockTag, isTextTag, isCommentTag ) import Data.Monoid (mconcat, mempty) import Control.Applicative ((<$>), (<*), (*>), (<$)) import Control.Monad import System.FilePath (takeExtension, addExtension) import Text.HTML.TagSoup import Text.HTML.TagSoup.Match (tagOpen) import qualified Data.Set as Set type MarkdownParser = Parser [Char] ParserState -- | Read markdown from an input string and return a Pandoc document. readMarkdown :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assuming @'\n'@ line endings) -> Pandoc readMarkdown opts s = (readWith parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n") -- | Read markdown from an input string and return a pair of a Pandoc document -- and a list of warnings. readMarkdownWithWarnings :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assuming @'\n'@ line endings) -> (Pandoc, [String]) readMarkdownWithWarnings opts s = (readWith parseMarkdownWithWarnings) def{ stateOptions = opts } (s ++ "\n\n") where parseMarkdownWithWarnings = do doc <- parseMarkdown warnings <- stateWarnings <$> getState return (doc, warnings) trimInlinesF :: F Inlines -> F Inlines trimInlinesF = liftM trimInlines -- -- Constants and data structure definitions -- isBulletListMarker :: Char -> Bool isBulletListMarker '*' = True isBulletListMarker '+' = True isBulletListMarker '-' = True isBulletListMarker _ = False isHruleChar :: Char -> Bool isHruleChar '*' = True isHruleChar '-' = True isHruleChar '_' = True isHruleChar _ = False setextHChars :: String setextHChars = "=-" isBlank :: Char -> Bool isBlank ' ' = True isBlank '\t' = True isBlank '\n' = True isBlank _ = False -- -- auxiliary functions -- isNull :: F Inlines -> Bool isNull ils = B.isNull $ runF ils def spnl :: Parser [Char] st () spnl = try $ do skipSpaces optional newline skipSpaces notFollowedBy (char '\n') indentSpaces :: MarkdownParser String indentSpaces = try $ do tabStop <- getOption readerTabStop count tabStop (char ' ') <|> string "\t" <?> "indentation" nonindentSpaces :: MarkdownParser String nonindentSpaces = do tabStop <- getOption readerTabStop sps <- many (char ' ') if length sps < tabStop then return sps else unexpected "indented line" skipNonindentSpaces :: MarkdownParser () skipNonindentSpaces = do tabStop <- getOption readerTabStop atMostSpaces (tabStop - 1) atMostSpaces :: Int -> MarkdownParser () atMostSpaces 0 = notFollowedBy (char ' ') atMostSpaces n = (char ' ' >> atMostSpaces (n-1)) <|> return () litChar :: MarkdownParser Char litChar = escapedChar' <|> characterReference <|> noneOf "\n" <|> try (newline >> notFollowedBy blankline >> return ' ') -- | Parse a sequence of inline elements between square brackets, -- including inlines between balanced pairs of square brackets. inlinesInBalancedBrackets :: MarkdownParser (F Inlines) inlinesInBalancedBrackets = charsInBalancedBrackets >>= parseFromString (trimInlinesF . mconcat <$> many inline) charsInBalancedBrackets :: MarkdownParser [Char] charsInBalancedBrackets = do char '[' result <- manyTill ( many1 (noneOf "`[]\n") <|> (snd <$> withRaw code) <|> ((\xs -> '[' : xs ++ "]") <$> charsInBalancedBrackets) <|> count 1 (satisfy (/='\n')) <|> (newline >> notFollowedBy blankline >> return "\n") ) (char ']') return $ concat result -- -- document structure -- titleLine :: MarkdownParser (F Inlines) titleLine = try $ do char '%' skipSpaces res <- many $ (notFollowedBy newline >> inline) <|> try (endline >> whitespace) newline return $ trimInlinesF $ mconcat res authorsLine :: MarkdownParser (F [Inlines]) authorsLine = try $ do char '%' skipSpaces authors <- sepEndBy (many (notFollowedBy (satisfy $ \c -> c == ';' || c == '\n') >> inline)) (char ';' <|> try (newline >> notFollowedBy blankline >> spaceChar)) newline return $ sequence $ filter (not . isNull) $ map (trimInlinesF . mconcat) authors dateLine :: MarkdownParser (F Inlines) dateLine = try $ do char '%' skipSpaces trimInlinesF . mconcat <$> manyTill inline newline titleBlock :: MarkdownParser () titleBlock = pandocTitleBlock <|> mmdTitleBlock pandocTitleBlock :: MarkdownParser () pandocTitleBlock = try $ do guardEnabled Ext_pandoc_title_block lookAhead (char '%') title <- option mempty titleLine author <- option (return []) authorsLine date <- option mempty dateLine optional blanklines let meta' = do title' <- title 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 updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' } yamlMetaBlock :: MarkdownParser (F Blocks) yamlMetaBlock = try $ do guardEnabled Ext_yaml_metadata_block pos <- getPosition string "---" blankline notFollowedBy blankline -- if --- is followed by a blank it's an HRULE rawYamlLines <- manyTill anyLine stopLine -- by including --- and ..., we allow yaml blocks with just comments: let rawYaml = unlines ("---" : (rawYamlLines ++ ["..."])) optional blanklines opts <- stateOptions <$> getState meta' <- case Yaml.decodeEither' $ UTF8.fromString rawYaml of Right (Yaml.Object hashmap) -> return $ return $ H.foldrWithKey (\k v m -> if ignorable k then m else B.setMeta (T.unpack k) (yamlToMeta opts v) m) nullMeta hashmap Right Yaml.Null -> return $ return nullMeta Right _ -> do addWarning (Just pos) "YAML header is not an object" return $ return nullMeta Left err' -> do case err' of InvalidYaml (Just YamlParseException{ yamlProblem = problem , yamlContext = _ctxt , yamlProblemMark = Yaml.YamlMark { yamlLine = yline , yamlColumn = ycol }}) -> addWarning (Just $ setSourceLine (setSourceColumn pos (sourceColumn pos + ycol)) (sourceLine pos + 1 + yline)) $ "Could not parse YAML header: " ++ problem _ -> addWarning (Just pos) $ "Could not parse YAML header: " ++ show err' return $ return nullMeta updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' } return mempty -- ignore fields ending with _ ignorable :: Text -> Bool ignorable t = (T.pack "_") `T.isSuffixOf` t toMetaValue :: ReaderOptions -> Text -> MetaValue toMetaValue opts x = case readMarkdown opts (T.unpack x) of Pandoc _ [Plain xs] -> MetaInlines xs Pandoc _ [Para xs] | endsWithNewline x -> MetaBlocks [Para xs] | otherwise -> MetaInlines xs Pandoc _ bs -> MetaBlocks bs where endsWithNewline t = (T.pack "\n") `T.isSuffixOf` t yamlToMeta :: ReaderOptions -> Yaml.Value -> MetaValue yamlToMeta opts (Yaml.String t) = toMetaValue opts t yamlToMeta _ (Yaml.Number n) = MetaString $ show n yamlToMeta _ (Yaml.Bool b) = MetaBool b yamlToMeta opts (Yaml.Array xs) = B.toMetaValue $ map (yamlToMeta opts) $ V.toList xs yamlToMeta opts (Yaml.Object o) = MetaMap $ H.foldrWithKey (\k v m -> if ignorable k then m else M.insert (T.unpack k) (yamlToMeta opts v) m) M.empty o yamlToMeta _ _ = MetaString "" stopLine :: MarkdownParser () stopLine = try $ (string "---" <|> string "...") >> blankline >> return () mmdTitleBlock :: MarkdownParser () mmdTitleBlock = try $ do guardEnabled Ext_mmd_title_block kvPairs <- many1 kvPair blanklines updateState $ \st -> st{ stateMeta' = stateMeta' st <> return (Meta $ M.fromList kvPairs) } kvPair :: MarkdownParser (String, MetaValue) kvPair = try $ do key <- many1Till (alphaNum <|> oneOf "_- ") (char ':') val <- manyTill anyChar (try $ newline >> lookAhead (blankline <|> nonspaceChar)) let key' = concat $ words $ map toLower key let val' = MetaBlocks $ B.toList $ B.plain $ B.text $ trim val return (key',val') parseMarkdown :: MarkdownParser Pandoc parseMarkdown = do -- markdown allows raw HTML updateState $ \state -> state { stateOptions = let oldOpts = stateOptions state in oldOpts{ readerParseRaw = True } } optional titleBlock blocks <- parseBlocks st <- getState let meta = runF (stateMeta' st) st let Pandoc _ bs = B.doc $ runF blocks st return $ Pandoc meta bs addWarning :: Maybe SourcePos -> String -> MarkdownParser () addWarning mbpos msg = updateState $ \st -> st{ stateWarnings = (msg ++ maybe "" (\pos -> " " ++ show pos) mbpos) : stateWarnings st } referenceKey :: MarkdownParser (F Blocks) referenceKey = try $ do pos <- getPosition skipNonindentSpaces (_,raw) <- reference char ':' skipSpaces >> optional newline >> skipSpaces >> notFollowedBy (char '[') let sourceURL = liftM unwords $ many $ try $ do notFollowedBy' referenceTitle skipMany spaceChar optional $ newline >> notFollowedBy blankline skipMany spaceChar notFollowedBy' (() <$ reference) many1 $ notFollowedBy space >> litChar let betweenAngles = try $ char '<' >> manyTill (escapedChar' <|> litChar) (char '>') src <- try betweenAngles <|> sourceURL tit <- option "" referenceTitle -- currently we just ignore MMD-style link/image attributes _kvs <- option [] $ guardEnabled Ext_link_attributes >> many (spnl >> keyValAttr) blanklines let target = (escapeURI $ trimr src, tit) st <- getState let oldkeys = stateKeys st let key = toKey raw case M.lookup key oldkeys of Just _ -> addWarning (Just pos) $ "Duplicate link reference `" ++ raw ++ "'" Nothing -> return () updateState $ \s -> s { stateKeys = M.insert key target oldkeys } return $ return mempty referenceTitle :: MarkdownParser String referenceTitle = try $ do skipSpaces >> optional newline >> skipSpaces quotedTitle '"' <|> quotedTitle '\'' <|> charsInBalanced '(' ')' litChar -- A link title in quotes quotedTitle :: Char -> MarkdownParser String quotedTitle c = try $ do char c notFollowedBy spaces let pEnder = try $ char c >> notFollowedBy (satisfy isAlphaNum) let regChunk = many1 (noneOf ['\\','\n','&',c]) <|> count 1 litChar let nestedChunk = (\x -> [c] ++ x ++ [c]) <$> quotedTitle c unwords . words . concat <$> manyTill (nestedChunk <|> regChunk) pEnder -- | PHP Markdown Extra style abbreviation key. Currently -- we just skip them, since Pandoc doesn't have an element for -- an abbreviation. abbrevKey :: MarkdownParser (F Blocks) abbrevKey = do guardEnabled Ext_abbreviations try $ do char '*' reference char ':' skipMany (satisfy (/= '\n')) blanklines return $ return mempty noteMarker :: MarkdownParser String noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']') rawLine :: MarkdownParser String rawLine = try $ do notFollowedBy blankline notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker optional indentSpaces anyLine rawLines :: MarkdownParser String rawLines = do first <- anyLine rest <- many rawLine return $ unlines (first:rest) noteBlock :: MarkdownParser (F Blocks) noteBlock = try $ do pos <- getPosition skipNonindentSpaces ref <- noteMarker char ':' optional blankline optional indentSpaces first <- rawLines rest <- many $ try $ blanklines >> indentSpaces >> rawLines let raw = unlines (first:rest) ++ "\n" optional blanklines parsed <- parseFromString parseBlocks raw let newnote = (ref, parsed) oldnotes <- stateNotes' <$> getState case lookup ref oldnotes of Just _ -> addWarning (Just pos) $ "Duplicate note reference `" ++ ref ++ "'" Nothing -> return () updateState $ \s -> s { stateNotes' = newnote : oldnotes } return mempty -- -- parsing blocks -- parseBlocks :: MarkdownParser (F Blocks) parseBlocks = mconcat <$> manyTill block eof block :: MarkdownParser (F Blocks) 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 , divHtml , htmlBlock , table , lineBlock , codeBlockIndented , blockQuote , hrule , orderedList , definitionList , noteBlock , referenceKey , abbrevKey , para , plain ] <?> "block" -- -- header blocks -- header :: MarkdownParser (F Blocks) header = setextHeader <|> atxHeader <?> "header" atxHeader :: MarkdownParser (F Blocks) atxHeader = try $ do level <- many1 (char '#') >>= return . length notFollowedBy $ guardEnabled Ext_fancy_lists >> (char '.' <|> char ')') -- this would be a list skipSpaces text <- trimInlinesF . mconcat <$> many (notFollowedBy atxClosing >> inline) attr <- atxClosing attr' <- registerHeader attr (runF text defaultParserState) return $ B.headerWith attr' level <$> text atxClosing :: MarkdownParser Attr atxClosing = try $ do attr' <- option nullAttr (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier) skipMany (char '#') skipSpaces attr <- option attr' (guardEnabled Ext_header_attributes >> attributes) blanklines return attr setextHeaderEnd :: MarkdownParser Attr setextHeaderEnd = try $ do attr <- option nullAttr $ (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier) <|> (guardEnabled Ext_header_attributes >> attributes) blanklines return attr mmdHeaderIdentifier :: MarkdownParser Attr mmdHeaderIdentifier = do ident <- stripFirstAndLast . snd <$> reference skipSpaces return (ident,[],[]) setextHeader :: MarkdownParser (F Blocks) setextHeader = try $ do -- This lookahead prevents us from wasting time parsing Inlines -- unless necessary -- it gives a significant performance boost. lookAhead $ anyLine >> many1 (oneOf setextHChars) >> blankline text <- trimInlinesF . mconcat <$> many1 (notFollowedBy setextHeaderEnd >> inline) attr <- setextHeaderEnd underlineChar <- oneOf setextHChars many (char underlineChar) blanklines let level = (fromMaybe 0 $ findIndex (== underlineChar) setextHChars) + 1 attr' <- registerHeader attr (runF text defaultParserState) return $ B.headerWith attr' level <$> text -- -- hrule block -- hrule :: Parser [Char] st (F Blocks) hrule = try $ do skipSpaces start <- satisfy isHruleChar count 2 (skipSpaces >> char start) skipMany (spaceChar <|> char start) newline optional blanklines return $ return B.horizontalRule -- -- code blocks -- indentedLine :: MarkdownParser String indentedLine = indentSpaces >> anyLine >>= return . (++ "\n") blockDelimiter :: (Char -> Bool) -> Maybe Int -> Parser [Char] st Int blockDelimiter f len = try $ do c <- lookAhead (satisfy f) case len of Just l -> count l (char c) >> many (char c) >> return l Nothing -> count 3 (char c) >> many (char c) >>= return . (+ 3) . length attributes :: MarkdownParser Attr attributes = try $ do char '{' spnl attrs <- many (attribute >>~ spnl) char '}' return $ foldl (\x f -> f x) nullAttr attrs attribute :: MarkdownParser (Attr -> Attr) attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr identifier :: MarkdownParser String identifier = do first <- letter rest <- many $ alphaNum <|> oneOf "-_:." return (first:rest) identifierAttr :: MarkdownParser (Attr -> Attr) identifierAttr = try $ do char '#' result <- identifier return $ \(_,cs,kvs) -> (result,cs,kvs) classAttr :: MarkdownParser (Attr -> Attr) classAttr = try $ do char '.' result <- identifier return $ \(id',cs,kvs) -> (id',cs ++ [result],kvs) keyValAttr :: MarkdownParser (Attr -> Attr) keyValAttr = try $ do key <- identifier char '=' val <- enclosed (char '"') (char '"') litChar <|> enclosed (char '\'') (char '\'') litChar <|> many (escapedChar' <|> noneOf " \t\n\r}") return $ \(id',cs,kvs) -> (id',cs,kvs ++ [(key,val)]) specialAttr :: MarkdownParser (Attr -> Attr) specialAttr = do char '-' return $ \(id',cs,kvs) -> (id',cs ++ ["unnumbered"],kvs) codeBlockFenced :: MarkdownParser (F Blocks) codeBlockFenced = try $ do c <- try (guardEnabled Ext_fenced_code_blocks >> lookAhead (char '~')) <|> (guardEnabled Ext_backtick_code_blocks >> lookAhead (char '`')) size <- blockDelimiter (== c) Nothing skipMany spaceChar attr <- option ([],[],[]) $ try (guardEnabled Ext_fenced_code_attributes >> attributes) <|> ((\x -> ("",[x],[])) <$> identifier) blankline contents <- manyTill anyLine (blockDelimiter (== c) (Just size)) blanklines return $ return $ B.codeBlockWith attr $ intercalate "\n" contents codeBlockIndented :: MarkdownParser (F Blocks) codeBlockIndented = do contents <- many1 (indentedLine <|> try (do b <- blanklines l <- indentedLine return $ b ++ l)) optional blanklines classes <- getOption readerIndentedCodeClasses return $ return $ B.codeBlockWith ("", classes, []) $ stripTrailingNewlines $ concat contents lhsCodeBlock :: MarkdownParser (F Blocks) lhsCodeBlock = do guardEnabled Ext_literate_haskell (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$> (lhsCodeBlockBird <|> lhsCodeBlockLaTeX)) <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$> lhsCodeBlockInverseBird) lhsCodeBlockLaTeX :: MarkdownParser String lhsCodeBlockLaTeX = try $ do string "\\begin{code}" manyTill spaceChar newline contents <- many1Till anyChar (try $ string "\\end{code}") blanklines return $ stripTrailingNewlines contents lhsCodeBlockBird :: MarkdownParser String lhsCodeBlockBird = lhsCodeBlockBirdWith '>' lhsCodeBlockInverseBird :: MarkdownParser String lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<' lhsCodeBlockBirdWith :: Char -> MarkdownParser String lhsCodeBlockBirdWith c = try $ do pos <- getPosition when (sourceColumn pos /= 1) $ fail "Not in first column" lns <- many1 $ birdTrackLine c -- if (as is normal) there is always a space after >, drop it let lns' = if all (\ln -> null ln || take 1 ln == " ") lns then map (drop 1) lns else lns blanklines return $ intercalate "\n" lns' birdTrackLine :: Char -> Parser [Char] st String birdTrackLine c = try $ do char c -- allow html tags on left margin: when (c == '<') $ notFollowedBy letter anyLine -- -- block quotes -- emailBlockQuoteStart :: MarkdownParser Char emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' >>~ optional (char ' ') emailBlockQuote :: MarkdownParser [String] emailBlockQuote = try $ do emailBlockQuoteStart let emailLine = many $ nonEndline <|> try (endline >> notFollowedBy emailBlockQuoteStart >> return '\n') let emailSep = try (newline >> emailBlockQuoteStart) first <- emailLine rest <- many $ try $ emailSep >> emailLine let raw = first:rest newline <|> (eof >> return '\n') optional blanklines return raw blockQuote :: MarkdownParser (F Blocks) blockQuote = do raw <- emailBlockQuote -- parse the extracted block, which may contain various block elements: contents <- parseFromString parseBlocks $ (intercalate "\n" raw) ++ "\n\n" return $ B.blockQuote <$> contents -- -- list blocks -- bulletListStart :: MarkdownParser () bulletListStart = try $ do optional newline -- if preceded by a Plain block in a list context skipNonindentSpaces notFollowedBy' (() <$ hrule) -- because hrules start out just like lists satisfy isBulletListMarker spaceChar <|> lookAhead newline skipSpaces anyOrderedListStart :: MarkdownParser (Int, ListNumberStyle, ListNumberDelim) anyOrderedListStart = try $ do optional newline -- if preceded by a Plain block in a list context skipNonindentSpaces notFollowedBy $ string "p." >> spaceChar >> digit -- page number (guardDisabled Ext_fancy_lists >> do many1 digit char '.' spaceChar return (1, DefaultStyle, DefaultDelim)) <|> do (num, style, delim) <- anyOrderedListMarker -- if it could be an abbreviated first name, insist on more than one space if delim == Period && (style == UpperAlpha || (style == UpperRoman && num `elem` [1, 5, 10, 50, 100, 500, 1000])) then char '\t' <|> (try $ char ' ' >> spaceChar) else spaceChar skipSpaces return (num, style, delim) listStart :: MarkdownParser () 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' (do indentSpaces many (spaceChar) listStart) 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 rawListItem :: MarkdownParser a -> MarkdownParser String rawListItem start = try $ do start first <- listLine rest <- many (notFollowedBy listStart >> notFollowedBy blankline >> listLine) blanks <- many blankline return $ unlines (first:rest) ++ blanks -- continuation of a list item - indented and separated by blankline -- or (in compact lists) endline. -- note: nested lists are parsed as continuations listContinuation :: MarkdownParser String listContinuation = try $ do lookAhead indentSpaces result <- many1 listContinuationLine blanks <- many blankline return $ concat result ++ blanks listContinuationLine :: MarkdownParser String listContinuationLine = try $ do notFollowedBy blankline notFollowedBy' listStart notFollowedBy' $ htmlTag (~== TagClose "div") optional indentSpaces result <- anyLine return $ result ++ "\n" listItem :: MarkdownParser a -> MarkdownParser (F Blocks) listItem start = try $ do first <- rawListItem start continuations <- many listContinuation -- parsing with ListItemState forces markers at beginning of lines to -- count as list item markers, even if not separated by blank space. -- see definition of "endline" state <- getState let oldContext = stateParserContext state setState $ state {stateParserContext = ListItemState} -- parse the extracted block, which may contain various block elements: let raw = concat (first:continuations) contents <- parseFromString parseBlocks raw updateState (\st -> st {stateParserContext = oldContext}) return contents orderedList :: MarkdownParser (F Blocks) orderedList = try $ do (start, style, delim) <- lookAhead anyOrderedListStart unless ((style == DefaultStyle || style == Decimal || style == Example) && (delim == DefaultDelim || delim == Period)) $ guardEnabled Ext_fancy_lists when (style == Example) $ guardEnabled Ext_example_lists items <- fmap sequence $ many1 $ listItem ( try $ do optional newline -- if preceded by Plain block in a list skipNonindentSpaces orderedListMarker style delim ) start' <- option 1 $ guardEnabled Ext_startnum >> return start return $ B.orderedListWith (start', style, delim) <$> fmap compactify' items bulletList :: MarkdownParser (F Blocks) bulletList = do items <- fmap sequence $ many1 $ listItem bulletListStart return $ B.bulletList <$> fmap compactify' items -- definition lists defListMarker :: MarkdownParser () defListMarker = do sps <- nonindentSpaces char ':' <|> char '~' tabStop <- getOption readerTabStop let remaining = tabStop - (length sps + 1) if remaining > 0 then count remaining (char ' ') <|> string "\t" else mzero return () definitionListItem :: MarkdownParser (F (Inlines, [Blocks])) definitionListItem = try $ do -- first, see if this has any chance of being a definition list: lookAhead (anyLine >> optional blankline >> defListMarker) term <- trimInlinesF . mconcat <$> manyTill inline newline optional blankline raw <- many1 defRawBlock state <- getState let oldContext = stateParserContext state -- parse the extracted block, which may contain various block elements: contents <- mapM (parseFromString parseBlocks) raw updateState (\st -> st {stateParserContext = oldContext}) return $ liftM2 (,) term (sequence contents) defRawBlock :: MarkdownParser String defRawBlock = try $ do defListMarker firstline <- anyLine rawlines <- many (notFollowedBy blankline >> indentSpaces >> anyLine) trailing <- option "" blanklines cont <- liftM concat $ many $ do lns <- many1 $ notFollowedBy blankline >> indentSpaces >> anyLine trl <- option "" blanklines return $ unlines lns ++ trl return $ firstline ++ "\n" ++ unlines rawlines ++ trailing ++ cont definitionList :: MarkdownParser (F Blocks) definitionList = do guardEnabled Ext_definition_lists items <- fmap sequence $ many1 definitionListItem return $ B.definitionList <$> fmap compactify'DL items compactify'DL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])] compactify'DL items = let defs = concatMap snd items defBlocks = reverse $ concatMap B.toList defs isPara (Para _) = True isPara _ = False in case defBlocks of (Para x:_) -> if not $ any isPara (drop 1 defBlocks) then let (t,ds) = last items lastDef = B.toList $ last ds ds' = init ds ++ [B.fromList $ init lastDef ++ [Plain x]] in init items ++ [(t, ds')] else items _ -> items -- -- paragraph block -- para :: MarkdownParser (F Blocks) para = try $ do exts <- getOption readerExtensions result <- trimInlinesF . mconcat <$> many1 inline option (B.plain <$> result) $ try $ do newline (blanklines >> return mempty) <|> (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 [Image alt (src,tit)] | Ext_implicit_figures `Set.member` exts -> -- the fig: at beginning of title indicates a figure return $ B.para $ B.singleton $ Image alt (src,'f':'i':'g':':':tit) _ -> return $ B.para result' plain :: MarkdownParser (F Blocks) plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline -- -- raw html -- htmlElement :: MarkdownParser String htmlElement = strictHtmlBlock <|> liftM snd (htmlTag isBlockTag) htmlBlock :: MarkdownParser (F Blocks) htmlBlock = do guardEnabled Ext_raw_html res <- (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks) <|> htmlBlock' return $ return $ B.rawBlock "html" res htmlBlock' :: MarkdownParser String htmlBlock' = try $ do first <- htmlElement finalSpace <- many spaceChar finalNewlines <- many newline return $ first ++ finalSpace ++ finalNewlines strictHtmlBlock :: MarkdownParser String strictHtmlBlock = htmlInBalanced (not . isInlineTag) rawVerbatimBlock :: MarkdownParser String rawVerbatimBlock = try $ do (TagOpen tag _, open) <- htmlTag (tagOpen (\t -> t == "pre" || t == "style" || t == "script") (const True)) contents <- manyTill anyChar (htmlTag (~== TagClose tag)) return $ open ++ contents ++ renderTags [TagClose tag] rawTeXBlock :: MarkdownParser (F Blocks) rawTeXBlock = do guardEnabled Ext_raw_tex result <- (B.rawBlock "latex" <$> rawLaTeXBlock) <|> (B.rawBlock "context" <$> rawConTeXtEnvironment) spaces return $ return result rawHtmlBlocks :: MarkdownParser String rawHtmlBlocks = do htmlBlocks <- many1 $ try $ do s <- rawVerbatimBlock <|> try ( do (t,raw) <- htmlTag isBlockTag exts <- getOption readerExtensions -- if open tag, need markdown="1" if -- markdown_attributes extension is set case t of TagOpen _ as | Ext_markdown_attribute `Set.member` exts -> if "markdown" `notElem` map fst as then mzero else return $ stripMarkdownAttribute raw | otherwise -> return raw _ -> return raw ) sps <- do sp1 <- many spaceChar sp2 <- option "" (blankline >> return "\n") sp3 <- many spaceChar sp4 <- option "" blanklines return $ sp1 ++ sp2 ++ sp3 ++ sp4 -- note: we want raw html to be able to -- precede a code block, when separated -- by a blank line return $ s ++ sps let combined = concat htmlBlocks return $ if last combined == '\n' then init combined else combined -- remove markdown="1" attribute stripMarkdownAttribute :: String -> String stripMarkdownAttribute s = renderTags' $ map filterAttrib $ parseTags s where filterAttrib (TagOpen t as) = TagOpen t [(k,v) | (k,v) <- as, k /= "markdown"] filterAttrib x = x -- -- line block -- lineBlock :: MarkdownParser (F Blocks) lineBlock = try $ do guardEnabled Ext_line_blocks lines' <- lineBlockLines >>= mapM (parseFromString (trimInlinesF . mconcat <$> many inline)) return $ B.para <$> (mconcat $ intersperse (return B.linebreak) lines') -- -- Tables -- -- Parse a dashed line with optional trailing spaces; return its length -- and the length including trailing space. dashedLine :: Char -> Parser [Char] st (Int, Int) dashedLine ch = do dashes <- many1 (char ch) sp <- many spaceChar return $ (length dashes, length $ dashes ++ sp) -- Parse a table header with dashed lines of '-' preceded by -- one (or zero) line of text. simpleTableHeader :: Bool -- ^ Headerless table -> MarkdownParser (F [Blocks], [Alignment], [Int]) simpleTableHeader headless = try $ do rawContent <- if headless then return "" else anyLine initSp <- nonindentSpaces dashes <- many1 (dashedLine '-') newline let (lengths, lines') = unzip dashes let indices = scanl (+) (length initSp) lines' -- If no header, calculate alignment on basis of first row of text rawHeads <- liftM (tail . splitStringByIndices (init indices)) $ if headless then lookAhead anyLine else return rawContent let aligns = zipWith alignType (map (\a -> [a]) rawHeads) lengths let rawHeads' = if headless then replicate (length dashes) "" else rawHeads heads <- fmap sequence $ mapM (parseFromString (mconcat <$> many plain)) $ map trim rawHeads' return (heads, aligns, indices) -- Returns an alignment type for a table, based on a list of strings -- (the rows of the column header) and a number (the length of the -- dashed line under the rows. alignType :: [String] -> Int -> Alignment alignType [] _ = AlignDefault alignType strLst len = let nonempties = filter (not . null) $ map trimr strLst (leftSpace, rightSpace) = case sortBy (comparing length) nonempties of (x:_) -> (head x `elem` " \t", length x < len) [] -> (False, False) in case (leftSpace, rightSpace) of (True, False) -> AlignRight (False, True) -> AlignLeft (True, True) -> AlignCenter (False, False) -> AlignDefault -- Parse a table footer - dashed lines followed by blank line. tableFooter :: MarkdownParser String tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines -- Parse a table separator - dashed line. tableSep :: MarkdownParser Char tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n' -- Parse a raw line and split it into chunks by indices. rawTableLine :: [Int] -> MarkdownParser [String] rawTableLine indices = do notFollowedBy' (blanklines <|> tableFooter) line <- many1Till anyChar newline return $ map trim $ tail $ splitStringByIndices (init indices) line -- Parse a table line and return a list of lists of blocks (columns). tableLine :: [Int] -> MarkdownParser (F [Blocks]) tableLine indices = rawTableLine indices >>= fmap sequence . mapM (parseFromString (mconcat <$> many plain)) -- Parse a multiline table row and return a list of blocks (columns). multilineRow :: [Int] -> MarkdownParser (F [Blocks]) multilineRow indices = do colLines <- many1 (rawTableLine indices) let cols = map unlines $ transpose colLines fmap sequence $ mapM (parseFromString (mconcat <$> many plain)) cols -- Parses a table caption: inlines beginning with 'Table:' -- and followed by blank lines. tableCaption :: MarkdownParser (F Inlines) tableCaption = try $ do guardEnabled Ext_table_captions skipNonindentSpaces string ":" <|> string "Table:" trimInlinesF . mconcat <$> many1 inline <* blanklines -- Parse a simple table with '---' header and one line per row. simpleTable :: Bool -- ^ Headerless table -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]]) simpleTable headless = do (aligns, _widths, heads', lines') <- tableWith (simpleTableHeader headless) tableLine (return ()) (if headless then tableFooter else tableFooter <|> blanklines) -- Simple tables get 0s for relative column widths (i.e., use default) return (aligns, replicate (length aligns) 0, heads', lines') -- Parse a multiline table: starts with row of '-' on top, then header -- (which may be multiline), then the rows, -- which may be multiline, separated by blank lines, and -- ending with a footer (dashed line followed by blank line). multilineTable :: Bool -- ^ Headerless table -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]]) multilineTable headless = tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter multilineTableHeader :: Bool -- ^ Headerless table -> MarkdownParser (F [Blocks], [Alignment], [Int]) multilineTableHeader headless = try $ do if headless then return '\n' else tableSep >>~ notFollowedBy blankline rawContent <- if headless then return $ repeat "" else many1 (notFollowedBy tableSep >> many1Till anyChar newline) initSp <- nonindentSpaces dashes <- many1 (dashedLine '-') newline let (lengths, lines') = unzip dashes let indices = scanl (+) (length initSp) lines' rawHeadsList <- if headless then liftM (map (:[]) . tail . splitStringByIndices (init indices)) $ lookAhead anyLine else return $ transpose $ map (\ln -> tail $ splitStringByIndices (init indices) ln) rawContent let aligns = zipWith alignType rawHeadsList lengths let rawHeads = if headless then replicate (length dashes) "" else map unwords rawHeadsList heads <- fmap sequence $ mapM (parseFromString (mconcat <$> many plain)) $ map trim rawHeads return (heads, aligns, indices) -- Parse a grid table: starts with row of '-' on top, then header -- (which may be grid), then the rows, -- which may be grid, separated by blank lines, and -- ending with a footer (dashed line followed by blank line). gridTable :: Bool -- ^ Headerless table -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]]) gridTable headless = tableWith (gridTableHeader headless) gridTableRow (gridTableSep '-') gridTableFooter gridTableSplitLine :: [Int] -> String -> [String] gridTableSplitLine indices line = map removeFinalBar $ tail $ splitStringByIndices (init indices) $ trimr line gridPart :: Char -> Parser [Char] st (Int, Int) gridPart ch = do dashes <- many1 (char ch) char '+' return (length dashes, length dashes + 1) gridDashedLines :: Char -> Parser [Char] st [(Int,Int)] gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline removeFinalBar :: String -> String removeFinalBar = reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse -- | Separator between rows of grid table. gridTableSep :: Char -> MarkdownParser Char gridTableSep ch = try $ gridDashedLines ch >> return '\n' -- | Parse header for a grid table. gridTableHeader :: Bool -- ^ Headerless table -> MarkdownParser (F [Blocks], [Alignment], [Int]) gridTableHeader headless = try $ do optional blanklines dashes <- gridDashedLines '-' rawContent <- if headless then return $ repeat "" else many1 (notFollowedBy (gridTableSep '=') >> char '|' >> many1Till anyChar newline) if headless then return () else gridTableSep '=' >> return () let lines' = map snd dashes let indices = scanl (+) 0 lines' let aligns = replicate (length lines') AlignDefault -- RST does not have a notion of alignments let rawHeads = if headless then replicate (length dashes) "" else map unwords $ transpose $ map (gridTableSplitLine indices) rawContent heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads return (heads, aligns, indices) gridTableRawLine :: [Int] -> MarkdownParser [String] gridTableRawLine indices = do char '|' line <- many1Till anyChar newline return (gridTableSplitLine indices line) -- | Parse row of grid table. gridTableRow :: [Int] -> MarkdownParser (F [Blocks]) gridTableRow indices = do colLines <- many1 (gridTableRawLine indices) let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $ transpose colLines fmap compactify' <$> fmap sequence (mapM (parseFromString parseBlocks) cols) removeOneLeadingSpace :: [String] -> [String] removeOneLeadingSpace xs = if all startsWithSpace xs then map (drop 1) xs else xs where startsWithSpace "" = True startsWithSpace (y:_) = y == ' ' -- | Parse footer for a grid table. gridTableFooter :: MarkdownParser [Char] gridTableFooter = blanklines pipeTable :: MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]]) pipeTable = try $ do let pipeBreak = nonindentSpaces *> optional (char '|') *> pipeTableHeaderPart `sepBy1` sepPipe <* optional (char '|') <* blankline (heads,aligns) <- try ( pipeBreak >>= \als -> return (return $ replicate (length als) mempty, als)) <|> ( pipeTableRow >>= \row -> pipeBreak >>= \als -> return (row, als) ) lines' <- sequence <$> many1 pipeTableRow let widths = replicate (length aligns) 0.0 return $ (aligns, widths, heads, lines') sepPipe :: MarkdownParser () sepPipe = try $ do char '|' <|> char '+' notFollowedBy blankline -- parse a row, also returning probable alignments for org-table cells pipeTableRow :: MarkdownParser (F [Blocks]) pipeTableRow = do nonindentSpaces optional (char '|') let cell = mconcat <$> many (notFollowedBy (blankline <|> char '|') >> inline) first <- cell sepPipe rest <- cell `sepBy1` sepPipe optional (char '|') blankline let cells = sequence (first:rest) return $ do cells' <- cells return $ map (\ils -> case trimInlines ils of ils' | B.isNull ils' -> mempty | otherwise -> B.plain $ ils') cells' pipeTableHeaderPart :: Parser [Char] st Alignment pipeTableHeaderPart = try $ do skipMany spaceChar left <- optionMaybe (char ':') many1 (char '-') right <- optionMaybe (char ':') skipMany spaceChar return $ case (left,right) of (Nothing,Nothing) -> AlignDefault (Just _,Nothing) -> AlignLeft (Nothing,Just _) -> AlignRight (Just _,Just _) -> AlignCenter -- Succeed only if current line contains a pipe. scanForPipe :: Parser [Char] st () scanForPipe = do inp <- getInput case break (\c -> c == '\n' || c == '|') inp of (_,'|':_) -> return () _ -> mzero -- | Parse a table using 'headerParser', 'rowParser', -- 'lineParser', and 'footerParser'. Variant of the version in -- Text.Pandoc.Parsing. tableWith :: MarkdownParser (F [Blocks], [Alignment], [Int]) -> ([Int] -> MarkdownParser (F [Blocks])) -> MarkdownParser sep -> MarkdownParser end -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]]) tableWith headerParser rowParser lineParser footerParser = try $ do (heads, aligns, indices) <- headerParser lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser footerParser numColumns <- getOption readerColumns let widths = if (indices == []) then replicate (length aligns) 0.0 else widthsFromIndices numColumns indices return $ (aligns, widths, heads, lines') table :: MarkdownParser (F Blocks) table = try $ do frontCaption <- option Nothing (Just <$> tableCaption) (aligns, widths, heads, lns) <- try (guardEnabled Ext_pipe_tables >> scanForPipe >> pipeTable) <|> try (guardEnabled Ext_multiline_tables >> multilineTable False) <|> try (guardEnabled Ext_simple_tables >> (simpleTable True <|> simpleTable False)) <|> try (guardEnabled Ext_multiline_tables >> multilineTable True) <|> try (guardEnabled Ext_grid_tables >> (gridTable False <|> gridTable True)) <?> "table" optional blanklines caption <- case frontCaption of Nothing -> option (return mempty) tableCaption Just c -> return c return $ do caption' <- caption heads' <- heads lns' <- lns return $ B.table caption' (zip aligns widths) heads' lns' -- -- inline -- inline :: MarkdownParser (F Inlines) inline = choice [ whitespace , bareURL , str , endline , code , strongOrEmph , note , cite , link , image , math , strikeout , subscript , superscript , inlineNote -- after superscript because of ^[link](/foo)^ , autoLink , spanHtml , rawHtmlInline , escapedChar , rawLaTeXInline' , exampleRef , smart , return . B.singleton <$> charRef , symbol , ltSign ] <?> "inline" escapedChar' :: MarkdownParser Char escapedChar' = try $ do char '\\' (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum)) <|> oneOf "\\`*_{}[]()>#+-.!~\"" escapedChar :: MarkdownParser (F Inlines) escapedChar = do result <- escapedChar' case result of ' ' -> return $ return $ B.str "\160" -- "\ " is a nonbreaking space '\n' -> guardEnabled Ext_escaped_line_breaks >> return (return B.linebreak) -- "\[newline]" is a linebreak _ -> return $ return $ B.str [result] ltSign :: MarkdownParser (F Inlines) ltSign = do guardDisabled Ext_raw_html <|> guardDisabled Ext_markdown_in_html_blocks <|> (notFollowedBy' rawHtmlBlocks >> return ()) char '<' return $ return $ B.str "<" exampleRef :: MarkdownParser (F Inlines) exampleRef = try $ do guardEnabled Ext_example_lists char '@' lab <- many1 (alphaNum <|> oneOf "-_") return $ do st <- askF return $ case M.lookup lab (stateExamples st) of Just n -> B.str (show n) Nothing -> B.str ('@':lab) symbol :: MarkdownParser (F Inlines) symbol = do result <- noneOf "<\\\n\t " <|> try (do lookAhead $ char '\\' notFollowedBy' (() <$ rawTeXBlock) char '\\') return $ return $ B.str [result] -- parses inline code, between n `s and n `s code :: MarkdownParser (F Inlines) code = try $ do starts <- many1 (char '`') skipSpaces result <- many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|> (char '\n' >> notFollowedBy' blankline >> return " ")) (try (skipSpaces >> count (length starts) (char '`') >> notFollowedBy (char '`'))) attr <- option ([],[],[]) (try $ guardEnabled Ext_inline_code_attributes >> optional whitespace >> attributes) return $ return $ B.codeWith attr $ trim $ concat result math :: MarkdownParser (F Inlines) math = (return . B.displayMath <$> (mathDisplay >>= applyMacros')) <|> (return . B.math <$> (mathInline >>= applyMacros')) -- Parses material enclosed in *s, **s, _s, or __s. -- Designed to avoid backtracking. enclosure :: Char -> MarkdownParser (F Inlines) enclosure c = do cs <- many1 (char c) (return (B.str cs) <>) <$> whitespace <|> case length cs of 3 -> three c 2 -> two c mempty 1 -> one c mempty _ -> return (return $ B.str cs) -- 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) (try (string [c,c,c]) >> return ((B.strong . B.emph) <$> contents)) <|> (try (string [c,c]) >> one c (B.strong <$> contents)) <|> (char c >> two c (B.emph <$> contents)) <|> return (return (B.str [c,c,c]) <> contents) -- Parse inlines til you hit two c's, and emit strong. -- If you never do hit two cs, emit ** plus inlines parsed. two :: Char -> F Inlines -> MarkdownParser (F Inlines) two c prefix' = do let ender = try $ string [c,c] contents <- mconcat <$> many (try $ notFollowedBy ender >> inline) (ender >> return (B.strong <$> (prefix' <> contents))) <|> return (return (B.str [c,c]) <> (prefix' <> contents)) -- Parse inlines til you hit a c, and emit emph. -- If you never hit a c, emit * plus inlines parsed. one :: Char -> F Inlines -> MarkdownParser (F Inlines) one c prefix' = do contents <- mconcat <$> many ( (notFollowedBy (char c) >> inline) <|> try (string [c,c] >> notFollowedBy (char c) >> two c mempty) ) (char c >> return (B.emph <$> (prefix' <> contents))) <|> return (return (B.str [c]) <> (prefix' <> contents)) strongOrEmph :: MarkdownParser (F Inlines) strongOrEmph = enclosure '*' <|> (checkIntraword >> enclosure '_') where checkIntraword = do exts <- getOption readerExtensions when (Ext_intraword_underscores `Set.member` exts) $ do pos <- getPosition lastStrPos <- stateLastStrPos <$> getState guard $ lastStrPos /= Just pos -- | Parses a list of inlines between start and end delimiters. inlinesBetween :: (Show b) => MarkdownParser a -> MarkdownParser b -> MarkdownParser (F Inlines) inlinesBetween start end = (trimInlinesF . mconcat) <$> try (start >> many1Till inner end) where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline) innerSpace = try $ whitespace >>~ notFollowedBy' end strikeout :: MarkdownParser (F Inlines) strikeout = fmap B.strikeout <$> (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd) where strikeStart = string "~~" >> lookAhead nonspaceChar >> notFollowedBy (char '~') strikeEnd = try $ string "~~" superscript :: MarkdownParser (F Inlines) superscript = fmap B.superscript <$> try (do guardEnabled Ext_superscript char '^' mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^')) subscript :: MarkdownParser (F Inlines) subscript = fmap B.subscript <$> try (do guardEnabled Ext_subscript char '~' mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~')) whitespace :: MarkdownParser (F Inlines) whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace" where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak) regsp = skipMany spaceChar >> return B.space nonEndline :: Parser [Char] st Char nonEndline = satisfy (/='\n') str :: MarkdownParser (F Inlines) str = do result <- many1 alphaNum pos <- getPosition updateState $ \s -> s{ stateLastStrPos = Just pos } let spacesToNbr = map (\c -> if c == ' ' then '\160' else c) isSmart <- getOption readerSmart if isSmart then case likelyAbbrev result of [] -> return $ return $ B.str result xs -> choice (map (\x -> try (string x >> oneOf " \n" >> lookAhead alphaNum >> return (return $ B.str $ result ++ spacesToNbr x ++ "\160"))) xs) <|> (return $ return $ B.str result) else return $ return $ B.str result -- | if the string matches the beginning of an abbreviation (before -- the first period, return strings that would finish the abbreviation. likelyAbbrev :: String -> [String] likelyAbbrev x = let abbrevs = [ "Mr.", "Mrs.", "Ms.", "Capt.", "Dr.", "Prof.", "Gen.", "Gov.", "e.g.", "i.e.", "Sgt.", "St.", "vol.", "vs.", "Sen.", "Rep.", "Pres.", "Hon.", "Rev.", "Ph.D.", "M.D.", "M.A.", "p.", "pp.", "ch.", "sec.", "cf.", "cp."] abbrPairs = map (break (=='.')) abbrevs in map snd $ filter (\(y,_) -> y == x) abbrPairs -- an endline character that can be treated as a space, not a structural break 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 notFollowedBy' bulletListStart notFollowedBy' anyOrderedListStart (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak)) <|> (guardEnabled Ext_ignore_line_breaks >> return mempty) <|> (return $ return B.space) -- -- links -- -- a reference label for a link reference :: MarkdownParser (F Inlines, String) reference = do notFollowedBy' (string "[^") -- footnote reference withRaw $ trimInlinesF <$> inlinesInBalancedBrackets parenthesizedChars :: MarkdownParser [Char] parenthesizedChars = do result <- charsInBalanced '(' ')' litChar return $ '(' : result ++ ")" -- source for a link, with optional title source :: MarkdownParser (String, String) source = do char '(' skipSpaces let urlChunk = try $ notFollowedBy (oneOf "\"')") >> (parenthesizedChars <|> count 1 litChar) let sourceURL = (unwords . words . concat) <$> many urlChunk let betweenAngles = try $ char '<' >> manyTill litChar (char '>') src <- try betweenAngles <|> sourceURL tit <- option "" $ try $ spnl >> linkTitle skipSpaces char ')' return (escapeURI $ trimr src, tit) linkTitle :: MarkdownParser String linkTitle = quotedTitle '"' <|> quotedTitle '\'' link :: MarkdownParser (F Inlines) link = try $ do st <- getState guard $ stateAllowLinks st setState $ st{ stateAllowLinks = False } (lab,raw) <- reference setState $ st{ stateAllowLinks = True } regLink B.link lab <|> referenceLink B.link (lab,raw) regLink :: (String -> String -> Inlines -> Inlines) -> F Inlines -> MarkdownParser (F Inlines) regLink constructor lab = try $ do (src, tit) <- source return $ constructor src tit <$> lab -- a link like [this][ref] or [this][] or [this] referenceLink :: (String -> String -> Inlines -> Inlines) -> (F Inlines, String) -> MarkdownParser (F Inlines) referenceLink constructor (lab, raw) = do sp <- (True <$ lookAhead (char ' ')) <|> return False (ref,raw') <- try (skipSpaces >> optional (newline >> skipSpaces) >> reference) <|> return (mempty, "") let labIsRef = raw' == "" || raw' == "[]" let key = toKey $ if labIsRef then raw else raw' parsedRaw <- parseFromString (mconcat <$> many inline) raw' fallback <- parseFromString (mconcat <$> many inline) $ dropBrackets raw implicitHeaderRefs <- option False $ True <$ guardEnabled Ext_implicit_header_references let makeFallback = do parsedRaw' <- parsedRaw fallback' <- fallback return $ B.str "[" <> fallback' <> B.str "]" <> (if sp && not (null raw) then B.space else mempty) <> parsedRaw' return $ do keys <- asksF stateKeys case M.lookup key keys of Nothing -> do headers <- asksF stateHeaders ref' <- if labIsRef then lab else ref if implicitHeaderRefs then case M.lookup ref' headers of Just ident -> constructor ('#':ident) "" <$> lab Nothing -> makeFallback else makeFallback Just (src,tit) -> constructor src tit <$> lab dropBrackets :: String -> String dropBrackets = reverse . dropRB . reverse . dropLB where dropRB (']':xs) = xs dropRB xs = xs dropLB ('[':xs) = xs dropLB xs = xs bareURL :: MarkdownParser (F Inlines) bareURL = try $ do guardEnabled Ext_autolink_bare_uris (orig, src) <- uri <|> emailAddress notFollowedBy $ try $ spaces >> htmlTag (~== TagClose "a") return $ return $ B.link src "" (B.str orig) autoLink :: MarkdownParser (F Inlines) autoLink = try $ do char '<' (orig, src) <- uri <|> emailAddress -- in rare cases, something may remain after the uri parser -- is finished, because the uri parser tries to avoid parsing -- final punctuation. for example: in `<http://hi---there>`, -- the URI parser will stop before the dashes. extra <- fromEntities <$> manyTill nonspaceChar (char '>') return $ return $ B.link (src ++ escapeURI extra) "" (B.str $ orig ++ extra) image :: MarkdownParser (F Inlines) image = try $ do char '!' (lab,raw) <- reference defaultExt <- getOption readerDefaultImageExtension let constructor src = case takeExtension src of "" -> B.image (addExtension src defaultExt) _ -> B.image src regLink constructor lab <|> referenceLink constructor (lab,raw) note :: MarkdownParser (F Inlines) note = try $ do guardEnabled Ext_footnotes ref <- noteMarker return $ do notes <- asksF stateNotes' case lookup ref notes of Nothing -> return $ B.str $ "[^" ++ ref ++ "]" Just contents -> do st <- askF -- process the note in a context that doesn't resolve -- notes, to avoid infinite looping with notes inside -- notes: let contents' = runF contents st{ stateNotes' = [] } return $ B.note contents' inlineNote :: MarkdownParser (F Inlines) inlineNote = try $ do guardEnabled Ext_inline_notes char '^' contents <- inlinesInBalancedBrackets return $ B.note . B.para <$> contents rawLaTeXInline' :: MarkdownParser (F Inlines) rawLaTeXInline' = try $ do guardEnabled Ext_raw_tex lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env RawInline _ s <- rawLaTeXInline return $ return $ B.rawInline "tex" s -- "tex" because it might be context or latex rawConTeXtEnvironment :: Parser [Char] st String rawConTeXtEnvironment = try $ do string "\\start" completion <- inBrackets (letter <|> digit <|> spaceChar) <|> (many1 letter) contents <- manyTill (rawConTeXtEnvironment <|> (count 1 anyChar)) (try $ string "\\stop" >> string completion) return $ "\\start" ++ completion ++ concat contents ++ "\\stop" ++ completion inBrackets :: (Parser [Char] st Char) -> Parser [Char] st String inBrackets parser = do char '[' contents <- many parser char ']' return $ "[" ++ contents ++ "]" spanHtml :: MarkdownParser (F Inlines) 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 classes = maybe [] words $ lookup "class" attrs let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"] return $ B.spanWith (ident, classes, keyvals) <$> contents divHtml :: MarkdownParser (F Blocks) 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 classes = maybe [] words $ lookup "class" attrs let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"] return $ B.divWith (ident, classes, keyvals) <$> contents rawHtmlInline :: MarkdownParser (F Inlines) rawHtmlInline = do guardEnabled Ext_raw_html mdInHtml <- option False $ guardEnabled Ext_markdown_in_html_blocks >> return True (_,result) <- htmlTag $ if mdInHtml then isInlineTag else not . isTextTag return $ return $ B.rawInline "html" result -- Citations cite :: MarkdownParser (F Inlines) cite = do guardEnabled Ext_citations citations <- textualCite <|> do (cs, raw) <- withRaw normalCite return $ (flip B.cite (B.text raw)) <$> cs return citations textualCite :: MarkdownParser (F Inlines) textualCite = try $ do (_, key) <- citeKey let first = Citation{ citationId = key , citationPrefix = [] , citationSuffix = [] , citationMode = AuthorInText , citationNoteNum = 0 , citationHash = 0 } mbrest <- option Nothing $ try $ spnl >> Just <$> withRaw normalCite case mbrest of 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 spnl char '[' suff <- suffix rest <- option (return []) $ try $ char ';' >> citeList spnl char ']' return $ do suff' <- suff rest' <- rest return $ c{ citationSuffix = B.toList suff' } : rest' normalCite :: MarkdownParser (F [Citation]) normalCite = try $ do char '[' spnl citations <- citeList spnl char ']' return citations 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 ":.#$%&-_+?<>~/") let key = first:rest return (suppress_author, key) suffix :: MarkdownParser (F Inlines) suffix = try $ do hasSpace <- option False (notFollowedBy nonspaceChar >> return True) spnl rest <- trimInlinesF . mconcat <$> many (notFollowedBy (oneOf ";]") >> inline) return $ if hasSpace then (B.space <>) <$> rest else rest prefix :: MarkdownParser (F Inlines) prefix = trimInlinesF . mconcat <$> manyTill inline (char ']' <|> liftM (const ']') (lookAhead citeKey)) citeList :: MarkdownParser (F [Citation]) citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl) citation :: MarkdownParser (F Citation) citation = try $ do pref <- prefix (suppress_author, key) <- citeKey suff <- suffix return $ do x <- pref y <- suff return $ Citation{ citationId = key , citationPrefix = B.toList x , citationSuffix = B.toList y , citationMode = if suppress_author then SuppressAuthor else NormalCitation , citationNoteNum = 0 , citationHash = 0 } smart :: MarkdownParser (F Inlines) smart = do getOption readerSmart >>= guard doubleQuoted <|> singleQuoted <|> choice (map (return . B.singleton <$>) [apostrophe, dash, ellipses]) singleQuoted :: MarkdownParser (F Inlines) singleQuoted = try $ do singleQuoteStart withQuoteContext InSingleQuote $ fmap B.singleQuoted . trimInlinesF . mconcat <$> many1Till inline singleQuoteEnd -- doubleQuoted will handle regular double-quoted sections, as well -- as dialogues with an open double-quote without a close double-quote -- in the same paragraph. doubleQuoted :: MarkdownParser (F Inlines) doubleQuoted = try $ do doubleQuoteStart contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline) (withQuoteContext InDoubleQuote $ doubleQuoteEnd >> return (fmap B.doubleQuoted . trimInlinesF $ contents)) <|> (return $ return (B.str "\8220") <> contents) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/MediaWiki.hs������������������������������������������������000644 �000765 �000024 �00000053377 12251233602 021636� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE RelaxedPolyRec, FlexibleInstances, TypeSynonymInstances #-} -- RelaxedPolyRec needed for inlinesBetween on GHC < 7 {- Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.MediaWiki Copyright : Copyright (C) 2012 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of mediawiki text to 'Pandoc' document. -} {- TODO: _ correctly handle tables within tables _ parse templates? -} module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>)) import Text.Pandoc.Options 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, stringify, trim ) import Data.Monoid (mconcat, mempty) import Control.Applicative ((<$>), (<*), (*>), (<$)) import Control.Monad 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) -- | Read mediawiki from an input string and return a Pandoc document. readMediaWiki :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assuming @'\n'@ line endings) -> Pandoc readMediaWiki opts s = case runParser parseMediaWiki MWState{ mwOptions = opts , mwMaxNestingLevel = 4 , mwNextLinkNumber = 1 , mwCategoryLinks = [] , mwHeaderMap = M.empty , mwIdentifierList = [] } "source" (s ++ "\n") of Left err' -> error $ "\nError:\n" ++ show err' Right result -> result 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 -- -- This is used to prevent exponential blowups for things like: -- ''a'''a''a'''a''a'''a''a'''a nested :: MWParser a -> MWParser a nested p = do nestlevel <- mwMaxNestingLevel `fmap` getState guard $ nestlevel > 0 updateState $ \st -> st{ mwMaxNestingLevel = mwMaxNestingLevel st - 1 } res <- p updateState $ \st -> st{ mwMaxNestingLevel = nestlevel } return res specialChars :: [Char] specialChars = "'[]<=&*{}|\":\\" spaceChars :: [Char] spaceChars = " \n\t" sym :: String -> MWParser () sym s = () <$ try (string s) newBlockTags :: [String] newBlockTags = ["haskell","syntaxhighlight","source","gallery","references"] isBlockTag' :: Tag String -> Bool isBlockTag' tag@(TagOpen t _) = (isBlockTag tag || t `elem` newBlockTags) && t `notElem` eitherBlockOrInline isBlockTag' tag@(TagClose t) = (isBlockTag tag || t `elem` newBlockTags) && t `notElem` eitherBlockOrInline isBlockTag' tag = isBlockTag tag isInlineTag' :: Tag String -> Bool isInlineTag' (TagComment _) = True isInlineTag' t = not (isBlockTag' t) eitherBlockOrInline :: [String] eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins", "map", "area", "object"] htmlComment :: MWParser () htmlComment = () <$ htmlTag isCommentTag inlinesInTags :: String -> MWParser Inlines inlinesInTags tag = try $ do (_,raw) <- htmlTag (~== TagOpen tag []) if '/' `elem` raw -- self-closing tag then return mempty else trimInlines . mconcat <$> manyTill inline (htmlTag (~== TagClose tag)) blocksInTags :: String -> MWParser Blocks blocksInTags tag = try $ do (_,raw) <- htmlTag (~== TagOpen tag []) if '/' `elem` raw -- self-closing tag then return mempty else mconcat <$> manyTill block (htmlTag (~== TagClose tag)) charsInTags :: String -> MWParser [Char] charsInTags tag = try $ do (_,raw) <- htmlTag (~== TagOpen tag []) if '/' `elem` raw -- self-closing tag then return "" else manyTill anyChar (htmlTag (~== TagClose tag)) -- -- main parser -- parseMediaWiki :: MWParser Pandoc parseMediaWiki = do bs <- mconcat <$> many block spaces eof categoryLinks <- reverse . mwCategoryLinks <$> getState let categories = if null categoryLinks then mempty else B.para $ mconcat $ intersperse B.space categoryLinks return $ B.doc $ bs <> categories -- -- block parsers -- block :: MWParser Blocks block = mempty <$ skipMany1 blankline <|> table <|> header <|> hrule <|> orderedList <|> bulletList <|> definitionList <|> mempty <$ try (spaces *> htmlComment) <|> preformatted <|> blockTag <|> (B.rawBlock "mediawiki" <$> template) <|> para para :: MWParser Blocks para = do contents <- trimInlines . mconcat <$> many1 inline if F.all (==Space) contents then return mempty else return $ B.para contents table :: MWParser Blocks table = do tableStart styles <- option [] parseAttrs <* blankline let tableWidth = case lookup "width" styles of Just w -> maybe 1.0 id $ parseWidth w Nothing -> 1.0 caption <- option mempty tableCaption optional rowsep hasheader <- option False $ True <$ (lookAhead (char '!')) (cellspecs',hdr) <- unzip <$> tableRow let widths = map ((tableWidth *) . snd) cellspecs' let restwidth = tableWidth - sum widths let zerocols = length $ filter (==0.0) widths let defaultwidth = if zerocols == 0 || zerocols == length widths then 0.0 else restwidth / fromIntegral zerocols let widths' = map (\w -> if w == 0 then defaultwidth else w) widths let cellspecs = zip (map fst cellspecs') widths' rows' <- many $ try $ rowsep *> (map snd <$> tableRow) tableEnd let cols = length hdr let (headers,rows) = if hasheader then (hdr, rows') else (replicate cols mempty, hdr:rows') return $ B.table caption cellspecs headers rows parseAttrs :: MWParser [(String,String)] parseAttrs = many1 parseAttr parseAttr :: MWParser (String, String) parseAttr = try $ do skipMany spaceChar k <- many1 letter char '=' char '"' v <- many1Till (satisfy (/='\n')) (char '"') return (k,v) tableStart :: MWParser () tableStart = try $ guardColumnOne *> skipSpaces *> sym "{|" tableEnd :: MWParser () tableEnd = try $ guardColumnOne *> skipSpaces *> sym "|}" rowsep :: MWParser () rowsep = try $ guardColumnOne *> skipSpaces *> sym "|-" <* optional parseAttr <* blanklines cellsep :: MWParser () cellsep = try $ (guardColumnOne *> skipSpaces <* ( (char '|' <* notFollowedBy (oneOf "-}+")) <|> (char '!') ) ) <|> (() <$ try (string "||")) <|> (() <$ try (string "!!")) tableCaption :: MWParser Inlines tableCaption = try $ do guardColumnOne skipSpaces sym "|+" optional (try $ parseAttr *> skipSpaces *> char '|' *> skipSpaces) (trimInlines . mconcat) <$> many (notFollowedBy (cellsep <|> rowsep) *> inline) tableRow :: MWParser [((Alignment, Double), Blocks)] tableRow = try $ many tableCell tableCell :: MWParser ((Alignment, Double), Blocks) tableCell = try $ do cellsep skipMany spaceChar attrs <- option [] $ try $ parseAttrs <* skipSpaces <* char '|' <* notFollowedBy (char '|') skipMany spaceChar ls <- concat <$> many (notFollowedBy (cellsep <|> rowsep <|> tableEnd) *> ((snd <$> withRaw table) <|> count 1 anyChar)) bs <- parseFromString (mconcat <$> many block) ls let align = case lookup "align" attrs of Just "left" -> AlignLeft Just "right" -> AlignRight Just "center" -> AlignCenter _ -> AlignDefault let width = case lookup "width" attrs of Just xs -> maybe 0.0 id $ parseWidth xs Nothing -> 0.0 return ((align, width), bs) parseWidth :: String -> Maybe Double parseWidth s = case reverse s of ('%':ds) | all isDigit ds -> safeRead ('0':'.':reverse ds) _ -> Nothing template :: MWParser String template = try $ do string "{{" notFollowedBy (char '{') let chunk = template <|> variable <|> many1 (noneOf "{}") <|> count 1 anyChar contents <- manyTill chunk (try $ string "}}") return $ "{{" ++ concat contents ++ "}}" blockTag :: MWParser Blocks blockTag = do (tag, _) <- lookAhead $ htmlTag isBlockTag' case tag of TagOpen "blockquote" _ -> B.blockQuote <$> blocksInTags "blockquote" TagOpen "pre" _ -> B.codeBlock . trimCode <$> charsInTags "pre" TagOpen "syntaxhighlight" attrs -> syntaxhighlight "syntaxhighlight" attrs TagOpen "source" attrs -> syntaxhighlight "source" attrs TagOpen "haskell" _ -> B.codeBlockWith ("",["haskell"],[]) . trimCode <$> charsInTags "haskell" TagOpen "gallery" _ -> blocksInTags "gallery" TagOpen "p" _ -> mempty <$ htmlTag (~== tag) TagClose "p" -> mempty <$ htmlTag (~== tag) _ -> B.rawBlock "html" . snd <$> htmlTag (~== tag) trimCode :: String -> String trimCode ('\n':xs) = stripTrailingNewlines xs trimCode xs = stripTrailingNewlines xs syntaxhighlight :: String -> [Attribute String] -> MWParser Blocks syntaxhighlight tag attrs = try $ do let mblang = lookup "lang" attrs let mbstart = lookup "start" attrs let mbline = lookup "line" attrs let classes = maybe [] (:[]) mblang ++ maybe [] (const ["numberLines"]) mbline let kvs = maybe [] (\x -> [("startFrom",x)]) mbstart contents <- charsInTags tag return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents hrule :: MWParser Blocks hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline) guardColumnOne :: MWParser () guardColumnOne = getPosition >>= \pos -> guard (sourceColumn pos == 1) preformatted :: MWParser Blocks preformatted = try $ do guardColumnOne char ' ' let endline' = B.linebreak <$ (try $ newline <* char ' ') let whitespace' = B.str <$> many1 ('\160' <$ spaceChar) let spToNbsp ' ' = '\160' spToNbsp x = x let nowiki' = mconcat . intersperse B.linebreak . map B.str . lines . fromEntities . map spToNbsp <$> try (htmlTag (~== TagOpen "nowiki" []) *> manyTill anyChar (htmlTag (~== TagClose "nowiki"))) let inline' = whitespace' <|> endline' <|> nowiki' <|> (try $ notFollowedBy newline *> inline) let strToCode (Str s) = Code ("",[],[]) s strToCode x = x contents <- mconcat <$> many1 inline' let spacesStr (Str xs) = all isSpace xs spacesStr _ = False if F.all spacesStr contents then return mempty else return $ B.para $ walk strToCode contents header :: MWParser Blocks header = try $ do guardColumnOne eqs <- many1 (char '=') let lev = length eqs guard $ lev <= 6 contents <- trimInlines . mconcat <$> manyTill inline (count lev $ char '=') attr <- registerHeader nullAttr contents return $ B.headerWith attr lev contents bulletList :: MWParser Blocks bulletList = B.bulletList <$> ( many1 (listItem '*') <|> (htmlTag (~== TagOpen "ul" []) *> spaces *> many (listItem '*' <|> li) <* optional (htmlTag (~== TagClose "ul"))) ) orderedList :: MWParser Blocks orderedList = (B.orderedList <$> many1 (listItem '#')) <|> (B.orderedList <$> (htmlTag (~== TagOpen "ul" []) *> spaces *> many (listItem '#' <|> li) <* optional (htmlTag (~== TagClose "ul")))) <|> do (tag,_) <- htmlTag (~== TagOpen "ol" []) spaces items <- many (listItem '#' <|> li) optional (htmlTag (~== TagClose "ol")) let start = maybe 1 id $ safeRead $ fromAttrib "start" tag return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items definitionList :: MWParser Blocks definitionList = B.definitionList <$> many1 defListItem defListItem :: MWParser (Inlines, [Blocks]) 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 notFollowedBy (try $ string ":<math>") *> many1 (listItem ':') else many (listItem ':') return (terms, defs) defListTerm :: MWParser Inlines defListTerm = char ';' >> skipMany spaceChar >> anyLine >>= parseFromString (trimInlines . mconcat <$> many inline) listStart :: Char -> MWParser () listStart c = char c *> notFollowedBy listStartChar listStartChar :: MWParser Char listStartChar = oneOf "*#;:" anyListStart :: MWParser Char anyListStart = char '*' <|> char '#' <|> char ':' <|> char ';' li :: MWParser Blocks li = lookAhead (htmlTag (~== TagOpen "li" [])) *> (firstParaToPlain <$> blocksInTags "li") <* spaces listItem :: Char -> MWParser Blocks listItem c = try $ do extras <- many (try $ char c <* lookAhead listStartChar) if null extras then listItem' c else do skipMany spaceChar first <- concat <$> manyTill listChunk newline rest <- many (try $ string extras *> (concat <$> manyTill listChunk newline)) contents <- parseFromString (many1 $ listItem' c) (unlines (first : rest)) case c of '*' -> return $ B.bulletList contents '#' -> return $ B.orderedList contents ':' -> return $ B.definitionList [(mempty, contents)] _ -> mzero -- The point of this is to handle stuff like -- * {{cite book -- | blah -- | blah -- }} -- * next list item -- which seems to be valid mediawiki. listChunk :: MWParser String listChunk = template <|> count 1 anyChar listItem' :: Char -> MWParser Blocks listItem' c = try $ do listStart c skipMany spaceChar first <- concat <$> manyTill listChunk newline rest <- many (try $ char c *> lookAhead listStartChar *> (concat <$> manyTill listChunk newline)) parseFromString (firstParaToPlain . mconcat <$> many1 block) $ unlines $ first : rest firstParaToPlain :: Blocks -> Blocks firstParaToPlain contents = case viewl (B.unMany contents) of (Para xs) :< ys -> B.Many $ (Plain xs) <| ys _ -> contents -- -- inline parsers -- inline :: MWParser Inlines inline = whitespace <|> url <|> str <|> doubleQuotes <|> strong <|> emph <|> image <|> internalLink <|> externalLink <|> math <|> inlineTag <|> B.singleton <$> charRef <|> inlineHtml <|> (B.rawInline "mediawiki" <$> variable) <|> (B.rawInline "mediawiki" <$> template) <|> special 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 "{{{" contents <- manyTill anyChar (try $ string "}}}") return $ "{{{" ++ contents ++ "}}}" inlineTag :: MWParser Inlines inlineTag = do (tag, _) <- lookAhead $ htmlTag isInlineTag' case tag of TagOpen "ref" _ -> B.note . B.plain <$> inlinesInTags "ref" TagOpen "nowiki" _ -> try $ do (_,raw) <- htmlTag (~== tag) if '/' `elem` raw then return mempty else B.text . fromEntities <$> manyTill anyChar (htmlTag (~== TagClose "nowiki")) TagOpen "br" _ -> B.linebreak <$ (htmlTag (~== TagOpen "br" []) -- will get /> too *> optional blankline) TagOpen "strike" _ -> B.strikeout <$> inlinesInTags "strike" TagOpen "del" _ -> B.strikeout <$> inlinesInTags "del" TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub" TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup" TagOpen "code" _ -> B.code <$> charsInTags "code" TagOpen "tt" _ -> B.code <$> charsInTags "tt" TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask" _ -> B.rawInline "html" . snd <$> htmlTag (~== tag) special :: MWParser Inlines special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *> oneOf specialChars) inlineHtml :: MWParser Inlines inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag' whitespace :: MWParser Inlines whitespace = B.space <$ (skipMany1 spaceChar <|> endline <|> htmlComment) endline :: MWParser () endline = () <$ try (newline <* notFollowedBy spaceChar <* notFollowedBy newline <* notFollowedBy' hrule <* notFollowedBy tableStart <* notFollowedBy' header <* notFollowedBy anyListStart) image :: MWParser Inlines image = try $ do sym "[[" sym "File:" <|> sym "Image:" fname <- many1 (noneOf "|]") _ <- many (try $ char '|' *> imageOption) caption <- (B.str fname <$ sym "]]") <|> try (char '|' *> (mconcat <$> manyTill inline (sym "]]"))) return $ B.image fname ("fig:" ++ stringify caption) caption imageOption :: MWParser String imageOption = try (oneOfStrings [ "border", "thumbnail", "frameless" , "thumb", "upright", "left", "right" , "center", "none", "baseline", "sub" , "super", "top", "text-top", "middle" , "bottom", "text-bottom" ]) <|> try (string "frame") <|> try (many1 (oneOf "x0123456789") <* string "px") <|> try (oneOfStrings ["link=","alt=","page=","class="] <* many (noneOf "|]")) internalLink :: MWParser Inlines internalLink = try $ do sym "[[" let addUnderscores x = let (pref,suff) = break (=='#') x in pref ++ intercalate "_" (words suff) pagename <- unwords . words <$> many (noneOf "|]") label <- option (B.text pagename) $ char '|' *> ( (mconcat <$> many1 (notFollowedBy (char ']') *> inline)) -- the "pipe trick" -- [[Help:Contents|] -> "Contents" <|> (return $ B.text $ drop 1 $ dropWhile (/=':') pagename) ) sym "]]" linktrail <- B.text <$> many letter let link = B.link (addUnderscores pagename) "wikilink" (label <> linktrail) if "Category:" `isPrefixOf` pagename then do updateState $ \st -> st{ mwCategoryLinks = link : mwCategoryLinks st } return mempty else return link externalLink :: MWParser Inlines externalLink = try $ do char '[' (_, src) <- uri lab <- try (trimInlines . mconcat <$> (skipMany1 spaceChar *> manyTill inline (char ']'))) <|> do char ']' num <- mwNextLinkNumber <$> getState updateState $ \st -> st{ mwNextLinkNumber = num + 1 } return $ B.str $ show num return $ B.link src "" lab url :: MWParser Inlines url = do (orig, src) <- uri return $ B.link src "" (B.str orig) -- | Parses a list of inlines between start and end delimiters. inlinesBetween :: (Show b) => MWParser a -> MWParser b -> MWParser Inlines inlinesBetween start end = (trimInlines . mconcat) <$> try (start >> many1Till inner end) where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline) innerSpace = try $ whitespace >>~ notFollowedBy' end emph :: MWParser Inlines emph = B.emph <$> nested (inlinesBetween start end) where start = sym "''" >> lookAhead nonspaceChar end = try $ notFollowedBy' (() <$ strong) >> sym "''" strong :: MWParser Inlines strong = B.strong <$> nested (inlinesBetween start end) where start = sym "'''" >> lookAhead nonspaceChar end = try $ sym "'''" doubleQuotes :: MWParser Inlines doubleQuotes = B.doubleQuoted . trimInlines . mconcat <$> try ((getState >>= guard . readerSmart . mwOptions) *> openDoubleQuote *> manyTill inline closeDoubleQuote ) where openDoubleQuote = char '"' <* lookAhead alphaNum closeDoubleQuote = char '"' <* notFollowedBy alphaNum �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/Native.hs���������������������������������������������������000644 �000765 �000024 �00000004332 12251233602 021204� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2011 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.Native Copyright : Copyright (C) 2011 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of a string representation of a pandoc type (@Pandoc@, @[Block]@, @Block@, @[Inline]@, or @Inline@) to a @Pandoc@ document. -} module Text.Pandoc.Readers.Native ( readNative ) where import Text.Pandoc.Definition import Text.Pandoc.Shared (safeRead) -- | Read native formatted text and return a Pandoc document. -- The input may be a full pandoc document, a block list, a block, -- an inline list, or an inline. Thus, for example, -- -- > Str "hi" -- -- will be treated as if it were -- -- > Pandoc nullMeta [Plain [Str "hi"]] -- readNative :: String -- ^ String to parse (assuming @'\n'@ line endings) -> Pandoc readNative s = case safeRead s of Just d -> d Nothing -> Pandoc nullMeta $ readBlocks s readBlocks :: String -> [Block] readBlocks s = case safeRead s of Just d -> d Nothing -> [readBlock s] readBlock :: String -> Block readBlock s = case safeRead s of Just d -> d Nothing -> Plain $ readInlines s readInlines :: String -> [Inline] readInlines s = case safeRead s of Just d -> d Nothing -> [readInline s] readInline :: String -> Inline readInline s = case safeRead s of Just d -> d Nothing -> error "Cannot parse document" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/OPML.hs�����������������������������������������������������000644 �000765 �000024 �00000007622 12251233602 020532� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������module Text.Pandoc.Readers.OPML ( readOPML ) where import Data.Char (toUpper) import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Builder import Text.Pandoc.Readers.HTML (readHtml) import Text.Pandoc.Readers.Markdown (readMarkdown) import Text.XML.Light import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) import Data.Generics import Data.Monoid import Control.Monad.State import Control.Applicative ((<$>), (<$)) type OPML = State OPMLState data OPMLState = OPMLState{ opmlSectionLevel :: Int , opmlDocTitle :: Inlines , opmlDocAuthors :: [Inlines] , opmlDocDate :: Inlines } deriving Show readOPML :: ReaderOptions -> String -> Pandoc readOPML _ inp = setTitle (opmlDocTitle st') $ setAuthors (opmlDocAuthors st') $ setDate (opmlDocDate st') $ doc $ mconcat bs where (bs, st') = runState (mapM parseBlock $ normalizeTree $ parseXML inp) OPMLState{ opmlSectionLevel = 0 , opmlDocTitle = mempty , opmlDocAuthors = [] , opmlDocDate = mempty } -- normalize input, consolidating adjacent Text and CRef elements normalizeTree :: [Content] -> [Content] normalizeTree = everywhere (mkT go) where go :: [Content] -> [Content] go (Text (CData CDataRaw _ _):xs) = xs go (Text (CData CDataText s1 z):Text (CData CDataText s2 _):xs) = Text (CData CDataText (s1 ++ s2) z):xs go (Text (CData CDataText s1 z):CRef r:xs) = Text (CData CDataText (s1 ++ convertEntity r) z):xs go (CRef r:Text (CData CDataText s1 z):xs) = Text (CData CDataText (convertEntity r ++ s1) z):xs go (CRef r1:CRef r2:xs) = Text (CData CDataText (convertEntity r1 ++ convertEntity r2) Nothing):xs go xs = xs convertEntity :: String -> String convertEntity e = maybe (map toUpper e) (:[]) (lookupEntity e) -- convenience function to get an attribute value, defaulting to "" attrValue :: String -> Element -> String attrValue attr elt = case lookupAttrBy (\x -> qName x == attr) (elAttribs elt) of Just z -> z Nothing -> "" asHtml :: String -> Inlines asHtml s = case readHtml def s of Pandoc _ [Plain ils] -> fromList ils _ -> mempty asMarkdown :: String -> Blocks asMarkdown s = fromList bs where Pandoc _ bs = readMarkdown def s getBlocks :: Element -> OPML Blocks getBlocks e = mconcat <$> (mapM parseBlock $ elContent e) parseBlock :: Content -> OPML Blocks parseBlock (Elem e) = case qName (elName e) of "ownerName" -> mempty <$ modify (\st -> st{opmlDocAuthors = [text $ strContent e]}) "dateModified" -> mempty <$ modify (\st -> st{opmlDocDate = text $ strContent e}) "title" -> mempty <$ modify (\st -> st{opmlDocTitle = text $ strContent e}) "outline" -> gets opmlSectionLevel >>= sect . (+1) "?xml" -> return mempty _ -> getBlocks e where sect n = do let headerText = asHtml $ attrValue "text" e let noteBlocks = asMarkdown $ attrValue "_note" e modify $ \st -> st{ opmlSectionLevel = n } bs <- getBlocks e modify $ \st -> st{ opmlSectionLevel = n - 1 } let headerText' = case map toUpper (attrValue "type" e) of "LINK" -> link (attrValue "url" e) "" headerText _ -> headerText return $ header n headerText' <> noteBlocks <> bs parseBlock _ = return mempty ��������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/RST.hs������������������������������������������������������000644 �000765 �000024 �00000111127 12251233602 020427� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.RST Copyright : Copyright (C) 2006-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion from reStructuredText to 'Pandoc' document. -} module Text.Pandoc.Readers.RST ( readRST ) where import Text.Pandoc.Definition import Text.Pandoc.Builder (setMeta, fromList) import Text.Pandoc.Shared import Text.Pandoc.Parsing import Text.Pandoc.Options import Control.Monad ( when, liftM, guard, mzero ) import Data.List ( findIndex, intersperse, intercalate, transpose, sort, deleteFirstsBy, isSuffixOf ) import qualified Data.Map as M import Text.Printf ( printf ) import Control.Applicative ((<$>), (<$), (<*), (*>)) import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>)) import qualified Text.Pandoc.Builder as B import Data.Monoid (mconcat, mempty) import Data.Sequence (viewr, ViewR(..)) import Data.Char (toLower) -- | Parse reStructuredText string and return Pandoc document. readRST :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assuming @'\n'@ line endings) -> Pandoc readRST opts s = (readWith parseRST) def{ stateOptions = opts } (s ++ "\n\n") type RSTParser = Parser [Char] ParserState -- -- Constants and data structure definitions --- bulletListMarkers :: [Char] bulletListMarkers = "*+-" underlineChars :: [Char] underlineChars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" -- treat these as potentially non-text when parsing inline: specialChars :: [Char] specialChars = "\\`|*_<>$:/[]{}()-.\"'\8216\8217\8220\8221" -- -- parsing documents -- isHeader :: Int -> Block -> Bool isHeader n (Header x _ _) = x == n isHeader _ _ = False -- | Promote all headers in a list of blocks. (Part of -- title transformation for RST.) promoteHeaders :: Int -> [Block] -> [Block] promoteHeaders num ((Header level attr text):rest) = (Header (level - num) attr text):(promoteHeaders num rest) promoteHeaders num (other:rest) = other:(promoteHeaders num rest) promoteHeaders _ [] = [] -- | If list of blocks starts with a header (or a header and subheader) -- of level that are not found elsewhere, return it as a title and -- promote all the other headers. Also process a definition list right -- after the title block as metadata. titleTransform :: ([Block], Meta) -- ^ list of blocks, metadata -> ([Block], Meta) -- ^ modified list of blocks, metadata titleTransform (bs, meta) = let (bs', meta') = case bs of ((Header 1 _ head1):(Header 2 _ head2):rest) | not (any (isHeader 1) rest || any (isHeader 2) rest) -> -- tit/sub (promoteHeaders 2 rest, setMeta "title" (fromList head1) $ setMeta "subtitle" (fromList head2) meta) ((Header 1 _ head1):rest) | not (any (isHeader 1) rest) -> -- title only (promoteHeaders 1 rest, setMeta "title" (fromList head1) meta) _ -> (bs, meta) in case bs' of (DefinitionList ds : rest) -> (rest, metaFromDefList ds meta') _ -> (bs', meta') metaFromDefList :: [([Inline], [[Block]])] -> Meta -> Meta metaFromDefList ds meta = adjustAuthors $ foldr f meta ds where f (k,v) = setMeta (map toLower $ stringify k) (mconcat $ map fromList v) adjustAuthors (Meta metamap) = Meta $ M.adjust toPlain "author" $ M.adjust toPlain "date" $ M.adjust toPlain "title" $ M.adjust splitAuthors "authors" $ metamap toPlain (MetaBlocks [Para xs]) = MetaInlines xs toPlain x = x splitAuthors (MetaBlocks [Para xs]) = MetaList $ map MetaInlines $ splitAuthors' xs splitAuthors x = x splitAuthors' = map normalizeSpaces . splitOnSemi . concatMap factorSemi splitOnSemi = splitBy (==Str ";") factorSemi (Str []) = [] factorSemi (Str s) = case break (==';') s of (xs,[]) -> [Str xs] (xs,';':ys) -> Str xs : Str ";" : factorSemi (Str ys) (xs,ys) -> Str xs : factorSemi (Str ys) factorSemi x = [x] parseRST :: RSTParser Pandoc parseRST = do optional blanklines -- skip blank lines at beginning of file startPos <- getPosition -- go through once just to get list of reference keys and notes -- docMinusKeys is the raw document with blanks where the keys were... docMinusKeys <- concat <$> manyTill (referenceKey <|> noteBlock <|> lineClump) eof setInput docMinusKeys setPosition startPos st' <- getState let reversedNotes = stateNotes st' updateState $ \s -> s { stateNotes = reverse reversedNotes } -- now parse it for real... blocks <- B.toList <$> parseBlocks standalone <- getOption readerStandalone state <- getState let meta = stateMeta state let (blocks', meta') = if standalone then titleTransform (blocks, meta) else (blocks, meta) return $ Pandoc meta' blocks' -- -- parsing blocks -- parseBlocks :: RSTParser Blocks parseBlocks = mconcat <$> manyTill block eof block :: RSTParser Blocks block = choice [ codeBlock , blockQuote , fieldList , directive , comment , header , hrule , lineBlock -- must go before definitionList , table , list , lhsCodeBlock , para , mempty <$ blanklines ] <?> "block" -- -- field list -- rawFieldListItem :: String -> RSTParser (String, String) rawFieldListItem indent = try $ do string indent char ':' name <- many1Till (noneOf "\n") (char ':') (() <$ lookAhead newline) <|> skipMany1 spaceChar first <- anyLine rest <- option "" $ try $ do lookAhead (string indent >> spaceChar) indentedBlock let raw = (if null first then "" else (first ++ "\n")) ++ rest ++ "\n" return (name, raw) fieldListItem :: String -> RSTParser (Inlines, [Blocks]) fieldListItem indent = try $ do (name, raw) <- rawFieldListItem indent let term = B.str name contents <- parseFromString parseBlocks raw optional blanklines return (term, [contents]) fieldList :: RSTParser Blocks fieldList = try $ do indent <- lookAhead $ many spaceChar items <- many1 $ fieldListItem indent case items of [] -> return mempty items' -> return $ B.definitionList items' -- -- line block -- lineBlock :: RSTParser Blocks lineBlock = try $ do lines' <- lineBlockLines lines'' <- mapM (parseFromString (trimInlines . mconcat <$> many inline)) lines' return $ B.para (mconcat $ intersperse B.linebreak lines'') -- -- paragraph block -- -- note: paragraph can end in a :: starting a code block para :: RSTParser Blocks para = try $ do result <- trimInlines . mconcat <$> many1 inline option (B.plain result) $ try $ do newline blanklines case viewr (B.unMany result) of ys :> (Str xs) | "::" `isSuffixOf` xs -> do raw <- option mempty codeBlockBody return $ B.para (B.Many ys <> B.str (take (length xs - 1) xs)) <> raw _ -> return (B.para result) plain :: RSTParser Blocks plain = B.plain . trimInlines . mconcat <$> many1 inline -- -- header blocks -- header :: RSTParser Blocks header = doubleHeader <|> singleHeader <?> "header" -- a header with lines on top and bottom doubleHeader :: RSTParser Blocks doubleHeader = try $ do c <- oneOf underlineChars rest <- many (char c) -- the top line let lenTop = length (c:rest) skipSpaces newline txt <- trimInlines . mconcat <$> many1 (notFollowedBy blankline >> inline) pos <- getPosition let len = (sourceColumn pos) - 1 if (len > lenTop) then fail "title longer than border" else return () blankline -- spaces and newline count lenTop (char c) -- the bottom line blanklines -- check to see if we've had this kind of header before. -- if so, get appropriate level. if not, add to list. state <- getState let headerTable = stateHeaderTable state let (headerTable',level) = case findIndex (== DoubleHeader c) headerTable of Just ind -> (headerTable, ind + 1) Nothing -> (headerTable ++ [DoubleHeader c], (length headerTable) + 1) setState (state { stateHeaderTable = headerTable' }) attr <- registerHeader nullAttr txt return $ B.headerWith attr level txt -- a header with line on the bottom only singleHeader :: RSTParser Blocks singleHeader = try $ do notFollowedBy' whitespace txt <- trimInlines . mconcat <$> many1 (do {notFollowedBy blankline; inline}) pos <- getPosition let len = (sourceColumn pos) - 1 blankline c <- oneOf underlineChars count (len - 1) (char c) many (char c) blanklines state <- getState let headerTable = stateHeaderTable state let (headerTable',level) = case findIndex (== SingleHeader c) headerTable of Just ind -> (headerTable, ind + 1) Nothing -> (headerTable ++ [SingleHeader c], (length headerTable) + 1) setState (state { stateHeaderTable = headerTable' }) attr <- registerHeader nullAttr txt return $ B.headerWith attr level txt -- -- hrule block -- hrule :: Parser [Char] st Blocks hrule = try $ do chr <- oneOf underlineChars count 3 (char chr) skipMany (char chr) blankline blanklines return B.horizontalRule -- -- code blocks -- -- read a line indented by a given string indentedLine :: String -> Parser [Char] st [Char] indentedLine indents = try $ do string indents anyLine -- one or more indented lines, possibly separated by blank lines. -- any amount of indentation will work. indentedBlock :: Parser [Char] st [Char] indentedBlock = try $ do indents <- lookAhead $ many1 spaceChar lns <- many1 $ try $ do b <- option "" blanklines l <- indentedLine indents return (b ++ l) optional blanklines return $ unlines lns codeBlockStart :: Parser [Char] st Char codeBlockStart = string "::" >> blankline >> blankline codeBlock :: Parser [Char] st Blocks codeBlock = try $ codeBlockStart >> codeBlockBody codeBlockBody :: Parser [Char] st Blocks codeBlockBody = try $ B.codeBlock . stripTrailingNewlines <$> indentedBlock lhsCodeBlock :: RSTParser Blocks lhsCodeBlock = try $ do getPosition >>= guard . (==1) . sourceColumn guardEnabled Ext_literate_haskell optional codeBlockStart lns <- many1 birdTrackLine -- if (as is normal) there is always a space after >, drop it let lns' = if all (\ln -> null ln || take 1 ln == " ") lns then map (drop 1) lns else lns blanklines return $ B.codeBlockWith ("", ["sourceCode", "literate", "haskell"], []) $ intercalate "\n" lns' birdTrackLine :: Parser [Char] st [Char] birdTrackLine = char '>' >> anyLine -- -- block quotes -- blockQuote :: RSTParser Blocks blockQuote = do raw <- indentedBlock -- parse the extracted block, which may contain various block elements: contents <- parseFromString parseBlocks $ raw ++ "\n\n" return $ B.blockQuote contents -- -- list blocks -- list :: RSTParser Blocks list = choice [ bulletList, orderedList, definitionList ] <?> "list" definitionListItem :: RSTParser (Inlines, [Blocks]) definitionListItem = try $ do -- avoid capturing a directive or comment notFollowedBy (try $ char '.' >> char '.') term <- trimInlines . mconcat <$> many1Till inline endline raw <- indentedBlock -- parse the extracted block, which may contain various block elements: contents <- parseFromString parseBlocks $ raw ++ "\n" return (term, [contents]) definitionList :: RSTParser Blocks definitionList = B.definitionList <$> many1 definitionListItem -- parses bullet list start and returns its length (inc. following whitespace) bulletListStart :: Parser [Char] st Int bulletListStart = try $ do notFollowedBy' hrule -- because hrules start out just like lists marker <- oneOf bulletListMarkers white <- many1 spaceChar return $ length (marker:white) -- parses ordered list start and returns its length (inc following whitespace) orderedListStart :: ListNumberStyle -> ListNumberDelim -> RSTParser Int orderedListStart style delim = try $ do (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim) white <- many1 spaceChar return $ markerLen + length white -- parse a line of a list item listLine :: Int -> RSTParser [Char] listLine markerLength = try $ do notFollowedBy blankline indentWith markerLength line <- anyLine return $ line ++ "\n" -- indent by specified number of spaces (or equiv. tabs) indentWith :: Int -> RSTParser [Char] indentWith num = do tabStop <- getOption readerTabStop if (num < tabStop) then count num (char ' ') else choice [ try (count num (char ' ')), (try (char '\t' >> count (num - tabStop) (char ' '))) ] -- parse raw text for one list item, excluding start marker and continuations rawListItem :: RSTParser Int -> RSTParser (Int, [Char]) rawListItem start = try $ do markerLength <- start firstLine <- anyLine restLines <- many (listLine markerLength) return (markerLength, (firstLine ++ "\n" ++ (concat restLines))) -- continuation of a list item - indented and separated by blankline or -- (in compact lists) endline. -- Note: nested lists are parsed as continuations. listContinuation :: Int -> RSTParser [Char] listContinuation markerLength = try $ do blanks <- many1 blankline result <- many1 (listLine markerLength) return $ blanks ++ concat result listItem :: RSTParser Int -> RSTParser Blocks listItem start = try $ do (markerLength, first) <- rawListItem start rest <- many (listContinuation markerLength) blanks <- choice [ try (many blankline >>~ lookAhead start), many1 blankline ] -- whole list must end with blank. -- parsing with ListItemState forces markers at beginning of lines to -- count as list item markers, even if not separated by blank space. -- see definition of "endline" state <- getState let oldContext = stateParserContext state setState $ state {stateParserContext = ListItemState} -- parse the extracted block, which may itself contain block elements parsed <- parseFromString parseBlocks $ concat (first:rest) ++ blanks updateState (\st -> st {stateParserContext = oldContext}) return $ case B.toList parsed of [Para xs] -> B.singleton $ Plain xs [Para xs, BulletList ys] -> B.fromList [Plain xs, BulletList ys] [Para xs, OrderedList s ys] -> B.fromList [Plain xs, OrderedList s ys] [Para xs, DefinitionList ys] -> B.fromList [Plain xs, DefinitionList ys] _ -> parsed orderedList :: RSTParser Blocks orderedList = try $ do (start, style, delim) <- lookAhead (anyOrderedListMarker >>~ spaceChar) items <- many1 (listItem (orderedListStart style delim)) let items' = compactify' items return $ B.orderedListWith (start, style, delim) items' bulletList :: RSTParser Blocks bulletList = B.bulletList . compactify' <$> many1 (listItem bulletListStart) -- -- directive (e.g. comment, container, compound-paragraph) -- comment :: RSTParser Blocks comment = try $ do string ".." skipMany1 spaceChar <|> (() <$ lookAhead newline) notFollowedBy' directiveLabel manyTill anyChar blanklines optional indentedBlock return mempty directiveLabel :: RSTParser String directiveLabel = map toLower <$> many1Till (letter <|> char '-') (try $ string "::") directive :: RSTParser Blocks directive = try $ do string ".." directive' -- TODO: line-block, parsed-literal, table, csv-table, list-table -- date -- include -- class -- title directive' :: RSTParser Blocks directive' = do skipMany1 spaceChar label <- directiveLabel skipMany spaceChar top <- many $ satisfy (/='\n') <|> try (char '\n' <* notFollowedBy' (rawFieldListItem " ") <* count 3 (char ' ') <* notFollowedBy blankline) newline fields <- many $ rawFieldListItem " " body <- option "" $ try $ blanklines >> indentedBlock optional blanklines let body' = body ++ "\n\n" case label of "raw" -> return $ B.rawBlock (trim top) (stripTrailingNewlines body) "role" -> return mempty "container" -> parseFromString parseBlocks body' "replace" -> B.para <$> -- consumed by substKey parseFromString (trimInlines . mconcat <$> many inline) (trim top) "unicode" -> B.para <$> -- consumed by substKey parseFromString (trimInlines . mconcat <$> many inline) (trim $ unicodeTransform top) "compound" -> parseFromString parseBlocks body' "pull-quote" -> B.blockQuote <$> parseFromString parseBlocks body' "epigraph" -> B.blockQuote <$> parseFromString parseBlocks body' "highlights" -> B.blockQuote <$> parseFromString parseBlocks body' "rubric" -> B.para . B.strong <$> parseFromString (trimInlines . mconcat <$> many inline) top _ | label `elem` ["attention","caution","danger","error","hint", "important","note","tip","warning"] -> do let tit = B.para $ B.strong $ B.str label bod <- parseFromString parseBlocks $ top ++ "\n\n" ++ body' return $ B.blockQuote $ tit <> bod "admonition" -> do tit <- B.para . B.strong <$> parseFromString (trimInlines . mconcat <$> many inline) top bod <- parseFromString parseBlocks body' return $ B.blockQuote $ tit <> bod "sidebar" -> do let subtit = maybe "" trim $ lookup "subtitle" fields tit <- B.para . B.strong <$> parseFromString (trimInlines . mconcat <$> many inline) (trim top ++ if null subtit then "" else (": " ++ subtit)) bod <- parseFromString parseBlocks body' return $ B.blockQuote $ tit <> bod "topic" -> do tit <- B.para . B.strong <$> parseFromString (trimInlines . mconcat <$> many inline) top bod <- parseFromString parseBlocks body' return $ tit <> bod "default-role" -> mempty <$ updateState (\s -> s { stateRstDefaultRole = case trim top of "" -> stateRstDefaultRole def role -> role }) "code" -> codeblock (lookup "number-lines" fields) (trim top) body "code-block" -> codeblock (lookup "number-lines" fields) (trim top) body "math" -> return $ B.para $ mconcat $ map B.displayMath $ toChunks $ top ++ "\n\n" ++ body "figure" -> do (caption, legend) <- parseFromString extractCaption body' let src = escapeURI $ trim top return $ B.para (B.image src "" caption) <> legend "image" -> do let src = escapeURI $ trim top let alt = B.str $ maybe "image" trim $ lookup "alt" fields return $ B.para $ case lookup "target" fields of Just t -> B.link (escapeURI $ trim t) "" $ B.image src "" alt Nothing -> B.image src "" alt _ -> return mempty -- Can contain haracter codes as decimal numbers or -- hexadecimal numbers, prefixed by 0x, x, \x, U+, u, or \u -- or as XML-style hexadecimal character entities, e.g. ᨫ -- or text, which is used as-is. Comments start with .. unicodeTransform :: String -> String unicodeTransform t = case t of ('.':'.':xs) -> unicodeTransform $ dropWhile (/='\n') xs -- comment ('0':'x':xs) -> go "0x" xs ('x':xs) -> go "x" xs ('\\':'x':xs) -> go "\\x" xs ('U':'+':xs) -> go "U+" xs ('u':xs) -> go "u" xs ('\\':'u':xs) -> go "\\u" xs ('&':'#':'x':xs) -> maybe ("&#x" ++ unicodeTransform xs) -- drop semicolon (\(c,s) -> c : unicodeTransform (drop 1 s)) $ extractUnicodeChar xs (x:xs) -> x : unicodeTransform xs [] -> [] where go pref zs = maybe (pref ++ unicodeTransform zs) (\(c,s) -> c : unicodeTransform s) $ extractUnicodeChar zs extractUnicodeChar :: String -> Maybe (Char, String) extractUnicodeChar s = maybe Nothing (\c -> Just (c,rest)) mbc where (ds,rest) = span isHexDigit s mbc = safeRead ('\'':'\\':'x':ds ++ "'") isHexDigit :: Char -> Bool isHexDigit c = c `elem` "0123456789ABCDEFabcdef" extractCaption :: RSTParser (Inlines, Blocks) extractCaption = do capt <- trimInlines . mconcat <$> many inline legend <- optional blanklines >> (mconcat <$> many block) return (capt,legend) -- divide string by blanklines toChunks :: String -> [String] toChunks = dropWhile null . map (trim . unlines) . splitBy (all (`elem` " \t")) . lines codeblock :: Maybe String -> String -> String -> RSTParser Blocks codeblock numberLines lang body = return $ B.codeBlockWith attribs $ stripTrailingNewlines body where attribs = ("", classes, kvs) classes = "sourceCode" : lang : maybe [] (\_ -> ["numberLines"]) numberLines kvs = case numberLines of Just "" -> [] Nothing -> [] Just n -> [("startFrom",trim n)] --- --- note block --- noteBlock :: RSTParser [Char] noteBlock = try $ do startPos <- getPosition string ".." spaceChar >> skipMany spaceChar ref <- noteMarker first <- (spaceChar >> skipMany spaceChar >> anyLine) <|> (newline >> return "") blanks <- option "" blanklines rest <- option "" indentedBlock endPos <- getPosition let raw = first ++ "\n" ++ blanks ++ rest ++ "\n" let newnote = (ref, raw) st <- getState let oldnotes = stateNotes st updateState $ \s -> s { stateNotes = newnote : oldnotes } -- return blanks so line count isn't affected return $ replicate (sourceLine endPos - sourceLine startPos) '\n' noteMarker :: RSTParser [Char] noteMarker = do char '[' res <- many1 digit <|> (try $ char '#' >> liftM ('#':) simpleReferenceName') <|> count 1 (oneOf "#*") char ']' return res -- -- reference key -- quotedReferenceName :: RSTParser Inlines quotedReferenceName = try $ do char '`' >> notFollowedBy (char '`') -- `` means inline code! label' <- trimInlines . mconcat <$> many1Till inline (char '`') return label' unquotedReferenceName :: RSTParser Inlines unquotedReferenceName = try $ do label' <- trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':') return label' -- Simple reference names are single words consisting of alphanumerics -- plus isolated (no two adjacent) internal hyphens, underscores, -- periods, colons and plus signs; no whitespace or other characters -- are allowed. simpleReferenceName' :: Parser [Char] st String simpleReferenceName' = do x <- alphaNum xs <- many $ alphaNum <|> (try $ oneOf "-_:+." >> lookAhead alphaNum) return (x:xs) simpleReferenceName :: Parser [Char] st Inlines simpleReferenceName = do raw <- simpleReferenceName' return $ B.str raw referenceName :: RSTParser Inlines referenceName = quotedReferenceName <|> (try $ simpleReferenceName >>~ lookAhead (char ':')) <|> unquotedReferenceName referenceKey :: RSTParser [Char] referenceKey = do startPos <- getPosition choice [substKey, anonymousKey, regularKey] optional blanklines endPos <- getPosition -- return enough blanks to replace key return $ replicate (sourceLine endPos - sourceLine startPos) '\n' targetURI :: Parser [Char] st [Char] targetURI = do skipSpaces optional newline contents <- many1 (try (many spaceChar >> newline >> many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n") blanklines return $ escapeURI $ trim $ contents substKey :: RSTParser () substKey = try $ do string ".." skipMany1 spaceChar (alt,ref) <- withRaw $ trimInlines . mconcat <$> enclosed (char '|') (char '|') inline res <- B.toList <$> directive' il <- case res of -- use alt unless :alt: attribute on image: [Para [Image [Str "image"] (src,tit)]] -> return $ B.image src tit alt [Para [Link [Image [Str "image"] (src,tit)] (src',tit')]] -> return $ B.link src' tit' (B.image src tit alt) [Para ils] -> return $ B.fromList ils _ -> mzero let key = toKey $ stripFirstAndLast ref updateState $ \s -> s{ stateSubstitutions = M.insert key il $ stateSubstitutions s } anonymousKey :: RSTParser () anonymousKey = try $ do oneOfStrings [".. __:", "__"] src <- targetURI pos <- getPosition let key = toKey $ "_" ++ printf "%09d" (sourceLine pos) updateState $ \s -> s { stateKeys = M.insert key (src,"") $ stateKeys s } stripTicks :: String -> String stripTicks = reverse . stripTick . reverse . stripTick where stripTick ('`':xs) = xs stripTick xs = xs regularKey :: RSTParser () regularKey = try $ do string ".. _" (_,ref) <- withRaw referenceName char ':' src <- targetURI let key = toKey $ stripTicks ref updateState $ \s -> s { stateKeys = M.insert key (src,"") $ stateKeys s } -- -- tables -- -- General tables TODO: -- - figure out if leading spaces are acceptable and if so, add -- support for them -- -- Simple tables TODO: -- - column spans -- - multiline support -- - ensure that rightmost column span does not need to reach end -- - require at least 2 columns -- -- Grid tables TODO: -- - column spans dashedLine :: Char -> Parser [Char] st (Int, Int) dashedLine ch = do dashes <- many1 (char ch) sp <- many (char ' ') return (length dashes, length $ dashes ++ sp) simpleDashedLines :: Char -> Parser [Char] st [(Int,Int)] simpleDashedLines ch = try $ many1 (dashedLine ch) -- Parse a table row separator simpleTableSep :: Char -> RSTParser Char simpleTableSep ch = try $ simpleDashedLines ch >> newline -- Parse a table footer simpleTableFooter :: RSTParser [Char] simpleTableFooter = try $ simpleTableSep '=' >> blanklines -- Parse a raw line and split it into chunks by indices. simpleTableRawLine :: [Int] -> RSTParser [String] simpleTableRawLine indices = do line <- many1Till anyChar newline return (simpleTableSplitLine indices line) -- Parse a table row and return a list of blocks (columns). simpleTableRow :: [Int] -> RSTParser [[Block]] simpleTableRow indices = do notFollowedBy' simpleTableFooter firstLine <- simpleTableRawLine indices colLines <- return [] -- TODO let cols = map unlines . transpose $ firstLine : colLines mapM (parseFromString (B.toList . mconcat <$> many plain)) cols simpleTableSplitLine :: [Int] -> String -> [String] simpleTableSplitLine indices line = map trim $ tail $ splitByIndices (init indices) line simpleTableHeader :: Bool -- ^ Headerless table -> RSTParser ([[Block]], [Alignment], [Int]) simpleTableHeader headless = try $ do optional blanklines rawContent <- if headless then return "" else simpleTableSep '=' >> anyLine dashes <- simpleDashedLines '=' <|> simpleDashedLines '-' newline let lines' = map snd dashes let indices = scanl (+) 0 lines' let aligns = replicate (length lines') AlignDefault let rawHeads = if headless then replicate (length dashes) "" else simpleTableSplitLine indices rawContent heads <- mapM (parseFromString (B.toList . mconcat <$> many plain)) $ map trim rawHeads return (heads, aligns, indices) -- Parse a simple table. simpleTable :: Bool -- ^ Headerless table -> RSTParser Blocks simpleTable headless = do Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter -- Simple tables get 0s for relative column widths (i.e., use default) return $ B.singleton $ Table c a (replicate (length a) 0) h l where sep = return () -- optional (simpleTableSep '-') gridTable :: Bool -- ^ Headerless table -> RSTParser Blocks gridTable headerless = B.singleton <$> gridTableWith (B.toList <$> parseBlocks) headerless table :: RSTParser Blocks table = gridTable False <|> simpleTable False <|> gridTable True <|> simpleTable True <?> "table" -- -- inline -- inline :: RSTParser Inlines inline = choice [ whitespace , link , str , endline , strong , emph , code , subst , interpretedRole , note , smart , hyphens , escapedChar , symbol ] <?> "inline" hyphens :: RSTParser Inlines hyphens = do result <- many1 (char '-') optional endline -- don't want to treat endline after hyphen or dash as a space return $ B.str result escapedChar :: Parser [Char] st Inlines escapedChar = do c <- escaped anyChar return $ if c == ' ' -- '\ ' is null in RST then mempty else B.str [c] symbol :: RSTParser Inlines symbol = do result <- oneOf specialChars return $ B.str [result] -- parses inline code, between codeStart and codeEnd code :: RSTParser Inlines code = try $ do string "``" result <- manyTill anyChar (try (string "``")) return $ B.code $ trim $ unwords $ lines result -- succeeds only if we're not right after a str (ie. in middle of word) atStart :: RSTParser a -> RSTParser a atStart p = do pos <- getPosition st <- getState -- single quote start can't be right after str guard $ stateLastStrPos st /= Just pos p emph :: RSTParser Inlines emph = B.emph . trimInlines . mconcat <$> enclosed (atStart $ char '*') (char '*') inline strong :: RSTParser Inlines strong = B.strong . trimInlines . mconcat <$> enclosed (atStart $ string "**") (try $ string "**") inline -- Note, this doesn't precisely implement the complex rule in -- http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#inline-markup-recognition-rules -- but it should be good enough for most purposes interpretedRole :: RSTParser Inlines interpretedRole = try $ do (role, contents) <- roleBefore <|> roleAfter case role of "sup" -> return $ B.superscript $ B.str contents "sub" -> return $ B.subscript $ B.str contents "math" -> return $ B.math contents _ -> return $ B.str contents --unknown roleMarker :: RSTParser String roleMarker = char ':' *> many1Till (letter <|> char '-') (char ':') roleBefore :: RSTParser (String,String) roleBefore = try $ do role <- roleMarker contents <- unmarkedInterpretedText return (role,contents) roleAfter :: RSTParser (String,String) roleAfter = try $ do contents <- unmarkedInterpretedText role <- roleMarker <|> (stateRstDefaultRole <$> getState) return (role,contents) unmarkedInterpretedText :: RSTParser [Char] unmarkedInterpretedText = enclosed (atStart $ char '`') (char '`') anyChar whitespace :: RSTParser Inlines whitespace = B.space <$ skipMany1 spaceChar <?> "whitespace" str :: RSTParser Inlines str = do let strChar = noneOf ("\t\n " ++ specialChars) result <- many1 strChar updateLastStrPos return $ B.str result -- an endline character that can be treated as a space, not a structural break endline :: RSTParser Inlines endline = try $ do newline notFollowedBy blankline -- parse potential list-starts at beginning of line differently in a list: st <- getState if (stateParserContext st) == ListItemState then notFollowedBy (anyOrderedListMarker >> spaceChar) >> notFollowedBy' bulletListStart else return () return B.space -- -- links -- link :: RSTParser Inlines link = choice [explicitLink, referenceLink, autoLink] <?> "link" explicitLink :: RSTParser Inlines explicitLink = try $ do char '`' notFollowedBy (char '`') -- `` marks start of inline code label' <- trimInlines . mconcat <$> manyTill (notFollowedBy (char '`') >> inline) (char '<') src <- manyTill (noneOf ">\n") (char '>') skipSpaces string "`_" optional $ char '_' -- anonymous form return $ B.link (escapeURI $ trim src) "" label' referenceLink :: RSTParser Inlines referenceLink = try $ do (label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) >>~ char '_' state <- getState let keyTable = stateKeys state let isAnonKey (Key ('_':_)) = True isAnonKey _ = False key <- option (toKey $ stripTicks ref) $ do char '_' let anonKeys = sort $ filter isAnonKey $ M.keys keyTable if null anonKeys then mzero else return (head anonKeys) (src,tit) <- case M.lookup key keyTable of Nothing -> fail "no corresponding key" Just target -> return target -- if anonymous link, remove key so it won't be used again when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable } return $ B.link src tit label' autoURI :: RSTParser Inlines autoURI = do (orig, src) <- uri return $ B.link src "" $ B.str orig autoEmail :: RSTParser Inlines autoEmail = do (orig, src) <- emailAddress return $ B.link src "" $ B.str orig autoLink :: RSTParser Inlines autoLink = autoURI <|> autoEmail subst :: RSTParser Inlines subst = try $ do (_,ref) <- withRaw $ enclosed (char '|') (char '|') inline state <- getState let substTable = stateSubstitutions state case M.lookup (toKey $ stripFirstAndLast ref) substTable of Nothing -> fail "no corresponding key" Just target -> return target note :: RSTParser Inlines note = try $ do ref <- noteMarker char '_' state <- getState let notes = stateNotes state case lookup ref notes of Nothing -> fail "note not found" Just raw -> do -- We temporarily empty the note list while parsing the note, -- so that we don't get infinite loops with notes inside notes... -- Note references inside other notes are allowed in reST, but -- not yet in this implementation. updateState $ \st -> st{ stateNotes = [] } contents <- parseFromString parseBlocks raw let newnotes = if (ref == "*" || ref == "#") -- auto-numbered -- delete the note so the next auto-numbered note -- doesn't get the same contents: then deleteFirstsBy (==) notes [(ref,raw)] else notes updateState $ \st -> st{ stateNotes = newnotes } return $ B.note contents smart :: RSTParser Inlines smart = do getOption readerSmart >>= guard doubleQuoted <|> singleQuoted <|> choice (map (B.singleton <$>) [apostrophe, dash, ellipses]) singleQuoted :: RSTParser Inlines singleQuoted = try $ do singleQuoteStart withQuoteContext InSingleQuote $ B.singleQuoted . trimInlines . mconcat <$> many1Till inline singleQuoteEnd doubleQuoted :: RSTParser Inlines doubleQuoted = try $ do doubleQuoteStart withQuoteContext InDoubleQuote $ B.doubleQuoted . trimInlines . mconcat <$> many1Till inline doubleQuoteEnd �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/TeXMath.hs��������������������������������������������������000644 �000765 �000024 �00000004447 12251233602 021277� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2007-2010 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.TeXMath Copyright : Copyright (C) 2007-2010 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable Conversion of TeX math to a list of 'Pandoc' inline elements. -} 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 @$@ 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 = readTeXMath' InlineMath �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/Textile.hs��������������������������������������������������000644 �000765 �000024 �00000050727 12251233602 021405� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{- Copyright (C) 2010 Paul Rivier <paul*rivier#demotera*com> | tr '*#' '.@' This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.Textile Copyright : Copyright (C) 2010-2012 Paul Rivier and John MacFarlane License : GNU GPL, version 2 or above Maintainer : Paul Rivier <paul*rivier#demotera*com> Stability : alpha Portability : portable Conversion from Textile to 'Pandoc' document, based on the spec available at http://redcloth.org/textile. Implemented and parsed: - Paragraphs - Code blocks - Lists - blockquote - Inlines : strong, emph, cite, code, deleted, superscript, subscript, links - footnotes - HTML-specific and CSS-specific attributes on headers Left to be implemented: - dimension sign - all caps - continued blocks (ex bq..) TODO : refactor common patterns across readers : - more ... -} module Text.Pandoc.Readers.Textile ( readTextile) where import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Shared import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Readers.HTML ( htmlTag, isInlineTag, isBlockTag ) import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock ) import Text.HTML.TagSoup (parseTags, innerText, fromAttrib, Tag(..)) import Text.HTML.TagSoup.Match import Data.List ( intercalate ) import Data.Char ( digitToInt, isUpper ) import Control.Monad ( guard, liftM ) import Control.Applicative ((<$>), (*>), (<*)) -- | Parse a Textile text and return a Pandoc document. readTextile :: ReaderOptions -- ^ Reader options -> String -- ^ String to parse (assuming @'\n'@ line endings) -> Pandoc readTextile opts s = (readWith parseTextile) def{ stateOptions = opts } (s ++ "\n\n") -- | Generate a Pandoc ADT from a textile document parseTextile :: Parser [Char] ParserState Pandoc parseTextile = do -- textile allows raw HTML and does smart punctuation by default oldOpts <- stateOptions `fmap` getState updateState $ \state -> state{ stateOptions = oldOpts{ readerSmart = True , readerParseRaw = True , readerOldDashes = True } } many blankline startPos <- getPosition -- go through once just to get list of reference keys and notes -- docMinusKeys is the raw document with blanks where the keys/notes were... let firstPassParser = noteBlock <|> lineClump manyTill firstPassParser eof >>= setInput . concat setPosition startPos st' <- getState let reversedNotes = stateNotes st' updateState $ \s -> s { stateNotes = reverse reversedNotes } -- now parse it for real... blocks <- parseBlocks return $ Pandoc nullMeta blocks -- FIXME noteMarker :: Parser [Char] ParserState [Char] noteMarker = skipMany spaceChar >> string "fn" >> manyTill digit (char '.') noteBlock :: Parser [Char] ParserState [Char] noteBlock = try $ do startPos <- getPosition ref <- noteMarker optional blankline contents <- liftM unlines $ many1Till anyLine (blanklines <|> noteBlock) endPos <- getPosition let newnote = (ref, contents ++ "\n") st <- getState let oldnotes = stateNotes st updateState $ \s -> s { stateNotes = newnote : oldnotes } -- return blanks so line count isn't affected return $ replicate (sourceLine endPos - sourceLine startPos) '\n' -- | Parse document blocks parseBlocks :: Parser [Char] ParserState [Block] parseBlocks = manyTill block eof -- | Block parsers list tried in definition order blockParsers :: [Parser [Char] ParserState Block] blockParsers = [ codeBlock , header , blockQuote , hrule , commentBlock , anyList , rawHtmlBlock , rawLaTeXBlock' , maybeExplicitBlock "table" table , maybeExplicitBlock "p" para ] -- | Any block in the order of definition of blockParsers block :: Parser [Char] ParserState Block block = choice blockParsers <?> "block" commentBlock :: Parser [Char] ParserState Block commentBlock = try $ do string "###." manyTill anyLine blanklines return Null codeBlock :: Parser [Char] ParserState Block codeBlock = codeBlockBc <|> codeBlockPre codeBlockBc :: Parser [Char] ParserState Block codeBlockBc = try $ do string "bc. " contents <- manyTill anyLine blanklines return $ CodeBlock ("",[],[]) $ unlines contents -- | Code Blocks in Textile are between <pre> and </pre> codeBlockPre :: Parser [Char] ParserState Block codeBlockPre = try $ do (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True)) result' <- (innerText . parseTags) `fmap` -- remove internal tags manyTill anyChar (htmlTag (tagClose (=="pre"))) optional blanklines -- drop leading newline if any let result'' = case result' of '\n':xs -> xs _ -> result' -- drop trailing newline if any let result''' = case reverse result'' of '\n':_ -> init result'' _ -> result'' let classes = words $ fromAttrib "class" t let ident = fromAttrib "id" t let kvs = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"] return $ CodeBlock (ident,classes,kvs) result''' -- | Header of the form "hN. content" with N in 1..6 header :: Parser [Char] ParserState Block header = try $ do char 'h' level <- digitToInt <$> oneOf "123456" attr <- attributes char '.' whitespace name <- normalizeSpaces <$> manyTill inline blockBreak attr' <- registerHeader attr (B.fromList name) return $ Header level attr' name -- | Blockquote of the form "bq. content" blockQuote :: Parser [Char] ParserState Block blockQuote = try $ do string "bq" >> attributes >> char '.' >> whitespace BlockQuote . singleton <$> para -- Horizontal rule hrule :: Parser [Char] st Block hrule = try $ do skipSpaces start <- oneOf "-*" count 2 (skipSpaces >> char start) skipMany (spaceChar <|> char start) newline optional blanklines return HorizontalRule -- Lists handling -- | Can be a bullet list or an ordered list. This implementation is -- strict in the nesting, sublist must start at exactly "parent depth -- plus one" anyList :: Parser [Char] ParserState Block anyList = try $ anyListAtDepth 1 <* blanklines -- | This allow one type of list to be nested into an other type, -- provided correct nesting anyListAtDepth :: Int -> Parser [Char] ParserState Block anyListAtDepth depth = choice [ bulletListAtDepth depth, orderedListAtDepth depth, definitionList ] -- | Bullet List of given depth, depth being the number of leading '*' bulletListAtDepth :: Int -> Parser [Char] ParserState Block bulletListAtDepth depth = try $ BulletList <$> many1 (bulletListItemAtDepth depth) -- | Bullet List Item of given depth, depth being the number of -- leading '*' bulletListItemAtDepth :: Int -> Parser [Char] ParserState [Block] bulletListItemAtDepth = genericListItemAtDepth '*' -- | Ordered List of given depth, depth being the number of -- leading '#' orderedListAtDepth :: Int -> Parser [Char] ParserState Block orderedListAtDepth depth = try $ do items <- many1 (orderedListItemAtDepth depth) return (OrderedList (1, DefaultStyle, DefaultDelim) items) -- | Ordered List Item of given depth, depth being the number of -- leading '#' orderedListItemAtDepth :: Int -> Parser [Char] ParserState [Block] orderedListItemAtDepth = genericListItemAtDepth '#' -- | Common implementation of list items genericListItemAtDepth :: Char -> Int -> Parser [Char] ParserState [Block] genericListItemAtDepth c depth = try $ do count depth (char c) >> attributes >> whitespace p <- many listInline newline sublist <- option [] (singleton <$> anyListAtDepth (depth + 1)) return (Plain p : sublist) -- | A definition list is a set of consecutive definition items definitionList :: Parser [Char] ParserState Block definitionList = try $ DefinitionList <$> many1 definitionListItem -- | List start character. listStart :: Parser [Char] st Char listStart = oneOf "*#-" listInline :: Parser [Char] ParserState Inline listInline = try (notFollowedBy newline >> inline) <|> try (endline <* notFollowedBy listStart) -- | A definition list item in textile begins with '- ', followed by -- the term defined, then spaces and ":=". The definition follows, on -- the same single line, or spaned on multiple line, after a line -- break. definitionListItem :: Parser [Char] ParserState ([Inline], [[Block]]) definitionListItem = try $ do string "- " term <- many1Till inline (try (whitespace >> string ":=")) def' <- multilineDef <|> inlineDef return (term, def') where inlineDef :: Parser [Char] ParserState [[Block]] inlineDef = liftM (\d -> [[Plain d]]) $ optional whitespace >> many listInline <* newline multilineDef :: Parser [Char] ParserState [[Block]] multilineDef = try $ do optional whitespace >> newline s <- many1Till anyChar (try (string "=:" >> newline)) -- this ++ "\n\n" does not look very good ds <- parseFromString parseBlocks (s ++ "\n\n") return [ds] -- | This terminates a block such as a paragraph. Because of raw html -- blocks support, we have to lookAhead for a rawHtmlBlock. blockBreak :: Parser [Char] ParserState () blockBreak = try (newline >> blanklines >> return ()) <|> try (optional spaces >> lookAhead rawHtmlBlock >> return ()) -- raw content -- | A raw Html Block, optionally followed by blanklines rawHtmlBlock :: Parser [Char] ParserState Block rawHtmlBlock = try $ do (_,b) <- htmlTag isBlockTag optional blanklines return $ RawBlock (Format "html") b -- | Raw block of LaTeX content rawLaTeXBlock' :: Parser [Char] ParserState Block rawLaTeXBlock' = do guardEnabled Ext_raw_tex RawBlock (Format "latex") <$> (rawLaTeXBlock <* spaces) -- | In textile, paragraphs are separated by blank lines. para :: Parser [Char] ParserState Block para = try $ Para . normalizeSpaces <$> manyTill inline blockBreak -- Tables -- | A table cell spans until a pipe | tableCell :: Parser [Char] ParserState TableCell tableCell = do c <- many1 (noneOf "|\n") content <- parseFromString (many1 inline) c return $ [ Plain $ normalizeSpaces content ] -- | A table row is made of many table cells tableRow :: Parser [Char] ParserState [TableCell] tableRow = try $ ( char '|' *> (endBy1 tableCell (optional blankline *> char '|')) <* newline) -- | Many table rows tableRows :: Parser [Char] ParserState [[TableCell]] tableRows = many1 tableRow -- | Table headers are made of cells separated by a tag "|_." tableHeaders :: Parser [Char] ParserState [TableCell] tableHeaders = let separator = (try $ string "|_.") in try $ ( separator *> (sepBy1 tableCell separator) <* char '|' <* newline ) -- | A table with an optional header. Current implementation can -- handle tables with and without header, but will parse cells -- alignment attributes as content. table :: Parser [Char] ParserState Block table = try $ do headers <- option [] tableHeaders rows <- tableRows blanklines let nbOfCols = max (length headers) (length $ head rows) return $ Table [] (replicate nbOfCols AlignDefault) (replicate nbOfCols 0.0) headers rows -- | Blocks like 'p' and 'table' do not need explicit block tag. -- However, they can be used to set HTML/CSS attributes when needed. maybeExplicitBlock :: String -- ^ block tag name -> Parser [Char] ParserState Block -- ^ implicit block -> Parser [Char] ParserState Block maybeExplicitBlock name blk = try $ do optional $ try $ string name >> attributes >> char '.' >> optional whitespace >> optional endline blk ---------- -- Inlines ---------- -- | Any inline element inline :: Parser [Char] ParserState Inline inline = choice inlineParsers <?> "inline" -- | Inline parsers tried in order inlineParsers :: [Parser [Char] ParserState Inline] inlineParsers = [ str , whitespace , endline , code , escapedInline , htmlSpan , rawHtmlInline , rawLaTeXInline' , note , try $ (char '[' *> inlineMarkup <* char ']') , inlineMarkup , link , image , mark , (Str . (:[])) <$> characterReference , smartPunctuation inline , symbol ] -- | Inline markups inlineMarkup :: Parser [Char] ParserState Inline inlineMarkup = choice [ simpleInline (string "??") (Cite []) , simpleInline (string "**") Strong , simpleInline (string "__") Emph , simpleInline (char '*') Strong , simpleInline (char '_') Emph , simpleInline (char '+') Emph -- approximates underline , simpleInline (char '-' <* notFollowedBy (char '-')) Strikeout , simpleInline (char '^') Superscript , simpleInline (char '~') Subscript ] -- | Trademark, registered, copyright mark :: Parser [Char] st Inline mark = try $ char '(' >> (try tm <|> try reg <|> copy) reg :: Parser [Char] st Inline reg = do oneOf "Rr" char ')' return $ Str "\174" tm :: Parser [Char] st Inline tm = do oneOf "Tt" oneOf "Mm" char ')' return $ Str "\8482" copy :: Parser [Char] st Inline copy = do oneOf "Cc" char ')' return $ Str "\169" note :: Parser [Char] ParserState Inline note = try $ do ref <- (char '[' *> many1 digit <* char ']') notes <- stateNotes <$> getState case lookup ref notes of Nothing -> fail "note not found" Just raw -> liftM Note $ parseFromString parseBlocks raw -- | Special chars markupChars :: [Char] markupChars = "\\*#_@~-+^|%=[]&" -- | Break strings on following chars. Space tab and newline break for -- inlines breaking. Open paren breaks for mark. Quote, dash and dot -- break for smart punctuation. Punctuation breaks for regular -- punctuation. Double quote breaks for named links. > and < break -- for inline html. stringBreakers :: [Char] stringBreakers = " \t\n\r.,\"'?!;:<>«»„“”‚‘’()[]" wordBoundaries :: [Char] wordBoundaries = markupChars ++ stringBreakers -- | Parse a hyphened sequence of words hyphenedWords :: Parser [Char] ParserState String hyphenedWords = do x <- wordChunk xs <- many (try $ char '-' >> wordChunk) return $ intercalate "-" (x:xs) wordChunk :: Parser [Char] ParserState String wordChunk = try $ do hd <- noneOf wordBoundaries tl <- many ( (noneOf wordBoundaries) <|> try (notFollowedBy' note *> oneOf markupChars <* lookAhead (noneOf wordBoundaries) ) ) return $ hd:tl -- | Any string str :: Parser [Char] ParserState Inline str = do baseStr <- hyphenedWords -- RedCloth compliance : if parsed word is uppercase and immediatly -- followed by parens, parens content is unconditionally word acronym fullStr <- option baseStr $ try $ do guard $ all isUpper baseStr acro <- enclosed (char '(') (char ')') anyChar return $ concat [baseStr, " (", acro, ")"] updateLastStrPos return $ Str fullStr -- | Textile allows HTML span infos, we discard them htmlSpan :: Parser [Char] ParserState Inline htmlSpan = try $ Str <$> ( char '%' *> attributes *> manyTill anyChar (char '%') ) -- | Some number of space chars whitespace :: Parser [Char] ParserState Inline whitespace = many1 spaceChar >> return Space <?> "whitespace" -- | In Textile, an isolated endline character is a line break endline :: Parser [Char] ParserState Inline endline = try $ do newline >> notFollowedBy blankline return LineBreak rawHtmlInline :: Parser [Char] ParserState Inline rawHtmlInline = RawInline (Format "html") . snd <$> htmlTag isInlineTag -- | Raw LaTeX Inline rawLaTeXInline' :: Parser [Char] ParserState Inline rawLaTeXInline' = try $ do guardEnabled Ext_raw_tex rawLaTeXInline -- | Textile standard link syntax is "label":target. But we -- can also have ["label":target]. link :: Parser [Char] ParserState Inline link = linkB <|> linkNoB linkNoB :: Parser [Char] ParserState Inline linkNoB = try $ do name <- surrounded (char '"') inline char ':' let stopChars = "!.,;:" url <- manyTill nonspaceChar (lookAhead $ space <|> try (oneOf stopChars >> (space <|> newline))) let name' = if name == [Str "$"] then [Str url] else name return $ Link name' (url, "") linkB :: Parser [Char] ParserState Inline linkB = try $ do char '[' name <- surrounded (char '"') inline char ':' url <- manyTill nonspaceChar (char ']') let name' = if name == [Str "$"] then [Str url] else name return $ Link name' (url, "") -- | image embedding image :: Parser [Char] ParserState Inline image = try $ do char '!' >> notFollowedBy space src <- manyTill anyChar (lookAhead $ oneOf "!(") alt <- option "" (try $ (char '(' >> manyTill anyChar (char ')'))) char '!' return $ Image [Str alt] (src, alt) escapedInline :: Parser [Char] ParserState Inline escapedInline = escapedEqs <|> escapedTag escapedEqs :: Parser [Char] ParserState Inline escapedEqs = Str <$> (try $ string "==" *> manyTill anyChar (try $ string "==")) -- | literal text escaped btw <notextile> tags escapedTag :: Parser [Char] ParserState Inline escapedTag = Str <$> (try $ string "<notextile>" *> manyTill anyChar (try $ string "</notextile>")) -- | Any special symbol defined in wordBoundaries symbol :: Parser [Char] ParserState Inline symbol = Str . singleton <$> (oneOf wordBoundaries <|> oneOf markupChars) -- | Inline code code :: Parser [Char] ParserState Inline code = code1 <|> code2 code1 :: Parser [Char] ParserState Inline code1 = Code nullAttr <$> surrounded (char '@') anyChar code2 :: Parser [Char] ParserState Inline code2 = do htmlTag (tagOpen (=="tt") null) Code nullAttr <$> manyTill anyChar (try $ htmlTag $ tagClose (=="tt")) -- | Html / CSS attributes attributes :: Parser [Char] ParserState Attr attributes = (foldl (flip ($)) ("",[],[])) `fmap` many attribute attribute :: Parser [Char] ParserState (Attr -> Attr) attribute = classIdAttr <|> styleAttr <|> langAttr classIdAttr :: Parser [Char] ParserState (Attr -> Attr) classIdAttr = try $ do -- (class class #id) char '(' ws <- words `fmap` manyTill anyChar (char ')') case reverse ws of [] -> return $ \(_,_,keyvals) -> ("",[],keyvals) (('#':ident'):classes') -> return $ \(_,_,keyvals) -> (ident',classes',keyvals) classes' -> return $ \(_,_,keyvals) -> ("",classes',keyvals) styleAttr :: Parser [Char] ParserState (Attr -> Attr) styleAttr = do style <- try $ enclosed (char '{') (char '}') anyChar return $ \(id',classes,keyvals) -> (id',classes,("style",style):keyvals) langAttr :: Parser [Char] ParserState (Attr -> Attr) langAttr = do lang <- try $ enclosed (char '[') (char ']') anyChar return $ \(id',classes,keyvals) -> (id',classes,("lang",lang):keyvals) -- | Parses material surrounded by a parser. surrounded :: Parser [Char] st t -- ^ surrounding parser -> Parser [Char] st a -- ^ content parser (to be used repeatedly) -> Parser [Char] st [a] surrounded border = enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border) -- | Inlines are most of the time of the same form 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) >>= return . construct . normalizeSpaces where inlineWithAttribute = (try $ optional attributes) >> inline -- | Create a singleton list singleton :: a -> [a] singleton x = [x] �����������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/Haddock/Lex.x�����������������������������������������������000644 �000765 �000024 �00000012653 12251233602 021705� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������-- -- Haddock - A Haskell Documentation Tool -- -- (c) Simon Marlow 2002 -- -- This file was modified and integrated into GHC by David Waern 2006. -- Then moved back into Haddock by Isaac Dupree in 2009 :-) -- Then copied into Pandoc by David Lazar in 2013 :-D { {-# LANGUAGE BangPatterns #-} -- Generated by Alex {-# OPTIONS -Wwarn -w #-} -- The above warning supression flag is a temporary kludge. -- While working on this module you are encouraged to remove it and fix -- any warnings in the module. See -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings -- for details module Text.Pandoc.Readers.Haddock.Lex ( Token(..), LToken, tokenise, tokenPos ) where import Data.Char import Numeric (readHex) } %wrapper "posn" $ws = $white # \n $digit = [0-9] $hexdigit = [0-9a-fA-F] $special = [\"\@] $alphanum = [A-Za-z0-9] $ident = [$alphanum \'\_\.\!\#\$\%\&\*\+\/\<\=\>\?\@\\\\\^\|\-\~\:] :- -- beginning of a paragraph <0,para> { $ws* \n ; $ws* \> { begin birdtrack } $ws* prop \> .* \n { strtoken TokProperty `andBegin` property} $ws* \>\>\> { strtoken TokExamplePrompt `andBegin` exampleexpr } $ws* [\*\-] { token TokBullet `andBegin` string } $ws* \[ { token TokDefStart `andBegin` def } $ws* \( $digit+ \) { token TokNumber `andBegin` string } $ws* $digit+ \. { token TokNumber `andBegin` string } $ws* { begin string } } -- beginning of a line <line> { $ws* \> { begin birdtrack } $ws* \>\>\> { strtoken TokExamplePrompt `andBegin` exampleexpr } $ws* \n { token TokPara `andBegin` para } -- ^ Here, we really want to be able to say -- $ws* (\n | <eof>) { token TokPara `andBegin` para} -- because otherwise a trailing line of whitespace will result in -- a spurious TokString at the end of a docstring. We don't have <eof>, -- though (NOW I realise what it was for :-). To get around this, we always -- append \n to the end of a docstring. () { begin string } } <birdtrack> .* \n? { strtokenNL TokBirdTrack `andBegin` line } <property> () { token TokPara `andBegin` para } <example> { $ws* \n { token TokPara `andBegin` para } $ws* \>\>\> { strtoken TokExamplePrompt `andBegin` exampleexpr } () { begin exampleresult } } <exampleexpr> .* \n { strtokenNL TokExampleExpression `andBegin` example } <exampleresult> .* \n { strtokenNL TokExampleResult `andBegin` example } <string,def> { $special { strtoken $ \s -> TokSpecial (head s) } \<\< [^\>]* \>\> { strtoken $ \s -> TokPic (init $ init $ tail $ tail s) } \< [^\>]* \> { strtoken $ \s -> TokURL (init (tail s)) } \# [^\#]* \# { strtoken $ \s -> TokAName (init (tail s)) } \/ [^\/]* \/ { strtoken $ \s -> TokEmphasis (init (tail s)) } [\'\`] $ident+ [\'\`] { strtoken $ \s -> TokIdent (init (tail s)) } \\ . { strtoken (TokString . tail) } "&#" $digit+ \; { strtoken $ \s -> TokString [chr (read (init (drop 2 s)))] } "&#" [xX] $hexdigit+ \; { strtoken $ \s -> case readHex (init (drop 3 s)) of [(n,_)] -> TokString [chr n] } -- allow special characters through if they don't fit one of the previous -- patterns. [\/\'\`\<\#\&\\] { strtoken TokString } [^ $special \/ \< \# \n \'\` \& \\ \]]* \n { strtokenNL TokString `andBegin` line } [^ $special \/ \< \# \n \'\` \& \\ \]]+ { strtoken TokString } } <def> { \] { token TokDefEnd `andBegin` string } } -- ']' doesn't have any special meaning outside of the [...] at the beginning -- of a definition paragraph. <string> { \] { strtoken TokString } } { -- | A located token type LToken = (Token, AlexPosn) data Token = TokPara | TokNumber | TokBullet | TokDefStart | TokDefEnd | TokSpecial Char | TokIdent String | TokString String | TokURL String | TokPic String | TokEmphasis String | TokAName String | TokBirdTrack String | TokProperty String | TokExamplePrompt String | TokExampleExpression String | TokExampleResult String deriving Show tokenPos :: LToken -> (Int, Int) tokenPos t = let AlexPn _ line col = snd t in (line, col) type StartCode = Int type Action = AlexPosn -> String -> StartCode -> (StartCode -> [LToken]) -> [LToken] tokenise :: String -> (Int, Int) -> [LToken] tokenise str (line, col) = go (posn,'\n',[],eofHack str) para where posn = AlexPn 0 line col go inp@(pos,_,_,str) sc = case alexScan inp sc of AlexEOF -> [] AlexError _ -> [] AlexSkip inp' len -> go inp' sc AlexToken inp' len act -> act pos (take len str) sc (\sc -> go inp' sc) -- NB. we add a final \n to the string, (see comment in the beginning of line -- production above). eofHack str = str++"\n" andBegin :: Action -> StartCode -> Action andBegin act new_sc = \pos str _ cont -> act pos str new_sc cont token :: Token -> Action token t = \pos _ sc cont -> (t, pos) : cont sc strtoken, strtokenNL :: (String -> Token) -> Action strtoken t = \pos str sc cont -> (t str, pos) : cont sc strtokenNL t = \pos str sc cont -> (t (filter (/= '\r') str), pos) : cont sc -- ^ We only want LF line endings in our internal doc string format, so we -- filter out all CRs. begin :: StartCode -> Action begin sc = \_ _ _ cont -> cont sc } �������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Readers/Haddock/Parse.y���������������������������������������������000644 �000765 �000024 �00000012310 12251233602 022216� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������-- This code was copied from the 'haddock' package, modified, and integrated -- into Pandoc by David Lazar. { {-# LANGUAGE BangPatterns #-} -- required for versions of Happy before 1.18.6 -- The above warning supression flag is a temporary kludge. -- While working on this module you are encouraged to remove it and fix -- any warnings in the module. See -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings -- for details module Text.Pandoc.Readers.Haddock.Parse (parseString, parseParas) where import Text.Pandoc.Readers.Haddock.Lex import Text.Pandoc.Builder import Text.Pandoc.Shared (trim, trimr) import Data.Generics (everywhere, mkT) import Data.Char (isSpace) import Data.Maybe (fromMaybe) import Data.List (stripPrefix, intersperse) import Data.Monoid (mempty, mconcat) } %expect 0 %tokentype { LToken } %token '/' { (TokSpecial '/',_) } '@' { (TokSpecial '@',_) } '[' { (TokDefStart,_) } ']' { (TokDefEnd,_) } DQUO { (TokSpecial '\"',_) } URL { (TokURL $$,_) } PIC { (TokPic $$,_) } ANAME { (TokAName $$,_) } '/../' { (TokEmphasis $$,_) } '-' { (TokBullet,_) } '(n)' { (TokNumber,_) } '>..' { (TokBirdTrack $$,_) } PROP { (TokProperty $$,_) } PROMPT { (TokExamplePrompt $$,_) } RESULT { (TokExampleResult $$,_) } EXP { (TokExampleExpression $$,_) } IDENT { (TokIdent $$,_) } PARA { (TokPara,_) } STRING { (TokString $$,_) } %monad { Either [LToken] } %name parseParas doc %name parseString seq %% doc :: { Blocks } : apara PARA doc { $1 <> $3 } | PARA doc { $2 } | apara { $1 } | {- empty -} { mempty } apara :: { Blocks } : ulpara { bulletList [$1] } | olpara { orderedList [$1] } | defpara { definitionList [$1] } | para { $1 } ulpara :: { Blocks } : '-' para { $2 } olpara :: { Blocks } : '(n)' para { $2 } defpara :: { (Inlines, [Blocks]) } : '[' seq ']' seq { (trimInlines $2, [plain $ trimInlines $4]) } para :: { Blocks } : seq { para' $1 } | codepara { codeBlockWith ([], ["haskell"], []) $1 } | property { $1 } | examples { $1 } codepara :: { String } : '>..' codepara { $1 ++ $2 } | '>..' { $1 } property :: { Blocks } : PROP { makeProperty $1 } examples :: { Blocks } : example examples { $1 <> $2 } | example { $1 } example :: { Blocks } : PROMPT EXP result { makeExample $1 $2 (lines $3) } | PROMPT EXP { makeExample $1 $2 [] } result :: { String } : RESULT result { $1 ++ $2 } | RESULT { $1 } seq :: { Inlines } : elem seq { $1 <> $2 } | elem { $1 } elem :: { Inlines } : elem1 { $1 } | '@' seq1 '@' { monospace $2 } seq1 :: { Inlines } : PARA seq1 { linebreak <> $2 } | elem1 seq1 { $1 <> $2 } | elem1 { $1 } elem1 :: { Inlines } : STRING { text $1 } | '/../' { emph (str $1) } | URL { makeHyperlink $1 } | PIC { image $1 $1 mempty } | ANAME { mempty } -- TODO | IDENT { codeWith ([], ["haskell"], []) $1 } | DQUO strings DQUO { codeWith ([], ["haskell"], []) $2 } strings :: { String } : STRING { $1 } | STRING strings { $1 ++ $2 } { happyError :: [LToken] -> Either [LToken] a happyError toks = Left toks para' :: Inlines -> Blocks para' = para . trimInlines monospace :: Inlines -> Inlines monospace = everywhere (mkT go) where go (Str s) = Code nullAttr s go x = x -- | Create a `Hyperlink` from given string. -- -- A hyperlink consists of a URL and an optional label. The label is separated -- from the url by one or more whitespace characters. makeHyperlink :: String -> Inlines makeHyperlink input = case break isSpace $ trim input of (url, "") -> link url url (str url) (url, lb) -> link url url (trimInlines $ text lb) makeProperty :: String -> Blocks makeProperty s = case trim s of 'p':'r':'o':'p':'>':xs -> codeBlockWith ([], ["property"], []) (dropWhile isSpace xs) xs -> error $ "makeProperty: invalid input " ++ show xs -- | Create an 'Example', stripping superfluous characters as appropriate makeExample :: String -> String -> [String] -> Blocks makeExample prompt expression result = para $ codeWith ([], ["haskell","expr"], []) (trim expression) <> linebreak <> (mconcat $ intersperse linebreak $ map coder result') where -- 1. drop trailing whitespace from the prompt, remember the prefix prefix = takeWhile isSpace prompt -- 2. drop, if possible, the exact same sequence of whitespace -- characters from each result line -- -- 3. interpret lines that only contain the string "<BLANKLINE>" as an -- empty line result' = map (substituteBlankLine . tryStripPrefix prefix) result where tryStripPrefix xs ys = fromMaybe ys $ stripPrefix xs ys substituteBlankLine "<BLANKLINE>" = "" substituteBlankLine line = line coder = codeWith ([], ["result"], []) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Compat/Monoid.hs����������������������������������������������������000644 �000765 �000024 �00000000645 12251233602 021044� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE CPP #-} module Text.Pandoc.Compat.Monoid ( Monoid(..) , (<>) ) where #if MIN_VERSION_base(4,5,0) import Data.Monoid ((<>), Monoid(..)) #else import Data.Monoid (mappend, Monoid(..)) #endif #if MIN_VERSION_base(4,5,0) #else infixr 6 <> -- | An infix synonym for 'mappend'. (<>) :: Monoid m => m -> m -> m (<>) = mappend {-# INLINE (<>) #-} #endif �������������������������������������������������������������������������������������������pandoc-1.12.2.1/src/Text/Pandoc/Compat/TagSoupEntity.hs���������������������������������������������000644 �000765 �000024 �00000000647 12251233602 022400� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE CPP #-} module Text.Pandoc.Compat.TagSoupEntity (lookupEntity ) where import qualified Text.HTML.TagSoup.Entity as TE lookupEntity :: String -> Maybe Char #if MIN_VERSION_tagsoup(0,13,0) lookupEntity = str2chr . TE.lookupEntity where str2chr :: Maybe String -> Maybe Char str2chr (Just [c]) = Just c str2chr _ = Nothing #else lookupEntity = TE.lookupEntity #endif �����������������������������������������������������������������������������������������pandoc-1.12.2.1/man/make-pandoc-man-pages.hs��������������������������������������������������������000644 �000765 �000024 �00000007322 12251233602 020254� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������{-# LANGUAGE CPP #-} -- Create pandoc.1 man and pandoc_markdown.5 man pages from README import Text.Pandoc import qualified Text.Pandoc.UTF8 as UTF8 import Data.Char (toUpper) import Control.Monad import System.FilePath import System.Environment (getArgs) import Text.Pandoc.Shared (normalize) import Data.Maybe ( catMaybes ) import Prelude hiding (catch) import Control.Exception ( catch ) import System.IO.Error ( isDoesNotExistError ) #if MIN_VERSION_directory(1,2,0) import Data.Time.Clock (UTCTime(..)) #else import System.Time (ClockTime(..)) #endif import System.Directory main :: IO () main = do ds1 <- modifiedDependencies ("man" </> "man1" </> "pandoc.1") ["README", "man" </> "man1" </> "pandoc.1.template"] ds2 <- modifiedDependencies ("man" </> "man5" </> "pandoc_markdown.5") ["README", "man" </> "man5" </> "pandoc_markdown.5.template"] unless (null ds1 && null ds2) $ do rmContents <- UTF8.readFile "README" let (Pandoc meta blocks) = readMarkdown def rmContents let manBlocks = removeSect [Str "Wrappers"] $ removeSect [Str "Pandoc's",Space,Str "markdown"] blocks let syntaxBlocks = extractSect [Str "Pandoc's",Space,Str "markdown"] blocks args <- getArgs let verbose = "--verbose" `elem` args unless (null ds1) $ makeManPage verbose ("man" </> "man1" </> "pandoc.1") meta manBlocks unless (null ds2) $ makeManPage verbose ("man" </> "man5" </> "pandoc_markdown.5") meta syntaxBlocks makeManPage :: Bool -> FilePath -> Meta -> [Block] -> IO () makeManPage verbose page meta blocks = do let templ = page <.> "template" manTemplate <- UTF8.readFile templ writeManPage page manTemplate (Pandoc meta blocks) when verbose $ putStrLn $ "Created " ++ page writeManPage :: FilePath -> String -> Pandoc -> IO () writeManPage page templ doc = do let opts = def{ writerStandalone = True , writerTemplate = templ } let manPage = writeMan opts $ bottomUp (concatMap removeLinks) $ bottomUp capitalizeHeaders doc UTF8.writeFile page manPage removeLinks :: Inline -> [Inline] removeLinks (Link l _) = l removeLinks x = [x] capitalizeHeaders :: Block -> Block capitalizeHeaders (Header 1 attr xs) = Header 1 attr $ bottomUp capitalize xs capitalizeHeaders x = x capitalize :: Inline -> Inline capitalize (Str xs) = Str $ map toUpper xs capitalize x = x removeSect :: [Inline] -> [Block] -> [Block] removeSect ils (Header 1 _ x:xs) | normalize x == normalize ils = dropWhile (not . isHeader1) xs removeSect ils (x:xs) = x : removeSect ils xs removeSect _ [] = [] extractSect :: [Inline] -> [Block] -> [Block] extractSect ils (Header 1 _ z:xs) | normalize z == normalize ils = bottomUp promoteHeader $ takeWhile (not . isHeader1) xs where promoteHeader (Header n attr x) = Header (n-1) attr x promoteHeader x = x extractSect ils (x:xs) = extractSect ils xs extractSect _ [] = [] isHeader1 :: Block -> Bool isHeader1 (Header 1 _ _ ) = True isHeader1 _ = False -- | Returns a list of 'dependencies' that have been modified after 'file'. modifiedDependencies :: FilePath -> [FilePath] -> IO [FilePath] modifiedDependencies file dependencies = do fileModTime <- catch (getModificationTime file) $ \e -> if isDoesNotExistError e #if MIN_VERSION_directory(1,2,0) then return (UTCTime (toEnum 0) 0) -- the minimum ClockTime #else then return (TOD 0 0) -- the minimum ClockTime #endif else ioError e depModTimes <- mapM getModificationTime dependencies let modified = zipWith (\dep time -> if time > fileModTime then Just dep else Nothing) dependencies depModTimes return $ catMaybes modified ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/man/man1/���������������������������������������������������������������������������000755 �000765 �000024 �00000000000 12251233602 014523� 5����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/man/man5/���������������������������������������������������������������������������000755 �000765 �000024 �00000000000 12251233602 014527� 5����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/man/man5/pandoc_markdown.5����������������������������������������������������������000644 �000765 �000024 �00000172067 12251233602 020000� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\"t .TH PANDOC_MARKDOWN 5 "January 19, 2013" "Pandoc User\[aq]s Guide" .SH NAME pandoc_markdown - markdown syntax for pandoc(1) .SH DESCRIPTION .PP Pandoc understands an extended and slightly revised version of John Gruber\[aq]s markdown syntax. This document explains the syntax, noting differences from standard markdown. Except where noted, these differences can be suppressed by using the \f[C]markdown_strict\f[] format instead of \f[C]markdown\f[]. An extensions can be enabled by adding \f[C]+EXTENSION\f[] to the format name and disabled by adding \f[C]\-EXTENSION\f[]. For example, \f[C]markdown_strict+footnotes\f[] is strict markdown with footnotes enabled, while \f[C]markdown\-footnotes\-pipe_tables\f[] is pandoc\[aq]s markdown without footnotes or pipe tables. .SH PHILOSOPHY .PP Markdown is designed to be easy to write, and, even more importantly, easy to read: .RS .PP A Markdown\-formatted document should be publishable as\-is, as plain text, without looking like it\[aq]s been marked up with tags or formatting instructions. \-\- John Gruber .RE .PP This principle has guided pandoc\[aq]s decisions in finding syntax for tables, footnotes, and other extensions. .PP There is, however, one respect in which pandoc\[aq]s aims are different from the original aims of markdown. Whereas markdown was originally designed with HTML generation in mind, pandoc is designed for multiple output formats. Thus, while pandoc allows the embedding of raw HTML, it discourages it, and provides other, non\-HTMLish ways of representing important document elements like definition lists, tables, mathematics, and footnotes. .SH PARAGRAPHS .PP A paragraph is one or more lines of text followed by one or more blank line. Newlines are treated as spaces, so you can reflow your paragraphs as you like. If you need a hard line break, put two or more spaces at the end of a line. .PP \f[B]Extension: \f[C]escaped_line_breaks\f[]\f[] .PP A backslash followed by a newline is also a hard line break. .SH HEADERS .PP There are two kinds of headers, Setext and atx. .SS Setext\-style headers .PP A setext\-style header is a line of text "underlined" with a row of \f[C]=\f[] signs (for a level one header) or \f[C]\-\f[] signs (for a level two header): .IP .nf \f[C] A\ level\-one\ header ================== A\ level\-two\ header \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \f[] .fi .PP The header text can contain inline formatting, such as emphasis (see Inline formatting, below). .SS Atx\-style headers .PP An Atx\-style header consists of one to six \f[C]#\f[] signs and a line of text, optionally followed by any number of \f[C]#\f[] signs. The number of \f[C]#\f[] signs at the beginning of the line is the header level: .IP .nf \f[C] ##\ A\ level\-two\ header ###\ A\ level\-three\ header\ ### \f[] .fi .PP As with setext\-style headers, the header text can contain formatting: .IP .nf \f[C] #\ A\ level\-one\ header\ with\ a\ [link](/url)\ and\ *emphasis* \f[] .fi .PP \f[B]Extension: \f[C]blank_before_header\f[]\f[] .PP Standard markdown syntax does not require a blank line before a header. Pandoc does require this (except, of course, at the beginning of the document). The reason for the requirement is that it is all too easy for a \f[C]#\f[] to end up at the beginning of a line by accident (perhaps through line wrapping). Consider, for example: .IP .nf \f[C] I\ like\ several\ of\ their\ flavors\ of\ ice\ cream: #22,\ for\ example,\ and\ #5. \f[] .fi .SS Header identifiers in HTML, LaTeX, and ConTeXt .PP \f[B]Extension: \f[C]header_attributes\f[]\f[] .PP Headers can be assigned attributes using this syntax at the end of the line containing the header text: .IP .nf \f[C] {#identifier\ .class\ .class\ key=value\ key=value} \f[] .fi .PP Although this syntax allows assignment of classes and key/value attributes, only identifiers currently have any affect in the writers (and only in some writers: HTML, LaTeX, ConTeXt, Textile, AsciiDoc). Thus, for example, the following headers will all be assigned the identifier \f[C]foo\f[]: .IP .nf \f[C] #\ My\ header\ {#foo} ##\ My\ header\ ##\ \ \ \ {#foo} My\ other\ header\ \ \ {#foo} \-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \f[] .fi .PP (This syntax is compatible with PHP Markdown Extra.) .PP Headers with the class \f[C]unnumbered\f[] will not be numbered, even if \f[C]\-\-number\-sections\f[] is specified. A single hyphen (\f[C]\-\f[]) in an attribute context is equivalent to \f[C]\&.unnumbered\f[], and preferable in non\-English documents. So, .IP .nf \f[C] #\ My\ header\ {\-} \f[] .fi .PP is just the same as .IP .nf \f[C] #\ My\ header\ {.unnumbered} \f[] .fi .PP \f[B]Extension: \f[C]auto_identifiers\f[]\f[] .PP A header without an explicitly specified identifier will be automatically assigned a unique identifier based on the header text. To derive the identifier from the header text, .IP \[bu] 2 Remove all formatting, links, etc. .IP \[bu] 2 Remove all footnotes. .IP \[bu] 2 Remove all punctuation, except underscores, hyphens, and periods. .IP \[bu] 2 Replace all spaces and newlines with hyphens. .IP \[bu] 2 Convert all alphabetic characters to lowercase. .IP \[bu] 2 Remove everything up to the first letter (identifiers may not begin with a number or punctuation mark). .IP \[bu] 2 If nothing is left after this, use the identifier \f[C]section\f[]. .PP Thus, for example, .PP .TS tab(@); l l. T{ Header T}@T{ Identifier T} _ T{ Header identifiers in HTML T}@T{ \f[C]header\-identifiers\-in\-html\f[] T} T{ \f[I]Dogs\f[]?\-\-in \f[I]my\f[] house? T}@T{ \f[C]dogs\-\-in\-my\-house\f[] T} T{ HTML, S5, or RTF? T}@T{ \f[C]html\-s5\-or\-rtf\f[] T} T{ 3. Applications T}@T{ \f[C]applications\f[] T} T{ 33 T}@T{ \f[C]section\f[] T} .TE .PP These rules should, in most cases, allow one to determine the identifier from the header text. The exception is when several headers have the same text; in this case, the first will get an identifier as described above; the second will get the same identifier with \f[C]\-1\f[] appended; the third with \f[C]\-2\f[]; and so on. .PP These identifiers are used to provide link targets in the table of contents generated by the \f[C]\-\-toc|\-\-table\-of\-contents\f[] option. They also make it easy to provide links from one section of a document to another. A link to this section, for example, might look like this: .IP .nf \f[C] See\ the\ section\ on [header\ identifiers](#header\-identifiers\-in\-html\-latex\-and\-context). \f[] .fi .PP Note, however, that this method of providing links to sections works only in HTML, LaTeX, and ConTeXt formats. .PP If the \f[C]\-\-section\-divs\f[] option is specified, then each section will be wrapped in a \f[C]div\f[] (or a \f[C]section\f[], if \f[C]\-\-html5\f[] was specified), and the identifier will be attached to the enclosing \f[C]<div>\f[] (or \f[C]<section>\f[]) tag rather than the header itself. This allows entire sections to be manipulated using javascript or treated differently in CSS. .PP \f[B]Extension: \f[C]implicit_header_references\f[]\f[] .PP Pandoc behaves as if reference links have been defined for each header. So, instead of .IP .nf \f[C] [header\ identifiers](#header\-identifiers\-in\-html) \f[] .fi .PP you can simply write .IP .nf \f[C] [header\ identifiers] \f[] .fi .PP or .IP .nf \f[C] [header\ identifiers][] \f[] .fi .PP or .IP .nf \f[C] [the\ section\ on\ header\ identifiers][header\ identifiers] \f[] .fi .PP If there are multiple headers with identical text, the corresponding reference will link to the first one only, and you will need to use explicit links to link to the others, as described above. .PP Unlike regular reference links, these references are case\-sensitive. .PP Note: if you have defined an explicit identifier for a header, then implicit references to it will not work. .SH BLOCK QUOTATIONS .PP Markdown uses email conventions for quoting blocks of text. A block quotation is one or more paragraphs or other block elements (such as lists or headers), with each line preceded by a \f[C]>\f[] character and a space. (The \f[C]>\f[] need not start at the left margin, but it should not be indented more than three spaces.) .IP .nf \f[C] >\ This\ is\ a\ block\ quote.\ This >\ paragraph\ has\ two\ lines. > >\ 1.\ This\ is\ a\ list\ inside\ a\ block\ quote. >\ 2.\ Second\ item. \f[] .fi .PP A "lazy" form, which requires the \f[C]>\f[] character only on the first line of each block, is also allowed: .IP .nf \f[C] >\ This\ is\ a\ block\ quote.\ This paragraph\ has\ two\ lines. >\ 1.\ This\ is\ a\ list\ inside\ a\ block\ quote. 2.\ Second\ item. \f[] .fi .PP Among the block elements that can be contained in a block quote are other block quotes. That is, block quotes can be nested: .IP .nf \f[C] >\ This\ is\ a\ block\ quote. > >\ >\ A\ block\ quote\ within\ a\ block\ quote. \f[] .fi .PP \f[B]Extension: \f[C]blank_before_blockquote\f[]\f[] .PP Standard markdown syntax does not require a blank line before a block quote. Pandoc does require this (except, of course, at the beginning of the document). The reason for the requirement is that it is all too easy for a \f[C]>\f[] to end up at the beginning of a line by accident (perhaps through line wrapping). So, unless the \f[C]markdown_strict\f[] format is used, the following does not produce a nested block quote in pandoc: .IP .nf \f[C] >\ This\ is\ a\ block\ quote. >>\ Nested. \f[] .fi .SH VERBATIM (CODE) BLOCKS .SS Indented code blocks .PP A block of text indented four spaces (or one tab) is treated as verbatim text: that is, special characters do not trigger special formatting, and all spaces and line breaks are preserved. For example, .IP .nf \f[C] \ \ \ \ if\ (a\ >\ 3)\ { \ \ \ \ \ \ moveShip(5\ *\ gravity,\ DOWN); \ \ \ \ } \f[] .fi .PP The initial (four space or one tab) indentation is not considered part of the verbatim text, and is removed in the output. .PP Note: blank lines in the verbatim text need not begin with four spaces. .SS Fenced code blocks .PP \f[B]Extension: \f[C]fenced_code_blocks\f[]\f[] .PP In addition to standard indented code blocks, Pandoc supports \f[I]fenced\f[] code blocks. These begin with a row of three or more tildes (\f[C]~\f[]) or backticks (\f[C]`\f[]) and end with a row of tildes or backticks that must be at least as long as the starting row. Everything between these lines is treated as code. No indentation is necessary: .IP .nf \f[C] ~~~~~~~ if\ (a\ >\ 3)\ { \ \ moveShip(5\ *\ gravity,\ DOWN); } ~~~~~~~ \f[] .fi .PP Like regular code blocks, fenced code blocks must be separated from surrounding text by blank lines. .PP If the code itself contains a row of tildes or backticks, just use a longer row of tildes or backticks at the start and end: .IP .nf \f[C] ~~~~~~~~~~~~~~~~ ~~~~~~~~~~ code\ including\ tildes ~~~~~~~~~~ ~~~~~~~~~~~~~~~~ \f[] .fi .PP Optionally, you may attach attributes to the code block using this syntax: .IP .nf \f[C] ~~~~\ {#mycode\ .haskell\ .numberLines\ startFrom="100"} qsort\ []\ \ \ \ \ =\ [] qsort\ (x:xs)\ =\ qsort\ (filter\ (<\ x)\ xs)\ ++\ [x]\ ++ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ qsort\ (filter\ (>=\ x)\ xs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \f[] .fi .PP Here \f[C]mycode\f[] is an identifier, \f[C]haskell\f[] and \f[C]numberLines\f[] are classes, and \f[C]startFrom\f[] is an attribute with value \f[C]100\f[]. Some output formats can use this information to do syntax highlighting. Currently, the only output formats that uses this information are HTML and LaTeX. If highlighting is supported for your output format and language, then the code block above will appear highlighted, with numbered lines. (To see which languages are supported, do \f[C]pandoc\ \-\-version\f[].) Otherwise, the code block above will appear as follows: .IP .nf \f[C] <pre\ id="mycode"\ class="haskell\ numberLines"\ startFrom="100"> \ \ <code> \ \ ... \ \ </code> </pre> \f[] .fi .PP A shortcut form can also be used for specifying the language of the code block: .IP .nf \f[C] ```haskell qsort\ []\ =\ [] ``` \f[] .fi .PP This is equivalent to: .IP .nf \f[C] ```\ {.haskell} qsort\ []\ =\ [] ``` \f[] .fi .PP To prevent all highlighting, use the \f[C]\-\-no\-highlight\f[] flag. To set the highlighting style, use \f[C]\-\-highlight\-style\f[]. .SH LINE BLOCKS .PP \f[B]Extension: \f[C]line_blocks\f[]\f[] .PP A line block is a sequence of lines beginning with a vertical bar (\f[C]|\f[]) followed by a space. The division into lines will be preserved in the output, as will any leading spaces; otherwise, the lines will be formatted as markdown. This is useful for verse and addresses: .IP .nf \f[C] |\ The\ limerick\ packs\ laughs\ anatomical |\ In\ space\ that\ is\ quite\ economical. |\ \ \ \ But\ the\ good\ ones\ I\[aq]ve\ seen |\ \ \ \ So\ seldom\ are\ clean |\ And\ the\ clean\ ones\ so\ seldom\ are\ comical |\ 200\ Main\ St. |\ Berkeley,\ CA\ 94718 \f[] .fi .PP The lines can be hard\-wrapped if needed, but the continuation line must begin with a space. .IP .nf \f[C] |\ The\ Right\ Honorable\ Most\ Venerable\ and\ Righteous\ Samuel\ L. \ \ Constable,\ Jr. |\ 200\ Main\ St. |\ Berkeley,\ CA\ 94718 \f[] .fi .PP This syntax is borrowed from reStructuredText. .SH LISTS .SS Bullet lists .PP A bullet list is a list of bulleted list items. A bulleted list item begins with a bullet (\f[C]*\f[], \f[C]+\f[], or \f[C]\-\f[]). Here is a simple example: .IP .nf \f[C] *\ one *\ two *\ three \f[] .fi .PP This will produce a "compact" list. If you want a "loose" list, in which each item is formatted as a paragraph, put spaces between the items: .IP .nf \f[C] *\ one *\ two *\ three \f[] .fi .PP The bullets need not be flush with the left margin; they may be indented one, two, or three spaces. The bullet must be followed by whitespace. .PP List items look best if subsequent lines are flush with the first line (after the bullet): .IP .nf \f[C] *\ here\ is\ my\ first \ \ list\ item. *\ and\ my\ second. \f[] .fi .PP But markdown also allows a "lazy" format: .IP .nf \f[C] *\ here\ is\ my\ first list\ item. *\ and\ my\ second. \f[] .fi .SS The four\-space rule .PP A list item may contain multiple paragraphs and other block\-level content. However, subsequent paragraphs must be preceded by a blank line and indented four spaces or a tab. The list will look better if the first paragraph is aligned with the rest: .IP .nf \f[C] \ \ *\ First\ paragraph. \ \ \ \ Continued. \ \ *\ Second\ paragraph.\ With\ a\ code\ block,\ which\ must\ be\ indented \ \ \ \ eight\ spaces: \ \ \ \ \ \ \ \ {\ code\ } \f[] .fi .PP List items may include other lists. In this case the preceding blank line is optional. The nested list must be indented four spaces or one tab: .IP .nf \f[C] *\ fruits \ \ \ \ +\ apples \ \ \ \ \ \ \ \ \-\ macintosh \ \ \ \ \ \ \ \ \-\ red\ delicious \ \ \ \ +\ pears \ \ \ \ +\ peaches *\ vegetables \ \ \ \ +\ brocolli \ \ \ \ +\ chard \f[] .fi .PP As noted above, markdown allows you to write list items "lazily," instead of indenting continuation lines. However, if there are multiple paragraphs or other blocks in a list item, the first line of each must be indented. .IP .nf \f[C] +\ A\ lazy,\ lazy,\ list item. +\ Another\ one;\ this\ looks bad\ but\ is\ legal. \ \ \ \ Second\ paragraph\ of\ second list\ item. \f[] .fi .PP \f[B]Note:\f[] Although the four\-space rule for continuation paragraphs comes from the official markdown syntax guide, the reference implementation, \f[C]Markdown.pl\f[], does not follow it. So pandoc will give different results than \f[C]Markdown.pl\f[] when authors have indented continuation paragraphs fewer than four spaces. .PP The markdown syntax guide is not explicit whether the four\-space rule applies to \f[I]all\f[] block\-level content in a list item; it only mentions paragraphs and code blocks. But it implies that the rule applies to all block\-level content (including nested lists), and pandoc interprets it that way. .SS Ordered lists .PP Ordered lists work just like bulleted lists, except that the items begin with enumerators rather than bullets. .PP In standard markdown, enumerators are decimal numbers followed by a period and a space. The numbers themselves are ignored, so there is no difference between this list: .IP .nf \f[C] 1.\ \ one 2.\ \ two 3.\ \ three \f[] .fi .PP and this one: .IP .nf \f[C] 5.\ \ one 7.\ \ two 1.\ \ three \f[] .fi .PP \f[B]Extension: \f[C]fancy_lists\f[]\f[] .PP Unlike standard markdown, Pandoc allows ordered list items to be marked with uppercase and lowercase letters and roman numerals, in addition to arabic numerals. List markers may be enclosed in parentheses or followed by a single right\-parentheses or period. They must be separated from the text that follows by at least one space, and, if the list marker is a capital letter with a period, by at least two spaces.[1] .PP The \f[C]fancy_lists\f[] extension also allows \[aq]\f[C]#\f[]\[aq] to be used as an ordered list marker in place of a numeral: .IP .nf \f[C] #.\ one #.\ two \f[] .fi .PP \f[B]Extension: \f[C]startnum\f[]\f[] .PP Pandoc also pays attention to the type of list marker used, and to the starting number, and both of these are preserved where possible in the output format. Thus, the following yields a list with numbers followed by a single parenthesis, starting with 9, and a sublist with lowercase roman numerals: .IP .nf \f[C] \ 9)\ \ Ninth 10)\ \ Tenth 11)\ \ Eleventh \ \ \ \ \ \ \ i.\ subone \ \ \ \ \ \ ii.\ subtwo \ \ \ \ \ iii.\ subthree \f[] .fi .PP Pandoc will start a new list each time a different type of list marker is used. So, the following will create three lists: .IP .nf \f[C] (2)\ Two (5)\ Three 1.\ \ Four *\ \ \ Five \f[] .fi .PP If default list markers are desired, use \f[C]#.\f[]: .IP .nf \f[C] #.\ \ one #.\ \ two #.\ \ three \f[] .fi .SS Definition lists .PP \f[B]Extension: \f[C]definition_lists\f[]\f[] .PP Pandoc supports definition lists, using a syntax inspired by PHP Markdown Extra and reStructuredText:[2] .IP .nf \f[C] Term\ 1 :\ \ \ Definition\ 1 Term\ 2\ with\ *inline\ markup* :\ \ \ Definition\ 2 \ \ \ \ \ \ \ \ {\ some\ code,\ part\ of\ Definition\ 2\ } \ \ \ \ Third\ paragraph\ of\ definition\ 2. \f[] .fi .PP Each term must fit on one line, which may optionally be followed by a blank line, and must be followed by one or more definitions. A definition begins with a colon or tilde, which may be indented one or two spaces. The body of the definition (including the first line, aside from the colon or tilde) should be indented four spaces. A term may have multiple definitions, and each definition may consist of one or more block elements (paragraph, code block, list, etc.), each indented four spaces or one tab stop. .PP If you leave space after the definition (as in the example above), the blocks of the definitions will be considered paragraphs. In some output formats, this will mean greater spacing between term/definition pairs. For a compact definition list, do not leave space between the definition and the next term: .IP .nf \f[C] Term\ 1 \ \ ~\ Definition\ 1 Term\ 2 \ \ ~\ Definition\ 2a \ \ ~\ Definition\ 2b \f[] .fi .SS Numbered example lists .PP \f[B]Extension: \f[C]example_lists\f[]\f[] .PP The special list marker \f[C]\@\f[] can be used for sequentially numbered examples. The first list item with a \f[C]\@\f[] marker will be numbered \[aq]1\[aq], the next \[aq]2\[aq], and so on, throughout the document. The numbered examples need not occur in a single list; each new list using \f[C]\@\f[] will take up where the last stopped. So, for example: .IP .nf \f[C] (\@)\ \ My\ first\ example\ will\ be\ numbered\ (1). (\@)\ \ My\ second\ example\ will\ be\ numbered\ (2). Explanation\ of\ examples. (\@)\ \ My\ third\ example\ will\ be\ numbered\ (3). \f[] .fi .PP Numbered examples can be labeled and referred to elsewhere in the document: .IP .nf \f[C] (\@good)\ \ This\ is\ a\ good\ example. As\ (\@good)\ illustrates,\ ... \f[] .fi .PP The label can be any string of alphanumeric characters, underscores, or hyphens. .SS Compact and loose lists .PP Pandoc behaves differently from \f[C]Markdown.pl\f[] on some "edge cases" involving lists. Consider this source: .IP .nf \f[C] +\ \ \ First +\ \ \ Second: \ \-\ \ \ Fee \ \-\ \ \ Fie \ \-\ \ \ Foe +\ \ \ Third \f[] .fi .PP Pandoc transforms this into a "compact list" (with no \f[C]<p>\f[] tags around "First", "Second", or "Third"), while markdown puts \f[C]<p>\f[] tags around "Second" and "Third" (but not "First"), because of the blank space around "Third". Pandoc follows a simple rule: if the text is followed by a blank line, it is treated as a paragraph. Since "Second" is followed by a list, and not a blank line, it isn\[aq]t treated as a paragraph. The fact that the list is followed by a blank line is irrelevant. (Note: Pandoc works this way even when the \f[C]markdown_strict\f[] format is specified. This behavior is consistent with the official markdown syntax description, even though it is different from that of \f[C]Markdown.pl\f[].) .SS Ending a list .PP What if you want to put an indented code block after a list? .IP .nf \f[C] \-\ \ \ item\ one \-\ \ \ item\ two \ \ \ \ {\ my\ code\ block\ } \f[] .fi .PP Trouble! Here pandoc (like other markdown implementations) will treat \f[C]{\ my\ code\ block\ }\f[] as the second paragraph of item two, and not as a code block. .PP To "cut off" the list after item two, you can insert some non\-indented content, like an HTML comment, which won\[aq]t produce visible output in any format: .IP .nf \f[C] \-\ \ \ item\ one \-\ \ \ item\ two <!\-\-\ end\ of\ list\ \-\-> \ \ \ \ {\ my\ code\ block\ } \f[] .fi .PP You can use the same trick if you want two consecutive lists instead of one big list: .IP .nf \f[C] 1.\ \ one 2.\ \ two 3.\ \ three <!\-\-\ \-\-> 1.\ \ uno 2.\ \ dos 3.\ \ tres \f[] .fi .SH HORIZONTAL RULES .PP A line containing a row of three or more \f[C]*\f[], \f[C]\-\f[], or \f[C]_\f[] characters (optionally separated by spaces) produces a horizontal rule: .IP .nf \f[C] *\ \ *\ \ *\ \ * \-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \f[] .fi .SH TABLES .PP Four kinds of tables may be used. The first three kinds presuppose the use of a fixed\-width font, such as Courier. The fourth kind can be used with proportionally spaced fonts, as it does not require lining up columns. .SS Simple tables .PP \f[B]Extension: \f[C]simple_tables\f[], \f[C]table_captions\f[]\f[] .PP Simple tables look like this: .IP .nf \f[C] \ \ Right\ \ \ \ \ Left\ \ \ \ \ Center\ \ \ \ \ Default \-\-\-\-\-\-\-\ \ \ \ \ \-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\ \ \ \-\-\-\-\-\-\- \ \ \ \ \ 12\ \ \ \ \ 12\ \ \ \ \ \ \ \ 12\ \ \ \ \ \ \ \ \ \ \ \ 12 \ \ \ \ 123\ \ \ \ \ 123\ \ \ \ \ \ \ 123\ \ \ \ \ \ \ \ \ \ 123 \ \ \ \ \ \ 1\ \ \ \ \ 1\ \ \ \ \ \ \ \ \ \ 1\ \ \ \ \ \ \ \ \ \ \ \ \ 1 Table:\ \ Demonstration\ of\ simple\ table\ syntax. \f[] .fi .PP The headers and table rows must each fit on one line. Column alignments are determined by the position of the header text relative to the dashed line below it:[3] .IP \[bu] 2 If the dashed line is flush with the header text on the right side but extends beyond it on the left, the column is right\-aligned. .IP \[bu] 2 If the dashed line is flush with the header text on the left side but extends beyond it on the right, the column is left\-aligned. .IP \[bu] 2 If the dashed line extends beyond the header text on both sides, the column is centered. .IP \[bu] 2 If the dashed line is flush with the header text on both sides, the default alignment is used (in most cases, this will be left). .PP The table must end with a blank line, or a line of dashes followed by a blank line. A caption may optionally be provided (as illustrated in the example above). A caption is a paragraph beginning with the string \f[C]Table:\f[] (or just \f[C]:\f[]), which will be stripped off. It may appear either before or after the table. .PP The column headers may be omitted, provided a dashed line is used to end the table. For example: .IP .nf \f[C] \-\-\-\-\-\-\-\ \ \ \ \ \-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\ \ \ \-\-\-\-\-\-\- \ \ \ \ \ 12\ \ \ \ \ 12\ \ \ \ \ \ \ \ 12\ \ \ \ \ \ \ \ \ \ \ \ \ 12 \ \ \ \ 123\ \ \ \ \ 123\ \ \ \ \ \ \ 123\ \ \ \ \ \ \ \ \ \ \ 123 \ \ \ \ \ \ 1\ \ \ \ \ 1\ \ \ \ \ \ \ \ \ \ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ 1 \-\-\-\-\-\-\-\ \ \ \ \ \-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\ \ \ \-\-\-\-\-\-\- \f[] .fi .PP When headers are omitted, column alignments are determined on the basis of the first line of the table body. So, in the tables above, the columns would be right, left, center, and right aligned, respectively. .SS Multiline tables .PP \f[B]Extension: \f[C]multiline_tables\f[], \f[C]table_captions\f[]\f[] .PP Multiline tables allow headers and table rows to span multiple lines of text (but cells that span multiple columns or rows of the table are not supported). Here is an example: .IP .nf \f[C] \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \ Centered\ \ \ Default\ \ \ \ \ \ \ \ \ \ \ Right\ Left \ \ Header\ \ \ \ Aligned\ \ \ \ \ \ \ \ \ Aligned\ Aligned \-\-\-\-\-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \ \ \ First\ \ \ \ row\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 12.0\ Example\ of\ a\ row\ that \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ spans\ multiple\ lines. \ \ Second\ \ \ \ row\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 5.0\ Here\[aq]s\ another\ one.\ Note \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ blank\ line\ between \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ rows. \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- Table:\ Here\[aq]s\ the\ caption.\ It,\ too,\ may\ span multiple\ lines. \f[] .fi .PP These work like simple tables, but with the following differences: .IP \[bu] 2 They must begin with a row of dashes, before the header text (unless the headers are omitted). .IP \[bu] 2 They must end with a row of dashes, then a blank line. .IP \[bu] 2 The rows must be separated by blank lines. .PP In multiline tables, the table parser pays attention to the widths of the columns, and the writers try to reproduce these relative widths in the output. So, if you find that one of the columns is too narrow in the output, try widening it in the markdown source. .PP Headers may be omitted in multiline tables as well as simple tables: .IP .nf \f[C] \-\-\-\-\-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \ \ \ First\ \ \ \ row\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 12.0\ Example\ of\ a\ row\ that \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ spans\ multiple\ lines. \ \ Second\ \ \ \ row\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 5.0\ Here\[aq]s\ another\ one.\ Note \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ blank\ line\ between \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ rows. \-\-\-\-\-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- :\ Here\[aq]s\ a\ multiline\ table\ without\ headers. \f[] .fi .PP It is possible for a multiline table to have just one row, but the row should be followed by a blank line (and then the row of dashes that ends the table), or the table may be interpreted as a simple table. .SS Grid tables .PP \f[B]Extension: \f[C]grid_tables\f[], \f[C]table_captions\f[]\f[] .PP Grid tables look like this: .IP .nf \f[C] :\ Sample\ grid\ table. +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ |\ Fruit\ \ \ \ \ \ \ \ \ |\ Price\ \ \ \ \ \ \ \ \ |\ Advantages\ \ \ \ \ \ \ \ \ | +===============+===============+====================+ |\ Bananas\ \ \ \ \ \ \ |\ $1.34\ \ \ \ \ \ \ \ \ |\ \-\ built\-in\ wrapper\ | |\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ |\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ |\ \-\ bright\ color\ \ \ \ \ | +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ |\ Oranges\ \ \ \ \ \ \ |\ $2.10\ \ \ \ \ \ \ \ \ |\ \-\ cures\ scurvy\ \ \ \ \ | |\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ |\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ |\ \-\ tasty\ \ \ \ \ \ \ \ \ \ \ \ | +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ \f[] .fi .PP The row of \f[C]=\f[]s separates the header from the table body, and can be omitted for a headerless table. The cells of grid tables may contain arbitrary block elements (multiple paragraphs, code blocks, lists, etc.). Alignments are not supported, nor are cells that span multiple columns or rows. Grid tables can be created easily using Emacs table mode. .SS Pipe tables .PP \f[B]Extension: \f[C]pipe_tables\f[], \f[C]table_captions\f[]\f[] .PP Pipe tables look like this: .IP .nf \f[C] |\ Right\ |\ Left\ |\ Default\ |\ Center\ | |\-\-\-\-\-\-:|:\-\-\-\-\-|\-\-\-\-\-\-\-\-\-|:\-\-\-\-\-\-:| |\ \ \ 12\ \ |\ \ 12\ \ |\ \ \ \ 12\ \ \ |\ \ \ \ 12\ \ | |\ \ 123\ \ |\ \ 123\ |\ \ \ 123\ \ \ |\ \ \ 123\ \ | |\ \ \ \ 1\ \ |\ \ \ \ 1\ |\ \ \ \ \ 1\ \ \ |\ \ \ \ \ 1\ \ | \ \ :\ Demonstration\ of\ simple\ table\ syntax. \f[] .fi .PP The syntax is the same as in PHP markdown extra. The beginning and ending pipe characters are optional, but pipes are required between all columns. The colons indicate column alignment as shown. The header can be omitted, but the horizontal line must still be included, as it defines column alignments. .PP Since the pipes indicate column boundaries, columns need not be vertically aligned, as they are in the above example. So, this is a perfectly legal (though ugly) pipe table: .IP .nf \f[C] fruit|\ price \-\-\-\-\-|\-\-\-\-\-: apple|2.05 pear|1.37 orange|3.09 \f[] .fi .PP The cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines. .PP Note: Pandoc also recognizes pipe tables of the following form, as can produced by Emacs\[aq] orgtbl\-mode: .IP .nf \f[C] |\ One\ |\ Two\ \ \ | |\-\-\-\-\-+\-\-\-\-\-\-\-| |\ my\ \ |\ table\ | |\ is\ \ |\ nice\ \ | \f[] .fi .PP The difference is that \f[C]+\f[] is used instead of \f[C]|\f[]. Other orgtbl features are not supported. In particular, to get non\-default column alignment, you\[aq]ll need to add colons as above. .SH TITLE BLOCK .PP \f[B]Extension: \f[C]pandoc_title_block\f[]\f[] .PP If the file begins with a title block .IP .nf \f[C] %\ title %\ author(s)\ (separated\ by\ semicolons) %\ date \f[] .fi .PP it will be parsed as bibliographic information, not regular text. (It will be used, for example, in the title of standalone LaTeX or HTML output.) The block may contain just a title, a title and an author, or all three elements. If you want to include an author but no title, or a title and a date but no author, you need a blank line: .IP .nf \f[C] % %\ Author %\ My\ title % %\ June\ 15,\ 2006 \f[] .fi .PP The title may occupy multiple lines, but continuation lines must begin with leading space, thus: .IP .nf \f[C] %\ My\ title \ \ on\ multiple\ lines \f[] .fi .PP If a document has multiple authors, the authors may be put on separate lines with leading space, or separated by semicolons, or both. So, all of the following are equivalent: .IP .nf \f[C] %\ Author\ One \ \ Author\ Two %\ Author\ One;\ Author\ Two %\ Author\ One; \ \ Author\ Two \f[] .fi .PP The date must fit on one line. .PP All three metadata fields may contain standard inline formatting (italics, links, footnotes, etc.). .PP Title blocks will always be parsed, but they will affect the output only when the \f[C]\-\-standalone\f[] (\f[C]\-s\f[]) option is chosen. In HTML output, titles will appear twice: once in the document head \-\- this is the title that will appear at the top of the window in a browser \-\- and once at the beginning of the document body. The title in the document head can have an optional prefix attached (\f[C]\-\-title\-prefix\f[] or \f[C]\-T\f[] option). The title in the body appears as an H1 element with class "title", so it can be suppressed or reformatted with CSS. If a title prefix is specified with \f[C]\-T\f[] and no title block appears in the document, the title prefix will be used by itself as the HTML title. .PP The man page writer extracts a title, man page section number, and other header and footer information from the title line. The title is assumed to be the first word on the title line, which may optionally end with a (single\-digit) section number in parentheses. (There should be no space between the title and the parentheses.) Anything after this is assumed to be additional footer and header text. A single pipe character (\f[C]|\f[]) should be used to separate the footer text from the header text. Thus, .IP .nf \f[C] %\ PANDOC(1) \f[] .fi .PP will yield a man page with the title \f[C]PANDOC\f[] and section 1. .IP .nf \f[C] %\ PANDOC(1)\ Pandoc\ User\ Manuals \f[] .fi .PP will also have "Pandoc User Manuals" in the footer. .IP .nf \f[C] %\ PANDOC(1)\ Pandoc\ User\ Manuals\ |\ Version\ 4.0 \f[] .fi .PP will also have "Version 4.0" in the header. .SH YAML METADATA BLOCK .PP \f[B]Extension: \f[C]yaml_metadata_block\f[]\f[] .PP A YAML metadata block is a valid YAML object, delimited by a line of three hyphens (\f[C]\-\-\-\f[]) at the top and a line of three hyphens (\f[C]\-\-\-\f[]) or three dots (\f[C]\&...\f[]) at the bottom. A YAML metadata block may occur anywhere in the document, but if it is not at the beginning, it must be preceded by a blank line. .PP Metadata will be taken from the fields of the YAML object and added to any existing document metadata. Metadata can contain lists and objects (nested arbitrarily), but all string scalars will be interpreted as markdown. Fields with names ending in an underscore will be ignored by pandoc. (They may be given a role by external processors.) .PP A document may contain multiple metadata blocks. The metadata fields will be combined through a \f[I]left\-biased union\f[]: if two metadata blocks attempt to set the same field, the value from the first block will be taken. .PP Note that YAML escaping rules must be followed. Thus, for example, if a title contains a colon, it must be quoted. The pipe character (\f[C]|\f[]) can be used to begin an indented block that will be interpreted literally, without need for escaping. This form is necessary when the field contains blank lines: .IP .nf \f[C] \-\-\- title:\ \ \[aq]This\ is\ the\ title:\ it\ contains\ a\ colon\[aq] author: \-\ name:\ Author\ One \ \ affiliation:\ University\ of\ Somewhere \-\ name:\ Author\ Two \ \ affiliation:\ University\ of\ Nowhere tags:\ [nothing,\ nothingness] abstract:\ | \ \ This\ is\ the\ abstract. \ \ It\ consists\ of\ two\ paragraphs. \&... \f[] .fi .PP Template variables will be set automatically from the metadata. Thus, for example, in writing HTML, the variable \f[C]abstract\f[] will be set to the HTML equivalent of the markdown in the \f[C]abstract\f[] field: .IP .nf \f[C] <p>This\ is\ the\ abstract.</p> <p>It\ consists\ of\ two\ paragraphs.</p> \f[] .fi .SH BACKSLASH ESCAPES .PP \f[B]Extension: \f[C]all_symbols_escapable\f[]\f[] .PP Except inside a code block or inline code, any punctuation or space character preceded by a backslash will be treated literally, even if it would normally indicate formatting. Thus, for example, if one writes .IP .nf \f[C] *\\*hello\\** \f[] .fi .PP one will get .IP .nf \f[C] <em>*hello*</em> \f[] .fi .PP instead of .IP .nf \f[C] <strong>hello</strong> \f[] .fi .PP This rule is easier to remember than standard markdown\[aq]s rule, which allows only the following characters to be backslash\-escaped: .IP .nf \f[C] \\`*_{}[]()>#+\-.! \f[] .fi .PP (However, if the \f[C]markdown_strict\f[] format is used, the standard markdown rule will be used.) .PP A backslash\-escaped space is parsed as a nonbreaking space. It will appear in TeX output as \f[C]~\f[] and in HTML and XML as \f[C]\\ \f[] or \f[C]\\ \f[]. .PP A backslash\-escaped newline (i.e. a backslash occurring at the end of a line) is parsed as a hard line break. It will appear in TeX output as \f[C]\\\\\f[] and in HTML as \f[C]<br\ />\f[]. This is a nice alternative to markdown\[aq]s "invisible" way of indicating hard line breaks using two trailing spaces on a line. .PP Backslash escapes do not work in verbatim contexts. .SH SMART PUNCTUATION .PP \f[B]Extension\f[] .PP If the \f[C]\-\-smart\f[] option is specified, pandoc will produce typographically correct output, converting straight quotes to curly quotes, \f[C]\-\-\-\f[] to em\-dashes, \f[C]\-\-\f[] to en\-dashes, and \f[C]\&...\f[] to ellipses. Nonbreaking spaces are inserted after certain abbreviations, such as "Mr." .PP Note: if your LaTeX template uses the \f[C]csquotes\f[] package, pandoc will detect automatically this and use \f[C]\\enquote{...}\f[] for quoted text. .SH INLINE FORMATTING .SS Emphasis .PP To \f[I]emphasize\f[] some text, surround it with \f[C]*\f[]s or \f[C]_\f[], like this: .IP .nf \f[C] This\ text\ is\ _emphasized\ with\ underscores_,\ and\ this is\ *emphasized\ with\ asterisks*. \f[] .fi .PP Double \f[C]*\f[] or \f[C]_\f[] produces \f[B]strong emphasis\f[]: .IP .nf \f[C] This\ is\ **strong\ emphasis**\ and\ __with\ underscores__. \f[] .fi .PP A \f[C]*\f[] or \f[C]_\f[] character surrounded by spaces, or backslash\-escaped, will not trigger emphasis: .IP .nf \f[C] This\ is\ *\ not\ emphasized\ *,\ and\ \\*neither\ is\ this\\*. \f[] .fi .PP \f[B]Extension: \f[C]intraword_underscores\f[]\f[] .PP Because \f[C]_\f[] is sometimes used inside words and identifiers, pandoc does not interpret a \f[C]_\f[] surrounded by alphanumeric characters as an emphasis marker. If you want to emphasize just part of a word, use \f[C]*\f[]: .IP .nf \f[C] feas*ible*,\ not\ feas*able*. \f[] .fi .SS Strikeout .PP \f[B]Extension: \f[C]strikeout\f[]\f[] .PP To strikeout a section of text with a horizontal line, begin and end it with \f[C]~~\f[]. Thus, for example, .IP .nf \f[C] This\ ~~is\ deleted\ text.~~ \f[] .fi .SS Superscripts and subscripts .PP \f[B]Extension: \f[C]superscript\f[], \f[C]subscript\f[]\f[] .PP Superscripts may be written by surrounding the superscripted text by \f[C]^\f[] characters; subscripts may be written by surrounding the subscripted text by \f[C]~\f[] characters. Thus, for example, .IP .nf \f[C] H~2~O\ is\ a\ liquid.\ \ 2^10^\ is\ 1024. \f[] .fi .PP If the superscripted or subscripted text contains spaces, these spaces must be escaped with backslashes. (This is to prevent accidental superscripting and subscripting through the ordinary use of \f[C]~\f[] and \f[C]^\f[].) Thus, if you want the letter P with \[aq]a cat\[aq] in subscripts, use \f[C]P~a\\\ cat~\f[], not \f[C]P~a\ cat~\f[]. .SS Verbatim .PP To make a short span of text verbatim, put it inside backticks: .IP .nf \f[C] What\ is\ the\ difference\ between\ `>>=`\ and\ `>>`? \f[] .fi .PP If the verbatim text includes a backtick, use double backticks: .IP .nf \f[C] Here\ is\ a\ literal\ backtick\ ``\ `\ ``. \f[] .fi .PP (The spaces after the opening backticks and before the closing backticks will be ignored.) .PP The general rule is that a verbatim span starts with a string of consecutive backticks (optionally followed by a space) and ends with a string of the same number of backticks (optionally preceded by a space). .PP Note that backslash\-escapes (and other markdown constructs) do not work in verbatim contexts: .IP .nf \f[C] This\ is\ a\ backslash\ followed\ by\ an\ asterisk:\ `\\*`. \f[] .fi .PP \f[B]Extension: \f[C]inline_code_attributes\f[]\f[] .PP Attributes can be attached to verbatim text, just as with fenced code blocks: .IP .nf \f[C] `<$>`{.haskell} \f[] .fi .SH MATH .PP \f[B]Extension: \f[C]tex_math_dollars\f[]\f[] .PP Anything between two \f[C]$\f[] characters will be treated as TeX math. The opening \f[C]$\f[] must have a character immediately to its right, while the closing \f[C]$\f[] must have a character immediately to its left. Thus, \f[C]$20,000\ and\ $30,000\f[] won\[aq]t parse as math. If for some reason you need to enclose text in literal \f[C]$\f[] characters, backslash\-escape them and they won\[aq]t be treated as math delimiters. .PP TeX math will be printed in all output formats. How it is rendered depends on the output format: .TP .B Markdown, LaTeX, Org\-Mode, ConTeXt It will appear verbatim between \f[C]$\f[] characters. .RS .RE .TP .B reStructuredText It will be rendered using an interpreted text role \f[C]:math:\f[], as described here. .RS .RE .TP .B AsciiDoc It will be rendered as \f[C]latexmath:[...]\f[]. .RS .RE .TP .B Texinfo It will be rendered inside a \f[C]\@math\f[] command. .RS .RE .TP .B groff man It will be rendered verbatim without \f[C]$\f[]\[aq]s. .RS .RE .TP .B MediaWiki It will be rendered inside \f[C]<math>\f[] tags. .RS .RE .TP .B Textile It will be rendered inside \f[C]<span\ class="math">\f[] tags. .RS .RE .TP .B RTF, OpenDocument, ODT It will be rendered, if possible, using unicode characters, and will otherwise appear verbatim. .RS .RE .TP .B Docbook If the \f[C]\-\-mathml\f[] flag is used, it will be rendered using mathml in an \f[C]inlineequation\f[] or \f[C]informalequation\f[] tag. Otherwise it will be rendered, if possible, using unicode characters. .RS .RE .TP .B Docx It will be rendered using OMML math markup. .RS .RE .TP .B FictionBook2 If the \f[C]\-\-webtex\f[] option is used, formulas are rendered as images using Google Charts or other compatible web service, downloaded and embedded in the e\-book. Otherwise, they will appear verbatim. .RS .RE .TP .B HTML, Slidy, DZSlides, S5, EPUB The way math is rendered in HTML will depend on the command\-line options selected: .RS .IP "1." 3 The default is to render TeX math as far as possible using unicode characters, as with RTF, DocBook, and OpenDocument output. Formulas are put inside a \f[C]span\f[] with \f[C]class="math"\f[], so that they may be styled differently from the surrounding text if needed. .IP "2." 3 If the \f[C]\-\-latexmathml\f[] option is used, TeX math will be displayed between \f[C]$\f[] or \f[C]$$\f[] characters and put in \f[C]<span>\f[] tags with class \f[C]LaTeX\f[]. The LaTeXMathML script will be used to render it as formulas. (This trick does not work in all browsers, but it works in Firefox. In browsers that do not support LaTeXMathML, TeX math will appear verbatim between \f[C]$\f[] characters.) .IP "3." 3 If the \f[C]\-\-jsmath\f[] option is used, TeX math will be put inside \f[C]<span>\f[] tags (for inline math) or \f[C]<div>\f[] tags (for display math) with class \f[C]math\f[]. The jsMath script will be used to render it. .IP "4." 3 If the \f[C]\-\-mimetex\f[] option is used, the mimeTeX CGI script will be called to generate images for each TeX formula. This should work in all browsers. The \f[C]\-\-mimetex\f[] option takes an optional URL as argument. If no URL is specified, it will be assumed that the mimeTeX CGI script is at \f[C]/cgi\-bin/mimetex.cgi\f[]. .IP "5." 3 If the \f[C]\-\-gladtex\f[] option is used, TeX formulas will be enclosed in \f[C]<eq>\f[] tags in the HTML output. The resulting \f[C]htex\f[] file may then be processed by gladTeX, which will produce image files for each formula and an \f[C]html\f[] file with links to these images. So, the procedure is: .RS 4 .IP .nf \f[C] pandoc\ \-s\ \-\-gladtex\ myfile.txt\ \-o\ myfile.htex gladtex\ \-d\ myfile\-images\ myfile.htex #\ produces\ myfile.html\ and\ images\ in\ myfile\-images \f[] .fi .RE .IP "6." 3 If the \f[C]\-\-webtex\f[] option is used, TeX formulas will be converted to \f[C]<img>\f[] tags that link to an external script that converts formulas to images. The formula will be URL\-encoded and concatenated with the URL provided. If no URL is specified, the Google Chart API will be used (\f[C]http://chart.apis.google.com/chart?cht=tx&chl=\f[]). .IP "7." 3 If the \f[C]\-\-mathjax\f[] option is used, TeX math will be displayed between \f[C]\\(...\\)\f[] (for inline math) or \f[C]\\[...\\]\f[] (for display math) and put in \f[C]<span>\f[] tags with class \f[C]math\f[]. The MathJax script will be used to render it as formulas. .RE .SH RAW HTML .PP \f[B]Extension: \f[C]raw_html\f[]\f[] .PP Markdown allows you to insert raw HTML (or DocBook) anywhere in a document (except verbatim contexts, where \f[C]<\f[], \f[C]>\f[], and \f[C]&\f[] are interpreted literally). (Techncially this is not an extension, since standard markdown allows it, but it has been made an extension so that it can be disabled if desired.) .PP The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous, DZSlides, EPUB, Markdown, and Textile output, and suppressed in other formats. .PP \f[B]Extension: \f[C]markdown_in_html_blocks\f[]\f[] .PP Standard markdown allows you to include HTML "blocks": blocks of HTML between balanced tags that are separated from the surrounding text with blank lines, and start and end at the left margin. Within these blocks, everything is interpreted as HTML, not markdown; so (for example), \f[C]*\f[] does not signify emphasis. .PP Pandoc behaves this way when the \f[C]markdown_strict\f[] format is used; but by default, pandoc interprets material between HTML block tags as markdown. Thus, for example, Pandoc will turn .IP .nf \f[C] <table> \ <tr> \ \ <td>*one*</td> \ \ <td>[a\ link](http://google.com)</td> \ </tr> </table> \f[] .fi .PP into .IP .nf \f[C] <table> \ <tr> \ \ <td><em>one</em></td> \ \ <td><a\ href="http://google.com">a\ link</a></td> \ </tr> </table> \f[] .fi .PP whereas \f[C]Markdown.pl\f[] will preserve it as is. .PP There is one exception to this rule: text between \f[C]<script>\f[] and \f[C]<style>\f[] tags is not interpreted as markdown. .PP This departure from standard markdown should make it easier to mix markdown with HTML block elements. For example, one can surround a block of markdown text with \f[C]<div>\f[] tags without preventing it from being interpreted as markdown. .SH RAW TEX .PP \f[B]Extension: \f[C]raw_tex\f[]\f[] .PP In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be included in a document. Inline TeX commands will be preserved and passed unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use LaTeX to include BibTeX citations: .IP .nf \f[C] This\ result\ was\ proved\ in\ \\cite{jones.1967}. \f[] .fi .PP Note that in LaTeX environments, like .IP .nf \f[C] \\begin{tabular}{|l|l|}\\hline Age\ &\ Frequency\ \\\\\ \\hline 18\-\-25\ \ &\ 15\ \\\\ 26\-\-35\ \ &\ 33\ \\\\ 36\-\-45\ \ &\ 22\ \\\\\ \\hline \\end{tabular} \f[] .fi .PP the material between the begin and end tags will be interpreted as raw LaTeX, not as markdown. .PP Inline LaTeX is ignored in output formats other than Markdown, LaTeX, and ConTeXt. .SH LATEX MACROS .PP \f[B]Extension: \f[C]latex_macros\f[]\f[] .PP For output formats other than LaTeX, pandoc will parse LaTeX \f[C]\\newcommand\f[] and \f[C]\\renewcommand\f[] definitions and apply the resulting macros to all LaTeX math. So, for example, the following will work in all output formats, not just LaTeX: .IP .nf \f[C] \\newcommand{\\tuple}[1]{\\langle\ #1\ \\rangle} $\\tuple{a,\ b,\ c}$ \f[] .fi .PP In LaTeX output, the \f[C]\\newcommand\f[] definition will simply be passed unchanged to the output. .SH LINKS .PP Markdown allows links to be specified in several ways. .SS Automatic links .PP If you enclose a URL or email address in pointy brackets, it will become a link: .IP .nf \f[C] <http://google.com> <sam\@green.eggs.ham> \f[] .fi .SS Inline links .PP An inline link consists of the link text in square brackets, followed by the URL in parentheses. (Optionally, the URL can be followed by a link title, in quotes.) .IP .nf \f[C] This\ is\ an\ [inline\ link](/url),\ and\ here\[aq]s\ [one\ with a\ title](http://fsf.org\ "click\ here\ for\ a\ good\ time!"). \f[] .fi .PP There can be no space between the bracketed part and the parenthesized part. The link text can contain formatting (such as emphasis), but the title cannot. .SS Reference links .PP An \f[I]explicit\f[] reference link has two parts, the link itself and the link definition, which may occur elsewhere in the document (either before or after the link). .PP The link consists of link text in square brackets, followed by a label in square brackets. (There can be space between the two.) The link definition consists of the bracketed label, followed by a colon and a space, followed by the URL, and optionally (after a space) a link title either in quotes or in parentheses. .PP Here are some examples: .IP .nf \f[C] [my\ label\ 1]:\ /foo/bar.html\ \ "My\ title,\ optional" [my\ label\ 2]:\ /foo [my\ label\ 3]:\ http://fsf.org\ (The\ free\ software\ foundation) [my\ label\ 4]:\ /bar#special\ \ \[aq]A\ title\ in\ single\ quotes\[aq] \f[] .fi .PP The URL may optionally be surrounded by angle brackets: .IP .nf \f[C] [my\ label\ 5]:\ <http://foo.bar.baz> \f[] .fi .PP The title may go on the next line: .IP .nf \f[C] [my\ label\ 3]:\ http://fsf.org \ \ "The\ free\ software\ foundation" \f[] .fi .PP Note that link labels are not case sensitive. So, this will work: .IP .nf \f[C] Here\ is\ [my\ link][FOO] [Foo]:\ /bar/baz \f[] .fi .PP In an \f[I]implicit\f[] reference link, the second pair of brackets is empty, or omitted entirely: .IP .nf \f[C] See\ [my\ website][],\ or\ [my\ website]. [my\ website]:\ http://foo.bar.baz \f[] .fi .PP Note: In \f[C]Markdown.pl\f[] and most other markdown implementations, reference link definitions cannot occur in nested constructions such as list items or block quotes. Pandoc lifts this arbitrary seeming restriction. So the following is fine in pandoc, though not in most other implementations: .IP .nf \f[C] >\ My\ block\ [quote]. > >\ [quote]:\ /foo \f[] .fi .SS Internal links .PP To link to another section of the same document, use the automatically generated identifier (see Header identifiers in HTML, LaTeX, and ConTeXt, below). For example: .IP .nf \f[C] See\ the\ [Introduction](#introduction). \f[] .fi .PP or .IP .nf \f[C] See\ the\ [Introduction]. [Introduction]:\ #introduction \f[] .fi .PP Internal links are currently supported for HTML formats (including HTML slide shows and EPUB), LaTeX, and ConTeXt. .SH IMAGES .PP A link immediately preceded by a \f[C]!\f[] will be treated as an image. The link text will be used as the image\[aq]s alt text: .IP .nf \f[C] ![la\ lune](lalune.jpg\ "Voyage\ to\ the\ moon") ![movie\ reel] [movie\ reel]:\ movie.gif \f[] .fi .SS Pictures with captions .PP \f[B]Extension: \f[C]implicit_figures\f[]\f[] .PP An image occurring by itself in a paragraph will be rendered as a figure with a caption.[4] (In LaTeX, a figure environment will be used; in HTML, the image will be placed in a \f[C]div\f[] with class \f[C]figure\f[], together with a caption in a \f[C]p\f[] with class \f[C]caption\f[].) The image\[aq]s alt text will be used as the caption. .IP .nf \f[C] ![This\ is\ the\ caption](/url/of/image.png) \f[] .fi .PP If you just want a regular inline image, just make sure it is not the only thing in the paragraph. One way to do this is to insert a nonbreaking space after the image: .IP .nf \f[C] ![This\ image\ won\[aq]t\ be\ a\ figure](/url/of/image.png)\\ \f[] .fi .SH FOOTNOTES .PP \f[B]Extension: \f[C]footnotes\f[]\f[] .PP Pandoc\[aq]s markdown allows footnotes, using the following syntax: .IP .nf \f[C] Here\ is\ a\ footnote\ reference,[^1]\ and\ another.[^longnote] [^1]:\ Here\ is\ the\ footnote. [^longnote]:\ Here\[aq]s\ one\ with\ multiple\ blocks. \ \ \ \ Subsequent\ paragraphs\ are\ indented\ to\ show\ that\ they belong\ to\ the\ previous\ footnote. \ \ \ \ \ \ \ \ {\ some.code\ } \ \ \ \ The\ whole\ paragraph\ can\ be\ indented,\ or\ just\ the\ first \ \ \ \ line.\ \ In\ this\ way,\ multi\-paragraph\ footnotes\ work\ like \ \ \ \ multi\-paragraph\ list\ items. This\ paragraph\ won\[aq]t\ be\ part\ of\ the\ note,\ because\ it isn\[aq]t\ indented. \f[] .fi .PP The identifiers in footnote references may not contain spaces, tabs, or newlines. These identifiers are used only to correlate the footnote reference with the note itself; in the output, footnotes will be numbered sequentially. .PP The footnotes themselves need not be placed at the end of the document. They may appear anywhere except inside other block elements (lists, block quotes, tables, etc.). .PP \f[B]Extension: \f[C]inline_notes\f[]\f[] .PP Inline footnotes are also allowed (though, unlike regular notes, they cannot contain multiple paragraphs). The syntax is as follows: .IP .nf \f[C] Here\ is\ an\ inline\ note.^[Inlines\ notes\ are\ easier\ to\ write,\ since you\ don\[aq]t\ have\ to\ pick\ an\ identifier\ and\ move\ down\ to\ type\ the note.] \f[] .fi .PP Inline and regular footnotes may be mixed freely. .SH CITATIONS .PP \f[B]Extension: \f[C]citations\f[]\f[] .PP Using an external filter, \f[C]pandoc\-citeproc\f[], pandoc can automatically generate citations and a bibliography in a number of styles. Basic usage is .IP .nf \f[C] pandoc\ \-\-filter\ pandoc\-citeproc\ myinput.txt \f[] .fi .PP In order to use this feature, you will need to specify a bibliography file using the \f[C]bibliography\f[] metadata field in a YAML metadata section. The bibliography may have any of these formats: .PP .TS tab(@); l l. T{ Format T}@T{ File extension T} _ T{ MODS T}@T{ \&.mods T} T{ BibLaTeX T}@T{ \&.bib T} T{ BibTeX T}@T{ \&.bibtex T} T{ RIS T}@T{ \&.ris T} T{ EndNote T}@T{ \&.enl T} T{ EndNote XML T}@T{ \&.xml T} T{ ISI T}@T{ \&.wos T} T{ MEDLINE T}@T{ \&.medline T} T{ Copac T}@T{ \&.copac T} T{ JSON citeproc T}@T{ \&.json T} .TE .PP Note that \f[C]\&.bib\f[] can generally be used with both BibTeX and BibLaTeX files, but you can use \f[C]\&.bibtex\f[] to force BibTeX. .PP Alternatively you can use a \f[C]references\f[] field in the document\[aq]s YAML metadata. This should include an array of YAML\-encoded references, for example: .IP .nf \f[C] \-\-\- references: \-\ id:\ fenner2012a \ \ title:\ One\-click\ science\ marketing \ \ author: \ \ \-\ family:\ Fenner \ \ \ \ given:\ Martin \ \ container\-title:\ Nature\ Materials \ \ volume:\ 11 \ \ URL:\ \[aq]http://dx.doi.org/10.1038/nmat3283\[aq] \ \ DOI:\ 10.1038/nmat3283 \ \ issue:\ 4 \ \ publisher:\ Nature\ Publishing\ Group \ \ page:\ 261\-263 \ \ type:\ article\-journal \ \ issued: \ \ \ \ year:\ 2012 \ \ \ \ month:\ 3 \&... \f[] .fi .PP (The program \f[C]mods2yaml\f[], which comes with \f[C]pandoc\-citeproc\f[], can help produce these from a MODS reference collection.) .PP By default, \f[C]pandoc\-citeproc\f[] will use a Chicago author\-date format for citations and references. To use another style, you will need to specify a CSL 1.0 style file in the \f[C]csl\f[] metadata field. A primer on creating and modifying CSL styles can be found at http://citationstyles.org/downloads/primer.html. A repository of CSL styles can be found at https://github.com/citation\-style\-language/styles. See also http://zotero.org/styles for easy browsing. .PP Citations go inside square brackets and are separated by semicolons. Each citation must have a key, composed of \[aq]\@\[aq] + the citation identifier from the database, and may optionally have a prefix, a locator, and a suffix. Here are some examples: .IP .nf \f[C] Blah\ blah\ [see\ \@doe99,\ pp.\ 33\-35;\ also\ \@smith04,\ ch.\ 1]. Blah\ blah\ [\@doe99,\ pp.\ 33\-35,\ 38\-39\ and\ *passim*]. Blah\ blah\ [\@smith04;\ \@doe99]. \f[] .fi .PP A minus sign (\f[C]\-\f[]) before the \f[C]\@\f[] will suppress mention of the author in the citation. This can be useful when the author is already mentioned in the text: .IP .nf \f[C] Smith\ says\ blah\ [\-\@smith04]. \f[] .fi .PP You can also write an in\-text citation, as follows: .IP .nf \f[C] \@smith04\ says\ blah. \@smith04\ [p.\ 33]\ says\ blah. \f[] .fi .PP If the style calls for a list of works cited, it will be placed at the end of the document. Normally, you will want to end your document with an appropriate header: .IP .nf \f[C] last\ paragraph... #\ References \f[] .fi .PP The bibliography will be inserted after this header. .SH NON\-PANDOC EXTENSIONS .PP The following markdown syntax extensions are not enabled by default in pandoc, but may be enabled by adding \f[C]+EXTENSION\f[] to the format name, where \f[C]EXTENSION\f[] is the name of the extension. Thus, for example, \f[C]markdown+hard_line_breaks\f[] is markdown with hard line breaks. .PP \f[B]Extension: \f[C]lists_without_preceding_blankline\f[]\f[] .PD 0 .P .PD Allow a list to occur right after a paragraph, with no intervening blank space. .PP \f[B]Extension: \f[C]hard_line_breaks\f[]\f[] .PD 0 .P .PD Causes all newlines within a paragraph to be interpreted as hard line breaks instead of spaces. .PP \f[B]Extension: \f[C]ignore_line_breaks\f[]\f[] .PD 0 .P .PD Causes newlines within a paragraph to be ignored, rather than being treated as spaces or as hard line breaks. This option is intended for use with East Asian languages where spaces are not used between words, but text is divided into lines for readability. .PP \f[B]Extension: \f[C]tex_math_single_backslash\f[]\f[] .PD 0 .P .PD Causes anything between \f[C]\\(\f[] and \f[C]\\)\f[] to be interpreted as inline TeX math, and anything between \f[C]\\[\f[] and \f[C]\\]\f[] to be interpreted as display TeX math. Note: a drawback of this extension is that it precludes escaping \f[C](\f[] and \f[C][\f[]. .PP \f[B]Extension: \f[C]tex_math_double_backslash\f[]\f[] .PD 0 .P .PD Causes anything between \f[C]\\\\(\f[] and \f[C]\\\\)\f[] to be interpreted as inline TeX math, and anything between \f[C]\\\\[\f[] and \f[C]\\\\]\f[] to be interpreted as display TeX math. .PP \f[B]Extension: \f[C]markdown_attribute\f[]\f[] .PD 0 .P .PD By default, pandoc interprets material inside block\-level tags as markdown. This extension changes the behavior so that markdown is only parsed inside block\-level tags if the tags have the attribute \f[C]markdown=1\f[]. .PP \f[B]Extension: \f[C]mmd_title_block\f[]\f[] .PD 0 .P .PD Enables a MultiMarkdown style title block at the top of the document, for example: .IP .nf \f[C] Title:\ \ \ My\ title Author:\ \ John\ Doe Date:\ \ \ \ September\ 1,\ 2008 Comment:\ This\ is\ a\ sample\ mmd\ title\ block,\ with \ \ \ \ \ \ \ \ \ a\ field\ spanning\ multiple\ lines. \f[] .fi .PP See the MultiMarkdown documentation for details. Note that only title, author, and date are recognized; other fields are simply ignored by pandoc. If \f[C]pandoc_title_block\f[] or \f[C]yaml_metadata_block\f[] is enabled, it will take precedence over \f[C]mmd_title_block\f[]. .PP \f[B]Extension: \f[C]abbreviations\f[]\f[] .PD 0 .P .PD Parses PHP Markdown Extra abbreviation keys, like .IP .nf \f[C] *[HTML]:\ Hyper\ Text\ Markup\ Language \f[] .fi .PP Note that the pandoc document model does not support abbreviations, so if this extension is enabled, abbreviation keys are simply skipped (as opposed to being parsed as paragraphs). .PP \f[B]Extension: \f[C]autolink_bare_uris\f[]\f[] .PD 0 .P .PD Makes all absolute URIs into links, even when not surrounded by pointy braces \f[C]<...>\f[]. .PP \f[B]Extension: \f[C]ascii_identifiers\f[]\f[] .PD 0 .P .PD Causes the identifiers produced by \f[C]auto_identifiers\f[] to be pure ASCII. Accents are stripped off of accented latin letters, and non\-latin letters are omitted. .PP \f[B]Extension: \f[C]link_attributes\f[]\f[] .PD 0 .P .PD Parses multimarkdown style key\-value attributes on link and image references. Note that pandoc\[aq]s internal document model provides nowhere to put these, so they are presently just ignored. .PP \f[B]Extension: \f[C]mmd_header_identifiers\f[]\f[] .PD 0 .P .PD Parses multimarkdown style header identifiers (in square brackets, after the header but before any trailing \f[C]#\f[]s in an ATX header). .SH MARKDOWN VARIANTS .PP In addition to pandoc\[aq]s extended markdown, the following markdown variants are supported: .TP .B \f[C]markdown_phpextra\f[] (PHP Markdown Extra) \f[C]footnotes\f[], \f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]markdown_attribute\f[], \f[C]fenced_code_blocks\f[], \f[C]definition_lists\f[], \f[C]intraword_underscores\f[], \f[C]header_attributes\f[], \f[C]abbreviations\f[]. .RS .RE .TP .B \f[C]markdown_github\f[] (Github\-flavored Markdown) \f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]tex_math_single_backslash\f[], \f[C]fenced_code_blocks\f[], \f[C]fenced_code_attributes\f[], \f[C]auto_identifiers\f[], \f[C]ascii_identifiers\f[], \f[C]backtick_code_blocks\f[], \f[C]autolink_bare_uris\f[], \f[C]intraword_underscores\f[], \f[C]strikeout\f[], \f[C]hard_line_breaks\f[] .RS .RE .TP .B \f[C]markdown_mmd\f[] (MultiMarkdown) \f[C]pipe_tables\f[] \f[C]raw_html\f[], \f[C]markdown_attribute\f[], \f[C]link_attributes\f[], \f[C]raw_tex\f[], \f[C]tex_math_double_backslash\f[], \f[C]intraword_underscores\f[], \f[C]mmd_title_block\f[], \f[C]footnotes\f[], \f[C]definition_lists\f[], \f[C]all_symbols_escapable\f[], \f[C]implicit_header_references\f[], \f[C]auto_identifiers\f[], \f[C]mmd_header_identifiers\f[] .RS .RE .TP .B \f[C]markdown_strict\f[] (Markdown.pl) \f[C]raw_html\f[] .RS .RE .SH EXTENSIONS WITH FORMATS OTHER THAN MARKDOWN .PP Some of the extensions discussed above can be used with formats other than markdown: .IP \[bu] 2 \f[C]auto_identifiers\f[] can be used with \f[C]latex\f[], \f[C]rst\f[], \f[C]mediawiki\f[], and \f[C]textile\f[] input (and is used by default). .IP \[bu] 2 \f[C]tex_math_dollars\f[], \f[C]tex_math_single_backslash\f[], and \f[C]tex_math_double_backslash\f[] can be used with \f[C]html\f[] input. (This is handy for reading web pages formatted using MathJax, for example.) .SH NOTES .SS [1] .PP The point of this rule is to ensure that normal paragraphs starting with people\[aq]s initials, like .IP .nf \f[C] B.\ Russell\ was\ an\ English\ philosopher. \f[] .fi .PP do not get treated as list items. .PP This rule will not prevent .IP .nf \f[C] (C)\ 2007\ Joe\ Smith \f[] .fi .PP from being interpreted as a list item. In this case, a backslash escape can be used: .IP .nf \f[C] (C\\)\ 2007\ Joe\ Smith \f[] .fi .SS [2] .PP I have also been influenced by the suggestions of David Wheeler. .SS [3] .PP This scheme is due to Michel Fortin, who proposed it on the Markdown discussion list. .SS [4] .PP This feature is not yet implemented for RTF, OpenDocument, or ODT. In those formats, you\[aq]ll just get an image in a paragraph by itself, with no caption. .SH SEE ALSO .PP \f[C]pandoc\f[] (1). �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/man/man5/pandoc_markdown.5.template�������������������������������������������������000644 �000765 �000024 �00000000275 12251233602 021601� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������$if(has-tables)$ .\"t $endif$ .TH PANDOC_MARKDOWN 5 "$date$" "$title$" .SH NAME pandoc_markdown - markdown syntax for pandoc(1) .SH DESCRIPTION $body$ .SH SEE ALSO .PP \f[C]pandoc\f[] (1). �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pandoc-1.12.2.1/man/man1/pandoc.1�������������������������������������������������������������������000644 �000765 �000024 �00000146313 12251233602 016061� 0����������������������������������������������������������������������������������������������������ustar�00jgm�����������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH PANDOC 1 "January 19, 2013" "Pandoc User\[aq]s Guide" .SH NAME pandoc - general markup converter .SH SYNOPSIS .PP pandoc [\f[I]options\f[]] [\f[I]input\-file\f[]]... .SH DESCRIPTION .PP Pandoc is a Haskell library for converting from one markup format to another, and a command\-line tool that uses this library. It can read markdown and (subsets of) Textile, reStructuredText, HTML, LaTeX, MediaWiki markup, Haddock markup, OPML, and DocBook; and it can write plain text, markdown, reStructuredText, XHTML, HTML 5, LaTeX (including beamer slide shows), ConTeXt, RTF, OPML, DocBook, OpenDocument, ODT, Word docx, GNU Texinfo, MediaWiki markup, EPUB (v2 or v3), FictionBook2, Textile, groff man pages, Emacs Org\-Mode, AsciiDoc, and Slidy, Slideous, DZSlides, reveal.js or S5 HTML slide shows. It can also produce PDF output on systems where LaTeX is installed. .PP Pandoc\[aq]s enhanced version of markdown includes syntax for footnotes, tables, flexible ordered lists, definition lists, fenced code blocks, superscript, subscript, strikeout, title blocks, automatic tables of contents, embedded LaTeX math, citations, and markdown inside HTML block elements. (These enhancements, described below under Pandoc\[aq]s markdown, can be disabled using the \f[C]markdown_strict\f[] input or output format.) .PP In contrast to most existing tools for converting markdown to HTML, which use regex substitutions, Pandoc has a modular design: it consists of a set of readers, which parse text in a given format and produce a native representation of the document, and a set of writers, which convert this native representation into a target format. Thus, adding an input or output format requires only adding a reader or writer. .SS Using \f[C]pandoc\f[] .PP If no \f[I]input\-file\f[] is specified, input is read from \f[I]stdin\f[]. Otherwise, the \f[I]input\-files\f[] are concatenated (with a blank line between each) and used as input. Output goes to \f[I]stdout\f[] by default (though output to \f[I]stdout\f[] is disabled for the \f[C]odt\f[], \f[C]docx\f[], \f[C]epub\f[], and \f[C]epub3\f[] output formats). For output to a file, use the \f[C]\-o\f[] option: .IP .nf \f[C] pandoc\ \-o\ output.html\ input.txt \f[] .fi .PP Instead of a file, an absolute URI may be given. In this case pandoc will fetch the content using HTTP: .IP .nf \f[C] pandoc\ \-f\ html\ \-t\ markdown\ http://www.fsf.org \f[] .fi .PP If multiple input files are given, \f[C]pandoc\f[] will concatenate them all (with blank lines between them) before parsing. .PP The format of the input and output can be specified explicitly using command\-line options. The input format can be specified using the \f[C]\-r/\-\-read\f[] or \f[C]\-f/\-\-from\f[] options, the output format using the \f[C]\-w/\-\-write\f[] or \f[C]\-t/\-\-to\f[] options. Thus, to convert \f[C]hello.txt\f[] from markdown to LaTeX, you could type: .IP .nf \f[C] pandoc\ \-f\ markdown\ \-t\ latex\ hello.txt \f[] .fi .PP To convert \f[C]hello.html\f[] from html to markdown: .IP .nf \f[C] pandoc\ \-f\ html\ \-t\ markdown\ hello.html \f[] .fi .PP Supported output formats are listed below under the \f[C]\-t/\-\-to\f[] option. Supported input formats are listed below under the \f[C]\-f/\-\-from\f[] option. Note that the \f[C]rst\f[], \f[C]textile\f[], \f[C]latex\f[], and \f[C]html\f[] readers are not complete; there are some constructs that they do not parse. .PP If the input or output format is not specified explicitly, \f[C]pandoc\f[] will attempt to guess it from the extensions of the input and output filenames. Thus, for example, .IP .nf \f[C] pandoc\ \-o\ hello.tex\ hello.txt \f[] .fi .PP will convert \f[C]hello.txt\f[] from markdown to LaTeX. If no output file is specified (so that output goes to \f[I]stdout\f[]), or if the output file\[aq]s extension is unknown, the output format will default to HTML. If no input file is specified (so that input comes from \f[I]stdin\f[]), or if the input files\[aq] extensions are unknown, the input format will be assumed to be markdown unless explicitly specified. .PP Pandoc uses the UTF\-8 character encoding for both input and output. If your local character encoding is not UTF\-8, you should pipe input and output through \f[C]iconv\f[]: .IP .nf \f[C] iconv\ \-t\ utf\-8\ input.txt\ |\ pandoc\ |\ iconv\ \-f\ utf\-8 \f[] .fi .SS Creating a PDF .PP Earlier versions of pandoc came with a program, \f[C]markdown2pdf\f[], that used pandoc and pdflatex to produce a PDF. This is no longer needed, since \f[C]pandoc\f[] can now produce \f[C]pdf\f[] output itself. To produce a PDF, simply specify an output file with a \f[C]\&.pdf\f[] extension. Pandoc will create a latex file and use pdflatex (or another engine, see \f[C]\-\-latex\-engine\f[]) to convert it to PDF: .IP .nf \f[C] pandoc\ test.txt\ \-o\ test.pdf \f[] .fi .PP Production of a PDF requires that a LaTeX engine be installed (see \f[C]\-\-latex\-engine\f[], below), and assumes that the following LaTeX packages are available: \f[C]amssymb\f[], \f[C]amsmath\f[], \f[C]ifxetex\f[], \f[C]ifluatex\f[], \f[C]listings\f[] (if the \f[C]\-\-listings\f[] option is used), \f[C]fancyvrb\f[], \f[C]longtable\f[], \f[C]booktabs\f[], \f[C]url\f[], \f[C]graphicx\f[], \f[C]hyperref\f[], \f[C]ulem\f[], \f[C]babel\f[] (if the \f[C]lang\f[] variable is set), \f[C]fontspec\f[] (if \f[C]xelatex\f[] or \f[C]lualatex\f[] is used as the LaTeX engine), \f[C]xltxtra\f[] and \f[C]xunicode\f[] (if \f[C]xelatex\f[] is used). .SS \f[C]hsmarkdown\f[] .PP A user who wants a drop\-in replacement for \f[C]Markdown.pl\f[] may create a symbolic link to the \f[C]pandoc\f[] executable called \f[C]hsmarkdown\f[]. When invoked under the name \f[C]hsmarkdown\f[], \f[C]pandoc\f[] will behave as if invoked with \f[C]\-f\ markdown_strict\ \-\-email\-obfuscation=references\f[], and all command\-line options will be treated as regular arguments. However, this approach does not work under Cygwin, due to problems with its simulation of symbolic links. .SH OPTIONS .SS General options .TP .B \f[C]\-f\f[] \f[I]FORMAT\f[], \f[C]\-r\f[] \f[I]FORMAT\f[], \f[C]\-\-from=\f[]\f[I]FORMAT\f[], \f[C]\-\-read=\f[]\f[I]FORMAT\f[] Specify input format. \f[I]FORMAT\f[] can be \f[C]native\f[] (native Haskell), \f[C]json\f[] (JSON version of native AST), \f[C]markdown\f[] (pandoc\[aq]s extended markdown), \f[C]markdown_strict\f[] (original unextended markdown), \f[C]markdown_phpextra\f[] (PHP Markdown Extra extended markdown), \f[C]markdown_github\f[] (github extended markdown), \f[C]textile\f[] (Textile), \f[C]rst\f[] (reStructuredText), \f[C]html\f[] (HTML), \f[C]docbook\f[] (DocBook), \f[C]opml\f[] (OPML), \f[C]mediawiki\f[] (MediaWiki markup), \f[C]haddock\f[] (Haddock markup), or \f[C]latex\f[] (LaTeX). If \f[C]+lhs\f[] is appended to \f[C]markdown\f[], \f[C]rst\f[], \f[C]latex\f[], or \f[C]html\f[], the input will be treated as literate Haskell source: see Literate Haskell support, below. Markdown syntax extensions can be individually enabled or disabled by appending \f[C]+EXTENSION\f[] or \f[C]\-EXTENSION\f[] to the format name. So, for example, \f[C]markdown_strict+footnotes+definition_lists\f[] is strict markdown with footnotes and definition lists enabled, and \f[C]markdown\-pipe_tables+hard_line_breaks\f[] is pandoc\[aq]s markdown without pipe tables and with hard line breaks. See Pandoc\[aq]s markdown, below, for a list of extensions and their names. .RS .RE .TP .B \f[C]\-t\f[] \f[I]FORMAT\f[], \f[C]\-w\f[] \f[I]FORMAT\f[], \f[C]\-\-to=\f[]\f[I]FORMAT\f[], \f[C]\-\-write=\f[]\f[I]FORMAT\f[] Specify output format. \f[I]FORMAT\f[] can be \f[C]native\f[] (native Haskell), \f[C]json\f[] (JSON version of native AST), \f[C]plain\f[] (plain text), \f[C]markdown\f[] (pandoc\[aq]s extended markdown), \f[C]markdown_strict\f[] (original unextended markdown), \f[C]markdown_phpextra\f[] (PHP Markdown extra extended markdown), \f[C]markdown_github\f[] (github extended markdown), \f[C]rst\f[] (reStructuredText), \f[C]html\f[] (XHTML 1), \f[C]html5\f[] (HTML 5), \f[C]latex\f[] (LaTeX), \f[C]beamer\f[] (LaTeX beamer slide show), \f[C]context\f[] (ConTeXt), \f[C]man\f[] (groff man), \f[C]mediawiki\f[] (MediaWiki markup), \f[C]textile\f[] (Textile), \f[C]org\f[] (Emacs Org\-Mode), \f[C]texinfo\f[] (GNU Texinfo), \f[C]opml\f[] (OPML), \f[C]docbook\f[] (DocBook), \f[C]opendocument\f[] (OpenDocument), \f[C]odt\f[] (OpenOffice text document), \f[C]docx\f[] (Word docx), \f[C]rtf\f[] (rich text format), \f[C]epub\f[] (EPUB v2 book), \f[C]epub3\f[] (EPUB v3), \f[C]fb2\f[] (FictionBook2 e\-book), \f[C]asciidoc\f[] (AsciiDoc), \f[C]slidy\f[] (Slidy HTML and javascript slide show), \f[C]slideous\f[] (Slideous HTML and javascript slide show), \f[C]dzslides\f[] (DZSlides HTML5 + javascript slide show), \f[C]revealjs\f[] (reveal.js HTML5 + javascript slide show), \f[C]s5\f[] (S5 HTML and javascript slide show), or the path of a custom lua writer (see Custom writers, below). Note that \f[C]odt\f[], \f[C]epub\f[], and \f[C]epub3\f[] output will not be directed to \f[I]stdout\f[]; an output filename must be specified using the \f[C]\-o/\-\-output\f[] option. If \f[C]+lhs\f[] is appended to \f[C]markdown\f[], \f[C]rst\f[], \f[C]latex\f[], \f[C]beamer\f[], \f[C]html\f[], or \f[C]html5\f[], the output will be rendered as literate Haskell source: see Literate Haskell support, below. Markdown syntax extensions can be individually enabled or disabled by appending \f[C]+EXTENSION\f[] or \f[C]\-EXTENSION\f[] to the format name, as described above under \f[C]\-f\f[]. .RS .RE .TP .B \f[C]\-o\f[] \f[I]FILE\f[], \f[C]\-\-output=\f[]\f[I]FILE\f[] Write output to \f[I]FILE\f[] instead of \f[I]stdout\f[]. If \f[I]FILE\f[] is \f[C]\-\f[], output will go to \f[I]stdout\f[]. (Exception: if the output format is \f[C]odt\f[], \f[C]docx\f[], \f[C]epub\f[], or \f[C]epub3\f[], output to stdout is disabled.) .RS .RE .TP .B \f[C]\-\-data\-dir=\f[]\f[I]DIRECTORY\f[] Specify the user data directory to search for pandoc data files. If this option is not specified, the default user data directory will be used. This is .RS .IP .nf \f[C] $HOME/.pandoc \f[] .fi .PP in unix, .IP .nf \f[C] C:\\Documents\ And\ Settings\\USERNAME\\Application\ Data\\pandoc \f[] .fi .PP in Windows XP, and .IP .nf \f[C] C:\\Users\\USERNAME\\AppData\\Roaming\\pandoc \f[] .fi .PP in Windows 7. (You can find the default user data directory on your system by looking at the output of \f[C]pandoc\ \-\-version\f[].) A \f[C]reference.odt\f[], \f[C]reference.docx\f[], \f[C]default.csl\f[], \f[C]epub.css\f[], \f[C]templates\f[], \f[C]slidy\f[], \f[C]slideous\f[], or \f[C]s5\f[] directory placed in this directory will override pandoc\[aq]s normal defaults. .RE .TP .B \f[C]\-v\f[], \f[C]\-\-version\f[] Print version. .RS .RE .TP .B \f[C]\-h\f[], \f[C]\-\-help\f[] Show usage message. .RS .RE .SS Reader options .TP .B \f[C]\-R\f[], \f[C]\-\-parse\-raw\f[] Parse untranslatable HTML codes and LaTeX environments as raw HTML or LaTeX, instead of ignoring them. Affects only HTML and LaTeX input. Raw HTML can be printed in markdown, reStructuredText, HTML, Slidy, Slideous, DZSlides, reveal.js, and S5 output; raw LaTeX can be printed in markdown, reStructuredText, LaTeX, and ConTeXt output. The default is for the readers to omit untranslatable HTML codes and LaTeX environments. (The LaTeX reader does pass through untranslatable LaTeX \f[I]commands\f[], even if \f[C]\-R\f[] is not specified.) .RS .RE .TP .B \f[C]\-S\f[], \f[C]\-\-smart\f[] Produce typographically correct output, converting straight quotes to curly quotes, \f[C]\-\-\-\f[] to em\-dashes, \f[C]\-\-\f[] to en\-dashes, and \f[C]\&...\f[] to ellipses. Nonbreaking spaces are inserted after certain abbreviations, such as "Mr." (Note: This option is significant only when the input format is \f[C]markdown\f[], \f[C]markdown_strict\f[], or \f[C]textile\f[]. It is selected automatically when the input format is \f[C]textile\f[] or the output format is \f[C]latex\f[] or \f[C]context\f[], unless \f[C]\-\-no\-tex\-ligatures\f[] is used.) .RS .RE .TP .B \f[C]\-\-old\-dashes\f[] Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes: \f[C]\-\f[] before a numeral is an en\-dash, and \f[C]\-\-\f[] is an em\-dash. This option is selected automatically for \f[C]textile\f[] input. .RS .RE .TP .B \f[C]\-\-base\-header\-level=\f[]\f[I]NUMBER\f[] Specify the base level for headers (defaults to 1). .RS .RE .TP .B \f[C]\-\-indented\-code\-classes=\f[]\f[I]CLASSES\f[] Specify classes to use for indented code blocks\-\-for example, \f[C]perl,numberLines\f[] or \f[C]haskell\f[]. Multiple classes may be separated by spaces or commas. .RS .RE .TP .B \f[C]\-\-default\-image\-extension=\f[]\f[I]EXTENSION\f[] Specify a default extension to use when image paths/URLs have no extension. This allows you to use the same source for formats that require different kinds of images. Currently this option only affects the markdown and LaTeX readers. .RS .RE .TP .B \f[C]\-\-filter=\f[]\f[I]EXECUTABLE\f[] Specify an executable to be used as a filter transforming the Pandoc AST after the input is parsed and before the output is written. The executable should read JSON from stdin and write JSON to stdout. The JSON must be formatted like pandoc\[aq]s own JSON input and output. The name of the output format will be passed to the filter as the first argument. Hence, .RS .IP .nf \f[C] pandoc\ \-\-filter\ ./caps.py\ \-t\ latex \f[] .fi .PP is equivalent to .IP .nf \f[C] pandoc\ \-t\ json\ |\ ./caps.py\ latex\ |\ pandoc\ \-f\ json\ \-t\ latex \f[] .fi .PP The latter form may be useful for debugging filters. .PP Filters may be written in any language. \f[C]Text.Pandoc.JSON\f[] exports \f[C]toJSONFilter\f[] to facilitate writing filters in Haskell. Those who would prefer to write filters in python can use the module \f[C]pandocfilters\f[], installable from PyPI. See http://github.com/jgm/pandocfilters for the module and several examples. Note that the \f[I]EXECUTABLE\f[] will be sought in the user\[aq]s \f[C]PATH\f[], 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 \f[C]\&./\f[]. .RE .TP .B \f[C]\-M\f[] \f[I]KEY[=VAL]\f[], \f[C]\-\-metadata=\f[]\f[I]KEY[:VAL]\f[] Set the metadata field \f[I]KEY\f[] to the value \f[I]VAL\f[]. 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 \f[C]\-\-variable\f[], \f[C]\-\-metadata\f[] causes template variables to be set. But unlike \f[C]\-\-variable\f[], \f[C]\-\-metadata\f[] affects the metadata of the underlying document (which is accessible from filters and may be printed in some output formats). .RS .RE .TP .B \f[C]\-\-normalize\f[] Normalize the document after reading: merge adjacent \f[C]Str\f[] or \f[C]Emph\f[] elements, for example, and remove repeated \f[C]Space\f[]s. .RS .RE .TP .B \f[C]\-p\f[], \f[C]\-\-preserve\-tabs\f[] Preserve tabs instead of converting them to spaces (the default). Note that this will only affect tabs in literal code spans and code blocks; tabs in regular text will be treated as spaces. .RS .RE .TP .B \f[C]\-\-tab\-stop=\f[]\f[I]NUMBER\f[] Specify the number of spaces per tab (default is 4). .RS .RE .SS General writer options .TP .B \f[C]\-s\f[], \f[C]\-\-standalone\f[] Produce output with an appropriate header and footer (e.g. a standalone HTML, LaTeX, or RTF file, not a fragment). This option is set automatically for \f[C]pdf\f[], \f[C]epub\f[], \f[C]epub3\f[], \f[C]fb2\f[], \f[C]docx\f[], and \f[C]odt\f[] output. .RS .RE .TP .B \f[C]\-\-template=\f[]\f[I]FILE\f[] Use \f[I]FILE\f[] as a custom template for the generated document. Implies \f[C]\-\-standalone\f[]. See Templates below for a description of template syntax. If no extension is specified, an extension corresponding to the writer will be added, so that \f[C]\-\-template=special\f[] looks for \f[C]special.html\f[] for HTML output. If the template is not found, pandoc will search for it in the user data directory (see \f[C]\-\-data\-dir\f[]). If this option is not used, a default template appropriate for the output format will be used (see \f[C]\-D/\-\-print\-default\-template\f[]). .RS .RE .TP .B \f[C]\-V\f[] \f[I]KEY[=VAL]\f[], \f[C]\-\-variable=\f[]\f[I]KEY[:VAL]\f[] Set the template variable \f[I]KEY\f[] to the value \f[I]VAL\f[] when rendering the document in standalone mode. This is generally only useful when the \f[C]\-\-template\f[] option is used to specify a custom template, since pandoc automatically sets the variables used in the default templates. If no \f[I]VAL\f[] is specified, the key will be given the value \f[C]true\f[]. .RS .RE .TP .B \f[C]\-D\f[] \f[I]FORMAT\f[], \f[C]\-\-print\-default\-template=\f[]\f[I]FORMAT\f[] Print the default template for an output \f[I]FORMAT\f[]. (See \f[C]\-t\f[] for a list of possible \f[I]FORMAT\f[]s.) .RS .RE .TP .B \f[C]\-\-print\-default\-data\-file=\f[]\f[I]FILE\f[] Print a default data file. .RS .RE .TP .B \f[C]\-\-no\-wrap\f[] Disable text wrapping in output. By default, text is wrapped appropriately for the output format. .RS .RE .TP .B \f[C]\-\-columns\f[]=\f[I]NUMBER\f[] Specify length of lines in characters (for text wrapping). .RS .RE .TP .B \f[C]\-\-toc\f[], \f[C]\-\-table\-of\-contents\f[] Include an automatically generated table of contents (or, in the case of \f[C]latex\f[], \f[C]context\f[], and \f[C]rst\f[], an instruction to create one) in the output document. This option has no effect on \f[C]man\f[], \f[C]docbook\f[], \f[C]slidy\f[], \f[C]slideous\f[], \f[C]s5\f[], \f[C]docx\f[], or \f[C]odt\f[] output. .RS .RE .TP .B \f[C]\-\-toc\-depth=\f[]\f[I]NUMBER\f[] Specify the number of section levels to include in the table of contents. The default is 3 (which means that level 1, 2, and 3 headers will be listed in the contents). .RS .RE .TP .B \f[C]\-\-no\-highlight\f[] Disables syntax highlighting for code blocks and inlines, even when a language attribute is given. .RS .RE .TP .B \f[C]\-\-highlight\-style\f[]=\f[I]STYLE\f[] Specifies the coloring style to be used in highlighted source code. Options are \f[C]pygments\f[] (the default), \f[C]kate\f[], \f[C]monochrome\f[], \f[C]espresso\f[], \f[C]zenburn\f[], \f[C]haddock\f[], and \f[C]tango\f[]. .RS .RE .TP .B \f[C]\-H\f[] \f[I]FILE\f[], \f[C]\-\-include\-in\-header=\f[]\f[I]FILE\f[] Include contents of \f[I]FILE\f[], verbatim, at the end of the header. This can be used, for example, to include special CSS or javascript in HTML documents. This option can be used repeatedly to include multiple files in the header. They will be included in the order specified. Implies \f[C]\-\-standalone\f[]. .RS .RE .TP .B \f[C]\-B\f[] \f[I]FILE\f[], \f[C]\-\-include\-before\-body=\f[]\f[I]FILE\f[] Include contents of \f[I]FILE\f[], verbatim, at the beginning of the document body (e.g. after the \f[C]<body>\f[] tag in HTML, or the \f[C]\\begin{document}\f[] command in LaTeX). This can be used to include navigation bars or banners in HTML documents. This option can be used repeatedly to include multiple files. They will be included in the order specified. Implies \f[C]\-\-standalone\f[]. .RS .RE .TP .B \f[C]\-A\f[] \f[I]FILE\f[], \f[C]\-\-include\-after\-body=\f[]\f[I]FILE\f[] Include contents of \f[I]FILE\f[], verbatim, at the end of the document body (before the \f[C]</body>\f[] tag in HTML, or the \f[C]\\end{document}\f[] command in LaTeX). This option can be be used repeatedly to include multiple files. They will be included in the order specified. Implies \f[C]\-\-standalone\f[]. .RS .RE .SS Options affecting specific writers .TP .B \f[C]\-\-self\-contained\f[] Produce a standalone HTML file with no external dependencies, using \f[C]data:\f[] URIs to incorporate the contents of linked scripts, stylesheets, images, and videos. The resulting file should be "self\-contained," in the sense that it needs no external files and no net access to be displayed properly by a browser. This option works only with HTML output formats, including \f[C]html\f[], \f[C]html5\f[], \f[C]html+lhs\f[], \f[C]html5+lhs\f[], \f[C]s5\f[], \f[C]slidy\f[], \f[C]slideous\f[], \f[C]dzslides\f[], and \f[C]revealjs\f[]. Scripts, images, and stylesheets at absolute URLs will be downloaded; those at relative URLs will be sought first relative to the working directory, then relative to the user data directory (see \f[C]\-\-data\-dir\f[]), and finally relative to pandoc\[aq]s default data directory. \f[C]\-\-self\-contained\f[] does not work with \f[C]\-\-mathjax\f[]. .RS .RE .TP .B \f[C]\-\-offline\f[] Deprecated synonym for \f[C]\-\-self\-contained\f[]. .RS .RE .TP .B \f[C]\-5\f[], \f[C]\-\-html5\f[] Produce HTML5 instead of HTML4. This option has no effect for writers other than \f[C]html\f[]. (\f[I]Deprecated:\f[] Use the \f[C]html5\f[] output format instead.) .RS .RE .TP .B \f[C]\-\-html\-q\-tags\f[] Use \f[C]<q>\f[] tags for quotes in HTML. .RS .RE .TP .B \f[C]\-\-ascii\f[] Use only ascii characters in output. Currently supported only for HTML output (which uses numerical entities instead of UTF\-8 when this option is selected). .RS .RE .TP .B \f[C]\-\-reference\-links\f[] Use reference\-style links, rather than inline links, in writing markdown or reStructuredText. By default inline links are used. .RS .RE .TP .B \f[C]\-\-atx\-headers\f[] Use ATX style headers in markdown and asciidoc output. The default is to use setext\-style headers for levels 1\-2, and then ATX headers. .RS .RE .TP .B \f[C]\-\-chapters\f[] 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 \f[C]\-\-beamer\f[] is used, top\-level headers will become \f[C]\\part{..}\f[]. .RS .RE .TP .B \f[C]\-N\f[], \f[C]\-\-number\-sections\f[] Number section headings in LaTeX, ConTeXt, HTML, or EPUB output. By default, sections are not numbered. Sections with class \f[C]unnumbered\f[] will never be numbered, even if \f[C]\-\-number\-sections\f[] is specified. .RS .RE .TP .B \f[C]\-\-number\-offset\f[]=\f[I]NUMBER[,NUMBER,...]\f[], Offset for section headings in HTML output (ignored in other output formats). The first number is added to the section number for top\-level headers, the second for second\-level headers, and so on. So, for example, if you want the first top\-level header in your document to be numbered "6", specify \f[C]\-\-number\-offset=5\f[]. If your document starts with a level\-2 header which you want to be numbered "1.5", specify \f[C]\-\-number\-offset=1,4\f[]. Offsets are 0 by default. Implies \f[C]\-\-number\-sections\f[]. .RS .RE .TP .B \f[C]\-\-no\-tex\-ligatures\f[] Do not convert quotation marks, apostrophes, and dashes to the TeX ligatures when writing LaTeX or ConTeXt. Instead, just use literal unicode characters. This is needed for using advanced OpenType features with XeLaTeX and LuaLaTeX. Note: normally \f[C]\-\-smart\f[] is selected automatically for LaTeX and ConTeXt output, but it must be specified explicitly if \f[C]\-\-no\-tex\-ligatures\f[] is selected. If you use literal curly quotes, dashes, and ellipses in your source, then you may want to use \f[C]\-\-no\-tex\-ligatures\f[] without \f[C]\-\-smart\f[]. .RS .RE .TP .B \f[C]\-\-listings\f[] Use listings package for LaTeX code blocks .RS .RE .TP .B \f[C]\-i\f[], \f[C]\-\-incremental\f[] Make list items in slide shows display incrementally (one by one). The default is for lists to be displayed all at once. .RS .RE .TP .B \f[C]\-\-slide\-level\f[]=\f[I]NUMBER\f[] Specifies that headers with the specified level create slides (for \f[C]beamer\f[], \f[C]s5\f[], \f[C]slidy\f[], \f[C]slideous\f[], \f[C]dzslides\f[]). Headers above this level in the hierarchy are used to divide the slide show into sections; headers below this level create subheads within a slide. The default is to set the slide level based on the contents of the document; see Structuring the slide show, below. .RS .RE .TP .B \f[C]\-\-section\-divs\f[] Wrap sections in \f[C]<div>\f[] tags (or \f[C]<section>\f[] tags in HTML5), and attach identifiers to the enclosing \f[C]<div>\f[] (or \f[C]<section>\f[]) rather than the header itself. See Section identifiers, below. .RS .RE .TP .B \f[C]\-\-email\-obfuscation=\f[]\f[I]none|javascript|references\f[] Specify a method for obfuscating \f[C]mailto:\f[] links in HTML documents. \f[I]none\f[] leaves \f[C]mailto:\f[] links as they are. \f[I]javascript\f[] obfuscates them using javascript. \f[I]references\f[] obfuscates them by printing their letters as decimal or hexadecimal character references. .RS .RE .TP .B \f[C]\-\-id\-prefix\f[]=\f[I]STRING\f[] Specify a prefix to be added to all automatically generated identifiers in HTML and DocBook output, and to footnote numbers in markdown output. This is useful for preventing duplicate identifiers when generating fragments to be included in other pages. .RS .RE .TP .B \f[C]\-T\f[] \f[I]STRING\f[], \f[C]\-\-title\-prefix=\f[]\f[I]STRING\f[] Specify \f[I]STRING\f[] as a prefix at the beginning of the title that appears in the HTML header (but not in the title as it appears at the beginning of the HTML body). Implies \f[C]\-\-standalone\f[]. .RS .RE .TP .B \f[C]\-c\f[] \f[I]URL\f[], \f[C]\-\-css=\f[]\f[I]URL\f[] Link to a CSS style sheet. This option can be be used repeatedly to include multiple files. They will be included in the order specified. .RS .RE .TP .B \f[C]\-\-reference\-odt=\f[]\f[I]FILE\f[] Use the specified file as a style reference in producing an ODT. For best results, the reference ODT should be a modified version of an ODT produced using pandoc. The contents of the reference ODT are ignored, but its stylesheets are used in the new ODT. If no reference ODT is specified on the command line, pandoc will look for a file \f[C]reference.odt\f[] in the user data directory (see \f[C]\-\-data\-dir\f[]). If this is not found either, sensible defaults will be used. .RS .RE .TP .B \f[C]\-\-reference\-docx=\f[]\f[I]FILE\f[] Use the specified file as a style reference in producing a docx file. For best results, the reference docx should be a modified version of a docx file produced using pandoc. The contents of the reference docx are ignored, but its stylesheets are used in the new docx. If no reference docx is specified on the command line, pandoc will look for a file \f[C]reference.docx\f[] in the user data directory (see \f[C]\-\-data\-dir\f[]). If this is not found either, sensible defaults will be used. The following styles are used by pandoc: [paragraph] Normal, Compact, Title, Authors, Date, Heading 1, Heading 2, Heading 3, Heading 4, Heading 5, Block Quote, Definition Term, Definition, Body Text, Table Caption, Image Caption; [character] Default Paragraph Font, Body Text Char, Verbatim Char, Footnote Ref, Link. .RS .RE .TP .B \f[C]\-\-epub\-stylesheet=\f[]\f[I]FILE\f[] Use the specified CSS file to style the EPUB. If no stylesheet is specified, pandoc will look for a file \f[C]epub.css\f[] in the user data directory (see \f[C]\-\-data\-dir\f[]). If it is not found there, sensible defaults will be used. .RS .RE .TP .B \f[C]\-\-epub\-cover\-image=\f[]\f[I]FILE\f[] Use the specified image as the EPUB cover. It is recommended that the image be less than 1000px in width and height. Note that in a markdown source document you can also specify \f[C]cover\-image\f[] in a YAML metadata block (see EPUB Metadata, below). .RS .RE .TP .B \f[C]\-\-epub\-metadata=\f[]\f[I]FILE\f[] Look in the specified XML file for metadata for the EPUB. The file should contain a series of Dublin Core elements, as documented at http://dublincore.org/documents/dces/. For example: .RS .IP .nf \f[C] \ <dc:rights>Creative\ Commons</dc:rights> \ <dc:language>es\-AR</dc:language> \f[] .fi .PP By default, pandoc will include the following metadata elements: \f[C]<dc:title>\f[] (from the document title), \f[C]<dc:creator>\f[] (from the document authors), \f[C]<dc:date>\f[] (from the document date, which should be in ISO 8601 format), \f[C]<dc:language>\f[] (from the \f[C]lang\f[] variable, or, if is not set, the locale), and \f[C]<dc:identifier\ id="BookId">\f[] (a randomly generated UUID). Any of these may be overridden by elements in the metadata file. .PP Note: if the source document is markdown, a YAML metadata block in the document can be used instead. See below under EPUB Metadata. .RE .TP .B \f[C]\-\-epub\-embed\-font=\f[]\f[I]FILE\f[] Embed the specified font in the EPUB. This option can be repeated to embed multiple fonts. To use embedded fonts, you will need to add declarations like the following to your CSS (see \f[C]\-\-epub\-stylesheet\f[]): .RS .IP .nf \f[C] \@font\-face\ { font\-family:\ DejaVuSans; font\-style:\ normal; font\-weight:\ normal; src:url("DejaVuSans\-Regular.ttf"); } \@font\-face\ { font\-family:\ DejaVuSans; font\-style:\ normal; font\-weight:\ bold; src:url("DejaVuSans\-Bold.ttf"); } \@font\-face\ { font\-family:\ DejaVuSans; font\-style:\ italic; font\-weight:\ normal; src:url("DejaVuSans\-Oblique.ttf"); } \@font\-face\ { font\-family:\ DejaVuSans; font\-style:\ italic; font\-weight:\ bold; src:url("DejaVuSans\-BoldOblique.ttf"); } body\ {\ font\-family:\ "DejaVuSans";\ } \f[] .fi .RE .TP .B \f[C]\-\-epub\-chapter\-level=\f[]\f[I]NUMBER\f[] Specify the header level at which to split the EPUB into separate "chapter" files. The default is to split into chapters at level 1 headers. This option only affects the internal composition of the EPUB, not the way chapters and sections are displayed to users. Some readers may be slow if the chapter files are too large, so for large documents with few level 1 headers, one might want to use a chapter level of 2 or 3. .RS .RE .TP .B \f[C]\-\-latex\-engine=\f[]\f[I]pdflatex|lualatex|xelatex\f[] Use the specified LaTeX engine when producing PDF output. The default is \f[C]pdflatex\f[]. If the engine is not in your PATH, the full path of the engine may be specified here. .RS .RE .SS Citation rendering .TP .B \f[C]\-\-bibliography=\f[]\f[I]FILE\f[] Set the \f[C]bibliography\f[] field in the document\[aq]s metadata to \f[I]FILE\f[], overriding any value set in the metadata, and process citations using \f[C]pandoc\-citeproc\f[]. (This is equivalent to \f[C]\-\-metadata\ bibliography=FILE\ \-\-filter\ pandoc\-citeproc\f[].) .RS .RE .TP .B \f[C]\-\-csl=\f[]\f[I]FILE\f[] Set the \f[C]csl\f[] field in the document\[aq]s metadata to \f[I]FILE\f[], overriding any value set in the metadata. (This is equivalent to \f[C]\-\-metadata\ csl=FILE\f[].) .RS .RE .TP .B \f[C]\-\-citation\-abbreviations=\f[]\f[I]FILE\f[] Set the \f[C]citation\-abbreviations\f[] field in the document\[aq]s metadata to \f[I]FILE\f[], overriding any value set in the metadata. (This is equivalent to \f[C]\-\-metadata\ citation\-abbreviations=FILE\f[].) .RS .RE .TP .B \f[C]\-\-natbib\f[] Use natbib for citations in LaTeX output. .RS .RE .TP .B \f[C]\-\-biblatex\f[] Use biblatex for citations in LaTeX output. .RS .RE .SS Math rendering in HTML .TP .B \f[C]\-m\f[] [\f[I]URL\f[]], \f[C]\-\-latexmathml\f[][=\f[I]URL\f[]] Use the LaTeXMathML script to display embedded TeX math in HTML output. To insert a link to a local copy of the \f[C]LaTeXMathML.js\f[] script, provide a \f[I]URL\f[]. If no \f[I]URL\f[] is provided, the contents of the script will be inserted directly into the HTML header, preserving portability at the price of efficiency. If you plan to use math on several pages, it is much better to link to a copy of the script, so it can be cached. .RS .RE .TP .B \f[C]\-\-mathml\f[][=\f[I]URL\f[]] Convert TeX math to MathML (in \f[C]docbook\f[] as well as \f[C]html\f[] and \f[C]html5\f[]). In standalone \f[C]html\f[] output, a small javascript (or a link to such a script if a \f[I]URL\f[] is supplied) will be inserted that allows the MathML to be viewed on some browsers. .RS .RE .TP .B \f[C]\-\-jsmath\f[][=\f[I]URL\f[]] Use jsMath to display embedded TeX math in HTML output. The \f[I]URL\f[] should point to the jsMath load script (e.g. \f[C]jsMath/easy/load.js\f[]); if provided, it will be linked to in the header of standalone HTML documents. If a \f[I]URL\f[] is not provided, no link to the jsMath load script will be inserted; it is then up to the author to provide such a link in the HTML template. .RS .RE .TP .B \f[C]\-\-mathjax\f[][=\f[I]URL\f[]] Use MathJax to display embedded TeX math in HTML output. The \f[I]URL\f[] should point to the \f[C]MathJax.js\f[] load script. If a \f[I]URL\f[] is not provided, a link to the MathJax CDN will be inserted. .RS .RE .TP .B \f[C]\-\-gladtex\f[] Enclose TeX math in \f[C]<eq>\f[] tags in HTML output. These can then be processed by gladTeX to produce links to images of the typeset formulas. .RS .RE .TP .B \f[C]\-\-mimetex\f[][=\f[I]URL\f[]] Render TeX math using the mimeTeX CGI script. If \f[I]URL\f[] is not specified, it is assumed that the script is at \f[C]/cgi\-bin/mimetex.cgi\f[]. .RS .RE .TP .B \f[C]\-\-webtex\f[][=\f[I]URL\f[]] Render TeX formulas using an external script that converts TeX formulas to images. The formula will be concatenated with the URL provided. If \f[I]URL\f[] is not specified, the Google Chart API will be used. .RS .RE .SS Options for wrapper scripts .TP .B \f[C]\-\-dump\-args\f[] Print information about command\-line arguments to \f[I]stdout\f[], then exit. This option is intended primarily for use in wrapper scripts. The first line of output contains the name of the output file specified with the \f[C]\-o\f[] option, or \f[C]\-\f[] (for \f[I]stdout\f[]) if no output file was specified. The remaining lines contain the command\-line arguments, one per line, in the order they appear. These do not include regular Pandoc options and their arguments, but do include any options appearing after a \f[C]\-\-\f[] separator at the end of the line. .RS .RE .TP .B \f[C]\-\-ignore\-args\f[] Ignore command\-line arguments (for use in wrapper scripts). Regular Pandoc options are not ignored. Thus, for example, .RS .IP .nf \f[C] pandoc\ \-\-ignore\-args\ \-o\ foo.html\ \-s\ foo.txt\ \-\-\ \-e\ latin1 \f[] .fi .PP is equivalent to .IP .nf \f[C] pandoc\ \-o\ foo.html\ \-s \f[] .fi .RE .SH TEMPLATES .PP When the \f[C]\-s/\-\-standalone\f[] option is used, pandoc uses a template to add header and footer material that is needed for a self\-standing document. To see the default template that is used, just type .IP .nf \f[C] pandoc\ \-D\ FORMAT \f[] .fi .PP where \f[C]FORMAT\f[] is the name of the output format. A custom template can be specified using the \f[C]\-\-template\f[] option. You can also override the system default templates for a given output format \f[C]FORMAT\f[] by putting a file \f[C]templates/default.FORMAT\f[] in the user data directory (see \f[C]\-\-data\-dir\f[], above). \f[I]Exceptions:\f[] For \f[C]odt\f[] output, customize the \f[C]default.opendocument\f[] template. For \f[C]pdf\f[] output, customize the \f[C]default.latex\f[] template. .PP Templates may contain \f[I]variables\f[]. Variable names are sequences of alphanumerics, \f[C]\-\f[], and \f[C]_\f[], starting with a letter. A variable name surrounded by \f[C]$\f[] signs will be replaced by its value. For example, the string \f[C]$title$\f[] in .IP .nf \f[C] <title>$title$ \f[] .fi .PP will be replaced by the document title. .PP To write a literal \f[C]$\f[] in a template, use \f[C]$$\f[]. .PP Some variables are set automatically by pandoc. These vary somewhat depending on the output format, but include metadata fields (such as \f[C]title\f[], \f[C]author\f[], and \f[C]date\f[]) as well as the following: .TP .B \f[C]header\-includes\f[] contents specified by \f[C]\-H/\-\-include\-in\-header\f[] (may have multiple values) .RS .RE .TP .B \f[C]toc\f[] non\-null value if \f[C]\-\-toc/\-\-table\-of\-contents\f[] was specified .RS .RE .TP .B \f[C]include\-before\f[] contents specified by \f[C]\-B/\-\-include\-before\-body\f[] (may have multiple values) .RS .RE .TP .B \f[C]include\-after\f[] contents specified by \f[C]\-A/\-\-include\-after\-body\f[] (may have multiple values) .RS .RE .TP .B \f[C]body\f[] body of document .RS .RE .TP .B \f[C]lang\f[] language code for HTML or LaTeX documents .RS .RE .TP .B \f[C]slidy\-url\f[] base URL for Slidy documents (defaults to \f[C]http://www.w3.org/Talks/Tools/Slidy2\f[]) .RS .RE .TP .B \f[C]slideous\-url\f[] base URL for Slideous documents (defaults to \f[C]default\f[]) .RS .RE .TP .B \f[C]s5\-url\f[] base URL for S5 documents (defaults to \f[C]ui/default\f[]) .RS .RE .TP .B \f[C]revealjs\-url\f[] base URL for reveal.js documents (defaults to \f[C]reveal.js\f[]) .RS .RE .TP .B \f[C]theme\f[] reveal.js or LaTeX beamer theme .RS .RE .TP .B \f[C]transition\f[] reveal.js transition .RS .RE .TP .B \f[C]fontsize\f[] font size (10pt, 11pt, 12pt) for LaTeX documents .RS .RE .TP .B \f[C]documentclass\f[] document class for LaTeX documents .RS .RE .TP .B \f[C]classoption\f[] option for LaTeX documentclass, e.g. \f[C]oneside\f[]; may be repeated for multiple options .RS .RE .TP .B \f[C]geometry\f[] options for LaTeX \f[C]geometry\f[] class, e.g. \f[C]margin=1in\f[]; may be repeated for multiple options .RS .RE .TP .B \f[C]mainfont\f[], \f[C]sansfont\f[], \f[C]monofont\f[], \f[C]mathfont\f[] fonts for LaTeX documents (works only with xelatex and lualatex) .RS .RE .TP .B \f[C]colortheme\f[] colortheme for LaTeX beamer documents .RS .RE .TP .B \f[C]fonttheme\f[] fonttheme for LaTeX beamer documents .RS .RE .TP .B \f[C]linkcolor\f[] color for internal links in LaTeX documents (\f[C]red\f[], \f[C]green\f[], \f[C]magenta\f[], \f[C]cyan\f[], \f[C]blue\f[], \f[C]black\f[]) .RS .RE .TP .B \f[C]urlcolor\f[] color for external links in LaTeX documents .RS .RE .TP .B \f[C]citecolor\f[] color for citation links in LaTeX documents .RS .RE .TP .B \f[C]links\-as\-notes\f[] causes links to be printed as footnotes in LaTeX documents .RS .RE .TP .B \f[C]biblio\-style\f[] bibliography style in LaTeX, when used with \f[C]\-\-natbib\f[] .RS .RE .TP .B \f[C]section\f[] section number in man pages .RS .RE .TP .B \f[C]header\f[] header in man pages .RS .RE .TP .B \f[C]footer\f[] footer in man pages .RS .RE .PP Variables may be set at the command line using the \f[C]\-V/\-\-variable\f[] option. Variables set in this way override metadata fields with the same name. .PP Templates may contain conditionals. The syntax is as follows: .IP .nf \f[C] $if(variable)$ X $else$ Y $endif$ \f[] .fi .PP This will include \f[C]X\f[] in the template if \f[C]variable\f[] has a non\-null value; otherwise it will include \f[C]Y\f[]. \f[C]X\f[] and \f[C]Y\f[] are placeholders for any valid template text, and may include interpolated variables or other conditionals. The \f[C]$else$\f[] section may be omitted. .PP When variables can have multiple values (for example, \f[C]author\f[] in a multi\-author document), you can use the \f[C]$for$\f[] keyword: .IP .nf \f[C] $for(author)$ $endfor$ \f[] .fi .PP You can optionally specify a separator to be used between consecutive items: .IP .nf \f[C] $for(author)$$author$$sep$,\ $endfor$ \f[] .fi .PP A dot can be used to select a field of a variable that takes an object as its value. So, for example: .IP .nf \f[C] $author.name$\ ($author.affiliation$) \f[] .fi .PP If you use custom templates, you may need to revise them as pandoc changes. We recommend tracking the changes in the default templates, and modifying your custom templates accordingly. An easy way to do this is to fork the pandoc\-templates repository (http://github.com/jgm/pandoc\-templates) and merge in changes after each pandoc release. .SH PRODUCING SLIDE SHOWS WITH PANDOC .PP You can use Pandoc to produce an HTML + javascript slide presentation that can be viewed via a web browser. There are five ways to do this, using S5, DZSlides, Slidy, Slideous, or reveal.js. You can also produce a PDF slide show using LaTeX beamer. .PP Here\[aq]s the markdown source for a simple slide show, \f[C]habits.txt\f[]: .IP .nf \f[C] %\ Habits %\ John\ Doe %\ March\ 22,\ 2005 #\ In\ the\ morning ##\ Getting\ up \-\ Turn\ off\ alarm \-\ Get\ out\ of\ bed ##\ Breakfast \-\ Eat\ eggs \-\ Drink\ coffee #\ In\ the\ evening ##\ Dinner \-\ Eat\ spaghetti \-\ Drink\ wine \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- ![picture\ of\ spaghetti](images/spaghetti.jpg) ##\ Going\ to\ sleep \-\ Get\ in\ bed \-\ Count\ sheep \f[] .fi .PP To produce an HTML/javascript slide show, simply type .IP .nf \f[C] pandoc\ \-t\ FORMAT\ \-s\ habits.txt\ \-o\ habits.html \f[] .fi .PP where \f[C]FORMAT\f[] is either \f[C]s5\f[], \f[C]slidy\f[], \f[C]slideous\f[], \f[C]dzslides\f[], or \f[C]revealjs\f[]. .PP For Slidy, Slideous, reveal.js, and S5, the file produced by pandoc with the \f[C]\-s/\-\-standalone\f[] option embeds a link to javascripts and CSS files, which are assumed to be available at the relative path \f[C]s5/default\f[] (for S5), \f[C]slideous\f[] (for Slideous), \f[C]reveal.js\f[] (for reveal.js), or at the Slidy website at \f[C]w3.org\f[] (for Slidy). (These paths can be changed by setting the \f[C]slidy\-url\f[], \f[C]slideous\-url\f[], \f[C]revealjs\-url\f[], or \f[C]s5\-url\f[] variables; see \f[C]\-\-variable\f[], above.) For DZSlides, the (relatively short) javascript and css are included in the file by default. .PP With all HTML slide formats, the \f[C]\-\-self\-contained\f[] option can be used to produce a single file that contains all of the data necessary to display the slide show, including linked scripts, stylesheets, images, and videos. .PP To produce a PDF slide show using beamer, type .IP .nf \f[C] pandoc\ \-t\ beamer\ habits.txt\ \-o\ habits.pdf \f[] .fi .PP Note that a reveal.js slide show can also be converted to a PDF by printing it to a file from the browser. .SS Structuring the slide show .PP By default, the \f[I]slide level\f[] is the highest header level in the hierarchy that is followed immediately by content, and not another header, somewhere in the document. In the example above, level 1 headers are always followed by level 2 headers, which are followed by content, so 2 is the slide level. This default can be overridden using the \f[C]\-\-slide\-level\f[] option. .PP The document is carved up into slides according to the following rules: .IP \[bu] 2 A horizontal rule always starts a new slide. .IP \[bu] 2 A header at the slide level always starts a new slide. .IP \[bu] 2 Headers \f[I]below\f[] the slide level in the hierarchy create headers \f[I]within\f[] a slide. .IP \[bu] 2 Headers \f[I]above\f[] the slide level in the hierarchy create "title slides," which just contain the section title and help to break the slide show into sections. .IP \[bu] 2 A title page is constructed automatically from the document\[aq]s title block, if present. (In the case of beamer, this can be disabled by commenting out some lines in the default template.) .PP These rules are designed to support many different styles of slide show. If you don\[aq]t care about structuring your slides into sections and subsections, you can just use level 1 headers for all each slide. (In that case, level 1 will be the slide level.) But you can also structure the slide show into sections, as in the example above. .PP Note: in reveal.js slide shows, if slide level is 2, a two\-dimensional layout will be produced, with level 1 headers building horizontally and level 2 headers building vertically. It is not recommended that you use deeper nesting of section levels with reveal.js. .SS Incremental lists .PP By default, these writers produces lists that display "all at once." If you want your lists to display incrementally (one item at a time), use the \f[C]\-i\f[] option. If you want a particular list to depart from the default (that is, to display incrementally without the \f[C]\-i\f[] option and all at once with the \f[C]\-i\f[] option), put it in a block quote: .IP .nf \f[C] >\ \-\ Eat\ spaghetti >\ \-\ Drink\ wine \f[] .fi .PP In this way incremental and nonincremental lists can be mixed in a single document. .SS Inserting pauses .PP You can add "pauses" within a slide by including a paragraph containing three dots, separated by spaces: .IP .nf \f[C] #\ Slide\ with\ a\ pause content\ before\ the\ pause \&.\ .\ . content\ after\ the\ pause \f[] .fi .SS Styling the slides .PP You can change the style of HTML slides by putting customized CSS files in \f[C]$DATADIR/s5/default\f[] (for S5), \f[C]$DATADIR/slidy\f[] (for Slidy), or \f[C]$DATADIR/slideous\f[] (for Slideous), where \f[C]$DATADIR\f[] is the user data directory (see \f[C]\-\-data\-dir\f[], above). The originals may be found in pandoc\[aq]s system data directory (generally \f[C]$CABALDIR/pandoc\-VERSION/s5/default\f[]). Pandoc will look there for any files it does not find in the user data directory. .PP For dzslides, the CSS is included in the HTML file itself, and may be modified there. .PP For reveal.js, themes can be used by setting the \f[C]theme\f[] variable, for example: .IP .nf \f[C] \-V\ theme=moon \f[] .fi .PP Or you can specify a custom stylesheet using the \f[C]\-\-css\f[] option. .PP To style beamer slides, you can specify a beamer "theme" or "colortheme" using the \f[C]\-V\f[] option: .IP .nf \f[C] pandoc\ \-t\ beamer\ habits.txt\ \-V\ theme:Warsaw\ \-o\ habits.pdf \f[] .fi .PP Note that header attributes will turn into slide attributes (on a \f[C]

\f[] or \f[C]
\f[]) in HTML slide formats, allowing you to style individual slides. In Beamer, the only header attribute that affects slides is the \f[C]allowframebreaks\f[] class, which sets the \f[C]allowframebreaks\f[] option, causing multiple slides to be created if the content overfills the frame. This is recommended especially for bibliographies: .IP .nf \f[C] #\ References\ {.allowframebreaks} \f[] .fi .SS Speaker notes .PP reveal.js has good support for speaker notes. You can add notes to your markdown document thus: .IP .nf \f[C] This\ is\ my\ note. \-\ It\ can\ contain\ markdown \-\ like\ this\ list
\f[] .fi .PP To show the notes window, press \f[C]s\f[] while viewing the presentation. Notes are not yet supported for other slide formats, but the notes will not appear on the slides themselves. .SH EPUB METADATA .PP EPUB metadata may be specified using the \f[C]\-\-epub\-metadata\f[] option, but if the source document is markdown, it is better to use a YAML metadata block. Here is an example: .IP .nf \f[C] \-\-\- 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 \&... \f[] .fi .PP The following fields are recognized: .TP .B \f[C]identifier\f[] Either a string value or an object with fields \f[C]text\f[] and \f[C]scheme\f[]. Valid values for \f[C]scheme\f[] are \f[C]ISBN\-10\f[], \f[C]GTIN\-13\f[], \f[C]UPC\f[], \f[C]ISMN\-10\f[], \f[C]DOI\f[], \f[C]LCCN\f[], \f[C]GTIN\-14\f[], \f[C]ISBN\-13\f[], \f[C]Legal\ deposit\ number\f[], \f[C]URN\f[], \f[C]OCLC\f[], \f[C]ISMN\-13\f[], \f[C]ISBN\-A\f[], \f[C]JP\f[], \f[C]OLCC\f[]. .RS .RE .TP .B \f[C]title\f[] Either a string value, or an object with fields \f[C]file\-as\f[] and \f[C]type\f[], or a list of such objects. Valid values for \f[C]type\f[] are \f[C]main\f[], \f[C]subtitle\f[], \f[C]short\f[], \f[C]collection\f[], \f[C]edition\f[], \f[C]extended\f[]. .RS .RE .TP .B \f[C]creator\f[] Either a string value, or an object with fields \f[C]role\f[], \f[C]file\-as\f[], and \f[C]text\f[], or a list of such objects. Valid values for \f[C]role\f[] are marc relators, but pandoc will attempt to translate the human\-readable versions (like "author" and "editor") to the appropriate marc relators. .RS .RE .TP .B \f[C]contributor\f[] Same format as \f[C]creator\f[]. .RS .RE .TP .B \f[C]date\f[] A string value in \f[C]YYYY\-MM\-DD\f[] format. (Only the year is necessary.) Pandoc will attempt to convert other common date formats. .RS .RE .TP .B \f[C]language\f[] A string value in RFC5646 format. Pandoc will default to the local language if nothing is specified. .RS .RE .TP .B \f[C]subject\f[] A string value or a list of such values. .RS .RE .TP .B \f[C]description\f[] A string value. .RS .RE .TP .B \f[C]type\f[] A string value. .RS .RE .TP .B \f[C]format\f[] A string value. .RS .RE .TP .B \f[C]relation\f[] A string value. .RS .RE .TP .B \f[C]coverage\f[] A string value. .RS .RE .TP .B \f[C]rights\f[] A string value. .RS .RE .TP .B \f[C]cover\-image\f[] A string value (path to cover image). .RS .RE .TP .B \f[C]stylesheet\f[] A string value (path to CSS stylesheet). .RS .RE .SH LITERATE HASKELL SUPPORT .PP If you append \f[C]+lhs\f[] (or \f[C]+literate_haskell\f[]) to an appropriate input or output format (\f[C]markdown\f[], \f[C]mardkown_strict\f[], \f[C]rst\f[], or \f[C]latex\f[] for input or output; \f[C]beamer\f[], \f[C]html\f[] or \f[C]html5\f[] for output only), pandoc will treat the document as literate Haskell source. This means that .IP \[bu] 2 In markdown input, "bird track" sections will be parsed as Haskell code rather than block quotations. Text between \f[C]\\begin{code}\f[] and \f[C]\\end{code}\f[] will also be treated as Haskell code. .IP \[bu] 2 In markdown output, code blocks with classes \f[C]haskell\f[] and \f[C]literate\f[] will be rendered using bird tracks, and block quotations will be indented one space, so they will not be treated as Haskell code. In addition, headers will be rendered setext\-style (with underlines) rather than atx\-style (with \[aq]#\[aq] characters). (This is because ghc treats \[aq]#\[aq] characters in column 1 as introducing line numbers.) .IP \[bu] 2 In restructured text input, "bird track" sections will be parsed as Haskell code. .IP \[bu] 2 In restructured text output, code blocks with class \f[C]haskell\f[] will be rendered using bird tracks. .IP \[bu] 2 In LaTeX input, text in \f[C]code\f[] environments will be parsed as Haskell code. .IP \[bu] 2 In LaTeX output, code blocks with class \f[C]haskell\f[] will be rendered inside \f[C]code\f[] environments. .IP \[bu] 2 In HTML output, code blocks with class \f[C]haskell\f[] will be rendered with class \f[C]literatehaskell\f[] and bird tracks. .PP Examples: .IP .nf \f[C] pandoc\ \-f\ markdown+lhs\ \-t\ html \f[] .fi .PP reads literate Haskell source formatted with markdown conventions and writes ordinary HTML (without bird tracks). .IP .nf \f[C] pandoc\ \-f\ markdown+lhs\ \-t\ html+lhs \f[] .fi .PP writes HTML with the Haskell code in bird tracks, so it can be copied and pasted as literate Haskell source. .SH CUSTOM WRITERS .PP Pandoc can be extended with custom writers written in lua. (Pandoc includes a lua interpreter, so lua need not be installed separately.) .PP To use a custom writer, simply specify the path to the lua script in place of the output format. For example: .IP .nf \f[C] pandoc\ \-t\ data/sample.lua \f[] .fi .PP Creating a custom writer requires writing a lua function for each possible element in a pandoc document. To get a documented example which you can modify according to your needs, do .IP .nf \f[C] pandoc\ \-\-print\-default\-data\-file\ sample.lua \f[] .fi .SH AUTHORS .PP © 2006\-2013 John MacFarlane (jgm at berkeley dot edu). Released under the GPL, version 2 or greater. This software carries no warranty of any kind. (See COPYRIGHT for full copyright and warranty notices.) Other contributors include Recai Oktaş, Paulo Tanimoto, Peter Wang, Andrea Rossato, Eric Kow, infinity0x, Luke Plant, shreevatsa.public, Puneeth Chaganti, Paul Rivier, rodja.trappe, Bradley Kuhn, thsutton, Nathan Gass, Jonathan Daugherty, Jérémy Bobbio, Justin Bogner, qerub, Christopher Sawicki, Kelsey Hightower, Masayoshi Takahashi, Antoine Latter, Ralf Stephan, Eric Seidel, B. Scott Michel, Gavin Beatty, Sergey Astanin, Arlo O\[aq]Keeffe, Denis Laxalde, Brent Yorgey, David Lazar, Jamie F. Olson. .SH PANDOC'S MARKDOWN For a complete description of pandoc's extensions to standard markdown, see \f[C]pandoc_markdown\f[] (5). .SH SEE ALSO .PP \f[C]pandoc_markdown\f[] (5). .PP The Pandoc source code and all documentation may be downloaded from . pandoc-1.12.2.1/man/man1/pandoc.1.template000644 000765 000024 00000000614 12251233602 017664 0ustar00jgmstaff000000 000000 $if(has-tables)$ .\"t $endif$ .TH PANDOC 1 "$date$" "$title$" .SH NAME pandoc - general markup converter $body$ .SH PANDOC'S MARKDOWN For a complete description of pandoc's extensions to standard markdown, see \f[C]pandoc_markdown\f[] (5). .SH SEE ALSO .PP \f[C]pandoc_markdown\f[] (5). .PP The Pandoc source code and all documentation may be downloaded from . pandoc-1.12.2.1/data/dzslides/000755 000765 000024 00000000000 12251233602 015646 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/data/epub.css000644 000765 000024 00000000667 12251233602 015503 0ustar00jgmstaff000000 000000 /* This defines styles and classes used in the book */ body { margin: 5%; text-align: justify; font-size: medium; } code { font-family: monospace; } h1 { text-align: left; } h2 { text-align: left; } h3 { text-align: left; } h4 { text-align: left; } h5 { text-align: left; } h6 { text-align: left; } h1.title { } h2.author { } h3.date { } ol.toc { padding: 0; margin-left: 1em; } ol.toc li { list-style-type: none; margin: 0; padding: 0; } pandoc-1.12.2.1/data/LaTeXMathML.js000644 000765 000024 00000217325 12251233602 016415 0ustar00jgmstaff000000 000000 /* LaTeXMathML.js from http://math.etsu.edu/LaTeXMathML/ Adapted by Jeff Knisely and Douglas Woodall from ASCIIMathML.js v. 1.4.7, (c) 2005 Peter Jipsen http://www.chapman.edu/~jipsen. Released under the GNU General Public License version 2 or later. See the GNU General Public License (at http://www.gnu.org/copyleft/gpl.html) for more details. */ var checkForMathML=true;var notifyIfNoMathML=true;var alertIfNoMathML=false;var mathcolor="";var mathfontfamily="";var showasciiformulaonhover=true;var isIE=document.createElementNS==null;if(document.getElementById==null) alert("This webpage requires a recent browser such as \nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer") function AMcreateElementXHTML(t){if(isIE)return document.createElement(t);else return document.createElementNS("http://www.w3.org/1999/xhtml",t);} function AMnoMathMLNote(){var nd=AMcreateElementXHTML("h3");nd.setAttribute("align","center") nd.appendChild(AMcreateElementXHTML("p"));nd.appendChild(document.createTextNode("To view the "));var an=AMcreateElementXHTML("a");an.appendChild(document.createTextNode("LaTeXMathML"));an.setAttribute("href","http://www.maths.nott.ac.uk/personal/drw/lm.html");nd.appendChild(an);nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));an=AMcreateElementXHTML("a");an.appendChild(document.createTextNode("MathPlayer"));an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");nd.appendChild(an);nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));nd.appendChild(AMcreateElementXHTML("p"));return nd;} function AMisMathMLavailable(){if(navigator.appName.slice(0,8)=="Netscape") if(navigator.appVersion.slice(0,1)>="5")return null;else return AMnoMathMLNote();else if(navigator.appName.slice(0,9)=="Microsoft") try{var ActiveX=new ActiveXObject("MathPlayer.Factory.1");return null;}catch(e){return AMnoMathMLNote();} else return AMnoMathMLNote();} var AMcal=[0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];var AMfrk=[0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];var AMbbb=[0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];var CONST=0,UNARY=1,BINARY=2,INFIX=3,LEFTBRACKET=4,RIGHTBRACKET=5,SPACE=6,UNDEROVER=7,DEFINITION=8,TEXT=9,BIG=10,LONG=11,STRETCHY=12,MATRIX=13;var AMsqrt={input:"\\sqrt",tag:"msqrt",output:"sqrt",ttype:UNARY},AMroot={input:"\\root",tag:"mroot",output:"root",ttype:BINARY},AMfrac={input:"\\frac",tag:"mfrac",output:"/",ttype:BINARY},AMover={input:"\\stackrel",tag:"mover",output:"stackrel",ttype:BINARY},AMatop={input:"\\atop",tag:"mfrac",output:"",ttype:INFIX},AMchoose={input:"\\choose",tag:"mfrac",output:"",ttype:INFIX},AMsub={input:"_",tag:"msub",output:"_",ttype:INFIX},AMsup={input:"^",tag:"msup",output:"^",ttype:INFIX},AMtext={input:"\\mathrm",tag:"mtext",output:"text",ttype:TEXT},AMmbox={input:"\\mbox",tag:"mtext",output:"mbox",ttype:TEXT};var AMsymbols=[{input:"\\alpha",tag:"mi",output:"\u03B1",ttype:CONST},{input:"\\beta",tag:"mi",output:"\u03B2",ttype:CONST},{input:"\\gamma",tag:"mi",output:"\u03B3",ttype:CONST},{input:"\\delta",tag:"mi",output:"\u03B4",ttype:CONST},{input:"\\epsilon",tag:"mi",output:"\u03B5",ttype:CONST},{input:"\\varepsilon",tag:"mi",output:"\u025B",ttype:CONST},{input:"\\zeta",tag:"mi",output:"\u03B6",ttype:CONST},{input:"\\eta",tag:"mi",output:"\u03B7",ttype:CONST},{input:"\\theta",tag:"mi",output:"\u03B8",ttype:CONST},{input:"\\vartheta",tag:"mi",output:"\u03D1",ttype:CONST},{input:"\\iota",tag:"mi",output:"\u03B9",ttype:CONST},{input:"\\kappa",tag:"mi",output:"\u03BA",ttype:CONST},{input:"\\lambda",tag:"mi",output:"\u03BB",ttype:CONST},{input:"\\mu",tag:"mi",output:"\u03BC",ttype:CONST},{input:"\\nu",tag:"mi",output:"\u03BD",ttype:CONST},{input:"\\xi",tag:"mi",output:"\u03BE",ttype:CONST},{input:"\\pi",tag:"mi",output:"\u03C0",ttype:CONST},{input:"\\varpi",tag:"mi",output:"\u03D6",ttype:CONST},{input:"\\rho",tag:"mi",output:"\u03C1",ttype:CONST},{input:"\\varrho",tag:"mi",output:"\u03F1",ttype:CONST},{input:"\\varsigma",tag:"mi",output:"\u03C2",ttype:CONST},{input:"\\sigma",tag:"mi",output:"\u03C3",ttype:CONST},{input:"\\tau",tag:"mi",output:"\u03C4",ttype:CONST},{input:"\\upsilon",tag:"mi",output:"\u03C5",ttype:CONST},{input:"\\phi",tag:"mi",output:"\u03C6",ttype:CONST},{input:"\\varphi",tag:"mi",output:"\u03D5",ttype:CONST},{input:"\\chi",tag:"mi",output:"\u03C7",ttype:CONST},{input:"\\psi",tag:"mi",output:"\u03C8",ttype:CONST},{input:"\\omega",tag:"mi",output:"\u03C9",ttype:CONST},{input:"\\Gamma",tag:"mo",output:"\u0393",ttype:CONST},{input:"\\Delta",tag:"mo",output:"\u0394",ttype:CONST},{input:"\\Theta",tag:"mo",output:"\u0398",ttype:CONST},{input:"\\Lambda",tag:"mo",output:"\u039B",ttype:CONST},{input:"\\Xi",tag:"mo",output:"\u039E",ttype:CONST},{input:"\\Pi",tag:"mo",output:"\u03A0",ttype:CONST},{input:"\\Sigma",tag:"mo",output:"\u03A3",ttype:CONST},{input:"\\Upsilon",tag:"mo",output:"\u03A5",ttype:CONST},{input:"\\Phi",tag:"mo",output:"\u03A6",ttype:CONST},{input:"\\Psi",tag:"mo",output:"\u03A8",ttype:CONST},{input:"\\Omega",tag:"mo",output:"\u03A9",ttype:CONST},{input:"\\frac12",tag:"mo",output:"\u00BD",ttype:CONST},{input:"\\frac14",tag:"mo",output:"\u00BC",ttype:CONST},{input:"\\frac34",tag:"mo",output:"\u00BE",ttype:CONST},{input:"\\frac13",tag:"mo",output:"\u2153",ttype:CONST},{input:"\\frac23",tag:"mo",output:"\u2154",ttype:CONST},{input:"\\frac15",tag:"mo",output:"\u2155",ttype:CONST},{input:"\\frac25",tag:"mo",output:"\u2156",ttype:CONST},{input:"\\frac35",tag:"mo",output:"\u2157",ttype:CONST},{input:"\\frac45",tag:"mo",output:"\u2158",ttype:CONST},{input:"\\frac16",tag:"mo",output:"\u2159",ttype:CONST},{input:"\\frac56",tag:"mo",output:"\u215A",ttype:CONST},{input:"\\frac18",tag:"mo",output:"\u215B",ttype:CONST},{input:"\\frac38",tag:"mo",output:"\u215C",ttype:CONST},{input:"\\frac58",tag:"mo",output:"\u215D",ttype:CONST},{input:"\\frac78",tag:"mo",output:"\u215E",ttype:CONST},{input:"\\pm",tag:"mo",output:"\u00B1",ttype:CONST},{input:"\\mp",tag:"mo",output:"\u2213",ttype:CONST},{input:"\\triangleleft",tag:"mo",output:"\u22B2",ttype:CONST},{input:"\\triangleright",tag:"mo",output:"\u22B3",ttype:CONST},{input:"\\cdot",tag:"mo",output:"\u22C5",ttype:CONST},{input:"\\star",tag:"mo",output:"\u22C6",ttype:CONST},{input:"\\ast",tag:"mo",output:"\u002A",ttype:CONST},{input:"\\times",tag:"mo",output:"\u00D7",ttype:CONST},{input:"\\div",tag:"mo",output:"\u00F7",ttype:CONST},{input:"\\circ",tag:"mo",output:"\u2218",ttype:CONST},{input:"\\bullet",tag:"mo",output:"\u2022",ttype:CONST},{input:"\\oplus",tag:"mo",output:"\u2295",ttype:CONST},{input:"\\ominus",tag:"mo",output:"\u2296",ttype:CONST},{input:"\\otimes",tag:"mo",output:"\u2297",ttype:CONST},{input:"\\bigcirc",tag:"mo",output:"\u25CB",ttype:CONST},{input:"\\oslash",tag:"mo",output:"\u2298",ttype:CONST},{input:"\\odot",tag:"mo",output:"\u2299",ttype:CONST},{input:"\\land",tag:"mo",output:"\u2227",ttype:CONST},{input:"\\wedge",tag:"mo",output:"\u2227",ttype:CONST},{input:"\\lor",tag:"mo",output:"\u2228",ttype:CONST},{input:"\\vee",tag:"mo",output:"\u2228",ttype:CONST},{input:"\\cap",tag:"mo",output:"\u2229",ttype:CONST},{input:"\\cup",tag:"mo",output:"\u222A",ttype:CONST},{input:"\\sqcap",tag:"mo",output:"\u2293",ttype:CONST},{input:"\\sqcup",tag:"mo",output:"\u2294",ttype:CONST},{input:"\\uplus",tag:"mo",output:"\u228E",ttype:CONST},{input:"\\amalg",tag:"mo",output:"\u2210",ttype:CONST},{input:"\\bigtriangleup",tag:"mo",output:"\u25B3",ttype:CONST},{input:"\\bigtriangledown",tag:"mo",output:"\u25BD",ttype:CONST},{input:"\\dag",tag:"mo",output:"\u2020",ttype:CONST},{input:"\\dagger",tag:"mo",output:"\u2020",ttype:CONST},{input:"\\ddag",tag:"mo",output:"\u2021",ttype:CONST},{input:"\\ddagger",tag:"mo",output:"\u2021",ttype:CONST},{input:"\\lhd",tag:"mo",output:"\u22B2",ttype:CONST},{input:"\\rhd",tag:"mo",output:"\u22B3",ttype:CONST},{input:"\\unlhd",tag:"mo",output:"\u22B4",ttype:CONST},{input:"\\unrhd",tag:"mo",output:"\u22B5",ttype:CONST},{input:"\\sum",tag:"mo",output:"\u2211",ttype:UNDEROVER},{input:"\\prod",tag:"mo",output:"\u220F",ttype:UNDEROVER},{input:"\\bigcap",tag:"mo",output:"\u22C2",ttype:UNDEROVER},{input:"\\bigcup",tag:"mo",output:"\u22C3",ttype:UNDEROVER},{input:"\\bigwedge",tag:"mo",output:"\u22C0",ttype:UNDEROVER},{input:"\\bigvee",tag:"mo",output:"\u22C1",ttype:UNDEROVER},{input:"\\bigsqcap",tag:"mo",output:"\u2A05",ttype:UNDEROVER},{input:"\\bigsqcup",tag:"mo",output:"\u2A06",ttype:UNDEROVER},{input:"\\coprod",tag:"mo",output:"\u2210",ttype:UNDEROVER},{input:"\\bigoplus",tag:"mo",output:"\u2A01",ttype:UNDEROVER},{input:"\\bigotimes",tag:"mo",output:"\u2A02",ttype:UNDEROVER},{input:"\\bigodot",tag:"mo",output:"\u2A00",ttype:UNDEROVER},{input:"\\biguplus",tag:"mo",output:"\u2A04",ttype:UNDEROVER},{input:"\\int",tag:"mo",output:"\u222B",ttype:CONST},{input:"\\oint",tag:"mo",output:"\u222E",ttype:CONST},{input:":=",tag:"mo",output:":=",ttype:CONST},{input:"\\lt",tag:"mo",output:"<",ttype:CONST},{input:"\\gt",tag:"mo",output:">",ttype:CONST},{input:"\\ne",tag:"mo",output:"\u2260",ttype:CONST},{input:"\\neq",tag:"mo",output:"\u2260",ttype:CONST},{input:"\\le",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\leq",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\leqslant",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\ge",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\geq",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\geqslant",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\equiv",tag:"mo",output:"\u2261",ttype:CONST},{input:"\\ll",tag:"mo",output:"\u226A",ttype:CONST},{input:"\\gg",tag:"mo",output:"\u226B",ttype:CONST},{input:"\\doteq",tag:"mo",output:"\u2250",ttype:CONST},{input:"\\prec",tag:"mo",output:"\u227A",ttype:CONST},{input:"\\succ",tag:"mo",output:"\u227B",ttype:CONST},{input:"\\preceq",tag:"mo",output:"\u227C",ttype:CONST},{input:"\\succeq",tag:"mo",output:"\u227D",ttype:CONST},{input:"\\subset",tag:"mo",output:"\u2282",ttype:CONST},{input:"\\supset",tag:"mo",output:"\u2283",ttype:CONST},{input:"\\subseteq",tag:"mo",output:"\u2286",ttype:CONST},{input:"\\supseteq",tag:"mo",output:"\u2287",ttype:CONST},{input:"\\sqsubset",tag:"mo",output:"\u228F",ttype:CONST},{input:"\\sqsupset",tag:"mo",output:"\u2290",ttype:CONST},{input:"\\sqsubseteq",tag:"mo",output:"\u2291",ttype:CONST},{input:"\\sqsupseteq",tag:"mo",output:"\u2292",ttype:CONST},{input:"\\sim",tag:"mo",output:"\u223C",ttype:CONST},{input:"\\simeq",tag:"mo",output:"\u2243",ttype:CONST},{input:"\\approx",tag:"mo",output:"\u2248",ttype:CONST},{input:"\\cong",tag:"mo",output:"\u2245",ttype:CONST},{input:"\\Join",tag:"mo",output:"\u22C8",ttype:CONST},{input:"\\bowtie",tag:"mo",output:"\u22C8",ttype:CONST},{input:"\\in",tag:"mo",output:"\u2208",ttype:CONST},{input:"\\ni",tag:"mo",output:"\u220B",ttype:CONST},{input:"\\owns",tag:"mo",output:"\u220B",ttype:CONST},{input:"\\propto",tag:"mo",output:"\u221D",ttype:CONST},{input:"\\vdash",tag:"mo",output:"\u22A2",ttype:CONST},{input:"\\dashv",tag:"mo",output:"\u22A3",ttype:CONST},{input:"\\models",tag:"mo",output:"\u22A8",ttype:CONST},{input:"\\perp",tag:"mo",output:"\u22A5",ttype:CONST},{input:"\\smile",tag:"mo",output:"\u2323",ttype:CONST},{input:"\\frown",tag:"mo",output:"\u2322",ttype:CONST},{input:"\\asymp",tag:"mo",output:"\u224D",ttype:CONST},{input:"\\notin",tag:"mo",output:"\u2209",ttype:CONST},{input:"\\begin{eqnarray}",output:"X",ttype:MATRIX,invisible:true},{input:"\\begin{array}",output:"X",ttype:MATRIX,invisible:true},{input:"\\\\",output:"}&{",ttype:DEFINITION},{input:"\\end{eqnarray}",output:"}}",ttype:DEFINITION},{input:"\\end{array}",output:"}}",ttype:DEFINITION},{input:"\\big",tag:"mo",output:"X",atval:"1.2",ieval:"2.2",ttype:BIG},{input:"\\Big",tag:"mo",output:"X",atval:"1.6",ieval:"2.6",ttype:BIG},{input:"\\bigg",tag:"mo",output:"X",atval:"2.2",ieval:"3.2",ttype:BIG},{input:"\\Bigg",tag:"mo",output:"X",atval:"2.9",ieval:"3.9",ttype:BIG},{input:"\\left",tag:"mo",output:"X",ttype:LEFTBRACKET},{input:"\\right",tag:"mo",output:"X",ttype:RIGHTBRACKET},{input:"{",output:"{",ttype:LEFTBRACKET,invisible:true},{input:"}",output:"}",ttype:RIGHTBRACKET,invisible:true},{input:"(",tag:"mo",output:"(",atval:"1",ttype:STRETCHY},{input:"[",tag:"mo",output:"[",atval:"1",ttype:STRETCHY},{input:"\\lbrack",tag:"mo",output:"[",atval:"1",ttype:STRETCHY},{input:"\\{",tag:"mo",output:"{",atval:"1",ttype:STRETCHY},{input:"\\lbrace",tag:"mo",output:"{",atval:"1",ttype:STRETCHY},{input:"\\langle",tag:"mo",output:"\u2329",atval:"1",ttype:STRETCHY},{input:"\\lfloor",tag:"mo",output:"\u230A",atval:"1",ttype:STRETCHY},{input:"\\lceil",tag:"mo",output:"\u2308",atval:"1",ttype:STRETCHY},{input:")",tag:"mo",output:")",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"]",tag:"mo",output:"]",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rbrack",tag:"mo",output:"]",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\}",tag:"mo",output:"}",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rbrace",tag:"mo",output:"}",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rangle",tag:"mo",output:"\u232A",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rfloor",tag:"mo",output:"\u230B",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rceil",tag:"mo",output:"\u2309",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"|",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\|",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"\\vert",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\Vert",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"\\mid",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\parallel",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"/",tag:"mo",output:"/",atval:"1.01",ttype:STRETCHY},{input:"\\backslash",tag:"mo",output:"\u2216",atval:"1",ttype:STRETCHY},{input:"\\setminus",tag:"mo",output:"\\",ttype:CONST},{input:"\\!",tag:"mspace",atname:"width",atval:"-0.167em",ttype:SPACE},{input:"\\,",tag:"mspace",atname:"width",atval:"0.167em",ttype:SPACE},{input:"\\>",tag:"mspace",atname:"width",atval:"0.222em",ttype:SPACE},{input:"\\:",tag:"mspace",atname:"width",atval:"0.222em",ttype:SPACE},{input:"\\;",tag:"mspace",atname:"width",atval:"0.278em",ttype:SPACE},{input:"~",tag:"mspace",atname:"width",atval:"0.333em",ttype:SPACE},{input:"\\quad",tag:"mspace",atname:"width",atval:"1em",ttype:SPACE},{input:"\\qquad",tag:"mspace",atname:"width",atval:"2em",ttype:SPACE},{input:"\\prime",tag:"mo",output:"\u2032",ttype:CONST},{input:"'",tag:"mo",output:"\u02B9",ttype:CONST},{input:"''",tag:"mo",output:"\u02BA",ttype:CONST},{input:"'''",tag:"mo",output:"\u2034",ttype:CONST},{input:"''''",tag:"mo",output:"\u2057",ttype:CONST},{input:"\\ldots",tag:"mo",output:"\u2026",ttype:CONST},{input:"\\cdots",tag:"mo",output:"\u22EF",ttype:CONST},{input:"\\vdots",tag:"mo",output:"\u22EE",ttype:CONST},{input:"\\ddots",tag:"mo",output:"\u22F1",ttype:CONST},{input:"\\forall",tag:"mo",output:"\u2200",ttype:CONST},{input:"\\exists",tag:"mo",output:"\u2203",ttype:CONST},{input:"\\Re",tag:"mo",output:"\u211C",ttype:CONST},{input:"\\Im",tag:"mo",output:"\u2111",ttype:CONST},{input:"\\aleph",tag:"mo",output:"\u2135",ttype:CONST},{input:"\\hbar",tag:"mo",output:"\u210F",ttype:CONST},{input:"\\ell",tag:"mo",output:"\u2113",ttype:CONST},{input:"\\wp",tag:"mo",output:"\u2118",ttype:CONST},{input:"\\emptyset",tag:"mo",output:"\u2205",ttype:CONST},{input:"\\infty",tag:"mo",output:"\u221E",ttype:CONST},{input:"\\surd",tag:"mo",output:"\\sqrt{}",ttype:DEFINITION},{input:"\\partial",tag:"mo",output:"\u2202",ttype:CONST},{input:"\\nabla",tag:"mo",output:"\u2207",ttype:CONST},{input:"\\triangle",tag:"mo",output:"\u25B3",ttype:CONST},{input:"\\therefore",tag:"mo",output:"\u2234",ttype:CONST},{input:"\\angle",tag:"mo",output:"\u2220",ttype:CONST},{input:"\\diamond",tag:"mo",output:"\u22C4",ttype:CONST},{input:"\\Diamond",tag:"mo",output:"\u25C7",ttype:CONST},{input:"\\neg",tag:"mo",output:"\u00AC",ttype:CONST},{input:"\\lnot",tag:"mo",output:"\u00AC",ttype:CONST},{input:"\\bot",tag:"mo",output:"\u22A5",ttype:CONST},{input:"\\top",tag:"mo",output:"\u22A4",ttype:CONST},{input:"\\square",tag:"mo",output:"\u25AB",ttype:CONST},{input:"\\Box",tag:"mo",output:"\u25A1",ttype:CONST},{input:"\\wr",tag:"mo",output:"\u2240",ttype:CONST},{input:"\\arccos",tag:"mi",output:"arccos",ttype:UNARY,func:true},{input:"\\arcsin",tag:"mi",output:"arcsin",ttype:UNARY,func:true},{input:"\\arctan",tag:"mi",output:"arctan",ttype:UNARY,func:true},{input:"\\arg",tag:"mi",output:"arg",ttype:UNARY,func:true},{input:"\\cos",tag:"mi",output:"cos",ttype:UNARY,func:true},{input:"\\cosh",tag:"mi",output:"cosh",ttype:UNARY,func:true},{input:"\\cot",tag:"mi",output:"cot",ttype:UNARY,func:true},{input:"\\coth",tag:"mi",output:"coth",ttype:UNARY,func:true},{input:"\\csc",tag:"mi",output:"csc",ttype:UNARY,func:true},{input:"\\deg",tag:"mi",output:"deg",ttype:UNARY,func:true},{input:"\\det",tag:"mi",output:"det",ttype:UNARY,func:true},{input:"\\dim",tag:"mi",output:"dim",ttype:UNARY,func:true},{input:"\\exp",tag:"mi",output:"exp",ttype:UNARY,func:true},{input:"\\gcd",tag:"mi",output:"gcd",ttype:UNARY,func:true},{input:"\\hom",tag:"mi",output:"hom",ttype:UNARY,func:true},{input:"\\inf",tag:"mo",output:"inf",ttype:UNDEROVER},{input:"\\ker",tag:"mi",output:"ker",ttype:UNARY,func:true},{input:"\\lg",tag:"mi",output:"lg",ttype:UNARY,func:true},{input:"\\lim",tag:"mo",output:"lim",ttype:UNDEROVER},{input:"\\liminf",tag:"mo",output:"liminf",ttype:UNDEROVER},{input:"\\limsup",tag:"mo",output:"limsup",ttype:UNDEROVER},{input:"\\ln",tag:"mi",output:"ln",ttype:UNARY,func:true},{input:"\\log",tag:"mi",output:"log",ttype:UNARY,func:true},{input:"\\max",tag:"mo",output:"max",ttype:UNDEROVER},{input:"\\min",tag:"mo",output:"min",ttype:UNDEROVER},{input:"\\Pr",tag:"mi",output:"Pr",ttype:UNARY,func:true},{input:"\\sec",tag:"mi",output:"sec",ttype:UNARY,func:true},{input:"\\sin",tag:"mi",output:"sin",ttype:UNARY,func:true},{input:"\\sinh",tag:"mi",output:"sinh",ttype:UNARY,func:true},{input:"\\sup",tag:"mo",output:"sup",ttype:UNDEROVER},{input:"\\tan",tag:"mi",output:"tan",ttype:UNARY,func:true},{input:"\\tanh",tag:"mi",output:"tanh",ttype:UNARY,func:true},{input:"\\gets",tag:"mo",output:"\u2190",ttype:CONST},{input:"\\leftarrow",tag:"mo",output:"\u2190",ttype:CONST},{input:"\\to",tag:"mo",output:"\u2192",ttype:CONST},{input:"\\rightarrow",tag:"mo",output:"\u2192",ttype:CONST},{input:"\\leftrightarrow",tag:"mo",output:"\u2194",ttype:CONST},{input:"\\uparrow",tag:"mo",output:"\u2191",ttype:CONST},{input:"\\downarrow",tag:"mo",output:"\u2193",ttype:CONST},{input:"\\updownarrow",tag:"mo",output:"\u2195",ttype:CONST},{input:"\\Leftarrow",tag:"mo",output:"\u21D0",ttype:CONST},{input:"\\Rightarrow",tag:"mo",output:"\u21D2",ttype:CONST},{input:"\\Leftrightarrow",tag:"mo",output:"\u21D4",ttype:CONST},{input:"\\iff",tag:"mo",output:"~\\Longleftrightarrow~",ttype:DEFINITION},{input:"\\Uparrow",tag:"mo",output:"\u21D1",ttype:CONST},{input:"\\Downarrow",tag:"mo",output:"\u21D3",ttype:CONST},{input:"\\Updownarrow",tag:"mo",output:"\u21D5",ttype:CONST},{input:"\\mapsto",tag:"mo",output:"\u21A6",ttype:CONST},{input:"\\longleftarrow",tag:"mo",output:"\u2190",ttype:LONG},{input:"\\longrightarrow",tag:"mo",output:"\u2192",ttype:LONG},{input:"\\longleftrightarrow",tag:"mo",output:"\u2194",ttype:LONG},{input:"\\Longleftarrow",tag:"mo",output:"\u21D0",ttype:LONG},{input:"\\Longrightarrow",tag:"mo",output:"\u21D2",ttype:LONG},{input:"\\Longleftrightarrow",tag:"mo",output:"\u21D4",ttype:LONG},{input:"\\longmapsto",tag:"mo",output:"\u21A6",ttype:CONST},AMsqrt,AMroot,AMfrac,AMover,AMsub,AMsup,AMtext,AMmbox,AMatop,AMchoose,{input:"\\acute",tag:"mover",output:"\u00B4",ttype:UNARY,acc:true},{input:"\\grave",tag:"mover",output:"\u0060",ttype:UNARY,acc:true},{input:"\\breve",tag:"mover",output:"\u02D8",ttype:UNARY,acc:true},{input:"\\check",tag:"mover",output:"\u02C7",ttype:UNARY,acc:true},{input:"\\dot",tag:"mover",output:".",ttype:UNARY,acc:true},{input:"\\ddot",tag:"mover",output:"..",ttype:UNARY,acc:true},{input:"\\mathring",tag:"mover",output:"\u00B0",ttype:UNARY,acc:true},{input:"\\vec",tag:"mover",output:"\u20D7",ttype:UNARY,acc:true},{input:"\\overrightarrow",tag:"mover",output:"\u20D7",ttype:UNARY,acc:true},{input:"\\overleftarrow",tag:"mover",output:"\u20D6",ttype:UNARY,acc:true},{input:"\\hat",tag:"mover",output:"\u005E",ttype:UNARY,acc:true},{input:"\\widehat",tag:"mover",output:"\u0302",ttype:UNARY,acc:true},{input:"\\tilde",tag:"mover",output:"~",ttype:UNARY,acc:true},{input:"\\widetilde",tag:"mover",output:"\u02DC",ttype:UNARY,acc:true},{input:"\\bar",tag:"mover",output:"\u203E",ttype:UNARY,acc:true},{input:"\\overbrace",tag:"mover",output:"\uFE37",ttype:UNARY,acc:true},{input:"\\overbracket",tag:"mover",output:"\u23B4",ttype:UNARY,acc:true},{input:"\\overline",tag:"mover",output:"\u00AF",ttype:UNARY,acc:true},{input:"\\underbrace",tag:"munder",output:"\uFE38",ttype:UNARY,acc:true},{input:"\\underbracket",tag:"munder",output:"\u23B5",ttype:UNARY,acc:true},{input:"\\underline",tag:"munder",output:"\u00AF",ttype:UNARY,acc:true},{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true",ttype:UNARY},{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false",ttype:UNARY},{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1",ttype:UNARY},{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2",ttype:UNARY},{input:"\\textrm",tag:"mstyle",output:"\\mathrm",ttype:DEFINITION},{input:"\\mathbf",tag:"mstyle",atname:"mathvariant",atval:"bold",ttype:UNARY},{input:"\\textbf",tag:"mstyle",atname:"mathvariant",atval:"bold",ttype:UNARY},{input:"\\mathit",tag:"mstyle",atname:"mathvariant",atval:"italic",ttype:UNARY},{input:"\\textit",tag:"mstyle",atname:"mathvariant",atval:"italic",ttype:UNARY},{input:"\\mathtt",tag:"mstyle",atname:"mathvariant",atval:"monospace",ttype:UNARY},{input:"\\texttt",tag:"mstyle",atname:"mathvariant",atval:"monospace",ttype:UNARY},{input:"\\mathsf",tag:"mstyle",atname:"mathvariant",atval:"sans-serif",ttype:UNARY},{input:"\\mathbb",tag:"mstyle",atname:"mathvariant",atval:"double-struck",ttype:UNARY,codes:AMbbb},{input:"\\mathcal",tag:"mstyle",atname:"mathvariant",atval:"script",ttype:UNARY,codes:AMcal},{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant",atval:"fraktur",ttype:UNARY,codes:AMfrk},{input:"\\textcolor",tag:"mstyle",atname:"mathvariant",atval:"mathcolor",ttype:BINARY},{input:"\\colorbox",tag:"mstyle",atname:"mathvariant",atval:"background",ttype:BINARY}];function compareNames(s1,s2){if(s1.input>s2.input)return 1 else return-1;} var AMnames=[];function AMinitSymbols(){AMsymbols.sort(compareNames);for(i=0;i>1;if(arr[m]=AMnames[k];} AMpreviousSymbol=AMcurrentSymbol;if(match!=""){AMcurrentSymbol=AMsymbols[mk].ttype;return AMsymbols[mk];} AMcurrentSymbol=CONST;k=1;st=str.slice(0,1);if("0"<=st&&st<="9")tagst="mn";else tagst=(("A">st||st>"Z")&&("a">st||st>"z")?"mo":"mi");return{input:st,tag:tagst,output:st,ttype:CONST};} var AMpreviousSymbol,AMcurrentSymbol;function AMparseSexpr(str){var symbol,node,result,result2,i,st,newFrag=document.createDocumentFragment();str=AMremoveCharsAndBlanks(str,0);symbol=AMgetSymbol(str);if(symbol==null||symbol.ttype==RIGHTBRACKET) return[null,str,null];if(symbol.ttype==DEFINITION){str=symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);symbol=AMgetSymbol(str);if(symbol==null||symbol.ttype==RIGHTBRACKET) return[null,str,null];} str=AMremoveCharsAndBlanks(str,symbol.input.length);switch(symbol.ttype){case SPACE:node=AMcreateElementMathML(symbol.tag);node.setAttribute(symbol.atname,symbol.atval);return[node,str,symbol.tag];case UNDEROVER:if(isIE){if(symbol.input.substr(0,4)=="\\big"){str="\\"+symbol.input.substr(4)+str;symbol=AMgetSymbol(str);symbol.ttype=UNDEROVER;str=AMremoveCharsAndBlanks(str,symbol.input.length);}} return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];case CONST:var output=symbol.output;if(isIE){if(symbol.input=="'") output="\u2032";else if(symbol.input=="''") output="\u2033";else if(symbol.input=="'''") output="\u2033\u2032";else if(symbol.input=="''''") output="\u2033\u2033";else if(symbol.input=="\\square") output="\u25A1";else if(symbol.input.substr(0,5)=="\\frac"){var denom=symbol.input.substr(6,1);if(denom=="5"||denom=="6"){str=symbol.input.replace(/\\frac/,"\\frac ")+str;return[node,str,symbol.tag];}}} node=AMcreateMmlNode(symbol.tag,document.createTextNode(output));return[node,str,symbol.tag];case LONG:node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));node.setAttribute("minsize","1.5");node.setAttribute("maxsize","1.5");node=AMcreateMmlNode("mover",node);node.appendChild(AMcreateElementMathML("mspace"));return[node,str,symbol.tag];case STRETCHY:if(isIE&&symbol.input=="\\backslash") symbol.output="\\";node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));if(symbol.input=="|"||symbol.input=="\\vert"||symbol.input=="\\|"||symbol.input=="\\Vert"){node.setAttribute("lspace","0em");node.setAttribute("rspace","0em");} node.setAttribute("maxsize",symbol.atval);if(symbol.rtag!=null) return[node,str,symbol.rtag];else return[node,str,symbol.tag];case BIG:var atval=symbol.atval;if(isIE) atval=symbol.ieval;symbol=AMgetSymbol(str);if(symbol==null) return[null,str,null];str=AMremoveCharsAndBlanks(str,symbol.input.length);node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("height",atval+"ex");node=AMcreateMmlNode("mrow",node);node.appendChild(space);}else{node.setAttribute("minsize",atval);node.setAttribute("maxsize",atval);} return[node,str,symbol.tag];case LEFTBRACKET:if(symbol.input=="\\left"){symbol=AMgetSymbol(str);if(symbol!=null){if(symbol.input==".") symbol.invisible=true;str=AMremoveCharsAndBlanks(str,symbol.input.length);}} result=AMparseExpr(str,true,false);if(symbol==null||(typeof symbol.invisible=="boolean"&&symbol.invisible)) node=AMcreateMmlNode("mrow",result[0]);else{node=AMcreateMmlNode("mo",document.createTextNode(symbol.output));node=AMcreateMmlNode("mrow",node);node.appendChild(result[0]);} return[node,result[1],result[2]];case MATRIX:if(symbol.input=="\\begin{array}"){var mask="";symbol=AMgetSymbol(str);str=AMremoveCharsAndBlanks(str,0);if(symbol==null) mask="l";else{str=AMremoveCharsAndBlanks(str,symbol.input.length);if(symbol.input!="{") mask="l";else do{symbol=AMgetSymbol(str);if(symbol!=null){str=AMremoveCharsAndBlanks(str,symbol.input.length);if(symbol.input!="}") mask=mask+symbol.input;}}while(symbol!=null&&symbol.input!=""&&symbol.input!="}");} result=AMparseExpr("{"+str,true,true);node=AMcreateMmlNode("mtable",result[0]);mask=mask.replace(/l/g,"left ");mask=mask.replace(/r/g,"right ");mask=mask.replace(/c/g,"center ");node.setAttribute("columnalign",mask);node.setAttribute("displaystyle","false");if(isIE) return[node,result[1],null];var lspace=AMcreateElementMathML("mspace");lspace.setAttribute("width","0.167em");var rspace=AMcreateElementMathML("mspace");rspace.setAttribute("width","0.167em");var node1=AMcreateMmlNode("mrow",lspace);node1.appendChild(node);node1.appendChild(rspace);return[node1,result[1],null];}else{result=AMparseExpr("{"+str,true,true);node=AMcreateMmlNode("mtable",result[0]);if(isIE) node.setAttribute("columnspacing","0.25em");else node.setAttribute("columnspacing","0.167em");node.setAttribute("columnalign","right center left");node.setAttribute("displaystyle","true");node=AMcreateMmlNode("mrow",node);return[node,result[1],null];} case TEXT:if(str.charAt(0)=="{")i=str.indexOf("}");else i=0;if(i==-1) i=str.length;st=str.slice(1,i);if(st.charAt(0)==" "){node=AMcreateElementMathML("mspace");node.setAttribute("width","0.33em");newFrag.appendChild(node);} newFrag.appendChild(AMcreateMmlNode(symbol.tag,document.createTextNode(st)));if(st.charAt(st.length-1)==" "){node=AMcreateElementMathML("mspace");node.setAttribute("width","0.33em");newFrag.appendChild(node);} str=AMremoveCharsAndBlanks(str,i+1);return[AMcreateMmlNode("mrow",newFrag),str,null];case UNARY:result=AMparseSexpr(str);if(result[0]==null)return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str];if(typeof symbol.func=="boolean"&&symbol.func){st=str.charAt(0);if(st=="^"||st=="_"||st==","){return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];}else{node=AMcreateMmlNode("mrow",AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("width","0.167em");node.appendChild(space);} node.appendChild(result[0]);return[node,result[1],symbol.tag];}} if(symbol.input=="\\sqrt"){if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("height","1.2ex");space.setAttribute("width","0em");node=AMcreateMmlNode(symbol.tag,result[0]) node.appendChild(space);return[node,result[1],symbol.tag];}else return[AMcreateMmlNode(symbol.tag,result[0]),result[1],symbol.tag];}else if(typeof symbol.acc=="boolean"&&symbol.acc){node=AMcreateMmlNode(symbol.tag,result[0]);var output=symbol.output;if(isIE){if(symbol.input=="\\hat") output="\u0302";else if(symbol.input=="\\widehat") output="\u005E";else if(symbol.input=="\\bar") output="\u00AF";else if(symbol.input=="\\grave") output="\u0300";else if(symbol.input=="\\tilde") output="\u0303";} var node1=AMcreateMmlNode("mo",document.createTextNode(output));if(symbol.input=="\\vec"||symbol.input=="\\check") node1.setAttribute("maxsize","1.2");if(isIE&&symbol.input=="\\bar") node1.setAttribute("maxsize","0.5");if(symbol.input=="\\underbrace"||symbol.input=="\\underline") node1.setAttribute("accentunder","true");else node1.setAttribute("accent","true");node.appendChild(node1);if(symbol.input=="\\overbrace"||symbol.input=="\\underbrace") node.ttype=UNDEROVER;return[node,result[1],symbol.tag];}else{if(!isIE&&typeof symbol.codes!="undefined"){for(i=0;i64&&st.charCodeAt(j)<91)newst=newst+ String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);else newst=newst+st.charAt(j);if(result[0].nodeName=="mi") result[0]=AMcreateElementMathML("mo").appendChild(document.createTextNode(newst));else result[0].replaceChild(AMcreateElementMathML("mo").appendChild(document.createTextNode(newst)),result[0].childNodes[i]);}} node=AMcreateMmlNode(symbol.tag,result[0]);node.setAttribute(symbol.atname,symbol.atval);if(symbol.input=="\\scriptstyle"||symbol.input=="\\scriptscriptstyle") node.setAttribute("displaystyle","false");return[node,result[1],symbol.tag];} case BINARY:result=AMparseSexpr(str);if(result[0]==null)return[AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];result2=AMparseSexpr(result[1]);if(result2[0]==null)return[AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];if(symbol.input=="\\textcolor"||symbol.input=="\\colorbox"){var tclr=str.match(/\{\s*([#\w]+)\s*\}/);str=str.replace(/\{\s*[#\w]+\s*\}/,"");if(tclr!=null){if(IsColorName.test(tclr[1].toLowerCase())){tclr=LaTeXColor[tclr[1].toLowerCase()];}else{tclr=tclr[1];} node=AMcreateElementMathML("mstyle");node.setAttribute(symbol.atval,tclr);node.appendChild(result2[0]);return[node,result2[1],symbol.tag];}} if(symbol.input=="\\root"||symbol.input=="\\stackrel")newFrag.appendChild(result2[0]);newFrag.appendChild(result[0]);if(symbol.input=="\\frac")newFrag.appendChild(result2[0]);return[AMcreateMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];case INFIX:str=AMremoveCharsAndBlanks(str,symbol.input.length);return[AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str,symbol.tag];default:return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];}} function AMparseIexpr(str){var symbol,sym1,sym2,node,result,tag,underover;str=AMremoveCharsAndBlanks(str,0);sym1=AMgetSymbol(str);result=AMparseSexpr(str);node=result[0];str=result[1];tag=result[2];symbol=AMgetSymbol(str);if(symbol.ttype==INFIX){str=AMremoveCharsAndBlanks(str,symbol.input.length);result=AMparseSexpr(str);if(result[0]==null) result[0]=AMcreateMmlNode("mo",document.createTextNode("\u25A1"));str=result[1];tag=result[2];if(symbol.input=="_"||symbol.input=="^"){sym2=AMgetSymbol(str);tag=null;underover=((sym1.ttype==UNDEROVER)||(node.ttype==UNDEROVER));if(symbol.input=="_"&&sym2.input=="^"){str=AMremoveCharsAndBlanks(str,sym2.input.length);var res2=AMparseSexpr(str);str=res2[1];tag=res2[2];node=AMcreateMmlNode((underover?"munderover":"msubsup"),node);node.appendChild(result[0]);node.appendChild(res2[0]);}else if(symbol.input=="_"){node=AMcreateMmlNode((underover?"munder":"msub"),node);node.appendChild(result[0]);}else{node=AMcreateMmlNode((underover?"mover":"msup"),node);node.appendChild(result[0]);} node=AMcreateMmlNode("mrow",node);}else{node=AMcreateMmlNode(symbol.tag,node);if(symbol.input=="\\atop"||symbol.input=="\\choose") node.setAttribute("linethickness","0ex");node.appendChild(result[0]);if(symbol.input=="\\choose") node=AMcreateMmlNode("mfenced",node);}} return[node,str,tag];} function AMparseExpr(str,rightbracket,matrix){var symbol,node,result,i,tag,newFrag=document.createDocumentFragment();do{str=AMremoveCharsAndBlanks(str,0);result=AMparseIexpr(str);node=result[0];str=result[1];tag=result[2];symbol=AMgetSymbol(str);if(node!=undefined){if((tag=="mn"||tag=="mi")&&symbol!=null&&typeof symbol.func=="boolean"&&symbol.func){var space=AMcreateElementMathML("mspace");space.setAttribute("width","0.167em");node=AMcreateMmlNode("mrow",node);node.appendChild(space);} newFrag.appendChild(node);}}while((symbol.ttype!=RIGHTBRACKET)&&symbol!=null&&symbol.output!="");tag=null;if(symbol.ttype==RIGHTBRACKET){if(symbol.input=="\\right"){str=AMremoveCharsAndBlanks(str,symbol.input.length);symbol=AMgetSymbol(str);if(symbol!=null&&symbol.input==".") symbol.invisible=true;if(symbol!=null) tag=symbol.rtag;} if(symbol!=null) str=AMremoveCharsAndBlanks(str,symbol.input.length);var len=newFrag.childNodes.length;if(matrix&&len>0&&newFrag.childNodes[len-1].nodeName=="mrow"&&len>1&&newFrag.childNodes[len-2].nodeName=="mo"&&newFrag.childNodes[len-2].firstChild.nodeValue=="&"){var pos=[];var m=newFrag.childNodes.length;for(i=0;matrix&&i2){newFrag.removeChild(newFrag.firstChild);newFrag.removeChild(newFrag.firstChild);} table.appendChild(AMcreateMmlNode("mtr",row));} return[table,str];} if(typeof symbol.invisible!="boolean"||!symbol.invisible){node=AMcreateMmlNode("mo",document.createTextNode(symbol.output));newFrag.appendChild(node);}} return[newFrag,str,tag];} function AMparseMath(str){var result,node=AMcreateElementMathML("mstyle");var cclr=str.match(/\\color\s*\{\s*([#\w]+)\s*\}/);str=str.replace(/\\color\s*\{\s*[#\w]+\s*\}/g,"");if(cclr!=null){if(IsColorName.test(cclr[1].toLowerCase())){cclr=LaTeXColor[cclr[1].toLowerCase()];}else{cclr=cclr[1];} node.setAttribute("mathcolor",cclr);}else{if(mathcolor!="")node.setAttribute("mathcolor",mathcolor);};if(mathfontfamily!="")node.setAttribute("fontfamily",mathfontfamily);node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false,false)[0]);node=AMcreateMmlNode("math",node);if(showasciiformulaonhover) node.setAttribute("title",str.replace(/\s+/g," "));if(false){var fnode=AMcreateElementXHTML("font");fnode.setAttribute("face",mathfontfamily);fnode.appendChild(node);return fnode;} return node;} function AMstrarr2docFrag(arr,linebreaks){var newFrag=document.createDocumentFragment();var expr=false;for(var i=0;i1||mtch){if(checkForMathML){checkForMathML=false;var nd=AMisMathMLavailable();AMnoMathML=nd!=null;if(AMnoMathML&¬ifyIfNoMathML) if(alertIfNoMathML) alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\nor Firefox/Mozilla/Netscape");else AMbody.insertBefore(nd,AMbody.childNodes[0]);} if(!AMnoMathML){frg=AMstrarr2docFrag(arr,n.nodeType==8);var len=frg.childNodes.length;n.parentNode.replaceChild(frg,n);return len-1;}else return 0;}}}else return 0;}else if(n.nodeName!="math"){for(i=0;i0){if(inAppendix){return"A"+sectionCntr+"."+cntr;}else{return sectionCntr+"."+cntr;}}else{return""+cntr;}};function LaTeXpreProcess(thebody){var TheBody=thebody;if(TheBody.hasChildNodes()){if(!(IsLaTeXElement.test(TheBody.className))) {for(var i=0;i");str=str.replace(/%[^\n]*(?=\n)/g,"");str=str.replace(/%[^\r]*(?=\r)/g,"");str=str.replace(/%[^\n]*$/,"") if(isIE&&str.match(/%/g)!=null&&IEcommentWarning){alert("Comments may not have parsed properly. Try putting in
=0){str[i]=str[i].replace(/\\section\s*\{/," \\[section\\]");var delimcnt=1;for(var ii=sectionIndex;ii=0){str[i]=str[i].replace(/\\subsection\s*\{/," \\[subsection\\]");var delimcnt=1;for(var ii=sectionIndex;ii=0){str[i]=str[i].replace(/\\subsubsection\s*\{/," \\[subsubsection\\]");var delimcnt=1;for(var ii=sectionIndex;ii=0){var tmp=strtmparray[1];var delimcnt=0;var capstart=-1;for(var pos=capIndex;pos0){capend=pos-1;FIGcap=tmp.substring(capstart,pos);break}}}
var FIGtr2=document.createElement("tr");var FIGtd2=document.createElement("td");FIGtd2.className="caption";var FIGanchor=document.createElement("a");FIGanchor.className="figure";if(FIGlbl!=null){FIGanchor.id=FIGlbl[1];}
LaTeXCounter["figure"]++;var fignmbr=makeNumberString(LaTeXCounter["figure"]);var anchorSpan=document.createElement("span");anchorSpan.className="figure";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(fignmbr));FIGanchor.appendChild(anchorSpan);FIGtd2.appendChild(FIGanchor);var FIGspan=document.createElement("span");FIGspan.className="figure";FIGspan.appendChild(document.createTextNode("Figure "+fignmbr+". "));FIGtd2.appendChild(FIGspan);FIGtd2.appendChild(document.createTextNode(""+FIGcap));FIGtr2.appendChild(FIGtd2);FIGtbody.appendChild(FIGtr2);var IsSpecial=false;var FIGinfo=strtmparray[1].match(/\\includegraphics\s*\{([^\}]+)\}/);if(FIGinfo==null){FIGinfo=strtmparray[1].match(/\\includegraphics\s*\[[^\]]*\]\s*\{\s*([^\}]+)\s*\}/);}
if(FIGinfo==null){FIGinfo=strtmparray[1].match(/\\special\s*\{\s*([^\}]+)\}/);IsSpecial=true};if(FIGinfo!=null){var FIGtr1=document.createElement("tr");var FIGtd1=document.createElement("td");FIGtd1.className="image";var FIGimg=document.createElement("img");var FIGsrc=FIGinfo[1];FIGimg.src=FIGsrc;FIGimg.alt="Figure "+FIGsrc+" did not load";FIGimg.title="Figure "+fignmbr+". "+FIGcap;FIGimg.id="figure"+fignmbr;FIGtd1.appendChild(FIGimg);FIGtr1.appendChild(FIGtd1);FIGtbody.appendChild(FIGtr1);}
nodeTmp.appendChild(FIGtbody);newFrag.appendChild(nodeTmp);break;case"table":var nodeTmp=document.createElement("table");if(strtmparray[1].search(/\\centering/)>=0){nodeTmp.className='LaTeXtable centered';nodeTmp.align="center";}else{nodeTmp.className='LaTeXtable';};tableid++;nodeTmp.id="LaTeXtable"+tableid;var TABlbl=strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");var capIndex=strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);var TABcap="";if(capIndex>=0){var tmp=strtmparray[1];var delimcnt=0;var capstart=-1;for(var pos=capIndex;pos0){capend=pos-1;TABcap=tmp.substring(capstart,pos);break}}}
if(TABcap!=""){var TABtbody=document.createElement("tbody");var TABcaption=document.createElement("caption");TABcaption.className="LaTeXtable centered";var TABanchor=document.createElement("a");TABanchor.className="LaTeXtable";if(TABlbl!=null){TABanchor.id=TABlbl[1];}
LaTeXCounter["table"]++;var tabnmbr=makeNumberString(LaTeXCounter["table"]);var anchorSpan=document.createElement("span");anchorSpan.className="LaTeXtable";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(tabnmbr));TABanchor.appendChild(anchorSpan);TABcaption.appendChild(TABanchor);var TABspan=document.createElement("span");TABspan.className="LaTeXtable";TABspan.appendChild(document.createTextNode("Table "+tabnmbr+". "));TABcaption.appendChild(TABspan);TABcaption.appendChild(document.createTextNode(""+TABcap));nodeTmp.appendChild(TABcaption);}
var TABinfo=strtmparray[1].match(/\\begin\s*\{\s*tabular\s*\}([\s\S]+)\\end\s*\{\s*tabular\s*\}/);if(TABinfo!=null){var TABtbody=document.createElement('tbody');var TABrow=null;var TABcell=null;var row=0;var col=0;var TABalign=TABinfo[1].match(/^\s*\{([^\}]+)\}/);TABinfo=TABinfo[1].replace(/^\s*\{[^\}]+\}/,"");TABinfo=TABinfo.replace(/\\hline/g,"");TABalign[1]=TABalign[1].replace(/\|/g,"");TABalign[1]=TABalign[1].replace(/\s/g,"");TABinfo=TABinfo.split("\\\\");for(row=0;row");strtmp[j]=strtmp[j].replace(/\$([^\$]+)\$/g," \\[$1\\[ ");strtmp[j]=strtmp[j].replace(//g,"\\$");strtmp[j]=strtmp[j].replace(/\\begin\s*\{\s*math\s*\}([\s\S]+?)\\end\s*\{\s*math\s*\}/g," \\[$1\\[ ");var strtmptmp=strtmp[j].split("\\[");for(var jjj=0;jjj-1){if(/^\\textcolor/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))){strtmptmp[jjj]=strtmptmp[jjj].replace(/\\textcolor\s*\{\s*(\w+)\s*\}\s*/," \\[textcolor\\]$1\\]|");}else{if(/^\\colorbox/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))){strtmptmp[jjj]=strtmptmp[jjj].replace(/\\colorbox\s*\{\s*(\w+)\s*\}\s*/," \\[colorbox\\]$1\\]|");}else{strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).replace(/\\\s*(\w+)\s*/," \\[$1\\]|");}}
TagIndex+=strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\|/);TagIndex++;strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\]\|/,"\\] ");if(strtmptmp[jjj].charAt(TagIndex)=="{"){strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);var delimcnt=1;for(var kk=TagIndex;kk=0;i--){EndDivClass=AllDivs[i].className.match(/end\w+/);if(EndDivClass!=null){EndDivClass=EndDivClass[0];var DivClass=EndDivClass.substring(3,EndDivClass.length);var EndDivNode=AllDivs[i];break;}}
while(EndDivClass!=null){var newFrag=document.createDocumentFragment();var RootNode=EndDivNode.parentNode;var ClassCount=1;while(EndDivNode.previousSibling!=null&&ClassCount>0){switch(EndDivNode.previousSibling.className){case EndDivClass:ClassCount++;newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);break;case DivClass:if(EndDivNode.previousSibling.nodeName=="DIV"){ClassCount--;if(lbl2id!=""){EndDivNode.previousSibling.id=lbl2id;lbl2id=""}
if(ClassCount==0){RootNode=EndDivNode.previousSibling;}else{newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);}};break;case'LaTeXMathMLlabel':lbl2id=EndDivNode.previousSibling.id;EndDivNode.parentNode.removeChild(EndDivNode.previousSibling);break;default:newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);}}
RootNode.appendChild(newFrag);EndDivNode.parentNode.removeChild(EndDivNode);AllDivs=TheBody.getElementsByTagName("DIV");for(i=AllDivs.length-1;i>=0;i--){EndDivClass=AllDivs[i].className.match(/end\w+/);if(EndDivClass!=null){ClassCount=0;EndDivClass=EndDivClass[0];DivClass=EndDivClass.substring(3,EndDivClass.length);EndDivNode=AllDivs[i];RootNode=EndDivNode.parentNode;break;}}}
var AllDivs=TheBody.getElementsByTagName("div");var DIV2LI=null;for(var i=0;i0){for(var m=0;m");document.write("");}
function generic()
{translate();};if(typeof window.addEventListener!='undefined')
{window.addEventListener('load',generic,false);}
else if(typeof document.addEventListener!='undefined')
{document.addEventListener('load',generic,false);}
else if(typeof window.attachEvent!='undefined')
{window.attachEvent('onload',generic);}
else
{if(typeof window.onload=='function')
{var existing=onload;window.onload=function()
{existing();generic();};}
else
{window.onload=generic;}}
pandoc-1.12.2.1/data/MathMLinHTML.js000644 000765 000024 00000005015 12251233602 016522 0ustar00jgmstaff000000 000000 /* 
March 19, 2004 MathHTML (c) Peter Jipsen http://www.chapman.edu/~jipsen
Released under the GNU General Public License version 2 or later.
See the GNU General Public License (at http://www.gnu.org/copyleft/gpl.html)
for more details.
*/

function convertMath(node) {// for Gecko
  if (node.nodeType==1) {
    var newnode = 
      document.createElementNS("http://www.w3.org/1998/Math/MathML",
        node.nodeName.toLowerCase());
    for(var i=0; i < node.attributes.length; i++)
      newnode.setAttribute(node.attributes[i].nodeName,
        node.attributes[i].nodeValue);
    for (var i=0; i");
  document.write("");
}
if(typeof window.addEventListener != 'undefined'){
  window.addEventListener('load', convert, false);
}
if(typeof window.attachEvent != 'undefined') {
  window.attachEvent('onload', convert);
}
pandoc-1.12.2.1/data/reference.docx000644 000765 000024 00000023066 12251233602 016651 0ustar00jgmstaff000000 000000 PKWBMm*[Content_Types].xmlUT	)Q)Quxn0E
Ķ]tQnnH8f n=y}PE 
ؾ^ƃ-Bʄ"]!ƂX!TkT9.~y
i:}fFF:I%$sk(Rd[X~4uȉ&o8)wNIQZ6WV=iOH]/̙EA_,jkX|PK
N%B_rels/UT	4PPuxPKzn#@52Wj_rels/.relsUT	xxOPuxJ0.;oUƽ7Cf$$ Uc|MH;Lz]U

|o੽\ʂp
9vjyD)Myp1B ov	s"rӅ4cuD=^jOҞ.AȿYeb/|Ĵ'qe%bYP%c
?_Fo!G*тĂچQq"(;PK
N%B	docProps/UT	4PPuxPK[#@,,wJdocProps/app.xmlUT	~WOPuxRN0+i`M!MZa(uhi%{J'8ѓ߳ZCHbvhO&%`,Zs-2L؆
VN[M'9C[By{qJ5-gq'FYƷ.Qtt؞\-9
a{\q0yA"g#kʞp*FX}PKan#@	SdocProps/core.xmlUT	FxOPux͓?O0~({8Q*Q	fkkJo nw0./EXmIKNMm\e'jKƜC#[WAk<"oY$ .Ĭi5I%i!loX4%Ѐ!ZL`$$:-XdE;=%4FDdzNh93=WGekhejPwik*mh`g1b2I-xظAuݴL*8{]==(Ƒ1z֟Yzy%[Xq1Yγ|,yo	goCǀ$gV/PK
%Bword/UT	
PPuxPK
ȡ%Bword/_rels/UT	PPuxPK%BUX.word/_rels/document.xml.relsUT	PPuxK й ,@:rTZ_?|Ϩiс!{$F]U}D—
(ƂIeV'YH&poF7jKؚ@nϪꚇMvnjqY.]
>f?)oxH3p\ʘ+@qS,: ŀk)c90s4ʥ^+)x6;PKn#@Rword/document.xmlUT	xOPuxEI0E==MaPa5BRGIJ???cɷZVk2[wEֆgOڊ)PKNzNe>(W&DҘKf/vwq˝AOM֔G)vl8}mWPKTK#@jp<word/fontTable.xmlUT	P:OPuxMK@
wMZ5FJ44vN҆QO	,lwvvxI&ZkPZhY Lf,S2;OX5"etRsk<tإ!fЀ[
C^nOnxo堥ڴ{YZkpJmK2W8甲sDQex5yc0Os$bЋGQOV@K>$\#Z1FߣjCKT;!]9)\
np՘FFYI[H5Y	JYҷS}Tv걋GSPu 57z
SvjHPK%Bword/footnotes.xmlUT	PPuxj0y{t1L^ʞ`{؍!{yRB|F?t	sZ$qC/Z
>}˹9e8[j*ʃd$K7DŽ`,QYGQ8獽Y^Ysq&& 7;AIRW5l>vYKGɛi9{S*oPKM2@0]Bword/numbering.xmlUT	KOPuxՙN0ǯSTv	hEPibƴ4q5Dv0{I{	)RGks'?;8=ǨCJ}b=@Br74ގ#1r@x		x14x28&r:͏8NʙYg\'ߤ)L)ªcYxXg4D8NDL9@T2˱W?US# %|3^x0jDҶ^wIYZG'2FXU	>N֒<3.pjd$x`=hމOx$ӇthXIzSa^hh?0WFjword/settings.xmlUT	P:OPuxUMs0Wx|.$S $awY^H=MdzBzoj>fwN4)1Kwsuݙ6$	)3hf(`TrUhAtG0P)$B
5wd畢[A\" j]%+IR|)`z2m͆&9}t6._n.U\)R^!Ȕ5vVp[ KmͿJmX:78~R
'2P0w
L8V%(p~y `DYʴ9sؒ֗֌P~"xUd,H=<TƐ#7$
̬rܫ+ɱG'o0#A3'(Lg̫Zcs.&\@)XAJrxRL᳨;KNUpbo5GQuv/RéDUHtɢ<~+IdNZj4'_LF^&vzV~/Ϟy6DPXV붘G\ś#e1q$T RKmT8وNjA8_ðlBnʋwDک\Xj6L`}cPh1-k;nЖ܆i-p/x&Yvhם([X]LᲉv]ޕl-
E,ֈ[_c
jlha,6*VmHeSͿjgVp[ќiBade
xPK~Bڞ#word/styles.xmlUT	}WQ}WQuxYQs6~WxI)rCH3Lz>[`]lɕw%`B&]y%a`=a.Ҳ-L]:رlKHD=0E|r`aTͦp}"Eox$f3+!nΚH'I.{g.
$_/z̽3R({SfFQ)E		CBRAU좏CAf8}qWȜx\ӨE'vw7yal͙0Fd<̥8oxIs0CTFfT SD%4T'c&U:jh4NxvG%8vN0NRVb4I}}LZq]S9K!d/2#ќO3R#xٿ③g+2ORCΒ x?[0VX3g)69A
لJ\/AE#7Y0
ro55^Ey}ŖXяBGl*ԶK_C,CE9t,`<{C5N9R>hsgα<Ԝm{sBE8ϸ(a|"}_A.G=	
FPMs>lb~}6ThB,{
J7cz>]i56go%b}P]'q\^UJ,NX;GZ'vZ9aڭk(֣Xkڭkb=Q[}P^}?o%*tZ/SAX9jz@\l2}&S]DiB-[9RbX*xѲ*e_!jr/Z*'A!X5Vlky\t]"af=ѩyݝSi~n;%|}oᛕFoLμNgw9|JOA:gQ2xsSuW&E\+!5`F&ڛlʕsS-$]Acղ>1)_=<;~Ç~6HKzG_Rgtɋo>Gާ!9D<@M`KlDNd
J[c̰&@&{)jpsĖQ䛍d3S(^&aPr쓈(QZ6u|=ژSҧeAC Ի͙I&9(#aU`fRIX)H1*097n)RA}8zDJm1.{\m6H	9ב|06L@~$E1/durߥDmmߡ~`nH]bF'ql/_|DJEYpѷs7(!)=律h=/KSnCq/\xBRԘ-LT8*pf_}b.`-ԝ%)9 ^6]/tKP=Q3V̀KZ:fkΉl-NՕZf:3%yLKTh5
GZ|ɦs&'.&ɕ$E:;Ss,e
adQrUkq&UsWU+΢K&b!&A&|M9$Lެ^س%!qՂ0G;D6ndQ	_v#o+,pM<}.|HG{JCqP΅SgKBmY\u{`Y$.!|YJH.t**yx/br>7U)yvԒ]_͝?َ!ɩ痨C܏F|plo=gIJ({iG&3J1t!Ѥ3)6@{!X?]0O7Bvp!1-ΤM-gEbl	)3v)[PH::9eylS#%pg3=mPK[#@d$|word/webSettings.xmlUT	~WOPux]1082hYc
ʝլ&Ѧa!mޑN^k68cKDzAt9>A!Ӡ{"n?^u{m4|PKWBMm*[Content_Types].xmlUT)QuxPK
N%BA_rels/UT4PuxPKzn#@52Wj_rels/.relsUTxxOuxPK
N%B	A-docProps/UT4PuxPK[#@,,wJpdocProps/app.xmlUT~WOuxPKan#@	SdocProps/core.xmlUTFxOuxPK
%BAword/UT
PuxPK
ȡ%BAword/_rels/UTPuxPK%BUX.&word/_rels/document.xml.relsUTPuxPKn#@R^word/document.xmlUTxOuxPKTK#@jp<F	word/fontTable.xmlUTP:OuxPK%B-word/footnotes.xmlUTPuxPKM2@0]B]word/numbering.xmlUTKOuxPKTK#@>jQword/settings.xmlUTP:OuxPK~Bڞ#word/styles.xmlUT}WQuxPK
N%BAword/theme/UT4PuxPKTK#@\"word/theme/theme1.xmlUTP:OuxPK[#@d$|Pword/webSettings.xmlUT~WOuxPK pandoc-1.12.2.1/data/reference.odt000644 000765 000024 00000024543 12251233602 016503 0ustar00jgmstaff000000 000000 PKC^2''mimetypeapplication/vnd.oasis.opendocument.textPK;CAJmeta.xmlUT	)R)RuxRv +xĞ
5[è:\'$á%o@}'\:szx~fosWPKC"&settings.xmlZ]s:}"67LBHiiI`6s&t#k=ߕi
8?vs|X(odۤ{O
fcF\.-/ޡ5wwhrǺʞ~
_8gggdW98l߼8r]m@./Q;6$1piMmV03>,=_]^|qp./p9:&wL04Jl+\jϘG?Yre+cu8;Tj}\{RQAyKzq9ERƨSZuI;갥w)m4ʻ(fbi3ph
WX!M%S[zs
\ic}	=ULl(@=Ob=Imڨl g%(=͈HqթĿ@Z~H3K$bMAYGi-7
8M9օ>^t\~B@sϞ{y ;w	eR=6k`R#n(od`>hDقRAVU'[|];z%M0۷J³?I|ձpY;Tŋ90V۶dM!08To# jIe7GO^Zeْ!x=b$7ڥ^p0U`asZɚPKC+^+content.xmlWo6~_i@4jbhQl@2M!)E$eEKelxH=|V2pcV|vsg\Q̈́Z-o/_]iT\9Dr["JycTPp5W裋`+Xg;uS;fSAK=^ĉ#/Rڹmۛv~
q&iՍ({cnfVܑyl%TL
qMVf5"651k#靳靳>"n=	xSM屃PQ#ی>_k\ؠݻ_q|۳MN)4E\W_} Gq[63]2	eQѝ
q)0	ٺK]%K;0v
1>4&?*0/Q?7fcRCYsԍMٵ /"2Њ\vRBu]an4u5+5u5vN%+22{K3._vvlvB	7*	q*!޴w"vnmN(I_%[{'kbʐz	`/ZӷS(QÍPaDXĠ\;2mYV%6nao7jK/!\-wF
,,1akIvH7IC2|6>^KuZJ>OՑүp,/Rm$y>-&rG>PKCqŃThumbnails/thumbnail.pngPNG


IHDRg?IDATxA
0Q_ EQ{jC\s8I1I1I1I1I1I1I1I1I1I1I,mi>*oGOy+އoo'^=gIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIꐵ|AR8I1I1I1I1I1I1I1I1I1I1I1I(ppIENDB`PKChmanifest.rdf͓n0
styles.xml][~0@db2 4HMf7-Ѷ(2٧<}/
}(
??$EILѺ֌IL|I^}wG0ݏ:ABm?RY?{Whq,xg#+C/RɅ7»~y`ûȺC>Fw*)mN|6&`]d*̷pۘbLTc*Xh)i:އ.p8L۩Z6S8pmM`ThTv#PW?"˫5jC"pa[;"X;Ԏ
*\tawam Ud9W}6`_w,"[
4!J$lRCD0-\+CEa9m%@4ѕ=(2E6FGϦ.ڻӋԦXctOƅ)wN5B|6)ɦ
vITm7(x`G.mvW0ЈD~Jqa$Ax*6$odţ7Q~.aJP9wh>Sߠ8p`0}(-'G.Ϧ=aD|'p8>ivXH}**P,`F	>b"oC'6/9Jd5	2>h<}6܀el0황
sq*~+~O986KGtDwQC)cuiKOxzG
>P	}`aP|D$S%L&@txW98NI!>E/"
#DA%wYPP=+(!6Q(Ѻ&gCJ[*	IUCasrfQG-sAXx?̇f%8IOs=cZņIk<	$ԅfn:qjaՙp
ˌB!:`̂QǞIdzcM8i8)GQ'n擦>41-‹s]Jy$C$^t,JLI94#!?w%S%\Fs!DdfÙtׁJDhy&s7L>Ǖ"ugS>
ՕlH⑉?kd?: Cew>$X("D]\vpcW
t
x
O.0N[J)|Zu
Žo>$rN۾8'.!ZVz՝~mTⅫwI5Cmo=
bӱT[Ɇ$eatR+RFZ`
Ou:o
}XoIkL{'
D`81ҲYkKWxG>ɒhOh>@gvu0&\e*#u&@۷q.w~e'4f+SSoŽYoȽo\F_onnI3fWvҬ|2Cw~i]o^fOoN>CsWм=⡊-=Et+l
>Nk>p.ce,dA*qzP:[/P	 MBx#^ŽH0@xp*8.UMU< '!"(j=/2O{s/fQאw*u>3SX{Ot~CB40b̥7RT}H\US̚o4>Dw8䅐\}둓Sd8͓B]SVܸHzUc'8W7V%B"x홥GRD
Zux-]ֻ,="%/TE:'c_|vNO6O@ 4^iKuӨ z+ؐJ-9RT><Н14rV'#	6?J[_5y(E'rNF^Yk|(>bj5┖owB:MtqmFB\~duIP׼xqzݒ[nzM}0,کԈ%vИP?!k+PxX<|)_*V'?,QbE3B@j%e~)qHj%Az\X$iq5r-kZړ_5(تkS-cj͆9LTk1LTk5L4zxeh+DṵwĪ޸Cy5?dRo6fRrZ3[v2*o`~軤ʚܴIa6awzrvaRW݋bvY烰{/kbvkmIWڽڽ¼:0|Il\uSWJXssAr+Ҷ<7Vn~4؆I6;]Js2=kGsq+;f,/VnL{;6v/+CfB\I^4[RjJ5@v/mLfKC״;ݫv&crNj6ܜ5UBlqY]K93`ypc9'\s=~gLLsale{O>pdV\~5dV셊 Ӎ=BfvB0F[%:2s+dfCGynRynjf7凁LGm"ndq7(w~Ioy9G'y6O{NE'zâ=~aщD{Xtb/:,:݈svL8d߇P?r?rOdnEKdnEKdnEKdnE+dnEKdnEKh({~7oϿ.{i
{n
{n
{nM{n	 3(dX88_Me
\}=nϫ*nF`ekaL\CCb7Pud({Y)$@4Q%t2$6؝bl$|NʃMETA-INF/manifest.xmlTKn fU8YT	PSv-;E{ AmTI}S]gVk>
sBL^( >X{GO}26
>yTbY7iS!V(B6}:ǵncAO9ۉ_PKC^2''mimetypePK;CAJMmeta.xmlUT)RuxPKC"&settings.xmlPKC+^+content.xmlPKCqŃThumbnails/thumbnail.pngPKChmanifest.rdfPKC Configurations2/images/Bitmaps/PKC]Configurations2/popupmenu/PKCConfigurations2/toolpanel/PKCConfigurations2/statusbar/PKCConfigurations2/progressbar/PKC?Configurations2/toolbar/PKCuConfigurations2/menubar/PKC'Configurations2/accelerator/current.xmlPKCConfigurations2/floater/PKC0s&>
(styles.xmlPKC_ŀ2>v#META-INF/manifest.xmlPK$pandoc-1.12.2.1/data/sample.lua000644 000765 000024 00000020527 12251233602 016017 0ustar00jgmstaff000000 000000 -- This is a sample custom writer for pandoc.  It produces output
-- that is very similar to that of pandoc's HTML writer.
-- There is one new feature: code blocks marked with class 'dot'
-- are piped through graphviz and images are included in the HTML
-- output using 'data:' URLs.
--
-- Invoke with: pandoc -t sample.lua
--
-- Note:  you need not have lua installed on your system to use this
-- custom writer.  However, if you do have lua installed, you can
-- use it to test changes to the script.  'lua sample.lua' will
-- produce informative error messages if your code contains
-- syntax errors.

-- Character escaping
local function escape(s, in_attribute)
  return s:gsub("[<>&\"']",
    function(x)
      if x == '<' then
        return '<'
      elseif x == '>' then
        return '>'
      elseif x == '&' then
        return '&'
      elseif x == '"' then
        return '"'
      elseif x == "'" then
        return '''
      else
        return x
      end
    end)
end

-- Helper function to convert an attributes table into
-- a string that can be put into HTML tags.
local function attributes(attr)
  local attr_table = {}
  for x,y in pairs(attr) do
    if y and y ~= "" then
      table.insert(attr_table, ' ' .. x .. '="' .. escape(y,true) .. '"')
    end
  end
  return table.concat(attr_table)
end

-- Run cmd on a temporary file containing inp and return result.
local function pipe(cmd, inp)
  local tmp = os.tmpname()
  local tmph = io.open(tmp, "w")
  tmph:write(inp)
  tmph:close()
  local outh = io.popen(cmd .. " " .. tmp,"r")
  local result = outh:read("*all")
  outh:close()
  os.remove(tmp)
  return result
end

-- Table to store footnotes, so they can be included at the end.
local notes = {}

-- Blocksep is used to separate block elements.
function Blocksep()
  return "\n\n"
end

-- This function is called once for the whole document. Parameters:
-- body is a string, metadata is a table, variables is a table.
-- One could use some kind of templating
-- system here; this just gives you a simple standalone HTML file.
function Doc(body, metadata, variables)
  local buffer = {}
  local function add(s)
    table.insert(buffer, s)
  end
  add('')
  add('')
  add('')
  add('' .. (metadata['title'] or '') .. '')
  add('')
  add('')
  if metadata['title'] and metadata['title'] ~= "" then
    add('

' .. metadata['title'] .. '

') end for _, author in pairs(metadata['author'] or {}) do add('

' .. author .. '

') end if metadata['date'] and metadata['date'] ~= "" then add('

' .. metadata.date .. '

') end add(body) if #notes > 0 then add('
    ') for _,note in pairs(notes) do add(note) end add('
') end add('') add('') return table.concat(buffer,'\n') end -- The functions that follow render corresponding pandoc elements. -- s is always a string, attr is always a table of attributes, and -- items is always an array of strings (the items in a list). -- Comments indicate the types of other variables. function Str(s) return escape(s) end function Space() return " " end function LineBreak() return "
" end function Emph(s) return "" .. s .. "" end function Strong(s) return "" .. s .. "" end function Subscript(s) return "" .. s .. "" end function Superscript(s) return "" .. s .. "" end function SmallCaps(s) return '' .. s .. '' end function Strikeout(s) return '' .. s .. '' end function Link(s, src, tit) return "" .. s .. "" end function Image(s, src, tit) return "" end function Code(s, attr) return "" .. escape(s) .. "
" end function InlineMath(s) return "\\(" .. escape(s) .. "\\)" end function DisplayMath(s) return "\\[" .. escape(s) .. "\\]" end function Note(s) local num = #notes + 1 -- insert the back reference right before the final closing tag. s = string.gsub(s, '(.*)' .. s .. '') -- return the footnote reference, linked to the note. return '' .. num .. '' end function Span(s, attr) return "" .. s .. "" end function Plain(s) return s end function Para(s) return "

" .. s .. "

" end -- lev is an integer, the header level. function Header(lev, s, attr) return "" .. s .. "" end function BlockQuote(s) return "
\n" .. s .. "\n
" end function HorizontalRule() return "
" end function CodeBlock(s, attr) -- If code block has class 'dot', pipe the contents through dot -- and base64, and include the base64-encoded png as a data: URL. if attr.class and string.match(' ' .. attr.class .. ' ',' dot ') then local png = pipe("base64", pipe("dot -Tpng", s)) return '' -- otherwise treat as code (one could pipe through a highlighter) else return "
" .. escape(s) ..
           "
" end end function BulletList(items) local buffer = {} for _, item in pairs(items) do table.insert(buffer, "
  • " .. item .. "
  • ") end return "
      \n" .. table.concat(buffer, "\n") .. "\n
    " end function OrderedList(items) local buffer = {} for _, item in pairs(items) do table.insert(buffer, "
  • " .. item .. "
  • ") end return "
      \n" .. table.concat(buffer, "\n") .. "\n
    " end -- Revisit association list STackValue instance. function DefinitionList(items) local buffer = {} for _,item in pairs(items) do for k, v in pairs(item) do table.insert(buffer,"
    " .. k .. "
    \n
    " .. table.concat(v,"
    \n
    ") .. "
    ") end end return "
    \n" .. table.concat(buffer, "\n") .. "\n
    " end -- Convert pandoc alignment to something HTML can use. -- align is AlignLeft, AlignRight, AlignCenter, or AlignDefault. function html_align(align) if align == 'AlignLeft' then return 'left' elseif align == 'AlignRight' then return 'right' elseif align == 'AlignCenter' then return 'center' else return 'left' end end -- Caption is a string, aligns is an array of strings, -- widths is an array of floats, headers is an array of -- strings, rows is an array of arrays of strings. function Table(caption, aligns, widths, headers, rows) local buffer = {} local function add(s) table.insert(buffer, s) end add("") if caption ~= "" then add("") end if widths and widths[1] ~= 0 then for _, w in pairs(widths) do add('') end end local header_row = {} local empty_header = true for i, h in pairs(headers) do local align = html_align(aligns[i]) table.insert(header_row,'') empty_header = empty_header and h == "" end if empty_header then head = "" else add('') for _,h in pairs(header_row) do add(h) end add('') end local class = "even" for _, row in pairs(rows) do class = (class == "even" and "odd") or "even" add('') for i,c in pairs(row) do add('') end add('') end add('\n" .. s .. "" end -- The following code will produce runtime warnings when you haven't defined -- all of the functions you need for the custom writer, so it's useful -- to include when you're working on a writer. local meta = {} meta.__index = function(_, key) io.stderr:write(string.format("WARNING: Undefined function '%s'\n",key)) return function() return "" end end setmetatable(_G, meta) pandoc-1.12.2.1/data/templates/000755 000765 000024 00000000000 12251233602 016023 5ustar00jgmstaff000000 000000 pandoc-1.12.2.1/data/templates/default.asciidoc000644 000765 000024 00000000436 12251233602 021152 0ustar00jgmstaff000000 000000 $if(titleblock)$ $title$ $for(author)$ :author: $author$ $endfor$ $if(date)$ :date: $date$ $endif$ $if(toc)$ :toc: $endif$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.beamer000644 000765 000024 00000007123 12251233602 020627 0ustar00jgmstaff000000 000000 \documentclass[$if(fontsize)$$fontsize$,$endif$$if(handout)$handout,$endif$$if(beamer)$ignorenonframetext,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$} $if(theme)$ \usetheme{$theme$} $endif$ $if(colortheme)$ \usecolortheme{$colortheme$} $endif$ $if(fonttheme)$ \usefonttheme{$fonttheme$} $endif$ \usepackage{amssymb,amsmath} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript \ifxetex \usepackage{fontspec,xltxtra,xunicode} \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \else \ifluatex \usepackage{fontspec} \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \else \usepackage[utf8]{inputenc} \fi \fi $if(natbib)$ \usepackage{natbib} \bibliographystyle{plainnat} $endif$ $if(biblatex)$ \usepackage{biblatex} $if(biblio-files)$ \bibliography{$biblio-files$} $endif$ $endif$ $if(listings)$ \usepackage{listings} $endif$ $if(lhs)$ \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} $endif$ $if(highlighting-macros)$ $highlighting-macros$ $endif$ $if(verbatim-in-note)$ \usepackage{fancyvrb} $endif$ $if(tables)$ \usepackage{longtable} % These lines are needed to make table captions work with longtable: \makeatletter \def\fnum@table{\tablename~\thetable} \makeatother $endif$ $if(url)$ \usepackage{url} $endif$ $if(graphics)$ \usepackage{graphicx} % Redefine \includegraphics so that, unless explicit options are % given, the image width will not exceed the width of the page. % Images get their normal width if they fit onto the page, but % are scaled down if they would overflow the margins. \makeatletter \def\ScaleIfNeeded{% \ifdim\Gin@nat@width>\linewidth \linewidth \else \Gin@nat@width \fi } \makeatother \let\Oldincludegraphics\includegraphics \renewcommand{\includegraphics}[2][]{\Oldincludegraphics[width=\ScaleIfNeeded]{#2}} $endif$ % Comment these out if you don't want a slide with just the % part/section/subsection/subsubsection title: \AtBeginPart{ \let\insertpartnumber\relax \let\partname\relax \frame{\partpage} } \AtBeginSection{ \let\insertsectionnumber\relax \let\sectionname\relax \frame{\sectionpage} } \AtBeginSubsection{ \let\insertsubsectionnumber\relax \let\subsectionname\relax \frame{\subsectionpage} } $if(strikeout)$ \usepackage[normalem]{ulem} % avoid problems with \sout in headers with hyperref: \pdfstringdefDisableCommands{\renewcommand{\sout}{}} $endif$ \setlength{\parindent}{0pt} \setlength{\parskip}{6pt plus 2pt minus 1pt} \setlength{\emergencystretch}{3em} % prevent overfull lines $if(numbersections)$ $else$ \setcounter{secnumdepth}{0} $endif$ $if(verbatim-in-note)$ \VerbatimFootnotes % allows verbatim text in footnotes $endif$ $if(lang)$ \usepackage[$lang$]{babel} $endif$ $for(header-includes)$ $header-includes$ $endfor$ $if(title)$ \title{$title$} $endif$ $if(subtitle)$ \subtitle{$subtitle$} $endif$ $if(author)$ \author{$for(author)$$author$$sep$ \and $endfor$} $endif$ $if(date)$ \date{$date$} $endif$ \begin{document} $if(title)$ \frame{\titlepage} $endif$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ \begin{frame} \tableofcontents[hideallsubsections] \end{frame} $endif$ $body$ $if(natbib)$ $if(biblio-files)$ $if(biblio-title)$ $if(book-class)$ \renewcommand\bibname{$biblio-title$} $else$ \renewcommand\refname{$biblio-title$} $endif$ $endif$ \begin{frame}[allowframebreaks]{$biblio-title$} \bibliography{$biblio-files$} \end{frame} $endif$ $endif$ $if(biblatex)$ \begin{frame}[allowframebreaks]{$biblio-title$} \printbibliography[heading=none] \end{frame} $endif$ $for(include-after)$ $include-after$ $endfor$ \end{document} pandoc-1.12.2.1/data/templates/default.context000644 000765 000024 00000003372 12251233602 021062 0ustar00jgmstaff000000 000000 \startmode[*mkii] \enableregime[utf-8] \setupcolors[state=start] \stopmode $if(mainlang)$ \mainlanguage[$mainlang$] $endif$ % Enable hyperlinks \setupinteraction[state=start, color=middleblue] \setuppapersize [$if(papersize)$$papersize$$else$letter$endif$][$if(papersize)$$papersize$$else$letter$endif$] \setuplayout [width=middle, backspace=1.5in, cutspace=1.5in, height=middle, topspace=0.75in, bottomspace=0.75in] \setuppagenumbering[location={footer,center}] \setupbodyfont[11pt] \setupwhitespace[medium] \setuphead[chapter] [style=\tfd] \setuphead[section] [style=\tfc] \setuphead[subsection] [style=\tfb] \setuphead[subsubsection][style=\bf] $if(number-sections)$ $else$ \setuphead[chapter, section, subsection, subsubsection][number=no] $endif$ \definedescription [description] [headstyle=bold, style=normal, location=hanging, width=broad, margin=1cm] \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 [blockquote] [before={\blank[medium]}, after={\blank[medium]}, indentnext=no, ] $if(toc)$ \setupcombinedlist[content][list={$placelist$}] $endif$ $for(header-includes)$ $header-includes$ $endfor$ \starttext $if(title)$ \startalignment[center] \blank[2*big] {\tfd $title$} $if(author)$ \blank[3*medium] {\tfa $for(author)$$author$$sep$\crlf $endfor$} $endif$ $if(date)$ \blank[2*medium] {\tfa $date$} $endif$ \blank[3*medium] \stopalignment $endif$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ \placecontent $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ \stoptext pandoc-1.12.2.1/data/templates/default.docbook000644 000765 000024 00000001217 12251233602 021012 0ustar00jgmstaff000000 000000 $if(mathml)$ $else$ $endif$
    $title$ $for(author)$ $author$ $endfor$ $if(date)$ $date$ $endif$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$
    pandoc-1.12.2.1/data/templates/default.dzslides000644 000765 000024 00000005573 12251233602 021224 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(highlighting-css)$ $endif$ $if(css)$ $for(css)$ $endfor$ $else$ $endif$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$

    $date$

    $endif$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ $dzslides-core$ pandoc-1.12.2.1/data/templates/default.epub000644 000765 000024 00000001544 12251233602 020330 0ustar00jgmstaff000000 000000 $pagetitle$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(titlepage)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$ $if(date)$

    $date$

    $endif$ $else$ $body$ $endif$ pandoc-1.12.2.1/data/templates/default.epub3000644 000765 000024 00000001446 12251233602 020414 0ustar00jgmstaff000000 000000 $pagetitle$ $if(quotes)$ $endif$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(titlepage)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$ $if(date)$

    $date$

    $endif$ $else$ $body$ $endif$ pandoc-1.12.2.1/data/templates/default.html000644 000765 000024 00000002702 12251233602 020336 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(quotes)$ $endif$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$ $if(date)$

    $date$

    $endif$
    $endif$ $if(toc)$
    $toc$
    $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.html5000644 000765 000024 00000002512 12251233602 020422 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(quotes)$ $endif$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$ $if(date)$

    $date$

    $endif$
    $endif$ $if(toc)$ $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.latex000644 000765 000024 00000010606 12251233602 020511 0ustar00jgmstaff000000 000000 \documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$$if(papersize)$$papersize$,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{amssymb,amsmath} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript % use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex \usepackage[utf8]{inputenc} $if(euro)$ \usepackage{eurosym} $endif$ \else % if luatex or xelatex \ifxetex \usepackage{mathspec} \usepackage{xltxtra,xunicode} \else \usepackage{fontspec} \fi \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \newcommand{\euro}{€} $if(mainfont)$ \setmainfont{$mainfont$} $endif$ $if(sansfont)$ \setsansfont{$sansfont$} $endif$ $if(monofont)$ \setmonofont[Mapping=tex-ansi]{$monofont$} $endif$ $if(mathfont)$ \setmathfont(Digits,Latin,Greek){$mathfont$} $endif$ \fi % use microtype if available \IfFileExists{microtype.sty}{\usepackage{microtype}}{} $if(geometry)$ \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} $endif$ $if(natbib)$ \usepackage{natbib} \bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} $endif$ $if(biblatex)$ \usepackage{biblatex} $if(biblio-files)$ \bibliography{$biblio-files$} $endif$ $endif$ $if(listings)$ \usepackage{listings} $endif$ $if(lhs)$ \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} $endif$ $if(highlighting-macros)$ $highlighting-macros$ $endif$ $if(verbatim-in-note)$ \usepackage{fancyvrb} $endif$ $if(tables)$ \usepackage{longtable,booktabs} $endif$ $if(graphics)$ \usepackage{graphicx} % Redefine \includegraphics so that, unless explicit options are % given, the image width will not exceed the width of the page. % Images get their normal width if they fit onto the page, but % are scaled down if they would overflow the margins. \makeatletter \def\ScaleIfNeeded{% \ifdim\Gin@nat@width>\linewidth \linewidth \else \Gin@nat@width \fi } \makeatother \let\Oldincludegraphics\includegraphics {% \catcode`\@=11\relax% \gdef\includegraphics{\@ifnextchar[{\Oldincludegraphics}{\Oldincludegraphics[width=\ScaleIfNeeded]}}% }% $endif$ \ifxetex \usepackage[setpagesize=false, % page size defined by xetex unicode=false, % unicode breaks when used with xetex xetex]{hyperref} \else \usepackage[unicode=true]{hyperref} \fi \hypersetup{breaklinks=true, bookmarks=true, pdfauthor={$author-meta$}, pdftitle={$title-meta$}, colorlinks=true, citecolor=$if(citecolor)$$citecolor$$else$blue$endif$, urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$, linkcolor=$if(linkcolor)$$linkcolor$$else$magenta$endif$, pdfborder={0 0 0}} \urlstyle{same} % don't use monospace font for urls $if(links-as-notes)$ % Make links footnotes instead of hotlinks: \renewcommand{\href}[2]{#2\footnote{\url{#1}}} $endif$ $if(strikeout)$ \usepackage[normalem]{ulem} % avoid problems with \sout in headers with hyperref: \pdfstringdefDisableCommands{\renewcommand{\sout}{}} $endif$ \setlength{\parindent}{0pt} \setlength{\parskip}{6pt plus 2pt minus 1pt} \setlength{\emergencystretch}{3em} % prevent overfull lines $if(numbersections)$ \setcounter{secnumdepth}{5} $else$ \setcounter{secnumdepth}{0} $endif$ $if(verbatim-in-note)$ \VerbatimFootnotes % allows verbatim text in footnotes $endif$ $if(lang)$ \ifxetex \usepackage{polyglossia} \setmainlanguage{$mainlang$} \else \usepackage[$lang$]{babel} \fi $endif$ $for(header-includes)$ $header-includes$ $endfor$ $if(title)$ \title{$title$} $endif$ $if(subtitle)$ \subtitle{$subtitle$} $endif$ \author{$for(author)$$author$$sep$ \and $endfor$} \date{$date$} \begin{document} $if(title)$ \maketitle $endif$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ { \hypersetup{linkcolor=black} \setcounter{tocdepth}{$toc-depth$} \tableofcontents } $endif$ $body$ $if(natbib)$ $if(biblio-files)$ $if(biblio-title)$ $if(book-class)$ \renewcommand\bibname{$biblio-title$} $else$ \renewcommand\refname{$biblio-title$} $endif$ $endif$ \bibliography{$biblio-files$} $endif$ $endif$ $if(biblatex)$ \printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ $endif$ $for(include-after)$ $include-after$ $endfor$ \end{document} pandoc-1.12.2.1/data/templates/default.man000644 000765 000024 00000000465 12251233602 020151 0ustar00jgmstaff000000 000000 $if(has-tables)$ .\"t $endif$ .TH "$title$" "$section$" "$date$" "$footer$" "$header$" $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ $if(author)$ .SH AUTHORS $for(author)$$author$$sep$; $endfor$. $endif$ pandoc-1.12.2.1/data/templates/default.markdown000644 000765 000024 00000000332 12251233602 021211 0ustar00jgmstaff000000 000000 $if(titleblock)$ $titleblock$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ $toc$ $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.mediawiki000644 000765 000024 00000000202 12251233602 021326 0ustar00jgmstaff000000 000000 $for(include-before)$ $include-before$ $endfor$ $if(toc)$ __TOC__ $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.opendocument000644 000765 000024 00000003766 12251233602 022105 0ustar00jgmstaff000000 000000 $automatic-styles$ $for(header-includes)$ $header-includes$ $endfor$ $if(title)$ $title$ $endif$ $for(author)$ $author$ $endfor$ $if(date)$ $date$ $endif$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.opml000644 000765 000024 00000000364 12251233602 020343 0ustar00jgmstaff000000 000000 $title$ $date$ $for(author)$$author$$sep$; $endfor$ $body$ pandoc-1.12.2.1/data/templates/default.org000644 000765 000024 00000000447 12251233602 020165 0ustar00jgmstaff000000 000000 $if(title)$ #+TITLE: $title$ $endif$ $if(author)$ #+AUTHOR: $for(author)$$author$$sep$; $endfor$ $endif$ $if(date)$ #+DATE: $date$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.plain000644 000765 000024 00000000332 12251233602 020472 0ustar00jgmstaff000000 000000 $if(titleblock)$ $titleblock$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ $toc$ $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.revealjs000644 000765 000024 00000006135 12251233602 021211 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(highlighting-css)$ $endif$ $if(css)$ $for(css)$ $endfor$ $else$ $endif$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$
    $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$

    $date$

    $endif$ $if(toc)$
    $toc$
    $endif$ $body$
    $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.rst000644 000765 000024 00000000661 12251233602 020204 0ustar00jgmstaff000000 000000 $if(title)$ $title$ $endif$ $for(author)$ :Author: $author$ $endfor$ $if(date)$ :Date: $date$ $endif$ $if(author)$ $else$ $if(date)$ $endif$ $endif$ $if(math)$ .. role:: math(raw) :format: html latex .. $endif$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ .. contents:: :depth: $toc-depth$ .. $endif$ $for(header-includes)$ $header-includes$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.rtf000644 000765 000024 00000001112 12251233602 020157 0ustar00jgmstaff000000 000000 {\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 Courier;}} {\colortbl;\red255\green0\blue0;\red0\green0\blue255;} \widowctrl\hyphauto $for(header-includes)$ $header-includes$ $endfor$ $if(title)$ {\pard \qc \f0 \sa180 \li0 \fi0 \b \fs36 $title$\par} $endif$ $for(author)$ {\pard \qc \f0 \sa180 \li0 \fi0 $author$\par} $endfor$ $if(date)$ {\pard \qc \f0 \sa180 \li0 \fi0 $date$\par} $endif$ $if(spacer)$ {\pard \ql \f0 \sa180 \li0 \fi0 \par} $endif$ $if(toc)$ $toc$ $endif$ $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ } pandoc-1.12.2.1/data/templates/default.s5000644 000765 000024 00000004031 12251233602 017716 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $for(include-before)$ $include-before$ $endfor$
    $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$

    $for(author)$$author$$sep$
    $endfor$

    $date$

    $endif$ $body$ $for(include-after)$ $include-after$ $endfor$
    pandoc-1.12.2.1/data/templates/default.slideous000644 000765 000024 00000004670 12251233602 021227 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $if(duration)$ $endif$ $for(include-before)$ $include-before$ $endfor$
    of {$$slidecount} ½ {$$title}, {$$author}
    $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$

    $for(author)$$author$$sep$
    $endfor$

    $if(date)$

    $date$

    $endif$
    $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.slidy000644 000765 000024 00000003207 12251233602 020517 0ustar00jgmstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ $if(highlighting-css)$ $endif$ $for(css)$ $endfor$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$ $if(duration)$ $endif$ $for(include-before)$ $include-before$ $endfor$ $if(title)$

    $title$

    $if(subtitle)$

    $subtitle$

    $endif$

    $for(author)$$author$$sep$
    $endfor$

    $if(date)$

    $date$

    $endif$
    $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/templates/default.texinfo000644 000765 000024 00000001373 12251233602 021051 0ustar00jgmstaff000000 000000 \input texinfo @documentencoding UTF-8 $for(header-includes)$ $header-includes$ $endfor$ $if(strikeout)$ @macro textstrikeout{text} ~~\text\~~ @end macro $endif$ $if(subscript)$ @macro textsubscript{text} @iftex @textsubscript{\text\} @end iftex @ifnottex _@{\text\@} @end ifnottex @end macro $endif$ $if(superscript)$ @macro textsuperscript{text} @iftex @textsuperscript{\text\} @end iftex @ifnottex ^@{\text\@} @end ifnottex @end macro $endif$ @ifnottex @paragraphindent 0 @end ifnottex $if(titlepage)$ @titlepage @title $title$ $for(author)$ @author $author$ $endfor$ $if(date)$ $date$ $endif$ @end titlepage $endif$ $for(include-before)$ $include-before$ $endfor$ $if(toc)$ @contents $endif$ $body$ $for(include-after)$ $include-after$ $endfor$ @bye pandoc-1.12.2.1/data/templates/default.textile000644 000765 000024 00000000147 12251233602 021051 0ustar00jgmstaff000000 000000 $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ pandoc-1.12.2.1/data/dzslides/template.html000644 000765 000024 00000035754 12251233602 020365 0ustar00jgmstaff000000 000000 The Title Of Your Presentation

    My Presentation

    by John Doe

    Some random text: But I've never been to the moon! You can see how I lived before I met you. Also Zoidberg. I could if you hadn't turned on the light and shut off my stereo.

    An incremental list

    • Item 1
    • Item 2
    • Item 3
    Some notes. They are only visible using onstage shell.
    Who's brave enough to fly into something we all keep calling a death sphere?

    Part two

    An image
    Kittens are so cute!
    A video

    End!

    pandoc-1.12.2.1/benchmark/benchmark-pandoc.hs000644 000765 000024 00000002666 12251233602 020610 0ustar00jgmstaff000000 000000 import Text.Pandoc import Criterion.Main import Criterion.Config import System.Environment (getArgs) import Data.Monoid readerBench :: Pandoc -> (String, ReaderOptions -> String -> IO Pandoc) -> Benchmark readerBench doc (name, reader) = let writer = case lookup name writers of Just (PureStringWriter w) -> w _ -> error $ "Could not find writer for " ++ name inp = writer def{ writerWrapText = True } doc -- we compute the length to force full evaluation getLength (Pandoc (Meta _) d) = length d in bench (name ++ " reader") $ whnfIO $ getLength `fmap` (reader def{ readerSmart = True }) inp writerBench :: Pandoc -> (String, WriterOptions -> Pandoc -> String) -> Benchmark writerBench doc (name, writer) = bench (name ++ " writer") $ nf (writer def{ writerWrapText = True }) doc main :: IO () main = do args <- getArgs (conf,_) <- parseArgs defaultConfig{ cfgSamples = Last $ Just 20 } defaultOptions args inp <- readFile "README" 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) $ filter (\(n,_) -> n /="haddock") readers let writers' = [(n,w) | (n, PureStringWriter w) <- writers] defaultMainWith conf (return ()) $ map (writerBench doc) writers' ++ readerBs
    " .. caption .. "
    ' .. h .. '
    ' .. c .. '