git.iko.soy/typeable/pandoc
on master help sign in
Merge remote-tracking branch 'origin/master' into en-dash-ligature-avoidance.
1ba8066Vaclav Zeman
Interact.hs+4
@@ -9,6 +9,10 @@
9
9
10-- You must have first done a 'cabal configure' or 'cabal install'
10-- You must have first done a 'cabal configure' or 'cabal install'
11
11
12+-- Note: Interact.hs doesn't work with Cabal >= 1.18. I recommend
13+-- using cabal sandboxes and the new 'cabal repl' command if you are
14+-- using a recent version.
15+
12import System.Process
16import System.Process
13import Distribution.Simple.LocalBuildInfo
17import Distribution.Simple.LocalBuildInfo
14import Distribution.Package
18import Distribution.Package
README+119−12
@@ -108,7 +108,7 @@ to PDF:
108Production of a PDF requires that a LaTeX engine be installed (see
108Production of a PDF requires that a LaTeX engine be installed (see
109`--latex-engine`, below), and assumes that the following LaTeX packages are
109`--latex-engine`, below), and assumes that the following LaTeX packages are
110available: `amssymb`, `amsmath`, `ifxetex`, `ifluatex`, `listings` (if the
110available: `amssymb`, `amsmath`, `ifxetex`, `ifluatex`, `listings` (if the
111−`--listings` option is used), `fancyvrb`, `longtable`, `url`,
111+`--listings` option is used), `fancyvrb`, `longtable`, `booktabs`, `url`,
112`graphicx`, `hyperref`, `ulem`, `babel` (if the `lang` variable is set),
112`graphicx`, `hyperref`, `ulem`, `babel` (if the `lang` variable is set),
113`fontspec` (if `xelatex` or `lualatex` is used as the LaTeX engine), `xltxtra`
113`fontspec` (if `xelatex` or `lualatex` is used as the LaTeX engine), `xltxtra`
114and `xunicode` (if `xelatex` is used).
114and `xunicode` (if `xelatex` is used).
@@ -434,8 +434,8 @@ Options affecting specific writers
434`--chapters`
434`--chapters`
435: Treat top-level headers as chapters in LaTeX, ConTeXt, and DocBook
435: Treat top-level headers as chapters in LaTeX, ConTeXt, and DocBook
436 output. When the LaTeX template uses the report, book, or
436 output. When the LaTeX template uses the report, book, or
437− memoir class, this option is implied. If `--beamer` is used,
437+ memoir class, this option is implied. If `beamer` is the output
438− top-level headers will become `\part{..}`.
438+ format, top-level headers will become `\part{..}`.
439
439
440`-N`, `--number-sections`
440`-N`, `--number-sections`
441: Number section headings in LaTeX, ConTeXt, HTML, or EPUB output.
441: Number section headings in LaTeX, ConTeXt, HTML, or EPUB output.
@@ -541,7 +541,9 @@ Options affecting specific writers
541
541
542`--epub-cover-image=`*FILE*
542`--epub-cover-image=`*FILE*
543: Use the specified image as the EPUB cover. It is recommended
543: Use the specified image as the EPUB cover. It is recommended
544− that the image be less than 1000px in width and height.
544+ that the image be less than 1000px in width and height. Note that
545+ in a markdown source document you can also specify `cover-image`
546+ in a YAML metadata block (see [EPUB Metadata], below).
545
547
546`--epub-metadata=`*FILE*
548`--epub-metadata=`*FILE*
547: Look in the specified XML file for metadata for the EPUB.
549: Look in the specified XML file for metadata for the EPUB.
@@ -560,6 +562,10 @@ Options affecting specific writers
560 id="BookId">` (a randomly generated UUID). Any of these may be
562 id="BookId">` (a randomly generated UUID). Any of these may be
561 overridden by elements in the metadata file.
563 overridden by elements in the metadata file.
562
564
565+ Note: if the source document is markdown, a YAML metadata block
566+ in the document can be used instead. See below under
567+ [EPUB Metadata].
568+
563`--epub-embed-font=`*FILE*
569`--epub-embed-font=`*FILE*
564: Embed the specified font in the EPUB. This option can be repeated
570: Embed the specified font in the EPUB. This option can be repeated
565 to embed multiple fonts. To use embedded fonts, you
571 to embed multiple fonts. To use embedded fonts, you
@@ -795,6 +801,8 @@ as `title`, `author`, and `date`) as well as the following:
795: causes links to be printed as footnotes in LaTeX documents
801: causes links to be printed as footnotes in LaTeX documents
796`biblio-style`
802`biblio-style`
797: bibliography style in LaTeX, when used with `--natbib`
803: bibliography style in LaTeX, when used with `--natbib`
804+`biblio-files`
805+: bibliography files to use in LaTeX, with `--natbib` or `--biblatex`
798`section`
806`section`
799: section number in man pages
807: section number in man pages
800`header`
808`header`
@@ -888,6 +896,9 @@ If you need a hard line break, put two or more spaces at the end of a line.
888**Extension: `escaped_line_breaks`**
896**Extension: `escaped_line_breaks`**
889
897
890A backslash followed by a newline is also a hard line break.
898A backslash followed by a newline is also a hard line break.
899+Note: in multiline and grid table cells, this is the only way
900+to create a hard line break, since trailing spaces in the cells
901+are ignored.
891
902
892Headers
903Headers
893-------
904-------
@@ -1271,7 +1282,7 @@ one tab:
1271 + pears
1282 + pears
1272 + peaches
1283 + peaches
1273 * vegetables
1284 * vegetables
1274− + brocolli
1285+ + broccoli
1275 + chard
1286 + chard
1276
1287
1277As noted above, markdown allows you to write list items "lazily," instead of
1288As noted above, markdown allows you to write list items "lazily," instead of
@@ -1837,6 +1848,18 @@ equivalent of the markdown in the `abstract` field:
1837 <p>This is the abstract.</p>
1848 <p>This is the abstract.</p>
1838 <p>It consists of two paragraphs.</p>
1849 <p>It consists of two paragraphs.</p>
1839
1850
1851+Note: The `author` variable in the default templates expects a simple list or
1852+string. To use the structured authors in the example, you would need a
1853+custom template. For example:
1854+
1855+ $for(author)$
1856+ $if(author.name)$
1857+ $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$
1858+ $else$
1859+ $author$
1860+ $endif$
1861+ $endfor$
1862+
1840
1863
1841Backslash escapes
1864Backslash escapes
1842-----------------
1865-----------------
@@ -2085,7 +2108,7 @@ Raw HTML
2085
2108
2086Markdown allows you to insert raw HTML (or DocBook) anywhere in a document
2109Markdown allows you to insert raw HTML (or DocBook) anywhere in a document
2087(except verbatim contexts, where `<`, `>`, and `&` are interpreted
2110(except verbatim contexts, where `<`, `>`, and `&` are interpreted
2088−literally). (Techncially this is not an extension, since standard
2111+literally). (Technically this is not an extension, since standard
2089markdown allows it, but it has been made an extension so that it can
2112markdown allows it, but it has been made an extension so that it can
2090be disabled if desired.)
2113be disabled if desired.)
2091
2114
@@ -2498,10 +2521,9 @@ the document, for example:
2498 Comment: This is a sample mmd title block, with
2521 Comment: This is a sample mmd title block, with
2499 a field spanning multiple lines.
2522 a field spanning multiple lines.
2500
2523
2501−See the MultiMarkdown documentation for details. Note that only title,
2524+See the MultiMarkdown documentation for details. If `pandoc_title_block` or
2502−author, and date are recognized; other fields are simply ignored by
2503−pandoc. If `pandoc_title_block` or `yaml_metadata_block` is enabled,
2525+`yaml_metadata_block` is enabled, it will take precedence over
2504−it will take precedence over `mmd_title_block`.
2526+`mmd_title_block`.
2505
2527
2506 [MultiMarkdown]: http://fletcherpenney.net/multimarkdown/
2528 [MultiMarkdown]: http://fletcherpenney.net/multimarkdown/
2507
2529
@@ -2559,6 +2581,20 @@ variants are supported:
2559`markdown_strict` (Markdown.pl)
2581`markdown_strict` (Markdown.pl)
2560: `raw_html`
2582: `raw_html`
2561
2583
2584+Extensions with formats other than markdown
2585+-------------------------------------------
2586+
2587+Some of the extensions discussed above can be used with formats
2588+other than markdown:
2589+
2590+* `auto_identifiers` can be used with `latex`, `rst`, `mediawiki`,
2591+ and `textile` input (and is used by default).
2592+
2593+* `tex_math_dollars`, `tex_math_single_backslash`, and
2594+ `tex_math_double_backslash` can be used with `html` input.
2595+ (This is handy for reading web pages formatted using MathJax,
2596+ for example.)
2597+
2562Producing slide shows with Pandoc
2598Producing slide shows with Pandoc
2563=================================
2599=================================
2564
2600
@@ -2749,11 +2785,81 @@ To show the notes window, press `s` while viewing the presentation.
2749Notes are not yet supported for other slide formats, but the notes
2785Notes are not yet supported for other slide formats, but the notes
2750will not appear on the slides themselves.
2786will not appear on the slides themselves.
2751
2787
2788+EPUB Metadata
2789+=============
2790+
2791+EPUB metadata may be specified using the `--epub-metadata` option, but
2792+if the source document is markdown, it is better to use a YAML metadata
2793+block. Here is an example:
2794+
2795+ ---
2796+ title:
2797+ - type: main
2798+ text: My Book
2799+ - type: subtitle
2800+ text: An investigation of metadata
2801+ creator:
2802+ - role: author
2803+ text: John Smith
2804+ - role: editor
2805+ text: Sarah Jones
2806+ identifier:
2807+ - scheme: DOI
2808+ text: doi:10.234234.234/33
2809+ publisher: My Press
2810+ rights: (c) 2007 John Smith, CC BY-NC
2811+ ...
2812+
2813+The following fields are recognized:
2814+
2815+`identifier`
2816+ ~ Either a string value or an object with fields `text` and
2817+ `scheme`. Valid values for `scheme` are `ISBN-10`,
2818+ `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,
2819+ `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`,
2820+ `ISMN-13`, `ISBN-A`, `JP`, `OLCC`.
2821+`title`
2822+ ~ Either a string value, or an object with fields `file-as` and
2823+ `type`, or a list of such objects. Valid values for `type` are
2824+ `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.
2825+`creator`
2826+ ~ Either a string value, or an object with fields `role`, `file-as`,
2827+ and `text`, or a list of such objects. Valid values for `role` are
2828+ [marc relators](http://www.loc.gov/marc/relators/relaterm.html), but
2829+ pandoc will attempt to translate the human-readable versions
2830+ (like "author" and "editor") to the appropriate marc relators.
2831+`contributor`
2832+ ~ Same format as `creator`.
2833+`date`
2834+ ~ A string value in `YYYY-MM-DD` format. (Only the year is necessary.)
2835+ Pandoc will attempt to convert other common date formats.
2836+`language`
2837+ ~ A string value in [RFC5646] format. Pandoc will default to the local
2838+ language if nothing is specified.
2839+`subject`
2840+ ~ A string value or a list of such values.
2841+`description`
2842+ ~ A string value.
2843+`type`
2844+ ~ A string value.
2845+`format`
2846+ ~ A string value.
2847+`relation`
2848+ ~ A string value.
2849+`coverage`
2850+ ~ A string value.
2851+`rights`
2852+ ~ A string value.
2853+`cover-image`
2854+ ~ A string value (path to cover image).
2855+`stylesheet`
2856+ ~ A string value (path to CSS stylesheet).
2857+
2752Literate Haskell support
2858Literate Haskell support
2753========================
2859========================
2754
2860
2755If you append `+lhs` (or `+literate_haskell`) to an appropriate input or output
2861If you append `+lhs` (or `+literate_haskell`) to an appropriate input or output
2756−format (`markdown`, `mardkown_strict`, `rst`, or `latex` for input or output;
2862+format (`markdown`, `markdown_strict`, `rst`, or `latex` for input or output;
2757`beamer`, `html` or `html5` for output only), pandoc will treat the document as
2863`beamer`, `html` or `html5` for output only), pandoc will treat the document as
2758literate Haskell source. This means that
2864literate Haskell source. This means that
2759
2865
@@ -2860,4 +2966,5 @@ Jamie F. Olson.
2860[reveal.js]: http://lab.hakim.se/reveal-js/
2966[reveal.js]: http://lab.hakim.se/reveal-js/
2861[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
2967[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
2862[lua]: http://www.lua.org
2968[lua]: http://www.lua.org
2863−
2969+[marc relators]: http://www.loc.gov/marc/relators/relaterm.html
2970+[RFC5646]: http://tools.ietf.org/html/rfc5646
RELEASE-CHECKLIST+1−1
@@ -16,7 +16,7 @@ _ Upload to Google Code (googlecode-upload.sh)
16
16
17_ Go to Google code and deprecate the old versions
17_ Go to Google code and deprecate the old versions
18
18
19−- Add release on github
19+- Add release on github (and upload files)
20
20
21_ Upload to HackageDB
21_ Upload to HackageDB
22
22
changelog+317−1
@@ -1,3 +1,319 @@
1+pandoc (1.12.3.3)
2+
3+ * To changes to source; recompiled tarball with latest alex and
4+ happy, so they will work with GHC 7.8.
5+
6+pandoc (1.12.3.2)
7+
8+ * Bumped version bounds for blaze-html, blaze-markup.
9+
10+ * ImageSize: Avoid use of lookAhead, which is not in binary >= 0.6
11+ (#1124).
12+
13+ * Fixed mediawiki ordered list parsing (#1122).
14+
15+ * HTML reader: Fixed bug reading inline math with `$$` (#225).
16+
17+ * Added support for LaTeX style literate Haskell code blocks in rST
18+ (Merijn Verstraaten).
19+
20+pandoc (1.12.3.1)
21+
22+ * Relaxed version constraint on binary, allowing the use of binary 0.5.
23+
24+pandoc (1.12.3)
25+
26+ * The `--bibliography` option now sets the `biblio-files` variable.
27+ So, if you're using `--natbib` or `--biblatex`, you can just use
28+ `--bibliography=foo.bib` instead of `-V bibliofiles=foo`.
29+
30+ * Don't run pandoc-citeproc filter if `--bibliography` is
31+ used together with `--natbib` or `--biblatex` (Florian Eitel).
32+
33+ * Template changes:
34+
35+ + Updated beamer template to include booktabs.
36+ + Added `abstract` variable to LaTeX template.
37+ + Put `header-includes` after `title` in LaTeX template (#908).
38+ + Allow use of `\includegraphics[size]` in beamer.
39+ This just required porting a macro definition from the default
40+ LaTeX template to the default beamer template.
41+
42+ * `reference.docx`: Include `FootnoteText` style.
43+ Otherwise Word ignores the style, even when specified in the `pPr`.
44+ (#901)
45+
46+ * `reference.odt`: Tidied `styles.xml`.
47+
48+ * Relaxed version bounds for dependencies.
49+
50+ * Added `withSocketsDo` around http conduit code in `openURL`,
51+ so it works on Windows (#1080).
52+
53+ * Added `Cite` function to `sample.lua`.
54+
55+ * Markdown reader:
56+
57+ + Fixed regression in title blocks (#1089).
58+ If author field was empty, date was being ignored.
59+ + Allow backslash-newline hard line breaks in grid and
60+ multiline table cells.
61+ + Citation keys may now start with underscores, and may contain
62+ underscores adjacent to internal punctuation.
63+
64+ * LaTeX reader:
65+
66+ + Add support for `Verb` macro (jrnold) (#1090).
67+ + Support babel-style quoting: `` "`..."' ``.
68+
69+ * Properly handle script blocks in strict mode. (That is,
70+ `markdown-markdown_in_html_blocks`.) Previously a spurious
71+ `<p>` tag was being added (#1093).
72+
73+ * Docbook reader: Avoid failure if `tbody` contains no `tr` or `row`
74+ elements.
75+
76+ * LaTeX writer:
77+
78+ + Factored out function for table cell creation.
79+ + Better treatment of footnotes in tables.
80+ Notes now appear in the regular sequence, rather than in the
81+ table cell. (This was a regression in 1.10.)
82+
83+ * HTML reader: Parse name/content pairs from meta tags as metadata.
84+ Closes #1106.
85+
86+ * Moved `fixDisplayMath` from Docx writer to `Writer.Shared`.
87+
88+ * OpenDocument writer: Fixed `RawInline`, `RawBlock` so they don't escape.
89+
90+ * ODT writer: Use mathml for proper rendering of formulas.
91+ Note: LibreOffice's support for this seems a bit buggy. But
92+ it should be better than what we had before.
93+
94+ * RST writer: Ensure no blank line after def in definition list (#992).
95+
96+ * Markdown writer: Don't use tilde code blocks with braced attributes in
97+ `markdown_github` output. A consequence of this change is that the
98+ backtick form will be preferred in general if both are enabled. That
99+ is good, as it is much more widespread than the tilde form. (#1084)
100+
101+ * Docx writer: Fixed problem with some modified reference docx files.
102+ Include `word/_rels/settings.xml.rels` if it exists, as well as other
103+ `rels` files besides the ones pandoc generates explicitly.
104+
105+ * HTML writer:
106+
107+ + With `--toc`, headers no longer link to themselves (#1081).
108+ + Omit footnotes from TOC entries. Otherwise we get doubled
109+ footnotes when headers have notes!
110+
111+ * EPUB writer:
112+
113+ + Avoid duplicate notes when headings contain notes.
114+ This arose because the headings are copied into the metadata
115+ "title" field, and the note gets rendered twice. We strip the
116+ note now before putting the heading in "title".
117+ + Strip out footnotes from toc entries.
118+ + Fixed bug with `--epub-stylesheet`. Now the contents of
119+ `writerEpubStylesheet` (set by `--epub-stylesheet`)
120+ should again work, and take precedence over a stylesheet specified
121+ in the metadata.
122+
123+ * `Text.Pandoc.Pretty`: Added `nestle`. API change.
124+
125+ * `Text.Pandoc.MIME`: Added `wmf`, `emf`.
126+
127+ * `Text.Pandoc.Shared`: `fetchItem` now handles image URLs beginning
128+ with `//`.
129+
130+ * `Text.Pandoc.ImageSize`: Parse EXIF format JPEGs. Previously
131+ we could only get size information for JFIF format, which led
132+ to squished images in Word documents. Closes #976.
133+
134+ * Removed old `MarkdownTest_1.0.3` directory (#1104).
135+
136+pandoc (1.12.2.1)
137+
138+ * Markdown reader: Fixed regression in list parser, involving
139+ continuation lines containing raw HTML (or even verbatim raw HTML).
140+
141+pandoc (1.12.2)
142+
143+ * Metadata may now be included in YAML blocks in a markdown document.
144+ For example,
145+
146+ ---
147+ title:
148+ - type: main
149+ text: My Book
150+ - type: subtitle
151+ text: An investigation of metadata
152+ creator:
153+ - role: author
154+ text: John Smith
155+ - role: editor
156+ text: Sarah Jones
157+ identifier:
158+ - scheme: DOI
159+ text: doi:10.234234.234/33
160+ publisher: My Press
161+ rights: (c) 2007 John Smith, CC BY-NC
162+ cover-image: img/mypic.jpg
163+ ...
164+
165+ Metadata may still be provided using `--epub-metadata`; it will
166+ be merged with the metadata in YAML blocks.
167+
168+ * EPUB writer:
169+
170+ + `meta` tags are now used instead of `opf` attributes for EPUB3.
171+ + Insert "svg" property as needed in opf (EPUB 3).
172+ + Simplify `imageTypeOf` using `getMimeType`.
173+ + Add properties attribute to `cover-image` item for EPUB 3.
174+ + Don't include node for `cover.xhtml` if no cover!
175+ + Ensure that same identifier is used throughout (#1044).
176+ If an identifier is given in metadata, we use that; otherwise
177+ we generate a random uuid.
178+ + Add cover reference to guide element (EPUB 2) (Shaun Attfield).
179+ Fixes an issue with Calibre putting the cover at the end of the book
180+ if the spine has `linear="no"`. Apparently this is best practice
181+ for other converters as well:
182+ <http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6>.
183+ + Allow `stylesheet` in metadata. The value is a path to the stylesheet.
184+ + Allow partial dates: `YYYY`, `YYYY-MM`.
185+
186+ * Markdown writer: Fix rendering of tight sublists (#1050).
187+ Previously a spurious blank line was included after a tight sublist.
188+
189+ * ODT writer: Add `draw:name` attribute to `draw:frame` elements (#1069).
190+ This is reported to be necessary to avoid an error from recent
191+ versions of Libre Office when files contain more than one image
192+ Thanks to wmanley for reporting and diagnosing the problem.
193+
194+ * ConTeXt writer: Don't hardcode figure/table placement and numbering.
195+ Instead, let this be set in the template, using `\setupfloat`.
196+ Thanks to on4aa and Aditya Mahajan for the suggestion (#1067).
197+
198+ * Implemented CSL flipflopping spans in DOCX, LaTeX, and HTML writers.
199+
200+ * Fixed bug with markdown intraword emphasis. Closes #1066.
201+
202+ * Docbook writer: Hierarchicalize block content in metadata.
203+ Previously headers just disappeared from block-level metadata
204+ when it was used in templates. Now we apply the 'hierarchicalize'
205+ transformation. Note that a block headed by a level-2 header will
206+ turn into a `<sect1>` element.
207+
208+ * OpenDocument writer: Skip raw HTML (#1035).
209+ Previously it was erroneously included as verbatim text.
210+
211+ * HTML/EPUB writer, footnotes: Put `<sup>` tag inside `<a>` tags.
212+ This allows better control of formatting, since the `<a>`
213+ tags have a distinguishing class (#1049).
214+
215+ * Docx writer:
216+
217+ + Use mime type info returned by fetchItem.
218+ + Fixed core metadata (#1046).
219+ Don't create empty date nodes if no date given.
220+ Don't create multiple `dc:creator` nodes; instead separate by
221+ semicolons.
222+ + Fix URL for core-properties in `_rels/.rels` (#1046).
223+
224+ * Plain writer: don't print `<span>` tags.
225+
226+ * LaTeX writer:
227+
228+ + Fix definition lists with internal links in terms (#1032).
229+ This fix puts braces around a term that contains an internal
230+ link, to avoid problems with square brackets.
231+ + Properly escape pdftitle, pdfauthor (#1059).
232+ + Use booktabs package for tables (thanks to Jose Luis Duran).
233+
234+ * Updated beamer template. Now references should work properly
235+ (in a slide) when `--biblatex` or `--natbib` is used.
236+
237+ * LaTeX reader:
238+
239+ + Parse contents of curly quotes or matched `"` as quotes.
240+ + Support `\textnormal` as span with class `nodecor`.
241+ This is needed for pandoc-citeproc.
242+ + Improved citation parsing. This fixes a run-time error that occured
243+ with `\citet{}` (empty list of keys). It also ensures that empty keys
244+ don't get produced.
245+
246+ * MediaWiki reader: Add automatic header identifiers.
247+
248+ * HTML reader:
249+
250+ + Use pandoc `Div` and `Span` for raw `<div>`, `<span>` when
251+ `--parse-raw`.
252+ + Recognize `svg` tags as block level content (thanks to MinRK).
253+ + Parse LaTeX math if appropriate options are set.
254+
255+ * Markdown reader:
256+
257+ + Yaml block must start immediately after `---`. If there's a blank
258+ line after `---`, we interpreted it as a horizontal rule.
259+ + Correctly handle empty bullet list items.
260+ + Stop parsing "list lines" when we hit a block tag.
261+ This fixes exponential slowdown in certain input, e.g.
262+ a series of lists followed by `</div>`.
263+
264+ * Slides: Preserve `<div class="references">` in references slide.
265+
266+ * `Text.Pandoc.Writer.Shared`:
267+
268+ + Fixed bug in `tagWithAttrs`. A space was omitted before key-value
269+ attributes, leading to invalid HTML.
270+ + `normalizeDate`: Allow dates with year only (thanks to Shaun Attfield).
271+ + Fixed bug in `openURL` with `data:` URIs. Previously the base-64
272+ encoded bytestring was returned. We now decode it so it's a proper
273+ image!
274+
275+ * DocBook reader: Handle numerical attributes starting with decimal.
276+ Also use `safeRead` instead of `read`.
277+
278+ * `Text.Pandoc.Parsing`:
279+
280+ + Generalized type of `registerHeader`, using new type classes
281+ `HasReadeOptions`, `HasIdentifierList`, `HasHeaderMap`.
282+ These allow certain common functions to be reused
283+ even in parsers that use custom state (instead of `ParserState`),
284+ such as the MediaWiki reader.
285+ + Moved inlineMath, displayMath from Markdown reader to Parsing.
286+ Generalize their types and export them from Parsing. (API change.)
287+
288+ * `Text.Pandoc.Readers.TexMath`: Export `readTeXMath'`, which attends
289+ to display/inline. Deprecate `readTeXMath`, and use `readTeXMath'`
290+ in all the writers. Require `texmath >= 0.6.5.2`.
291+
292+ * `Text.Pandoc.MIME`:
293+
294+ + Add entry for `jfif`.
295+ + In looking up extensions, drop the encoding info.
296+ E.g. for 'image/jpg;base64' we should lookup 'image/jpg'.
297+
298+ * Templates: Changed how array variables are resolved. Previously if
299+ `foo` is an array (which might be because multiple values were set on
300+ the command line), `$foo$` would resolve to the concatenation of the
301+ elements of foo. This is rarely useful behavior. It has been changed
302+ so that the first value is rendered. Of course, you can still iterate
303+ over the values using `$for(foo)$`. This has the result that you can
304+ override earlier settings using `-V` by putting new values later on the
305+ command line, which is useful for many purposes.
306+
307+ * `Text.Pandoc`: Don't default to `pandocExtensions` for all writers.
308+
309+ * Allow "epub2" as synonym for "epub", "html4" for "html".
310+
311+ * Don't look for slidy files in data files with `--self-contained`.
312+
313+ * Allow `https:` command line arguments to be downloaded.
314+
315+ * Fixed `make_osx_package.sh` so data files embedded in `pandoc-citeproc`.
316+
1pandoc (1.12.1)
317pandoc (1.12.1)
2
318
3 * `Text.Pandoc.Definition`: Changed default JSON serialization format.
319 * `Text.Pandoc.Definition`: Changed default JSON serialization format.
@@ -3540,7 +3856,7 @@ pandoc (1.5.1.1)
3540
3856
3541 [ John MacFarlane ]
3857 [ John MacFarlane ]
3542
3858
3543− * Fixed uniqueIdent in Shared so that header identifiers work as
3859+ * Fixed uniqueIdent in Shared so that header identifiers work as
3544 advertized in the README and are are valid XHTML names.
3860 advertized in the README and are are valid XHTML names.
3545
3861
3546pandoc (1.5.1)
3862pandoc (1.5.1)
data/reference.docx

Binary file not shown.

data/reference.odt

Binary file not shown.

data/sample.lua+4
@@ -181,6 +181,10 @@ function Span(s, attr)
181 return "<span" .. attributes(attr) .. ">" .. s .. "</span>"
181 return "<span" .. attributes(attr) .. ">" .. s .. "</span>"
182end
182end
183
183
184+function Cite(s)
185+ return "<span class=\"cite\">" .. s .. "</span>"
186+end
187+
184function Plain(s)
188function Plain(s)
185 return s
189 return s
186end
190end
data/templates+1−1

Submodule changed.

github-upload.shnew file+18
@@ -0,0 +1,18 @@
1+#!/bin/bash
2+
3+VERSION=$1
4+FULLNAME=pandoc-$VERSION
5+read -s -p "Token (https://github.com/settings/applications): " TOKEN
6+
7+curl -H "Authorization: token $TOKEN" \
8+ -H "Accept: application/vnd.github.manifold-preview" \
9+ -H "Content-Type: application/x-apple-diskimage" \
10+ --data-binary @$FULLNAME.pkg.zip \
11+ "https://uploads.github.com/repos/jgm/pandoc/releases/$VERSION/assets?name=$FULLNAME.pkg.zip"
12+
13+curl -H "Authorization: token $TOKEN" \
14+ -H "Accept: application/vnd.github.manifold-preview" \
15+ -H "Content-Type: application/x-msi" \
16+ --data-binary @$FULLNAME.msi \
17+ "https://uploads.github.com/repos/jgm/pandoc/releases/$VERSION/assets?name=$FULLNAME.msi"
18+
googlecode-upload.sh+1−1
@@ -2,4 +2,4 @@
2VERSION=$1
2VERSION=$1
3googlecode_upload.py -s "Source tarball" -p pandoc -u fiddlosopher --labels=Featured,Type-Source,OpSys-All dist/pandoc-$VERSION.tar.gz
3googlecode_upload.py -s "Source tarball" -p pandoc -u fiddlosopher --labels=Featured,Type-Source,OpSys-All dist/pandoc-$VERSION.tar.gz
4googlecode_upload.py -s "Windows installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-Windows pandoc-$VERSION.msi
4googlecode_upload.py -s "Windows installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-Windows pandoc-$VERSION.msi
5−googlecode_upload.py -s "Mac OS X installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-OSX pandoc-$VERSION.dmg
5+googlecode_upload.py -s "Mac OS X installer" -p pandoc -u fiddlosopher --labels=Featured,Type-Installer,OpSys-OSX pandoc-$VERSION.pkg.zip
make_osx_package.sh+16−9
@@ -1,4 +1,4 @@
1−#!/bin/sh -e
1+#!/bin/bash -e
2
2
3DIST=`pwd`/osx_package
3DIST=`pwd`/osx_package
4SANDBOX=`pwd`/.cabal-sandbox
4SANDBOX=`pwd`/.cabal-sandbox
@@ -8,10 +8,13 @@ ROOT=$DIST/pandoc
8DEST=$ROOT/usr/local
8DEST=$ROOT/usr/local
9SCRIPTS=osx-resources
9SCRIPTS=osx-resources
10BASE=pandoc-$VERSION
10BASE=pandoc-$VERSION
11−ME=jgm
11+ME=$(whoami)
12CODESIGNID="Developer ID Application: John Macfarlane"
12CODESIGNID="Developer ID Application: John Macfarlane"
13PACKAGEMAKER=/Applications/PackageMaker.app/Contents/MacOS/PackageMaker
13PACKAGEMAKER=/Applications/PackageMaker.app/Contents/MacOS/PackageMaker
14−EXES="pandoc pandoc-citeproc biblio2yaml"
14+EXES="pandoc pandoc-citeproc"
15+
16+read -s -p "sudo password: " PASSWORD
17+echo $PASSWORD | sudo -S echo "Password valid, continuing."
15
18
16echo Removing old files...
19echo Removing old files...
17rm -rf $DIST
20rm -rf $DIST
@@ -50,6 +53,8 @@ codesign --force --sign "$CODESIGNID" $DEST/bin/pandoc
50spctl --assess --type execute $DEST/bin/pandoc
53spctl --assess --type execute $DEST/bin/pandoc
51
54
52echo Creating OSX package...
55echo Creating OSX package...
56+# remove old package first
57+echo $PASSWORD | sudo -S rm -rf $BASE.pkg $BASE.dmg
53
58
54sudo $PACKAGEMAKER \
59sudo $PACKAGEMAKER \
55 --root $ROOT \
60 --root $ROOT \
@@ -67,11 +72,13 @@ sudo codesign --force --sign "$CODESIGNID" $BASE.pkg
67# make sure it's valid...
72# make sure it's valid...
68spctl --assess --type install $BASE.pkg
73spctl --assess --type install $BASE.pkg
69
74
70−echo Creating disk image...
75+echo Creating zip...
76+zip -9 -r $BASE.pkg.zip $BASE.pkg
71
77
78+# echo Creating disk image...
72−sudo hdiutil create "$BASE.dmg" \
79+# sudo hdiutil create "$BASE.dmg" \
73− -format UDZO -ov \
80+# -format UDZO -ov \
74− -volname "pandoc $VERSION" \
81+# -volname "pandoc $VERSION" \
75− -srcfolder $BASE.pkg
82+# -srcfolder $BASE.pkg
76−sudo hdiutil internet-enable "$BASE.dmg"
83+# sudo hdiutil internet-enable "$BASE.dmg"
77
84
pandoc.cabal+21−21
@@ -1,5 +1,5 @@
1Name: pandoc
1Name: pandoc
2−Version: 1.12.2
2+Version: 1.12.3.3
3Cabal-Version: >= 1.10
3Cabal-Version: >= 1.10
4Build-Type: Custom
4Build-Type: Custom
5License: GPL
5License: GPL
@@ -202,40 +202,41 @@ Library
202 syb >= 0.1 && < 0.5,
202 syb >= 0.1 && < 0.5,
203 containers >= 0.1 && < 0.6,
203 containers >= 0.1 && < 0.6,
204 unordered-containers >= 0.2 && < 0.3,
204 unordered-containers >= 0.2 && < 0.3,
205− array >= 0.3 && < 0.5,
205+ array >= 0.3 && < 0.6,
206 parsec >= 3.1 && < 3.2,
206 parsec >= 3.1 && < 3.2,
207 mtl >= 1.1 && < 2.2,
207 mtl >= 1.1 && < 2.2,
208 network >= 2 && < 2.5,
208 network >= 2 && < 2.5,
209 filepath >= 1.1 && < 1.4,
209 filepath >= 1.1 && < 1.4,
210− process >= 1 && < 1.2,
210+ process >= 1 && < 1.3,
211 directory >= 1 && < 1.3,
211 directory >= 1 && < 1.3,
212 bytestring >= 0.9 && < 0.11,
212 bytestring >= 0.9 && < 0.11,
213− text >= 0.11 && < 0.12,
213+ text >= 0.11 && < 1.2,
214− zip-archive >= 0.1.3.3 && < 0.2,
214+ zip-archive >= 0.1.3.3 && < 0.3,
215 old-locale >= 1 && < 1.1,
215 old-locale >= 1 && < 1.1,
216 time >= 1.2 && < 1.5,
216 time >= 1.2 && < 1.5,
217 HTTP >= 4000.0.5 && < 4000.3,
217 HTTP >= 4000.0.5 && < 4000.3,
218− texmath >= 0.6.5.2 && < 0.7,
218+ texmath >= 0.6.6 && < 0.7,
219 xml >= 1.3.12 && < 1.4,
219 xml >= 1.3.12 && < 1.4,
220 random >= 1 && < 1.1,
220 random >= 1 && < 1.1,
221 extensible-exceptions >= 0.1 && < 0.2,
221 extensible-exceptions >= 0.1 && < 0.2,
222 pandoc-types >= 1.12.3 && < 1.13,
222 pandoc-types >= 1.12.3 && < 1.13,
223− aeson >= 0.6 && < 0.7,
223+ aeson >= 0.6 && < 0.8,
224 tagsoup >= 0.12.5 && < 0.14,
224 tagsoup >= 0.12.5 && < 0.14,
225 base64-bytestring >= 0.1 && < 1.1,
225 base64-bytestring >= 0.1 && < 1.1,
226 zlib >= 0.5 && < 0.6,
226 zlib >= 0.5 && < 0.6,
227− highlighting-kate >= 0.5.5 && < 0.6,
227+ highlighting-kate >= 0.5.6 && < 0.6,
228 data-default >= 0.4 && < 0.6,
228 data-default >= 0.4 && < 0.6,
229− temporary >= 1.1 && < 1.2,
229+ temporary >= 1.1 && < 1.3,
230− blaze-html >= 0.5 && < 0.7,
230+ blaze-html >= 0.5 && < 0.8,
231− blaze-markup >= 0.5.1 && < 0.6,
231+ blaze-markup >= 0.5.1 && < 0.7,
232− attoparsec >= 0.10 && < 0.11,
232+ attoparsec >= 0.10 && < 0.12,
233 yaml >= 0.8.3 && < 0.9,
233 yaml >= 0.8.3 && < 0.9,
234 vector >= 0.10 && < 0.11,
234 vector >= 0.10 && < 0.11,
235− hslua >= 0.3 && < 0.4
235+ hslua >= 0.3 && < 0.4,
236+ binary >= 0.5 && < 0.8
236 Build-Tools: alex, happy
237 Build-Tools: alex, happy
237 if flag(http-conduit)
238 if flag(http-conduit)
238− Build-Depends: http-conduit >= 1.9 && < 1.10,
239+ Build-Depends: http-conduit >= 1.9 && < 2.1,
239 http-types >= 0.8 && < 0.9
240 http-types >= 0.8 && < 0.9
240 cpp-options: -DHTTP_CONDUIT
241 cpp-options: -DHTTP_CONDUIT
241 if flag(embed_data_files)
242 if flag(embed_data_files)
@@ -316,12 +317,11 @@ Executable pandoc
316 directory >= 1 && < 1.3,
317 directory >= 1 && < 1.3,
317 filepath >= 1.1 && < 1.4,
318 filepath >= 1.1 && < 1.4,
318 network >= 2 && < 2.5,
319 network >= 2 && < 2.5,
319− text >= 0.11 && < 0.12,
320+ text >= 0.11 && < 1.2,
320 bytestring >= 0.9 && < 0.11,
321 bytestring >= 0.9 && < 0.11,
321 extensible-exceptions >= 0.1 && < 0.2,
322 extensible-exceptions >= 0.1 && < 0.2,
322− highlighting-kate >= 0.5.5 && < 0.6,
323+ highlighting-kate >= 0.5.6 && < 0.6,
323− aeson >= 0.6 && < 0.7,
324+ aeson >= 0.6 && < 0.8,
324− text >= 0.11 && < 0.12,
325 yaml >= 0.8.3 && < 0.9,
325 yaml >= 0.8.3 && < 0.9,
326 containers >= 0.1 && < 0.6,
326 containers >= 0.1 && < 0.6,
327 HTTP >= 4000.0.5 && < 4000.3
327 HTTP >= 4000.0.5 && < 4000.3
@@ -359,11 +359,11 @@ Test-Suite test-pandoc
359 pandoc,
359 pandoc,
360 pandoc-types >= 1.12.3 && < 1.13,
360 pandoc-types >= 1.12.3 && < 1.13,
361 bytestring >= 0.9 && < 0.11,
361 bytestring >= 0.9 && < 0.11,
362− text >= 0.11 && < 0.12,
362+ text >= 0.11 && < 1.2,
363 directory >= 1 && < 1.3,
363 directory >= 1 && < 1.3,
364 filepath >= 1.1 && < 1.4,
364 filepath >= 1.1 && < 1.4,
365− process >= 1 && < 1.2,
365+ process >= 1 && < 1.3,
366− highlighting-kate >= 0.5.5 && < 0.6,
366+ highlighting-kate >= 0.5.6 && < 0.6,
367 Diff >= 0.2 && < 0.4,
367 Diff >= 0.2 && < 0.4,
368 test-framework >= 0.3 && < 0.9,
368 test-framework >= 0.3 && < 0.9,
369 test-framework-hunit >= 0.2 && < 0.4,
369 test-framework-hunit >= 0.2 && < 0.4,
pandoc.hs+21−12
@@ -35,7 +35,8 @@ import Text.Pandoc.Builder (setMeta)
35import Text.Pandoc.PDF (makePDF)
35import Text.Pandoc.PDF (makePDF)
36import Text.Pandoc.Readers.LaTeX (handleIncludes)
36import Text.Pandoc.Readers.LaTeX (handleIncludes)
37import Text.Pandoc.Shared ( tabFilter, readDataFileUTF8, readDataFile,
37import Text.Pandoc.Shared ( tabFilter, readDataFileUTF8, readDataFile,
38− safeRead, headerShift, normalize, err, warn )
38+ safeRead, headerShift, normalize, err, warn,
39+ openURL )
39import Text.Pandoc.XML ( toEntities )
40import Text.Pandoc.XML ( toEntities )
40import Text.Pandoc.SelfContained ( makeSelfContained )
41import Text.Pandoc.SelfContained ( makeSelfContained )
41import Text.Pandoc.Process (pipeProcess)
42import Text.Pandoc.Process (pipeProcess)
@@ -55,7 +56,6 @@ import Control.Exception.Extensible ( throwIO )
55import qualified Text.Pandoc.UTF8 as UTF8
56import qualified Text.Pandoc.UTF8 as UTF8
56import Control.Monad (when, unless, liftM)
57import Control.Monad (when, unless, liftM)
57import Data.Foldable (foldrM)
58import Data.Foldable (foldrM)
58−import Network.HTTP (simpleHTTP, mkRequest, getResponseBody, RequestMethod(..))
59import Network.URI (parseURI, isURI, URI(..))
59import Network.URI (parseURI, isURI, URI(..))
60import qualified Data.ByteString.Lazy as B
60import qualified Data.ByteString.Lazy as B
61import qualified Data.ByteString as BS
61import qualified Data.ByteString as BS
@@ -656,7 +656,7 @@ options =
656 (ReqArg
656 (ReqArg
657 (\arg opt -> do
657 (\arg opt -> do
658 let b = takeBaseName arg
658 let b = takeBaseName arg
659− if (b == "pdflatex" || b == "lualatex" || b == "xelatex")
659+ if b `elem` ["pdflatex", "lualatex", "xelatex"]
660 then return opt { optLaTeXEngine = arg }
660 then return opt { optLaTeXEngine = arg }
661 else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.")
661 else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.")
662 "PROGRAM")
662 "PROGRAM")
@@ -667,6 +667,9 @@ options =
667 (\arg opt -> return opt{ optMetadata = addMetadata
667 (\arg opt -> return opt{ optMetadata = addMetadata
668 "bibliography" (readMetaValue arg)
668 "bibliography" (readMetaValue arg)
669 $ optMetadata opt
669 $ optMetadata opt
670+ , optVariables =
671+ ("biblio-files", dropExtension arg) :
672+ optVariables opt
670 })
673 })
671 "FILE")
674 "FILE")
672 ""
675 ""
@@ -958,7 +961,9 @@ main = do
958
961
959 -- --bibliography implies -F pandoc-citeproc for backwards compatibility:
962 -- --bibliography implies -F pandoc-citeproc for backwards compatibility:
960 let filters' = case M.lookup "bibliography" metadata of
963 let filters' = case M.lookup "bibliography" metadata of
964+ Just _ | optCiteMethod opts /= Natbib &&
965+ optCiteMethod opts /= Biblatex &&
961− Just _ | all (\f -> takeBaseName f /= "pandoc-citeproc")
966+ all (\f -> takeBaseName f /= "pandoc-citeproc")
962 filters -> "pandoc-citeproc" : filters
967 filters -> "pandoc-citeproc" : filters
963 _ -> filters
968 _ -> filters
964 let plugins = map externalFilter filters'
969 let plugins = map externalFilter filters'
@@ -982,7 +987,10 @@ main = do
982
987
983 let writerName' = if null writerName
988 let writerName' = if null writerName
984 then defaultWriterName outputFile
989 then defaultWriterName outputFile
985− else writerName
990+ else case writerName of
991+ "epub2" -> "epub"
992+ "html4" -> "html"
993+ x -> x
986
994
987 let pdfOutput = map toLower (takeExtension outputFile) == ".pdf"
995 let pdfOutput = map toLower (takeExtension outputFile) == ".pdf"
988
996
@@ -1031,12 +1039,10 @@ main = do
1031
1039
1032 variables' <- case mathMethod of
1040 variables' <- case mathMethod of
1033 LaTeXMathML Nothing -> do
1041 LaTeXMathML Nothing -> do
1034− s <- readDataFileUTF8 datadir
1042+ s <- readDataFileUTF8 datadir "LaTeXMathML.js"
1035− ("LaTeXMathML.js")
1036 return $ ("mathml-script", s) : variables
1043 return $ ("mathml-script", s) : variables
1037 MathML Nothing -> do
1044 MathML Nothing -> do
1038− s <- readDataFileUTF8 datadir
1045+ s <- readDataFileUTF8 datadir "MathMLinHTML.js"
1039− ("MathMLinHTML.js")
1040 return $ ("mathml-script", s) : variables
1046 return $ ("mathml-script", s) : variables
1041 _ -> return variables
1047 _ -> return variables
1042
1048
@@ -1117,10 +1123,13 @@ main = do
1117 readSource "-" = UTF8.getContents
1123 readSource "-" = UTF8.getContents
1118 readSource src = case parseURI src of
1124 readSource src = case parseURI src of
1119 Just u | uriScheme u `elem` ["http:","https:"] ->
1125 Just u | uriScheme u `elem` ["http:","https:"] ->
1120− readURI u
1126+ readURI src
1121 _ -> UTF8.readFile src
1127 _ -> UTF8.readFile src
1122− readURI uri = simpleHTTP (mkRequest GET uri) >>= getResponseBody >>=
1128+ readURI src = do
1123− return . UTF8.toStringLazy -- treat all as UTF8
1129+ res <- openURL src
1130+ case res of
1131+ Left e -> throwIO e
1132+ Right (bs,_) -> return $ UTF8.toString bs
1124
1133
1125 let convertTabs = tabFilter (if preserveTabs then 0 else tabStop)
1134 let convertTabs = tabFilter (if preserveTabs then 0 else tabStop)
1126
1135
src/Text/Pandoc.hs+4−1
@@ -267,7 +267,10 @@ getDefaultExtensions "markdown_strict" = strictExtensions
267getDefaultExtensions "markdown_phpextra" = phpMarkdownExtraExtensions
267getDefaultExtensions "markdown_phpextra" = phpMarkdownExtraExtensions
268getDefaultExtensions "markdown_mmd" = multimarkdownExtensions
268getDefaultExtensions "markdown_mmd" = multimarkdownExtensions
269getDefaultExtensions "markdown_github" = githubMarkdownExtensions
269getDefaultExtensions "markdown_github" = githubMarkdownExtensions
270−getDefaultExtensions _ = pandocExtensions
270+getDefaultExtensions "markdown" = pandocExtensions
271+getDefaultExtensions "plain" = pandocExtensions
272+getDefaultExtensions "textile" = Set.fromList [Ext_auto_identifiers, Ext_raw_tex]
273+getDefaultExtensions _ = Set.fromList [Ext_auto_identifiers]
271
274
272-- | Retrieve reader based on formatSpec (format+extensions).
275-- | Retrieve reader based on formatSpec (format+extensions).
273getReader :: String -> Either String (ReaderOptions -> String -> IO Pandoc)
276getReader :: String -> Either String (ReaderOptions -> String -> IO Pandoc)
src/Text/Pandoc/ImageSize.hs+227−6
@@ -32,9 +32,14 @@ module Text.Pandoc.ImageSize ( ImageType(..), imageType, imageSize,
32 sizeInPixels, sizeInPoints ) where
32 sizeInPixels, sizeInPoints ) where
33import Data.ByteString (ByteString, unpack)
33import Data.ByteString (ByteString, unpack)
34import qualified Data.ByteString.Char8 as B
34import qualified Data.ByteString.Char8 as B
35+import qualified Data.ByteString.Lazy as BL
36+import Control.Applicative
35import Control.Monad
37import Control.Monad
36import Data.Bits
38import Data.Bits
39+import Data.Binary
40+import Data.Binary.Get
37import Text.Pandoc.Shared (safeRead)
41import Text.Pandoc.Shared (safeRead)
42+import qualified Data.Map as M
38
43
39-- quick and dirty functions to get image sizes
44-- quick and dirty functions to get image sizes
40-- algorithms borrowed from wwwis.pl
45-- algorithms borrowed from wwwis.pl
@@ -53,7 +58,8 @@ imageType :: ByteString -> Maybe ImageType
53imageType img = case B.take 4 img of
58imageType img = case B.take 4 img of
54 "\x89\x50\x4e\x47" -> return Png
59 "\x89\x50\x4e\x47" -> return Png
55 "\x47\x49\x46\x38" -> return Gif
60 "\x47\x49\x46\x38" -> return Gif
56− "\xff\xd8\xff\xe0" -> return Jpeg
61+ "\xff\xd8\xff\xe0" -> return Jpeg -- JFIF
62+ "\xff\xd8\xff\xe1" -> return Jpeg -- Exif
57 "%PDF" -> return Pdf
63 "%PDF" -> return Pdf
58 "%!PS"
64 "%!PS"
59 | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF"
65 | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF"
@@ -139,8 +145,14 @@ gifSize img = do
139jpegSize :: ByteString -> Maybe ImageSize
145jpegSize :: ByteString -> Maybe ImageSize
140jpegSize img = do
146jpegSize img = do
141 let (hdr, rest) = B.splitAt 4 img
147 let (hdr, rest) = B.splitAt 4 img
142− guard $ hdr == "\xff\xd8\xff\xe0"
143 guard $ B.length rest >= 14
148 guard $ B.length rest >= 14
149+ case hdr of
150+ "\xff\xd8\xff\xe0" -> jfifSize rest
151+ "\xff\xd8\xff\xe1" -> exifSize $ B.takeWhile (/= '\xff') rest
152+ _ -> mzero
153+
154+jfifSize :: ByteString -> Maybe ImageSize
155+jfifSize rest = do
144 let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral
156 let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral
145 $ unpack $ B.take 5 $ B.drop 9 $ rest
157 $ unpack $ B.take 5 $ B.drop 9 $ rest
146 let factor = case dpiDensity of
158 let factor = case dpiDensity of
@@ -149,11 +161,11 @@ jpegSize img = do
149 _ -> const 72
161 _ -> const 72
150 let dpix = factor (shift dpix1 8 + dpix2)
162 let dpix = factor (shift dpix1 8 + dpix2)
151 let dpiy = factor (shift dpiy1 8 + dpiy2)
163 let dpiy = factor (shift dpiy1 8 + dpiy2)
152− (w,h) <- findJpegSize rest
164+ (w,h) <- findJfifSize rest
153 return $ ImageSize { pxX = w, pxY = h, dpiX = dpix, dpiY = dpiy }
165 return $ ImageSize { pxX = w, pxY = h, dpiX = dpix, dpiY = dpiy }
154
166
155−findJpegSize :: ByteString -> Maybe (Integer,Integer)
167+findJfifSize :: ByteString -> Maybe (Integer,Integer)
156−findJpegSize bs = do
168+findJfifSize bs = do
157 let bs' = B.dropWhile (=='\xff') $ B.dropWhile (/='\xff') bs
169 let bs' = B.dropWhile (=='\xff') $ B.dropWhile (/='\xff') bs
158 case B.uncons bs' of
170 case B.uncons bs' of
159 Just (c,bs'') | c >= '\xc0' && c <= '\xc3' -> do
171 Just (c,bs'') | c >= '\xc0' && c <= '\xc3' -> do
@@ -165,8 +177,217 @@ findJpegSize bs = do
165 [c1,c2] -> do
177 [c1,c2] -> do
166 let len = shift c1 8 + c2
178 let len = shift c1 8 + c2
167 -- skip variables
179 -- skip variables
168− findJpegSize $ B.drop len bs''
180+ findJfifSize $ B.drop len bs''
169 _ -> fail "JPEG parse error"
181 _ -> fail "JPEG parse error"
170 Nothing -> fail "Did not find length record"
182 Nothing -> fail "Did not find length record"
171
183
184+exifSize :: ByteString -> Maybe ImageSize
185+exifSize bs = runGet (Just <$> exifHeader bl) bl
186+ where bl = BL.fromChunks [bs]
187+-- NOTE: It would be nicer to do
188+-- runGet ((Just <$> exifHeader) <|> return Nothing)
189+-- which would prevent pandoc from raising an error when an exif header can't
190+-- be parsed. But we only get an Alternative instance for Get in binary 0.6,
191+-- and binary 0.5 ships with ghc 7.6.
192+
193+exifHeader :: BL.ByteString -> Get ImageSize
194+exifHeader hdr = do
195+ _app1DataSize <- getWord16be
196+ exifHdr <- getWord32be
197+ unless (exifHdr == 0x45786966) $ fail "Did not find exif header"
198+ zeros <- getWord16be
199+ unless (zeros == 0) $ fail "Expected zeros after exif header"
200+ -- beginning of tiff header -- we read whole thing to use
201+ -- in getting data from offsets:
202+ let tiffHeader = BL.drop 8 hdr
203+ byteAlign <- getWord16be
204+ let bigEndian = byteAlign == 0x4d4d
205+ let (getWord16, getWord32, getWord64) =
206+ if bigEndian
207+ then (getWord16be, getWord32be, getWord64be)
208+ else (getWord16le, getWord32le, getWord64le)
209+ let getRational = do
210+ num <- getWord32
211+ den <- getWord32
212+ return $ fromIntegral num / fromIntegral den
213+ tagmark <- getWord16
214+ unless (tagmark == 0x002a) $ fail "Failed alignment sanity check"
215+ ifdOffset <- getWord32
216+ skip (fromIntegral ifdOffset - 8) -- skip to IDF
217+ numentries <- getWord16
218+ let ifdEntry = do
219+ tag <- getWord16 >>= \t ->
220+ maybe (fail $ "Unknown tag type " ++ show t) return
221+ (M.lookup t tagTypeTable)
222+ dataFormat <- getWord16
223+ numComponents <- getWord32
224+ (fmt, bytesPerComponent) <-
225+ case dataFormat of
226+ 1 -> return (UnsignedByte . runGet getWord8, 1)
227+ 2 -> return (AsciiString, 1)
228+ 3 -> return (UnsignedShort . runGet getWord16, 2)
229+ 4 -> return (UnsignedLong . runGet getWord32, 4)
230+ 5 -> return (UnsignedRational . runGet getRational, 8)
231+ 6 -> return (SignedByte . runGet getWord8, 1)
232+ 7 -> return (Undefined . runGet getWord8, 1)
233+ 8 -> return (SignedShort . runGet getWord16, 2)
234+ 9 -> return (SignedLong . runGet getWord32, 4)
235+ 10 -> return (SignedRational . runGet getRational, 8)
236+ 11 -> return (SingleFloat . runGet getWord32 {- TODO -}, 4)
237+ 12 -> return (DoubleFloat . runGet getWord64 {- TODO -}, 8)
238+ _ -> fail $ "Unknown data format " ++ show dataFormat
239+ let totalBytes = fromIntegral $ numComponents * bytesPerComponent
240+ payload <- if totalBytes <= 4 -- data is right here
241+ then fmt <$>
242+ (getLazyByteString (fromIntegral totalBytes) <*
243+ skip (4 - totalBytes))
244+ else do -- get data from offset
245+ offs <- getWord32
246+ return $ fmt $ BL.take (fromIntegral totalBytes) $
247+ BL.drop (fromIntegral offs) tiffHeader
248+ return (tag, payload)
249+ entries <- sequence $ replicate (fromIntegral numentries) ifdEntry
250+ subentries <- case lookup ExifOffset entries of
251+ Just (UnsignedLong offset) -> do
252+ pos <- bytesRead
253+ skip (fromIntegral offset - (fromIntegral pos - 8))
254+ numsubentries <- getWord16
255+ sequence $
256+ replicate (fromIntegral numsubentries) ifdEntry
257+ _ -> return []
258+ let allentries = entries ++ subentries
259+ (width, height) <- case (lookup ExifImageWidth allentries,
260+ lookup ExifImageHeight allentries) of
261+ (Just (UnsignedLong w), Just (UnsignedLong h)) ->
262+ return (fromIntegral w, fromIntegral h)
263+ _ -> fail "Could not determine image width, height"
264+ let resfactor = case lookup ResolutionUnit allentries of
265+ Just (UnsignedShort 1) -> (100 / 254)
266+ _ -> 1
267+ let xres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor)
268+ $ lookup XResolution allentries
269+ let yres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor)
270+ $ lookup YResolution allentries
271+ return $ ImageSize{
272+ pxX = width
273+ , pxY = height
274+ , dpiX = xres
275+ , dpiY = yres }
276+
277+data DataFormat = UnsignedByte Word8
278+ | AsciiString BL.ByteString
279+ | UnsignedShort Word16
280+ | UnsignedLong Word32
281+ | UnsignedRational Rational
282+ | SignedByte Word8
283+ | Undefined Word8
284+ | SignedShort Word16
285+ | SignedLong Word32
286+ | SignedRational Rational
287+ | SingleFloat Word32
288+ | DoubleFloat Word64
289+ deriving (Show)
290+
291+data TagType = ImageDescription
292+ | Make
293+ | Model
294+ | Orientation
295+ | XResolution
296+ | YResolution
297+ | ResolutionUnit
298+ | Software
299+ | DateTime
300+ | WhitePoint
301+ | PrimaryChromaticities
302+ | YCbCrCoefficients
303+ | YCbCrPositioning
304+ | ReferenceBlackWhite
305+ | Copyright
306+ | ExifOffset
307+ | ExposureTime
308+ | FNumber
309+ | ExposureProgram
310+ | ISOSpeedRatings
311+ | ExifVersion
312+ | DateTimeOriginal
313+ | DateTimeDigitized
314+ | ComponentConfiguration
315+ | CompressedBitsPerPixel
316+ | ShutterSpeedValue
317+ | ApertureValue
318+ | BrightnessValue
319+ | ExposureBiasValue
320+ | MaxApertureValue
321+ | SubjectDistance
322+ | MeteringMode
323+ | LightSource
324+ | Flash
325+ | FocalLength
326+ | MakerNote
327+ | UserComment
328+ | FlashPixVersion
329+ | ColorSpace
330+ | ExifImageWidth
331+ | ExifImageHeight
332+ | RelatedSoundFile
333+ | ExifInteroperabilityOffset
334+ | FocalPlaneXResolution
335+ | FocalPlaneYResolution
336+ | FocalPlaneResolutionUnit
337+ | SensingMethod
338+ | FileSource
339+ | SceneType
340+ deriving (Show, Eq, Ord)
172
341
342+tagTypeTable :: M.Map Word16 TagType
343+tagTypeTable = M.fromList
344+ [ (0x010e, ImageDescription)
345+ , (0x010f, Make)
346+ , (0x0110, Model)
347+ , (0x0112, Orientation)
348+ , (0x011a, XResolution)
349+ , (0x011b, YResolution)
350+ , (0x0128, ResolutionUnit)
351+ , (0x0131, Software)
352+ , (0x0132, DateTime)
353+ , (0x013e, WhitePoint)
354+ , (0x013f, PrimaryChromaticities)
355+ , (0x0211, YCbCrCoefficients)
356+ , (0x0213, YCbCrPositioning)
357+ , (0x0214, ReferenceBlackWhite)
358+ , (0x8298, Copyright)
359+ , (0x8769, ExifOffset)
360+ , (0x829a, ExposureTime)
361+ , (0x829d, FNumber)
362+ , (0x8822, ExposureProgram)
363+ , (0x8827, ISOSpeedRatings)
364+ , (0x9000, ExifVersion)
365+ , (0x9003, DateTimeOriginal)
366+ , (0x9004, DateTimeDigitized)
367+ , (0x9101, ComponentConfiguration)
368+ , (0x9102, CompressedBitsPerPixel)
369+ , (0x9201, ShutterSpeedValue)
370+ , (0x9202, ApertureValue)
371+ , (0x9203, BrightnessValue)
372+ , (0x9204, ExposureBiasValue)
373+ , (0x9205, MaxApertureValue)
374+ , (0x9206, SubjectDistance)
375+ , (0x9207, MeteringMode)
376+ , (0x9208, LightSource)
377+ , (0x9209, Flash)
378+ , (0x920a, FocalLength)
379+ , (0x927c, MakerNote)
380+ , (0x9286, UserComment)
381+ , (0xa000, FlashPixVersion)
382+ , (0xa001, ColorSpace)
383+ , (0xa002, ExifImageWidth)
384+ , (0xa003, ExifImageHeight)
385+ , (0xa004, RelatedSoundFile)
386+ , (0xa005, ExifInteroperabilityOffset)
387+ , (0xa20e, FocalPlaneXResolution)
388+ , (0xa20f, FocalPlaneYResolution)
389+ , (0xa210, FocalPlaneResolutionUnit)
390+ , (0xa217, SensingMethod)
391+ , (0xa300, FileSource)
392+ , (0xa301, SceneType)
393+ ]
src/Text/Pandoc/MIME.hs+5−1
@@ -40,7 +40,8 @@ getMimeType f = M.lookup (map toLower $ drop 1 $ takeExtension f) mimeTypes
40 where mimeTypes = M.fromList mimeTypesList
40 where mimeTypes = M.fromList mimeTypesList
41
41
42extensionFromMimeType :: String -> Maybe String
42extensionFromMimeType :: String -> Maybe String
43−extensionFromMimeType mimetype = M.lookup mimetype reverseMimeTypes
43+extensionFromMimeType mimetype = M.lookup (takeWhile (/=';') mimetype) reverseMimeTypes
44+ -- note: we just look up the basic mime type, dropping the content-encoding etc.
44 where reverseMimeTypes = M.fromList $ map (\(k,v) -> (v,k)) mimeTypesList
45 where reverseMimeTypes = M.fromList $ map (\(k,v) -> (v,k)) mimeTypesList
45
46
46mimeTypesList :: [(String, String)]
47mimeTypesList :: [(String, String)]
@@ -146,6 +147,7 @@ mimeTypesList = -- List borrowed from happstack-server.
146 ,("dxr","application/x-director")
147 ,("dxr","application/x-director")
147 ,("emb","chemical/x-embl-dl-nucleotide")
148 ,("emb","chemical/x-embl-dl-nucleotide")
148 ,("embl","chemical/x-embl-dl-nucleotide")
149 ,("embl","chemical/x-embl-dl-nucleotide")
150+ ,("emf","image/x-emf")
149 ,("eml","message/rfc822")
151 ,("eml","message/rfc822")
150 ,("ent","chemical/x-ncbi-asn1-ascii")
152 ,("ent","chemical/x-ncbi-asn1-ascii")
151 ,("eot","application/vnd.ms-fontobject")
153 ,("eot","application/vnd.ms-fontobject")
@@ -219,6 +221,7 @@ mimeTypesList = -- List borrowed from happstack-server.
219 ,("jnlp","application/x-java-jnlp-file")
221 ,("jnlp","application/x-java-jnlp-file")
220 ,("jpe","image/jpeg")
222 ,("jpe","image/jpeg")
221 ,("jpeg","image/jpeg")
223 ,("jpeg","image/jpeg")
224+ ,("jfif","image/jpeg")
222 ,("jpg","image/jpeg")
225 ,("jpg","image/jpeg")
223 ,("js","application/x-javascript")
226 ,("js","application/x-javascript")
224 ,("kar","audio/midi")
227 ,("kar","audio/midi")
@@ -463,6 +466,7 @@ mimeTypesList = -- List borrowed from happstack-server.
463 ,("wm","video/x-ms-wm")
466 ,("wm","video/x-ms-wm")
464 ,("wma","audio/x-ms-wma")
467 ,("wma","audio/x-ms-wma")
465 ,("wmd","application/x-ms-wmd")
468 ,("wmd","application/x-ms-wmd")
469+ ,("wmf","image/x-wmf")
466 ,("wml","text/vnd.wap.wml")
470 ,("wml","text/vnd.wap.wml")
467 ,("wmlc","application/vnd.wap.wmlc")
471 ,("wmlc","application/vnd.wap.wmlc")
468 ,("wmls","text/vnd.wap.wmlscript")
472 ,("wmls","text/vnd.wap.wmlscript")
src/Text/Pandoc/PDF.hs+2−1
@@ -41,6 +41,7 @@ import System.Directory
41import System.Environment
41import System.Environment
42import Control.Monad (unless)
42import Control.Monad (unless)
43import Data.List (isInfixOf)
43import Data.List (isInfixOf)
44+import Data.Maybe (fromMaybe)
44import qualified Data.ByteString.Base64 as B64
45import qualified Data.ByteString.Base64 as B64
45import qualified Text.Pandoc.UTF8 as UTF8
46import qualified Text.Pandoc.UTF8 as UTF8
46import Text.Pandoc.Definition
47import Text.Pandoc.Definition
@@ -87,7 +88,7 @@ handleImage' baseURL tmpdir (Image ils (src,tit)) = do
87 res <- fetchItem baseURL src
88 res <- fetchItem baseURL src
88 case res of
89 case res of
89 Right (contents, Just mime) -> do
90 Right (contents, Just mime) -> do
90− let ext = maybe (takeExtension src) id $
91+ let ext = fromMaybe (takeExtension src) $
91 extensionFromMimeType mime
92 extensionFromMimeType mime
92 let basename = UTF8.toString $ B64.encode $ UTF8.fromString src
93 let basename = UTF8.toString $ B64.encode $ UTF8.fromString src
93 let fname = tmpdir </> basename <.> ext
94 let fname = tmpdir </> basename <.> ext
src/Text/Pandoc/Parsing.hs+79−14
@@ -1,4 +1,5 @@
1−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1+{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances,
2+ FlexibleInstances#-}
2{-
3{-
3Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
4Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
4
5
@@ -47,6 +48,8 @@ module Text.Pandoc.Parsing ( (>>~),
47 romanNumeral,
48 romanNumeral,
48 emailAddress,
49 emailAddress,
49 uri,
50 uri,
51+ mathInline,
52+ mathDisplay,
50 withHorizDisplacement,
53 withHorizDisplacement,
51 withRaw,
54 withRaw,
52 escaped,
55 escaped,
@@ -65,6 +68,9 @@ module Text.Pandoc.Parsing ( (>>~),
65 guardEnabled,
68 guardEnabled,
66 guardDisabled,
69 guardDisabled,
67 ParserState (..),
70 ParserState (..),
71+ HasReaderOptions (..),
72+ HasHeaderMap (..),
73+ HasIdentifierList (..),
68 defaultParserState,
74 defaultParserState,
69 HeaderType (..),
75 HeaderType (..),
70 ParserContext (..),
76 ParserContext (..),
@@ -265,7 +271,7 @@ spaceChar = satisfy $ \c -> c == ' ' || c == '\t'
265
271
266-- | Parses a nonspace, nonnewline character.
272-- | Parses a nonspace, nonnewline character.
267nonspaceChar :: Parser [Char] st Char
273nonspaceChar :: Parser [Char] st Char
268−nonspaceChar = satisfy $ \x -> x /= '\t' && x /= '\n' && x /= ' ' && x /= '\r'
274+nonspaceChar = satisfy $ flip notElem ['\t', '\n', ' ', '\r']
269
275
270-- | Skips zero or more spaces or tabs.
276-- | Skips zero or more spaces or tabs.
271skipSpaces :: Parser [Char] st ()
277skipSpaces :: Parser [Char] st ()
@@ -451,6 +457,39 @@ uri = try $ do
451 let uri' = scheme ++ ":" ++ fromEntities str'
457 let uri' = scheme ++ ":" ++ fromEntities str'
452 return (uri', escapeURI uri')
458 return (uri', escapeURI uri')
453
459
460+mathInlineWith :: String -> String -> Parser [Char] st String
461+mathInlineWith op cl = try $ do
462+ string op
463+ notFollowedBy space
464+ words' <- many1Till (count 1 (noneOf "\n\\")
465+ <|> (char '\\' >> anyChar >>= \c -> return ['\\',c])
466+ <|> count 1 newline <* notFollowedBy' blankline
467+ *> return " ")
468+ (try $ string cl)
469+ notFollowedBy digit -- to prevent capture of $5
470+ return $ concat words'
471+
472+mathDisplayWith :: String -> String -> Parser [Char] st String
473+mathDisplayWith op cl = try $ do
474+ string op
475+ many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl)
476+
477+mathDisplay :: Parser [Char] ParserState String
478+mathDisplay =
479+ (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
480+ <|> (guardEnabled Ext_tex_math_single_backslash >>
481+ mathDisplayWith "\\[" "\\]")
482+ <|> (guardEnabled Ext_tex_math_double_backslash >>
483+ mathDisplayWith "\\\\[" "\\\\]")
484+
485+mathInline :: Parser [Char] ParserState String
486+mathInline =
487+ (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
488+ <|> (guardEnabled Ext_tex_math_single_backslash >>
489+ mathInlineWith "\\(" "\\)")
490+ <|> (guardEnabled Ext_tex_math_double_backslash >>
491+ mathInlineWith "\\\\(" "\\\\)")
492+
454-- | Applies a parser, returns tuple of its results and its horizontal
493-- | Applies a parser, returns tuple of its results and its horizontal
455-- displacement (the difference between the source column at the end
494-- displacement (the difference between the source column at the end
456-- and the source column at the beginning). Vertical displacement
495-- and the source column at the beginning). Vertical displacement
@@ -826,6 +865,34 @@ instance HasMeta ParserState where
826 deleteMeta field st =
865 deleteMeta field st =
827 st{ stateMeta = deleteMeta field $ stateMeta st }
866 st{ stateMeta = deleteMeta field $ stateMeta st }
828
867
868+class Monad m => HasReaderOptions m where
869+ askReaderOption :: (ReaderOptions -> b) -> m b
870+
871+class Monad m => HasHeaderMap m where
872+ getHeaderMap :: m (M.Map Inlines String)
873+ putHeaderMap :: M.Map Inlines String -> m ()
874+ modifyHeaderMap :: (M.Map Inlines String -> M.Map Inlines String) -> m ()
875+ -- default
876+ modifyHeaderMap f = getHeaderMap >>= putHeaderMap . f
877+
878+class Monad m => HasIdentifierList m where
879+ getIdentifierList :: m [String]
880+ putIdentifierList :: [String] -> m ()
881+ modifyIdentifierList :: ([String] -> [String]) -> m ()
882+ -- default
883+ modifyIdentifierList f = getIdentifierList >>= putIdentifierList . f
884+
885+instance HasReaderOptions (Parser s ParserState) where
886+ askReaderOption = getOption
887+
888+instance HasHeaderMap (Parser s ParserState) where
889+ getHeaderMap = fmap stateHeaders getState
890+ putHeaderMap hm = updateState $ \st -> st{ stateHeaders = hm }
891+
892+instance HasIdentifierList (Parser s ParserState) where
893+ getIdentifierList = fmap stateIdentifiers getState
894+ putIdentifierList l = updateState $ \st -> st{ stateIdentifiers = l }
895+
829defaultParserState :: ParserState
896defaultParserState :: ParserState
830defaultParserState =
897defaultParserState =
831 ParserState { stateOptions = def,
898 ParserState { stateOptions = def,
@@ -895,10 +962,11 @@ type SubstTable = M.Map Key Inlines
895-- and the auto_identifers extension is set, generate a new
962-- and the auto_identifers extension is set, generate a new
896-- unique identifier, and update the list of identifiers
963-- unique identifier, and update the list of identifiers
897-- in state.
964-- in state.
965+registerHeader :: (HasReaderOptions m, HasHeaderMap m, HasIdentifierList m)
898−registerHeader :: Attr -> Inlines -> Parser s ParserState Attr
966+ => Attr -> Inlines -> m Attr
899registerHeader (ident,classes,kvs) header' = do
967registerHeader (ident,classes,kvs) header' = do
900− ids <- stateIdentifiers `fmap` getState
968+ ids <- getIdentifierList
901− exts <- getOption readerExtensions
969+ exts <- askReaderOption readerExtensions
902 let insert' = M.insertWith (\_new old -> old)
970 let insert' = M.insertWith (\_new old -> old)
903 if null ident && Ext_auto_identifiers `Set.member` exts
971 if null ident && Ext_auto_identifiers `Set.member` exts
904 then do
972 then do
@@ -906,16 +974,13 @@ registerHeader (ident,classes,kvs) header' = do
906 let id'' = if Ext_ascii_identifiers `Set.member` exts
974 let id'' = if Ext_ascii_identifiers `Set.member` exts
907 then catMaybes $ map toAsciiChar id'
975 then catMaybes $ map toAsciiChar id'
908 else id'
976 else id'
909− updateState $ \st -> st{
977+ putIdentifierList $ if id' == id''
910− stateIdentifiers = if id' == id''
911− then id' : ids
978+ then id' : ids
912− else id' : id'' : ids,
979+ else id' : id'' : ids
913− stateHeaders = insert' header' id' $ stateHeaders st }
980+ modifyHeaderMap $ insert' header' id'
914 return (id'',classes,kvs)
981 return (id'',classes,kvs)
915 else do
982 else do
916− unless (null ident) $
983+ unless (null ident) $ modifyHeaderMap $ insert' header' ident
917− updateState $ \st -> st{
918− stateHeaders = insert' header' ident $ stateHeaders st }
919 return (ident,classes,kvs)
984 return (ident,classes,kvs)
920
985
921-- | Fail unless we're in "smart typography" mode.
986-- | Fail unless we're in "smart typography" mode.
@@ -997,7 +1062,7 @@ doubleQuoteStart :: Parser [Char] ParserState ()
997doubleQuoteStart = do
1062doubleQuoteStart = do
998 failIfInQuoteContext InDoubleQuote
1063 failIfInQuoteContext InDoubleQuote
999 try $ do charOrRef "\"\8220\147"
1064 try $ do charOrRef "\"\8220\147"
1000− notFollowedBy (satisfy (\c -> c == ' ' || c == '\t' || c == '\n'))
1065+ notFollowedBy . satisfy $ flip elem [' ', '\t', '\n']
1001
1066
1002doubleQuoteEnd :: Parser [Char] st ()
1067doubleQuoteEnd :: Parser [Char] st ()
1003doubleQuoteEnd = do
1068doubleQuoteEnd = do
src/Text/Pandoc/Pretty.hs+11−3
@@ -60,6 +60,7 @@ module Text.Pandoc.Pretty (
60 , hsep
60 , hsep
61 , vcat
61 , vcat
62 , vsep
62 , vsep
63+ , nestle
63 , chomp
64 , chomp
64 , inside
65 , inside
65 , braces
66 , braces
@@ -72,7 +73,7 @@ module Text.Pandoc.Pretty (
72 )
73 )
73
74
74where
75where
75−import Data.Sequence (Seq, fromList, (<|), singleton, mapWithIndex)
76+import Data.Sequence (Seq, fromList, (<|), singleton, mapWithIndex, viewl, ViewL(..))
76import Data.Foldable (toList)
77import Data.Foldable (toList)
77import Data.List (intercalate)
78import Data.List (intercalate)
78import Data.Monoid
79import Data.Monoid
@@ -80,8 +81,7 @@ import Data.String
80import Control.Monad.State
81import Control.Monad.State
81import Data.Char (isSpace)
82import Data.Char (isSpace)
82
83
83−data Monoid a =>
84− RenderState a = RenderState{
84+data RenderState a = RenderState{
85 output :: [a] -- ^ In reverse order
85 output :: [a] -- ^ In reverse order
86 , prefix :: String
86 , prefix :: String
87 , usePrefix :: Bool
87 , usePrefix :: Bool
@@ -186,6 +186,14 @@ vcat = foldr ($$) empty
186vsep :: [Doc] -> Doc
186vsep :: [Doc] -> Doc
187vsep = foldr ($+$) empty
187vsep = foldr ($+$) empty
188
188
189+-- | Removes leading blank lines from a 'Doc'.
190+nestle :: Doc -> Doc
191+nestle (Doc d) = Doc $ go d
192+ where go x = case viewl x of
193+ (BlankLine :< rest) -> go rest
194+ (NewLine :< rest) -> go rest
195+ _ -> x
196+
189-- | Chomps trailing blank space off of a 'Doc'.
197-- | Chomps trailing blank space off of a 'Doc'.
190chomp :: Doc -> Doc
198chomp :: Doc -> Doc
191chomp d = Doc (fromList dl')
199chomp d = Doc (fromList dl')
src/Text/Pandoc/Readers/DocBook.hs+7−4
@@ -12,6 +12,7 @@ import Data.Char (isSpace)
12import Control.Monad.State
12import Control.Monad.State
13import Control.Applicative ((<$>))
13import Control.Applicative ((<$>))
14import Data.List (intersperse)
14import Data.List (intersperse)
15+import Data.Maybe (fromMaybe)
15
16
16{-
17{-
17
18
@@ -683,7 +684,7 @@ parseBlock (Elem e) =
683 "lowerroman" -> LowerRoman
684 "lowerroman" -> LowerRoman
684 "upperroman" -> UpperRoman
685 "upperroman" -> UpperRoman
685 _ -> Decimal
686 _ -> Decimal
686− let start = maybe 1 id $
687+ let start = fromMaybe 1 $
687 (attrValue "override" <$> filterElement (named "listitem") e)
688 (attrValue "override" <$> filterElement (named "listitem") e)
688 >>= safeRead
689 >>= safeRead
689 orderedListWith (start,listStyle,DefaultDelim)
690 orderedListWith (start,listStyle,DefaultDelim)
@@ -779,7 +780,7 @@ parseBlock (Elem e) =
779 caption <- case filterChild isCaption e of
780 caption <- case filterChild isCaption e of
780 Just t -> getInlines t
781 Just t -> getInlines t
781 Nothing -> return mempty
782 Nothing -> return mempty
782− let e' = maybe e id $ filterChild (named "tgroup") e
783+ let e' = fromMaybe e $ filterChild (named "tgroup") e
783 let isColspec x = named "colspec" x || named "col" x
784 let isColspec x = named "colspec" x || named "col" x
784 let colspecs = case filterChild (named "colgroup") e' of
785 let colspecs = case filterChild (named "colgroup") e' of
785 Just c -> filterChildren isColspec c
786 Just c -> filterChildren isColspec c
@@ -801,12 +802,14 @@ parseBlock (Elem e) =
801 Just "center" -> AlignCenter
802 Just "center" -> AlignCenter
802 _ -> AlignDefault
803 _ -> AlignDefault
803 let toWidth c = case findAttr (unqual "colwidth") c of
804 let toWidth c = case findAttr (unqual "colwidth") c of
804− Just w -> maybe 0 id
805+ Just w -> fromMaybe 0
805 $ safeRead $ '0': filter (\x ->
806 $ safeRead $ '0': filter (\x ->
806 (x >= '0' && x <= '9')
807 (x >= '0' && x <= '9')
807 || x == '.') w
808 || x == '.') w
808 Nothing -> 0 :: Double
809 Nothing -> 0 :: Double
810+ let numrows = case bodyrows of
811+ [] -> 0
809− let numrows = maximum $ map length bodyrows
812+ xs -> maximum $ map length xs
810 let aligns = case colspecs of
813 let aligns = case colspecs of
811 [] -> replicate numrows AlignDefault
814 [] -> replicate numrows AlignDefault
812 cs -> map toAlignment cs
815 cs -> map toAlignment cs
src/Text/Pandoc/Readers/HTML.hs+21−5
@@ -76,9 +76,18 @@ pBody :: TagParser [Block]
76pBody = pInTags "body" block
76pBody = pInTags "body" block
77
77
78pHead :: TagParser [Block]
78pHead :: TagParser [Block]
79−pHead = pInTags "head" $ pTitle <|> ([] <$ pAnyTag)
79+pHead = pInTags "head" $ pTitle <|> pMetaTag <|> ([] <$ pAnyTag)
80 where pTitle = pInTags "title" inline >>= setTitle . normalizeSpaces
80 where pTitle = pInTags "title" inline >>= setTitle . normalizeSpaces
81 setTitle t = [] <$ (updateState $ B.setMeta "title" (B.fromList t))
81 setTitle t = [] <$ (updateState $ B.setMeta "title" (B.fromList t))
82+ pMetaTag = do
83+ mt <- pSatisfy (~== TagOpen "meta" [])
84+ let name = fromAttrib "name" mt
85+ if null name
86+ then return []
87+ else do
88+ let content = fromAttrib "content" mt
89+ updateState $ B.setMeta name (B.text content)
90+ return []
82
91
83block :: TagParser [Block]
92block :: TagParser [Block]
84block = choice
93block = choice
@@ -207,7 +216,7 @@ pHeader = try $ do
207 let bodyTitle = TagOpen tagtype attr ~== TagOpen "h1" [("class","title")]
216 let bodyTitle = TagOpen tagtype attr ~== TagOpen "h1" [("class","title")]
208 let level = read (drop 1 tagtype)
217 let level = read (drop 1 tagtype)
209 contents <- liftM concat $ manyTill inline (pCloses tagtype <|> eof)
218 contents <- liftM concat $ manyTill inline (pCloses tagtype <|> eof)
210− let ident = maybe "" id $ lookup "id" attr
219+ let ident = fromMaybe "" $ lookup "id" attr
211 let classes = maybe [] words $ lookup "class" attr
220 let classes = maybe [] words $ lookup "class" attr
212 let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"]
221 let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"]
213 return $ if bodyTitle
222 return $ if bodyTitle
@@ -257,7 +266,7 @@ pCol = try $ do
257 skipMany pBlank
266 skipMany pBlank
258 return $ case lookup "width" attribs of
267 return $ case lookup "width" attribs of
259 Just x | not (null x) && last x == '%' ->
268 Just x | not (null x) && last x == '%' ->
260− maybe 0.0 id $ safeRead ('0':'.':init x)
269+ fromMaybe 0.0 $ safeRead ('0':'.':init x)
261 _ -> 0.0
270 _ -> 0.0
262
271
263pColgroup :: TagParser [Double]
272pColgroup :: TagParser [Double]
@@ -467,7 +476,13 @@ pBlank = try $ do
467
476
468pTagContents :: Parser [Char] ParserState Inline
477pTagContents :: Parser [Char] ParserState Inline
469pTagContents =
478pTagContents =
479+ Math DisplayMath `fmap` mathDisplay
480+ <|> Math InlineMath `fmap` mathInline
481+ <|> pStr
482+ <|> pSpace
470− pStr <|> pSpace <|> smartPunctuation pTagContents <|> pSymbol <|> pBad
483+ <|> smartPunctuation pTagContents
484+ <|> pSymbol
485+ <|> pBad
471
486
472pStr :: Parser [Char] ParserState Inline
487pStr :: Parser [Char] ParserState Inline
473pStr = do
488pStr = do
@@ -482,6 +497,7 @@ isSpecial '"' = True
482isSpecial '\'' = True
497isSpecial '\'' = True
483isSpecial '.' = True
498isSpecial '.' = True
484isSpecial '-' = True
499isSpecial '-' = True
500+isSpecial '$' = True
485isSpecial '\8216' = True
501isSpecial '\8216' = True
486isSpecial '\8217' = True
502isSpecial '\8217' = True
487isSpecial '\8220' = True
503isSpecial '\8220' = True
@@ -557,7 +573,7 @@ blockHtmlTags = ["address", "article", "aside", "blockquote", "body", "button",
557 "noframes", "noscript", "object", "ol", "output", "p", "pre", "progress",
573 "noframes", "noscript", "object", "ol", "output", "p", "pre", "progress",
558 "section", "table", "tbody", "textarea", "thead", "tfoot", "ul", "dd",
574 "section", "table", "tbody", "textarea", "thead", "tfoot", "ul", "dd",
559 "dt", "frameset", "li", "tbody", "td", "tfoot",
575 "dt", "frameset", "li", "tbody", "td", "tfoot",
560− "th", "thead", "tr", "script", "style", "video"]
576+ "th", "thead", "tr", "script", "style", "svg", "video"]
561
577
562-- We want to allow raw docbook in markdown documents, so we
578-- We want to allow raw docbook in markdown documents, so we
563-- include docbook block tags here too.
579-- include docbook block tags here too.
src/Text/Pandoc/Readers/LaTeX.hs+25−11
@@ -38,7 +38,8 @@ import Text.Pandoc.Definition
38import Text.Pandoc.Walk
38import Text.Pandoc.Walk
39import Text.Pandoc.Shared
39import Text.Pandoc.Shared
40import Text.Pandoc.Options
40import Text.Pandoc.Options
41−import Text.Pandoc.Parsing hiding ((<|>), many, optional, space)
41+import Text.Pandoc.Parsing hiding ((<|>), many, optional, space,
42+ mathDisplay, mathInline)
42import qualified Text.Pandoc.UTF8 as UTF8
43import qualified Text.Pandoc.UTF8 as UTF8
43import Data.Char ( chr, ord )
44import Data.Char ( chr, ord )
44import Control.Monad
45import Control.Monad
@@ -163,13 +164,25 @@ mathChars = concat <$>
163 <|> (\c -> ['\\',c]) <$> (try $ char '\\' *> anyChar)
164 <|> (\c -> ['\\',c]) <$> (try $ char '\\' *> anyChar)
164 )
165 )
165
166
167+quoted' :: (Inlines -> Inlines) -> LP String -> LP () -> LP Inlines
168+quoted' f starter ender = do
169+ startchs <- starter
170+ try ((f . mconcat) <$> manyTill inline ender) <|> lit startchs
171+
166double_quote :: LP Inlines
172double_quote :: LP Inlines
167−double_quote = (doubleQuoted . mconcat) <$>
173+double_quote =
174+ ( quoted' doubleQuoted (try $ string "``") (void $ try $ string "''")
175+ <|> quoted' doubleQuoted (string "“") (void $ char '”')
176+ -- the following is used by babel for localized quotes:
168− (try $ string "``" *> manyTill inline (try $ string "''"))
177+ <|> quoted' doubleQuoted (try $ string "\"`") (void $ try $ string "\"'")
178+ <|> quoted' doubleQuoted (string "\"") (void $ char '"')
179+ )
169
180
170single_quote :: LP Inlines
181single_quote :: LP Inlines
171−single_quote = (singleQuoted . mconcat) <$>
182+single_quote =
172− (try $ char '`' *> manyTill inline (try $ char '\'' >> notFollowedBy letter))
183+ ( quoted' singleQuoted (string "`") (try $ char '\'' >> notFollowedBy letter)
184+ <|> quoted' singleQuoted (string "‘") (try $ char '’' >> notFollowedBy letter)
185+ )
173
186
174inline :: LP Inlines
187inline :: LP Inlines
175inline = (mempty <$ comment)
188inline = (mempty <$ comment)
@@ -181,10 +194,10 @@ inline = (mempty <$ comment)
181 ((char '-') *> option (str "–") (str "—" <$ char '-')))
194 ((char '-') *> option (str "–") (str "—" <$ char '-')))
182 <|> double_quote
195 <|> double_quote
183 <|> single_quote
196 <|> single_quote
184− <|> (str "“" <$ try (string "``")) -- nb. {``} won't be caught by double_quote
185 <|> (str "”" <$ try (string "''"))
197 <|> (str "”" <$ try (string "''"))
186− <|> (str "‘" <$ char '`') -- nb. {`} won't be caught by single_quote
198+ <|> (str "”" <$ char '”')
187 <|> (str "’" <$ char '\'')
199 <|> (str "’" <$ char '\'')
200+ <|> (str "’" <$ char '’')
188 <|> (str "\160" <$ char '~')
201 <|> (str "\160" <$ char '~')
189 <|> (mathDisplay $ string "$$" *> mathChars <* string "$$")
202 <|> (mathDisplay $ string "$$" *> mathChars <* string "$$")
190 <|> (mathInline $ char '$' *> mathChars <* char '$')
203 <|> (mathInline $ char '$' *> mathChars <* char '$')
@@ -373,6 +386,7 @@ inlineCommands = M.fromList $
373 , ("backslash", lit "\\")
386 , ("backslash", lit "\\")
374 , ("slash", lit "/")
387 , ("slash", lit "/")
375 , ("textbf", strong <$> tok)
388 , ("textbf", strong <$> tok)
389+ , ("textnormal", spanWith ("",["nodecor"],[]) <$> tok)
376 , ("ldots", lit "…")
390 , ("ldots", lit "…")
377 , ("dots", lit "…")
391 , ("dots", lit "…")
378 , ("mdots", lit "…")
392 , ("mdots", lit "…")
@@ -443,6 +457,7 @@ inlineCommands = M.fromList $
443 , ("footnote", (note . mconcat) <$> (char '{' *> manyTill block (char '}')))
457 , ("footnote", (note . mconcat) <$> (char '{' *> manyTill block (char '}')))
444 , ("verb", doverb)
458 , ("verb", doverb)
445 , ("lstinline", doverb)
459 , ("lstinline", doverb)
460+ , ("Verb", doverb)
446 , ("texttt", (code . stringify . toList) <$> tok)
461 , ("texttt", (code . stringify . toList) <$> tok)
447 , ("url", (unescapeURL <$> braced) >>= \url ->
462 , ("url", (unescapeURL <$> braced) >>= \url ->
448 pure (link url "" (str url)))
463 pure (link url "" (str url)))
@@ -754,7 +769,7 @@ inlineText :: LP Inlines
754inlineText = str <$> many1 inlineChar
769inlineText = str <$> many1 inlineChar
755
770
756inlineChar :: LP Char
771inlineChar :: LP Char
757−inlineChar = noneOf "\\$%^_&~#{}^'`-[] \t\n"
772+inlineChar = noneOf "\\$%^_&~#{}^'`\"‘’“”-[] \t\n"
758
773
759environment :: LP Blocks
774environment :: LP Blocks
760environment = do
775environment = do
@@ -859,9 +874,8 @@ verbatimEnv = do
859 (_,r) <- withRaw $ do
874 (_,r) <- withRaw $ do
860 controlSeq "begin"
875 controlSeq "begin"
861 name <- braced
876 name <- braced
862− guard $ name == "verbatim" || name == "Verbatim" ||
877+ guard $ name `elem` ["verbatim", "Verbatim", "lstlisting",
863− name == "lstlisting" || name == "minted" ||
864− name == "alltt"
878+ "minted", "alltt"]
865 verbEnv name
879 verbEnv name
866 rest <- getInput
880 rest <- getInput
867 return (r,rest)
881 return (r,rest)
src/Text/Pandoc/Readers/Markdown.hs+33−58
@@ -215,10 +215,10 @@ pandocTitleBlock = try $ do
215 author' <- author
215 author' <- author
216 date' <- date
216 date' <- date
217 return $
217 return $
218− ( if B.isNull title' then id else B.setMeta "title" title'
218+ (if B.isNull title' then id else B.setMeta "title" title')
219− . if null author' then id else B.setMeta "author" author'
219+ . (if null author' then id else B.setMeta "author" author')
220− . if B.isNull date' then id else B.setMeta "date" date' )
220+ . (if B.isNull date' then id else B.setMeta "date" date')
221− nullMeta
221+ $ nullMeta
222 updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }
222 updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }
223
223
224yamlMetaBlock :: MarkdownParser (F Blocks)
224yamlMetaBlock :: MarkdownParser (F Blocks)
@@ -730,9 +730,14 @@ listStart = bulletListStart <|> (anyOrderedListStart >> return ())
730listLine :: MarkdownParser String
730listLine :: MarkdownParser String
731listLine = try $ do
731listLine = try $ do
732 notFollowedBy' (do indentSpaces
732 notFollowedBy' (do indentSpaces
733− many (spaceChar)
733+ many spaceChar
734 listStart)
734 listStart)
735+ notFollowedBy' $ htmlTag (~== TagClose "div")
736+ chunks <- manyTill
737+ ( many1 (satisfy $ \c -> c /= '\n' && c /= '<')
735− chunks <- manyTill (liftM snd (htmlTag isCommentTag) <|> count 1 anyChar) newline
738+ <|> liftM snd (htmlTag isCommentTag)
739+ <|> count 1 anyChar
740+ ) newline
736 return $ concat chunks
741 return $ concat chunks
737
742
738-- parse raw text for one list item, excluding start marker and continuations
743-- parse raw text for one list item, excluding start marker and continuations
@@ -759,6 +764,7 @@ listContinuationLine :: MarkdownParser String
759listContinuationLine = try $ do
764listContinuationLine = try $ do
760 notFollowedBy blankline
765 notFollowedBy blankline
761 notFollowedBy' listStart
766 notFollowedBy' listStart
767+ notFollowedBy' $ htmlTag (~== TagClose "div")
762 optional indentSpaces
768 optional indentSpaces
763 result <- anyLine
769 result <- anyLine
764 return $ result ++ "\n"
770 return $ result ++ "\n"
@@ -783,8 +789,8 @@ listItem start = try $ do
783orderedList :: MarkdownParser (F Blocks)
789orderedList :: MarkdownParser (F Blocks)
784orderedList = try $ do
790orderedList = try $ do
785 (start, style, delim) <- lookAhead anyOrderedListStart
791 (start, style, delim) <- lookAhead anyOrderedListStart
786− unless ((style == DefaultStyle || style == Decimal || style == Example) &&
792+ unless (style `elem` [DefaultStyle, Decimal, Example] &&
787− (delim == DefaultDelim || delim == Period)) $
793+ delim `elem` [DefaultDelim, Period]) $
788 guardEnabled Ext_fancy_lists
794 guardEnabled Ext_fancy_lists
789 when (style == Example) $ guardEnabled Ext_example_lists
795 when (style == Example) $ guardEnabled Ext_example_lists
790 items <- fmap sequence $ many1 $ listItem
796 items <- fmap sequence $ many1 $ listItem
@@ -896,7 +902,9 @@ plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline
896--
902--
897
903
898htmlElement :: MarkdownParser String
904htmlElement :: MarkdownParser String
905+htmlElement = rawVerbatimBlock
906+ <|> strictHtmlBlock
899−htmlElement = strictHtmlBlock <|> liftM snd (htmlTag isBlockTag)
907+ <|> liftM snd (htmlTag isBlockTag)
900
908
901htmlBlock :: MarkdownParser (F Blocks)
909htmlBlock :: MarkdownParser (F Blocks)
902htmlBlock = do
910htmlBlock = do
@@ -917,8 +925,8 @@ strictHtmlBlock = htmlInBalanced (not . isInlineTag)
917
925
918rawVerbatimBlock :: MarkdownParser String
926rawVerbatimBlock :: MarkdownParser String
919rawVerbatimBlock = try $ do
927rawVerbatimBlock = try $ do
920− (TagOpen tag _, open) <- htmlTag (tagOpen (\t ->
928+ (TagOpen tag _, open) <- htmlTag (tagOpen (flip elem
921− t == "pre" || t == "style" || t == "script")
929+ ["pre", "style", "script"])
922 (const True))
930 (const True))
923 contents <- manyTill anyChar (htmlTag (~== TagClose tag))
931 contents <- manyTill anyChar (htmlTag (~== TagClose tag))
924 return $ open ++ contents ++ renderTags [TagClose tag]
932 return $ open ++ contents ++ renderTags [TagClose tag]
@@ -1118,12 +1126,12 @@ multilineTableHeader headless = try $ do
1118 then liftM (map (:[]) . tail .
1126 then liftM (map (:[]) . tail .
1119 splitStringByIndices (init indices)) $ lookAhead anyLine
1127 splitStringByIndices (init indices)) $ lookAhead anyLine
1120 else return $ transpose $ map
1128 else return $ transpose $ map
1121− (\ln -> tail $ splitStringByIndices (init indices) ln)
1129+ (tail . splitStringByIndices (init indices))
1122 rawContent
1130 rawContent
1123 let aligns = zipWith alignType rawHeadsList lengths
1131 let aligns = zipWith alignType rawHeadsList lengths
1124 let rawHeads = if headless
1132 let rawHeads = if headless
1125 then replicate (length dashes) ""
1133 then replicate (length dashes) ""
1126− else map unwords rawHeadsList
1134+ else map (unlines . map trim) rawHeadsList
1127 heads <- fmap sequence $
1135 heads <- fmap sequence $
1128 mapM (parseFromString (mconcat <$> many plain)) $
1136 mapM (parseFromString (mconcat <$> many plain)) $
1129 map trim rawHeads
1137 map trim rawHeads
@@ -1180,7 +1188,7 @@ gridTableHeader headless = try $ do
1180 -- RST does not have a notion of alignments
1188 -- RST does not have a notion of alignments
1181 let rawHeads = if headless
1189 let rawHeads = if headless
1182 then replicate (length dashes) ""
1190 then replicate (length dashes) ""
1183− else map unwords $ transpose
1191+ else map (unlines . map trim) $ transpose
1184 $ map (gridTableSplitLine indices) rawContent
1192 $ map (gridTableSplitLine indices) rawContent
1185 heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads
1193 heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads
1186 return (heads, aligns, indices)
1194 return (heads, aligns, indices)
@@ -1406,39 +1414,6 @@ math :: MarkdownParser (F Inlines)
1406math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
1414math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
1407 <|> (return . B.math <$> (mathInline >>= applyMacros'))
1415 <|> (return . B.math <$> (mathInline >>= applyMacros'))
1408
1416
1409−mathDisplay :: MarkdownParser String
1410−mathDisplay =
1411− (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
1412− <|> (guardEnabled Ext_tex_math_single_backslash >>
1413− mathDisplayWith "\\[" "\\]")
1414− <|> (guardEnabled Ext_tex_math_double_backslash >>
1415− mathDisplayWith "\\\\[" "\\\\]")
1416−
1417−mathDisplayWith :: String -> String -> MarkdownParser String
1418−mathDisplayWith op cl = try $ do
1419− string op
1420− many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl)
1421−
1422−mathInline :: MarkdownParser String
1423−mathInline =
1424− (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
1425− <|> (guardEnabled Ext_tex_math_single_backslash >>
1426− mathInlineWith "\\(" "\\)")
1427− <|> (guardEnabled Ext_tex_math_double_backslash >>
1428− mathInlineWith "\\\\(" "\\\\)")
1429−
1430−mathInlineWith :: String -> String -> MarkdownParser String
1431−mathInlineWith op cl = try $ do
1432− string op
1433− notFollowedBy space
1434− words' <- many1Till (count 1 (noneOf "\n\\")
1435− <|> (char '\\' >> anyChar >>= \c -> return ['\\',c])
1436− <|> count 1 newline <* notFollowedBy' blankline
1437− *> return " ")
1438− (try $ string cl)
1439− notFollowedBy digit -- to prevent capture of $5
1440− return $ concat words'
1441−
1442-- Parses material enclosed in *s, **s, _s, or __s.
1417-- Parses material enclosed in *s, **s, _s, or __s.
1443-- Designed to avoid backtracking.
1418-- Designed to avoid backtracking.
1444enclosure :: Char
1419enclosure :: Char
@@ -1455,6 +1430,7 @@ enclosure c = do
1455-- Parse inlines til you hit one c or a sequence of two cs.
1430-- Parse inlines til you hit one c or a sequence of two cs.
1456-- If one c, emit emph and then parse two.
1431-- If one c, emit emph and then parse two.
1457-- If two cs, emit strong and then parse one.
1432-- If two cs, emit strong and then parse one.
1433+-- Otherwise, emit ccc then the results.
1458three :: Char -> MarkdownParser (F Inlines)
1434three :: Char -> MarkdownParser (F Inlines)
1459three c = do
1435three c = do
1460 contents <- mconcat <$> many (notFollowedBy (char c) >> inline)
1436 contents <- mconcat <$> many (notFollowedBy (char c) >> inline)
@@ -1479,7 +1455,7 @@ one c prefix' = do
1479 contents <- mconcat <$> many ( (notFollowedBy (char c) >> inline)
1455 contents <- mconcat <$> many ( (notFollowedBy (char c) >> inline)
1480 <|> try (string [c,c] >>
1456 <|> try (string [c,c] >>
1481 notFollowedBy (char c) >>
1457 notFollowedBy (char c) >>
1482− two c prefix') )
1458+ two c mempty) )
1483 (char c >> return (B.emph <$> (prefix' <> contents)))
1459 (char c >> return (B.emph <$> (prefix' <> contents)))
1484 <|> return (return (B.str [c]) <> (prefix' <> contents))
1460 <|> return (return (B.str [c]) <> (prefix' <> contents))
1485
1461
@@ -1564,16 +1540,14 @@ endline :: MarkdownParser (F Inlines)
1564endline = try $ do
1540endline = try $ do
1565 newline
1541 newline
1566 notFollowedBy blankline
1542 notFollowedBy blankline
1543+ -- parse potential list-starts differently if in a list:
1544+ st <- getState
1545+ when (stateParserContext st == ListItemState) $ notFollowedBy listStart
1567 guardDisabled Ext_lists_without_preceding_blankline <|> notFollowedBy listStart
1546 guardDisabled Ext_lists_without_preceding_blankline <|> notFollowedBy listStart
1568 guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart
1547 guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart
1569 guardEnabled Ext_blank_before_header <|> notFollowedBy (char '#') -- atx header
1548 guardEnabled Ext_blank_before_header <|> notFollowedBy (char '#') -- atx header
1570 guardEnabled Ext_backtick_code_blocks >>
1549 guardEnabled Ext_backtick_code_blocks >>
1571 notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced))
1550 notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced))
1572− -- parse potential list-starts differently if in a list:
1573− st <- getState
1574− when (stateParserContext st == ListItemState) $ do
1575− notFollowedBy' bulletListStart
1576− notFollowedBy' anyOrderedListStart
1577 (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))
1551 (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))
1578 <|> (guardEnabled Ext_ignore_line_breaks >> return mempty)
1552 <|> (guardEnabled Ext_ignore_line_breaks >> return mempty)
1579 <|> (return $ return B.space)
1553 <|> (return $ return B.space)
@@ -1746,7 +1720,7 @@ spanHtml = try $ do
1746 guardEnabled Ext_markdown_in_html_blocks
1720 guardEnabled Ext_markdown_in_html_blocks
1747 (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" [])
1721 (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" [])
1748 contents <- mconcat <$> manyTill inline (htmlTag (~== TagClose "span"))
1722 contents <- mconcat <$> manyTill inline (htmlTag (~== TagClose "span"))
1749− let ident = maybe "" id $ lookup "id" attrs
1723+ let ident = fromMaybe "" $ lookup "id" attrs
1750 let classes = maybe [] words $ lookup "class" attrs
1724 let classes = maybe [] words $ lookup "class" attrs
1751 let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
1725 let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
1752 return $ B.spanWith (ident, classes, keyvals) <$> contents
1726 return $ B.spanWith (ident, classes, keyvals) <$> contents
@@ -1756,7 +1730,7 @@ divHtml = try $ do
1756 guardEnabled Ext_markdown_in_html_blocks
1730 guardEnabled Ext_markdown_in_html_blocks
1757 (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "div" [])
1731 (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "div" [])
1758 contents <- mconcat <$> manyTill block (htmlTag (~== TagClose "div"))
1732 contents <- mconcat <$> manyTill block (htmlTag (~== TagClose "div"))
1759− let ident = maybe "" id $ lookup "id" attrs
1733+ let ident = fromMaybe "" $ lookup "id" attrs
1760 let classes = maybe [] words $ lookup "class" attrs
1734 let classes = maybe [] words $ lookup "class" attrs
1761 let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
1735 let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
1762 return $ B.divWith (ident, classes, keyvals) <$> contents
1736 return $ B.divWith (ident, classes, keyvals) <$> contents
@@ -1835,9 +1809,10 @@ citeKey = try $ do
1835 guard $ lastStrPos /= Just pos
1809 guard $ lastStrPos /= Just pos
1836 suppress_author <- option False (char '-' >> return True)
1810 suppress_author <- option False (char '-' >> return True)
1837 char '@'
1811 char '@'
1838− first <- letter
1812+ first <- letter <|> char '_'
1813+ let regchar = satisfy (\c -> isAlphaNum c || c == '_')
1839− let internal p = try $ p >>~ lookAhead (letter <|> digit)
1814+ let internal p = try $ p >>~ lookAhead regchar
1840− rest <- many $ letter <|> digit <|> internal (oneOf ":.#$%&-_+?<>~/")
1815+ rest <- many $ regchar <|> internal (oneOf ":.#$%&-+?<>~/")
1841 let key = first:rest
1816 let key = first:rest
1842 return (suppress_author, key)
1817 return (suppress_author, key)
1843
1818
src/Text/Pandoc/Readers/MediaWiki.hs+38−14
@@ -1,4 +1,5 @@
1+{-# LANGUAGE RelaxedPolyRec, FlexibleInstances, TypeSynonymInstances #-}
1−{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7
2+-- RelaxedPolyRec needed for inlinesBetween on GHC < 7
2{-
3{-
3 Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu>
4 Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu>
4
5
@@ -51,7 +52,9 @@ import Data.List (intersperse, intercalate, isPrefixOf )
51import Text.HTML.TagSoup
52import Text.HTML.TagSoup
52import Data.Sequence (viewl, ViewL(..), (<|))
53import Data.Sequence (viewl, ViewL(..), (<|))
53import qualified Data.Foldable as F
54import qualified Data.Foldable as F
55+import qualified Data.Map as M
54import Data.Char (isDigit, isSpace)
56import Data.Char (isDigit, isSpace)
57+import Data.Maybe (fromMaybe)
55
58
56-- | Read mediawiki from an input string and return a Pandoc document.
59-- | Read mediawiki from an input string and return a Pandoc document.
57readMediaWiki :: ReaderOptions -- ^ Reader options
60readMediaWiki :: ReaderOptions -- ^ Reader options
@@ -62,6 +65,8 @@ readMediaWiki opts s =
62 , mwMaxNestingLevel = 4
65 , mwMaxNestingLevel = 4
63 , mwNextLinkNumber = 1
66 , mwNextLinkNumber = 1
64 , mwCategoryLinks = []
67 , mwCategoryLinks = []
68+ , mwHeaderMap = M.empty
69+ , mwIdentifierList = []
65 }
70 }
66 "source" (s ++ "\n") of
71 "source" (s ++ "\n") of
67 Left err' -> error $ "\nError:\n" ++ show err'
72 Left err' -> error $ "\nError:\n" ++ show err'
@@ -71,10 +76,23 @@ data MWState = MWState { mwOptions :: ReaderOptions
71 , mwMaxNestingLevel :: Int
76 , mwMaxNestingLevel :: Int
72 , mwNextLinkNumber :: Int
77 , mwNextLinkNumber :: Int
73 , mwCategoryLinks :: [Inlines]
78 , mwCategoryLinks :: [Inlines]
79+ , mwHeaderMap :: M.Map Inlines String
80+ , mwIdentifierList :: [String]
74 }
81 }
75
82
76type MWParser = Parser [Char] MWState
83type MWParser = Parser [Char] MWState
77
84
85+instance HasReaderOptions MWParser where
86+ askReaderOption f = (f . mwOptions) `fmap` getState
87+
88+instance HasHeaderMap MWParser where
89+ getHeaderMap = fmap mwHeaderMap getState
90+ putHeaderMap hm = updateState $ \st -> st{ mwHeaderMap = hm }
91+
92+instance HasIdentifierList MWParser where
93+ getIdentifierList = fmap mwIdentifierList getState
94+ putIdentifierList l = updateState $ \st -> st{ mwIdentifierList = l }
95+
78--
96--
79-- auxiliary functions
97-- auxiliary functions
80--
98--
@@ -131,9 +149,16 @@ inlinesInTags tag = try $ do
131blocksInTags :: String -> MWParser Blocks
149blocksInTags :: String -> MWParser Blocks
132blocksInTags tag = try $ do
150blocksInTags tag = try $ do
133 (_,raw) <- htmlTag (~== TagOpen tag [])
151 (_,raw) <- htmlTag (~== TagOpen tag [])
152+ let closer = if tag == "li"
153+ then htmlTag (~== TagClose "li")
154+ <|> lookAhead (
155+ htmlTag (~== TagOpen "li" [])
156+ <|> htmlTag (~== TagClose "ol")
157+ <|> htmlTag (~== TagClose "ul"))
158+ else htmlTag (~== TagClose tag)
134 if '/' `elem` raw -- self-closing tag
159 if '/' `elem` raw -- self-closing tag
135 then return mempty
160 then return mempty
136− else mconcat <$> manyTill block (htmlTag (~== TagClose tag))
161+ else mconcat <$> manyTill block closer
137
162
138charsInTags :: String -> MWParser [Char]
163charsInTags :: String -> MWParser [Char]
139charsInTags tag = try $ do
164charsInTags tag = try $ do
@@ -187,7 +212,7 @@ table = do
187 tableStart
212 tableStart
188 styles <- option [] parseAttrs <* blankline
213 styles <- option [] parseAttrs <* blankline
189 let tableWidth = case lookup "width" styles of
214 let tableWidth = case lookup "width" styles of
190− Just w -> maybe 1.0 id $ parseWidth w
215+ Just w -> fromMaybe 1.0 $ parseWidth w
191 Nothing -> 1.0
216 Nothing -> 1.0
192 caption <- option mempty tableCaption
217 caption <- option mempty tableCaption
193 optional rowsep
218 optional rowsep
@@ -268,7 +293,7 @@ tableCell = try $ do
268 Just "center" -> AlignCenter
293 Just "center" -> AlignCenter
269 _ -> AlignDefault
294 _ -> AlignDefault
270 let width = case lookup "width" attrs of
295 let width = case lookup "width" attrs of
271− Just xs -> maybe 0.0 id $ parseWidth xs
296+ Just xs -> fromMaybe 0.0 $ parseWidth xs
272 Nothing -> 0.0
297 Nothing -> 0.0
273 return ((align, width), bs)
298 return ((align, width), bs)
274
299
@@ -351,7 +376,8 @@ header = try $ do
351 let lev = length eqs
376 let lev = length eqs
352 guard $ lev <= 6
377 guard $ lev <= 6
353 contents <- trimInlines . mconcat <$> manyTill inline (count lev $ char '=')
378 contents <- trimInlines . mconcat <$> manyTill inline (count lev $ char '=')
379+ attr <- registerHeader nullAttr contents
354− return $ B.header lev contents
380+ return $ B.headerWith attr lev contents
355
381
356bulletList :: MWParser Blocks
382bulletList :: MWParser Blocks
357bulletList = B.bulletList <$>
383bulletList = B.bulletList <$>
@@ -362,15 +388,13 @@ bulletList = B.bulletList <$>
362orderedList :: MWParser Blocks
388orderedList :: MWParser Blocks
363orderedList =
389orderedList =
364 (B.orderedList <$> many1 (listItem '#'))
390 (B.orderedList <$> many1 (listItem '#'))
365− <|> (B.orderedList <$> (htmlTag (~== TagOpen "ul" []) *> spaces *>
391+ <|> try
366− many (listItem '#' <|> li) <*
367− optional (htmlTag (~== TagClose "ul"))))
368− <|> do (tag,_) <- htmlTag (~== TagOpen "ol" [])
392+ (do (tag,_) <- htmlTag (~== TagOpen "ol" [])
369− spaces
393+ spaces
370− items <- many (listItem '#' <|> li)
394+ items <- many (listItem '#' <|> li)
371− optional (htmlTag (~== TagClose "ol"))
395+ optional (htmlTag (~== TagClose "ol"))
372− let start = maybe 1 id $ safeRead $ fromAttrib "start" tag
396+ let start = fromMaybe 1 $ safeRead $ fromAttrib "start" tag
373− return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items
397+ return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items)
374
398
375definitionList :: MWParser Blocks
399definitionList :: MWParser Blocks
376definitionList = B.definitionList <$> many1 defListItem
400definitionList = B.definitionList <$> many1 defListItem
src/Text/Pandoc/Readers/RST.hs+17−6
@@ -347,14 +347,25 @@ lhsCodeBlock = try $ do
347 getPosition >>= guard . (==1) . sourceColumn
347 getPosition >>= guard . (==1) . sourceColumn
348 guardEnabled Ext_literate_haskell
348 guardEnabled Ext_literate_haskell
349 optional codeBlockStart
349 optional codeBlockStart
350− lns <- many1 birdTrackLine
350+ lns <- latexCodeBlock <|> birdCodeBlock
351− -- if (as is normal) there is always a space after >, drop it
352− let lns' = if all (\ln -> null ln || take 1 ln == " ") lns
353− then map (drop 1) lns
354− else lns
355 blanklines
351 blanklines
356 return $ B.codeBlockWith ("", ["sourceCode", "literate", "haskell"], [])
352 return $ B.codeBlockWith ("", ["sourceCode", "literate", "haskell"], [])
357− $ intercalate "\n" lns'
353+ $ intercalate "\n" lns
354+
355+latexCodeBlock :: Parser [Char] st [[Char]]
356+latexCodeBlock = try $ do
357+ try (latexBlockLine "\\begin{code}")
358+ many1Till anyLine (try $ latexBlockLine "\\end{code}")
359+ where
360+ latexBlockLine s = skipMany spaceChar >> string s >> blankline
361+
362+birdCodeBlock :: Parser [Char] st [[Char]]
363+birdCodeBlock = filterSpace <$> many1 birdTrackLine
364+ where filterSpace lns =
365+ -- if (as is normal) there is always a space after >, drop it
366+ if all (\ln -> null ln || take 1 ln == " ") lns
367+ then map (drop 1) lns
368+ else lns
358
369
359birdTrackLine :: Parser [Char] st [Char]
370birdTrackLine :: Parser [Char] st [Char]
360birdTrackLine = char '>' >> anyLine
371birdTrackLine = char '>' >> anyLine
src/Text/Pandoc/Readers/Textile.hs+1−1
@@ -594,7 +594,7 @@ surrounded border = enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try bo
594simpleInline :: Parser [Char] ParserState t -- ^ surrounding parser
594simpleInline :: Parser [Char] ParserState t -- ^ surrounding parser
595 -> ([Inline] -> Inline) -- ^ Inline constructor
595 -> ([Inline] -> Inline) -- ^ Inline constructor
596 -> Parser [Char] ParserState Inline -- ^ content parser (to be used repeatedly)
596 -> Parser [Char] ParserState Inline -- ^ content parser (to be used repeatedly)
597−simpleInline border construct = surrounded border (inlineWithAttribute) >>=
597+simpleInline border construct = surrounded border inlineWithAttribute >>=
598 return . construct . normalizeSpaces
598 return . construct . normalizeSpaces
599 where inlineWithAttribute = (try $ optional attributes) >> inline
599 where inlineWithAttribute = (try $ optional attributes) >> inline
600
600
src/Text/Pandoc/Shared.hs+19−16
@@ -91,7 +91,8 @@ import Data.Char ( toLower, isLower, isUpper, isAlpha,
91 isLetter, isDigit, isSpace )
91 isLetter, isDigit, isSpace )
92import Data.List ( find, isPrefixOf, intercalate )
92import Data.List ( find, isPrefixOf, intercalate )
93import qualified Data.Map as M
93import qualified Data.Map as M
94−import Network.URI ( escapeURIString, isURI, unEscapeString )
94+import Network.URI ( escapeURIString, isURI, nonStrictRelativeTo,
95+ unEscapeString, parseURIReference )
95import System.Directory
96import System.Directory
96import Text.Pandoc.MIME (getMimeType)
97import Text.Pandoc.MIME (getMimeType)
97import System.FilePath ( (</>), takeExtension, dropExtension )
98import System.FilePath ( (</>), takeExtension, dropExtension )
@@ -108,6 +109,7 @@ import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..),
108import qualified Data.ByteString as BS
109import qualified Data.ByteString as BS
109import qualified Data.ByteString.Char8 as B8
110import qualified Data.ByteString.Char8 as B8
110import Text.Pandoc.Compat.Monoid
111import Text.Pandoc.Compat.Monoid
112+import Data.ByteString.Base64 (decodeLenient)
111
113
112#ifdef EMBED_DATA_FILES
114#ifdef EMBED_DATA_FILES
113import Text.Pandoc.Data (dataFiles)
115import Text.Pandoc.Data (dataFiles)
@@ -120,6 +122,7 @@ import Data.ByteString.Lazy (toChunks)
120import Network.HTTP.Conduit (httpLbs, parseUrl, withManager,
122import Network.HTTP.Conduit (httpLbs, parseUrl, withManager,
121 responseBody, responseHeaders)
123 responseBody, responseHeaders)
122import Network.HTTP.Types.Header ( hContentType)
124import Network.HTTP.Types.Header ( hContentType)
125+import Network (withSocketsDo)
123#else
126#else
124import Network.URI (parseURI)
127import Network.URI (parseURI)
125import Network.HTTP (findHeader, rspBody,
128import Network.HTTP (findHeader, rspBody,
@@ -269,7 +272,7 @@ normalizeDate s = fmap (formatTime defaultTimeLocale "%F")
269 (msum $ map (\fs -> parsetimeWith fs s) formats :: Maybe Day)
272 (msum $ map (\fs -> parsetimeWith fs s) formats :: Maybe Day)
270 where parsetimeWith = parseTime defaultTimeLocale
273 where parsetimeWith = parseTime defaultTimeLocale
271 formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y",
274 formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y",
272− "%d %B %Y", "%b. %d, %Y", "%B %d, %Y"]
275+ "%d %B %Y", "%b. %d, %Y", "%B %d, %Y", "%Y"]
273
276
274--
277--
275-- Pandoc block and inline list processing
278-- Pandoc block and inline list processing
@@ -530,7 +533,7 @@ headerShift n = walk shift
530
533
531-- | Detect if a list is tight.
534-- | Detect if a list is tight.
532isTightList :: [[Block]] -> Bool
535isTightList :: [[Block]] -> Bool
533−isTightList = and . map firstIsPlain
536+isTightList = all firstIsPlain
534 where firstIsPlain (Plain _ : _) = True
537 where firstIsPlain (Plain _ : _) = True
535 firstIsPlain _ = False
538 firstIsPlain _ = False
536
539
@@ -562,14 +565,10 @@ makeMeta title authors date =
562-- | Render HTML tags.
565-- | Render HTML tags.
563renderTags' :: [Tag String] -> String
566renderTags' :: [Tag String] -> String
564renderTags' = renderTagsOptions
567renderTags' = renderTagsOptions
565− renderOptions{ optMinimize = \x ->
568+ renderOptions{ optMinimize = matchTags ["hr", "br", "img",
566− let y = map toLower x
567− in y == "hr" || y == "br" ||
568− y == "img" || y == "meta" ||
569− y == "link"
569+ "meta", "link"]
570− , optRawTag = \x ->
571− let y = map toLower x
572− in y == "script" || y == "style" }
570+ , optRawTag = matchTags ["script", "style"] }
571+ where matchTags = \tags -> flip elem tags . map toLower
573
572
574--
573--
575-- File handling
574-- File handling
@@ -625,9 +624,13 @@ fetchItem :: Maybe String -> String
625 -> IO (Either E.SomeException (BS.ByteString, Maybe String))
624 -> IO (Either E.SomeException (BS.ByteString, Maybe String))
626fetchItem sourceURL s
625fetchItem sourceURL s
627 | isURI s = openURL s
626 | isURI s = openURL s
628− | otherwise = case sourceURL of
627+ | otherwise =
628+ case sourceURL >>= parseURIReference of
629+ Just u -> case parseURIReference s of
630+ Just s' -> openURL $ show $
631+ s' `nonStrictRelativeTo` u
629− Just u -> openURL (u ++ "/" ++ s)
632+ Nothing -> openURL $ show u ++ "/" ++ s
630− Nothing -> E.try readLocalFile
633+ Nothing -> E.try readLocalFile
631 where readLocalFile = do
634 where readLocalFile = do
632 let mime = case takeExtension s of
635 let mime = case takeExtension s of
633 ".gz" -> getMimeType $ dropExtension s
636 ".gz" -> getMimeType $ dropExtension s
@@ -641,9 +644,9 @@ openURL u
641 | "data:" `isPrefixOf` u =
644 | "data:" `isPrefixOf` u =
642 let mime = takeWhile (/=',') $ drop 5 u
645 let mime = takeWhile (/=',') $ drop 5 u
643 contents = B8.pack $ unEscapeString $ drop 1 $ dropWhile (/=',') u
646 contents = B8.pack $ unEscapeString $ drop 1 $ dropWhile (/=',') u
644− in return $ Right (contents, Just mime)
647+ in return $ Right (decodeLenient contents, Just mime)
645#ifdef HTTP_CONDUIT
648#ifdef HTTP_CONDUIT
646− | otherwise = E.try $ do
649+ | otherwise = withSocketsDo $ E.try $ do
647 req <- parseUrl u
650 req <- parseUrl u
648 resp <- withManager $ httpLbs req
651 resp <- withManager $ httpLbs req
649 return (BS.concat $ toChunks $ responseBody resp,
652 return (BS.concat $ toChunks $ responseBody resp,
src/Text/Pandoc/Writers/ConTeXt.hs+4−4
@@ -130,7 +130,7 @@ blockToConTeXt (Plain lst) = inlineListToConTeXt lst
130-- title beginning with fig: indicates that the image is a figure
130-- title beginning with fig: indicates that the image is a figure
131blockToConTeXt (Para [Image txt (src,'f':'i':'g':':':_)]) = do
131blockToConTeXt (Para [Image txt (src,'f':'i':'g':':':_)]) = do
132 capt <- inlineListToConTeXt txt
132 capt <- inlineListToConTeXt txt
133− return $ blankline $$ "\\placefigure[here,nonumber]" <> braces capt <>
133+ return $ blankline $$ "\\placefigure" <> braces capt <>
134 braces ("\\externalfigure" <> brackets (text src)) <> blankline
134 braces ("\\externalfigure" <> brackets (text src)) <> blankline
135blockToConTeXt (Para lst) = do
135blockToConTeXt (Para lst) = do
136 contents <- inlineListToConTeXt lst
136 contents <- inlineListToConTeXt lst
@@ -205,9 +205,9 @@ blockToConTeXt (Table caption aligns widths heads rows) = do
205 else liftM ($$ "\\HL") $ tableRowToConTeXt heads
205 else liftM ($$ "\\HL") $ tableRowToConTeXt heads
206 captionText <- inlineListToConTeXt caption
206 captionText <- inlineListToConTeXt caption
207 rows' <- mapM tableRowToConTeXt rows
207 rows' <- mapM tableRowToConTeXt rows
208− return $ "\\placetable" <> brackets ("here" <> if null caption
208+ return $ "\\placetable" <> (if null caption
209− then ",none"
209+ then brackets "none"
210− else "")
210+ else empty)
211 <> braces captionText $$
211 <> braces captionText $$
212 "\\starttable" <> brackets (text colDescriptors) $$
212 "\\starttable" <> brackets (text colDescriptors) $$
213 "\\HL" $$ headers $$
213 "\\HL" $$ headers $$
src/Text/Pandoc/Writers/Docbook.hs+3−2
@@ -85,8 +85,9 @@ writeDocbook opts (Pandoc meta blocks) =
85 auths' = map (authorToDocbook opts) $ docAuthors meta
85 auths' = map (authorToDocbook opts) $ docAuthors meta
86 meta' = B.setMeta "author" auths' meta
86 meta' = B.setMeta "author" auths' meta
87 Just metadata = metaToJSON opts
87 Just metadata = metaToJSON opts
88− (Just . render colwidth . blocksToDocbook opts)
88+ (Just . render colwidth . (vcat .
89+ (map (elementToDocbook opts' startLvl)) . hierarchicalize))
89− (Just . render colwidth . inlinesToDocbook opts)
90+ (Just . render colwidth . inlinesToDocbook opts')
90 meta'
91 meta'
91 main = render' $ vcat (map (elementToDocbook opts' startLvl) elements)
92 main = render' $ vcat (map (elementToDocbook opts' startLvl) elements)
92 context = defField "body" main
93 context = defField "body" main
src/Text/Pandoc/Writers/Docx.hs+42−47
@@ -29,7 +29,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29Conversion of 'Pandoc' documents to docx.
29Conversion of 'Pandoc' documents to docx.
30-}
30-}
31module Text.Pandoc.Writers.Docx ( writeDocx ) where
31module Text.Pandoc.Writers.Docx ( writeDocx ) where
32−import Data.List ( intercalate, groupBy )
32+import Data.Maybe (fromMaybe)
33+import Data.List ( intercalate, isPrefixOf, isSuffixOf )
33import qualified Data.ByteString as B
34import qualified Data.ByteString as B
34import qualified Data.ByteString.Lazy as BL
35import qualified Data.ByteString.Lazy as BL
35import qualified Data.ByteString.Lazy.Char8 as BL8
36import qualified Data.ByteString.Lazy.Char8 as BL8
@@ -42,6 +43,7 @@ import Text.Pandoc.Definition
42import Text.Pandoc.Generic
43import Text.Pandoc.Generic
43import Text.Pandoc.ImageSize
44import Text.Pandoc.ImageSize
44import Text.Pandoc.Shared hiding (Element)
45import Text.Pandoc.Shared hiding (Element)
46+import Text.Pandoc.Writers.Shared (fixDisplayMath)
45import Text.Pandoc.Options
47import Text.Pandoc.Options
46import Text.Pandoc.Readers.TeXMath
48import Text.Pandoc.Readers.TeXMath
47import Text.Pandoc.Highlighting ( highlight )
49import Text.Pandoc.Highlighting ( highlight )
@@ -55,8 +57,8 @@ import Data.Unique (hashUnique, newUnique)
55import System.Random (randomRIO)
57import System.Random (randomRIO)
56import Text.Printf (printf)
58import Text.Printf (printf)
57import qualified Control.Exception as E
59import qualified Control.Exception as E
58−import System.FilePath (takeExtension)
59−import Text.Pandoc.MIME (getMimeType)
60+import Text.Pandoc.MIME (getMimeType, extensionFromMimeType)
61+import Control.Applicative ((<|>))
60
62
61data WriterState = WriterState{
63data WriterState = WriterState{
62 stTextProperties :: [Element]
64 stTextProperties :: [Element]
@@ -130,7 +132,8 @@ writeDocx opts doc@(Pandoc meta _) = do
130 let mkOverrideNode (part', contentType') = mknode "Override"
132 let mkOverrideNode (part', contentType') = mknode "Override"
131 [("PartName",part'),("ContentType",contentType')] ()
133 [("PartName",part'),("ContentType",contentType')] ()
132 let mkImageOverride (_, imgpath, mbMimeType, _, _) =
134 let mkImageOverride (_, imgpath, mbMimeType, _, _) =
135+ mkOverrideNode ("/word/" ++ imgpath,
133− mkOverrideNode ("/word/" ++ imgpath, maybe "application/octet-stream" id mbMimeType)
136+ fromMaybe "application/octet-stream" mbMimeType)
134 let overrides = map mkOverrideNode
137 let overrides = map mkOverrideNode
135 [("/word/webSettings.xml",
138 [("/word/webSettings.xml",
136 "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")
139 "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")
@@ -231,10 +234,11 @@ writeDocx opts doc@(Pandoc meta _) = do
231 ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")
234 ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")
232 ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]
235 ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]
233 $ mknode "dc:title" [] (stringify $ docTitle meta)
236 $ mknode "dc:title" [] (stringify $ docTitle meta)
234− : mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")]
235− (maybe "" id $ normalizeDate $ stringify $ docDate meta)
236− : mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] () -- put current time here
237− : map (mknode "dc:creator" [] . stringify) (docAuthors meta)
237+ : mknode "dc:creator" [] (intercalate "; " (map stringify $ docAuthors meta))
238+ : maybe []
239+ (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] $ x
240+ , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] $ x
241+ ]) (normalizeDate $ stringify $ docDate meta)
238 let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps
242 let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps
239
243
240 let relsPath = "_rels/.rels"
244 let relsPath = "_rels/.rels"
@@ -247,7 +251,7 @@ writeDocx opts doc@(Pandoc meta _) = do
247 ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")
251 ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")
248 ,("Target","docProps/app.xml")]
252 ,("Target","docProps/app.xml")]
249 , [("Id","rId3")
253 , [("Id","rId3")
250− ,("Type","http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties")
254+ ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")
251 ,("Target","docProps/core.xml")]
255 ,("Target","docProps/core.xml")]
252 ]
256 ]
253 let relsEntry = toEntry relsPath epochtime $ renderXml rels
257 let relsEntry = toEntry relsPath epochtime $ renderXml rels
@@ -259,6 +263,12 @@ writeDocx opts doc@(Pandoc meta _) = do
259 fontTableEntry <- entryFromArchive "word/fontTable.xml"
263 fontTableEntry <- entryFromArchive "word/fontTable.xml"
260 settingsEntry <- entryFromArchive "word/settings.xml"
264 settingsEntry <- entryFromArchive "word/settings.xml"
261 webSettingsEntry <- entryFromArchive "word/webSettings.xml"
265 webSettingsEntry <- entryFromArchive "word/webSettings.xml"
266+ let miscRels = [ f | f <- filesInArchive refArchive
267+ , "word/_rels/" `isPrefixOf` f
268+ , ".xml.rels" `isSuffixOf` f
269+ , f /= "word/_rels/document.xml.rels"
270+ , f /= "word/_rels/footnotes.xml.rels" ]
271+ miscRelEntries <- mapM entryFromArchive miscRels
262
272
263 -- Create archive
273 -- Create archive
264 let archive = foldr addEntryToArchive emptyArchive $
274 let archive = foldr addEntryToArchive emptyArchive $
@@ -266,7 +276,7 @@ writeDocx opts doc@(Pandoc meta _) = do
266 footnoteRelEntry : numEntry : styleEntry : footnotesEntry :
276 footnoteRelEntry : numEntry : styleEntry : footnotesEntry :
267 docPropsEntry : docPropsAppEntry : themeEntry :
277 docPropsEntry : docPropsAppEntry : themeEntry :
268 fontTableEntry : settingsEntry : webSettingsEntry :
278 fontTableEntry : settingsEntry : webSettingsEntry :
269− imageEntries
279+ imageEntries ++ miscRelEntries
270 return $ fromArchive archive
280 return $ fromArchive archive
271
281
272styleToOpenXml :: Style -> [Element]
282styleToOpenXml :: Style -> [Element]
@@ -321,7 +331,7 @@ mkNum markers marker numid =
321 NumberMarker _ _ start ->
331 NumberMarker _ _ start ->
322 map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",show (lvl :: Int))]
332 map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",show (lvl :: Int))]
323 $ mknode "w:startOverride" [("w:val",show start)] ()) [0..6]
333 $ mknode "w:startOverride" [("w:val",show start)] ()) [0..6]
324− where absnumid = maybe 0 id $ M.lookup marker markers
334+ where absnumid = fromMaybe 0 $ M.lookup marker markers
325
335
326mkAbstractNum :: (ListMarker,Int) -> IO Element
336mkAbstractNum :: (ListMarker,Int) -> IO Element
327mkAbstractNum (marker,numid) = do
337mkAbstractNum (marker,numid) = do
@@ -637,7 +647,12 @@ formattedString str = do
637inlineToOpenXML :: WriterOptions -> Inline -> WS [Element]
647inlineToOpenXML :: WriterOptions -> Inline -> WS [Element]
638inlineToOpenXML _ (Str str) = formattedString str
648inlineToOpenXML _ (Str str) = formattedString str
639inlineToOpenXML opts Space = inlineToOpenXML opts (Str " ")
649inlineToOpenXML opts Space = inlineToOpenXML opts (Str " ")
650+inlineToOpenXML opts (Span (_,classes,_) ils) = do
651+ let off x = withTextProp (mknode x [("w:val","0")] ())
652+ ((if "csl-no-emph" `elem` classes then off "w:i" else id) .
653+ (if "csl-no-strong" `elem` classes then off "w:b" else id) .
654+ (if "csl-no-smallcaps" `elem` classes then off "w:smallCaps" else id))
640−inlineToOpenXML opts (Span _ ils) = inlinesToOpenXML opts ils
655+ $ inlinesToOpenXML opts ils
641inlineToOpenXML opts (Strong lst) =
656inlineToOpenXML opts (Strong lst) =
642 withTextProp (mknode "w:b" [] ()) $ inlinesToOpenXML opts lst
657 withTextProp (mknode "w:b" [] ()) $ inlinesToOpenXML opts lst
643inlineToOpenXML opts (Emph lst) =
658inlineToOpenXML opts (Emph lst) =
@@ -736,7 +751,7 @@ inlineToOpenXML opts (Image alt (src, tit)) = do
736 liftIO $ warn $ "Could not find image `" ++ src ++ "', skipping..."
751 liftIO $ warn $ "Could not find image `" ++ src ++ "', skipping..."
737 -- emit alt text
752 -- emit alt text
738 inlinesToOpenXML opts alt
753 inlinesToOpenXML opts alt
739− Right (img, _) -> do
754+ Right (img, mt) -> do
740 ident <- ("rId"++) `fmap` getUniqueId
755 ident <- ("rId"++) `fmap` getUniqueId
741 let size = imageSize img
756 let size = imageSize img
742 let (xpt,ypt) = maybe (120,120) sizeInPoints size
757 let (xpt,ypt) = maybe (120,120) sizeInPoints size
@@ -775,19 +790,21 @@ inlineToOpenXML opts (Image alt (src, tit)) = do
775 , mknode "wp:effectExtent" [("b","0"),("l","0"),("r","0"),("t","0")] ()
790 , mknode "wp:effectExtent" [("b","0"),("l","0"),("r","0"),("t","0")] ()
776 , mknode "wp:docPr" [("descr",tit),("id","1"),("name","Picture")] ()
791 , mknode "wp:docPr" [("descr",tit),("id","1"),("name","Picture")] ()
777 , graphic ]
792 , graphic ]
793+ let imgext = case mt >>= extensionFromMimeType of
794+ Just x -> '.':x
778− let imgext = case imageType img of
795+ Nothing -> case imageType img of
779− Just Png -> ".png"
796+ Just Png -> ".png"
780− Just Jpeg -> ".jpeg"
797+ Just Jpeg -> ".jpeg"
781− Just Gif -> ".gif"
798+ Just Gif -> ".gif"
782− Just Pdf -> ".pdf"
799+ Just Pdf -> ".pdf"
783− Just Eps -> ".eps"
800+ Just Eps -> ".eps"
784− Nothing -> takeExtension src
801+ Nothing -> ""
785 if null imgext
802 if null imgext
786 then -- without an extension there is no rule for content type
803 then -- without an extension there is no rule for content type
787 inlinesToOpenXML opts alt -- return alt to avoid corrupted docx
804 inlinesToOpenXML opts alt -- return alt to avoid corrupted docx
788 else do
805 else do
789 let imgpath = "media/" ++ ident ++ imgext
806 let imgpath = "media/" ++ ident ++ imgext
790− let mbMimeType = getMimeType imgpath
807+ let mbMimeType = mt <|> getMimeType imgpath
791 -- insert mime type to use in constructing [Content_Types].xml
808 -- insert mime type to use in constructing [Content_Types].xml
792 modify $ \st -> st{ stImages =
809 modify $ \st -> st{ stImages =
793 M.insert src (ident, imgpath, mbMimeType, imgElt, img)
810 M.insert src (ident, imgpath, mbMimeType, imgElt, img)
@@ -799,30 +816,8 @@ br = mknode "w:r" [] [mknode "w:br" [("w:type","textWrapping")] () ]
799
816
800parseXml :: Archive -> String -> IO Element
817parseXml :: Archive -> String -> IO Element
801parseXml refArchive relpath =
818parseXml refArchive relpath =
802− case (findEntryByPath relpath refArchive >>= parseXMLDoc . UTF8.toStringLazy . fromEntry) of
819+ case findEntryByPath relpath refArchive of
820+ Just e -> case parseXMLDoc $ UTF8.toStringLazy $ fromEntry e of
803− Just d -> return d
821+ Just d -> return d
822+ Nothing -> fail $ relpath ++ " corrupt in reference docx"
804 Nothing -> fail $ relpath ++ " missing in reference docx"
823 Nothing -> fail $ relpath ++ " missing in reference docx"
805−
806−isDisplayMath :: Inline -> Bool
807−isDisplayMath (Math DisplayMath _) = True
808−isDisplayMath _ = False
809−
810−stripLeadingTrailingSpace :: [Inline] -> [Inline]
811−stripLeadingTrailingSpace = go . reverse . go . reverse
812− where go (Space:xs) = xs
813− go xs = xs
814−
815−fixDisplayMath :: Block -> Block
816−fixDisplayMath (Plain lst)
817− | any isDisplayMath lst && not (all isDisplayMath lst) =
818− -- chop into several paragraphs so each displaymath is its own
819− Div ("",["math"],[]) $ map (Plain . stripLeadingTrailingSpace) $
820− groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||
821− not (isDisplayMath x || isDisplayMath y)) lst
822−fixDisplayMath (Para lst)
823− | any isDisplayMath lst && not (all isDisplayMath lst) =
824− -- chop into several paragraphs so each displaymath is its own
825− Div ("",["math"],[]) $ map (Para . stripLeadingTrailingSpace) $
826− groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||
827− not (isDisplayMath x || isDisplayMath y)) lst
828−fixDisplayMath x = x
src/Text/Pandoc/Writers/EPUB.hs+663−82
@@ -1,4 +1,4 @@
1−{-# LANGUAGE PatternGuards, CPP #-}
1+{-# LANGUAGE PatternGuards, CPP, ScopedTypeVariables #-}
2{-
2{-
3Copyright (C) 2010 John MacFarlane <jgm@berkeley.edu>
3Copyright (C) 2010 John MacFarlane <jgm@berkeley.edu>
4
4
@@ -30,16 +30,18 @@ Conversion of 'Pandoc' documents to EPUB.
30-}
30-}
31module Text.Pandoc.Writers.EPUB ( writeEPUB ) where
31module Text.Pandoc.Writers.EPUB ( writeEPUB ) where
32import Data.IORef
32import Data.IORef
33+import qualified Data.Map as M
33−import Data.Maybe ( fromMaybe, isNothing )
34+import Data.Maybe ( fromMaybe )
34import Data.List ( isInfixOf, intercalate )
35import Data.List ( isInfixOf, intercalate )
35import System.Environment ( getEnv )
36import System.Environment ( getEnv )
36import Text.Printf (printf)
37import Text.Printf (printf)
37import System.FilePath ( (</>), takeBaseName, takeExtension, takeFileName )
38import System.FilePath ( (</>), takeBaseName, takeExtension, takeFileName )
38import qualified Data.ByteString.Lazy as B
39import qualified Data.ByteString.Lazy as B
39import qualified Data.ByteString.Lazy.Char8 as B8
40import qualified Data.ByteString.Lazy.Char8 as B8
40−import Text.Pandoc.UTF8 ( fromStringLazy, toString )
41+import qualified Text.Pandoc.UTF8 as UTF8
41import Text.Pandoc.SelfContained ( makeSelfContained )
42import Text.Pandoc.SelfContained ( makeSelfContained )
42import Codec.Archive.Zip
43import Codec.Archive.Zip
44+import Control.Applicative ((<$>))
43import Data.Time.Clock.POSIX
45import Data.Time.Clock.POSIX
44import Data.Time
46import Data.Time
45import System.Locale
47import System.Locale
@@ -54,7 +56,7 @@ import Text.XML.Light hiding (ppTopElement)
54import Text.Pandoc.UUID
56import Text.Pandoc.UUID
55import Text.Pandoc.Writers.HTML
57import Text.Pandoc.Writers.HTML
56import Text.Pandoc.Writers.Markdown ( writePlain )
58import Text.Pandoc.Writers.Markdown ( writePlain )
57−import Data.Char ( toLower )
59+import Data.Char ( toLower, isDigit )
58import Network.URI ( unEscapeString )
60import Network.URI ( unEscapeString )
59import Text.Pandoc.MIME (getMimeType)
61import Text.Pandoc.MIME (getMimeType)
60#if MIN_VERSION_base(4,6,0)
62#if MIN_VERSION_base(4,6,0)
@@ -70,12 +72,237 @@ import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
70-- in filenames, chapter0003.xhtml.
72-- in filenames, chapter0003.xhtml.
71data Chapter = Chapter (Maybe [Int]) [Block]
73data Chapter = Chapter (Maybe [Int]) [Block]
72
74
75+data EPUBMetadata = EPUBMetadata{
76+ epubIdentifier :: [Identifier]
77+ , epubTitle :: [Title]
78+ , epubDate :: String
79+ , epubLanguage :: String
80+ , epubCreator :: [Creator]
81+ , epubContributor :: [Creator]
82+ , epubSubject :: [String]
83+ , epubDescription :: Maybe String
84+ , epubType :: Maybe String
85+ , epubFormat :: Maybe String
86+ , epubPublisher :: Maybe String
87+ , epubSource :: Maybe String
88+ , epubRelation :: Maybe String
89+ , epubCoverage :: Maybe String
90+ , epubRights :: Maybe String
91+ , epubCoverImage :: Maybe String
92+ , epubStylesheet :: Maybe Stylesheet
93+ } deriving Show
94+
95+data Stylesheet = StylesheetPath FilePath
96+ | StylesheetContents String
97+ deriving Show
98+
99+data Creator = Creator{
100+ creatorText :: String
101+ , creatorRole :: Maybe String
102+ , creatorFileAs :: Maybe String
103+ } deriving Show
104+
105+data Identifier = Identifier{
106+ identifierText :: String
107+ , identifierScheme :: Maybe String
108+ } deriving Show
109+
110+data Title = Title{
111+ titleText :: String
112+ , titleFileAs :: Maybe String
113+ , titleType :: Maybe String
114+ } deriving Show
115+
116+dcName :: String -> QName
117+dcName n = QName n Nothing (Just "dc")
118+
119+dcNode :: Node t => String -> t -> Element
120+dcNode = node . dcName
121+
122+opfName :: String -> QName
123+opfName n = QName n Nothing (Just "opf")
124+
125+plainify :: [Inline] -> String
126+plainify t =
127+ trimr $ writePlain def{ writerStandalone = False }
128+ $ Pandoc nullMeta [Plain $ walk removeNote t]
129+
130+removeNote :: Inline -> Inline
131+removeNote (Note _) = Str ""
132+removeNote x = x
133+
134+getEPUBMetadata :: WriterOptions -> Meta -> IO EPUBMetadata
135+getEPUBMetadata opts meta = do
136+ let md = metadataFromMeta opts meta
137+ let elts = onlyElems $ parseXML $ writerEpubMetadata opts
138+ let md' = foldr addMetadataFromXML md elts
139+ let addIdentifier m =
140+ if null (epubIdentifier m)
141+ then do
142+ randomId <- fmap show getRandomUUID
143+ return $ m{ epubIdentifier = [Identifier randomId Nothing] }
144+ else return m
145+ let addLanguage m =
146+ if null (epubLanguage m)
147+ then case lookup "lang" (writerVariables opts) of
148+ Just x -> return m{ epubLanguage = x }
149+ Nothing -> do
150+ localeLang <- catch (liftM
151+ (map (\c -> if c == '_' then '-' else c) .
152+ takeWhile (/='.')) $ getEnv "LANG")
153+ (\e -> let _ = (e :: SomeException) in return "en-US")
154+ return m{ epubLanguage = localeLang }
155+ else return m
156+ let fixDate m =
157+ if null (epubDate m)
158+ then do
159+ currentTime <- getCurrentTime
160+ return $ m{ epubDate = showDateTimeISO8601 currentTime }
161+ else return m
162+ let addAuthor m =
163+ if any (\c -> creatorRole c == Just "aut") $ epubCreator m
164+ then return m
165+ else do
166+ let authors' = map plainify $ docAuthors meta
167+ let toAuthor name = Creator{ creatorText = name
168+ , creatorRole = Just "aut"
169+ , creatorFileAs = Nothing }
170+ return $ m{ epubCreator = map toAuthor authors' ++ epubCreator m }
171+ addIdentifier md' >>= fixDate >>= addAuthor >>= addLanguage
172+
173+addMetadataFromXML :: Element -> EPUBMetadata -> EPUBMetadata
174+addMetadataFromXML e@(Element (QName name _ (Just "dc")) attrs _ _) md
175+ | name == "identifier" = md{ epubIdentifier =
176+ Identifier{ identifierText = strContent e
177+ , identifierScheme = lookupAttr (opfName "scheme") attrs
178+ } : epubIdentifier md }
179+ | name == "title" = md{ epubTitle =
180+ Title{ titleText = strContent e
181+ , titleFileAs = getAttr "file-as"
182+ , titleType = getAttr "type"
183+ } : epubTitle md }
184+ | name == "date" = md{ epubDate = fromMaybe "" $ normalizeDate'
185+ $ strContent e }
186+ | name == "language" = md{ epubLanguage = strContent e }
187+ | name == "creator" = md{ epubCreator =
188+ Creator{ creatorText = strContent e
189+ , creatorRole = getAttr "role"
190+ , creatorFileAs = getAttr "file-as"
191+ } : epubCreator md }
192+ | name == "contributor" = md{ epubContributor =
193+ Creator { creatorText = strContent e
194+ , creatorRole = getAttr "role"
195+ , creatorFileAs = getAttr "file-as"
196+ } : epubContributor md }
197+ | name == "subject" = md{ epubSubject = strContent e : epubSubject md }
198+ | name == "description" = md { epubDescription = Just $ strContent e }
199+ | name == "type" = md { epubType = Just $ strContent e }
200+ | name == "format" = md { epubFormat = Just $ strContent e }
201+ | name == "type" = md { epubType = Just $ strContent e }
202+ | name == "publisher" = md { epubPublisher = Just $ strContent e }
203+ | name == "source" = md { epubSource = Just $ strContent e }
204+ | name == "relation" = md { epubRelation = Just $ strContent e }
205+ | name == "coverage" = md { epubCoverage = Just $ strContent e }
206+ | name == "rights" = md { epubRights = Just $ strContent e }
207+ | otherwise = md
208+ where getAttr n = lookupAttr (opfName n) attrs
209+addMetadataFromXML _ md = md
210+
211+metaValueToString :: MetaValue -> String
212+metaValueToString (MetaString s) = s
213+metaValueToString (MetaInlines ils) = plainify ils
214+metaValueToString (MetaBlocks bs) = plainify $ query (:[]) bs
215+metaValueToString (MetaBool b) = show b
216+metaValueToString _ = ""
217+
218+getList :: String -> Meta -> (MetaValue -> a) -> [a]
219+getList s meta handleMetaValue =
220+ case lookupMeta s meta of
221+ Just (MetaList xs) -> map handleMetaValue xs
222+ Just mv -> [handleMetaValue mv]
223+ Nothing -> []
224+
225+getIdentifier :: Meta -> [Identifier]
226+getIdentifier meta = getList "identifier" meta handleMetaValue
227+ where handleMetaValue (MetaMap m) =
228+ Identifier{ identifierText = maybe "" metaValueToString
229+ $ M.lookup "text" m
230+ , identifierScheme = metaValueToString <$>
231+ M.lookup "scheme" m }
232+ handleMetaValue mv = Identifier (metaValueToString mv) Nothing
233+
234+getTitle :: Meta -> [Title]
235+getTitle meta = getList "title" meta handleMetaValue
236+ where handleMetaValue (MetaMap m) =
237+ Title{ titleText = maybe "" metaValueToString $ M.lookup "text" m
238+ , titleFileAs = metaValueToString <$> M.lookup "file-as" m
239+ , titleType = metaValueToString <$> M.lookup "type" m }
240+ handleMetaValue mv = Title (metaValueToString mv) Nothing Nothing
241+
242+getCreator :: String -> Meta -> [Creator]
243+getCreator s meta = getList s meta handleMetaValue
244+ where handleMetaValue (MetaMap m) =
245+ Creator{ creatorText = maybe "" metaValueToString $ M.lookup "text" m
246+ , creatorFileAs = metaValueToString <$> M.lookup "file-as" m
247+ , creatorRole = metaValueToString <$> M.lookup "role" m }
248+ handleMetaValue mv = Creator (metaValueToString mv) Nothing Nothing
249+
250+simpleList :: String -> Meta -> [String]
251+simpleList s meta =
252+ case lookupMeta s meta of
253+ Just (MetaList xs) -> map metaValueToString xs
254+ Just x -> [metaValueToString x]
255+ Nothing -> []
256+
257+metadataFromMeta :: WriterOptions -> Meta -> EPUBMetadata
258+metadataFromMeta opts meta = EPUBMetadata{
259+ epubIdentifier = identifiers
260+ , epubTitle = titles
261+ , epubDate = date
262+ , epubLanguage = language
263+ , epubCreator = creators
264+ , epubContributor = contributors
265+ , epubSubject = subjects
266+ , epubDescription = description
267+ , epubType = epubtype
268+ , epubFormat = format
269+ , epubPublisher = publisher
270+ , epubSource = source
271+ , epubRelation = relation
272+ , epubCoverage = coverage
273+ , epubRights = rights
274+ , epubCoverImage = coverImage
275+ , epubStylesheet = stylesheet
276+ }
277+ where identifiers = getIdentifier meta
278+ titles = getTitle meta
279+ date = fromMaybe "" $
280+ (metaValueToString <$> lookupMeta "date" meta) >>= normalizeDate'
281+ language = maybe "" metaValueToString $
282+ lookupMeta "language" meta `mplus` lookupMeta "lang" meta
283+ creators = getCreator "creator" meta
284+ contributors = getCreator "contributor" meta
285+ subjects = simpleList "subject" meta
286+ description = metaValueToString <$> lookupMeta "description" meta
287+ epubtype = metaValueToString <$> lookupMeta "type" meta
288+ format = metaValueToString <$> lookupMeta "format" meta
289+ publisher = metaValueToString <$> lookupMeta "publisher" meta
290+ source = metaValueToString <$> lookupMeta "source" meta
291+ relation = metaValueToString <$> lookupMeta "relation" meta
292+ coverage = metaValueToString <$> lookupMeta "coverage" meta
293+ rights = metaValueToString <$> lookupMeta "rights" meta
294+ coverImage = lookup "epub-cover-image" (writerVariables opts) `mplus`
295+ (metaValueToString <$> lookupMeta "cover-image" meta)
296+ stylesheet = (StylesheetContents <$> writerEpubStylesheet opts) `mplus`
297+ ((StylesheetPath . metaValueToString) <$>
298+ lookupMeta "stylesheet" meta)
299+
73-- | Produce an EPUB file from a Pandoc document.
300-- | Produce an EPUB file from a Pandoc document.
74writeEPUB :: WriterOptions -- ^ Writer options
301writeEPUB :: WriterOptions -- ^ Writer options
75 -> Pandoc -- ^ Document to convert
302 -> Pandoc -- ^ Document to convert
76 -> IO B.ByteString
303 -> IO B.ByteString
77writeEPUB opts doc@(Pandoc meta _) = do
304writeEPUB opts doc@(Pandoc meta _) = do
78− let version = maybe EPUB2 id (writerEpubVersion opts)
305+ let version = fromMaybe EPUB2 (writerEpubVersion opts)
79 let epub3 = version == EPUB3
306 let epub3 = version == EPUB3
80 epochtime <- floor `fmap` getPOSIXTime
307 epochtime <- floor `fmap` getPOSIXTime
81 let mkEntry path content = toEntry path epochtime content
308 let mkEntry path content = toEntry path epochtime content
@@ -93,11 +320,11 @@ writeEPUB opts doc@(Pandoc meta _) = do
93 then MathML Nothing
320 then MathML Nothing
94 else writerHTMLMathMethod opts
321 else writerHTMLMathMethod opts
95 , writerWrapText = False }
322 , writerWrapText = False }
96− let mbCoverImage = lookup "epub-cover-image" vars
323+ metadata <- getEPUBMetadata opts' meta
97
324
98 -- cover page
325 -- cover page
99 (cpgEntry, cpicEntry) <-
326 (cpgEntry, cpicEntry) <-
100− case mbCoverImage of
327+ case epubCoverImage metadata of
101 Nothing -> return ([],[])
328 Nothing -> return ([],[])
102 Just img -> do
329 Just img -> do
103 let coverImage = "cover-image" ++ takeExtension img
330 let coverImage = "cover-image" ++ takeExtension img
@@ -179,32 +406,33 @@ writeEPUB opts doc@(Pandoc meta _) = do
179 chapToEntry num (Chapter mbnum bs) = mkEntry (showChapter num)
406 chapToEntry num (Chapter mbnum bs) = mkEntry (showChapter num)
180 $ renderHtml
407 $ renderHtml
181 $ writeHtml opts'{ writerNumberOffset =
408 $ writeHtml opts'{ writerNumberOffset =
182− maybe [] id mbnum }
409+ fromMaybe [] mbnum }
183 $ case bs of
410 $ case bs of
184 (Header _ _ xs : _) ->
411 (Header _ _ xs : _) ->
412+ -- remove notes or we get doubled footnotes
185− Pandoc (setMeta "title" (fromList xs) nullMeta) bs
413+ Pandoc (setMeta "title" (walk removeNote $ fromList xs)
414+ nullMeta) bs
186 _ ->
415 _ ->
187 Pandoc nullMeta bs
416 Pandoc nullMeta bs
188
417
189 let chapterEntries = zipWith chapToEntry [1..] chapters
418 let chapterEntries = zipWith chapToEntry [1..] chapters
190
419
191 -- incredibly inefficient (TODO):
420 -- incredibly inefficient (TODO):
421+ let containsMathML ent = epub3 &&
192− let containsMathML ent = "<math" `isInfixOf` (B8.unpack $ fromEntry ent)
422+ "<math" `isInfixOf` (B8.unpack $ fromEntry ent)
423+ let containsSVG ent = epub3 &&
424+ "<svg" `isInfixOf` (B8.unpack $ fromEntry ent)
425+ let props ent = ["mathml" | containsMathML ent] ++ ["svg" | containsSVG ent]
193
426
194 -- contents.opf
427 -- contents.opf
195− localeLang <- catch (liftM (map (\c -> if c == '_' then '-' else c) .
196− takeWhile (/='.')) $ getEnv "LANG")
197− (\e -> let _ = (e :: SomeException) in return "en-US")
198− let lang = case lookup "lang" (writerVariables opts') of
199− Just x -> x
200− Nothing -> localeLang
201− uuid <- getRandomUUID
202 let chapterNode ent = unode "item" !
428 let chapterNode ent = unode "item" !
203 ([("id", takeBaseName $ eRelativePath ent),
429 ([("id", takeBaseName $ eRelativePath ent),
204 ("href", eRelativePath ent),
430 ("href", eRelativePath ent),
205 ("media-type", "application/xhtml+xml")]
431 ("media-type", "application/xhtml+xml")]
432+ ++ case props ent of
433+ [] -> []
206− ++ [("properties","mathml") | epub3 &&
434+ xs -> [("properties", unwords xs)])
207− containsMathML ent]) $ ()
435+ $ ()
208 let chapterRefNode ent = unode "itemref" !
436 let chapterRefNode ent = unode "itemref" !
209 [("idref", takeBaseName $ eRelativePath ent)] $ ()
437 [("idref", takeBaseName $ eRelativePath ent)] $ ()
210 let pictureNode ent = unode "item" !
438 let pictureNode ent = unode "item" !
@@ -215,23 +443,23 @@ writeEPUB opts doc@(Pandoc meta _) = do
215 let fontNode ent = unode "item" !
443 let fontNode ent = unode "item" !
216 [("id", takeBaseName $ eRelativePath ent),
444 [("id", takeBaseName $ eRelativePath ent),
217 ("href", eRelativePath ent),
445 ("href", eRelativePath ent),
218− ("media-type", maybe "" id $ getMimeType $ eRelativePath ent)] $ ()
446+ ("media-type", fromMaybe "" $ getMimeType $ eRelativePath ent)] $ ()
219− let plainify t = trimr $
220− writePlain opts'{ writerStandalone = False } $
221− Pandoc meta [Plain t]
222− let plainTitle = plainify $ docTitle meta
447+ let plainTitle = case docTitle meta of
223− let plainAuthors = map plainify $ docAuthors meta
448+ [] -> case epubTitle metadata of
449+ [] -> "UNTITLED"
450+ (x:_) -> titleText x
451+ x -> plainify x
452+ let uuid = case epubIdentifier metadata of
453+ (x:_) -> identifierText x -- use first identifier as UUID
454+ [] -> error "epubIdentifier is null" -- shouldn't happen
224 currentTime <- getCurrentTime
455 currentTime <- getCurrentTime
225− let plainDate = maybe (showDateTimeISO8601 currentTime) id
226− $ normalizeDate $ stringify $ docDate meta
227− let contentsData = fromStringLazy $ ppTopElement $
456+ let contentsData = UTF8.fromStringLazy $ ppTopElement $
228 unode "package" ! [("version", case version of
457 unode "package" ! [("version", case version of
229 EPUB2 -> "2.0"
458 EPUB2 -> "2.0"
230 EPUB3 -> "3.0")
459 EPUB3 -> "3.0")
231 ,("xmlns","http://www.idpf.org/2007/opf")
460 ,("xmlns","http://www.idpf.org/2007/opf")
232− ,("unique-identifier","BookId")] $
461+ ,("unique-identifier","epub-id-1")] $
233− [ metadataElement version (writerEpubMetadata opts')
462+ [ metadataElement version metadata currentTime
234− uuid lang plainTitle plainAuthors plainDate currentTime mbCoverImage
235 , unode "manifest" $
463 , unode "manifest" $
236 [ unode "item" ! [("id","ncx"), ("href","toc.ncx")
464 [ unode "item" ! [("id","ncx"), ("href","toc.ncx")
237 ,("media-type","application/x-dtbncx+xml")] $ ()
465 ,("media-type","application/x-dtbncx+xml")] $ ()
@@ -243,10 +471,15 @@ writeEPUB opts doc@(Pandoc meta _) = do
243 [("properties","nav") | epub3 ]) $ ()
471 [("properties","nav") | epub3 ]) $ ()
244 ] ++
472 ] ++
245 map chapterNode (cpgEntry ++ (tpEntry : chapterEntries)) ++
473 map chapterNode (cpgEntry ++ (tpEntry : chapterEntries)) ++
474+ (case cpicEntry of
475+ [] -> []
476+ (x:_) -> [add_attrs
477+ [Attr (unqual "properties") "cover-image" | epub3]
478+ (pictureNode x)]) ++
246− map pictureNode (cpicEntry ++ picEntries) ++
479+ map pictureNode picEntries ++
247 map fontNode fontEntries
480 map fontNode fontEntries
248 , unode "spine" ! [("toc","ncx")] $
481 , unode "spine" ! [("toc","ncx")] $
249− case mbCoverImage of
482+ case epubCoverImage metadata of
250 Nothing -> []
483 Nothing -> []
251 Just _ -> [ unode "itemref" !
484 Just _ -> [ unode "itemref" !
252 [("idref", "cover"),("linear","no")] $ () ]
485 [("idref", "cover"),("linear","no")] $ () ]
@@ -260,8 +493,13 @@ writeEPUB opts doc@(Pandoc meta _) = do
260 else "no")] $ ()) :
493 else "no")] $ ()) :
261 map chapterRefNode chapterEntries)
494 map chapterRefNode chapterEntries)
262 , unode "guide" $
495 , unode "guide" $
263− unode "reference" !
496+ [ unode "reference" !
264− [("type","toc"),("title",plainTitle),("href","nav.xhtml")] $ ()
497+ [("type","toc"),("title",plainTitle),
498+ ("href","nav.xhtml")] $ ()
499+ ] ++
500+ [ unode "reference" !
501+ [("type","cover"),("title","Cover"),("href","cover.xhtml")] $ () | epubCoverImage metadata /= Nothing
502+ ]
265 ]
503 ]
266 let contentsEntry = mkEntry "content.opf" contentsData
504 let contentsEntry = mkEntry "content.opf" contentsData
267
505
@@ -303,19 +541,19 @@ writeEPUB opts doc@(Pandoc meta _) = do
303 [ unode "navLabel" $ unode "text" (plainify $ docTitle meta)
541 [ unode "navLabel" $ unode "text" (plainify $ docTitle meta)
304 , unode "content" ! [("src","title_page.xhtml")] $ () ]
542 , unode "content" ! [("src","title_page.xhtml")] $ () ]
305
543
306− let tocData = fromStringLazy $ ppTopElement $
544+ let tocData = UTF8.fromStringLazy $ ppTopElement $
307 unode "ncx" ! [("version","2005-1")
545 unode "ncx" ! [("version","2005-1")
308 ,("xmlns","http://www.daisy.org/z3986/2005/ncx/")] $
546 ,("xmlns","http://www.daisy.org/z3986/2005/ncx/")] $
309 [ unode "head" $
547 [ unode "head" $
310 [ unode "meta" ! [("name","dtb:uid")
548 [ unode "meta" ! [("name","dtb:uid")
311− ,("content", show uuid)] $ ()
549+ ,("content", uuid)] $ ()
312 , unode "meta" ! [("name","dtb:depth")
550 , unode "meta" ! [("name","dtb:depth")
313 ,("content", "1")] $ ()
551 ,("content", "1")] $ ()
314 , unode "meta" ! [("name","dtb:totalPageCount")
552 , unode "meta" ! [("name","dtb:totalPageCount")
315 ,("content", "0")] $ ()
553 ,("content", "0")] $ ()
316 , unode "meta" ! [("name","dtb:maxPageNumber")
554 , unode "meta" ! [("name","dtb:maxPageNumber")
317 ,("content", "0")] $ ()
555 ,("content", "0")] $ ()
318− ] ++ case mbCoverImage of
556+ ] ++ case epubCoverImage metadata of
319 Nothing -> []
557 Nothing -> []
320 Just _ -> [unode "meta" ! [("name","cover"),
558 Just _ -> [unode "meta" ! [("name","cover"),
321 ("content","cover-image")] $ ()]
559 ("content","cover-image")] $ ()]
@@ -335,7 +573,7 @@ writeEPUB opts doc@(Pandoc meta _) = do
335 (_:_) -> [unode "ol" ! [("class","toc")] $ subs]
573 (_:_) -> [unode "ol" ! [("class","toc")] $ subs]
336
574
337 let navtag = if epub3 then "nav" else "div"
575 let navtag = if epub3 then "nav" else "div"
338− let navData = fromStringLazy $ ppTopElement $
576+ let navData = UTF8.fromStringLazy $ ppTopElement $
339 unode "html" ! [("xmlns","http://www.w3.org/1999/xhtml")
577 unode "html" ! [("xmlns","http://www.w3.org/1999/xhtml")
340 ,("xmlns:epub","http://www.idpf.org/2007/ops")] $
578 ,("xmlns:epub","http://www.idpf.org/2007/ops")] $
341 [ unode "head" $
579 [ unode "head" $
@@ -349,10 +587,10 @@ writeEPUB opts doc@(Pandoc meta _) = do
349 let navEntry = mkEntry "nav.xhtml" navData
587 let navEntry = mkEntry "nav.xhtml" navData
350
588
351 -- mimetype
589 -- mimetype
352− let mimetypeEntry = mkEntry "mimetype" $ fromStringLazy "application/epub+zip"
590+ let mimetypeEntry = mkEntry "mimetype" $ UTF8.fromStringLazy "application/epub+zip"
353
591
354 -- container.xml
592 -- container.xml
355− let containerData = fromStringLazy $ ppTopElement $
593+ let containerData = UTF8.fromStringLazy $ ppTopElement $
356 unode "container" ! [("version","1.0")
594 unode "container" ! [("version","1.0")
357 ,("xmlns","urn:oasis:names:tc:opendocument:xmlns:container")] $
595 ,("xmlns","urn:oasis:names:tc:opendocument:xmlns:container")] $
358 unode "rootfiles" $
596 unode "rootfiles" $
@@ -361,18 +599,19 @@ writeEPUB opts doc@(Pandoc meta _) = do
361 let containerEntry = mkEntry "META-INF/container.xml" containerData
599 let containerEntry = mkEntry "META-INF/container.xml" containerData
362
600
363 -- com.apple.ibooks.display-options.xml
601 -- com.apple.ibooks.display-options.xml
364− let apple = fromStringLazy $ ppTopElement $
602+ let apple = UTF8.fromStringLazy $ ppTopElement $
365 unode "display_options" $
603 unode "display_options" $
366 unode "platform" ! [("name","*")] $
604 unode "platform" ! [("name","*")] $
367 unode "option" ! [("name","specified-fonts")] $ "true"
605 unode "option" ! [("name","specified-fonts")] $ "true"
368 let appleEntry = mkEntry "META-INF/com.apple.ibooks.display-options.xml" apple
606 let appleEntry = mkEntry "META-INF/com.apple.ibooks.display-options.xml" apple
369
607
370 -- stylesheet
608 -- stylesheet
371− stylesheet <- case writerEpubStylesheet opts of
609+ stylesheet <- case epubStylesheet metadata of
372− Just s -> return s
610+ Just (StylesheetPath fp) -> UTF8.readFile fp
611+ Just (StylesheetContents s) -> return s
373− Nothing -> toString `fmap`
612+ Nothing -> UTF8.toString `fmap`
374 readDataFile (writerUserDataDir opts) "epub.css"
613 readDataFile (writerUserDataDir opts) "epub.css"
375− let stylesheetEntry = mkEntry "stylesheet.css" $ fromStringLazy stylesheet
614+ let stylesheetEntry = mkEntry "stylesheet.css" $ UTF8.fromStringLazy stylesheet
376
615
377 -- construct archive
616 -- construct archive
378 let archive = foldr addEntryToArchive emptyArchive
617 let archive = foldr addEntryToArchive emptyArchive
@@ -381,33 +620,97 @@ writeEPUB opts doc@(Pandoc meta _) = do
381 (picEntries ++ cpicEntry ++ cpgEntry ++ chapterEntries ++ fontEntries))
620 (picEntries ++ cpicEntry ++ cpgEntry ++ chapterEntries ++ fontEntries))
382 return $ fromArchive archive
621 return $ fromArchive archive
383
622
384−metadataElement :: EPUBVersion -> String -> UUID -> String -> String -> [String]
623+metadataElement :: EPUBVersion -> EPUBMetadata -> UTCTime -> Element
385− -> String -> UTCTime -> Maybe a -> Element
386−metadataElement version metadataXML uuid lang title authors date currentTime mbCoverImage =
624+metadataElement version md currentTime =
387− let userNodes = parseXML metadataXML
388− elt = unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/")
625+ unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/")
389− ,("xmlns:opf","http://www.idpf.org/2007/opf")] $
626+ ,("xmlns:opf","http://www.idpf.org/2007/opf")] $ mdNodes
390− filter isMetadataElement $ onlyElems userNodes
627+ where mdNodes = identifierNodes ++ titleNodes ++ dateNodes ++ languageNodes
391− dublinElements = ["contributor","coverage","creator","date",
628+ ++ creatorNodes ++ contributorNodes ++ subjectNodes
392− "description","format","identifier","language","publisher",
629+ ++ descriptionNodes ++ typeNodes ++ formatNodes
393− "relation","rights","source","subject","title","type"]
630+ ++ publisherNodes ++ sourceNodes ++ relationNodes
394− isMetadataElement e = (qPrefix (elName e) == Just "dc" &&
631+ ++ coverageNodes ++ rightsNodes ++ coverImageNodes
395− qName (elName e) `elem` dublinElements) ||
632+ ++ modifiedNodes
396− (qPrefix (elName e) == Nothing &&
633+ withIds base f = concat . zipWith f (map (\x -> base ++ ('-' : show x))
397− qName (elName e) `elem` ["link","meta"])
634+ ([1..] :: [Int]))
398− contains e n = not (null (findElements (QName n Nothing (Just "dc")) e))
635+ identifierNodes = withIds "epub-id" toIdentifierNode $
399− newNodes = [ unode "dc:title" title | not (elt `contains` "title") ] ++
636+ epubIdentifier md
400− [ unode "dc:language" lang | not (elt `contains` "language") ] ++
637+ titleNodes = withIds "epub-title" toTitleNode $ epubTitle md
401− [ unode "dc:identifier" ! [("id","BookId")] $ show uuid |
638+ dateNodes = dcTag' "date" $ epubDate md
402− not (elt `contains` "identifier") ] ++
639+ languageNodes = [dcTag "language" $ epubLanguage md]
403− [ unode "dc:creator" ! [("opf:role","aut") | version == EPUB2]
640+ creatorNodes = withIds "epub-creator" (toCreatorNode "creator") $
404− $ a | a <- authors, not (elt `contains` "creator") ] ++
641+ epubCreator md
405− [ unode "dc:date" date | not (elt `contains` "date") ] ++
642+ contributorNodes = withIds "epub-contributor"
643+ (toCreatorNode "contributor") $ epubContributor md
644+ subjectNodes = map (dcTag "subject") $ epubSubject md
645+ descriptionNodes = maybe [] (dcTag' "description") $ epubDescription md
646+ typeNodes = maybe [] (dcTag' "type") $ epubType md
647+ formatNodes = maybe [] (dcTag' "format") $ epubFormat md
648+ publisherNodes = maybe [] (dcTag' "publisher") $ epubPublisher md
649+ sourceNodes = maybe [] (dcTag' "source") $ epubSource md
650+ relationNodes = maybe [] (dcTag' "relation") $ epubRelation md
651+ coverageNodes = maybe [] (dcTag' "coverage") $ epubCoverage md
652+ rightsNodes = maybe [] (dcTag' "rights") $ epubRights md
653+ coverImageNodes = maybe []
654+ (const $ [unode "meta" ! [("name","cover"),
655+ ("content","cover-image")] $ ()])
656+ $ epubCoverImage md
406− [ unode "meta" ! [("property", "dcterms:modified")] $
657+ modifiedNodes = [ unode "meta" ! [("property", "dcterms:modified")] $
407− (showDateTimeISO8601 currentTime) | version == EPUB3] ++
658+ (showDateTimeISO8601 currentTime) | version == EPUB3 ]
408− [ unode "meta" ! [("name","cover"), ("content","cover-image")] $ () |
659+ dcTag n s = unode ("dc:" ++ n) s
409− not (isNothing mbCoverImage) ]
660+ dcTag' n s = [dcTag n s]
410− in elt{ elContent = elContent elt ++ map Elem newNodes }
661+ toIdentifierNode id' (Identifier txt scheme)
662+ | version == EPUB2 = [dcNode "identifier" !
663+ ([("id",id')] ++ maybe [] (\x -> [("opf:scheme", x)]) scheme) $
664+ txt]
665+ | otherwise = [dcNode "identifier" ! [("id",id')] $ txt] ++
666+ maybe [] (\x -> [unode "meta" !
667+ [("refines",'#':id'),("property","identifier-type"),
668+ ("scheme","onix:codelist5")] $ x])
669+ (schemeToOnix `fmap` scheme)
670+ toCreatorNode s id' creator
671+ | version == EPUB2 = [dcNode s !
672+ ([("id",id')] ++
673+ maybe [] (\x -> [("opf:file-as",x)]) (creatorFileAs creator) ++
674+ maybe [] (\x -> [("opf:role",x)])
675+ (creatorRole creator >>= toRelator)) $ creatorText creator]
676+ | otherwise = [dcNode s ! [("id",id')] $ creatorText creator] ++
677+ maybe [] (\x -> [unode "meta" !
678+ [("refines",'#':id'),("property","file-as")] $ x])
679+ (creatorFileAs creator) ++
680+ maybe [] (\x -> [unode "meta" !
681+ [("refines",'#':id'),("property","role"),
682+ ("scheme","marc:relators")] $ x])
683+ (creatorRole creator >>= toRelator)
684+ toTitleNode id' title
685+ | version == EPUB2 = [dcNode "title" !
686+ ([("id",id')] ++
687+ maybe [] (\x -> [("opf:file-as",x)]) (titleFileAs title) ++
688+ maybe [] (\x -> [("opf:title-type",x)]) (titleType title)) $
689+ titleText title]
690+ | otherwise = [dcNode "title" ! [("id",id')] $ titleText title]
691+ ++
692+ maybe [] (\x -> [unode "meta" !
693+ [("refines",'#':id'),("property","file-as")] $ x])
694+ (titleFileAs title) ++
695+ maybe [] (\x -> [unode "meta" !
696+ [("refines",'#':id'),("property","title-type")] $ x])
697+ (titleType title)
698+ schemeToOnix "ISBN-10" = "02"
699+ schemeToOnix "GTIN-13" = "03"
700+ schemeToOnix "UPC" = "04"
701+ schemeToOnix "ISMN-10" = "05"
702+ schemeToOnix "DOI" = "06"
703+ schemeToOnix "LCCN" = "13"
704+ schemeToOnix "GTIN-14" = "14"
705+ schemeToOnix "ISBN-13" = "15"
706+ schemeToOnix "Legal deposit number" = "17"
707+ schemeToOnix "URN" = "22"
708+ schemeToOnix "OCLC" = "23"
709+ schemeToOnix "ISMN-13" = "25"
710+ schemeToOnix "ISBN-A" = "26"
711+ schemeToOnix "JP" = "27"
712+ schemeToOnix "OLCC" = "28"
713+ schemeToOnix _ = "01"
411
714
412showDateTimeISO8601 :: UTCTime -> String
715showDateTimeISO8601 :: UTCTime -> String
413showDateTimeISO8601 = formatTime defaultTimeLocale "%FT%TZ"
716showDateTimeISO8601 = formatTime defaultTimeLocale "%FT%TZ"
@@ -457,15 +760,9 @@ ppTopElement = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++) . unEntity .
457 unEntity (x:xs) = x : unEntity xs
760 unEntity (x:xs) = x : unEntity xs
458
761
459imageTypeOf :: FilePath -> Maybe String
762imageTypeOf :: FilePath -> Maybe String
460−imageTypeOf x = case drop 1 (map toLower (takeExtension x)) of
763+imageTypeOf x = case getMimeType x of
461− "jpg" -> Just "image/jpeg"
764+ Just y@('i':'m':'a':'g':'e':_) -> Just y
462− "jpeg" -> Just "image/jpeg"
463− "jfif" -> Just "image/jpeg"
464− "png" -> Just "image/png"
465− "gif" -> Just "image/gif"
466− "svg" -> Just "image/svg+xml"
467− _ -> Nothing
765+ _ -> Nothing
468−
469
766
470data IdentState = IdentState{
767data IdentState = IdentState{
471 chapterNumber :: Int,
768 chapterNumber :: Int,
@@ -519,3 +816,287 @@ replaceRefs refTable = walk replaceOneRef
519 Just url -> Link lab (url,tit)
816 Just url -> Link lab (url,tit)
520 Nothing -> x
817 Nothing -> x
521 replaceOneRef x = x
818 replaceOneRef x = x
819+
820+-- Variant of normalizeDate that allows partial dates: YYYY, YYYY-MM
821+normalizeDate' :: String -> Maybe String
822+normalizeDate' xs =
823+ let xs' = trim xs in
824+ case xs' of
825+ [y1,y2,y3,y4] | all isDigit [y1,y2,y3,y4] -> Just xs' -- YYYY
826+ [y1,y2,y3,y4,'-',m1,m2] | all isDigit [y1,y2,y3,y4,m1,m2] -- YYYY-MM
827+ -> Just xs'
828+ _ -> normalizeDate xs'
829+
830+toRelator :: String -> Maybe String
831+toRelator x
832+ | x `elem` relators = Just x
833+ | otherwise = lookup (map toLower x) relatorMap
834+
835+relators :: [String]
836+relators = map snd relatorMap
837+
838+relatorMap :: [(String, String)]
839+relatorMap =
840+ [("abridger", "abr")
841+ ,("actor", "act")
842+ ,("adapter", "adp")
843+ ,("addressee", "rcp")
844+ ,("analyst", "anl")
845+ ,("animator", "anm")
846+ ,("annotator", "ann")
847+ ,("appellant", "apl")
848+ ,("appellee", "ape")
849+ ,("applicant", "app")
850+ ,("architect", "arc")
851+ ,("arranger", "arr")
852+ ,("art copyist", "acp")
853+ ,("art director", "adi")
854+ ,("artist", "art")
855+ ,("artistic director", "ard")
856+ ,("assignee", "asg")
857+ ,("associated name", "asn")
858+ ,("attributed name", "att")
859+ ,("auctioneer", "auc")
860+ ,("author", "aut")
861+ ,("author in quotations or text abstracts", "aqt")
862+ ,("author of afterword, colophon, etc.", "aft")
863+ ,("author of dialog", "aud")
864+ ,("author of introduction, etc.", "aui")
865+ ,("autographer", "ato")
866+ ,("bibliographic antecedent", "ant")
867+ ,("binder", "bnd")
868+ ,("binding designer", "bdd")
869+ ,("blurb writer", "blw")
870+ ,("book designer", "bkd")
871+ ,("book producer", "bkp")
872+ ,("bookjacket designer", "bjd")
873+ ,("bookplate designer", "bpd")
874+ ,("bookseller", "bsl")
875+ ,("braille embosser", "brl")
876+ ,("broadcaster", "brd")
877+ ,("calligrapher", "cll")
878+ ,("cartographer", "ctg")
879+ ,("caster", "cas")
880+ ,("censor", "cns")
881+ ,("choreographer", "chr")
882+ ,("cinematographer", "cng")
883+ ,("client", "cli")
884+ ,("collection registrar", "cor")
885+ ,("collector", "col")
886+ ,("collotyper", "clt")
887+ ,("colorist", "clr")
888+ ,("commentator", "cmm")
889+ ,("commentator for written text", "cwt")
890+ ,("compiler", "com")
891+ ,("complainant", "cpl")
892+ ,("complainant-appellant", "cpt")
893+ ,("complainant-appellee", "cpe")
894+ ,("composer", "cmp")
895+ ,("compositor", "cmt")
896+ ,("conceptor", "ccp")
897+ ,("conductor", "cnd")
898+ ,("conservator", "con")
899+ ,("consultant", "csl")
900+ ,("consultant to a project", "csp")
901+ ,("contestant", "cos")
902+ ,("contestant-appellant", "cot")
903+ ,("contestant-appellee", "coe")
904+ ,("contestee", "cts")
905+ ,("contestee-appellant", "ctt")
906+ ,("contestee-appellee", "cte")
907+ ,("contractor", "ctr")
908+ ,("contributor", "ctb")
909+ ,("copyright claimant", "cpc")
910+ ,("copyright holder", "cph")
911+ ,("corrector", "crr")
912+ ,("correspondent", "crp")
913+ ,("costume designer", "cst")
914+ ,("court governed", "cou")
915+ ,("court reporter", "crt")
916+ ,("cover designer", "cov")
917+ ,("creator", "cre")
918+ ,("curator", "cur")
919+ ,("dancer", "dnc")
920+ ,("data contributor", "dtc")
921+ ,("data manager", "dtm")
922+ ,("dedicatee", "dte")
923+ ,("dedicator", "dto")
924+ ,("defendant", "dfd")
925+ ,("defendant-appellant", "dft")
926+ ,("defendant-appellee", "dfe")
927+ ,("degree granting institution", "dgg")
928+ ,("delineator", "dln")
929+ ,("depicted", "dpc")
930+ ,("depositor", "dpt")
931+ ,("designer", "dsr")
932+ ,("director", "drt")
933+ ,("dissertant", "dis")
934+ ,("distribution place", "dbp")
935+ ,("distributor", "dst")
936+ ,("donor", "dnr")
937+ ,("draftsman", "drm")
938+ ,("dubious author", "dub")
939+ ,("editor", "edt")
940+ ,("editor of compilation", "edc")
941+ ,("editor of moving image work", "edm")
942+ ,("electrician", "elg")
943+ ,("electrotyper", "elt")
944+ ,("enacting jurisdiction", "enj")
945+ ,("engineer", "eng")
946+ ,("engraver", "egr")
947+ ,("etcher", "etr")
948+ ,("event place", "evp")
949+ ,("expert", "exp")
950+ ,("facsimilist", "fac")
951+ ,("field director", "fld")
952+ ,("film director", "fmd")
953+ ,("film distributor", "fds")
954+ ,("film editor", "flm")
955+ ,("film producer", "fmp")
956+ ,("filmmaker", "fmk")
957+ ,("first party", "fpy")
958+ ,("forger", "frg")
959+ ,("former owner", "fmo")
960+ ,("funder", "fnd")
961+ ,("geographic information specialist", "gis")
962+ ,("honoree", "hnr")
963+ ,("host", "hst")
964+ ,("host institution", "his")
965+ ,("illuminator", "ilu")
966+ ,("illustrator", "ill")
967+ ,("inscriber", "ins")
968+ ,("instrumentalist", "itr")
969+ ,("interviewee", "ive")
970+ ,("interviewer", "ivr")
971+ ,("inventor", "inv")
972+ ,("issuing body", "isb")
973+ ,("judge", "jud")
974+ ,("jurisdiction governed", "jug")
975+ ,("laboratory", "lbr")
976+ ,("laboratory director", "ldr")
977+ ,("landscape architect", "lsa")
978+ ,("lead", "led")
979+ ,("lender", "len")
980+ ,("libelant", "lil")
981+ ,("libelant-appellant", "lit")
982+ ,("libelant-appellee", "lie")
983+ ,("libelee", "lel")
984+ ,("libelee-appellant", "let")
985+ ,("libelee-appellee", "lee")
986+ ,("librettist", "lbt")
987+ ,("licensee", "lse")
988+ ,("licensor", "lso")
989+ ,("lighting designer", "lgd")
990+ ,("lithographer", "ltg")
991+ ,("lyricist", "lyr")
992+ ,("manufacture place", "mfp")
993+ ,("manufacturer", "mfr")
994+ ,("marbler", "mrb")
995+ ,("markup editor", "mrk")
996+ ,("metadata contact", "mdc")
997+ ,("metal-engraver", "mte")
998+ ,("moderator", "mod")
999+ ,("monitor", "mon")
1000+ ,("music copyist", "mcp")
1001+ ,("musical director", "msd")
1002+ ,("musician", "mus")
1003+ ,("narrator", "nrt")
1004+ ,("onscreen presenter", "osp")
1005+ ,("opponent", "opn")
1006+ ,("organizer of meeting", "orm")
1007+ ,("originator", "org")
1008+ ,("other", "oth")
1009+ ,("owner", "own")
1010+ ,("panelist", "pan")
1011+ ,("papermaker", "ppm")
1012+ ,("patent applicant", "pta")
1013+ ,("patent holder", "pth")
1014+ ,("patron", "pat")
1015+ ,("performer", "prf")
1016+ ,("permitting agency", "pma")
1017+ ,("photographer", "pht")
1018+ ,("plaintiff", "ptf")
1019+ ,("plaintiff-appellant", "ptt")
1020+ ,("plaintiff-appellee", "pte")
1021+ ,("platemaker", "plt")
1022+ ,("praeses", "pra")
1023+ ,("presenter", "pre")
1024+ ,("printer", "prt")
1025+ ,("printer of plates", "pop")
1026+ ,("printmaker", "prm")
1027+ ,("process contact", "prc")
1028+ ,("producer", "pro")
1029+ ,("production company", "prn")
1030+ ,("production designer", "prs")
1031+ ,("production manager", "pmn")
1032+ ,("production personnel", "prd")
1033+ ,("production place", "prp")
1034+ ,("programmer", "prg")
1035+ ,("project director", "pdr")
1036+ ,("proofreader", "pfr")
1037+ ,("provider", "prv")
1038+ ,("publication place", "pup")
1039+ ,("publisher", "pbl")
1040+ ,("publishing director", "pbd")
1041+ ,("puppeteer", "ppt")
1042+ ,("radio director", "rdd")
1043+ ,("radio producer", "rpc")
1044+ ,("recording engineer", "rce")
1045+ ,("recordist", "rcd")
1046+ ,("redaktor", "red")
1047+ ,("renderer", "ren")
1048+ ,("reporter", "rpt")
1049+ ,("repository", "rps")
1050+ ,("research team head", "rth")
1051+ ,("research team member", "rtm")
1052+ ,("researcher", "res")
1053+ ,("respondent", "rsp")
1054+ ,("respondent-appellant", "rst")
1055+ ,("respondent-appellee", "rse")
1056+ ,("responsible party", "rpy")
1057+ ,("restager", "rsg")
1058+ ,("restorationist", "rsr")
1059+ ,("reviewer", "rev")
1060+ ,("rubricator", "rbr")
1061+ ,("scenarist", "sce")
1062+ ,("scientific advisor", "sad")
1063+ ,("screenwriter", "aus")
1064+ ,("scribe", "scr")
1065+ ,("sculptor", "scl")
1066+ ,("second party", "spy")
1067+ ,("secretary", "sec")
1068+ ,("seller", "sll")
1069+ ,("set designer", "std")
1070+ ,("setting", "stg")
1071+ ,("signer", "sgn")
1072+ ,("singer", "sng")
1073+ ,("sound designer", "sds")
1074+ ,("speaker", "spk")
1075+ ,("sponsor", "spn")
1076+ ,("stage director", "sgd")
1077+ ,("stage manager", "stm")
1078+ ,("standards body", "stn")
1079+ ,("stereotyper", "str")
1080+ ,("storyteller", "stl")
1081+ ,("supporting host", "sht")
1082+ ,("surveyor", "srv")
1083+ ,("teacher", "tch")
1084+ ,("technical director", "tcd")
1085+ ,("television director", "tld")
1086+ ,("television producer", "tlp")
1087+ ,("thesis advisor", "ths")
1088+ ,("transcriber", "trc")
1089+ ,("translator", "trl")
1090+ ,("type designer", "tyd")
1091+ ,("typographer", "tyg")
1092+ ,("university place", "uvp")
1093+ ,("videographer", "vdg")
1094+ ,("witness", "wit")
1095+ ,("wood engraver", "wde")
1096+ ,("woodcutter", "wdc")
1097+ ,("writer of accompanying material", "wam")
1098+ ,("writer of added commentary", "wac")
1099+ ,("writer of added lyrics", "wal")
1100+ ,("writer of added text", "wat")
1101+ ]
1102+
src/Text/Pandoc/Writers/FB2.hs+2−4
@@ -44,7 +44,7 @@ import qualified Text.XML.Light.Cursor as XC
44
44
45import Text.Pandoc.Definition
45import Text.Pandoc.Definition
46import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)
46import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)
47−import Text.Pandoc.Shared (orderedListMarkers)
47+import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock)
48import Text.Pandoc.Walk
48import Text.Pandoc.Walk
49
49
50-- | Data to be written at the end of the document:
50-- | Data to be written at the end of the document:
@@ -157,9 +157,7 @@ renderSection level (ttl, body) = do
157 else cMapM blockToXml body
157 else cMapM blockToXml body
158 return $ el "section" (title ++ content)
158 return $ el "section" (title ++ content)
159 where
159 where
160− hasSubsections = any isHeader
160+ hasSubsections = any isHeaderBlock
161− isHeader (Header _ _ _) = True
162− isHeader _ = False
163
161
164-- | Only <p> and <empty-line> are allowed within <title> in FB2.
162-- | Only <p> and <empty-line> are allowed within <title> in FB2.
165formatTitle :: [Inline] -> [Content]
163formatTitle :: [Inline] -> [Content]
src/Text/Pandoc/Writers/HTML.hs+34−25
@@ -45,7 +45,7 @@ import Numeric ( showHex )
45import Data.Char ( ord, toLower )
45import Data.Char ( ord, toLower )
46import Data.List ( isPrefixOf, intersperse )
46import Data.List ( isPrefixOf, intersperse )
47import Data.String ( fromString )
47import Data.String ( fromString )
48−import Data.Maybe ( catMaybes )
48+import Data.Maybe ( catMaybes, fromMaybe )
49import Control.Monad.State
49import Control.Monad.State
50import Text.Blaze.Html hiding(contents)
50import Text.Blaze.Html hiding(contents)
51import Text.Blaze.Internal(preEscapedString)
51import Text.Blaze.Internal(preEscapedString)
@@ -118,7 +118,7 @@ pandocToHtml opts (Pandoc meta blocks) = do
118 let stringifyHTML = escapeStringForXML . stringify
118 let stringifyHTML = escapeStringForXML . stringify
119 let authsMeta = map stringifyHTML $ docAuthors meta
119 let authsMeta = map stringifyHTML $ docAuthors meta
120 let dateMeta = stringifyHTML $ docDate meta
120 let dateMeta = stringifyHTML $ docDate meta
121− let slideLevel = maybe (getSlideLevel blocks) id $ writerSlideLevel opts
121+ let slideLevel = fromMaybe (getSlideLevel blocks) $ writerSlideLevel opts
122 let sects = hierarchicalize $
122 let sects = hierarchicalize $
123 if writerSlideVariant opts == NoSlides
123 if writerSlideVariant opts == NoSlides
124 then blocks
124 then blocks
@@ -475,28 +475,21 @@ blockToHtml opts (BlockQuote blocks) =
475 else do
475 else do
476 contents <- blockListToHtml opts blocks
476 contents <- blockListToHtml opts blocks
477 return $ H.blockquote $ nl opts >> contents >> nl opts
477 return $ H.blockquote $ nl opts >> contents >> nl opts
478−blockToHtml opts (Header level (ident,_,_) lst) = do
478+blockToHtml opts (Header level (_,_,_) lst) = do
479 contents <- inlineListToHtml opts lst
479 contents <- inlineListToHtml opts lst
480 secnum <- liftM stSecNum get
480 secnum <- liftM stSecNum get
481 let contents' = if writerNumberSections opts && not (null secnum)
481 let contents' = if writerNumberSections opts && not (null secnum)
482 then (H.span ! A.class_ "header-section-number" $ toHtml
482 then (H.span ! A.class_ "header-section-number" $ toHtml
483 $ showSecNum secnum) >> strToHtml " " >> contents
483 $ showSecNum secnum) >> strToHtml " " >> contents
484 else contents
484 else contents
485− let revealSlash = ['/' | writerSlideVariant opts == RevealJsSlides]
486− let contents'' = if writerTableOfContents opts && not (null ident)
487− then H.a ! A.href (toValue $
488− '#' : revealSlash ++
489− writerIdentifierPrefix opts ++
490− ident) $ contents'
491− else contents'
492 return $ case level of
485 return $ case level of
493− 1 -> H.h1 contents''
486+ 1 -> H.h1 contents'
494− 2 -> H.h2 contents''
487+ 2 -> H.h2 contents'
495− 3 -> H.h3 contents''
488+ 3 -> H.h3 contents'
496− 4 -> H.h4 contents''
489+ 4 -> H.h4 contents'
497− 5 -> H.h5 contents''
490+ 5 -> H.h5 contents'
498− 6 -> H.h6 contents''
491+ 6 -> H.h6 contents'
499− _ -> H.p contents''
492+ _ -> H.p contents'
500blockToHtml opts (BulletList lst) = do
493blockToHtml opts (BulletList lst) = do
501 contents <- mapM (blockListToHtml opts) lst
494 contents <- mapM (blockListToHtml opts) lst
502 return $ unordList opts contents
495 return $ unordList opts contents
@@ -524,7 +517,7 @@ blockToHtml opts (DefinitionList lst) = do
524 contents <- mapM (\(term, defs) ->
517 contents <- mapM (\(term, defs) ->
525 do term' <- if null term
518 do term' <- if null term
526 then return mempty
519 then return mempty
527− else liftM (H.dt) $ inlineListToHtml opts term
520+ else liftM H.dt $ inlineListToHtml opts term
528 defs' <- mapM ((liftM (\x -> H.dd $ (x >> nl opts))) .
521 defs' <- mapM ((liftM (\x -> H.dd $ (x >> nl opts))) .
529 blockListToHtml opts) defs
522 blockListToHtml opts) defs
530 return $ mconcat $ nl opts : term' : nl opts :
523 return $ mconcat $ nl opts : term' : nl opts :
@@ -613,8 +606,22 @@ inlineToHtml opts inline =
613 (Str str) -> return $ strToHtml str
606 (Str str) -> return $ strToHtml str
614 (Space) -> return $ strToHtml " "
607 (Space) -> return $ strToHtml " "
615 (LineBreak) -> return $ if writerHtml5 opts then H5.br else H.br
608 (LineBreak) -> return $ if writerHtml5 opts then H5.br else H.br
609+ (Span (id',classes,kvs) ils)
616− (Span attr ils) -> inlineListToHtml opts ils >>=
610+ -> inlineListToHtml opts ils >>=
617− return . addAttrs opts attr . H.span
611+ return . addAttrs opts attr' . H.span
612+ where attr' = (id',classes',kvs')
613+ classes' = filter (`notElem` ["csl-no-emph",
614+ "csl-no-strong",
615+ "csl-no-smallcaps"]) classes
616+ kvs' = if null styles
617+ then kvs
618+ else (("style", concat styles) : kvs)
619+ styles = ["font-style:normal;"
620+ | "csl-no-emph" `elem` classes]
621+ ++ ["font-weight:normal;"
622+ | "csl-no-strong" `elem` classes]
623+ ++ ["font-variant:normal;"
624+ | "csl-no-smallcaps" `elem` classes]
618 (Emph lst) -> inlineListToHtml opts lst >>= return . H.em
625 (Emph lst) -> inlineListToHtml opts lst >>= return . H.em
619 (Strong lst) -> inlineListToHtml opts lst >>= return . H.strong
626 (Strong lst) -> inlineListToHtml opts lst >>= return . H.strong
620 (Code attr str) -> case hlCode of
627 (Code attr str) -> case hlCode of
@@ -742,7 +749,9 @@ inlineToHtml opts inline =
742 else [A.title $ toValue tit])
749 else [A.title $ toValue tit])
743 return $ foldl (!) H5.embed attributes
750 return $ foldl (!) H5.embed attributes
744 -- note: null title included, as in Markdown.pl
751 -- note: null title included, as in Markdown.pl
745− (Note contents) -> do
752+ (Note contents)
753+ | writerIgnoreNotes opts -> return mempty
754+ | otherwise -> do
746 st <- get
755 st <- get
747 let notes = stNotes st
756 let notes = stNotes st
748 let number = (length notes) + 1
757 let number = (length notes) + 1
@@ -757,11 +766,11 @@ inlineToHtml opts inline =
757 writerIdentifierPrefix opts ++ "fn" ++ ref)
766 writerIdentifierPrefix opts ++ "fn" ++ ref)
758 ! A.class_ "footnoteRef"
767 ! A.class_ "footnoteRef"
759 ! prefixedId opts ("fnref" ++ ref)
768 ! prefixedId opts ("fnref" ++ ref)
769+ $ H.sup
760 $ toHtml ref
770 $ toHtml ref
761− let link' = case writerEpubVersion opts of
771+ return $ case writerEpubVersion opts of
762− Just EPUB3 -> link ! customAttribute "epub:type" "noteref"
772+ Just EPUB3 -> link ! customAttribute "epub:type" "noteref"
763− _ -> link
773+ _ -> link
764− return $ H.sup $ link'
765 (Cite cits il)-> do contents <- inlineListToHtml opts il
774 (Cite cits il)-> do contents <- inlineListToHtml opts il
766 let citationIds = unwords $ map citationId cits
775 let citationIds = unwords $ map citationId cits
767 let result = H.span ! A.class_ "citation" $ contents
776 let result = H.span ! A.class_ "citation" $ contents
src/Text/Pandoc/Writers/LaTeX.hs+69−30
@@ -40,6 +40,7 @@ import Network.URI ( isURI, unEscapeString )
40import Data.List ( (\\), isSuffixOf, isInfixOf,
40import Data.List ( (\\), isSuffixOf, isInfixOf,
41 isPrefixOf, intercalate, intersperse )
41 isPrefixOf, intercalate, intersperse )
42import Data.Char ( toLower, isPunctuation, isAscii, isLetter, isDigit, ord )
42import Data.Char ( toLower, isPunctuation, isAscii, isLetter, isDigit, ord )
43+import Data.Maybe ( fromMaybe )
43import Control.Applicative ((<|>))
44import Control.Applicative ((<|>))
44import Control.Monad.State
45import Control.Monad.State
45import Text.Pandoc.Pretty
46import Text.Pandoc.Pretty
@@ -50,6 +51,8 @@ import Text.Pandoc.Highlighting (highlight, styleToLaTeX,
50
51
51data WriterState =
52data WriterState =
52 WriterState { stInNote :: Bool -- true if we're in a note
53 WriterState { stInNote :: Bool -- true if we're in a note
54+ , stInMinipage :: Bool -- true if in minipage
55+ , stNotes :: [Doc] -- notes in a minipage
53 , stOLLevel :: Int -- level of ordered list nesting
56 , stOLLevel :: Int -- level of ordered list nesting
54 , stOptions :: WriterOptions -- writer options, so they don't have to be parameter
57 , stOptions :: WriterOptions -- writer options, so they don't have to be parameter
55 , stVerbInNote :: Bool -- true if document has verbatim text in note
58 , stVerbInNote :: Bool -- true if document has verbatim text in note
@@ -70,7 +73,7 @@ data WriterState =
70writeLaTeX :: WriterOptions -> Pandoc -> String
73writeLaTeX :: WriterOptions -> Pandoc -> String
71writeLaTeX options document =
74writeLaTeX options document =
72 evalState (pandocToLaTeX options document) $
75 evalState (pandocToLaTeX options document) $
73− WriterState { stInNote = False,
76+ WriterState { stInNote = False, stInMinipage = False, stNotes = [],
74 stOLLevel = 1, stOptions = options,
77 stOLLevel = 1, stOptions = options,
75 stVerbInNote = False,
78 stVerbInNote = False,
76 stTable = False, stStrikeout = False,
79 stTable = False, stStrikeout = False,
@@ -126,14 +129,16 @@ pandocToLaTeX options (Pandoc meta blocks) = do
126 (biblioTitle :: String) <- liftM (render colwidth) $ inlineListToLaTeX lastHeader
129 (biblioTitle :: String) <- liftM (render colwidth) $ inlineListToLaTeX lastHeader
127 let main = render colwidth $ vsep body
130 let main = render colwidth $ vsep body
128 st <- get
131 st <- get
132+ titleMeta <- stringToLaTeX TextString $ stringify $ docTitle meta
133+ authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta
129 let context = defField "toc" (writerTableOfContents options) $
134 let context = defField "toc" (writerTableOfContents options) $
130 defField "toc-depth" (show (writerTOCDepth options -
135 defField "toc-depth" (show (writerTOCDepth options -
131 if writerChapters options
136 if writerChapters options
132 then 1
137 then 1
133 else 0)) $
138 else 0)) $
134 defField "body" main $
139 defField "body" main $
135− defField "title-meta" (stringify $ docTitle meta) $
140+ defField "title-meta" titleMeta $
136− defField "author-meta" (intercalate "; " $ map stringify $ docAuthors meta) $
141+ defField "author-meta" (intercalate "; " authorsMeta) $
137 defField "documentclass" (if writerBeamer options
142 defField "documentclass" (if writerBeamer options
138 then ("beamer" :: String)
143 then ("beamer" :: String)
139 else if writerChapters options
144 else if writerChapters options
@@ -186,7 +191,7 @@ stringToLaTeX _ [] = return ""
186stringToLaTeX ctx (x:xs) = do
191stringToLaTeX ctx (x:xs) = do
187 opts <- gets stOptions
192 opts <- gets stOptions
188 rest <- stringToLaTeX ctx xs
193 rest <- stringToLaTeX ctx xs
189− let ligatures = writerTeXLigatures opts && not (ctx == CodeString)
194+ let ligatures = writerTeXLigatures opts && (ctx /= CodeString)
190 let isUrl = ctx == URLString
195 let isUrl = ctx == URLString
191 when (x == '€') $
196 when (x == '€') $
192 modify $ \st -> st{ stUsesEuro = True }
197 modify $ \st -> st{ stUsesEuro = True }
@@ -236,7 +241,7 @@ inCmd cmd contents = char '\\' <> text cmd <> braces contents
236toSlides :: [Block] -> State WriterState [Block]
241toSlides :: [Block] -> State WriterState [Block]
237toSlides bs = do
242toSlides bs = do
238 opts <- gets stOptions
243 opts <- gets stOptions
239− let slideLevel = maybe (getSlideLevel bs) id $ writerSlideLevel opts
244+ let slideLevel = fromMaybe (getSlideLevel bs) $ writerSlideLevel opts
240 let bs' = prepSlides slideLevel bs
245 let bs' = prepSlides slideLevel bs
241 concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs')
246 concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs')
242
247
@@ -439,7 +444,7 @@ blockToLaTeX (DefinitionList lst) = do
439 incremental <- gets stIncremental
444 incremental <- gets stIncremental
440 let inc = if incremental then "[<+->]" else ""
445 let inc = if incremental then "[<+->]" else ""
441 items <- mapM defListItemToLaTeX lst
446 items <- mapM defListItemToLaTeX lst
442− let spacing = if and $ map isTightList (map snd lst)
447+ let spacing = if all isTightList (map snd lst)
443 then text "\\itemsep1pt\\parskip0pt\\parsep0pt"
448 then text "\\itemsep1pt\\parskip0pt\\parsep0pt"
444 else empty
449 else empty
445 return $ text ("\\begin{description}" ++ inc) $$ spacing $$ vcat items $$
450 return $ text ("\\begin{description}" ++ inc) $$ spacing $$ vcat items $$
@@ -451,12 +456,12 @@ blockToLaTeX (Header level (id',classes,_) lst) =
451blockToLaTeX (Table caption aligns widths heads rows) = do
456blockToLaTeX (Table caption aligns widths heads rows) = do
452 headers <- if all null heads
457 headers <- if all null heads
453 then return empty
458 then return empty
454− else ($$ "\\hline\\noalign{\\medskip}") `fmap`
459+ else ($$ "\\midrule\\endhead") `fmap`
455 (tableRowToLaTeX True aligns widths) heads
460 (tableRowToLaTeX True aligns widths) heads
456 captionText <- inlineListToLaTeX caption
461 captionText <- inlineListToLaTeX caption
457 let capt = if isEmpty captionText
462 let capt = if isEmpty captionText
458 then empty
463 then empty
459− else text "\\noalign{\\medskip}"
464+ else text "\\addlinespace"
460 $$ text "\\caption" <> braces captionText
465 $$ text "\\caption" <> braces captionText
461 rows' <- mapM (tableRowToLaTeX False aligns widths) rows
466 rows' <- mapM (tableRowToLaTeX False aligns widths) rows
462 let colDescriptors = text $ concat $ map toColDescriptor aligns
467 let colDescriptors = text $ concat $ map toColDescriptor aligns
@@ -464,10 +469,10 @@ blockToLaTeX (Table caption aligns widths heads rows) = do
464 return $ "\\begin{longtable}[c]" <>
469 return $ "\\begin{longtable}[c]" <>
465 braces ("@{}" <> colDescriptors <> "@{}")
470 braces ("@{}" <> colDescriptors <> "@{}")
466 -- the @{} removes extra space at beginning and end
471 -- the @{} removes extra space at beginning and end
467− $$ "\\hline\\noalign{\\medskip}"
472+ $$ "\\toprule\\addlinespace"
468 $$ headers
473 $$ headers
469 $$ vcat rows'
474 $$ vcat rows'
470− $$ "\\hline"
475+ $$ "\\bottomrule"
471 $$ capt
476 $$ capt
472 $$ "\\end{longtable}"
477 $$ "\\end{longtable}"
473
478
@@ -488,23 +493,42 @@ tableRowToLaTeX :: Bool
488 -> [[Block]]
493 -> [[Block]]
489 -> State WriterState Doc
494 -> State WriterState Doc
490tableRowToLaTeX header aligns widths cols = do
495tableRowToLaTeX header aligns widths cols = do
491− renderedCells <- mapM blockListToLaTeX cols
492− let valign = text $ if header then "[b]" else "[t]"
493− let halign x = case x of
494− AlignLeft -> "\\raggedright"
495− AlignRight -> "\\raggedleft"
496− AlignCenter -> "\\centering"
497− AlignDefault -> "\\raggedright"
498 -- scale factor compensates for extra space between columns
496 -- scale factor compensates for extra space between columns
499 -- so the whole table isn't larger than columnwidth
497 -- so the whole table isn't larger than columnwidth
500 let scaleFactor = 0.97 ** fromIntegral (length aligns)
498 let scaleFactor = 0.97 ** fromIntegral (length aligns)
501− let toCell 0 _ c = c
499+ let widths' = map (scaleFactor *) widths
500+ cells <- mapM (tableCellToLaTeX header) $ zip3 widths' aligns cols
501+ return $ hsep (intersperse "&" cells) $$ "\\\\\\addlinespace"
502+
503+tableCellToLaTeX :: Bool -> (Double, Alignment, [Block])
504+ -> State WriterState Doc
505+tableCellToLaTeX _ (0, _, blocks) = blockListToLaTeX blocks
506+tableCellToLaTeX header (width, align, blocks) = do
507+ modify $ \st -> st{ stInMinipage = True, stNotes = [] }
508+ cellContents <- blockListToLaTeX blocks
509+ notes <- gets stNotes
510+ modify $ \st -> st{ stInMinipage = False, stNotes = [] }
511+ let valign = text $ if header then "[b]" else "[t]"
512+ let halign = case align of
513+ AlignLeft -> "\\raggedright"
514+ AlignRight -> "\\raggedleft"
515+ AlignCenter -> "\\centering"
516+ AlignDefault -> "\\raggedright"
502− toCell w a c = "\\begin{minipage}" <> valign <>
517+ return $ ("\\begin{minipage}" <> valign <>
503− braces (text (printf "%.2f\\columnwidth"
518+ braces (text (printf "%.2f\\columnwidth" width)) <>
504− (w * scaleFactor))) <>
505− (halign a <> cr <> c <> cr) <> "\\end{minipage}"
519+ (halign <> cr <> cellContents <> cr) <> "\\end{minipage}")
506− let cells = zipWith3 toCell widths aligns renderedCells
520+ $$ case notes of
507− return $ hsep (intersperse "&" cells) $$ "\\\\\\noalign{\\medskip}"
521+ [] -> empty
522+ ns -> (case length ns of
523+ n | n > 1 -> "\\addtocounter" <>
524+ braces "footnote" <>
525+ braces (text $ show $ 1 - n)
526+ | otherwise -> empty)
527+ $$
528+ vcat (intersperse
529+ ("\\addtocounter" <> braces "footnote" <> braces "1")
530+ $ map (\x -> "\\footnotetext" <> braces x)
531+ $ reverse ns)
508
532
509listItemToLaTeX :: [Block] -> State WriterState Doc
533listItemToLaTeX :: [Block] -> State WriterState Doc
510listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item" $$) .
534listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item" $$) .
@@ -600,7 +624,16 @@ isQuoted _ = False
600-- | Convert inline element to LaTeX
624-- | Convert inline element to LaTeX
601inlineToLaTeX :: Inline -- ^ Inline to convert
625inlineToLaTeX :: Inline -- ^ Inline to convert
602 -> State WriterState Doc
626 -> State WriterState Doc
603−inlineToLaTeX (Span _ ils) = inlineListToLaTeX ils >>= return . braces
627+inlineToLaTeX (Span (_,classes,_) ils) = do
628+ let noEmph = "csl-no-emph" `elem` classes
629+ let noStrong = "csl-no-strong" `elem` classes
630+ let noSmallCaps = "csl-no-smallcaps" `elem` classes
631+ ((if noEmph then inCmd "textup" else id) .
632+ (if noStrong then inCmd "textnormal" else id) .
633+ (if noSmallCaps then inCmd "textnormal" else id) .
634+ (if not (noEmph || noStrong || noSmallCaps)
635+ then braces
636+ else id)) `fmap` inlineListToLaTeX ils
604inlineToLaTeX (Emph lst) =
637inlineToLaTeX (Emph lst) =
605 inlineListToLaTeX lst >>= return . inCmd "emph"
638 inlineListToLaTeX lst >>= return . inCmd "emph"
606inlineToLaTeX (Strong lst) =
639inlineToLaTeX (Strong lst) =
@@ -698,14 +731,20 @@ inlineToLaTeX (Image _ (source, _)) = do
698 source'' <- stringToLaTeX URLString source'
731 source'' <- stringToLaTeX URLString source'
699 return $ "\\includegraphics" <> braces (text source'')
732 return $ "\\includegraphics" <> braces (text source'')
700inlineToLaTeX (Note contents) = do
733inlineToLaTeX (Note contents) = do
734+ inMinipage <- gets stInMinipage
701 modify (\s -> s{stInNote = True})
735 modify (\s -> s{stInNote = True})
702 contents' <- blockListToLaTeX contents
736 contents' <- blockListToLaTeX contents
703 modify (\s -> s {stInNote = False})
737 modify (\s -> s {stInNote = False})
704 let optnl = case reverse contents of
738 let optnl = case reverse contents of
705 (CodeBlock _ _ : _) -> cr
739 (CodeBlock _ _ : _) -> cr
706 _ -> empty
740 _ -> empty
707− return $ "\\footnote" <> braces (nest 2 contents' <> optnl)
741+ let noteContents = nest 2 contents' <> optnl
742+ modify $ \st -> st{ stNotes = noteContents : stNotes st }
743+ return $
744+ if inMinipage
745+ then "\\footnotemark{}"
708− -- note: a \n before } needed when note ends with a Verbatim environment
746+ -- note: a \n before } needed when note ends with a Verbatim environment
747+ else "\\footnote" <> braces noteContents
709
748
710citationsToNatbib :: [Citation] -> State WriterState Doc
749citationsToNatbib :: [Citation] -> State WriterState Doc
711citationsToNatbib (one:[])
750citationsToNatbib (one:[])
@@ -726,9 +765,9 @@ citationsToNatbib cits
726 | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits
765 | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits
727 = citeCommand "citep" p s ks
766 = citeCommand "citep" p s ks
728 where
767 where
729− noPrefix = and . map (null . citationPrefix)
768+ noPrefix = all (null . citationPrefix)
730− noSuffix = and . map (null . citationSuffix)
769+ noSuffix = all (null . citationSuffix)
731− ismode m = and . map (((==) m) . citationMode)
770+ ismode m = all (((==) m) . citationMode)
732 p = citationPrefix $ head $ cits
771 p = citationPrefix $ head $ cits
733 s = citationSuffix $ last $ cits
772 s = citationSuffix $ last $ cits
734 ks = intercalate ", " $ map citationId cits
773 ks = intercalate ", " $ map citationId cits
src/Text/Pandoc/Writers/Markdown.hs+23−15
@@ -338,7 +338,7 @@ blockToMarkdown opts (RawBlock f str)
338 else return $ if isEnabled Ext_markdown_attribute opts
338 else return $ if isEnabled Ext_markdown_attribute opts
339 then text (addMarkdownAttribute str) <> text "\n"
339 then text (addMarkdownAttribute str) <> text "\n"
340 else text str <> text "\n"
340 else text str <> text "\n"
341− | f == "latex" || f == "tex" || f == "markdown" = do
341+ | f `elem` ["latex", "tex", "markdown"] = do
342 st <- get
342 st <- get
343 if stPlain st
343 if stPlain st
344 then return empty
344 then return empty
@@ -381,13 +381,11 @@ blockToMarkdown opts (CodeBlock (_,classes,_) str)
381 isEnabled Ext_literate_haskell opts =
381 isEnabled Ext_literate_haskell opts =
382 return $ prefixed "> " (text str) <> blankline
382 return $ prefixed "> " (text str) <> blankline
383blockToMarkdown opts (CodeBlock attribs str) = return $
383blockToMarkdown opts (CodeBlock attribs str) = return $
384− case attribs of
384+ case attribs == nullAttr of
385+ False | isEnabled Ext_backtick_code_blocks opts ->
386+ backticks <> attrs <> cr <> text str <> cr <> backticks <> blankline
385− x | x /= nullAttr && isEnabled Ext_fenced_code_blocks opts ->
387+ | isEnabled Ext_fenced_code_blocks opts ->
386− tildes <> " " <> attrs <> cr <> text str <>
388+ tildes <> attrs <> cr <> text str <> cr <> tildes <> blankline
387− cr <> tildes <> blankline
388− (_,(cls:_),_) | isEnabled Ext_backtick_code_blocks opts ->
389− backticks <> " " <> text cls <> cr <> text str <>
390− cr <> backticks <> blankline
391 _ -> nest (writerTabStop opts) (text str) <> blankline
389 _ -> nest (writerTabStop opts) (text str) <> blankline
392 where tildes = text $ case [ln | ln <- lines str, all (=='~') ln] of
390 where tildes = text $ case [ln | ln <- lines str, all (=='~') ln] of
393 [] -> "~~~~"
391 [] -> "~~~~"
@@ -396,8 +394,10 @@ blockToMarkdown opts (CodeBlock attribs str) = return $
396 | otherwise -> replicate (n+1) '~'
394 | otherwise -> replicate (n+1) '~'
397 backticks = text "```"
395 backticks = text "```"
398 attrs = if isEnabled Ext_fenced_code_attributes opts
396 attrs = if isEnabled Ext_fenced_code_attributes opts
399− then nowrap $ attrsToMarkdown attribs
397+ then nowrap $ " " <> attrsToMarkdown attribs
398+ else case attribs of
399+ (_,[cls],_) -> " " <> text cls
400− else empty
400+ _ -> empty
401blockToMarkdown opts (BlockQuote blocks) = do
401blockToMarkdown opts (BlockQuote blocks) = do
402 st <- get
402 st <- get
403 -- if we're writing literate haskell, put a space before the bird tracks
403 -- if we're writing literate haskell, put a space before the bird tracks
@@ -555,7 +555,14 @@ bulletListItemToMarkdown opts items = do
555 contents <- blockListToMarkdown opts items
555 contents <- blockListToMarkdown opts items
556 let sps = replicate (writerTabStop opts - 2) ' '
556 let sps = replicate (writerTabStop opts - 2) ' '
557 let start = text ('-' : ' ' : sps)
557 let start = text ('-' : ' ' : sps)
558+ -- remove trailing blank line if it is a tight list
559+ let contents' = case reverse items of
560+ (BulletList xs:_) | isTightList xs ->
561+ chomp contents <> cr
562+ (OrderedList _ xs:_) | isTightList xs ->
563+ chomp contents <> cr
564+ _ -> contents
558− return $ hang (writerTabStop opts) start $ contents <> cr
565+ return $ hang (writerTabStop opts) start $ contents' <> cr
559
566
560-- | Convert ordered list item (a list of blocks) to markdown.
567-- | Convert ordered list item (a list of blocks) to markdown.
561orderedListItemToMarkdown :: WriterOptions -- ^ options
568orderedListItemToMarkdown :: WriterOptions -- ^ options
@@ -621,10 +628,11 @@ getReference label (src, tit) = do
621 Nothing -> do
628 Nothing -> do
622 let label' = case find ((== label) . fst) (stRefs st) of
629 let label' = case find ((== label) . fst) (stRefs st) of
623 Just _ -> -- label is used; generate numerical label
630 Just _ -> -- label is used; generate numerical label
624− case find (\n -> not (any (== [Str (show n)])
631+ case find (\n -> notElem [Str (show n)]
632+ (map fst (stRefs st)))
625− (map fst (stRefs st)))) [1..(10000 :: Integer)] of
633+ [1..(10000 :: Integer)] of
626− Just x -> [Str (show x)]
634+ Just x -> [Str (show x)]
627− Nothing -> error "no unique label"
635+ Nothing -> error "no unique label"
628 Nothing -> label
636 Nothing -> label
629 modify (\s -> s{ stRefs = (label', (src,tit)) : stRefs st })
637 modify (\s -> s{ stRefs = (label', (src,tit)) : stRefs st })
630 return label'
638 return label'
src/Text/Pandoc/Writers/MediaWiki.hs+1−1
@@ -51,7 +51,7 @@ data WriterState = WriterState {
51writeMediaWiki :: WriterOptions -> Pandoc -> String
51writeMediaWiki :: WriterOptions -> Pandoc -> String
52writeMediaWiki opts document =
52writeMediaWiki opts document =
53 evalState (pandocToMediaWiki opts document)
53 evalState (pandocToMediaWiki opts document)
54− (WriterState { stNotes = False, stListLevel = [], stUseTags = False })
54+ WriterState { stNotes = False, stListLevel = [], stUseTags = False }
55
55
56-- | Return MediaWiki representation of document.
56-- | Return MediaWiki representation of document.
57pandocToMediaWiki :: WriterOptions -> Pandoc -> State WriterState String
57pandocToMediaWiki :: WriterOptions -> Pandoc -> State WriterState String
src/Text/Pandoc/Writers/ODT.hs+44−9
@@ -30,7 +30,10 @@ Conversion of 'Pandoc' documents to ODT.
30-}
30-}
31module Text.Pandoc.Writers.ODT ( writeODT ) where
31module Text.Pandoc.Writers.ODT ( writeODT ) where
32import Data.IORef
32import Data.IORef
33−import Data.List ( isPrefixOf )
33+import Data.List ( isPrefixOf, isSuffixOf )
34+import Data.Maybe ( fromMaybe )
35+import Text.XML.Light.Output
36+import Text.TeXMath
34import qualified Data.ByteString.Lazy as B
37import qualified Data.ByteString.Lazy as B
35import Text.Pandoc.UTF8 ( fromStringLazy )
38import Text.Pandoc.UTF8 ( fromStringLazy )
36import Codec.Archive.Zip
39import Codec.Archive.Zip
@@ -40,13 +43,14 @@ import Text.Pandoc.ImageSize ( imageSize, sizeInPoints )
40import Text.Pandoc.MIME ( getMimeType )
43import Text.Pandoc.MIME ( getMimeType )
41import Text.Pandoc.Definition
44import Text.Pandoc.Definition
42import Text.Pandoc.Walk
45import Text.Pandoc.Walk
46+import Text.Pandoc.Writers.Shared ( fixDisplayMath )
43import Text.Pandoc.Writers.OpenDocument ( writeOpenDocument )
47import Text.Pandoc.Writers.OpenDocument ( writeOpenDocument )
44import Control.Monad (liftM)
48import Control.Monad (liftM)
45import Text.Pandoc.XML
49import Text.Pandoc.XML
46import Text.Pandoc.Pretty
50import Text.Pandoc.Pretty
47import qualified Control.Exception as E
51import qualified Control.Exception as E
48import Data.Time.Clock.POSIX ( getPOSIXTime )
52import Data.Time.Clock.POSIX ( getPOSIXTime )
49−import System.FilePath ( takeExtension )
53+import System.FilePath ( takeExtension, takeDirectory )
50
54
51-- | Produce an ODT file from a Pandoc document.
55-- | Produce an ODT file from a Pandoc document.
52writeODT :: WriterOptions -- ^ Writer options
56writeODT :: WriterOptions -- ^ Writer options
@@ -60,9 +64,9 @@ writeODT opts doc@(Pandoc meta _) = do
60 Just f -> B.readFile f
64 Just f -> B.readFile f
61 Nothing -> (B.fromChunks . (:[])) `fmap`
65 Nothing -> (B.fromChunks . (:[])) `fmap`
62 readDataFile datadir "reference.odt"
66 readDataFile datadir "reference.odt"
63− -- handle pictures
67+ -- handle formulas and pictures
64 picEntriesRef <- newIORef ([] :: [Entry])
68 picEntriesRef <- newIORef ([] :: [Entry])
65− doc' <- walkM (transformPic opts picEntriesRef) doc
69+ doc' <- walkM (transformPicMath opts picEntriesRef) $ walk fixDisplayMath doc
66 let newContents = writeOpenDocument opts{writerWrapText = False} doc'
70 let newContents = writeOpenDocument opts{writerWrapText = False} doc'
67 epochtime <- floor `fmap` getPOSIXTime
71 epochtime <- floor `fmap` getPOSIXTime
68 let contentEntry = toEntry "content.xml" epochtime
72 let contentEntry = toEntry "content.xml" epochtime
@@ -72,7 +76,11 @@ writeODT opts doc@(Pandoc meta _) = do
72 $ contentEntry : picEntries
76 $ contentEntry : picEntries
73 -- construct META-INF/manifest.xml based on archive
77 -- construct META-INF/manifest.xml based on archive
74 let toFileEntry fp = case getMimeType fp of
78 let toFileEntry fp = case getMimeType fp of
79+ Nothing -> if "Formula-" `isPrefixOf` fp && "/" `isSuffixOf` fp
80+ then selfClosingTag "manifest:file-entry"
81+ [("manifest:media-type","application/vnd.oasis.opendocument.formula")
82+ ,("manifest:full-path",fp)]
75− Nothing -> empty
83+ else empty
76 Just m -> selfClosingTag "manifest:file-entry"
84 Just m -> selfClosingTag "manifest:file-entry"
77 [("manifest:media-type", m)
85 [("manifest:media-type", m)
78 ,("manifest:full-path", fp)
86 ,("manifest:full-path", fp)
@@ -80,6 +88,8 @@ writeODT opts doc@(Pandoc meta _) = do
80 ]
88 ]
81 let files = [ ent | ent <- filesInArchive archive,
89 let files = [ ent | ent <- filesInArchive archive,
82 not ("META-INF" `isPrefixOf` ent) ]
90 not ("META-INF" `isPrefixOf` ent) ]
91+ let formulas = [ takeDirectory ent ++ "/" | ent <- filesInArchive archive,
92+ "Formula-" `isPrefixOf` ent, takeExtension ent == ".xml" ]
83 let manifestEntry = toEntry "META-INF/manifest.xml" epochtime
93 let manifestEntry = toEntry "META-INF/manifest.xml" epochtime
84 $ fromStringLazy $ render Nothing
94 $ fromStringLazy $ render Nothing
85 $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
95 $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
@@ -91,6 +101,7 @@ writeODT opts doc@(Pandoc meta _) = do
91 [("manifest:media-type","application/vnd.oasis.opendocument.text")
101 [("manifest:media-type","application/vnd.oasis.opendocument.text")
92 ,("manifest:full-path","/")]
102 ,("manifest:full-path","/")]
93 $$ vcat ( map toFileEntry $ files )
103 $$ vcat ( map toFileEntry $ files )
104+ $$ vcat ( map toFileEntry $ formulas )
94 )
105 )
95 )
106 )
96 let archive' = addEntryToArchive manifestEntry archive
107 let archive' = addEntryToArchive manifestEntry archive
@@ -118,8 +129,8 @@ writeODT opts doc@(Pandoc meta _) = do
118 $ addEntryToArchive metaEntry archive'
129 $ addEntryToArchive metaEntry archive'
119 return $ fromArchive archive''
130 return $ fromArchive archive''
120
131
121−transformPic :: WriterOptions -> IORef [Entry] -> Inline -> IO Inline
132+transformPicMath :: WriterOptions -> IORef [Entry] -> Inline -> IO Inline
122−transformPic opts entriesRef (Image lab (src,_)) = do
133+transformPicMath opts entriesRef (Image lab (src,_)) = do
123 res <- fetchItem (writerSourceURL opts) src
134 res <- fetchItem (writerSourceURL opts) src
124 case res of
135 case res of
125 Left (_ :: E.SomeException) -> do
136 Left (_ :: E.SomeException) -> do
@@ -127,7 +138,7 @@ transformPic opts entriesRef (Image lab (src,_)) = do
127 return $ Emph lab
138 return $ Emph lab
128 Right (img, _) -> do
139 Right (img, _) -> do
129 let size = imageSize img
140 let size = imageSize img
130− let (w,h) = maybe (0,0) id $ sizeInPoints `fmap` size
141+ let (w,h) = fromMaybe (0,0) $ sizeInPoints `fmap` size
131 let tit' = show w ++ "x" ++ show h
142 let tit' = show w ++ "x" ++ show h
132 entries <- readIORef entriesRef
143 entries <- readIORef entriesRef
133 let newsrc = "Pictures/" ++ show (length entries) ++ takeExtension src
144 let newsrc = "Pictures/" ++ show (length entries) ++ takeExtension src
@@ -136,5 +147,29 @@ transformPic opts entriesRef (Image lab (src,_)) = do
136 let entry = toEntry newsrc epochtime $ toLazy img
147 let entry = toEntry newsrc epochtime $ toLazy img
137 modifyIORef entriesRef (entry:)
148 modifyIORef entriesRef (entry:)
138 return $ Image lab (newsrc, tit')
149 return $ Image lab (newsrc, tit')
139−transformPic _ _ x = return x
150+transformPicMath _ entriesRef (Math t math) = do
151+ entries <- readIORef entriesRef
152+ let dt = if t == InlineMath then DisplayInline else DisplayBlock
153+ case texMathToMathML dt math of
154+ Left _ -> return $ Math t math
155+ Right r -> do
156+ let conf = useShortEmptyTags (const False) defaultConfigPP
157+ let mathml = ppcTopElement conf r
158+ epochtime <- floor `fmap` getPOSIXTime
159+ let dirname = "Formula-" ++ show (length entries) ++ "/"
160+ let fname = dirname ++ "content.xml"
161+ let entry = toEntry fname epochtime (fromStringLazy mathml)
162+ modifyIORef entriesRef (entry:)
163+ return $ RawInline (Format "opendocument") $ render Nothing $
164+ inTags False "draw:frame" [("text:anchor-type",
165+ if t == DisplayMath
166+ then "paragraph"
167+ else "as-char")
168+ ,("style:vertical-pos", "middle")
169+ ,("style:vertical-rel", "text")] $
170+ selfClosingTag "draw:object" [("xlink:href", dirname)
171+ , ("xlink:type", "simple")
172+ , ("xlink:show", "embed")
173+ , ("xlink:actuate", "onLoad")]
140
174
175+transformPicMath _ _ x = return x
src/Text/Pandoc/Writers/OpenDocument.hs+18−8
@@ -64,6 +64,7 @@ data WriterState =
64 , stInDefinition :: Bool
64 , stInDefinition :: Bool
65 , stTight :: Bool
65 , stTight :: Bool
66 , stFirstPara :: Bool
66 , stFirstPara :: Bool
67+ , stImageId :: Int
67 }
68 }
68
69
69defaultWriterState :: WriterState
70defaultWriterState :: WriterState
@@ -78,6 +79,7 @@ defaultWriterState =
78 , stInDefinition = False
79 , stInDefinition = False
79 , stTight = False
80 , stTight = False
80 , stFirstPara = False
81 , stFirstPara = False
82+ , stImageId = 1
81 }
83 }
82
84
83when :: Bool -> Doc -> Doc
85when :: Bool -> Doc -> Doc
@@ -283,8 +285,12 @@ blocksToOpenDocument o b = vcat <$> mapM (blockToOpenDocument o) b
283-- | Convert a Pandoc block element to OpenDocument.
285-- | Convert a Pandoc block element to OpenDocument.
284blockToOpenDocument :: WriterOptions -> Block -> State WriterState Doc
286blockToOpenDocument :: WriterOptions -> Block -> State WriterState Doc
285blockToOpenDocument o bs
287blockToOpenDocument o bs
288+ | Plain b <- bs = if null b
289+ then return empty
286− | Plain b <- bs = inParagraphTags =<< inlinesToOpenDocument o b
290+ else inParagraphTags =<< inlinesToOpenDocument o b
291+ | Para b <- bs = if null b
292+ then return empty
287− | Para b <- bs = inParagraphTags =<< inlinesToOpenDocument o b
293+ else inParagraphTags =<< inlinesToOpenDocument o b
288 | Div _ xs <- bs = blocksToOpenDocument o xs
294 | Div _ xs <- bs = blocksToOpenDocument o xs
289 | Header i _ b <- bs = setFirstPara >>
295 | Header i _ b <- bs = setFirstPara >>
290 (inHeaderTags i =<< inlinesToOpenDocument o b)
296 (inHeaderTags i =<< inlinesToOpenDocument o b)
@@ -296,8 +302,8 @@ blockToOpenDocument o bs
296 | Table c a w h r <- bs = setFirstPara >> table c a w h r
302 | Table c a w h r <- bs = setFirstPara >> table c a w h r
297 | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p"
303 | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p"
298 [ ("text:style-name", "Horizontal_20_Line") ])
304 [ ("text:style-name", "Horizontal_20_Line") ])
299− | RawBlock f s <- bs = if f == "opendocument"
305+ | RawBlock f s <- bs = if f == Format "opendocument"
300− then preformatted s
306+ then return $ text s
301 else return empty
307 else return empty
302 | Null <- bs = return empty
308 | Null <- bs = return empty
303 | otherwise = return empty
309 | otherwise = return empty
@@ -376,11 +382,11 @@ inlineToOpenDocument o ils
376 | Code _ s <- ils = withTextStyle Pre $ inTextStyle $ preformatted s
382 | Code _ s <- ils = withTextStyle Pre $ inTextStyle $ preformatted s
377 | Math t s <- ils = inlinesToOpenDocument o (readTeXMath' t s)
383 | Math t s <- ils = inlinesToOpenDocument o (readTeXMath' t s)
378 | Cite _ l <- ils = inlinesToOpenDocument o l
384 | Cite _ l <- ils = inlinesToOpenDocument o l
379− | RawInline f s <- ils = if f == "opendocument" || f == "html"
385+ | RawInline f s <- ils = if f == Format "opendocument"
380− then withTextStyle Pre $ inTextStyle $ preformatted s
386+ then return $ text s
381 else return empty
387 else return empty
382 | Link l (s,t) <- ils = mkLink s t <$> inlinesToOpenDocument o l
388 | Link l (s,t) <- ils = mkLink s t <$> inlinesToOpenDocument o l
383− | Image _ (s,t) <- ils = return $ mkImg s t
389+ | Image _ (s,t) <- ils = mkImg s t
384 | Note l <- ils = mkNote l
390 | Note l <- ils = mkNote l
385 | otherwise = return empty
391 | otherwise = return empty
386 where
392 where
@@ -389,7 +395,11 @@ inlineToOpenDocument o ils
389 , ("xlink:href" , s )
395 , ("xlink:href" , s )
390 , ("office:name", t )
396 , ("office:name", t )
391 ] . inSpanTags "Definition"
397 ] . inSpanTags "Definition"
398+ mkImg s t = do
399+ id' <- gets stImageId
400+ modify (\st -> st{ stImageId = id' + 1 })
392− mkImg s t = inTags False "draw:frame" (attrsFromTitle t) $
401+ return $ inTags False "draw:frame"
402+ (("draw:name", "img" ++ show id'):attrsFromTitle t) $
393 selfClosingTag "draw:image" [ ("xlink:href" , s )
403 selfClosingTag "draw:image" [ ("xlink:href" , s )
394 , ("xlink:type" , "simple")
404 , ("xlink:type" , "simple")
395 , ("xlink:show" , "embed" )
405 , ("xlink:show" , "embed" )
src/Text/Pandoc/Writers/Org.hs+1−1
@@ -129,7 +129,7 @@ blockToOrg (Para inlines) = do
129blockToOrg (RawBlock "html" str) =
129blockToOrg (RawBlock "html" str) =
130 return $ blankline $$ "#+BEGIN_HTML" $$
130 return $ blankline $$ "#+BEGIN_HTML" $$
131 nest 2 (text str) $$ "#+END_HTML" $$ blankline
131 nest 2 (text str) $$ "#+END_HTML" $$ blankline
132−blockToOrg (RawBlock f str) | f == "org" || f == "latex" || f == "tex" =
132+blockToOrg (RawBlock f str) | f `elem` ["org", "latex", "tex"] =
133 return $ text str
133 return $ text str
134blockToOrg (RawBlock _ _) = return empty
134blockToOrg (RawBlock _ _) = return empty
135blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline
135blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline
src/Text/Pandoc/Writers/RST.hs+1−1
@@ -287,7 +287,7 @@ definitionListItemToRST (label, defs) = do
287 label' <- inlineListToRST label
287 label' <- inlineListToRST label
288 contents <- liftM vcat $ mapM blockListToRST defs
288 contents <- liftM vcat $ mapM blockListToRST defs
289 tabstop <- get >>= (return . writerTabStop . stOptions)
289 tabstop <- get >>= (return . writerTabStop . stOptions)
290− return $ label' $$ nest tabstop (contents <> cr)
290+ return $ label' $$ nest tabstop (nestle contents <> cr)
291
291
292-- | Convert list of Pandoc block elements to RST.
292-- | Convert list of Pandoc block elements to RST.
293blockListToRST :: [Block] -- ^ List of block elements
293blockListToRST :: [Block] -- ^ List of block elements
src/Text/Pandoc/Writers/Shared.hs+28−2
@@ -34,6 +34,7 @@ module Text.Pandoc.Writers.Shared (
34 , setField
34 , setField
35 , defField
35 , defField
36 , tagWithAttrs
36 , tagWithAttrs
37+ , fixDisplayMath
37 )
38 )
38where
39where
39import Text.Pandoc.Definition
40import Text.Pandoc.Definition
@@ -46,6 +47,7 @@ import qualified Data.Map as M
46import qualified Data.Text as T
47import qualified Data.Text as T
47import Data.Aeson (FromJSON(..), fromJSON, ToJSON (..), Value(Object), Result(..))
48import Data.Aeson (FromJSON(..), fromJSON, ToJSON (..), Value(Object), Result(..))
48import qualified Data.Traversable as Traversable
49import qualified Data.Traversable as Traversable
50+import Data.List ( groupBy )
49
51
50-- | Create JSON value for template from a 'Meta' and an association list
52-- | Create JSON value for template from a 'Meta' and an association list
51-- of variables, specified at the command line or in the writer.
53-- of variables, specified at the command line or in the writer.
@@ -65,8 +67,7 @@ metaToJSON opts blockWriter inlineWriter (Meta metamap)
65 renderedMap <- Traversable.mapM
67 renderedMap <- Traversable.mapM
66 (metaValueToJSON blockWriter inlineWriter)
68 (metaValueToJSON blockWriter inlineWriter)
67 metamap
69 metamap
68− return $ M.foldWithKey (\key val obj -> defField key val obj)
69− baseContext renderedMap
70+ return $ M.foldWithKey defField baseContext renderedMap
70 | otherwise = return (Object H.empty)
71 | otherwise = return (Object H.empty)
71
72
72metaValueToJSON :: Monad m
73metaValueToJSON :: Monad m
@@ -137,3 +138,28 @@ tagWithAttrs tag (ident,classes,kvs) = hsep
137 ,hsep (map (\(k,v) -> text k <> "=" <>
138 ,hsep (map (\(k,v) -> text k <> "=" <>
138 doubleQuotes (text (escapeStringForXML v))) kvs)
139 doubleQuotes (text (escapeStringForXML v))) kvs)
139 ] <> ">"
140 ] <> ">"
141+
142+isDisplayMath :: Inline -> Bool
143+isDisplayMath (Math DisplayMath _) = True
144+isDisplayMath _ = False
145+
146+stripLeadingTrailingSpace :: [Inline] -> [Inline]
147+stripLeadingTrailingSpace = go . reverse . go . reverse
148+ where go (Space:xs) = xs
149+ go xs = xs
150+
151+-- Put display math in its own block (for ODT/DOCX).
152+fixDisplayMath :: Block -> Block
153+fixDisplayMath (Plain lst)
154+ | any isDisplayMath lst && not (all isDisplayMath lst) =
155+ -- chop into several paragraphs so each displaymath is its own
156+ Div ("",["math"],[]) $ map (Plain . stripLeadingTrailingSpace) $
157+ groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||
158+ not (isDisplayMath x || isDisplayMath y)) lst
159+fixDisplayMath (Para lst)
160+ | any isDisplayMath lst && not (all isDisplayMath lst) =
161+ -- chop into several paragraphs so each displaymath is its own
162+ Div ("",["math"],[]) $ map (Para . stripLeadingTrailingSpace) $
163+ groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||
164+ not (isDisplayMath x || isDisplayMath y)) lst
165+fixDisplayMath x = x
src/Text/Pandoc/Writers/Texinfo.hs+1−5
@@ -293,7 +293,7 @@ blockListToTexinfo (x:xs) = do
293 case x of
293 case x of
294 Header level _ _ -> do
294 Header level _ _ -> do
295 -- We need need to insert a menu for this node.
295 -- We need need to insert a menu for this node.
296− let (before, after) = break isHeader xs
296+ let (before, after) = break isHeaderBlock xs
297 before' <- blockListToTexinfo before
297 before' <- blockListToTexinfo before
298 let menu = if level < 4
298 let menu = if level < 4
299 then collectNodes (level + 1) after
299 then collectNodes (level + 1) after
@@ -315,10 +315,6 @@ blockListToTexinfo (x:xs) = do
315 xs' <- blockListToTexinfo xs
315 xs' <- blockListToTexinfo xs
316 return $ x' $$ xs'
316 return $ x' $$ xs'
317
317
318−isHeader :: Block -> Bool
319−isHeader (Header _ _ _) = True
320−isHeader _ = False
321−
322collectNodes :: Int -> [Block] -> [Block]
318collectNodes :: Int -> [Block] -> [Block]
323collectNodes _ [] = []
319collectNodes _ [] = []
324collectNodes level (x:xs) =
320collectNodes level (x:xs) =
src/Text/Pandoc/Writers/Textile.hs+1−1
@@ -51,7 +51,7 @@ data WriterState = WriterState {
51writeTextile :: WriterOptions -> Pandoc -> String
51writeTextile :: WriterOptions -> Pandoc -> String
52writeTextile opts document =
52writeTextile opts document =
53 evalState (pandocToTextile opts document)
53 evalState (pandocToTextile opts document)
54− (WriterState { stNotes = [], stListLevel = [], stUseTags = False })
54+ WriterState { stNotes = [], stListLevel = [], stUseTags = False }
55
55
56-- | Return Textile representation of document.
56-- | Return Textile representation of document.
57pandocToTextile :: WriterOptions -> Pandoc -> State WriterState String
57pandocToTextile :: WriterOptions -> Pandoc -> State WriterState String
tests/MarkdownTest_1.0.3/MarkdownTest.pldeleted−176
@@ -1,176 +0,0 @@
1−#!/usr/bin/perl
2−
3−#
4−# MarkdownTester -- Run tests for Markdown implementations
5−#
6−# Copyright (c) 2004-2005 John Gruber
7−# <http://daringfireball.net/projects/markdown/>
8−#
9−
10−use strict;
11−use warnings;
12−use Getopt::Long;
13−use Benchmark;
14−
15−our $VERSION = '1.0.2';
16−# Sat 24 Dec 2005
17−
18−my $time_start = new Benchmark;
19−my $test_dir = "Tests";
20−my $script = "./Markdown.pl";
21−my $use_tidy = 0;
22−my ($flag_version);
23−
24−GetOptions (
25− "script=s" => \$script,
26− "testdir=s" => \$test_dir,
27− "tidy" => \$use_tidy,
28− "version" => \$flag_version,
29− );
30−
31−if($flag_version) {
32− my $progname = $0;
33− $progname =~ s{.*/}{};
34− die "$progname version $VERSION\n";
35−}
36−
37−unless (-d $test_dir) { die "'$test_dir' is not a directory.\n"; }
38−unless (-f $script) { die "$script does not exist.\n"; }
39−unless (-x $script) { die "$script is not executable.\n"; }
40−
41−my $tests_passed = 0;
42−my $tests_failed = 0;
43−
44−TEST:
45−foreach my $testfile (glob "$test_dir/*.text") {
46− my $testname = $testfile;
47− $testname =~ s{.*/(.+)\.text$}{$1}i;
48− print "$testname ... ";
49−
50− # Look for a corresponding .html file for each .text file:
51− my $resultfile = $testfile;
52− $resultfile =~ s{\.text$}{\.html}i;
53− unless (-f $resultfile) {
54− print "'$resultfile' does not exist.\n\n";
55− next TEST;
56− }
57−
58− # open(TEST, $testfile) || die("Can't open testfile: $!");
59− open(RESULT, $resultfile) || die("Can't open resultfile: $!");
60− undef $/;
61− # my $t_input = <TEST>;
62− my $t_result = <RESULT>;
63−
64− my $t_output = `'$script' '$testfile'`;
65−
66− # Normalize the output and expected result strings:
67− $t_result =~ s/\s+\z//; # trim trailing whitespace
68− $t_output =~ s/\s+\z//; # trim trailing whitespace
69− if ($use_tidy) {
70− # Escape the strings, pass them through to CLI tidy tool for tag-level equivalency
71− $t_result =~ s{'}{'\\''}g; # escape ' chars for shell
72− $t_output =~ s{'}{'\\''}g;
73− $t_result = `echo '$t_result' | tidy --show-body-only 1 --quiet 1 --show-warnings 0`;
74− $t_output = `echo '$t_output' | tidy --show-body-only 1 --quiet 1 --show-warnings 0`;
75− }
76−
77− if ($t_output eq $t_result) {
78− print "OK\n";
79− $tests_passed++;
80− }
81− else {
82− print "FAILED\n\n";
83−# This part added by JM to print diffs
84− open(OUT, '>tmp1') or die $!;
85− print OUT $t_output or die $!;
86− open(RES, '>tmp2') or die $!;
87− print RES $t_result or die $!;
88− print `diff tmp1 tmp2`;
89− close RES;
90− close OUT;
91− print "\n";
92− `rm tmp?`;
93−# End of added part
94− $tests_failed++;
95− }
96−}
97−
98−print "\n\n";
99−print "$tests_passed passed; $tests_failed failed.\n";
100−
101−my $time_end = new Benchmark;
102−my $time_diff = timediff($time_end, $time_start);
103−print "Benchmark: ", timestr($time_diff), "\n";
104−
105−
106−__END__
107−
108−=pod
109−
110−=head1 NAME
111−
112−B<MarkdownTest>
113−
114−
115−=head1 SYNOPSIS
116−
117−B<MarkdownTest.pl> [ B<--options> ] [ I<file> ... ]
118−
119−
120−=head1 DESCRIPTION
121−
122−
123−=head1 OPTIONS
124−
125−Use "--" to end switch parsing. For example, to open a file named "-z", use:
126−
127− MarkdownTest.pl -- -z
128−
129−=over 4
130−
131−=item B<--script>
132−
133−Specify the path to the Markdown script to test. Defaults to
134−"./Markdown.pl". Example:
135−
136− ./MarkdownTest.pl --script ./PHP-Markdown/php-markdown
137−
138−=item B<--testdir>
139−
140−Specify the path to a directory containing test data. Defaults to "Tests".
141−
142−=item B<--tidy>
143−
144−Flag to turn on using the command line 'tidy' tool to normalize HTML
145−output before comparing script output to the expected test result.
146−Assumes that the 'tidy' command is available in your PATH. Defaults to
147−off.
148−
149−=back
150−
151−
152−
153−=head1 BUGS
154−
155−
156−
157−=head1 VERSION HISTORY
158−
159−1.0 Mon 13 Dec 2004-2005
160−
161−1.0.1 Mon 19 Sep 2005
162−
163− + Better handling of case when foo.text exists, but foo.html doesn't.
164− It now prints a message and moves on, rather than dying.
165−
166−
167−=head1 COPYRIGHT AND LICENSE
168−
169−Copyright (c) 2004-2005 John Gruber
170−<http://daringfireball.net/>
171−All rights reserved.
172−
173−This is free software; you may redistribute it and/or modify it under
174−the same terms as Perl itself.
175−
176−=cut
tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.htmldeleted−17
@@ -1,17 +0,0 @@
1−<p>AT&amp;T has an ampersand in their name.</p>
2−
3−<p>AT&amp;T is another way to write it.</p>
4−
5−<p>This &amp; that.</p>
6−
7−<p>4 &lt; 5.</p>
8−
9−<p>6 > 5.</p>
10−
11−<p>Here's a <a href="http://example.com/?foo=1&amp;bar=2">link</a> with an ampersand in the URL.</p>
12−
13−<p>Here's a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T">AT&amp;T</a>.</p>
14−
15−<p>Here's an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
16−
17−<p>Here's an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
tests/MarkdownTest_1.0.3/Tests/Amps and angle encoding.textdeleted−21
@@ -1,21 +0,0 @@
1−AT&T has an ampersand in their name.
2−
3−AT&amp;T is another way to write it.
4−
5−This & that.
6−
7−4 < 5.
8−
9−6 > 5.
10−
11−Here's a [link] [1] with an ampersand in the URL.
12−
13−Here's a link with an amersand in the link text: [AT&T] [2].
14−
15−Here's an inline [link](/script?foo=1&bar=2).
16−
17−Here's an inline [link](</script?foo=1&bar=2>).
18−
19−
20−[1]: http://example.com/?foo=1&bar=2
21−[2]: http://att.com/ "AT&T"
tests/MarkdownTest_1.0.3/Tests/Auto links.htmldeleted−18
@@ -1,18 +0,0 @@
1−<p>Link: <a href="http://example.com/">http://example.com/</a>.</p>
2−
3−<p>With an ampersand: <a href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a></p>
4−
5−<ul>
6−<li>In a list?</li>
7−<li><a href="http://example.com/">http://example.com/</a></li>
8−<li>It should.</li>
9−</ul>
10−
11−<blockquote>
12− <p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p>
13−</blockquote>
14−
15−<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>
16−
17−<pre><code>or here: &lt;http://example.com/&gt;
18−</code></pre>
tests/MarkdownTest_1.0.3/Tests/Auto links.textdeleted−13
@@ -1,13 +0,0 @@
1−Link: <http://example.com/>.
2−
3−With an ampersand: <http://example.com/?foo=1&bar=2>
4−
5−* In a list?
6−* <http://example.com/>
7−* It should.
8−
9−> Blockquoted: <http://example.com/>
10−
11−Auto-links should not occur here: `<http://example.com/>`
12−
13− or here: <http://example.com/>
tests/MarkdownTest_1.0.3/Tests/Backslash escapes.htmldeleted−118
@@ -1,118 +0,0 @@
1−<p>These should all get escaped:</p>
2−
3−<p>Backslash: \</p>
4−
5−<p>Backtick: `</p>
6−
7−<p>Asterisk: *</p>
8−
9−<p>Underscore: _</p>
10−
11−<p>Left brace: {</p>
12−
13−<p>Right brace: }</p>
14−
15−<p>Left bracket: [</p>
16−
17−<p>Right bracket: ]</p>
18−
19−<p>Left paren: (</p>
20−
21−<p>Right paren: )</p>
22−
23−<p>Greater-than: ></p>
24−
25−<p>Hash: #</p>
26−
27−<p>Period: .</p>
28−
29−<p>Bang: !</p>
30−
31−<p>Plus: +</p>
32−
33−<p>Minus: -</p>
34−
35−<p>These should not, because they occur within a code block:</p>
36−
37−<pre><code>Backslash: \\
38−
39−Backtick: \`
40−
41−Asterisk: \*
42−
43−Underscore: \_
44−
45−Left brace: \{
46−
47−Right brace: \}
48−
49−Left bracket: \[
50−
51−Right bracket: \]
52−
53−Left paren: \(
54−
55−Right paren: \)
56−
57−Greater-than: \&gt;
58−
59−Hash: \#
60−
61−Period: \.
62−
63−Bang: \!
64−
65−Plus: \+
66−
67−Minus: \-
68−</code></pre>
69−
70−<p>Nor should these, which occur in code spans:</p>
71−
72−<p>Backslash: <code>\\</code></p>
73−
74−<p>Backtick: <code>\`</code></p>
75−
76−<p>Asterisk: <code>\*</code></p>
77−
78−<p>Underscore: <code>\_</code></p>
79−
80−<p>Left brace: <code>\{</code></p>
81−
82−<p>Right brace: <code>\}</code></p>
83−
84−<p>Left bracket: <code>\[</code></p>
85−
86−<p>Right bracket: <code>\]</code></p>
87−
88−<p>Left paren: <code>\(</code></p>
89−
90−<p>Right paren: <code>\)</code></p>
91−
92−<p>Greater-than: <code>\&gt;</code></p>
93−
94−<p>Hash: <code>\#</code></p>
95−
96−<p>Period: <code>\.</code></p>
97−
98−<p>Bang: <code>\!</code></p>
99−
100−<p>Plus: <code>\+</code></p>
101−
102−<p>Minus: <code>\-</code></p>
103−
104−
105−<p>These should get escaped, even though they're matching pairs for
106−other Markdown constructs:</p>
107−
108−<p>*asterisks*</p>
109−
110−<p>_underscores_</p>
111−
112−<p>`backticks`</p>
113−
114−<p>This is a code span with a literal backslash-backtick sequence: <code>\`</code></p>
115−
116−<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p>
117−
118−<p>This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.</p>
tests/MarkdownTest_1.0.3/Tests/Backslash escapes.textdeleted−120
@@ -1,120 +0,0 @@
1−These should all get escaped:
2−
3−Backslash: \\
4−
5−Backtick: \`
6−
7−Asterisk: \*
8−
9−Underscore: \_
10−
11−Left brace: \{
12−
13−Right brace: \}
14−
15−Left bracket: \[
16−
17−Right bracket: \]
18−
19−Left paren: \(
20−
21−Right paren: \)
22−
23−Greater-than: \>
24−
25−Hash: \#
26−
27−Period: \.
28−
29−Bang: \!
30−
31−Plus: \+
32−
33−Minus: \-
34−
35−
36−
37−These should not, because they occur within a code block:
38−
39− Backslash: \\
40−
41− Backtick: \`
42−
43− Asterisk: \*
44−
45− Underscore: \_
46−
47− Left brace: \{
48−
49− Right brace: \}
50−
51− Left bracket: \[
52−
53− Right bracket: \]
54−
55− Left paren: \(
56−
57− Right paren: \)
58−
59− Greater-than: \>
60−
61− Hash: \#
62−
63− Period: \.
64−
65− Bang: \!
66−
67− Plus: \+
68−
69− Minus: \-
70−
71−
72−Nor should these, which occur in code spans:
73−
74−Backslash: `\\`
75−
76−Backtick: `` \` ``
77−
78−Asterisk: `\*`
79−
80−Underscore: `\_`
81−
82−Left brace: `\{`
83−
84−Right brace: `\}`
85−
86−Left bracket: `\[`
87−
88−Right bracket: `\]`
89−
90−Left paren: `\(`
91−
92−Right paren: `\)`
93−
94−Greater-than: `\>`
95−
96−Hash: `\#`
97−
98−Period: `\.`
99−
100−Bang: `\!`
101−
102−Plus: `\+`
103−
104−Minus: `\-`
105−
106−
107−These should get escaped, even though they're matching pairs for
108−other Markdown constructs:
109−
110−\*asterisks\*
111−
112−\_underscores\_
113−
114−\`backticks\`
115−
116−This is a code span with a literal backslash-backtick sequence: `` \` ``
117−
118−This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.
119−
120−This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.
tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.htmldeleted−15
@@ -1,15 +0,0 @@
1−<blockquote>
2− <p>Example:</p>
3−
4−<pre><code>sub status {
5− print "working";
6−}
7−</code></pre>
8−
9− <p>Or:</p>
10−
11−<pre><code>sub status {
12− return "working";
13−}
14−</code></pre>
15−</blockquote>
tests/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.textdeleted−11
@@ -1,11 +0,0 @@
1−> Example:
2−>
3−> sub status {
4−> print "working";
5−> }
6−>
7−> Or:
8−>
9−> sub status {
10−> return "working";
11−> }
tests/MarkdownTest_1.0.3/Tests/Code Blocks.htmldeleted−18
@@ -1,18 +0,0 @@
1−<pre><code>code block on the first line
2−</code></pre>
3−
4−<p>Regular text.</p>
5−
6−<pre><code>code block indented by spaces
7−</code></pre>
8−
9−<p>Regular text.</p>
10−
11−<pre><code>the lines in this block
12−all contain trailing spaces
13−</code></pre>
14−
15−<p>Regular Text.</p>
16−
17−<pre><code>code block on the last line
18−</code></pre>
tests/MarkdownTest_1.0.3/Tests/Code Blocks.textdeleted−14
@@ -1,14 +0,0 @@
1− code block on the first line
2−
3−Regular text.
4−
5− code block indented by spaces
6−
7−Regular text.
8−
9− the lines in this block
10− all contain trailing spaces
11−
12−Regular Text.
13−
14− code block on the last line
tests/MarkdownTest_1.0.3/Tests/Code Spans.htmldeleted−6
@@ -1,6 +0,0 @@
1−<p><code>&lt;test a="</code> content of attribute <code>"&gt;</code></p>
2−
3−<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p>
4−
5−<p>Here's how you put <code>`backticks`</code> in a code span.</p>
6−
tests/MarkdownTest_1.0.3/Tests/Code Spans.textdeleted−6
@@ -1,6 +0,0 @@
1−`<test a="` content of attribute `">`
2−
3−Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span>
4−
5−Here's how you put `` `backticks` `` in a code span.
6−
tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.htmldeleted−8
@@ -1,8 +0,0 @@
1−<p>In Markdown 1.0.0 and earlier. Version
2−8. This line turns into a list item.
3−Because a hard-wrapped line in the
4−middle of a paragraph looked like a
5−list item.</p>
6−
7−<p>Here's one with a bullet.
8−* criminey.</p>
tests/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.textdeleted−8
@@ -1,8 +0,0 @@
1−In Markdown 1.0.0 and earlier. Version
2−8. This line turns into a list item.
3−Because a hard-wrapped line in the
4−middle of a paragraph looked like a
5−list item.
6−
7−Here's one with a bullet.
8−* criminey.
tests/MarkdownTest_1.0.3/Tests/Horizontal rules.htmldeleted−71
@@ -1,71 +0,0 @@
1−<p>Dashes:</p>
2−
3−<hr />
4−
5−<hr />
6−
7−<hr />
8−
9−<hr />
10−
11−<pre><code>---
12−</code></pre>
13−
14−<hr />
15−
16−<hr />
17−
18−<hr />
19−
20−<hr />
21−
22−<pre><code>- - -
23−</code></pre>
24−
25−<p>Asterisks:</p>
26−
27−<hr />
28−
29−<hr />
30−
31−<hr />
32−
33−<hr />
34−
35−<pre><code>***
36−</code></pre>
37−
38−<hr />
39−
40−<hr />
41−
42−<hr />
43−
44−<hr />
45−
46−<pre><code>* * *
47−</code></pre>
48−
49−<p>Underscores:</p>
50−
51−<hr />
52−
53−<hr />
54−
55−<hr />
56−
57−<hr />
58−
59−<pre><code>___
60−</code></pre>
61−
62−<hr />
63−
64−<hr />
65−
66−<hr />
67−
68−<hr />
69−
70−<pre><code>_ _ _
71−</code></pre>
tests/MarkdownTest_1.0.3/Tests/Horizontal rules.textdeleted−67
@@ -1,67 +0,0 @@
1−Dashes:
2−
3−---
4−
5− ---
6−
7− ---
8−
9− ---
10−
11− ---
12−
13−- - -
14−
15− - - -
16−
17− - - -
18−
19− - - -
20−
21− - - -
22−
23−
24−Asterisks:
25−
26−***
27−
28− ***
29−
30− ***
31−
32− ***
33−
34− ***
35−
36−* * *
37−
38− * * *
39−
40− * * *
41−
42− * * *
43−
44− * * *
45−
46−
47−Underscores:
48−
49−___
50−
51− ___
52−
53− ___
54−
55− ___
56−
57− ___
58−
59−_ _ _
60−
61− _ _ _
62−
63− _ _ _
64−
65− _ _ _
66−
67− _ _ _
tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).htmldeleted−15
@@ -1,15 +0,0 @@
1−<p>Simple block on one line:</p>
2−
3−<div>foo</div>
4−
5−<p>And nested without indentation:</p>
6−
7−<div>
8−<div>
9−<div>
10−foo
11−</div>
12−<div style=">"/>
13−</div>
14−<div>bar</div>
15−</div>
tests/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).textdeleted−15
@@ -1,15 +0,0 @@
1−Simple block on one line:
2−
3−<div>foo</div>
4−
5−And nested without indentation:
6−
7−<div>
8−<div>
9−<div>
10−foo
11−</div>
12−<div style=">"/>
13−</div>
14−<div>bar</div>
15−</div>
tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).htmldeleted−72
@@ -1,72 +0,0 @@
1−<p>Here's a simple block:</p>
2−
3−<div>
4− foo
5−</div>
6−
7−<p>This should be a code block, though:</p>
8−
9−<pre><code>&lt;div&gt;
10− foo
11−&lt;/div&gt;
12−</code></pre>
13−
14−<p>As should this:</p>
15−
16−<pre><code>&lt;div&gt;foo&lt;/div&gt;
17−</code></pre>
18−
19−<p>Now, nested:</p>
20−
21−<div>
22− <div>
23− <div>
24− foo
25− </div>
26− </div>
27−</div>
28−
29−<p>This should just be an HTML comment:</p>
30−
31−<!-- Comment -->
32−
33−<p>Multiline:</p>
34−
35−<!--
36−Blah
37−Blah
38−-->
39−
40−<p>Code block:</p>
41−
42−<pre><code>&lt;!-- Comment --&gt;
43−</code></pre>
44−
45−<p>Just plain comment, with trailing spaces on the line:</p>
46−
47−<!-- foo -->
48−
49−<p>Code:</p>
50−
51−<pre><code>&lt;hr /&gt;
52−</code></pre>
53−
54−<p>Hr's:</p>
55−
56−<hr>
57−
58−<hr/>
59−
60−<hr />
61−
62−<hr>
63−
64−<hr/>
65−
66−<hr />
67−
68−<hr class="foo" id="bar" />
69−
70−<hr class="foo" id="bar"/>
71−
72−<hr class="foo" id="bar" >
tests/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).textdeleted−69
@@ -1,69 +0,0 @@
1−Here's a simple block:
2−
3−<div>
4− foo
5−</div>
6−
7−This should be a code block, though:
8−
9− <div>
10− foo
11− </div>
12−
13−As should this:
14−
15− <div>foo</div>
16−
17−Now, nested:
18−
19−<div>
20− <div>
21− <div>
22− foo
23− </div>
24− </div>
25−</div>
26−
27−This should just be an HTML comment:
28−
29−<!-- Comment -->
30−
31−Multiline:
32−
33−<!--
34−Blah
35−Blah
36−-->
37−
38−Code block:
39−
40− <!-- Comment -->
41−
42−Just plain comment, with trailing spaces on the line:
43−
44−<!-- foo -->
45−
46−Code:
47−
48− <hr />
49−
50−Hr's:
51−
52−<hr>
53−
54−<hr/>
55−
56−<hr />
57−
58−<hr>
59−
60−<hr/>
61−
62−<hr />
63−
64−<hr class="foo" id="bar" />
65−
66−<hr class="foo" id="bar"/>
67−
68−<hr class="foo" id="bar" >
69−
tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.htmldeleted−13
@@ -1,13 +0,0 @@
1−<p>Paragraph one.</p>
2−
3−<!-- This is a simple comment -->
4−
5−<!--
6− This is another comment.
7−-->
8−
9−<p>Paragraph two.</p>
10−
11−<!-- one comment block -- -- with two comments -->
12−
13−<p>The end.</p>
tests/MarkdownTest_1.0.3/Tests/Inline HTML comments.textdeleted−13
@@ -1,13 +0,0 @@
1−Paragraph one.
2−
3−<!-- This is a simple comment -->
4−
5−<!--
6− This is another comment.
7−-->
8−
9−Paragraph two.
10−
11−<!-- one comment block -- -- with two comments -->
12−
13−The end.
tests/MarkdownTest_1.0.3/Tests/Links, inline style.htmldeleted−11
@@ -1,11 +0,0 @@
1−<p>Just a <a href="/url/">URL</a>.</p>
2−
3−<p><a href="/url/" title="title">URL and title</a>.</p>
4−
5−<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p>
6−
7−<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p>
8−
9−<p><a href="/url/" title="title has spaces afterward">URL and title</a>.</p>
10−
11−<p><a href="">Empty</a>.</p>
tests/MarkdownTest_1.0.3/Tests/Links, inline style.textdeleted−12
@@ -1,12 +0,0 @@
1−Just a [URL](/url/).
2−
3−[URL and title](/url/ "title").
4−
5−[URL and title](/url/ "title preceded by two spaces").
6−
7−[URL and title](/url/ "title preceded by a tab").
8−
9−[URL and title](/url/ "title has spaces afterward" ).
10−
11−
12−[Empty]().
tests/MarkdownTest_1.0.3/Tests/Links, reference style.htmldeleted−52
@@ -1,52 +0,0 @@
1−<p>Foo <a href="/url/" title="Title">bar</a>.</p>
2−
3−<p>Foo <a href="/url/" title="Title">bar</a>.</p>
4−
5−<p>Foo <a href="/url/" title="Title">bar</a>.</p>
6−
7−<p>With <a href="/url/">embedded [brackets]</a>.</p>
8−
9−<p>Indented <a href="/url">once</a>.</p>
10−
11−<p>Indented <a href="/url">twice</a>.</p>
12−
13−<p>Indented <a href="/url">thrice</a>.</p>
14−
15−<p>Indented [four][] times.</p>
16−
17−<pre><code>[four]: /url
18−</code></pre>
19−
20−<hr />
21−
22−<p><a href="foo">this</a> should work</p>
23−
24−<p>So should <a href="foo">this</a>.</p>
25−
26−<p>And <a href="foo">this</a>.</p>
27−
28−<p>And <a href="foo">this</a>.</p>
29−
30−<p>And <a href="foo">this</a>.</p>
31−
32−<p>But not [that] [].</p>
33−
34−<p>Nor [that][].</p>
35−
36−<p>Nor [that].</p>
37−
38−<p>[Something in brackets like <a href="foo">this</a> should work]</p>
39−
40−<p>[Same with <a href="foo">this</a>.]</p>
41−
42−<p>In this case, <a href="/somethingelse/">this</a> points to something else.</p>
43−
44−<p>Backslashing should suppress [this] and [this].</p>
45−
46−<hr />
47−
48−<p>Here's one where the <a href="/url/">link
49−breaks</a> across lines.</p>
50−
51−<p>Here's another where the <a href="/url/">link
52−breaks</a> across lines, but with a line-ending space.</p>
tests/MarkdownTest_1.0.3/Tests/Links, reference style.textdeleted−71
@@ -1,71 +0,0 @@
1−Foo [bar] [1].
2−
3−Foo [bar][1].
4−
5−Foo [bar]
6−[1].
7−
8−[1]: /url/ "Title"
9−
10−
11−With [embedded [brackets]] [b].
12−
13−
14−Indented [once][].
15−
16−Indented [twice][].
17−
18−Indented [thrice][].
19−
20−Indented [four][] times.
21−
22− [once]: /url
23−
24− [twice]: /url
25−
26− [thrice]: /url
27−
28− [four]: /url
29−
30−
31−[b]: /url/
32−
33−* * *
34−
35−[this] [this] should work
36−
37−So should [this][this].
38−
39−And [this] [].
40−
41−And [this][].
42−
43−And [this].
44−
45−But not [that] [].
46−
47−Nor [that][].
48−
49−Nor [that].
50−
51−[Something in brackets like [this][] should work]
52−
53−[Same with [this].]
54−
55−In this case, [this](/somethingelse/) points to something else.
56−
57−Backslashing should suppress \[this] and [this\].
58−
59−[this]: foo
60−
61−
62−* * *
63−
64−Here's one where the [link
65−breaks] across lines.
66−
67−Here's another where the [link
68−breaks] across lines, but with a line-ending space.
69−
70−
71−[link breaks]: /url/
tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.htmldeleted−9
@@ -1,9 +0,0 @@
1−<p>This is the <a href="/simple">simple case</a>.</p>
2−
3−<p>This one has a <a href="/foo">line
4−break</a>.</p>
5−
6−<p>This one has a <a href="/foo">line
7−break</a> with a line-ending space.</p>
8−
9−<p><a href="/that">this</a> and the <a href="/other">other</a></p>
tests/MarkdownTest_1.0.3/Tests/Links, shortcut references.textdeleted−20
@@ -1,20 +0,0 @@
1−This is the [simple case].
2−
3−[simple case]: /simple
4−
5−
6−
7−This one has a [line
8−break].
9−
10−This one has a [line
11−break] with a line-ending space.
12−
13−[line break]: /foo
14−
15−
16−[this] [that] and the [other]
17−
18−[this]: /this
19−[that]: /that
20−[other]: /other
tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.htmldeleted−3
@@ -1,3 +0,0 @@
1−<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
2−
3−<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
tests/MarkdownTest_1.0.3/Tests/Literal quotes in titles.textdeleted−7
@@ -1,7 +0,0 @@
1−Foo [bar][].
2−
3−Foo [bar](/url/ "Title with "quotes" inside").
4−
5−
6− [bar]: /url/ "Title with "quotes" inside"
7−
tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.htmldeleted−314
@@ -1,314 +0,0 @@
1−<h1>Markdown: Basics</h1>
2−
3−<ul id="ProjectSubmenu">
4− <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
5− <li><a class="selected" title="Markdown Basics">Basics</a></li>
6− <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
7− <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
8− <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
9−</ul>
10−
11−<h2>Getting the Gist of Markdown's Formatting Syntax</h2>
12−
13−<p>This page offers a brief overview of what it's like to use Markdown.
14−The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for
15−every feature, but Markdown should be very easy to pick up simply by
16−looking at a few examples of it in action. The examples on this page
17−are written in a before/after style, showing example syntax and the
18−HTML output produced by Markdown.</p>
19−
20−<p>It's also helpful to simply try Markdown out; the <a href="/projects/markdown/dingus" title="Markdown Dingus">Dingus</a> is a
21−web application that allows you type your own Markdown-formatted text
22−and translate it to XHTML.</p>
23−
24−<p><strong>Note:</strong> This document is itself written using Markdown; you
25−can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p>
26−
27−<h2>Paragraphs, Headers, Blockquotes</h2>
28−
29−<p>A paragraph is simply one or more consecutive lines of text, separated
30−by one or more blank lines. (A blank line is any line that looks like a
31−blank line -- a line containing nothing spaces or tabs is considered
32−blank.) Normal paragraphs should not be intended with spaces or tabs.</p>
33−
34−<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>.
35−Setext-style headers for <code>&lt;h1&gt;</code> and <code>&lt;h2&gt;</code> are created by
36−"underlining" with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively.
37−To create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the
38−beginning of the line -- the number of hashes equals the resulting
39−HTML header level.</p>
40−
41−<p>Blockquotes are indicated using email-style '<code>&gt;</code>' angle brackets.</p>
42−
43−<p>Markdown:</p>
44−
45−<pre><code>A First Level Header
46−====================
47−
48−A Second Level Header
49−---------------------
50−
51−Now is the time for all good men to come to
52−the aid of their country. This is just a
53−regular paragraph.
54−
55−The quick brown fox jumped over the lazy
56−dog's back.
57−
58−### Header 3
59−
60−&gt; This is a blockquote.
61−&gt;
62−&gt; This is the second paragraph in the blockquote.
63−&gt;
64−&gt; ## This is an H2 in a blockquote
65−</code></pre>
66−
67−<p>Output:</p>
68−
69−<pre><code>&lt;h1&gt;A First Level Header&lt;/h1&gt;
70−
71−&lt;h2&gt;A Second Level Header&lt;/h2&gt;
72−
73−&lt;p&gt;Now is the time for all good men to come to
74−the aid of their country. This is just a
75−regular paragraph.&lt;/p&gt;
76−
77−&lt;p&gt;The quick brown fox jumped over the lazy
78−dog's back.&lt;/p&gt;
79−
80−&lt;h3&gt;Header 3&lt;/h3&gt;
81−
82−&lt;blockquote&gt;
83− &lt;p&gt;This is a blockquote.&lt;/p&gt;
84−
85− &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;
86−
87− &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;
88−&lt;/blockquote&gt;
89−</code></pre>
90−
91−<h3>Phrase Emphasis</h3>
92−
93−<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>
94−
95−<p>Markdown:</p>
96−
97−<pre><code>Some of these words *are emphasized*.
98−Some of these words _are emphasized also_.
99−
100−Use two asterisks for **strong emphasis**.
101−Or, if you prefer, __use two underscores instead__.
102−</code></pre>
103−
104−<p>Output:</p>
105−
106−<pre><code>&lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.
107−Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;
108−
109−&lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.
110−Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;
111−</code></pre>
112−
113−<h2>Lists</h2>
114−
115−<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,
116−<code>+</code>, and <code>-</code>) as list markers. These three markers are
117−interchangable; this:</p>
118−
119−<pre><code>* Candy.
120−* Gum.
121−* Booze.
122−</code></pre>
123−
124−<p>this:</p>
125−
126−<pre><code>+ Candy.
127−+ Gum.
128−+ Booze.
129−</code></pre>
130−
131−<p>and this:</p>
132−
133−<pre><code>- Candy.
134−- Gum.
135−- Booze.
136−</code></pre>
137−
138−<p>all produce the same output:</p>
139−
140−<pre><code>&lt;ul&gt;
141−&lt;li&gt;Candy.&lt;/li&gt;
142−&lt;li&gt;Gum.&lt;/li&gt;
143−&lt;li&gt;Booze.&lt;/li&gt;
144−&lt;/ul&gt;
145−</code></pre>
146−
147−<p>Ordered (numbered) lists use regular numbers, followed by periods, as
148−list markers:</p>
149−
150−<pre><code>1. Red
151−2. Green
152−3. Blue
153−</code></pre>
154−
155−<p>Output:</p>
156−
157−<pre><code>&lt;ol&gt;
158−&lt;li&gt;Red&lt;/li&gt;
159−&lt;li&gt;Green&lt;/li&gt;
160−&lt;li&gt;Blue&lt;/li&gt;
161−&lt;/ol&gt;
162−</code></pre>
163−
164−<p>If you put blank lines between items, you'll get <code>&lt;p&gt;</code> tags for the
165−list item text. You can create multi-paragraph list items by indenting
166−the paragraphs by 4 spaces or 1 tab:</p>
167−
168−<pre><code>* A list item.
169−
170− With multiple paragraphs.
171−
172−* Another item in the list.
173−</code></pre>
174−
175−<p>Output:</p>
176−
177−<pre><code>&lt;ul&gt;
178−&lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;
179−&lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;
180−&lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;
181−&lt;/ul&gt;
182−</code></pre>
183−
184−<h3>Links</h3>
185−
186−<p>Markdown supports two styles for creating links: <em>inline</em> and
187−<em>reference</em>. With both styles, you use square brackets to delimit the
188−text you want to turn into a link.</p>
189−
190−<p>Inline-style links use parentheses immediately after the link text.
191−For example:</p>
192−
193−<pre><code>This is an [example link](http://example.com/).
194−</code></pre>
195−
196−<p>Output:</p>
197−
198−<pre><code>&lt;p&gt;This is an &lt;a href="http://example.com/"&gt;
199−example link&lt;/a&gt;.&lt;/p&gt;
200−</code></pre>
201−
202−<p>Optionally, you may include a title attribute in the parentheses:</p>
203−
204−<pre><code>This is an [example link](http://example.com/ "With a Title").
205−</code></pre>
206−
207−<p>Output:</p>
208−
209−<pre><code>&lt;p&gt;This is an &lt;a href="http://example.com/" title="With a Title"&gt;
210−example link&lt;/a&gt;.&lt;/p&gt;
211−</code></pre>
212−
213−<p>Reference-style links allow you to refer to your links by names, which
214−you define elsewhere in your document:</p>
215−
216−<pre><code>I get 10 times more traffic from [Google][1] than from
217−[Yahoo][2] or [MSN][3].
218−
219−[1]: http://google.com/ "Google"
220−[2]: http://search.yahoo.com/ "Yahoo Search"
221−[3]: http://search.msn.com/ "MSN Search"
222−</code></pre>
223−
224−<p>Output:</p>
225−
226−<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"
227−title="Google"&gt;Google&lt;/a&gt; than from &lt;a href="http://search.yahoo.com/"
228−title="Yahoo Search"&gt;Yahoo&lt;/a&gt; or &lt;a href="http://search.msn.com/"
229−title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;
230−</code></pre>
231−
232−<p>The title attribute is optional. Link names may contain letters,
233−numbers and spaces, but are <em>not</em> case sensitive:</p>
234−
235−<pre><code>I start my morning with a cup of coffee and
236−[The New York Times][NY Times].
237−
238−[ny times]: http://www.nytimes.com/
239−</code></pre>
240−
241−<p>Output:</p>
242−
243−<pre><code>&lt;p&gt;I start my morning with a cup of coffee and
244−&lt;a href="http://www.nytimes.com/"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
245−</code></pre>
246−
247−<h3>Images</h3>
248−
249−<p>Image syntax is very much like link syntax.</p>
250−
251−<p>Inline (titles are optional):</p>
252−
253−<pre><code>![alt text](/path/to/img.jpg "Title")
254−</code></pre>
255−
256−<p>Reference-style:</p>
257−
258−<pre><code>![alt text][id]
259−
260−[id]: /path/to/img.jpg "Title"
261−</code></pre>
262−
263−<p>Both of the above examples produce the same output:</p>
264−
265−<pre><code>&lt;img src="/path/to/img.jpg" alt="alt text" title="Title" /&gt;
266−</code></pre>
267−
268−<h3>Code</h3>
269−
270−<p>In a regular paragraph, you can create code span by wrapping text in
271−backtick quotes. Any ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> or
272−<code>&gt;</code>) will automatically be translated into HTML entities. This makes
273−it easy to use Markdown to write about HTML example code:</p>
274−
275−<pre><code>I strongly recommend against using any `&lt;blink&gt;` tags.
276−
277−I wish SmartyPants used named entities like `&amp;mdash;`
278−instead of decimal-encoded entites like `&amp;#8212;`.
279−</code></pre>
280−
281−<p>Output:</p>
282−
283−<pre><code>&lt;p&gt;I strongly recommend against using any
284−&lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
285−
286−&lt;p&gt;I wish SmartyPants used named entities like
287−&lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded
288−entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;
289−</code></pre>
290−
291−<p>To specify an entire block of pre-formatted code, indent every line of
292−the block by 4 spaces or 1 tab. Just like with code spans, <code>&amp;</code>, <code>&lt;</code>,
293−and <code>&gt;</code> characters will be escaped automatically.</p>
294−
295−<p>Markdown:</p>
296−
297−<pre><code>If you want your page to validate under XHTML 1.0 Strict,
298−you've got to put paragraph tags in your blockquotes:
299−
300− &lt;blockquote&gt;
301− &lt;p&gt;For example.&lt;/p&gt;
302− &lt;/blockquote&gt;
303−</code></pre>
304−
305−<p>Output:</p>
306−
307−<pre><code>&lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,
308−you've got to put paragraph tags in your blockquotes:&lt;/p&gt;
309−
310−&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;
311− &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;
312−&amp;lt;/blockquote&amp;gt;
313−&lt;/code&gt;&lt;/pre&gt;
314−</code></pre>
tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.textdeleted−306
@@ -1,306 +0,0 @@
1−Markdown: Basics
2−================
3−
4−<ul id="ProjectSubmenu">
5− <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
6− <li><a class="selected" title="Markdown Basics">Basics</a></li>
7− <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
8− <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
9− <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
10−</ul>
11−
12−
13−Getting the Gist of Markdown's Formatting Syntax
14−------------------------------------------------
15−
16−This page offers a brief overview of what it's like to use Markdown.
17−The [syntax page] [s] provides complete, detailed documentation for
18−every feature, but Markdown should be very easy to pick up simply by
19−looking at a few examples of it in action. The examples on this page
20−are written in a before/after style, showing example syntax and the
21−HTML output produced by Markdown.
22−
23−It's also helpful to simply try Markdown out; the [Dingus] [d] is a
24−web application that allows you type your own Markdown-formatted text
25−and translate it to XHTML.
26−
27−**Note:** This document is itself written using Markdown; you
28−can [see the source for it by adding '.text' to the URL] [src].
29−
30− [s]: /projects/markdown/syntax "Markdown Syntax"
31− [d]: /projects/markdown/dingus "Markdown Dingus"
32− [src]: /projects/markdown/basics.text
33−
34−
35−## Paragraphs, Headers, Blockquotes ##
36−
37−A paragraph is simply one or more consecutive lines of text, separated
38−by one or more blank lines. (A blank line is any line that looks like a
39−blank line -- a line containing nothing spaces or tabs is considered
40−blank.) Normal paragraphs should not be intended with spaces or tabs.
41−
42−Markdown offers two styles of headers: *Setext* and *atx*.
43−Setext-style headers for `<h1>` and `<h2>` are created by
44−"underlining" with equal signs (`=`) and hyphens (`-`), respectively.
45−To create an atx-style header, you put 1-6 hash marks (`#`) at the
46−beginning of the line -- the number of hashes equals the resulting
47−HTML header level.
48−
49−Blockquotes are indicated using email-style '`>`' angle brackets.
50−
51−Markdown:
52−
53− A First Level Header
54− ====================
55−
56− A Second Level Header
57− ---------------------
58−
59− Now is the time for all good men to come to
60− the aid of their country. This is just a
61− regular paragraph.
62−
63− The quick brown fox jumped over the lazy
64− dog's back.
65−
66− ### Header 3
67−
68− > This is a blockquote.
69− >
70− > This is the second paragraph in the blockquote.
71− >
72− > ## This is an H2 in a blockquote
73−
74−
75−Output:
76−
77− <h1>A First Level Header</h1>
78−
79− <h2>A Second Level Header</h2>
80−
81− <p>Now is the time for all good men to come to
82− the aid of their country. This is just a
83− regular paragraph.</p>
84−
85− <p>The quick brown fox jumped over the lazy
86− dog's back.</p>
87−
88− <h3>Header 3</h3>
89−
90− <blockquote>
91− <p>This is a blockquote.</p>
92−
93− <p>This is the second paragraph in the blockquote.</p>
94−
95− <h2>This is an H2 in a blockquote</h2>
96− </blockquote>
97−
98−
99−
100−### Phrase Emphasis ###
101−
102−Markdown uses asterisks and underscores to indicate spans of emphasis.
103−
104−Markdown:
105−
106− Some of these words *are emphasized*.
107− Some of these words _are emphasized also_.
108−
109− Use two asterisks for **strong emphasis**.
110− Or, if you prefer, __use two underscores instead__.
111−
112−Output:
113−
114− <p>Some of these words <em>are emphasized</em>.
115− Some of these words <em>are emphasized also</em>.</p>
116−
117− <p>Use two asterisks for <strong>strong emphasis</strong>.
118− Or, if you prefer, <strong>use two underscores instead</strong>.</p>
119−
120−
121−
122−## Lists ##
123−
124−Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
125−`+`, and `-`) as list markers. These three markers are
126−interchangable; this:
127−
128− * Candy.
129− * Gum.
130− * Booze.
131−
132−this:
133−
134− + Candy.
135− + Gum.
136− + Booze.
137−
138−and this:
139−
140− - Candy.
141− - Gum.
142− - Booze.
143−
144−all produce the same output:
145−
146− <ul>
147− <li>Candy.</li>
148− <li>Gum.</li>
149− <li>Booze.</li>
150− </ul>
151−
152−Ordered (numbered) lists use regular numbers, followed by periods, as
153−list markers:
154−
155− 1. Red
156− 2. Green
157− 3. Blue
158−
159−Output:
160−
161− <ol>
162− <li>Red</li>
163− <li>Green</li>
164− <li>Blue</li>
165− </ol>
166−
167−If you put blank lines between items, you'll get `<p>` tags for the
168−list item text. You can create multi-paragraph list items by indenting
169−the paragraphs by 4 spaces or 1 tab:
170−
171− * A list item.
172−
173− With multiple paragraphs.
174−
175− * Another item in the list.
176−
177−Output:
178−
179− <ul>
180− <li><p>A list item.</p>
181− <p>With multiple paragraphs.</p></li>
182− <li><p>Another item in the list.</p></li>
183− </ul>
184−
185−
186−
187−### Links ###
188−
189−Markdown supports two styles for creating links: *inline* and
190−*reference*. With both styles, you use square brackets to delimit the
191−text you want to turn into a link.
192−
193−Inline-style links use parentheses immediately after the link text.
194−For example:
195−
196− This is an [example link](http://example.com/).
197−
198−Output:
199−
200− <p>This is an <a href="http://example.com/">
201− example link</a>.</p>
202−
203−Optionally, you may include a title attribute in the parentheses:
204−
205− This is an [example link](http://example.com/ "With a Title").
206−
207−Output:
208−
209− <p>This is an <a href="http://example.com/" title="With a Title">
210− example link</a>.</p>
211−
212−Reference-style links allow you to refer to your links by names, which
213−you define elsewhere in your document:
214−
215− I get 10 times more traffic from [Google][1] than from
216− [Yahoo][2] or [MSN][3].
217−
218− [1]: http://google.com/ "Google"
219− [2]: http://search.yahoo.com/ "Yahoo Search"
220− [3]: http://search.msn.com/ "MSN Search"
221−
222−Output:
223−
224− <p>I get 10 times more traffic from <a href="http://google.com/"
225− title="Google">Google</a> than from <a href="http://search.yahoo.com/"
226− title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
227− title="MSN Search">MSN</a>.</p>
228−
229−The title attribute is optional. Link names may contain letters,
230−numbers and spaces, but are *not* case sensitive:
231−
232− I start my morning with a cup of coffee and
233− [The New York Times][NY Times].
234−
235− [ny times]: http://www.nytimes.com/
236−
237−Output:
238−
239− <p>I start my morning with a cup of coffee and
240− <a href="http://www.nytimes.com/">The New York Times</a>.</p>
241−
242−
243−### Images ###
244−
245−Image syntax is very much like link syntax.
246−
247−Inline (titles are optional):
248−
249− ![alt text](/path/to/img.jpg "Title")
250−
251−Reference-style:
252−
253− ![alt text][id]
254−
255− [id]: /path/to/img.jpg "Title"
256−
257−Both of the above examples produce the same output:
258−
259− <img src="/path/to/img.jpg" alt="alt text" title="Title" />
260−
261−
262−
263−### Code ###
264−
265−In a regular paragraph, you can create code span by wrapping text in
266−backtick quotes. Any ampersands (`&`) and angle brackets (`<` or
267−`>`) will automatically be translated into HTML entities. This makes
268−it easy to use Markdown to write about HTML example code:
269−
270− I strongly recommend against using any `<blink>` tags.
271−
272− I wish SmartyPants used named entities like `&mdash;`
273− instead of decimal-encoded entites like `&#8212;`.
274−
275−Output:
276−
277− <p>I strongly recommend against using any
278− <code>&lt;blink&gt;</code> tags.</p>
279−
280− <p>I wish SmartyPants used named entities like
281− <code>&amp;mdash;</code> instead of decimal-encoded
282− entites like <code>&amp;#8212;</code>.</p>
283−
284−
285−To specify an entire block of pre-formatted code, indent every line of
286−the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,
287−and `>` characters will be escaped automatically.
288−
289−Markdown:
290−
291− If you want your page to validate under XHTML 1.0 Strict,
292− you've got to put paragraph tags in your blockquotes:
293−
294− <blockquote>
295− <p>For example.</p>
296− </blockquote>
297−
298−Output:
299−
300− <p>If you want your page to validate under XHTML 1.0 Strict,
301− you've got to put paragraph tags in your blockquotes:</p>
302−
303− <pre><code>&lt;blockquote&gt;
304− &lt;p&gt;For example.&lt;/p&gt;
305− &lt;/blockquote&gt;
306− </code></pre>
tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.htmldeleted−942
@@ -1,942 +0,0 @@
1−<h1>Markdown: Syntax</h1>
2−
3−<ul id="ProjectSubmenu">
4− <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
5− <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li>
6− <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li>
7− <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
8− <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
9−</ul>
10−
11−<ul>
12−<li><a href="#overview">Overview</a>
13−<ul>
14−<li><a href="#philosophy">Philosophy</a></li>
15−<li><a href="#html">Inline HTML</a></li>
16−<li><a href="#autoescape">Automatic Escaping for Special Characters</a></li>
17−</ul></li>
18−<li><a href="#block">Block Elements</a>
19−<ul>
20−<li><a href="#p">Paragraphs and Line Breaks</a></li>
21−<li><a href="#header">Headers</a></li>
22−<li><a href="#blockquote">Blockquotes</a></li>
23−<li><a href="#list">Lists</a></li>
24−<li><a href="#precode">Code Blocks</a></li>
25−<li><a href="#hr">Horizontal Rules</a></li>
26−</ul></li>
27−<li><a href="#span">Span Elements</a>
28−<ul>
29−<li><a href="#link">Links</a></li>
30−<li><a href="#em">Emphasis</a></li>
31−<li><a href="#code">Code</a></li>
32−<li><a href="#img">Images</a></li>
33−</ul></li>
34−<li><a href="#misc">Miscellaneous</a>
35−<ul>
36−<li><a href="#backslash">Backslash Escapes</a></li>
37−<li><a href="#autolink">Automatic Links</a></li>
38−</ul></li>
39−</ul>
40−
41−<p><strong>Note:</strong> This document is itself written using Markdown; you
42−can <a href="/projects/markdown/syntax.text">see the source for it by adding '.text' to the URL</a>.</p>
43−
44−<hr />
45−
46−<h2 id="overview">Overview</h2>
47−
48−<h3 id="philosophy">Philosophy</h3>
49−
50−<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>
51−
52−<p>Readability, however, is emphasized above all else. A Markdown-formatted
53−document should be publishable as-is, as plain text, without looking
54−like it's been marked up with tags or formatting instructions. While
55−Markdown's syntax has been influenced by several existing text-to-HTML
56−filters -- including <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a>, <a href="http://www.aaronsw.com/2002/atx/">atx</a>, <a href="http://textism.com/tools/textile/">Textile</a>, <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>,
57−<a href="http://www.triptico.com/software/grutatxt.html">Grutatext</a>, and <a href="http://ettext.taint.org/doc/">EtText</a> -- the single biggest source of
58−inspiration for Markdown's syntax is the format of plain text email.</p>
59−
60−<p>To this end, Markdown's syntax is comprised entirely of punctuation
61−characters, which punctuation characters have been carefully chosen so
62−as to look like what they mean. E.g., asterisks around a word actually
63−look like *emphasis*. Markdown lists look like, well, lists. Even
64−blockquotes look like quoted passages of text, assuming you've ever
65−used email.</p>
66−
67−<h3 id="html">Inline HTML</h3>
68−
69−<p>Markdown's syntax is intended for one purpose: to be used as a
70−format for <em>writing</em> for the web.</p>
71−
72−<p>Markdown is not a replacement for HTML, or even close to it. Its
73−syntax is very small, corresponding only to a very small subset of
74−HTML tags. The idea is <em>not</em> to create a syntax that makes it easier
75−to insert HTML tags. In my opinion, HTML tags are already easy to
76−insert. The idea for Markdown is to make it easy to read, write, and
77−edit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em>
78−format. Thus, Markdown's formatting syntax only addresses issues that
79−can be conveyed in plain text.</p>
80−
81−<p>For any markup that is not covered by Markdown's syntax, you simply
82−use HTML itself. There's no need to preface it or delimit it to
83−indicate that you're switching from Markdown to HTML; you just use
84−the tags.</p>
85−
86−<p>The only restrictions are that block-level HTML elements -- e.g. <code>&lt;div&gt;</code>,
87−<code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>, <code>&lt;p&gt;</code>, etc. -- must be separated from surrounding
88−content by blank lines, and the start and end tags of the block should
89−not be indented with tabs or spaces. Markdown is smart enough not
90−to add extra (unwanted) <code>&lt;p&gt;</code> tags around HTML block-level tags.</p>
91−
92−<p>For example, to add an HTML table to a Markdown article:</p>
93−
94−<pre><code>This is a regular paragraph.
95−
96−&lt;table&gt;
97− &lt;tr&gt;
98− &lt;td&gt;Foo&lt;/td&gt;
99− &lt;/tr&gt;
100−&lt;/table&gt;
101−
102−This is another regular paragraph.
103−</code></pre>
104−
105−<p>Note that Markdown formatting syntax is not processed within block-level
106−HTML tags. E.g., you can't use Markdown-style <code>*emphasis*</code> inside an
107−HTML block.</p>
108−
109−<p>Span-level HTML tags -- e.g. <code>&lt;span&gt;</code>, <code>&lt;cite&gt;</code>, or <code>&lt;del&gt;</code> -- can be
110−used anywhere in a Markdown paragraph, list item, or header. If you
111−want, you can even use HTML tags instead of Markdown formatting; e.g. if
112−you'd prefer to use HTML <code>&lt;a&gt;</code> or <code>&lt;img&gt;</code> tags instead of Markdown's
113−link or image syntax, go right ahead.</p>
114−
115−<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within
116−span-level tags.</p>
117−
118−<h3 id="autoescape">Automatic Escaping for Special Characters</h3>
119−
120−<p>In HTML, there are two characters that demand special treatment: <code>&lt;</code>
121−and <code>&amp;</code>. Left angle brackets are used to start tags; ampersands are
122−used to denote HTML entities. If you want to use them as literal
123−characters, you must escape them as entities, e.g. <code>&amp;lt;</code>, and
124−<code>&amp;amp;</code>.</p>
125−
126−<p>Ampersands in particular are bedeviling for web writers. If you want to
127−write about 'AT&amp;T', you need to write '<code>AT&amp;amp;T</code>'. You even need to
128−escape ampersands within URLs. Thus, if you want to link to:</p>
129−
130−<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird
131−</code></pre>
132−
133−<p>you need to encode the URL as:</p>
134−
135−<pre><code>http://images.google.com/images?num=30&amp;amp;q=larry+bird
136−</code></pre>
137−
138−<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to
139−forget, and is probably the single most common source of HTML validation
140−errors in otherwise well-marked-up web sites.</p>
141−
142−<p>Markdown allows you to use these characters naturally, taking care of
143−all the necessary escaping for you. If you use an ampersand as part of
144−an HTML entity, it remains unchanged; otherwise it will be translated
145−into <code>&amp;amp;</code>.</p>
146−
147−<p>So, if you want to include a copyright symbol in your article, you can write:</p>
148−
149−<pre><code>&amp;copy;
150−</code></pre>
151−
152−<p>and Markdown will leave it alone. But if you write:</p>
153−
154−<pre><code>AT&amp;T
155−</code></pre>
156−
157−<p>Markdown will translate it to:</p>
158−
159−<pre><code>AT&amp;amp;T
160−</code></pre>
161−
162−<p>Similarly, because Markdown supports <a href="#html">inline HTML</a>, if you use
163−angle brackets as delimiters for HTML tags, Markdown will treat them as
164−such. But if you write:</p>
165−
166−<pre><code>4 &lt; 5
167−</code></pre>
168−
169−<p>Markdown will translate it to:</p>
170−
171−<pre><code>4 &amp;lt; 5
172−</code></pre>
173−
174−<p>However, inside Markdown code spans and blocks, angle brackets and
175−ampersands are <em>always</em> encoded automatically. This makes it easy to use
176−Markdown to write about HTML code. (As opposed to raw HTML, which is a
177−terrible format for writing about HTML syntax, because every single <code>&lt;</code>
178−and <code>&amp;</code> in your example code needs to be escaped.)</p>
179−
180−<hr />
181−
182−<h2 id="block">Block Elements</h2>
183−
184−<h3 id="p">Paragraphs and Line Breaks</h3>
185−
186−<p>A paragraph is simply one or more consecutive lines of text, separated
187−by one or more blank lines. (A blank line is any line that looks like a
188−blank line -- a line containing nothing but spaces or tabs is considered
189−blank.) Normal paragraphs should not be intended with spaces or tabs.</p>
190−
191−<p>The implication of the "one or more consecutive lines of text" rule is
192−that Markdown supports "hard-wrapped" text paragraphs. This differs
193−significantly from most other text-to-HTML formatters (including Movable
194−Type's "Convert Line Breaks" option) which translate every line break
195−character in a paragraph into a <code>&lt;br /&gt;</code> tag.</p>
196−
197−<p>When you <em>do</em> want to insert a <code>&lt;br /&gt;</code> break tag using Markdown, you
198−end a line with two or more spaces, then type return.</p>
199−
200−<p>Yes, this takes a tad more effort to create a <code>&lt;br /&gt;</code>, but a simplistic
201−"every line break is a <code>&lt;br /&gt;</code>" rule wouldn't work for Markdown.
202−Markdown's email-style <a href="#blockquote">blockquoting</a> and multi-paragraph <a href="#list">list items</a>
203−work best -- and look better -- when you format them with hard breaks.</p>
204−
205−<h3 id="header">Headers</h3>
206−
207−<p>Markdown supports two styles of headers, <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a> and <a href="http://www.aaronsw.com/2002/atx/">atx</a>.</p>
208−
209−<p>Setext-style headers are "underlined" using equal signs (for first-level
210−headers) and dashes (for second-level headers). For example:</p>
211−
212−<pre><code>This is an H1
213−=============
214−
215−This is an H2
216−-------------
217−</code></pre>
218−
219−<p>Any number of underlining <code>=</code>'s or <code>-</code>'s will work.</p>
220−
221−<p>Atx-style headers use 1-6 hash characters at the start of the line,
222−corresponding to header levels 1-6. For example:</p>
223−
224−<pre><code># This is an H1
225−
226−## This is an H2
227−
228−###### This is an H6
229−</code></pre>
230−
231−<p>Optionally, you may "close" atx-style headers. This is purely
232−cosmetic -- you can use this if you think it looks better. The
233−closing hashes don't even need to match the number of hashes
234−used to open the header. (The number of opening hashes
235−determines the header level.) :</p>
236−
237−<pre><code># This is an H1 #
238−
239−## This is an H2 ##
240−
241−### This is an H3 ######
242−</code></pre>
243−
244−<h3 id="blockquote">Blockquotes</h3>
245−
246−<p>Markdown uses email-style <code>&gt;</code> characters for blockquoting. If you're
247−familiar with quoting passages of text in an email message, then you
248−know how to create a blockquote in Markdown. It looks best if you hard
249−wrap the text and put a <code>&gt;</code> before every line:</p>
250−
251−<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
252−&gt; consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
253−&gt; Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
254−&gt;
255−&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
256−&gt; id sem consectetuer libero luctus adipiscing.
257−</code></pre>
258−
259−<p>Markdown allows you to be lazy and only put the <code>&gt;</code> before the first
260−line of a hard-wrapped paragraph:</p>
261−
262−<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
263−consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
264−Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
265−
266−&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
267−id sem consectetuer libero luctus adipiscing.
268−</code></pre>
269−
270−<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
271−adding additional levels of <code>&gt;</code>:</p>
272−
273−<pre><code>&gt; This is the first level of quoting.
274−&gt;
275−&gt; &gt; This is nested blockquote.
276−&gt;
277−&gt; Back to the first level.
278−</code></pre>
279−
280−<p>Blockquotes can contain other Markdown elements, including headers, lists,
281−and code blocks:</p>
282−
283−<pre><code>&gt; ## This is a header.
284−&gt;
285−&gt; 1. This is the first list item.
286−&gt; 2. This is the second list item.
287−&gt;
288−&gt; Here's some example code:
289−&gt;
290−&gt; return shell_exec("echo $input | $markdown_script");
291−</code></pre>
292−
293−<p>Any decent text editor should make email-style quoting easy. For
294−example, with BBEdit, you can make a selection and choose Increase
295−Quote Level from the Text menu.</p>
296−
297−<h3 id="list">Lists</h3>
298−
299−<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p>
300−
301−<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably
302−-- as list markers:</p>
303−
304−<pre><code>* Red
305−* Green
306−* Blue
307−</code></pre>
308−
309−<p>is equivalent to:</p>
310−
311−<pre><code>+ Red
312−+ Green
313−+ Blue
314−</code></pre>
315−
316−<p>and:</p>
317−
318−<pre><code>- Red
319−- Green
320−- Blue
321−</code></pre>
322−
323−<p>Ordered lists use numbers followed by periods:</p>
324−
325−<pre><code>1. Bird
326−2. McHale
327−3. Parish
328−</code></pre>
329−
330−<p>It's important to note that the actual numbers you use to mark the
331−list have no effect on the HTML output Markdown produces. The HTML
332−Markdown produces from the above list is:</p>
333−
334−<pre><code>&lt;ol&gt;
335−&lt;li&gt;Bird&lt;/li&gt;
336−&lt;li&gt;McHale&lt;/li&gt;
337−&lt;li&gt;Parish&lt;/li&gt;
338−&lt;/ol&gt;
339−</code></pre>
340−
341−<p>If you instead wrote the list in Markdown like this:</p>
342−
343−<pre><code>1. Bird
344−1. McHale
345−1. Parish
346−</code></pre>
347−
348−<p>or even:</p>
349−
350−<pre><code>3. Bird
351−1. McHale
352−8. Parish
353−</code></pre>
354−
355−<p>you'd get the exact same HTML output. The point is, if you want to,
356−you can use ordinal numbers in your ordered Markdown lists, so that
357−the numbers in your source match the numbers in your published HTML.
358−But if you want to be lazy, you don't have to.</p>
359−
360−<p>If you do use lazy list numbering, however, you should still start the
361−list with the number 1. At some point in the future, Markdown may support
362−starting ordered lists at an arbitrary number.</p>
363−
364−<p>List markers typically start at the left margin, but may be indented by
365−up to three spaces. List markers must be followed by one or more spaces
366−or a tab.</p>
367−
368−<p>To make lists look nice, you can wrap items with hanging indents:</p>
369−
370−<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
371− Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
372− viverra nec, fringilla in, laoreet vitae, risus.
373−* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
374− Suspendisse id sem consectetuer libero luctus adipiscing.
375−</code></pre>
376−
377−<p>But if you want to be lazy, you don't have to:</p>
378−
379−<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
380−Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
381−viverra nec, fringilla in, laoreet vitae, risus.
382−* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
383−Suspendisse id sem consectetuer libero luctus adipiscing.
384−</code></pre>
385−
386−<p>If list items are separated by blank lines, Markdown will wrap the
387−items in <code>&lt;p&gt;</code> tags in the HTML output. For example, this input:</p>
388−
389−<pre><code>* Bird
390−* Magic
391−</code></pre>
392−
393−<p>will turn into:</p>
394−
395−<pre><code>&lt;ul&gt;
396−&lt;li&gt;Bird&lt;/li&gt;
397−&lt;li&gt;Magic&lt;/li&gt;
398−&lt;/ul&gt;
399−</code></pre>
400−
401−<p>But this:</p>
402−
403−<pre><code>* Bird
404−
405−* Magic
406−</code></pre>
407−
408−<p>will turn into:</p>
409−
410−<pre><code>&lt;ul&gt;
411−&lt;li&gt;&lt;p&gt;Bird&lt;/p&gt;&lt;/li&gt;
412−&lt;li&gt;&lt;p&gt;Magic&lt;/p&gt;&lt;/li&gt;
413−&lt;/ul&gt;
414−</code></pre>
415−
416−<p>List items may consist of multiple paragraphs. Each subsequent
417−paragraph in a list item must be intended by either 4 spaces
418−or one tab:</p>
419−
420−<pre><code>1. This is a list item with two paragraphs. Lorem ipsum dolor
421− sit amet, consectetuer adipiscing elit. Aliquam hendrerit
422− mi posuere lectus.
423−
424− Vestibulum enim wisi, viverra nec, fringilla in, laoreet
425− vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
426− sit amet velit.
427−
428−2. Suspendisse id sem consectetuer libero luctus adipiscing.
429−</code></pre>
430−
431−<p>It looks nice if you indent every line of the subsequent
432−paragraphs, but here again, Markdown will allow you to be
433−lazy:</p>
434−
435−<pre><code>* This is a list item with two paragraphs.
436−
437− This is the second paragraph in the list item. You're
438−only required to indent the first line. Lorem ipsum dolor
439−sit amet, consectetuer adipiscing elit.
440−
441−* Another item in the same list.
442−</code></pre>
443−
444−<p>To put a blockquote within a list item, the blockquote's <code>&gt;</code>
445−delimiters need to be indented:</p>
446−
447−<pre><code>* A list item with a blockquote:
448−
449− &gt; This is a blockquote
450− &gt; inside a list item.
451−</code></pre>
452−
453−<p>To put a code block within a list item, the code block needs
454−to be indented <em>twice</em> -- 8 spaces or two tabs:</p>
455−
456−<pre><code>* A list item with a code block:
457−
458− &lt;code goes here&gt;
459−</code></pre>
460−
461−<p>It's worth noting that it's possible to trigger an ordered list by
462−accident, by writing something like this:</p>
463−
464−<pre><code>1986. What a great season.
465−</code></pre>
466−
467−<p>In other words, a <em>number-period-space</em> sequence at the beginning of a
468−line. To avoid this, you can backslash-escape the period:</p>
469−
470−<pre><code>1986\. What a great season.
471−</code></pre>
472−
473−<h3 id="precode">Code Blocks</h3>
474−
475−<p>Pre-formatted code blocks are used for writing about programming or
476−markup source code. Rather than forming normal paragraphs, the lines
477−of a code block are interpreted literally. Markdown wraps a code block
478−in both <code>&lt;pre&gt;</code> and <code>&lt;code&gt;</code> tags.</p>
479−
480−<p>To produce a code block in Markdown, simply indent every line of the
481−block by at least 4 spaces or 1 tab. For example, given this input:</p>
482−
483−<pre><code>This is a normal paragraph:
484−
485− This is a code block.
486−</code></pre>
487−
488−<p>Markdown will generate:</p>
489−
490−<pre><code>&lt;p&gt;This is a normal paragraph:&lt;/p&gt;
491−
492−&lt;pre&gt;&lt;code&gt;This is a code block.
493−&lt;/code&gt;&lt;/pre&gt;
494−</code></pre>
495−
496−<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each
497−line of the code block. For example, this:</p>
498−
499−<pre><code>Here is an example of AppleScript:
500−
501− tell application "Foo"
502− beep
503− end tell
504−</code></pre>
505−
506−<p>will turn into:</p>
507−
508−<pre><code>&lt;p&gt;Here is an example of AppleScript:&lt;/p&gt;
509−
510−&lt;pre&gt;&lt;code&gt;tell application "Foo"
511− beep
512−end tell
513−&lt;/code&gt;&lt;/pre&gt;
514−</code></pre>
515−
516−<p>A code block continues until it reaches a line that is not indented
517−(or the end of the article).</p>
518−
519−<p>Within a code block, ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> and <code>&gt;</code>)
520−are automatically converted into HTML entities. This makes it very
521−easy to include example HTML source code using Markdown -- just paste
522−it and indent it, and Markdown will handle the hassle of encoding the
523−ampersands and angle brackets. For example, this:</p>
524−
525−<pre><code> &lt;div class="footer"&gt;
526− &amp;copy; 2004 Foo Corporation
527− &lt;/div&gt;
528−</code></pre>
529−
530−<p>will turn into:</p>
531−
532−<pre><code>&lt;pre&gt;&lt;code&gt;&amp;lt;div class="footer"&amp;gt;
533− &amp;amp;copy; 2004 Foo Corporation
534−&amp;lt;/div&amp;gt;
535−&lt;/code&gt;&lt;/pre&gt;
536−</code></pre>
537−
538−<p>Regular Markdown syntax is not processed within code blocks. E.g.,
539−asterisks are just literal asterisks within a code block. This means
540−it's also easy to use Markdown to write about Markdown's own syntax.</p>
541−
542−<h3 id="hr">Horizontal Rules</h3>
543−
544−<p>You can produce a horizontal rule tag (<code>&lt;hr /&gt;</code>) by placing three or
545−more hyphens, asterisks, or underscores on a line by themselves. If you
546−wish, you may use spaces between the hyphens or asterisks. Each of the
547−following lines will produce a horizontal rule:</p>
548−
549−<pre><code>* * *
550−
551−***
552−
553−*****
554−
555−- - -
556−
557−---------------------------------------
558−
559−_ _ _
560−</code></pre>
561−
562−<hr />
563−
564−<h2 id="span">Span Elements</h2>
565−
566−<h3 id="link">Links</h3>
567−
568−<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p>
569−
570−<p>In both styles, the link text is delimited by [square brackets].</p>
571−
572−<p>To create an inline link, use a set of regular parentheses immediately
573−after the link text's closing square bracket. Inside the parentheses,
574−put the URL where you want the link to point, along with an <em>optional</em>
575−title for the link, surrounded in quotes. For example:</p>
576−
577−<pre><code>This is [an example](http://example.com/ "Title") inline link.
578−
579−[This link](http://example.net/) has no title attribute.
580−</code></pre>
581−
582−<p>Will produce:</p>
583−
584−<pre><code>&lt;p&gt;This is &lt;a href="http://example.com/" title="Title"&gt;
585−an example&lt;/a&gt; inline link.&lt;/p&gt;
586−
587−&lt;p&gt;&lt;a href="http://example.net/"&gt;This link&lt;/a&gt; has no
588−title attribute.&lt;/p&gt;
589−</code></pre>
590−
591−<p>If you're referring to a local resource on the same server, you can
592−use relative paths:</p>
593−
594−<pre><code>See my [About](/about/) page for details.
595−</code></pre>
596−
597−<p>Reference-style links use a second set of square brackets, inside
598−which you place a label of your choosing to identify the link:</p>
599−
600−<pre><code>This is [an example][id] reference-style link.
601−</code></pre>
602−
603−<p>You can optionally use a space to separate the sets of brackets:</p>
604−
605−<pre><code>This is [an example] [id] reference-style link.
606−</code></pre>
607−
608−<p>Then, anywhere in the document, you define your link label like this,
609−on a line by itself:</p>
610−
611−<pre><code>[id]: http://example.com/ "Optional Title Here"
612−</code></pre>
613−
614−<p>That is:</p>
615−
616−<ul>
617−<li>Square brackets containing the link identifier (optionally
618−indented from the left margin using up to three spaces);</li>
619−<li>followed by a colon;</li>
620−<li>followed by one or more spaces (or tabs);</li>
621−<li>followed by the URL for the link;</li>
622−<li>optionally followed by a title attribute for the link, enclosed
623−in double or single quotes.</li>
624−</ul>
625−
626−<p>The link URL may, optionally, be surrounded by angle brackets:</p>
627−
628−<pre><code>[id]: &lt;http://example.com/&gt; "Optional Title Here"
629−</code></pre>
630−
631−<p>You can put the title attribute on the next line and use extra spaces
632−or tabs for padding, which tends to look better with longer URLs:</p>
633−
634−<pre><code>[id]: http://example.com/longish/path/to/resource/here
635− "Optional Title Here"
636−</code></pre>
637−
638−<p>Link definitions are only used for creating links during Markdown
639−processing, and are stripped from your document in the HTML output.</p>
640−
641−<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p>
642−
643−<pre><code>[link text][a]
644−[link text][A]
645−</code></pre>
646−
647−<p>are equivalent.</p>
648−
649−<p>The <em>implicit link name</em> shortcut allows you to omit the name of the
650−link, in which case the link text itself is used as the name.
651−Just use an empty set of square brackets -- e.g., to link the word
652−"Google" to the google.com web site, you could simply write:</p>
653−
654−<pre><code>[Google][]
655−</code></pre>
656−
657−<p>And then define the link:</p>
658−
659−<pre><code>[Google]: http://google.com/
660−</code></pre>
661−
662−<p>Because link names may contain spaces, this shortcut even works for
663−multiple words in the link text:</p>
664−
665−<pre><code>Visit [Daring Fireball][] for more information.
666−</code></pre>
667−
668−<p>And then define the link:</p>
669−
670−<pre><code>[Daring Fireball]: http://daringfireball.net/
671−</code></pre>
672−
673−<p>Link definitions can be placed anywhere in your Markdown document. I
674−tend to put them immediately after each paragraph in which they're
675−used, but if you want, you can put them all at the end of your
676−document, sort of like footnotes.</p>
677−
678−<p>Here's an example of reference links in action:</p>
679−
680−<pre><code>I get 10 times more traffic from [Google] [1] than from
681−[Yahoo] [2] or [MSN] [3].
682−
683− [1]: http://google.com/ "Google"
684− [2]: http://search.yahoo.com/ "Yahoo Search"
685− [3]: http://search.msn.com/ "MSN Search"
686−</code></pre>
687−
688−<p>Using the implicit link name shortcut, you could instead write:</p>
689−
690−<pre><code>I get 10 times more traffic from [Google][] than from
691−[Yahoo][] or [MSN][].
692−
693− [google]: http://google.com/ "Google"
694− [yahoo]: http://search.yahoo.com/ "Yahoo Search"
695− [msn]: http://search.msn.com/ "MSN Search"
696−</code></pre>
697−
698−<p>Both of the above examples will produce the following HTML output:</p>
699−
700−<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"
701−title="Google"&gt;Google&lt;/a&gt; than from
702−&lt;a href="http://search.yahoo.com/" title="Yahoo Search"&gt;Yahoo&lt;/a&gt;
703−or &lt;a href="http://search.msn.com/" title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;
704−</code></pre>
705−
706−<p>For comparison, here is the same paragraph written using
707−Markdown's inline link style:</p>
708−
709−<pre><code>I get 10 times more traffic from [Google](http://google.com/ "Google")
710−than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
711−[MSN](http://search.msn.com/ "MSN Search").
712−</code></pre>
713−
714−<p>The point of reference-style links is not that they're easier to
715−write. The point is that with reference-style links, your document
716−source is vastly more readable. Compare the above examples: using
717−reference-style links, the paragraph itself is only 81 characters
718−long; with inline-style links, it's 176 characters; and as raw HTML,
719−it's 234 characters. In the raw HTML, there's more markup than there
720−is text.</p>
721−
722−<p>With Markdown's reference-style links, a source document much more
723−closely resembles the final output, as rendered in a browser. By
724−allowing you to move the markup-related metadata out of the paragraph,
725−you can add links without interrupting the narrative flow of your
726−prose.</p>
727−
728−<h3 id="em">Emphasis</h3>
729−
730−<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of
731−emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an
732−HTML <code>&lt;em&gt;</code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML
733−<code>&lt;strong&gt;</code> tag. E.g., this input:</p>
734−
735−<pre><code>*single asterisks*
736−
737−_single underscores_
738−
739−**double asterisks**
740−
741−__double underscores__
742−</code></pre>
743−
744−<p>will produce:</p>
745−
746−<pre><code>&lt;em&gt;single asterisks&lt;/em&gt;
747−
748−&lt;em&gt;single underscores&lt;/em&gt;
749−
750−&lt;strong&gt;double asterisks&lt;/strong&gt;
751−
752−&lt;strong&gt;double underscores&lt;/strong&gt;
753−</code></pre>
754−
755−<p>You can use whichever style you prefer; the lone restriction is that
756−the same character must be used to open and close an emphasis span.</p>
757−
758−<p>Emphasis can be used in the middle of a word:</p>
759−
760−<pre><code>un*fucking*believable
761−</code></pre>
762−
763−<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it'll be treated as a
764−literal asterisk or underscore.</p>
765−
766−<p>To produce a literal asterisk or underscore at a position where it
767−would otherwise be used as an emphasis delimiter, you can backslash
768−escape it:</p>
769−
770−<pre><code>\*this text is surrounded by literal asterisks\*
771−</code></pre>
772−
773−<h3 id="code">Code</h3>
774−
775−<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>).
776−Unlike a pre-formatted code block, a code span indicates code within a
777−normal paragraph. For example:</p>
778−
779−<pre><code>Use the `printf()` function.
780−</code></pre>
781−
782−<p>will produce:</p>
783−
784−<pre><code>&lt;p&gt;Use the &lt;code&gt;printf()&lt;/code&gt; function.&lt;/p&gt;
785−</code></pre>
786−
787−<p>To include a literal backtick character within a code span, you can use
788−multiple backticks as the opening and closing delimiters:</p>
789−
790−<pre><code>``There is a literal backtick (`) here.``
791−</code></pre>
792−
793−<p>which will produce this:</p>
794−
795−<pre><code>&lt;p&gt;&lt;code&gt;There is a literal backtick (`) here.&lt;/code&gt;&lt;/p&gt;
796−</code></pre>
797−
798−<p>The backtick delimiters surrounding a code span may include spaces --
799−one after the opening, one before the closing. This allows you to place
800−literal backtick characters at the beginning or end of a code span:</p>
801−
802−<pre><code>A single backtick in a code span: `` ` ``
803−
804−A backtick-delimited string in a code span: `` `foo` ``
805−</code></pre>
806−
807−<p>will produce:</p>
808−
809−<pre><code>&lt;p&gt;A single backtick in a code span: &lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
810−
811−&lt;p&gt;A backtick-delimited string in a code span: &lt;code&gt;`foo`&lt;/code&gt;&lt;/p&gt;
812−</code></pre>
813−
814−<p>With a code span, ampersands and angle brackets are encoded as HTML
815−entities automatically, which makes it easy to include example HTML
816−tags. Markdown will turn this:</p>
817−
818−<pre><code>Please don't use any `&lt;blink&gt;` tags.
819−</code></pre>
820−
821−<p>into:</p>
822−
823−<pre><code>&lt;p&gt;Please don't use any &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
824−</code></pre>
825−
826−<p>You can write this:</p>
827−
828−<pre><code>`&amp;#8212;` is the decimal-encoded equivalent of `&amp;mdash;`.
829−</code></pre>
830−
831−<p>to produce:</p>
832−
833−<pre><code>&lt;p&gt;&lt;code&gt;&amp;amp;#8212;&lt;/code&gt; is the decimal-encoded
834−equivalent of &lt;code&gt;&amp;amp;mdash;&lt;/code&gt;.&lt;/p&gt;
835−</code></pre>
836−
837−<h3 id="img">Images</h3>
838−
839−<p>Admittedly, it's fairly difficult to devise a "natural" syntax for
840−placing images into a plain text document format.</p>
841−
842−<p>Markdown uses an image syntax that is intended to resemble the syntax
843−for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p>
844−
845−<p>Inline image syntax looks like this:</p>
846−
847−<pre><code>![Alt text](/path/to/img.jpg)
848−
849−![Alt text](/path/to/img.jpg "Optional title")
850−</code></pre>
851−
852−<p>That is:</p>
853−
854−<ul>
855−<li>An exclamation mark: <code>!</code>;</li>
856−<li>followed by a set of square brackets, containing the <code>alt</code>
857−attribute text for the image;</li>
858−<li>followed by a set of parentheses, containing the URL or path to
859−the image, and an optional <code>title</code> attribute enclosed in double
860−or single quotes.</li>
861−</ul>
862−
863−<p>Reference-style image syntax looks like this:</p>
864−
865−<pre><code>![Alt text][id]
866−</code></pre>
867−
868−<p>Where "id" is the name of a defined image reference. Image references
869−are defined using syntax identical to link references:</p>
870−
871−<pre><code>[id]: url/to/image "Optional title attribute"
872−</code></pre>
873−
874−<p>As of this writing, Markdown has no syntax for specifying the
875−dimensions of an image; if this is important to you, you can simply
876−use regular HTML <code>&lt;img&gt;</code> tags.</p>
877−
878−<hr />
879−
880−<h2 id="misc">Miscellaneous</h2>
881−
882−<h3 id="autolink">Automatic Links</h3>
883−
884−<p>Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p>
885−
886−<pre><code>&lt;http://example.com/&gt;
887−</code></pre>
888−
889−<p>Markdown will turn this into:</p>
890−
891−<pre><code>&lt;a href="http://example.com/"&gt;http://example.com/&lt;/a&gt;
892−</code></pre>
893−
894−<p>Automatic links for email addresses work similarly, except that
895−Markdown will also perform a bit of randomized decimal and hex
896−entity-encoding to help obscure your address from address-harvesting
897−spambots. For example, Markdown will turn this:</p>
898−
899−<pre><code>&lt;address@example.com&gt;
900−</code></pre>
901−
902−<p>into something like this:</p>
903−
904−<pre><code>&lt;a href="&amp;#x6D;&amp;#x61;i&amp;#x6C;&amp;#x74;&amp;#x6F;:&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;
905−&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;
906−&amp;#109;"&gt;&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;
907−&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;&amp;#109;&lt;/a&gt;
908−</code></pre>
909−
910−<p>which will render in a browser as a clickable link to "address@example.com".</p>
911−
912−<p>(This sort of entity-encoding trick will indeed fool many, if not
913−most, address-harvesting bots, but it definitely won't fool all of
914−them. It's better than nothing, but an address published in this way
915−will probably eventually start receiving spam.)</p>
916−
917−<h3 id="backslash">Backslash Escapes</h3>
918−
919−<p>Markdown allows you to use backslash escapes to generate literal
920−characters which would otherwise have special meaning in Markdown's
921−formatting syntax. For example, if you wanted to surround a word with
922−literal asterisks (instead of an HTML <code>&lt;em&gt;</code> tag), you can backslashes
923−before the asterisks, like this:</p>
924−
925−<pre><code>\*literal asterisks\*
926−</code></pre>
927−
928−<p>Markdown provides backslash escapes for the following characters:</p>
929−
930−<pre><code>\ backslash
931−` backtick
932−* asterisk
933−_ underscore
934−{} curly braces
935−[] square brackets
936−() parentheses
937−# hash mark
938−+ plus sign
939−- minus sign (hyphen)
940−. dot
941−! exclamation mark
942−</code></pre>
tests/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.textdeleted−888
@@ -1,888 +0,0 @@
1−Markdown: Syntax
2−================
3−
4−<ul id="ProjectSubmenu">
5− <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
6− <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li>
7− <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li>
8− <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
9− <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
10−</ul>
11−
12−
13−* [Overview](#overview)
14− * [Philosophy](#philosophy)
15− * [Inline HTML](#html)
16− * [Automatic Escaping for Special Characters](#autoescape)
17−* [Block Elements](#block)
18− * [Paragraphs and Line Breaks](#p)
19− * [Headers](#header)
20− * [Blockquotes](#blockquote)
21− * [Lists](#list)
22− * [Code Blocks](#precode)
23− * [Horizontal Rules](#hr)
24−* [Span Elements](#span)
25− * [Links](#link)
26− * [Emphasis](#em)
27− * [Code](#code)
28− * [Images](#img)
29−* [Miscellaneous](#misc)
30− * [Backslash Escapes](#backslash)
31− * [Automatic Links](#autolink)
32−
33−
34−**Note:** This document is itself written using Markdown; you
35−can [see the source for it by adding '.text' to the URL][src].
36−
37− [src]: /projects/markdown/syntax.text
38−
39−* * *
40−
41−<h2 id="overview">Overview</h2>
42−
43−<h3 id="philosophy">Philosophy</h3>
44−
45−Markdown is intended to be as easy-to-read and easy-to-write as is feasible.
46−
47−Readability, however, is emphasized above all else. A Markdown-formatted
48−document should be publishable as-is, as plain text, without looking
49−like it's been marked up with tags or formatting instructions. While
50−Markdown's syntax has been influenced by several existing text-to-HTML
51−filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4],
52−[Grutatext] [5], and [EtText] [6] -- the single biggest source of
53−inspiration for Markdown's syntax is the format of plain text email.
54−
55− [1]: http://docutils.sourceforge.net/mirror/setext.html
56− [2]: http://www.aaronsw.com/2002/atx/
57− [3]: http://textism.com/tools/textile/
58− [4]: http://docutils.sourceforge.net/rst.html
59− [5]: http://www.triptico.com/software/grutatxt.html
60− [6]: http://ettext.taint.org/doc/
61−
62−To this end, Markdown's syntax is comprised entirely of punctuation
63−characters, which punctuation characters have been carefully chosen so
64−as to look like what they mean. E.g., asterisks around a word actually
65−look like \*emphasis\*. Markdown lists look like, well, lists. Even
66−blockquotes look like quoted passages of text, assuming you've ever
67−used email.
68−
69−
70−
71−<h3 id="html">Inline HTML</h3>
72−
73−Markdown's syntax is intended for one purpose: to be used as a
74−format for *writing* for the web.
75−
76−Markdown is not a replacement for HTML, or even close to it. Its
77−syntax is very small, corresponding only to a very small subset of
78−HTML tags. The idea is *not* to create a syntax that makes it easier
79−to insert HTML tags. In my opinion, HTML tags are already easy to
80−insert. The idea for Markdown is to make it easy to read, write, and
81−edit prose. HTML is a *publishing* format; Markdown is a *writing*
82−format. Thus, Markdown's formatting syntax only addresses issues that
83−can be conveyed in plain text.
84−
85−For any markup that is not covered by Markdown's syntax, you simply
86−use HTML itself. There's no need to preface it or delimit it to
87−indicate that you're switching from Markdown to HTML; you just use
88−the tags.
89−
90−The only restrictions are that block-level HTML elements -- e.g. `<div>`,
91−`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding
92−content by blank lines, and the start and end tags of the block should
93−not be indented with tabs or spaces. Markdown is smart enough not
94−to add extra (unwanted) `<p>` tags around HTML block-level tags.
95−
96−For example, to add an HTML table to a Markdown article:
97−
98− This is a regular paragraph.
99−
100− <table>
101− <tr>
102− <td>Foo</td>
103− </tr>
104− </table>
105−
106− This is another regular paragraph.
107−
108−Note that Markdown formatting syntax is not processed within block-level
109−HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an
110−HTML block.
111−
112−Span-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be
113−used anywhere in a Markdown paragraph, list item, or header. If you
114−want, you can even use HTML tags instead of Markdown formatting; e.g. if
115−you'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's
116−link or image syntax, go right ahead.
117−
118−Unlike block-level HTML tags, Markdown syntax *is* processed within
119−span-level tags.
120−
121−
122−<h3 id="autoescape">Automatic Escaping for Special Characters</h3>
123−
124−In HTML, there are two characters that demand special treatment: `<`
125−and `&`. Left angle brackets are used to start tags; ampersands are
126−used to denote HTML entities. If you want to use them as literal
127−characters, you must escape them as entities, e.g. `&lt;`, and
128−`&amp;`.
129−
130−Ampersands in particular are bedeviling for web writers. If you want to
131−write about 'AT&T', you need to write '`AT&amp;T`'. You even need to
132−escape ampersands within URLs. Thus, if you want to link to:
133−
134− http://images.google.com/images?num=30&q=larry+bird
135−
136−you need to encode the URL as:
137−
138− http://images.google.com/images?num=30&amp;q=larry+bird
139−
140−in your anchor tag `href` attribute. Needless to say, this is easy to
141−forget, and is probably the single most common source of HTML validation
142−errors in otherwise well-marked-up web sites.
143−
144−Markdown allows you to use these characters naturally, taking care of
145−all the necessary escaping for you. If you use an ampersand as part of
146−an HTML entity, it remains unchanged; otherwise it will be translated
147−into `&amp;`.
148−
149−So, if you want to include a copyright symbol in your article, you can write:
150−
151− &copy;
152−
153−and Markdown will leave it alone. But if you write:
154−
155− AT&T
156−
157−Markdown will translate it to:
158−
159− AT&amp;T
160−
161−Similarly, because Markdown supports [inline HTML](#html), if you use
162−angle brackets as delimiters for HTML tags, Markdown will treat them as
163−such. But if you write:
164−
165− 4 < 5
166−
167−Markdown will translate it to:
168−
169− 4 &lt; 5
170−
171−However, inside Markdown code spans and blocks, angle brackets and
172−ampersands are *always* encoded automatically. This makes it easy to use
173−Markdown to write about HTML code. (As opposed to raw HTML, which is a
174−terrible format for writing about HTML syntax, because every single `<`
175−and `&` in your example code needs to be escaped.)
176−
177−
178−* * *
179−
180−
181−<h2 id="block">Block Elements</h2>
182−
183−
184−<h3 id="p">Paragraphs and Line Breaks</h3>
185−
186−A paragraph is simply one or more consecutive lines of text, separated
187−by one or more blank lines. (A blank line is any line that looks like a
188−blank line -- a line containing nothing but spaces or tabs is considered
189−blank.) Normal paragraphs should not be intended with spaces or tabs.
190−
191−The implication of the "one or more consecutive lines of text" rule is
192−that Markdown supports "hard-wrapped" text paragraphs. This differs
193−significantly from most other text-to-HTML formatters (including Movable
194−Type's "Convert Line Breaks" option) which translate every line break
195−character in a paragraph into a `<br />` tag.
196−
197−When you *do* want to insert a `<br />` break tag using Markdown, you
198−end a line with two or more spaces, then type return.
199−
200−Yes, this takes a tad more effort to create a `<br />`, but a simplistic
201−"every line break is a `<br />`" rule wouldn't work for Markdown.
202−Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l]
203−work best -- and look better -- when you format them with hard breaks.
204−
205− [bq]: #blockquote
206− [l]: #list
207−
208−
209−
210−<h3 id="header">Headers</h3>
211−
212−Markdown supports two styles of headers, [Setext] [1] and [atx] [2].
213−
214−Setext-style headers are "underlined" using equal signs (for first-level
215−headers) and dashes (for second-level headers). For example:
216−
217− This is an H1
218− =============
219−
220− This is an H2
221− -------------
222−
223−Any number of underlining `=`'s or `-`'s will work.
224−
225−Atx-style headers use 1-6 hash characters at the start of the line,
226−corresponding to header levels 1-6. For example:
227−
228− # This is an H1
229−
230− ## This is an H2
231−
232− ###### This is an H6
233−
234−Optionally, you may "close" atx-style headers. This is purely
235−cosmetic -- you can use this if you think it looks better. The
236−closing hashes don't even need to match the number of hashes
237−used to open the header. (The number of opening hashes
238−determines the header level.) :
239−
240− # This is an H1 #
241−
242− ## This is an H2 ##
243−
244− ### This is an H3 ######
245−
246−
247−<h3 id="blockquote">Blockquotes</h3>
248−
249−Markdown uses email-style `>` characters for blockquoting. If you're
250−familiar with quoting passages of text in an email message, then you
251−know how to create a blockquote in Markdown. It looks best if you hard
252−wrap the text and put a `>` before every line:
253−
254− > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
255− > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
256− > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
257− >
258− > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
259− > id sem consectetuer libero luctus adipiscing.
260−
261−Markdown allows you to be lazy and only put the `>` before the first
262−line of a hard-wrapped paragraph:
263−
264− > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
265− consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
266− Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
267−
268− > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
269− id sem consectetuer libero luctus adipiscing.
270−
271−Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
272−adding additional levels of `>`:
273−
274− > This is the first level of quoting.
275− >
276− > > This is nested blockquote.
277− >
278− > Back to the first level.
279−
280−Blockquotes can contain other Markdown elements, including headers, lists,
281−and code blocks:
282−
283− > ## This is a header.
284− >
285− > 1. This is the first list item.
286− > 2. This is the second list item.
287− >
288− > Here's some example code:
289− >
290− > return shell_exec("echo $input | $markdown_script");
291−
292−Any decent text editor should make email-style quoting easy. For
293−example, with BBEdit, you can make a selection and choose Increase
294−Quote Level from the Text menu.
295−
296−
297−<h3 id="list">Lists</h3>
298−
299−Markdown supports ordered (numbered) and unordered (bulleted) lists.
300−
301−Unordered lists use asterisks, pluses, and hyphens -- interchangably
302−-- as list markers:
303−
304− * Red
305− * Green
306− * Blue
307−
308−is equivalent to:
309−
310− + Red
311− + Green
312− + Blue
313−
314−and:
315−
316− - Red
317− - Green
318− - Blue
319−
320−Ordered lists use numbers followed by periods:
321−
322− 1. Bird
323− 2. McHale
324− 3. Parish
325−
326−It's important to note that the actual numbers you use to mark the
327−list have no effect on the HTML output Markdown produces. The HTML
328−Markdown produces from the above list is:
329−
330− <ol>
331− <li>Bird</li>
332− <li>McHale</li>
333− <li>Parish</li>
334− </ol>
335−
336−If you instead wrote the list in Markdown like this:
337−
338− 1. Bird
339− 1. McHale
340− 1. Parish
341−
342−or even:
343−
344− 3. Bird
345− 1. McHale
346− 8. Parish
347−
348−you'd get the exact same HTML output. The point is, if you want to,
349−you can use ordinal numbers in your ordered Markdown lists, so that
350−the numbers in your source match the numbers in your published HTML.
351−But if you want to be lazy, you don't have to.
352−
353−If you do use lazy list numbering, however, you should still start the
354−list with the number 1. At some point in the future, Markdown may support
355−starting ordered lists at an arbitrary number.
356−
357−List markers typically start at the left margin, but may be indented by
358−up to three spaces. List markers must be followed by one or more spaces
359−or a tab.
360−
361−To make lists look nice, you can wrap items with hanging indents:
362−
363− * Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
364− Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
365− viverra nec, fringilla in, laoreet vitae, risus.
366− * Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
367− Suspendisse id sem consectetuer libero luctus adipiscing.
368−
369−But if you want to be lazy, you don't have to:
370−
371− * Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
372− Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
373− viverra nec, fringilla in, laoreet vitae, risus.
374− * Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
375− Suspendisse id sem consectetuer libero luctus adipiscing.
376−
377−If list items are separated by blank lines, Markdown will wrap the
378−items in `<p>` tags in the HTML output. For example, this input:
379−
380− * Bird
381− * Magic
382−
383−will turn into:
384−
385− <ul>
386− <li>Bird</li>
387− <li>Magic</li>
388− </ul>
389−
390−But this:
391−
392− * Bird
393−
394− * Magic
395−
396−will turn into:
397−
398− <ul>
399− <li><p>Bird</p></li>
400− <li><p>Magic</p></li>
401− </ul>
402−
403−List items may consist of multiple paragraphs. Each subsequent
404−paragraph in a list item must be intended by either 4 spaces
405−or one tab:
406−
407− 1. This is a list item with two paragraphs. Lorem ipsum dolor
408− sit amet, consectetuer adipiscing elit. Aliquam hendrerit
409− mi posuere lectus.
410−
411− Vestibulum enim wisi, viverra nec, fringilla in, laoreet
412− vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
413− sit amet velit.
414−
415− 2. Suspendisse id sem consectetuer libero luctus adipiscing.
416−
417−It looks nice if you indent every line of the subsequent
418−paragraphs, but here again, Markdown will allow you to be
419−lazy:
420−
421− * This is a list item with two paragraphs.
422−
423− This is the second paragraph in the list item. You're
424− only required to indent the first line. Lorem ipsum dolor
425− sit amet, consectetuer adipiscing elit.
426−
427− * Another item in the same list.
428−
429−To put a blockquote within a list item, the blockquote's `>`
430−delimiters need to be indented:
431−
432− * A list item with a blockquote:
433−
434− > This is a blockquote
435− > inside a list item.
436−
437−To put a code block within a list item, the code block needs
438−to be indented *twice* -- 8 spaces or two tabs:
439−
440− * A list item with a code block:
441−
442− <code goes here>
443−
444−
445−It's worth noting that it's possible to trigger an ordered list by
446−accident, by writing something like this:
447−
448− 1986. What a great season.
449−
450−In other words, a *number-period-space* sequence at the beginning of a
451−line. To avoid this, you can backslash-escape the period:
452−
453− 1986\. What a great season.
454−
455−
456−
457−<h3 id="precode">Code Blocks</h3>
458−
459−Pre-formatted code blocks are used for writing about programming or
460−markup source code. Rather than forming normal paragraphs, the lines
461−of a code block are interpreted literally. Markdown wraps a code block
462−in both `<pre>` and `<code>` tags.
463−
464−To produce a code block in Markdown, simply indent every line of the
465−block by at least 4 spaces or 1 tab. For example, given this input:
466−
467− This is a normal paragraph:
468−
469− This is a code block.
470−
471−Markdown will generate:
472−
473− <p>This is a normal paragraph:</p>
474−
475− <pre><code>This is a code block.
476− </code></pre>
477−
478−One level of indentation -- 4 spaces or 1 tab -- is removed from each
479−line of the code block. For example, this:
480−
481− Here is an example of AppleScript:
482−
483− tell application "Foo"
484− beep
485− end tell
486−
487−will turn into:
488−
489− <p>Here is an example of AppleScript:</p>
490−
491− <pre><code>tell application "Foo"
492− beep
493− end tell
494− </code></pre>
495−
496−A code block continues until it reaches a line that is not indented
497−(or the end of the article).
498−
499−Within a code block, ampersands (`&`) and angle brackets (`<` and `>`)
500−are automatically converted into HTML entities. This makes it very
501−easy to include example HTML source code using Markdown -- just paste
502−it and indent it, and Markdown will handle the hassle of encoding the
503−ampersands and angle brackets. For example, this:
504−
505− <div class="footer">
506− &copy; 2004 Foo Corporation
507− </div>
508−
509−will turn into:
510−
511− <pre><code>&lt;div class="footer"&gt;
512− &amp;copy; 2004 Foo Corporation
513− &lt;/div&gt;
514− </code></pre>
515−
516−Regular Markdown syntax is not processed within code blocks. E.g.,
517−asterisks are just literal asterisks within a code block. This means
518−it's also easy to use Markdown to write about Markdown's own syntax.
519−
520−
521−
522−<h3 id="hr">Horizontal Rules</h3>
523−
524−You can produce a horizontal rule tag (`<hr />`) by placing three or
525−more hyphens, asterisks, or underscores on a line by themselves. If you
526−wish, you may use spaces between the hyphens or asterisks. Each of the
527−following lines will produce a horizontal rule:
528−
529− * * *
530−
531− ***
532−
533− *****
534−
535− - - -
536−
537− ---------------------------------------
538−
539− _ _ _
540−
541−
542−* * *
543−
544−<h2 id="span">Span Elements</h2>
545−
546−<h3 id="link">Links</h3>
547−
548−Markdown supports two style of links: *inline* and *reference*.
549−
550−In both styles, the link text is delimited by [square brackets].
551−
552−To create an inline link, use a set of regular parentheses immediately
553−after the link text's closing square bracket. Inside the parentheses,
554−put the URL where you want the link to point, along with an *optional*
555−title for the link, surrounded in quotes. For example:
556−
557− This is [an example](http://example.com/ "Title") inline link.
558−
559− [This link](http://example.net/) has no title attribute.
560−
561−Will produce:
562−
563− <p>This is <a href="http://example.com/" title="Title">
564− an example</a> inline link.</p>
565−
566− <p><a href="http://example.net/">This link</a> has no
567− title attribute.</p>
568−
569−If you're referring to a local resource on the same server, you can
570−use relative paths:
571−
572− See my [About](/about/) page for details.
573−
574−Reference-style links use a second set of square brackets, inside
575−which you place a label of your choosing to identify the link:
576−
577− This is [an example][id] reference-style link.
578−
579−You can optionally use a space to separate the sets of brackets:
580−
581− This is [an example] [id] reference-style link.
582−
583−Then, anywhere in the document, you define your link label like this,
584−on a line by itself:
585−
586− [id]: http://example.com/ "Optional Title Here"
587−
588−That is:
589−
590−* Square brackets containing the link identifier (optionally
591− indented from the left margin using up to three spaces);
592−* followed by a colon;
593−* followed by one or more spaces (or tabs);
594−* followed by the URL for the link;
595−* optionally followed by a title attribute for the link, enclosed
596− in double or single quotes.
597−
598−The link URL may, optionally, be surrounded by angle brackets:
599−
600− [id]: <http://example.com/> "Optional Title Here"
601−
602−You can put the title attribute on the next line and use extra spaces
603−or tabs for padding, which tends to look better with longer URLs:
604−
605− [id]: http://example.com/longish/path/to/resource/here
606− "Optional Title Here"
607−
608−Link definitions are only used for creating links during Markdown
609−processing, and are stripped from your document in the HTML output.
610−
611−Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links:
612−
613− [link text][a]
614− [link text][A]
615−
616−are equivalent.
617−
618−The *implicit link name* shortcut allows you to omit the name of the
619−link, in which case the link text itself is used as the name.
620−Just use an empty set of square brackets -- e.g., to link the word
621−"Google" to the google.com web site, you could simply write:
622−
623− [Google][]
624−
625−And then define the link:
626−
627− [Google]: http://google.com/
628−
629−Because link names may contain spaces, this shortcut even works for
630−multiple words in the link text:
631−
632− Visit [Daring Fireball][] for more information.
633−
634−And then define the link:
635−
636− [Daring Fireball]: http://daringfireball.net/
637−
638−Link definitions can be placed anywhere in your Markdown document. I
639−tend to put them immediately after each paragraph in which they're
640−used, but if you want, you can put them all at the end of your
641−document, sort of like footnotes.
642−
643−Here's an example of reference links in action:
644−
645− I get 10 times more traffic from [Google] [1] than from
646− [Yahoo] [2] or [MSN] [3].
647−
648− [1]: http://google.com/ "Google"
649− [2]: http://search.yahoo.com/ "Yahoo Search"
650− [3]: http://search.msn.com/ "MSN Search"
651−
652−Using the implicit link name shortcut, you could instead write:
653−
654− I get 10 times more traffic from [Google][] than from
655− [Yahoo][] or [MSN][].
656−
657− [google]: http://google.com/ "Google"
658− [yahoo]: http://search.yahoo.com/ "Yahoo Search"
659− [msn]: http://search.msn.com/ "MSN Search"
660−
661−Both of the above examples will produce the following HTML output:
662−
663− <p>I get 10 times more traffic from <a href="http://google.com/"
664− title="Google">Google</a> than from
665− <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
666− or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
667−
668−For comparison, here is the same paragraph written using
669−Markdown's inline link style:
670−
671− I get 10 times more traffic from [Google](http://google.com/ "Google")
672− than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
673− [MSN](http://search.msn.com/ "MSN Search").
674−
675−The point of reference-style links is not that they're easier to
676−write. The point is that with reference-style links, your document
677−source is vastly more readable. Compare the above examples: using
678−reference-style links, the paragraph itself is only 81 characters
679−long; with inline-style links, it's 176 characters; and as raw HTML,
680−it's 234 characters. In the raw HTML, there's more markup than there
681−is text.
682−
683−With Markdown's reference-style links, a source document much more
684−closely resembles the final output, as rendered in a browser. By
685−allowing you to move the markup-related metadata out of the paragraph,
686−you can add links without interrupting the narrative flow of your
687−prose.
688−
689−
690−<h3 id="em">Emphasis</h3>
691−
692−Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
693−emphasis. Text wrapped with one `*` or `_` will be wrapped with an
694−HTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML
695−`<strong>` tag. E.g., this input:
696−
697− *single asterisks*
698−
699− _single underscores_
700−
701− **double asterisks**
702−
703− __double underscores__
704−
705−will produce:
706−
707− <em>single asterisks</em>
708−
709− <em>single underscores</em>
710−
711− <strong>double asterisks</strong>
712−
713− <strong>double underscores</strong>
714−
715−You can use whichever style you prefer; the lone restriction is that
716−the same character must be used to open and close an emphasis span.
717−
718−Emphasis can be used in the middle of a word:
719−
720− un*fucking*believable
721−
722−But if you surround an `*` or `_` with spaces, it'll be treated as a
723−literal asterisk or underscore.
724−
725−To produce a literal asterisk or underscore at a position where it
726−would otherwise be used as an emphasis delimiter, you can backslash
727−escape it:
728−
729− \*this text is surrounded by literal asterisks\*
730−
731−
732−
733−<h3 id="code">Code</h3>
734−
735−To indicate a span of code, wrap it with backtick quotes (`` ` ``).
736−Unlike a pre-formatted code block, a code span indicates code within a
737−normal paragraph. For example:
738−
739− Use the `printf()` function.
740−
741−will produce:
742−
743− <p>Use the <code>printf()</code> function.</p>
744−
745−To include a literal backtick character within a code span, you can use
746−multiple backticks as the opening and closing delimiters:
747−
748− ``There is a literal backtick (`) here.``
749−
750−which will produce this:
751−
752− <p><code>There is a literal backtick (`) here.</code></p>
753−
754−The backtick delimiters surrounding a code span may include spaces --
755−one after the opening, one before the closing. This allows you to place
756−literal backtick characters at the beginning or end of a code span:
757−
758− A single backtick in a code span: `` ` ``
759−
760− A backtick-delimited string in a code span: `` `foo` ``
761−
762−will produce:
763−
764− <p>A single backtick in a code span: <code>`</code></p>
765−
766− <p>A backtick-delimited string in a code span: <code>`foo`</code></p>
767−
768−With a code span, ampersands and angle brackets are encoded as HTML
769−entities automatically, which makes it easy to include example HTML
770−tags. Markdown will turn this:
771−
772− Please don't use any `<blink>` tags.
773−
774−into:
775−
776− <p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
777−
778−You can write this:
779−
780− `&#8212;` is the decimal-encoded equivalent of `&mdash;`.
781−
782−to produce:
783−
784− <p><code>&amp;#8212;</code> is the decimal-encoded
785− equivalent of <code>&amp;mdash;</code>.</p>
786−
787−
788−
789−<h3 id="img">Images</h3>
790−
791−Admittedly, it's fairly difficult to devise a "natural" syntax for
792−placing images into a plain text document format.
793−
794−Markdown uses an image syntax that is intended to resemble the syntax
795−for links, allowing for two styles: *inline* and *reference*.
796−
797−Inline image syntax looks like this:
798−
799− ![Alt text](/path/to/img.jpg)
800−
801− ![Alt text](/path/to/img.jpg "Optional title")
802−
803−That is:
804−
805−* An exclamation mark: `!`;
806−* followed by a set of square brackets, containing the `alt`
807− attribute text for the image;
808−* followed by a set of parentheses, containing the URL or path to
809− the image, and an optional `title` attribute enclosed in double
810− or single quotes.
811−
812−Reference-style image syntax looks like this:
813−
814− ![Alt text][id]
815−
816−Where "id" is the name of a defined image reference. Image references
817−are defined using syntax identical to link references:
818−
819− [id]: url/to/image "Optional title attribute"
820−
821−As of this writing, Markdown has no syntax for specifying the
822−dimensions of an image; if this is important to you, you can simply
823−use regular HTML `<img>` tags.
824−
825−
826−* * *
827−
828−
829−<h2 id="misc">Miscellaneous</h2>
830−
831−<h3 id="autolink">Automatic Links</h3>
832−
833−Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:
834−
835− <http://example.com/>
836−
837−Markdown will turn this into:
838−
839− <a href="http://example.com/">http://example.com/</a>
840−
841−Automatic links for email addresses work similarly, except that
842−Markdown will also perform a bit of randomized decimal and hex
843−entity-encoding to help obscure your address from address-harvesting
844−spambots. For example, Markdown will turn this:
845−
846− <address@example.com>
847−
848−into something like this:
849−
850− <a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;
851− &#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;
852− &#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;
853− &#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>
854−
855−which will render in a browser as a clickable link to "address@example.com".
856−
857−(This sort of entity-encoding trick will indeed fool many, if not
858−most, address-harvesting bots, but it definitely won't fool all of
859−them. It's better than nothing, but an address published in this way
860−will probably eventually start receiving spam.)
861−
862−
863−
864−<h3 id="backslash">Backslash Escapes</h3>
865−
866−Markdown allows you to use backslash escapes to generate literal
867−characters which would otherwise have special meaning in Markdown's
868−formatting syntax. For example, if you wanted to surround a word with
869−literal asterisks (instead of an HTML `<em>` tag), you can backslashes
870−before the asterisks, like this:
871−
872− \*literal asterisks\*
873−
874−Markdown provides backslash escapes for the following characters:
875−
876− \ backslash
877− ` backtick
878− * asterisk
879− _ underscore
880− {} curly braces
881− [] square brackets
882− () parentheses
883− # hash mark
884− + plus sign
885− - minus sign (hyphen)
886− . dot
887− ! exclamation mark
888−
tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.htmldeleted−9
@@ -1,9 +0,0 @@
1−<blockquote>
2− <p>foo</p>
3−
4− <blockquote>
5− <p>bar</p>
6− </blockquote>
7−
8− <p>foo</p>
9−</blockquote>
tests/MarkdownTest_1.0.3/Tests/Nested blockquotes.textdeleted−5
@@ -1,5 +0,0 @@
1−> foo
2−>
3−> > bar
4−>
5−> foo
tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.htmldeleted−148
@@ -1,148 +0,0 @@
1−<h2>Unordered</h2>
2−
3−<p>Asterisks tight:</p>
4−
5−<ul>
6−<li>asterisk 1</li>
7−<li>asterisk 2</li>
8−<li>asterisk 3</li>
9−</ul>
10−
11−<p>Asterisks loose:</p>
12−
13−<ul>
14−<li><p>asterisk 1</p></li>
15−<li><p>asterisk 2</p></li>
16−<li><p>asterisk 3</p></li>
17−</ul>
18−
19−<hr />
20−
21−<p>Pluses tight:</p>
22−
23−<ul>
24−<li>Plus 1</li>
25−<li>Plus 2</li>
26−<li>Plus 3</li>
27−</ul>
28−
29−<p>Pluses loose:</p>
30−
31−<ul>
32−<li><p>Plus 1</p></li>
33−<li><p>Plus 2</p></li>
34−<li><p>Plus 3</p></li>
35−</ul>
36−
37−<hr />
38−
39−<p>Minuses tight:</p>
40−
41−<ul>
42−<li>Minus 1</li>
43−<li>Minus 2</li>
44−<li>Minus 3</li>
45−</ul>
46−
47−<p>Minuses loose:</p>
48−
49−<ul>
50−<li><p>Minus 1</p></li>
51−<li><p>Minus 2</p></li>
52−<li><p>Minus 3</p></li>
53−</ul>
54−
55−<h2>Ordered</h2>
56−
57−<p>Tight:</p>
58−
59−<ol>
60−<li>First</li>
61−<li>Second</li>
62−<li>Third</li>
63−</ol>
64−
65−<p>and:</p>
66−
67−<ol>
68−<li>One</li>
69−<li>Two</li>
70−<li>Three</li>
71−</ol>
72−
73−<p>Loose using tabs:</p>
74−
75−<ol>
76−<li><p>First</p></li>
77−<li><p>Second</p></li>
78−<li><p>Third</p></li>
79−</ol>
80−
81−<p>and using spaces:</p>
82−
83−<ol>
84−<li><p>One</p></li>
85−<li><p>Two</p></li>
86−<li><p>Three</p></li>
87−</ol>
88−
89−<p>Multiple paragraphs:</p>
90−
91−<ol>
92−<li><p>Item 1, graf one.</p>
93−
94−<p>Item 2. graf two. The quick brown fox jumped over the lazy dog's
95−back.</p></li>
96−<li><p>Item 2.</p></li>
97−<li><p>Item 3.</p></li>
98−</ol>
99−
100−<h2>Nested</h2>
101−
102−<ul>
103−<li>Tab
104−<ul>
105−<li>Tab
106−<ul>
107−<li>Tab</li>
108−</ul></li>
109−</ul></li>
110−</ul>
111−
112−<p>Here's another:</p>
113−
114−<ol>
115−<li>First</li>
116−<li>Second:
117−<ul>
118−<li>Fee</li>
119−<li>Fie</li>
120−<li>Foe</li>
121−</ul></li>
122−<li>Third</li>
123−</ol>
124−
125−<p>Same thing but with paragraphs:</p>
126−
127−<ol>
128−<li><p>First</p></li>
129−<li><p>Second:</p>
130−
131−<ul>
132−<li>Fee</li>
133−<li>Fie</li>
134−<li>Foe</li>
135−</ul></li>
136−<li><p>Third</p></li>
137−</ol>
138−
139−
140−<p>This was an error in Markdown 1.0.1:</p>
141−
142−<ul>
143−<li><p>this</p>
144−
145−<ul><li>sub</li></ul>
146−
147−<p>that</p></li>
148−</ul>
tests/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.textdeleted−131
@@ -1,131 +0,0 @@
1−## Unordered
2−
3−Asterisks tight:
4−
5−* asterisk 1
6−* asterisk 2
7−* asterisk 3
8−
9−
10−Asterisks loose:
11−
12−* asterisk 1
13−
14−* asterisk 2
15−
16−* asterisk 3
17−
18−* * *
19−
20−Pluses tight:
21−
22−+ Plus 1
23−+ Plus 2
24−+ Plus 3
25−
26−
27−Pluses loose:
28−
29−+ Plus 1
30−
31−+ Plus 2
32−
33−+ Plus 3
34−
35−* * *
36−
37−
38−Minuses tight:
39−
40−- Minus 1
41−- Minus 2
42−- Minus 3
43−
44−
45−Minuses loose:
46−
47−- Minus 1
48−
49−- Minus 2
50−
51−- Minus 3
52−
53−
54−## Ordered
55−
56−Tight:
57−
58−1. First
59−2. Second
60−3. Third
61−
62−and:
63−
64−1. One
65−2. Two
66−3. Three
67−
68−
69−Loose using tabs:
70−
71−1. First
72−
73−2. Second
74−
75−3. Third
76−
77−and using spaces:
78−
79−1. One
80−
81−2. Two
82−
83−3. Three
84−
85−Multiple paragraphs:
86−
87−1. Item 1, graf one.
88−
89− Item 2. graf two. The quick brown fox jumped over the lazy dog's
90− back.
91−
92−2. Item 2.
93−
94−3. Item 3.
95−
96−
97−
98−## Nested
99−
100−* Tab
101− * Tab
102− * Tab
103−
104−Here's another:
105−
106−1. First
107−2. Second:
108− * Fee
109− * Fie
110− * Foe
111−3. Third
112−
113−Same thing but with paragraphs:
114−
115−1. First
116−
117−2. Second:
118− * Fee
119− * Fie
120− * Foe
121−
122−3. Third
123−
124−
125−This was an error in Markdown 1.0.1:
126−
127−* this
128−
129− * sub
130−
131− that
tests/MarkdownTest_1.0.3/Tests/Strong and em together.htmldeleted−7
@@ -1,7 +0,0 @@
1−<p><strong><em>This is strong and em.</em></strong></p>
2−
3−<p>So is <strong><em>this</em></strong> word.</p>
4−
5−<p><strong><em>This is strong and em.</em></strong></p>
6−
7−<p>So is <strong><em>this</em></strong> word.</p>
tests/MarkdownTest_1.0.3/Tests/Strong and em together.textdeleted−7
@@ -1,7 +0,0 @@
1−***This is strong and em.***
2−
3−So is ***this*** word.
4−
5−___This is strong and em.___
6−
7−So is ___this___ word.
tests/MarkdownTest_1.0.3/Tests/Tabs.htmldeleted−25
@@ -1,25 +0,0 @@
1−<ul>
2−<li><p>this is a list item
3−indented with tabs</p></li>
4−<li><p>this is a list item
5−indented with spaces</p></li>
6−</ul>
7−
8−<p>Code:</p>
9−
10−<pre><code>this code block is indented by one tab
11−</code></pre>
12−
13−<p>And:</p>
14−
15−<pre><code> this code block is indented by two tabs
16−</code></pre>
17−
18−<p>And:</p>
19−
20−<pre><code>+ this is an example list item
21− indented with tabs
22−
23−+ this is an example list item
24− indented with spaces
25−</code></pre>
tests/MarkdownTest_1.0.3/Tests/Tabs.textdeleted−21
@@ -1,21 +0,0 @@
1−+ this is a list item
2− indented with tabs
3−
4−+ this is a list item
5− indented with spaces
6−
7−Code:
8−
9− this code block is indented by one tab
10−
11−And:
12−
13− this code block is indented by two tabs
14−
15−And:
16−
17− + this is an example list item
18− indented with tabs
19−
20− + this is an example list item
21− indented with spaces
tests/MarkdownTest_1.0.3/Tests/Tidyness.htmldeleted−8
@@ -1,8 +0,0 @@
1−<blockquote>
2−<p>A list within a blockquote:</p>
3−<ul>
4−<li>asterisk 1</li>
5−<li>asterisk 2</li>
6−<li>asterisk 3</li>
7−</ul>
8−</blockquote>
tests/MarkdownTest_1.0.3/Tests/Tidyness.textdeleted−5
@@ -1,5 +0,0 @@
1−> A list within a blockquote:
2−>
3−> * asterisk 1
4−> * asterisk 2
5−> * asterisk 3
tests/Tests/Readers/LaTeX.hs+1−1
@@ -21,7 +21,7 @@ tests = [ testGroup "basic"
21 [ "simple" =:
21 [ "simple" =:
22 "word" =?> para "word"
22 "word" =?> para "word"
23 , "space" =:
23 , "space" =:
24− "some text" =?> para ("some text")
24+ "some text" =?> para "some text"
25 , "emphasized" =:
25 , "emphasized" =:
26 "\\emph{emphasized}" =?> para (emph "emphasized")
26 "\\emph{emphasized}" =?> para (emph "emphasized")
27 ]
27 ]
tests/Tests/Readers/Markdown.hs+7−2
@@ -136,6 +136,11 @@ tests = [ testGroup "inline code"
136 "`*` {.haskell .special x=\"7\"}"
136 "`*` {.haskell .special x=\"7\"}"
137 =?> para (codeWith ("",["haskell","special"],[("x","7")]) "*")
137 =?> para (codeWith ("",["haskell","special"],[("x","7")]) "*")
138 ]
138 ]
139+ , testGroup "emph and strong"
140+ [ "two strongs in emph" =:
141+ "***a**b **c**d*" =?> para (emph (strong (str "a") <> str "b" <> space
142+ <> strong (str "c") <> str "d"))
143+ ]
139 , testGroup "raw LaTeX"
144 , testGroup "raw LaTeX"
140 [ "in URL" =:
145 [ "in URL" =:
141 "\\begin\n" =?> para (text "\\begin")
146 "\\begin\n" =?> para (text "\\begin")
@@ -166,13 +171,13 @@ tests = [ testGroup "inline code"
166 , testGroup "smart punctuation"
171 , testGroup "smart punctuation"
167 [ test markdownSmart "quote before ellipses"
172 [ test markdownSmart "quote before ellipses"
168 ("'...hi'"
173 ("'...hi'"
169− =?> para (singleQuoted ("…hi")))
174+ =?> para (singleQuoted "…hi"))
170 , test markdownSmart "apostrophe before emph"
175 , test markdownSmart "apostrophe before emph"
171 ("D'oh! A l'*aide*!"
176 ("D'oh! A l'*aide*!"
172 =?> para ("D’oh! A l’" <> emph "aide" <> "!"))
177 =?> para ("D’oh! A l’" <> emph "aide" <> "!"))
173 , test markdownSmart "apostrophe in French"
178 , test markdownSmart "apostrophe in French"
174 ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»"
179 ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»"
175− =?> para ("À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»"))
180+ =?> para "À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»")
176 ]
181 ]
177 , testGroup "mixed emphasis and strong"
182 , testGroup "mixed emphasis and strong"
178 [ "emph and strong emph alternating" =:
183 [ "emph and strong emph alternating" =:
tests/Tests/Walk.hs+2−2
@@ -21,11 +21,11 @@ tests = [ testGroup "Walk"
21
21
22p_walk :: (Typeable a, Walkable a Pandoc)
22p_walk :: (Typeable a, Walkable a Pandoc)
23 => (a -> a) -> Pandoc -> Bool
23 => (a -> a) -> Pandoc -> Bool
24−p_walk f = (\(d :: Pandoc) -> everywhere (mkT f) d == walk f d)
24+p_walk f d = everywhere (mkT f) d == walk f d
25
25
26p_query :: (Eq a, Typeable a1, Monoid a, Walkable a1 Pandoc)
26p_query :: (Eq a, Typeable a1, Monoid a, Walkable a1 Pandoc)
27 => (a1 -> a) -> Pandoc -> Bool
27 => (a1 -> a) -> Pandoc -> Bool
28−p_query f = (\(d :: Pandoc) -> everything mappend (mempty `mkQ` f) d == query f d)
28+p_query f d = everything mappend (mempty `mkQ` f) d == query f d
29
29
30inlineTrans :: Inline -> Inline
30inlineTrans :: Inline -> Inline
31inlineTrans (Str xs) = Str $ map toUpper xs
31inlineTrans (Str xs) = Str $ map toUpper xs
tests/Tests/Writers/Markdown.hs+4
@@ -31,4 +31,8 @@ tests :: [Test]
31tests = [ "indented code after list"
31tests = [ "indented code after list"
32 =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")
32 =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")
33 =?> "1. one\n\n two\n\n<!-- -->\n\n test"
33 =?> "1. one\n\n two\n\n<!-- -->\n\n test"
34+ , "list with tight sublist"
35+ =: bulletList [ plain "foo" <> bulletList [ plain "bar" ],
36+ plain "baz" ]
37+ =?> "- foo\n - bar\n- baz\n"
34 ]
38 ]
tests/html-reader.native+10−10
@@ -1,4 +1,4 @@
1−Pandoc (Meta {unMeta = fromList [("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]})
1+Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]})
2[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Str "'",Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
2[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Str "'",Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
3,HorizontalRule
3,HorizontalRule
4,Header 1 ("",[],[]) [Str "Headers"]
4,Header 1 ("",[],[]) [Str "Headers"]
@@ -207,18 +207,18 @@ Pandoc (Meta {unMeta = fromList [("title",MetaInlines [Str "Pandoc",Space,Str "T
207,BulletList
207,BulletList
208 [[Plain [Str "\\cite[22",Str "-",Str "23]{smith",Str ".",Str "1899}"]]
208 [[Plain [Str "\\cite[22",Str "-",Str "23]{smith",Str ".",Str "1899}"]]
209 ,[Plain [Str "\\doublespacing"]]
209 ,[Plain [Str "\\doublespacing"]]
210− ,[Plain [Str "$2+2=4$"]]
210+ ,[Plain [Str "$",Str "2+2=4",Str "$"]]
211− ,[Plain [Str "$x",Space,Str "\\in",Space,Str "y$"]]
211+ ,[Plain [Str "$",Str "x",Space,Str "\\in",Space,Str "y",Str "$"]]
212− ,[Plain [Str "$\\alpha",Space,Str "\\wedge",Space,Str "\\omega$"]]
212+ ,[Plain [Str "$",Str "\\alpha",Space,Str "\\wedge",Space,Str "\\omega",Str "$"]]
213− ,[Plain [Str "$223$"]]
213+ ,[Plain [Str "$",Str "223",Str "$"]]
214− ,[Plain [Str "$p$",Str "-",Str "Tree"]]
214+ ,[Plain [Str "$",Str "p",Str "$",Str "-",Str "Tree"]]
215− ,[Plain [Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)",Str "-",Str "f(x)}{h}$"]]
215+ ,[Plain [Str "$",Str "\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)",Str "-",Str "f(x)}{h}",Str "$"]]
216− ,[Plain [Str "Here",Str "'",Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",Space,Str "x^2$",Str "."]]]
216+ ,[Plain [Str "Here",Str "'",Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$",Str "\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",Space,Str "x^2",Str "$",Str "."]]]
217,Para [Str "These",Space,Str "shouldn",Str "'",Str "t",Space,Str "be",Space,Str "math:"]
217,Para [Str "These",Space,Str "shouldn",Str "'",Str "t",Space,Str "be",Space,Str "math:"]
218,BulletList
218,BulletList
219 [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
219 [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
220− ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$34,000",Str ".",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Str "\"",Str "lot",Str "\"",Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]]
220+ ,[Plain [Str "$",Str "22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$",Str "34,000",Str ".",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Str "\"",Str "lot",Str "\"",Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]]
221− ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$",Str "."]]]
221+ ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$",Str "73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23",Str "$",Str "."]]]
222,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
222,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
223,Para [Str "\\begin{tabular}{|l|l|}\\hline",Space,Str "Animal",Space,Str "&",Space,Str "Number",Space,Str "\\\\",Space,Str "\\hline",Space,Str "Dog",Space,Str "&",Space,Str "2",Space,Str "\\\\",Space,Str "Cat",Space,Str "&",Space,Str "1",Space,Str "\\\\",Space,Str "\\hline",Space,Str "\\end{tabular}"]
223,Para [Str "\\begin{tabular}{|l|l|}\\hline",Space,Str "Animal",Space,Str "&",Space,Str "Number",Space,Str "\\\\",Space,Str "\\hline",Space,Str "Dog",Space,Str "&",Space,Str "2",Space,Str "\\\\",Space,Str "Cat",Space,Str "&",Space,Str "1",Space,Str "\\\\",Space,Str "\\hline",Space,Str "\\end{tabular}"]
224,HorizontalRule
224,HorizontalRule
tests/latex-reader.native+1−1
@@ -302,7 +302,7 @@ Pandoc (Meta {unMeta = fromList [("authors",MetaList [MetaInlines [Str "John",Sp
302,Para [Str "4",Space,Str "<",Space,Str "5."]
302,Para [Str "4",Space,Str "<",Space,Str "5."]
303,Para [Str "6",Space,Str ">",Space,Str "5."]
303,Para [Str "6",Space,Str ">",Space,Str "5."]
304,Para [Str "Backslash:",Space,Str "\\"]
304,Para [Str "Backslash:",Space,Str "\\"]
305−,Para [Str "Backtick:",Space,Str "\8216"]
305+,Para [Str "Backtick:",Space,Str "`"]
306,Para [Str "Asterisk:",Space,Str "*"]
306,Para [Str "Asterisk:",Space,Str "*"]
307,Para [Str "Underscore:",Space,Str "_"]
307,Para [Str "Underscore:",Space,Str "_"]
308,Para [Str "Left",Space,Str "brace:",Space,Str "{"]
308,Para [Str "Left",Space,Str "brace:",Space,Str "{"]
tests/lhs-test.markdown+2−2
@@ -4,11 +4,11 @@ lhs test
4`unsplit` is an arrow that takes a pair of values and combines them to return
4`unsplit` is an arrow that takes a pair of values and combines them to return
5a single value:
5a single value:
6
6
7−~~~~ {.sourceCode .literate .haskell}
7+``` {.sourceCode .literate .haskell}
8unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d
8unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d
9unsplit = arr . uncurry
9unsplit = arr . uncurry
10 -- arr (\op (x,y) -> x `op` y)
10 -- arr (\op (x,y) -> x `op` y)
11−~~~~
11+```
12
12
13`(***)` combines two arrows into a new arrow by running the two arrows on a
13`(***)` combines two arrows into a new arrow by running the two arrows on a
14pair of values (one arrow on the first item of the pair and one arrow on the
14pair of values (one arrow on the first item of the pair and one arrow on the
tests/markdown-reader-more.native+1−1
@@ -40,7 +40,7 @@
40,OrderedList (3,Example,TwoParens)
40,OrderedList (3,Example,TwoParens)
41 [[Plain [Str "Third",Space,Str "example."]]]
41 [[Plain [Str "Third",Space,Str "example."]]]
42,Header 2 ("macros",[],[]) [Str "Macros"]
42,Header 2 ("macros",[],[]) [Str "Macros"]
43−,Para [Math InlineMath "\\langle x,y \\rangle"]
43+,Para [Math InlineMath "{\\langle x,y \\rangle}"]
44,Header 2 ("case-insensitive-references",[],[]) [Str "Case-insensitive",Space,Str "references"]
44,Header 2 ("case-insensitive-references",[],[]) [Str "Case-insensitive",Space,Str "references"]
45,Para [Link [Str "Fum"] ("/fum","")]
45,Para [Link [Str "Fum"] ("/fum","")]
46,Para [Link [Str "FUM"] ("/fum","")]
46,Para [Link [Str "FUM"] ("/fum","")]
tests/mediawiki-reader.native+29−29
@@ -1,39 +1,39 @@
1Pandoc (Meta {unMeta = fromList []})
1Pandoc (Meta {unMeta = fromList []})
2−[Header 1 ("",[],[]) [Str "header"]
2+[Header 1 ("header",[],[]) [Str "header"]
3−,Header 2 ("",[],[]) [Str "header",Space,Str "level",Space,Str "two"]
3+,Header 2 ("header-level-two",[],[]) [Str "header",Space,Str "level",Space,Str "two"]
4−,Header 3 ("",[],[]) [Str "header",Space,Str "level",Space,Str "3"]
4+,Header 3 ("header-level-3",[],[]) [Str "header",Space,Str "level",Space,Str "3"]
5−,Header 4 ("",[],[]) [Str "header",Space,Emph [Str "level"],Space,Str "four"]
5+,Header 4 ("header-level-four",[],[]) [Str "header",Space,Emph [Str "level"],Space,Str "four"]
6−,Header 5 ("",[],[]) [Str "header",Space,Str "level",Space,Str "5"]
6+,Header 5 ("header-level-5",[],[]) [Str "header",Space,Str "level",Space,Str "5"]
7−,Header 6 ("",[],[]) [Str "header",Space,Str "level",Space,Str "6"]
7+,Header 6 ("header-level-6",[],[]) [Str "header",Space,Str "level",Space,Str "6"]
8,Para [Str "=======",Space,Str "not",Space,Str "a",Space,Str "header",Space,Str "========"]
8,Para [Str "=======",Space,Str "not",Space,Str "a",Space,Str "header",Space,Str "========"]
9,Para [Code ("",[],[]) "==\160not\160a\160header\160=="]
9,Para [Code ("",[],[]) "==\160not\160a\160header\160=="]
10−,Header 2 ("",[],[]) [Str "emph",Space,Str "and",Space,Str "strong"]
10+,Header 2 ("emph-and-strong",[],[]) [Str "emph",Space,Str "and",Space,Str "strong"]
11,Para [Emph [Str "emph"],Space,Strong [Str "strong"]]
11,Para [Emph [Str "emph"],Space,Strong [Str "strong"]]
12,Para [Strong [Emph [Str "strong",Space,Str "and",Space,Str "emph"]]]
12,Para [Strong [Emph [Str "strong",Space,Str "and",Space,Str "emph"]]]
13,Para [Strong [Emph [Str "emph",Space,Str "inside"],Space,Str "strong"]]
13,Para [Strong [Emph [Str "emph",Space,Str "inside"],Space,Str "strong"]]
14,Para [Strong [Str "strong",Space,Str "with",Space,Emph [Str "emph"]]]
14,Para [Strong [Str "strong",Space,Str "with",Space,Emph [Str "emph"]]]
15,Para [Emph [Strong [Str "strong",Space,Str "inside"],Space,Str "emph"]]
15,Para [Emph [Strong [Str "strong",Space,Str "inside"],Space,Str "emph"]]
16−,Header 2 ("",[],[]) [Str "horizontal",Space,Str "rule"]
16+,Header 2 ("horizontal-rule",[],[]) [Str "horizontal",Space,Str "rule"]
17,Para [Str "top"]
17,Para [Str "top"]
18,HorizontalRule
18,HorizontalRule
19,Para [Str "bottom"]
19,Para [Str "bottom"]
20,HorizontalRule
20,HorizontalRule
21−,Header 2 ("",[],[]) [Str "nowiki"]
21+,Header 2 ("nowiki",[],[]) [Str "nowiki"]
22,Para [Str "''not",Space,Str "emph''"]
22,Para [Str "''not",Space,Str "emph''"]
23−,Header 2 ("",[],[]) [Str "strikeout"]
23+,Header 2 ("strikeout",[],[]) [Str "strikeout"]
24,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "struck",Space,Str "out"]]]
24,Para [Strikeout [Str "This",Space,Str "is",Space,Emph [Str "struck",Space,Str "out"]]]
25−,Header 2 ("",[],[]) [Str "entities"]
25+,Header 2 ("entities",[],[]) [Str "entities"]
26,Para [Str "hi",Space,Str "&",Space,Str "low"]
26,Para [Str "hi",Space,Str "&",Space,Str "low"]
27,Para [Str "hi",Space,Str "&",Space,Str "low"]
27,Para [Str "hi",Space,Str "&",Space,Str "low"]
28,Para [Str "G\246del"]
28,Para [Str "G\246del"]
29,Para [Str "\777\2730"]
29,Para [Str "\777\2730"]
30−,Header 2 ("",[],[]) [Str "comments"]
30+,Header 2 ("comments",[],[]) [Str "comments"]
31,Para [Str "inline",Space,Str "comment"]
31,Para [Str "inline",Space,Str "comment"]
32,Para [Str "between",Space,Str "blocks"]
32,Para [Str "between",Space,Str "blocks"]
33−,Header 2 ("",[],[]) [Str "linebreaks"]
33+,Header 2 ("linebreaks",[],[]) [Str "linebreaks"]
34,Para [Str "hi",LineBreak,Str "there"]
34,Para [Str "hi",LineBreak,Str "there"]
35,Para [Str "hi",LineBreak,Str "there"]
35,Para [Str "hi",LineBreak,Str "there"]
36−,Header 2 ("",[],[]) [Str ":",Space,Str "indents"]
36+,Header 2 ("indents",[],[]) [Str ":",Space,Str "indents"]
37,Para [Str "hi"]
37,Para [Str "hi"]
38,DefinitionList
38,DefinitionList
39 [([],
39 [([],
@@ -46,36 +46,36 @@ Pandoc (Meta {unMeta = fromList []})
46 [([],
46 [([],
47 [[Plain [Str "there"]]])]]])]
47 [[Plain [Str "there"]]])]]])]
48,Para [Str "bud"]
48,Para [Str "bud"]
49−,Header 2 ("",[],[]) [Str "p",Space,Str "tags"]
49+,Header 2 ("p-tags",[],[]) [Str "p",Space,Str "tags"]
50,Para [Str "hi",Space,Str "there"]
50,Para [Str "hi",Space,Str "there"]
51,Para [Str "bud"]
51,Para [Str "bud"]
52,Para [Str "another"]
52,Para [Str "another"]
53−,Header 2 ("",[],[]) [Str "raw",Space,Str "html"]
53+,Header 2 ("raw-html",[],[]) [Str "raw",Space,Str "html"]
54,Para [Str "hi",Space,RawInline (Format "html") "<span style=\"color:red\">",Emph [Str "there"],RawInline (Format "html") "</span>",Str "."]
54,Para [Str "hi",Space,RawInline (Format "html") "<span style=\"color:red\">",Emph [Str "there"],RawInline (Format "html") "</span>",Str "."]
55,Para [RawInline (Format "html") "<ins>",Str "inserted",RawInline (Format "html") "</ins>"]
55,Para [RawInline (Format "html") "<ins>",Str "inserted",RawInline (Format "html") "</ins>"]
56,RawBlock (Format "html") "<div class=\"special\">"
56,RawBlock (Format "html") "<div class=\"special\">"
57,Para [Str "hi",Space,Emph [Str "there"]]
57,Para [Str "hi",Space,Emph [Str "there"]]
58,RawBlock (Format "html") "</div>"
58,RawBlock (Format "html") "</div>"
59−,Header 2 ("",[],[]) [Str "sup,",Space,Str "sub,",Space,Str "del"]
59+,Header 2 ("sup-sub-del",[],[]) [Str "sup,",Space,Str "sub,",Space,Str "del"]
60,Para [Str "H",Subscript [Str "2"],Str "O",Space,Str "base",Superscript [Emph [Str "exponent"]],Space,Strikeout [Str "hello"]]
60,Para [Str "H",Subscript [Str "2"],Str "O",Space,Str "base",Superscript [Emph [Str "exponent"]],Space,Strikeout [Str "hello"]]
61−,Header 2 ("",[],[]) [Str "inline",Space,Str "code"]
61+,Header 2 ("inline-code",[],[]) [Str "inline",Space,Str "code"]
62,Para [Code ("",[],[]) "*\8594*",Space,Code ("",[],[]) "typed",Space,Code ("",["haskell"],[]) ">>="]
62,Para [Code ("",[],[]) "*\8594*",Space,Code ("",[],[]) "typed",Space,Code ("",["haskell"],[]) ">>="]
63−,Header 2 ("",[],[]) [Str "code",Space,Str "blocks"]
63+,Header 2 ("code-blocks",[],[]) [Str "code",Space,Str "blocks"]
64,CodeBlock ("",[],[]) "case xs of\n (_:_) -> reverse xs\n [] -> ['*']"
64,CodeBlock ("",[],[]) "case xs of\n (_:_) -> reverse xs\n [] -> ['*']"
65,CodeBlock ("",["haskell"],[]) "case xs of\n (_:_) -> reverse xs\n [] -> ['*']"
65,CodeBlock ("",["haskell"],[]) "case xs of\n (_:_) -> reverse xs\n [] -> ['*']"
66,CodeBlock ("",["ruby","numberLines"],[("startFrom","100")]) "widgets.each do |w|\n print w.price\nend"
66,CodeBlock ("",["ruby","numberLines"],[("startFrom","100")]) "widgets.each do |w|\n print w.price\nend"
67−,Header 2 ("",[],[]) [Str "block",Space,Str "quotes"]
67+,Header 2 ("block-quotes",[],[]) [Str "block",Space,Str "quotes"]
68,Para [Str "Regular",Space,Str "paragraph"]
68,Para [Str "Regular",Space,Str "paragraph"]
69,BlockQuote
69,BlockQuote
70 [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote."]
70 [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote."]
71 ,Para [Str "With",Space,Str "two",Space,Str "paragraphs."]]
71 ,Para [Str "With",Space,Str "two",Space,Str "paragraphs."]]
72,Para [Str "Nother",Space,Str "paragraph."]
72,Para [Str "Nother",Space,Str "paragraph."]
73−,Header 2 ("",[],[]) [Str "external",Space,Str "links"]
73+,Header 2 ("external-links",[],[]) [Str "external",Space,Str "links"]
74,Para [Link [Emph [Str "Google"],Space,Str "search",Space,Str "engine"] ("http://google.com","")]
74,Para [Link [Emph [Str "Google"],Space,Str "search",Space,Str "engine"] ("http://google.com","")]
75,Para [Link [Str "http://johnmacfarlane.net/pandoc/"] ("http://johnmacfarlane.net/pandoc/","")]
75,Para [Link [Str "http://johnmacfarlane.net/pandoc/"] ("http://johnmacfarlane.net/pandoc/","")]
76,Para [Link [Str "1"] ("http://google.com",""),Space,Link [Str "2"] ("http://yahoo.com","")]
76,Para [Link [Str "1"] ("http://google.com",""),Space,Link [Str "2"] ("http://yahoo.com","")]
77,Para [Link [Str "email",Space,Str "me"] ("mailto:info@example.org","")]
77,Para [Link [Str "email",Space,Str "me"] ("mailto:info@example.org","")]
78−,Header 2 ("",[],[]) [Str "internal",Space,Str "links"]
78+,Header 2 ("internal-links",[],[]) [Str "internal",Space,Str "links"]
79,Para [Link [Str "Help"] ("Help","wikilink")]
79,Para [Link [Str "Help"] ("Help","wikilink")]
80,Para [Link [Str "the",Space,Str "help",Space,Str "page"] ("Help","wikilink")]
80,Para [Link [Str "the",Space,Str "help",Space,Str "page"] ("Help","wikilink")]
81,Para [Link [Str "Helpers"] ("Help","wikilink")]
81,Para [Link [Str "Helpers"] ("Help","wikilink")]
@@ -83,12 +83,12 @@ Pandoc (Meta {unMeta = fromList []})
83,Para [Link [Str "Contents"] ("Help:Contents","wikilink")]
83,Para [Link [Str "Contents"] ("Help:Contents","wikilink")]
84,Para [Link [Str "#My",Space,Str "anchor"] ("#My_anchor","wikilink")]
84,Para [Link [Str "#My",Space,Str "anchor"] ("#My_anchor","wikilink")]
85,Para [Link [Str "and",Space,Str "text"] ("Page#with_anchor","wikilink")]
85,Para [Link [Str "and",Space,Str "text"] ("Page#with_anchor","wikilink")]
86−,Header 2 ("",[],[]) [Str "images"]
86+,Header 2 ("images",[],[]) [Str "images"]
87,Para [Image [Str "caption"] ("example.jpg","fig:caption")]
87,Para [Image [Str "caption"] ("example.jpg","fig:caption")]
88,Para [Image [Str "the",Space,Emph [Str "caption"],Space,Str "with",Space,Link [Str "external",Space,Str "link"] ("http://google.com","")] ("example.jpg","fig:the caption with external link")]
88,Para [Image [Str "the",Space,Emph [Str "caption"],Space,Str "with",Space,Link [Str "external",Space,Str "link"] ("http://google.com","")] ("example.jpg","fig:the caption with external link")]
89,Para [Image [Str "caption"] ("example.jpg","fig:caption")]
89,Para [Image [Str "caption"] ("example.jpg","fig:caption")]
90,Para [Image [Str "example.jpg"] ("example.jpg","fig:example.jpg")]
90,Para [Image [Str "example.jpg"] ("example.jpg","fig:example.jpg")]
91−,Header 2 ("",[],[]) [Str "lists"]
91+,Header 2 ("lists",[],[]) [Str "lists"]
92,BulletList
92,BulletList
93 [[Plain [Str "Start",Space,Str "each",Space,Str "line"]]
93 [[Plain [Str "Start",Space,Str "each",Space,Str "line"]]
94 ,[Plain [Str "with",Space,Str "an",Space,Str "asterisk",Space,Str "(*)."]
94 ,[Plain [Str "with",Space,Str "an",Space,Str "asterisk",Space,Str "(*)."]
@@ -161,10 +161,10 @@ Pandoc (Meta {unMeta = fromList []})
161 [[Plain [Str "Amsterdam"]]
161 [[Plain [Str "Amsterdam"]]
162 ,[Plain [Str "Rotterdam"]]
162 ,[Plain [Str "Rotterdam"]]
163 ,[Plain [Str "The",Space,Str "Hague"]]]
163 ,[Plain [Str "The",Space,Str "Hague"]]]
164−,Header 2 ("",[],[]) [Str "math"]
164+,Header 2 ("math",[],[]) [Str "math"]
165,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."]
165,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."]
166,Para [Str "With",Space,Str "spaces:",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."]
166,Para [Str "With",Space,Str "spaces:",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."]
167−,Header 2 ("",[],[]) [Str "preformatted",Space,Str "blocks"]
167+,Header 2 ("preformatted-blocks",[],[]) [Str "preformatted",Space,Str "blocks"]
168,Para [Code ("",[],[]) "Start\160each\160line\160with\160a\160space.",LineBreak,Code ("",[],[]) "Text\160is\160",Strong [Code ("",[],[]) "preformatted"],Code ("",[],[]) "\160and",LineBreak,Emph [Code ("",[],[]) "markups"],Code ("",[],[]) "\160",Strong [Emph [Code ("",[],[]) "can"]],Code ("",[],[]) "\160be\160done."]
168,Para [Code ("",[],[]) "Start\160each\160line\160with\160a\160space.",LineBreak,Code ("",[],[]) "Text\160is\160",Strong [Code ("",[],[]) "preformatted"],Code ("",[],[]) "\160and",LineBreak,Emph [Code ("",[],[]) "markups"],Code ("",[],[]) "\160",Strong [Emph [Code ("",[],[]) "can"]],Code ("",[],[]) "\160be\160done."]
169,Para [Code ("",[],[]) "\160hell\160\160\160\160\160\160yeah"]
169,Para [Code ("",[],[]) "\160hell\160\160\160\160\160\160yeah"]
170,Para [Code ("",[],[]) "Start\160with\160a\160space\160in\160the\160first\160column,",LineBreak,Code ("",[],[]) "(before\160the\160<nowiki>).",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "Then\160your\160block\160format\160will\160be",LineBreak,Code ("",[],[]) "\160\160\160\160maintained.",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "This\160is\160good\160for\160copying\160in\160code\160blocks:",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "def\160function():",LineBreak,Code ("",[],[]) "\160\160\160\160\"\"\"documentation\160string\"\"\"",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "\160\160\160\160if\160True:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160True",LineBreak,Code ("",[],[]) "\160\160\160\160else:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160False"]
170,Para [Code ("",[],[]) "Start\160with\160a\160space\160in\160the\160first\160column,",LineBreak,Code ("",[],[]) "(before\160the\160<nowiki>).",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "Then\160your\160block\160format\160will\160be",LineBreak,Code ("",[],[]) "\160\160\160\160maintained.",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "This\160is\160good\160for\160copying\160in\160code\160blocks:",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "def\160function():",LineBreak,Code ("",[],[]) "\160\160\160\160\"\"\"documentation\160string\"\"\"",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "\160\160\160\160if\160True:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160True",LineBreak,Code ("",[],[]) "\160\160\160\160else:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160False"]
@@ -174,12 +174,12 @@ Pandoc (Meta {unMeta = fromList []})
174,Para [Str "Don't",Space,Str "need"]
174,Para [Str "Don't",Space,Str "need"]
175,Para [Code ("",[],[]) "a\160blank\160line"]
175,Para [Code ("",[],[]) "a\160blank\160line"]
176,Para [Str "around",Space,Str "a",Space,Str "preformatted",Space,Str "block."]
176,Para [Str "around",Space,Str "a",Space,Str "preformatted",Space,Str "block."]
177−,Header 2 ("",[],[]) [Str "templates"]
177+,Header 2 ("templates",[],[]) [Str "templates"]
178,RawBlock (Format "mediawiki") "{{Welcome}}"
178,RawBlock (Format "mediawiki") "{{Welcome}}"
179,RawBlock (Format "mediawiki") "{{Foo:Bar}}"
179,RawBlock (Format "mediawiki") "{{Foo:Bar}}"
180,RawBlock (Format "mediawiki") "{{Thankyou|all your effort|Me}}"
180,RawBlock (Format "mediawiki") "{{Thankyou|all your effort|Me}}"
181,Para [Str "Written",Space,RawInline (Format "mediawiki") "{{{date}}}",Space,Str "by",Space,RawInline (Format "mediawiki") "{{{name}}}",Str "."]
181,Para [Str "Written",Space,RawInline (Format "mediawiki") "{{{date}}}",Space,Str "by",Space,RawInline (Format "mediawiki") "{{{name}}}",Str "."]
182−,Header 2 ("",[],[]) [Str "tables"]
182+,Header 2 ("tables",[],[]) [Str "tables"]
183,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
183,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
184 [[]
184 [[]
185 ,[]]
185 ,[]]
@@ -245,6 +245,6 @@ Pandoc (Meta {unMeta = fromList []})
245 [[]]
245 [[]]
246 [[[Para [Str "Orange"]]]]
246 [[[Para [Str "Orange"]]]]
247,Para [Str "Paragraph",Space,Str "after",Space,Str "the",Space,Str "table."]
247,Para [Str "Paragraph",Space,Str "after",Space,Str "the",Space,Str "table."]
248−,Header 2 ("",[],[]) [Str "notes"]
248+,Header 2 ("notes",[],[]) [Str "notes"]
249,Para [Str "My",Space,Str "note!",Note [Plain [Str "This."]]]
249,Para [Str "My",Space,Str "note!",Note [Plain [Str "This."]]]
250,Para [Str "URL",Space,Str "note.",Note [Plain [Link [Str "http://docs.python.org/library/functions.html#range"] ("http://docs.python.org/library/functions.html#range","")]]]]
250,Para [Str "URL",Space,Str "note.",Note [Plain [Link [Str "http://docs.python.org/library/functions.html#range"] ("http://docs.python.org/library/functions.html#range","")]]]]
tests/mediawiki-reader.wiki+2−2
@@ -232,11 +232,11 @@ ends the list.
232 <li>list item A2</li>
232 <li>list item A2</li>
233</ol>
233</ol>
234
234
235−<ul>
235+<ol>
236#abc
236#abc
237#def
237#def
238#ghi
238#ghi
239−</ul>
239+</ol>
240
240
241<ol start="9">
241<ol start="9">
242<li>Amsterdam</li>
242<li>Amsterdam</li>
tests/tables.context+7−7
@@ -1,6 +1,6 @@
1Simple table with caption:
1Simple table with caption:
2
2
3−\placetable[here]{Demonstration of simple table syntax.}
3+\placetable{Demonstration of simple table syntax.}
4\starttable[|r|l|c|l|]
4\starttable[|r|l|c|l|]
5\HL
5\HL
6\NC Right
6\NC Right
@@ -29,7 +29,7 @@ Simple table with caption:
29
29
30Simple table without caption:
30Simple table without caption:
31
31
32−\placetable[here,none]{}
32+\placetable[none]{}
33\starttable[|r|l|c|l|]
33\starttable[|r|l|c|l|]
34\HL
34\HL
35\NC Right
35\NC Right
@@ -58,7 +58,7 @@ Simple table without caption:
58
58
59Simple table indented two spaces:
59Simple table indented two spaces:
60
60
61−\placetable[here]{Demonstration of simple table syntax.}
61+\placetable{Demonstration of simple table syntax.}
62\starttable[|r|l|c|l|]
62\starttable[|r|l|c|l|]
63\HL
63\HL
64\NC Right
64\NC Right
@@ -87,7 +87,7 @@ Simple table indented two spaces:
87
87
88Multiline table with caption:
88Multiline table with caption:
89
89
90−\placetable[here]{Here's the caption. It may span multiple lines.}
90+\placetable{Here's the caption. It may span multiple lines.}
91\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
91\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
92\HL
92\HL
93\NC Centered Header
93\NC Centered Header
@@ -111,7 +111,7 @@ Multiline table with caption:
111
111
112Multiline table without caption:
112Multiline table without caption:
113
113
114−\placetable[here,none]{}
114+\placetable[none]{}
115\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
115\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
116\HL
116\HL
117\NC Centered Header
117\NC Centered Header
@@ -135,7 +135,7 @@ Multiline table without caption:
135
135
136Table without column headers:
136Table without column headers:
137
137
138−\placetable[here,none]{}
138+\placetable[none]{}
139\starttable[|r|l|c|r|]
139\starttable[|r|l|c|r|]
140\HL
140\HL
141\NC 12
141\NC 12
@@ -158,7 +158,7 @@ Table without column headers:
158
158
159Multiline table without column headers:
159Multiline table without column headers:
160
160
161−\placetable[here,none]{}
161+\placetable[none]{}
162\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
162\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
163\HL
163\HL
164\NC First
164\NC First
tests/tables.latex+45−45
@@ -1,59 +1,59 @@
1Simple table with caption:
1Simple table with caption:
2
2
3\begin{longtable}[c]{@{}rlcl@{}}
3\begin{longtable}[c]{@{}rlcl@{}}
4−\hline\noalign{\medskip}
4+\toprule\addlinespace
5Right & Left & Center & Default
5Right & Left & Center & Default
6−\\\noalign{\medskip}
6+\\\addlinespace
7−\hline\noalign{\medskip}
7+\midrule\endhead
812 & 12 & 12 & 12
812 & 12 & 12 & 12
9−\\\noalign{\medskip}
9+\\\addlinespace
10123 & 123 & 123 & 123
10123 & 123 & 123 & 123
11−\\\noalign{\medskip}
11+\\\addlinespace
121 & 1 & 1 & 1
121 & 1 & 1 & 1
13−\\\noalign{\medskip}
13+\\\addlinespace
14−\hline
14+\bottomrule
15−\noalign{\medskip}
15+\addlinespace
16\caption{Demonstration of simple table syntax.}
16\caption{Demonstration of simple table syntax.}
17\end{longtable}
17\end{longtable}
18
18
19Simple table without caption:
19Simple table without caption:
20
20
21\begin{longtable}[c]{@{}rlcl@{}}
21\begin{longtable}[c]{@{}rlcl@{}}
22−\hline\noalign{\medskip}
22+\toprule\addlinespace
23Right & Left & Center & Default
23Right & Left & Center & Default
24−\\\noalign{\medskip}
24+\\\addlinespace
25−\hline\noalign{\medskip}
25+\midrule\endhead
2612 & 12 & 12 & 12
2612 & 12 & 12 & 12
27−\\\noalign{\medskip}
27+\\\addlinespace
28123 & 123 & 123 & 123
28123 & 123 & 123 & 123
29−\\\noalign{\medskip}
29+\\\addlinespace
301 & 1 & 1 & 1
301 & 1 & 1 & 1
31−\\\noalign{\medskip}
31+\\\addlinespace
32−\hline
32+\bottomrule
33\end{longtable}
33\end{longtable}
34
34
35Simple table indented two spaces:
35Simple table indented two spaces:
36
36
37\begin{longtable}[c]{@{}rlcl@{}}
37\begin{longtable}[c]{@{}rlcl@{}}
38−\hline\noalign{\medskip}
38+\toprule\addlinespace
39Right & Left & Center & Default
39Right & Left & Center & Default
40−\\\noalign{\medskip}
40+\\\addlinespace
41−\hline\noalign{\medskip}
41+\midrule\endhead
4212 & 12 & 12 & 12
4212 & 12 & 12 & 12
43−\\\noalign{\medskip}
43+\\\addlinespace
44123 & 123 & 123 & 123
44123 & 123 & 123 & 123
45−\\\noalign{\medskip}
45+\\\addlinespace
461 & 1 & 1 & 1
461 & 1 & 1 & 1
47−\\\noalign{\medskip}
47+\\\addlinespace
48−\hline
48+\bottomrule
49−\noalign{\medskip}
49+\addlinespace
50\caption{Demonstration of simple table syntax.}
50\caption{Demonstration of simple table syntax.}
51\end{longtable}
51\end{longtable}
52
52
53Multiline table with caption:
53Multiline table with caption:
54
54
55\begin{longtable}[c]{@{}clrl@{}}
55\begin{longtable}[c]{@{}clrl@{}}
56−\hline\noalign{\medskip}
56+\toprule\addlinespace
57\begin{minipage}[b]{0.13\columnwidth}\centering
57\begin{minipage}[b]{0.13\columnwidth}\centering
58Centered Header
58Centered Header
59\end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright
59\end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright
@@ -63,8 +63,8 @@ Right Aligned
63\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
63\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
64Default aligned
64Default aligned
65\end{minipage}
65\end{minipage}
66−\\\noalign{\medskip}
66+\\\addlinespace
67−\hline\noalign{\medskip}
67+\midrule\endhead
68\begin{minipage}[t]{0.13\columnwidth}\centering
68\begin{minipage}[t]{0.13\columnwidth}\centering
69First
69First
70\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
70\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
@@ -74,7 +74,7 @@ row
74\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
74\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
75Example of a row that spans multiple lines.
75Example of a row that spans multiple lines.
76\end{minipage}
76\end{minipage}
77−\\\noalign{\medskip}
77+\\\addlinespace
78\begin{minipage}[t]{0.13\columnwidth}\centering
78\begin{minipage}[t]{0.13\columnwidth}\centering
79Second
79Second
80\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
80\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
@@ -84,16 +84,16 @@ row
84\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
84\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
85Here's another one. Note the blank line between rows.
85Here's another one. Note the blank line between rows.
86\end{minipage}
86\end{minipage}
87−\\\noalign{\medskip}
87+\\\addlinespace
88−\hline
88+\bottomrule
89−\noalign{\medskip}
89+\addlinespace
90\caption{Here's the caption. It may span multiple lines.}
90\caption{Here's the caption. It may span multiple lines.}
91\end{longtable}
91\end{longtable}
92
92
93Multiline table without caption:
93Multiline table without caption:
94
94
95\begin{longtable}[c]{@{}clrl@{}}
95\begin{longtable}[c]{@{}clrl@{}}
96−\hline\noalign{\medskip}
96+\toprule\addlinespace
97\begin{minipage}[b]{0.13\columnwidth}\centering
97\begin{minipage}[b]{0.13\columnwidth}\centering
98Centered Header
98Centered Header
99\end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright
99\end{minipage} & \begin{minipage}[b]{0.12\columnwidth}\raggedright
@@ -103,8 +103,8 @@ Right Aligned
103\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
103\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
104Default aligned
104Default aligned
105\end{minipage}
105\end{minipage}
106−\\\noalign{\medskip}
106+\\\addlinespace
107−\hline\noalign{\medskip}
107+\midrule\endhead
108\begin{minipage}[t]{0.13\columnwidth}\centering
108\begin{minipage}[t]{0.13\columnwidth}\centering
109First
109First
110\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
110\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
@@ -114,7 +114,7 @@ row
114\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
114\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
115Example of a row that spans multiple lines.
115Example of a row that spans multiple lines.
116\end{minipage}
116\end{minipage}
117−\\\noalign{\medskip}
117+\\\addlinespace
118\begin{minipage}[t]{0.13\columnwidth}\centering
118\begin{minipage}[t]{0.13\columnwidth}\centering
119Second
119Second
120\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
120\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
@@ -124,27 +124,27 @@ row
124\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
124\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
125Here's another one. Note the blank line between rows.
125Here's another one. Note the blank line between rows.
126\end{minipage}
126\end{minipage}
127−\\\noalign{\medskip}
127+\\\addlinespace
128−\hline
128+\bottomrule
129\end{longtable}
129\end{longtable}
130
130
131Table without column headers:
131Table without column headers:
132
132
133\begin{longtable}[c]{@{}rlcr@{}}
133\begin{longtable}[c]{@{}rlcr@{}}
134−\hline\noalign{\medskip}
134+\toprule\addlinespace
13512 & 12 & 12 & 12
13512 & 12 & 12 & 12
136−\\\noalign{\medskip}
136+\\\addlinespace
137123 & 123 & 123 & 123
137123 & 123 & 123 & 123
138−\\\noalign{\medskip}
138+\\\addlinespace
1391 & 1 & 1 & 1
1391 & 1 & 1 & 1
140−\\\noalign{\medskip}
140+\\\addlinespace
141−\hline
141+\bottomrule
142\end{longtable}
142\end{longtable}
143
143
144Multiline table without column headers:
144Multiline table without column headers:
145
145
146\begin{longtable}[c]{@{}clrl@{}}
146\begin{longtable}[c]{@{}clrl@{}}
147−\hline\noalign{\medskip}
147+\toprule\addlinespace
148\begin{minipage}[t]{0.13\columnwidth}\centering
148\begin{minipage}[t]{0.13\columnwidth}\centering
149First
149First
150\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
150\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
@@ -154,7 +154,7 @@ row
154\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
154\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
155Example of a row that spans multiple lines.
155Example of a row that spans multiple lines.
156\end{minipage}
156\end{minipage}
157−\\\noalign{\medskip}
157+\\\addlinespace
158\begin{minipage}[t]{0.13\columnwidth}\centering
158\begin{minipage}[t]{0.13\columnwidth}\centering
159Second
159Second
160\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
160\end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
@@ -164,6 +164,6 @@ row
164\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
164\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
165Here's another one. Note the blank line between rows.
165Here's another one. Note the blank line between rows.
166\end{minipage}
166\end{minipage}
167−\\\noalign{\medskip}
167+\\\addlinespace
168−\hline
168+\bottomrule
169\end{longtable}
169\end{longtable}
tests/writer.context+4−1
@@ -30,6 +30,9 @@
30\setupitemize[autointro] % prevent orphan list intro
30\setupitemize[autointro] % prevent orphan list intro
31\setupitemize[indentnext=no]
31\setupitemize[indentnext=no]
32
32
33+\setupfloat[figure][default={here,nonumber}]
34+\setupfloat[table][default={here,nonumber}]
35+
33\setupthinrules[width=15em] % width of horizontal rules
36\setupthinrules[width=15em] % width of horizontal rules
34
37
35\setupdelimitedtext
38\setupdelimitedtext
@@ -842,7 +845,7 @@ or here: <http://example.com/>
842
845
843From \quotation{Voyage dans la Lune} by Georges Melies (1902):
846From \quotation{Voyage dans la Lune} by Georges Melies (1902):
844
847
845−\placefigure[here,nonumber]{lalune}{\externalfigure[lalune.jpg]}
848+\placefigure{lalune}{\externalfigure[lalune.jpg]}
846
849
847Here is a movie {\externalfigure[movie.jpg]} icon.
850Here is a movie {\externalfigure[movie.jpg]} icon.
848
851
tests/writer.html+3−3
@@ -544,12 +544,12 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'a'+'>');
544<p>Here is a movie <img src="movie.jpg" alt="movie" /> icon.</p>
544<p>Here is a movie <img src="movie.jpg" alt="movie" /> icon.</p>
545<hr />
545<hr />
546<h1 id="footnotes">Footnotes</h1>
546<h1 id="footnotes">Footnotes</h1>
547−<p>Here is a footnote reference,<sup><a href="#fn1" class="footnoteRef" id="fnref1">1</a></sup> and another.<sup><a href="#fn2" class="footnoteRef" id="fnref2">2</a></sup> This should <em>not</em> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<sup><a href="#fn3" class="footnoteRef" id="fnref3">3</a></sup></p>
547+<p>Here is a footnote reference,<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> and another.<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a> This should <em>not</em> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a></p>
548<blockquote>
548<blockquote>
549−<p>Notes can go in quotes.<sup><a href="#fn4" class="footnoteRef" id="fnref4">4</a></sup></p>
549+<p>Notes can go in quotes.<a href="#fn4" class="footnoteRef" id="fnref4"><sup>4</sup></a></p>
550</blockquote>
550</blockquote>
551<ol style="list-style-type: decimal">
551<ol style="list-style-type: decimal">
552−<li>And in list items.<sup><a href="#fn5" class="footnoteRef" id="fnref5">5</a></sup></li>
552+<li>And in list items.<a href="#fn5" class="footnoteRef" id="fnref5"><sup>5</sup></a></li>
553</ol>
553</ol>
554<p>This paragraph should not be part of the note, as it is not indented.</p>
554<p>This paragraph should not be part of the note, as it is not indented.</p>
555<div class="footnotes">
555<div class="footnotes">
tests/writer.opendocument+2−2
@@ -1576,9 +1576,9 @@ link in pointy braces</text:span></text:a>.</text:p>
1576<text:h text:style-name="Heading_20_1" text:outline-level="1">Images</text:h>
1576<text:h text:style-name="Heading_20_1" text:outline-level="1">Images</text:h>
1577<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by
1577<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by
1578Georges Melies (1902):</text:p>
1578Georges Melies (1902):</text:p>
1579−<text:p text:style-name="Text_20_body"><draw:frame><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>
1579+<text:p text:style-name="Text_20_body"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>
1580<text:p text:style-name="Text_20_body">Here is a movie
1580<text:p text:style-name="Text_20_body">Here is a movie
1581−<draw:frame><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>
1581+<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>
1582icon.</text:p>
1582icon.</text:p>
1583<text:p text:style-name="Horizontal_20_Line" />
1583<text:p text:style-name="Horizontal_20_Line" />
1584<text:h text:style-name="Heading_20_1" text:outline-level="1">Footnotes</text:h>
1584<text:h text:style-name="Heading_20_1" text:outline-level="1">Footnotes</text:h>
windows/make-windows-installer.bat−1
@@ -10,7 +10,6 @@ cabal-dev install -v1 --reinstall --flags="embed_data_files" pandoc-citeproc
10if %errorlevel% neq 0 exit /b %errorlevel%
10if %errorlevel% neq 0 exit /b %errorlevel%
11strip cabal-dev\bin\pandoc.exe
11strip cabal-dev\bin\pandoc.exe
12strip cabal-dev\bin\pandoc-citeproc.exe
12strip cabal-dev\bin\pandoc-citeproc.exe
13−strip cabal-dev\bin\biblio2yaml.exe
14cabal-dev\bin\pandoc.exe -s --template data\templates\default.html -S README -o README.html
13cabal-dev\bin\pandoc.exe -s --template data\templates\default.html -S README -o README.html
15if %errorlevel% neq 0 exit /b %errorlevel%
14if %errorlevel% neq 0 exit /b %errorlevel%
16cabal-dev\bin\pandoc.exe -s --template data\templates\default.rtf COPYING -t rtf -S -o COPYING.rtf
15cabal-dev\bin\pandoc.exe -s --template data\templates\default.rtf COPYING -t rtf -S -o COPYING.rtf
windows/pandoc.wxs−2
@@ -57,8 +57,6 @@
57 Name="Version" Type="string" Value="[ProductVersion]" KeyPath="yes"/>
57 Name="Version" Type="string" Value="[ProductVersion]" KeyPath="yes"/>
58 <File Id="pandoc_citeprocEXE" Name="pandoc-citeproc.exe"
58 <File Id="pandoc_citeprocEXE" Name="pandoc-citeproc.exe"
59 Source="..\cabal-dev\bin\pandoc-citeproc.exe" />
59 Source="..\cabal-dev\bin\pandoc-citeproc.exe" />
60− <File Id="biblio2yamlEXE" Name="biblio2yaml.exe"
61− Source="..\cabal-dev\bin\biblio2yaml.exe" />
62 </Component>
60 </Component>
63
61
64 <Component Id="UpdatePathUser"
62 <Component Id="UpdatePathUser"