diff options
59 files changed, 852 insertions, 414 deletions
diff --git a/.travis.yml b/.travis.yml index 30395b8b2..37ea4fbb3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,9 +28,6 @@ matrix: include: # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See: # https://github.com/hvr/multi-ghc-travis - - env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 - compiler: ": #GHC 7.6.3" - addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}} - env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 compiler: ": #GHC 7.8.4" addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31d786214..97976fa09 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -132,7 +132,7 @@ Please follow these guidelines: 9. It is better not to introduce new dependencies. Dependencies on external C libraries should especially be avoided. -10. We aim for compatibility with ghc versions from 7.4.2 to the +10. We aim for compatibility with ghc versions from 7.8.3 to the latest release. All pull requests and commits are tested automatically on travis-ci.org, using GHC versions in the `Tested-With` stanza of `pandoc.cabal`. We currently relax @@ -8,6 +8,9 @@ There are also binary installers for Windows and Mac OS X. If you are installing the development version from github, see also: https://github.com/jgm/pandoc/wiki/Installing-the-development-version-of-pandoc +Please note that pandoc only supports [GHC] versions 7.8 and +above. The easiest way to get GHC is by installing the [Haskell platform] + How to get the source --------------------- diff --git a/MANUAL.txt b/MANUAL.txt index 96d136d19..784cd415b 100644 --- a/MANUAL.txt +++ b/MANUAL.txt @@ -1,6 +1,6 @@ % Pandoc User's Guide % John MacFarlane -% July 17, 2016 +% September 26, 2016 Synopsis ======== @@ -421,12 +421,23 @@ Reader options exports `toJSONFilter` to facilitate writing filters in Haskell. Those who would prefer to write filters in python can use the module [`pandocfilters`], installable from PyPI. There are also - pandoc filter libraries in [PHP], [perl], and [javascript/node.js]. + pandoc filter libraries in [PHP], [perl], and + [javascript/node.js]. - Note that the *EXECUTABLE* will be sought in the user's - `PATH`, and not in the working directory, if no directory is - provided. If you want to run a script in the working directory, - preface the filename with `./`. + If no directory is provided pandoc will look for executable or + non-executable filters in the director `$DATADIR/filters`, and + then for executable filters in the user's `PATH`. If you want to + run a script in the working directory, preface the filename with + `./`. + + In order of preference, pandoc will look for filters in + + 1. a specified full or relative path (executable or + non-executable) + + 2. `$DATADIR/filters` (executable or non-executable) + + 3. `$PATH` (executable only) `-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*] @@ -2462,10 +2473,8 @@ when the field contains blank lines: --- title: 'This is the title: it contains a colon' author: - - name: Author One - affiliation: University of Somewhere - - name: Author Two - affiliation: University of Nowhere + - Author One + - Author Two tags: [nothing, nothingness] abstract: | This is the abstract. @@ -2480,9 +2489,23 @@ equivalent of the Markdown in the `abstract` field: <p>This is the abstract.</p> <p>It consists of two paragraphs.</p> -Note: The `author` variable in the default templates expects a simple list or -string. To use the structured authors in the example, you would need a -custom template. For example: +Variables can contain arbitrary YAML structures, but the template must match +this structure. The `author` variable in the default templates expects a +simple list or string, but can be changed to support more complicated +structures. The following combination, for example, would add an affiliation +to the author if one is given: + + --- + title: The document title + author: + - name: Author One + affiliation: University of Somewhere + - name: Author Two + affiliation: University of Nowhere + ... + +To use the structured authors in the example above, you would need a custom +template: $for(author)$ $if(author.name)$ @@ -3854,7 +3877,7 @@ style `Emphatically`. Similarly, | A Bird came down the Walk--- | He did not know I saw--- </div> - + would style the two contained lines with the `Poetry` paragraph style. If the styles are not yet in your reference.docx, they will be defined @@ -1,3 +1,235 @@ +pandoc (1.17.3) + + * Textile reader: + + + Support `bc..` extended code blocks (#3037). Also, remove trailing + newline in code blocks (consistently with Markdown reader). + + Improve table parsing. We now handle cell and row attributes, mostly + by skipping them. However, alignments are now handled properly. + Since in pandoc alignment is per-column, not per-cell, we + try to devine column alignments from cell alignments. + Table captions are also now parsed, and textile indicators + for thead and tfoot no longer cause parse failure. (However, + a row designated as tfoot will just be a regular row in pandoc.) + + Improve definition list parsing. We now allow multiple terms + (which we concatenate with linebreaks). An exponential parsing + bug (#3020) is also fixed. + + Disallow empty URL in explicit link (#3036). + + * RST reader: + + + Use Div instead of BlockQuote for admonitions (#3031). + The Div has class `admonition` and (if relevant) one of the + following: `attention`, `caution`, `danger`, `error`, `hint`, + `important`, `note`, `tip`, `warning`. **Note:** This will change + the rendering of some RST documents! The word ("Warning", "Attention", + etc.) is no longer added; that must be done with CSS or a filter. + + A Div is now used for `sidebar` as well. + + * LaTeX reader: + + + More robust parsing of unknown environments (#3026). + We no longer fail on things like `^` inside options for tikz. + + Be more forgiving of non-standard characters, e.g. `^` outside of math. + Some custom environments give these a meaning, so we should try not to + fall over when we encounter them. + + Drop duplicate `*` in bibtexKeyChars (Albert Krewinkel) + + * MediaWiki reader: + + + Fix for unquoted attribute values in mediawiki tables (#3053). + Previously an unquoted attribute value in a table row + could cause parsing problems. + + Improved treatment of verbatim constructions (#3055). + Previously these yielded strings of alternating Code and Space + elements; we now incorporate the spaces into the Code. Emphasis + etc. is still possible inside these. + + Properly interpret XML tags in pre environments (#3042). They are meant + to be interpreted as literal text. + + * Org reader (Albert Krewinkel): + + + Preserve indentation of verse lines (#3064). Leading spaces in verse + lines are converted to non-breaking spaces, so indentation is preserved. + + Ensure image sources are proper links. Image sources as those in plain + images, image links, or figures, must be proper URIs or relative file + paths to be recognized as images. This restriction is now enforced + for all image sources. This also fixes the reader's usage of uncleaned + image sources, leading to `file:` prefixes not being deleted from figure + images. Thanks to @bsag for noticing this bug. + + Extract meta parsing code to module. Parsing of meta-data is well + separable from other block parsing tasks. Moving into new module to get + small files and clearly arranged code. + + Read markup only for special meta keys. Most meta-keys should be read + as normal string values, only a few are interpreted as marked-up text. + + Allow multiple, comma-separated authors. Multiple authors can be specified + in the `#+AUTHOR` meta line if they are given as a comma-separated list. + + Give precedence to later meta lines. The last meta-line of any given type + is the significant line. Previously the value of the first line was kept, + even if more lines of the same type were encounterd. + + Read LaTeX_header as header-includes. LaTeX-specific header commands + can be defined in `#+LaTeX_header` lines. They are parsed as + format-specific inlines to ensure that they will only show up in LaTeX + output. + + Set documentclass meta from LaTeX_class. + + Set classoption meta from LaTeX_class_options. + + Read HTML_head as header-includes. HTML-specific head content can be + defined in `#+HTML_head` lines. They are parsed as format-specific + inlines to ensure that they will only show up in HTML output. + + Respect `author` export option. The `author` option controls whether the + author should be included in the final markup. Setting + `#+OPTIONS: author:nil` will drop the author from the final meta-data + output. + + Respect `email` export option. The `email` option controls whether the + email meta-field should be included in the final markup. Setting + `#+OPTIONS: email:nil` will drop the email field from the final meta-data + output. + + Respect `creator` export option. The `creator` option controls whether + the creator meta-field should be included in the final markup. Setting + `#+OPTIONS: creator:nil` will drop the creator field from the final + meta-data output. Org-mode recognizes the special value `comment` for + this field, causing the creator to be included in a comment. This is + difficult to translate to Pandoc internals and is hence interpreted the + same as other truish values (i.e. the meta field is kept if it's present). + + Respect unnumbered header property (#3095). Sections the `unnumbered` + property should, as the name implies, be excluded from the automatic + numbering of section provided by some output formats. The Pandoc + convention for this is to add an "unnumbered" class to the header. The + reader treats properties as key-value pairs per default, so a special + case is added to translate the above property to a class instead. + + * Docx reader: + + + Use XML convenience functions (Jesse Rosenthal). + The functions `isElem` and `elemName` (defined in Docx/Util.hs) make the + code a lot cleaner than the original XML.Light functions, but they had + been used inconsistently. This puts them in wherever applicable. + + Handle anchor spans with content in headers. Previously, we would only + be able to figure out internal links to a header in a docx if the anchor + span was empty. We change that to read the inlines out of the first + anchor span in a header. + + Let headers use exisiting id. Previously we always generated an id for + headers (since they wouldn't bring one from Docx). Now we let it use an + existing one if possible. This should allow us to recurs through anchor + spans. + + Use all anchor spans for header ids. Previously we only used the first + anchor span to affect header ids. This allows us to use all the anchor + spans in a header, whether they're nested or not (#3088). + + Test for nested anchor spans in header. This ensures that anchor spans + in header with content (or with other anchor spans inside) will resolve + to links to a header id properly. + + * DocBook writer: + + + Include an anchor element when a div or span has an id (#3102). + Note that DocBook does not have a class attribute, but at least this + provides an anchor for internal links. + + * LaTeX writer: + + + Don't use * for unnumbered paragraph, subparagraph. The starred variants + don't exist. This helps with part of #3058...it gets rid of the spurious + `*`s. But we still have numbers on the 4th and 5th level headers. + + Properly escape backticks in verbatim (#3121, Jesse Rosenthal). + Otherwise they can cause unintended ligatures like `` ?` ``. + + Handle NARRAOW NO-BREAK SPACE into LaTeX (Vaclav Zeman) as `\,`. + + * Text.Pandoc.Error: Fix out of index error in `handleError` + (Matthew Pickering). The fix is to not try to show the exact line when it + would cause an out-of-bounds error as a result of included files. + + * Man writer: + + + Allow section numbers that are not a single digit (#3089). + + * Docx Writer: + + + Implement user-defined styles (Jesse Rosenthal). Divs and Spans + with a `custom-style` key in the attributes will apply the corresponding + key to the contained blocks or inlines. + + * Org writer (Albert Krewinkel): + + + Remove blank line after figure caption. Org-mode only treats an image + as a figure if it is directly preceded by a caption. + + Ensure blank line after figure. An Org-mode figure should be surrounded + by blank lines. The figure would be recognized regardless, but images + in the following line would unintentionally be treated as figures as + well. + + Ensure link targets are paths or URLs. Org-mode treats links as + document internal searches unless the link target looks like a URL or + file path, either relative or absolute. This change ensures that this + is always the case. + + Translate language identifiers. Pandoc and Org-mode use different + programming language identifiers. An additional translation between + those identifiers is added to avoid unexpected behavior. This fixes a + problem where language specific source code would sometimes be output + as example code. + + * HTML, EPUB, slidy, revealjs templates: Use `<p>` instead of `<h1>` for + subtitle, author, date (#3119). Note that, as a result of this change, + authors may need to update CSS. + + * Beamer template: + + + Restore whitespace between paragraphs. This was + a regression in the last release (jgm/pandoc-templates#207). + + Added `themeoptions` variable (Carsten Gips). + + Added `beamerarticle` variable. This causes the `beamerarticle` + package to be loaded in beamer, to produce an article from beamer slides. + (Carsten Gips) + + Added support for `fontfamilies` structured variable + (Artem Klevtsov). + + * LaTeX template: Added dummy definition for `\institute`. + This isn't a standard command, and we want to avoid a crash when + `institute` is used with the default template. + + * Text.Pandoc.PDF: Don't crash with nonexistent image (#3100). Instead, + emit the alt text, emphasized. This accords with what the ODT writer + currently does. The user will still get a warning about a nonexistent + image. + + * Tell where to get tarball in INSTALL (#3062). + + * Rename README to MANUAL.txt and add GitHub-friendly README.md + (Albert Krewinkel). + + * MANUAL.txt: + + + Put note on structured vars in separate paragraph (#2148, Albert + Krewinkel). Make it clearer that structured author variables require a + custom template + + Note that `--katex` works best with `html5` (#3077). + + Fix the LaTeX and EPUB links in manual (Morton Fox). + + * Improve spacing of footnotes in `--help` output (Waldir Pimenta). + + * Allow aeson 1.0.*. + + * Use texmath 0.8.6.5 (#3040). + + * Remove support for GHC < 7.8 (Jesse Rosenthal). + + + Remove Compat.Monoid. + + Remove an inline monad compatibility macro. + + Remove Text.Pandoc.Compat.Except. + + Remove directory compat. + + Change constraint on mtl. + + Remove unnecessary CPP condition in UTF8. + + Bump base lower bound to 4.7. + + Remove 7.6 build from .travis.yaml. + + Bump supported ghc version in CONTRIBUTING.md. + + Add note about GHC version support to INSTALL. + + Remove GHC 7.6 from list of tested versions (Albert Krewinkel). + + Remove TagSoup compat. + + Add EOL note to time compat module. Because time 1.4 is a boot library + for GHC 7.8, we will support the compatibility module as long as we + support 7.8. But we should be clear about when we will no longer need it. + + Remove blaze-html CPP conditional. + + Remove http-client CPP conditionals. + + Remove unnecessary CPP in custom Prelude. + pandoc (1.17.2) * Added Zim Wiki writer, template and tests. `zimwiki` is now diff --git a/data/templates b/data/templates -Subproject 284279f61e493bf70a8375eb772d293b9fb5d6b +Subproject 8db1c3600174521698e22ec7eacc60c8963f55a diff --git a/deb/stack.yaml b/deb/stack.yaml index eee7f0035..315162ab9 100644 --- a/deb/stack.yaml +++ b/deb/stack.yaml @@ -14,11 +14,7 @@ flags: packages: - '..' extra-deps: -- data-default-0.6.0 -- pandoc-citeproc-0.10.1 +- pandoc-citeproc-0.10.1.1 - http-client-0.5.0 - http-client-tls-0.3.0 -- 'cmark-0.5.3.1' -- 'aeson-pretty-0.8.1' -- 'texmath-0.8.6.5' -resolver: lts-6.5 +resolver: lts-7.0 diff --git a/man/pandoc.1 b/man/pandoc.1 index 41375973b..81531e2b1 100644 --- a/man/pandoc.1 +++ b/man/pandoc.1 @@ -1,5 +1,5 @@ .\"t -.TH PANDOC 1 "June 4, 2016" "pandoc 1.17.2" +.TH PANDOC 1 "September 26, 2016" "pandoc 1.17.3" .SH NAME pandoc - general markup converter .SH SYNOPSIS @@ -1103,6 +1103,7 @@ Use KaTeX to display embedded TeX math in HTML output. The \f[I]URL\f[] should point to the \f[C]katex.js\f[] load script. If a \f[I]URL\f[] is not provided, a link to the KaTeX CDN will be inserted. +Note: KaTeX seems to work best with \f[C]html5\f[] output. .RS .RE .TP @@ -1353,6 +1354,11 @@ themes for LaTeX \f[C]beamer\f[] documents .RS .RE .TP +.B \f[C]themeoptions\f[] +options for LaTeX beamer themes (a list). +.RS +.RE +.TP .B \f[C]navigation\f[] controls navigation symbols in \f[C]beamer\f[] documents (default is \f[C]empty\f[] for no navigation symbols; other valid values are @@ -1365,6 +1371,12 @@ enables on "title pages" for new sections in \f[C]beamer\f[] documents (default = true). .RS .RE +.TP +.B \f[C]beamerarticle\f[] +when true, the \f[C]beamerarticle\f[] package is loaded (for producing +an article from beamer slides). +.RS +.RE .SS Variables for LaTeX .PP LaTeX variables are used when creating a PDF. @@ -3039,10 +3051,8 @@ This form is necessary when the field contains blank lines: \-\-\- title:\ \ \[aq]This\ is\ the\ title:\ it\ contains\ a\ colon\[aq] author: -\-\ name:\ Author\ One -\ \ affiliation:\ University\ of\ Somewhere -\-\ name:\ Author\ Two -\ \ affiliation:\ University\ of\ Nowhere +\-\ Author\ One +\-\ Author\ Two tags:\ [nothing,\ nothingness] abstract:\ | \ \ This\ is\ the\ abstract. @@ -3064,11 +3074,29 @@ field: \f[] .fi .PP -Note: The \f[C]author\f[] variable in the default templates expects a -simple list or string. -To use the structured authors in the example, you would need a custom -template. -For example: +Variables can contain arbitrary YAML structures, but the template must +match this structure. +The \f[C]author\f[] variable in the default templates expects a simple +list or string, but can be changed to support more complicated +structures. +The following combination, for example, would add an affiliation to the +author if one is given: +.IP +.nf +\f[C] +\-\-\- +title:\ The\ document\ title +author: +\-\ name:\ Author\ One +\ \ affiliation:\ University\ of\ Somewhere +\-\ name:\ Author\ Two +\ \ affiliation:\ University\ of\ Nowhere +\&... +\f[] +.fi +.PP +To use the structured authors in the example above, you would need a +custom template: .IP .nf \f[C] @@ -4772,6 +4800,58 @@ To see a list of language names that pandoc will recognize, type \f[C]pandoc\ \-\-version\f[]. .PP To disable highlighting, use the \f[C]\-\-no\-highlight\f[] option. +.SH CUSTOM STYLES IN DOCX OUTPUT +.PP +By default, pandoc\[aq]s docx output applies a predefined set of styles +for blocks such as paragraphs and block quotes, and uses largely default +formatting (italics, bold) for inlines. +This will work for most purposes, especially alongside a +\f[C]reference.docx\f[] file. +However, if you need to apply your own styles to blocks, or match a +preexisting set of styles, pandoc allows you to define custom styles for +blocks and text using \f[C]div\f[]s and \f[C]span\f[]s, respecitively. +.PP +If you define a \f[C]div\f[] or \f[C]span\f[] with the attribute +\f[C]custom\-style\f[], pandoc will apply your specified style to the +contained elements. +So, for example, +.IP +.nf +\f[C] +<span\ custom\-style="Emphatically">Get\ out,</span>\ he\ said. +\f[] +.fi +.PP +would produce a docx file with "Get out," styled with character style +\f[C]Emphatically\f[]. +Similarly, +.IP +.nf +\f[C] +Dickinson\ starts\ the\ poem\ simply: + +<div\ custom\-style="Poetry"> +|\ A\ Bird\ came\ down\ the\ Walk\-\-\- +|\ He\ did\ not\ know\ I\ saw\-\-\- +</div> +\f[] +.fi +.PP +would style the two contained lines with the \f[C]Poetry\f[] paragraph +style. +.PP +If the styles are not yet in your reference.docx, they will be defined +in the output file as inheriting from normal text. +If they are already defined, pandoc will not alter the definition. +.PP +This feature allows for greatest customization in conjunction with +pandoc filters. +If you want all paragraphs after block quotes to be indented, you can +write a filter to apply the styles necessary. +If you want all italics to be transformed to the \f[C]Emphasis\f[] +character style (perhaps to change their color), you can write a filter +which will transform all italicized inlines to inlines within an +\f[C]Emphasis\f[] custom\-style \f[C]span\f[]. .SH CUSTOM WRITERS .PP Pandoc can be extended with custom writers written in lua. diff --git a/osx/stack.yaml b/osx/stack.yaml index 7ae23e90b..61bd06f73 100644 --- a/osx/stack.yaml +++ b/osx/stack.yaml @@ -17,11 +17,7 @@ ghc-options: packages: - '..' extra-deps: -- 'pandoc-citeproc-0.10.1' +- pandoc-citeproc-0.10.1.1 - 'http-client-0.5.0' - 'http-client-tls-0.3.0' -- 'data-default-instances-base-0.1.0.1' -- 'cmark-0.5.3.1' -- 'aeson-pretty-0.8.1' -- 'texmath-0.8.6.5' -resolver: nightly-2016-07-11 +resolver: lts-7.0 diff --git a/pandoc.cabal b/pandoc.cabal index 1db7ded0b..e8d34e73d 100644 --- a/pandoc.cabal +++ b/pandoc.cabal @@ -1,5 +1,5 @@ Name: pandoc -Version: 1.17.2 +Version: 1.17.3 Cabal-Version: >= 1.10 Build-Type: Custom License: GPL @@ -11,7 +11,7 @@ Bug-Reports: https://github.com/jgm/pandoc/issues Stability: alpha Homepage: http://pandoc.org Category: Text -Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1 +Tested-With: GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1 Synopsis: Conversion between markup formats Description: Pandoc is a Haskell library for converting from one markup format to another, and a command-line tool that uses @@ -249,13 +249,13 @@ Flag old-locale Default: False Library - Build-Depends: base >= 4.2 && <5, + Build-Depends: base >= 4.7 && <5, syb >= 0.1 && < 0.7, containers >= 0.1 && < 0.6, unordered-containers >= 0.2 && < 0.3, array >= 0.3 && < 0.6, parsec >= 3.1 && < 3.2, - mtl >= 1.1 && < 2.3, + mtl >= 2.2 && < 2.3, filepath >= 1.1 && < 1.5, process >= 1 && < 1.5, directory >= 1 && < 1.3, @@ -401,6 +401,7 @@ Library Text.Pandoc.Readers.Org.Blocks, Text.Pandoc.Readers.Org.ExportSettings, Text.Pandoc.Readers.Org.Inlines, + Text.Pandoc.Readers.Org.Meta, Text.Pandoc.Readers.Org.ParserState, Text.Pandoc.Readers.Org.Parsing, Text.Pandoc.Readers.Org.Shared, @@ -414,10 +415,6 @@ Library Text.Pandoc.Slides, Text.Pandoc.Highlighting, Text.Pandoc.Compat.Time, - Text.Pandoc.Compat.Except, - Text.Pandoc.Compat.TagSoupEntity, - Text.Pandoc.Compat.Directory, - Text.Pandoc.Compat.Monoid, Paths_pandoc Buildable: True @@ -426,7 +423,7 @@ Executable pandoc Build-Depends: pandoc, pandoc-types >= 1.16 && < 1.17, base >= 4.2 && <5, - directory >= 1 && < 1.3, + directory >= 1.2 && < 1.3, filepath >= 1.1 && < 1.5, text >= 0.11 && < 1.3, bytestring >= 0.9 && < 0.11, @@ -1,4 +1,4 @@ -{-# LANGUAGE CPP, TupleSections, ScopedTypeVariables #-} +{-# LANGUAGE CPP, TupleSections, ScopedTypeVariables, PatternGuards #-} {- Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu> @@ -1042,9 +1042,24 @@ adjustMetadata metadata d = return $ M.foldWithKey setMeta d metadata applyTransforms :: [Transform] -> Pandoc -> IO Pandoc applyTransforms transforms d = return $ foldr ($) d transforms -applyFilters :: [FilePath] -> [String] -> Pandoc -> IO Pandoc -applyFilters filters args d = - foldrM ($) d $ map (flip externalFilter args) filters + -- First we check to see if a filter is a path. If it isn't, we + -- check to see whether it's in `userdir/filters`. If not, we leave + -- it unchanged. +expandFilterPath :: Maybe FilePath -> FilePath -> IO FilePath +expandFilterPath mbDatadir fp + | '/' `elem` fp = return fp + | Just datadir <- mbDatadir = do + let filterPath = (datadir </> "filters" </> fp) + filterPathExists <- doesFileExist filterPath + if filterPathExists + then return filterPath + else return fp + | otherwise = return fp + +applyFilters :: Maybe FilePath -> [FilePath] -> [String] -> Pandoc -> IO Pandoc +applyFilters mbDatadir filters args d = do + expandedFilters <- mapM (expandFilterPath mbDatadir) filters + foldrM ($) d $ map (flip externalFilter args) expandedFilters uppercaseFirstLetter :: String -> String uppercaseFirstLetter (c:cs) = toUpper c : cs @@ -1377,7 +1392,7 @@ convertWithOpts opts args = do doc' <- (maybe return (extractMedia media) mbExtractMedia >=> adjustMetadata metadata >=> applyTransforms transforms >=> - applyFilters filters' [format]) doc + applyFilters datadir filters' [format]) doc let writeBinary :: B.ByteString -> IO () writeBinary = B.writeFile (UTF8.encodePath outputFile) diff --git a/prelude/Prelude.hs b/prelude/Prelude.hs index 50e86a7b9..34f133d83 100644 --- a/prelude/Prelude.hs +++ b/prelude/Prelude.hs @@ -19,12 +19,8 @@ where #if MIN_VERSION_base(4,8,0) import "base" Prelude as P -#elif MIN_VERSION_base(4,6,0) -import "base" Prelude as P -import Control.Applicative -import Data.Monoid #else -import "base" Prelude as P hiding (catch) +import "base" Prelude as P import Control.Applicative import Data.Monoid #endif diff --git a/src/Text/Pandoc/Compat/Directory.hs b/src/Text/Pandoc/Compat/Directory.hs deleted file mode 100644 index 61dd5c525..000000000 --- a/src/Text/Pandoc/Compat/Directory.hs +++ /dev/null @@ -1,21 +0,0 @@ -{-# LANGUAGE CPP #-} -module Text.Pandoc.Compat.Directory ( getModificationTime ) - where - -#if MIN_VERSION_directory(1,2,0) -import System.Directory - - -#else -import qualified System.Directory as S -import Data.Time.Clock (UTCTime) -import Data.Time.Clock.POSIX -import System.Time - -getModificationTime :: FilePath -> IO UTCTime -getModificationTime fp = convert `fmap` S.getModificationTime fp - where - convert (TOD x _) = posixSecondsToUTCTime (realToFrac x) - -#endif - diff --git a/src/Text/Pandoc/Compat/Except.hs b/src/Text/Pandoc/Compat/Except.hs deleted file mode 100644 index 9ce7c0d36..000000000 --- a/src/Text/Pandoc/Compat/Except.hs +++ /dev/null @@ -1,37 +0,0 @@ -{-# LANGUAGE CPP #-} -module Text.Pandoc.Compat.Except ( ExceptT - , Except - , Error(..) - , runExceptT - , runExcept - , MonadError - , throwError - , catchError ) - where - -#if MIN_VERSION_mtl(2,2,1) -import Control.Monad.Except - -class Error a where - noMsg :: a - strMsg :: String -> a - - noMsg = strMsg "" - strMsg _ = noMsg - -#else -import Control.Monad.Error -import Control.Monad.Identity (Identity, runIdentity) - -type ExceptT = ErrorT - -type Except s a = ErrorT s Identity a - -runExceptT :: ExceptT e m a -> m (Either e a) -runExceptT = runErrorT - -runExcept :: ExceptT e Identity a -> Either e a -runExcept = runIdentity . runExceptT -#endif - - diff --git a/src/Text/Pandoc/Compat/Monoid.hs b/src/Text/Pandoc/Compat/Monoid.hs deleted file mode 100644 index 4daceb8e1..000000000 --- a/src/Text/Pandoc/Compat/Monoid.hs +++ /dev/null @@ -1,17 +0,0 @@ -{-# LANGUAGE CPP #-} -module Text.Pandoc.Compat.Monoid ( (<>) ) - where - -#if MIN_VERSION_base(4,5,0) -import Data.Monoid ((<>)) - -#else -import Data.Monoid - -infixr 6 <> - ---- | An infix synonym for 'mappend'. -(<>) :: Monoid m => m -> m -> m -(<>) = mappend -{-# INLINE (<>) #-} -#endif diff --git a/src/Text/Pandoc/Compat/TagSoupEntity.hs b/src/Text/Pandoc/Compat/TagSoupEntity.hs deleted file mode 100644 index 80985aef9..000000000 --- a/src/Text/Pandoc/Compat/TagSoupEntity.hs +++ /dev/null @@ -1,15 +0,0 @@ -{-# LANGUAGE CPP #-} -module Text.Pandoc.Compat.TagSoupEntity (lookupEntity - ) where - -import qualified Text.HTML.TagSoup.Entity as TE - -lookupEntity :: String -> Maybe Char -#if MIN_VERSION_tagsoup(0,13,0) -lookupEntity = str2chr . TE.lookupEntity - where str2chr :: Maybe String -> Maybe Char - str2chr (Just [c]) = Just c - str2chr _ = Nothing -#else -lookupEntity = TE.lookupEntity -#endif diff --git a/src/Text/Pandoc/Compat/Time.hs b/src/Text/Pandoc/Compat/Time.hs index aa08ca224..b1cde82a4 100644 --- a/src/Text/Pandoc/Compat/Time.hs +++ b/src/Text/Pandoc/Compat/Time.hs @@ -1,4 +1,16 @@ {-# LANGUAGE CPP #-} + +{- +This compatibility module is needed because, in time 1.5, the +`defaultTimeLocale` function was moved from System.Locale (in the +old-locale library) into Data.Time. + +We support both behaviors because time 1.4 is a boot library for GHC +7.8. time 1.5 is a boot library for GHC 7.10. + +When support is dropped for GHC 7.8, this module may be obsoleted. +-} + #if MIN_VERSION_time(1,5,0) module Text.Pandoc.Compat.Time ( module Data.Time diff --git a/src/Text/Pandoc/Error.hs b/src/Text/Pandoc/Error.hs index 292396aee..5e26771fe 100644 --- a/src/Text/Pandoc/Error.hs +++ b/src/Text/Pandoc/Error.hs @@ -33,7 +33,6 @@ module Text.Pandoc.Error (PandocError(..), handleError) where import Text.Parsec.Error import Text.Parsec.Pos hiding (Line) -import Text.Pandoc.Compat.Except import GHC.Generics (Generic) import Data.Generics (Typeable) import Control.Exception (Exception) @@ -48,10 +47,6 @@ data PandocError = -- | Generic parse failure instance Exception PandocError -instance Error PandocError where - strMsg = ParseFailure - - -- | An unsafe method to handle `PandocError`s. handleError :: Either PandocError a -> a handleError (Right r) = r diff --git a/src/Text/Pandoc/ImageSize.hs b/src/Text/Pandoc/ImageSize.hs index 90dfbb5fb..e46c91eda 100644 --- a/src/Text/Pandoc/ImageSize.hs +++ b/src/Text/Pandoc/ImageSize.hs @@ -59,8 +59,7 @@ import Numeric (showFFloat) import Text.Pandoc.Definition import Text.Pandoc.Options import qualified Data.Map as M -import Text.Pandoc.Compat.Except -import Control.Monad.Trans +import Control.Monad.Except import Data.Maybe (fromMaybe) -- quick and dirty functions to get image sizes diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs index 4dbe1f000..9faff1816 100644 --- a/src/Text/Pandoc/PDF.hs +++ b/src/Text/Pandoc/PDF.hs @@ -34,7 +34,7 @@ import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.Char8 as BC import qualified Data.ByteString as BS -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import System.Exit (ExitCode (..)) import System.FilePath import System.IO (stderr, stdout) @@ -131,7 +131,8 @@ handleImage' opts tmpdir (Image attr ils (src,tit)) = do return $ Image attr ils (fname,tit) _ -> do warn $ "Could not find image `" ++ src ++ "', skipping..." - return $ Image attr ils (src,tit) + -- return alt text + return $ Emph ils handleImage' _ _ x = return x convertImages :: FilePath -> Inline -> IO Inline diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs index f248b2514..e45e2247d 100644 --- a/src/Text/Pandoc/Parsing.hs +++ b/src/Text/Pandoc/Parsing.hs @@ -184,9 +184,9 @@ import Text.Pandoc.Shared import qualified Data.Map as M import Text.TeXMath.Readers.TeX.Macros (applyMacros, Macro, parseMacroDefinitions) -import Text.Pandoc.Compat.TagSoupEntity ( lookupEntity ) +import Text.HTML.TagSoup.Entity ( lookupEntity ) import Text.Pandoc.Asciify (toAsciiChar) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Data.Default import qualified Data.Set as Set import Control.Monad.Reader @@ -578,8 +578,8 @@ characterReference = try $ do '#':_ -> ent _ -> ent ++ ";" case lookupEntity ent' of - Just c -> return c - Nothing -> fail "entity not found" + Just (c : _) -> return c + _ -> fail "entity not found" -- | Parses an uppercase roman numeral and returns (UpperRoman, number). upperRoman :: Stream s m Char => ParserT s st m (ListNumberStyle, Int) diff --git a/src/Text/Pandoc/Pretty.hs b/src/Text/Pandoc/Pretty.hs index e830a1e78..0bac628af 100644 --- a/src/Text/Pandoc/Pretty.hs +++ b/src/Text/Pandoc/Pretty.hs @@ -80,7 +80,7 @@ import Data.List (intercalate) import Data.String import Control.Monad.State import Data.Char (isSpace) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) data RenderState a = RenderState{ output :: [a] -- ^ In reverse order @@ -126,18 +126,6 @@ isEmpty = null . toList . unDoc empty :: Doc empty = mempty -#if MIN_VERSION_base(4,5,0) --- (<>) is defined in Data.Monoid -#else -infixr 6 <> - --- | An infix synonym for 'mappend'. --- @a <> b@ is the result of concatenating @a@ with @b@. -(<>) :: Monoid m => m -> m -> m -(<>) = mappend -{-# INLINE (<>) #-} -#endif - -- | Concatenate a list of 'Doc's. cat :: [Doc] -> Doc cat = mconcat diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs index e8fe92e27..336b40933 100644 --- a/src/Text/Pandoc/Readers/DocBook.hs +++ b/src/Text/Pandoc/Readers/DocBook.hs @@ -5,7 +5,7 @@ import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Builder import Text.XML.Light -import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) +import Text.HTML.TagSoup.Entity (lookupEntity) import Data.Either (rights) import Data.Generics import Data.Char (isSpace) @@ -14,7 +14,7 @@ import Data.List (intersperse) import Data.Maybe (fromMaybe) import Text.TeXMath (readMathML, writeTeX) import Text.Pandoc.Error (PandocError) -import Text.Pandoc.Compat.Except +import Control.Monad.Except import Data.Default import Data.Foldable (asum) @@ -564,7 +564,7 @@ normalizeTree = everywhere (mkT go) go xs = xs convertEntity :: String -> String -convertEntity e = maybe (map toUpper e) (:[]) (lookupEntity e) +convertEntity e = maybe (map toUpper e) id (lookupEntity e) -- convenience function to get an attribute value, defaulting to "" attrValue :: String -> Element -> String @@ -916,7 +916,7 @@ elementToStr x = x parseInline :: Content -> DB Inlines parseInline (Text (CData _ s _)) = return $ text s parseInline (CRef ref) = - return $ maybe (text $ map toUpper ref) (text . (:[])) $ lookupEntity ref + return $ maybe (text $ map toUpper ref) (text) $ lookupEntity ref parseInline (Elem e) = case qName (elName e) of "equation" -> equation displayMath diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs index 2bc17c069..fa534f801 100644 --- a/src/Text/Pandoc/Readers/Docx.hs +++ b/src/Text/Pandoc/Readers/Docx.hs @@ -1,7 +1,7 @@ -{-# LANGUAGE PatternGuards, OverloadedStrings #-} +{-# LANGUAGE PatternGuards, OverloadedStrings, CPP #-} {- -Copyright (C) 2014 Jesse Rosenthal <jrosenthal@jhu.edu> +Copyright (C) 2014-2016 Jesse Rosenthal <jrosenthal@jhu.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA {- | Module : Text.Pandoc.Readers.Docx - Copyright : Copyright (C) 2014 Jesse Rosenthal + Copyright : Copyright (C) 2014-2016 Jesse Rosenthal License : GNU GPL, version 2 or above Maintainer : Jesse Rosenthal <jrosenthal@jhu.edu> @@ -83,7 +83,7 @@ import Text.Pandoc.Readers.Docx.Lists import Text.Pandoc.Readers.Docx.Combine import Text.Pandoc.Shared import Text.Pandoc.MediaBag (insertMedia, MediaBag) -import Data.List (delete, (\\), intersect) +import Data.List (delete, intersect) import Text.TeXMath (writeTeX) import Data.Default (Default) import qualified Data.ByteString.Lazy as B @@ -93,9 +93,12 @@ import Control.Monad.Reader import Control.Monad.State import Data.Sequence (ViewL(..), viewl) import qualified Data.Sequence as Seq (null) +#if !(MIN_VERSION_base(4,8,0)) +import Data.Traversable (traverse) +#endif import Text.Pandoc.Error -import Text.Pandoc.Compat.Except +import Control.Monad.Except readDocxWithWarnings :: ReaderOptions -> B.ByteString @@ -412,39 +415,39 @@ parPartToInlines (PlainOMath exps) = do return $ math $ writeTeX exps isAnchorSpan :: Inline -> Bool -isAnchorSpan (Span (_, classes, kvs) ils) = +isAnchorSpan (Span (_, classes, kvs) _) = classes == ["anchor"] && - null kvs && - null ils + null kvs isAnchorSpan _ = False dummyAnchors :: [String] dummyAnchors = ["_GoBack"] makeHeaderAnchor :: Blocks -> DocxContext Blocks -makeHeaderAnchor bs = case viewl $ unMany bs of - (x :< xs) -> do - x' <- (makeHeaderAnchor' x) - xs' <- (makeHeaderAnchor $ Many xs) - return $ (singleton x') <> xs' - EmptyL -> return mempty +makeHeaderAnchor bs = traverse makeHeaderAnchor' bs makeHeaderAnchor' :: Block -> DocxContext Block -- If there is an anchor already there (an anchor span in the header, -- to be exact), we rename and associate the new id with the old one. -makeHeaderAnchor' (Header n (_, classes, kvs) ils) - | (c:cs) <- filter isAnchorSpan ils - , (Span (ident, ["anchor"], _) _) <- c = do +makeHeaderAnchor' (Header n (ident, classes, kvs) ils) + | (c:_) <- filter isAnchorSpan ils + , (Span (anchIdent, ["anchor"], _) cIls) <- c = do hdrIDMap <- gets docxAnchorMap - let newIdent = uniqueIdent ils (Set.fromList $ M.elems hdrIDMap) - modify $ \s -> s {docxAnchorMap = M.insert ident newIdent hdrIDMap} - return $ Header n (newIdent, classes, kvs) (ils \\ (c:cs)) + let newIdent = if null ident + then uniqueIdent ils (Set.fromList $ M.elems hdrIDMap) + else ident + newIls = concatMap f ils where f il | il == c = cIls + | otherwise = [il] + modify $ \s -> s {docxAnchorMap = M.insert anchIdent newIdent hdrIDMap} + makeHeaderAnchor' $ Header n (newIdent, classes, kvs) newIls -- Otherwise we just give it a name, and register that name (associate -- it with itself.) -makeHeaderAnchor' (Header n (_, classes, kvs) ils) = +makeHeaderAnchor' (Header n (ident, classes, kvs) ils) = do hdrIDMap <- gets docxAnchorMap - let newIdent = uniqueIdent ils (Set.fromList $ M.elems hdrIDMap) + let newIdent = if null ident + then uniqueIdent ils (Set.fromList $ M.elems hdrIDMap) + else ident modify $ \s -> s {docxAnchorMap = M.insert newIdent newIdent hdrIDMap} return $ Header n (newIdent, classes, kvs) ils makeHeaderAnchor' blk = return blk diff --git a/src/Text/Pandoc/Readers/Docx/Lists.hs b/src/Text/Pandoc/Readers/Docx/Lists.hs index c265ad074..395a53907 100644 --- a/src/Text/Pandoc/Readers/Docx/Lists.hs +++ b/src/Text/Pandoc/Readers/Docx/Lists.hs @@ -1,5 +1,5 @@ {- -Copyright (C) 2014 Jesse Rosenthal <jrosenthal@jhu.edu> +Copyright (C) 2014-2016 Jesse Rosenthal <jrosenthal@jhu.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA {- | Module : Text.Pandoc.Readers.Docx.Lists - Copyright : Copyright (C) 2014 Jesse Rosenthal + Copyright : Copyright (C) 2014-2016 Jesse Rosenthal License : GNU GPL, version 2 or above Maintainer : Jesse Rosenthal <jrosenthal@jhu.edu> diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs index 9ae7f22ec..b9021ec08 100644 --- a/src/Text/Pandoc/Readers/Docx/Parse.hs +++ b/src/Text/Pandoc/Readers/Docx/Parse.hs @@ -1,7 +1,7 @@ {-# LANGUAGE PatternGuards, ViewPatterns, FlexibleInstances #-} {- -Copyright (C) 2014 Jesse Rosenthal <jrosenthal@jhu.edu> +Copyright (C) 2014-2016 Jesse Rosenthal <jrosenthal@jhu.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA {- | Module : Text.Pandoc.Readers.Docx.Parse - Copyright : Copyright (C) 2014 Jesse Rosenthal + Copyright : Copyright (C) 2014-2016 Jesse Rosenthal License : GNU GPL, version 2 or above Maintainer : Jesse Rosenthal <jrosenthal@jhu.edu> @@ -64,7 +64,7 @@ import Control.Monad.Reader import Control.Monad.State import Control.Applicative ((<|>)) import qualified Data.Map as M -import Text.Pandoc.Compat.Except +import Control.Monad.Except import Text.Pandoc.Shared (safeRead) import Text.TeXMath.Readers.OMML (readOMML) import Text.Pandoc.Readers.Docx.Fonts (getUnicode, Font(..)) @@ -91,9 +91,6 @@ data ReaderState = ReaderState { stateWarnings :: [String] } data DocxError = DocxError | WrongElem deriving Show -instance Error DocxError where - noMsg = WrongElem - type D = ExceptT DocxError (ReaderT ReaderEnv (State ReaderState)) runD :: D a -> ReaderEnv -> ReaderState -> (Either DocxError a, ReaderState) diff --git a/src/Text/Pandoc/Readers/EPUB.hs b/src/Text/Pandoc/Readers/EPUB.hs index b8a0b47e7..e547b84cd 100644 --- a/src/Text/Pandoc/Readers/EPUB.hs +++ b/src/Text/Pandoc/Readers/EPUB.hs @@ -16,8 +16,7 @@ import Text.Pandoc.Options ( ReaderOptions(..), readerTrace) import Text.Pandoc.Shared (escapeURI, collapseFilePath, addMetaField) import Network.URI (unEscapeString) import Text.Pandoc.MediaBag (MediaBag, insertMedia) -import Text.Pandoc.Compat.Except (MonadError, throwError, runExcept, Except) -import Text.Pandoc.Compat.Monoid ((<>)) +import Control.Monad.Except (MonadError, throwError, runExcept, Except) import Text.Pandoc.MIME (MimeType) import qualified Text.Pandoc.Builder as B import Codec.Archive.Zip ( Archive (..), toArchiveOrFail, fromEntry @@ -31,6 +30,7 @@ import Control.Monad (guard, liftM, when) import Data.List (isPrefixOf, isInfixOf) import Data.Maybe (mapMaybe, fromMaybe) import qualified Data.Map as M (Map, lookup, fromList, elems) +import Data.Monoid ((<>)) import Control.DeepSeq (deepseq, NFData) import Debug.Trace (trace) diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs index 164e3a98f..8ce3fa379 100644 --- a/src/Text/Pandoc/Readers/HTML.hs +++ b/src/Text/Pandoc/Readers/HTML.hs @@ -66,7 +66,7 @@ import Control.Monad.Reader (Reader,ask, asks, local, runReader) import Network.URI (URI, parseURIReference, nonStrictRelativeTo) import Text.Pandoc.Error import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Parsec.Error import qualified Data.Set as Set diff --git a/src/Text/Pandoc/Readers/Haddock.hs b/src/Text/Pandoc/Readers/Haddock.hs index 99deac3c2..12953bb72 100644 --- a/src/Text/Pandoc/Readers/Haddock.hs +++ b/src/Text/Pandoc/Readers/Haddock.hs @@ -16,7 +16,7 @@ module Text.Pandoc.Readers.Haddock import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.Shared (trim, splitBy) import Data.List (intersperse, stripPrefix) import Data.Maybe (fromMaybe) diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index e43714526..9928500dc 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -64,7 +64,7 @@ import Text.HTML.TagSoup import qualified Data.Set as Set import Text.Printf (printf) import Debug.Trace (trace) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.Error type MarkdownParser = Parser [Char] ParserState diff --git a/src/Text/Pandoc/Readers/MediaWiki.hs b/src/Text/Pandoc/Readers/MediaWiki.hs index dcf0c5f4a..c625b8905 100644 --- a/src/Text/Pandoc/Readers/MediaWiki.hs +++ b/src/Text/Pandoc/Readers/MediaWiki.hs @@ -39,7 +39,7 @@ module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Builder (Inlines, Blocks, trimInlines) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.Options import Text.Pandoc.Readers.HTML ( htmlTag, isBlockTag, isCommentTag ) import Text.Pandoc.XML ( fromEntities ) diff --git a/src/Text/Pandoc/Readers/OPML.hs b/src/Text/Pandoc/Readers/OPML.hs index b2e5f2e67..4dcf5e5a0 100644 --- a/src/Text/Pandoc/Readers/OPML.hs +++ b/src/Text/Pandoc/Readers/OPML.hs @@ -7,11 +7,11 @@ import Text.Pandoc.Builder import Text.Pandoc.Readers.HTML (readHtml) import Text.Pandoc.Readers.Markdown (readMarkdown) import Text.XML.Light -import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) +import Text.HTML.TagSoup.Entity (lookupEntity) import Data.Generics import Control.Monad.State import Data.Default -import Text.Pandoc.Compat.Except +import Control.Monad.Except import Text.Pandoc.Error type OPML = ExceptT PandocError (State OPMLState) @@ -53,7 +53,7 @@ normalizeTree = everywhere (mkT go) go xs = xs convertEntity :: String -> String -convertEntity e = maybe (map toUpper e) (:[]) (lookupEntity e) +convertEntity e = maybe (map toUpper e) id (lookupEntity e) -- convenience function to get an attribute value, defaulting to "" attrValue :: String -> Element -> String diff --git a/src/Text/Pandoc/Readers/Odt/Arrows/State.hs b/src/Text/Pandoc/Readers/Odt/Arrows/State.hs index 30f96c557..b056f1ecc 100644 --- a/src/Text/Pandoc/Readers/Odt/Arrows/State.hs +++ b/src/Text/Pandoc/Readers/Odt/Arrows/State.hs @@ -45,8 +45,8 @@ import Control.Arrow import Control.Monad import Data.Foldable +import Data.Monoid -import Text.Pandoc.Compat.Monoid import Text.Pandoc.Readers.Odt.Arrows.Utils import Text.Pandoc.Readers.Odt.Generic.Fallible diff --git a/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs b/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs index fca2575c2..218a85661 100644 --- a/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs +++ b/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs @@ -43,10 +43,10 @@ import Control.Arrow import Control.Monad ( join, MonadPlus(..) ) import qualified Data.Foldable as F +import Data.Monoid import Text.Pandoc.Readers.Odt.Generic.Fallible import Text.Pandoc.Readers.Odt.Generic.Utils -import Text.Pandoc.Compat.Monoid and2 :: (Arrow a) => a b c -> a b c' -> a b (c,c') and2 = (&&&) diff --git a/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs b/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs index d0fdc228f..877443543 100644 --- a/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs +++ b/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs @@ -41,8 +41,9 @@ module Text.Pandoc.Readers.Odt.Generic.Fallible where import Control.Applicative import Control.Monad -import Text.Pandoc.Compat.Monoid ((<>)) + import qualified Data.Foldable as F +import Data.Monoid ((<>)) -- | Default for now. Will probably become a class at some point. type Failure = () diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs index 6a8bb8b28..8961f73f1 100644 --- a/src/Text/Pandoc/Readers/Org/Blocks.hs +++ b/src/Text/Pandoc/Readers/Org/Blocks.hs @@ -34,8 +34,8 @@ module Text.Pandoc.Readers.Org.Blocks ) where import Text.Pandoc.Readers.Org.BlockStarts -import Text.Pandoc.Readers.Org.ExportSettings ( exportSettings ) import Text.Pandoc.Readers.Org.Inlines +import Text.Pandoc.Readers.Org.Meta ( metaExport, metaLine ) import Text.Pandoc.Readers.Org.ParserState import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Readers.Org.Shared @@ -45,16 +45,14 @@ import Text.Pandoc.Readers.Org.Shared import qualified Text.Pandoc.Builder as B import Text.Pandoc.Builder ( Inlines, Blocks ) import Text.Pandoc.Definition -import Text.Pandoc.Compat.Monoid ((<>)) import Text.Pandoc.Options import Text.Pandoc.Shared ( compactify', compactify'DL ) import Control.Monad ( foldM, guard, mzero, void ) import Data.Char ( isSpace, toLower, toUpper) import Data.List ( foldl', intersperse, isPrefixOf ) -import qualified Data.Map as M import Data.Maybe ( fromMaybe, isNothing ) -import Network.HTTP ( urlEncode ) +import Data.Monoid ((<>)) -- -- Org headers @@ -82,6 +80,10 @@ newtype PropertyValue = PropertyValue { fromValue :: String } toPropertyValue :: String -> PropertyValue toPropertyValue = PropertyValue +-- | Check whether the property value is non-nil (i.e. truish). +isNonNil :: PropertyValue -> Bool +isNonNil p = map toLower (fromValue p) `notElem` ["()", "{}", "nil"] + -- | Key/value pairs from a PROPERTIES drawer type Properties = [(PropertyKey, PropertyValue)] @@ -202,12 +204,16 @@ propertiesToAttr properties = toStringPair prop = (fromKey (fst prop), fromValue (snd prop)) customIdKey = toPropertyKey "custom_id" classKey = toPropertyKey "class" + unnumberedKey = toPropertyKey "unnumbered" + specialProperties = [customIdKey, classKey, unnumberedKey] id' = fromMaybe mempty . fmap fromValue . lookup customIdKey $ properties cls = fromMaybe mempty . fmap fromValue . lookup classKey $ properties - kvs' = map toStringPair . filter ((`notElem` [customIdKey, classKey]) . fst) + kvs' = map toStringPair . filter ((`notElem` specialProperties) . fst) $ properties + isUnnumbered = + fromMaybe False . fmap isNonNil . lookup unnumberedKey $ properties in - (id', words cls, kvs') + (id', words cls ++ (if isUnnumbered then ["unnumbered"] else []), kvs') tagTitle :: Inlines -> [Tag] -> Inlines tagTitle title tags = title <> (mconcat $ map tagToInline tags) @@ -232,8 +238,8 @@ blockList = do -- | Get the meta information safed in the state. meta :: OrgParser Meta meta = do - st <- getState - return $ runF (orgStateMeta st) st + meta' <- metaExport + runF meta' <$> getState blocks :: OrgParser (F Blocks) blocks = mconcat <$> manyTill block (void (lookAhead headerStart) <|> eof) @@ -631,67 +637,9 @@ exampleCode = B.codeBlockWith ("", ["example"], []) specialLine :: OrgParser (F Blocks) specialLine = fmap return . try $ metaLine <|> commentLine --- The order, in which blocks are tried, makes sure that we're not looking at --- the beginning of a block, so we don't need to check for it -metaLine :: OrgParser Blocks -metaLine = mempty <$ metaLineStart <* (optionLine <|> declarationLine) - commentLine :: OrgParser Blocks commentLine = commentLineStart *> anyLine *> pure mempty -declarationLine :: OrgParser () -declarationLine = try $ do - key <- metaKey - value <- metaInlines - updateState $ \st -> - let meta' = B.setMeta key <$> value <*> pure nullMeta - in st { orgStateMeta = orgStateMeta st <> meta' } - -metaInlines :: OrgParser (F MetaValue) -metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline - -metaKey :: OrgParser String -metaKey = map toLower <$> many1 (noneOf ": \n\r") - <* char ':' - <* skipSpaces - -optionLine :: OrgParser () -optionLine = try $ do - key <- metaKey - case key of - "link" -> parseLinkFormat >>= uncurry addLinkFormat - "options" -> exportSettings - _ -> mzero - -addLinkFormat :: String - -> (String -> String) - -> OrgParser () -addLinkFormat key formatter = updateState $ \s -> - let fs = orgStateLinkFormatters s - in s{ orgStateLinkFormatters = M.insert key formatter fs } - -parseLinkFormat :: OrgParser ((String, String -> String)) -parseLinkFormat = try $ do - linkType <- (:) <$> letter <*> many (alphaNum <|> oneOf "-_") <* skipSpaces - linkSubst <- parseFormat - return (linkType, linkSubst) - --- | An ad-hoc, single-argument-only implementation of a printf-style format --- parser. -parseFormat :: OrgParser (String -> String) -parseFormat = try $ do - replacePlain <|> replaceUrl <|> justAppend - where - -- inefficient, but who cares - replacePlain = try $ (\x -> concat . flip intersperse x) - <$> sequence [tillSpecifier 's', rest] - replaceUrl = try $ (\x -> concat . flip intersperse x . urlEncode) - <$> sequence [tillSpecifier 'h', rest] - justAppend = try $ (++) <$> rest - - rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r") - tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:"")) - -- -- Tables @@ -868,9 +816,6 @@ paraOrPlain = try $ do *> return (B.para <$> ils)) <|> (return (B.plain <$> ils)) -inlinesTillNewline :: OrgParser (F Inlines) -inlinesTillNewline = trimInlinesF . mconcat <$> manyTill inline newline - -- -- list blocks diff --git a/src/Text/Pandoc/Readers/Org/ExportSettings.hs b/src/Text/Pandoc/Readers/Org/ExportSettings.hs index b48acc9c4..283cfa998 100644 --- a/src/Text/Pandoc/Readers/Org/ExportSettings.hs +++ b/src/Text/Pandoc/Readers/Org/ExportSettings.hs @@ -54,13 +54,15 @@ exportSetting = choice , ignoredSetting "<" , ignoredSetting "\\n" , archivedTreeSetting "arch" (\val es -> es { exportArchivedTrees = val }) - , ignoredSetting "author" + , booleanSetting "author" (\val es -> es { exportWithAuthor = val }) , ignoredSetting "c" - , ignoredSetting "creator" + -- org-mode allows the special value `comment` for creator, which we'll + -- interpret as true as it doesn't make sense in the context of Pandoc. + , booleanSetting "creator" (\val es -> es { exportWithCreator = val }) , complementableListSetting "d" (\val es -> es { exportDrawers = val }) , ignoredSetting "date" , ignoredSetting "e" - , ignoredSetting "email" + , booleanSetting "email" (\val es -> es { exportWithEmail = val }) , ignoredSetting "f" , integerSetting "H" (\val es -> es { exportHeadlineLevels = val }) , ignoredSetting "inline" diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs index 31f098d27..14e77dda9 100644 --- a/src/Text/Pandoc/Readers/Org/Inlines.hs +++ b/src/Text/Pandoc/Readers/Org/Inlines.hs @@ -43,7 +43,6 @@ import Text.Pandoc.Readers.Org.Shared import qualified Text.Pandoc.Builder as B import Text.Pandoc.Builder ( Inlines ) import Text.Pandoc.Definition -import Text.Pandoc.Compat.Monoid ( (<>) ) import Text.Pandoc.Options import Text.Pandoc.Readers.LaTeX ( inlineCommand, rawLaTeXInline ) import Text.TeXMath ( readTeX, writePandoc, DisplayType(..) ) @@ -55,6 +54,7 @@ import Data.Char ( isAlphaNum, isSpace ) import Data.List ( intersperse ) import Data.Maybe ( fromMaybe ) import qualified Data.Map as M +import Data.Monoid ( (<>) ) import Data.Traversable (sequence) -- diff --git a/src/Text/Pandoc/Readers/Org/Meta.hs b/src/Text/Pandoc/Readers/Org/Meta.hs new file mode 100644 index 000000000..ea088bfdb --- /dev/null +++ b/src/Text/Pandoc/Readers/Org/Meta.hs @@ -0,0 +1,181 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE TupleSections #-} +{- +Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-} + +{- | + Module : Text.Pandoc.Readers.Org.Meta + Copyright : Copyright (C) 2014-2016 Albert Krewinkel + License : GNU GPL, version 2 or above + + Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> + +Parsers for Org-mode meta declarations. +-} +module Text.Pandoc.Readers.Org.Meta + ( metaLine + , metaExport + ) where + +import Text.Pandoc.Readers.Org.BlockStarts +import Text.Pandoc.Readers.Org.ExportSettings ( exportSettings ) +import Text.Pandoc.Readers.Org.Inlines +import Text.Pandoc.Readers.Org.ParserState +import Text.Pandoc.Readers.Org.Parsing + +import qualified Text.Pandoc.Builder as B +import Text.Pandoc.Builder ( Blocks, Inlines ) +import Text.Pandoc.Definition + +import Control.Monad ( mzero ) +import Data.Char ( toLower ) +import Data.List ( intersperse ) +import qualified Data.Map as M +import Data.Monoid ((<>)) +import Network.HTTP ( urlEncode ) + +-- | Returns the current meta, respecting export options. +metaExport :: OrgParser (F Meta) +metaExport = do + st <- getState + let settings = orgStateExportSettings st + return $ (if exportWithAuthor settings then id else removeMeta "author") + . (if exportWithCreator settings then id else removeMeta "creator") + . (if exportWithEmail settings then id else removeMeta "email") + <$> orgStateMeta st + +removeMeta :: String -> Meta -> Meta +removeMeta key meta' = + let metaMap = unMeta meta' + in Meta $ M.delete key metaMap + +-- | Parse and handle a single line containing meta information +-- The order, in which blocks are tried, makes sure that we're not looking at +-- the beginning of a block, so we don't need to check for it +metaLine :: OrgParser Blocks +metaLine = mempty <$ metaLineStart <* (optionLine <|> declarationLine) + +declarationLine :: OrgParser () +declarationLine = try $ do + key <- map toLower <$> metaKey + (key', value) <- metaValue key + updateState $ \st -> + let meta' = B.setMeta key' <$> value <*> pure nullMeta + in st { orgStateMeta = meta' <> orgStateMeta st } + +metaKey :: OrgParser String +metaKey = map toLower <$> many1 (noneOf ": \n\r") + <* char ':' + <* skipSpaces + +metaValue :: String -> OrgParser (String, (F MetaValue)) +metaValue key = + let inclKey = "header-includes" + in case key of + "author" -> (key,) <$> metaInlinesCommaSeparated + "title" -> (key,) <$> metaInlines + "date" -> (key,) <$> metaInlines + "header-includes" -> (key,) <$> accumulatingList key metaInlines + "latex_header" -> (inclKey,) <$> + accumulatingList inclKey (metaExportSnippet "latex") + "latex_class" -> ("documentclass",) <$> metaString + -- Org-mode expects class options to contain the surrounding brackets, + -- pandoc does not. + "latex_class_options" -> ("classoption",) <$> + metaModifiedString (filter (`notElem` "[]")) + "html_head" -> (inclKey,) <$> + accumulatingList inclKey (metaExportSnippet "html") + _ -> (key,) <$> metaString + +metaInlines :: OrgParser (F MetaValue) +metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline + +metaInlinesCommaSeparated :: OrgParser (F MetaValue) +metaInlinesCommaSeparated = do + authStrs <- (many1 (noneOf ",\n")) `sepBy1` (char ',') + newline + authors <- mapM (parseFromString inlinesTillNewline . (++ "\n")) authStrs + let toMetaInlines = MetaInlines . B.toList + return $ MetaList . map toMetaInlines <$> sequence authors + +metaString :: OrgParser (F MetaValue) +metaString = metaModifiedString id + +metaModifiedString :: (String -> String) -> OrgParser (F MetaValue) +metaModifiedString f = return . MetaString . f <$> anyLine + +-- | Read an format specific meta definition +metaExportSnippet :: String -> OrgParser (F MetaValue) +metaExportSnippet format = + return . MetaInlines . B.toList . B.rawInline format <$> anyLine + +-- | Accumulate the result of the @parser@ in a list under @key@. +accumulatingList :: String + -> OrgParser (F MetaValue) + -> OrgParser (F MetaValue) +accumulatingList key p = do + value <- p + meta' <- orgStateMeta <$> getState + return $ (\m v -> MetaList (curList m ++ [v])) <$> meta' <*> value + where curList m = case lookupMeta key m of + Just (MetaList ms) -> ms + Just x -> [x] + _ -> [] + +-- +-- export options +-- +optionLine :: OrgParser () +optionLine = try $ do + key <- metaKey + case key of + "link" -> parseLinkFormat >>= uncurry addLinkFormat + "options" -> exportSettings + _ -> mzero + +addLinkFormat :: String + -> (String -> String) + -> OrgParser () +addLinkFormat key formatter = updateState $ \s -> + let fs = orgStateLinkFormatters s + in s{ orgStateLinkFormatters = M.insert key formatter fs } + +parseLinkFormat :: OrgParser ((String, String -> String)) +parseLinkFormat = try $ do + linkType <- (:) <$> letter <*> many (alphaNum <|> oneOf "-_") <* skipSpaces + linkSubst <- parseFormat + return (linkType, linkSubst) + +-- | An ad-hoc, single-argument-only implementation of a printf-style format +-- parser. +parseFormat :: OrgParser (String -> String) +parseFormat = try $ do + replacePlain <|> replaceUrl <|> justAppend + where + -- inefficient, but who cares + replacePlain = try $ (\x -> concat . flip intersperse x) + <$> sequence [tillSpecifier 's', rest] + replaceUrl = try $ (\x -> concat . flip intersperse x . urlEncode) + <$> sequence [tillSpecifier 'h', rest] + justAppend = try $ (++) <$> rest + + rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r") + tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:"")) + +inlinesTillNewline :: OrgParser (F Inlines) +inlinesTillNewline = trimInlinesF . mconcat <$> manyTill inline newline diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs index 48e7717cd..84dbe9d33 100644 --- a/src/Text/Pandoc/Readers/Org/ParserState.hs +++ b/src/Text/Pandoc/Readers/Org/ParserState.hs @@ -163,6 +163,9 @@ data ExportSettings = ExportSettings , exportSmartQuotes :: Bool -- ^ Parse quotes smartly , exportSpecialStrings :: Bool -- ^ Parse ellipses and dashes smartly , exportSubSuperscripts :: Bool -- ^ TeX-like syntax for sub- and superscripts + , exportWithAuthor :: Bool -- ^ Include author in final meta-data + , exportWithCreator :: Bool -- ^ Include creator in final meta-data + , exportWithEmail :: Bool -- ^ Include email in final meta-data } instance Default ExportSettings where @@ -177,6 +180,9 @@ defaultExportSettings = ExportSettings , exportSmartQuotes = True , exportSpecialStrings = True , exportSubSuperscripts = True + , exportWithAuthor = True + , exportWithCreator = True + , exportWithEmail = True } diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs index 46f082ccd..f181d523a 100644 --- a/src/Text/Pandoc/Readers/RST.hs +++ b/src/Text/Pandoc/Readers/RST.hs @@ -48,7 +48,7 @@ import Text.Pandoc.Builder (Inlines, Blocks, trimInlines) import qualified Text.Pandoc.Builder as B import Data.Sequence (viewr, ViewR(..)) import Data.Char (toLower, isHexDigit, isSpace) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.Error -- | Parse reStructuredText string and return Pandoc document. diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs index a4de85dfb..8dbbf7be2 100644 --- a/src/Text/Pandoc/Readers/Textile.hs +++ b/src/Text/Pandoc/Readers/Textile.hs @@ -65,7 +65,7 @@ import Text.HTML.TagSoup.Match import Data.List ( intercalate, transpose, intersperse ) import Data.Char ( digitToInt, isUpper ) import Control.Monad ( guard, liftM, when ) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Printf import Debug.Trace (trace) import Text.Pandoc.Error diff --git a/src/Text/Pandoc/Readers/Txt2Tags.hs b/src/Text/Pandoc/Readers/Txt2Tags.hs index 277d747d6..0aafc83c7 100644 --- a/src/Text/Pandoc/Readers/Txt2Tags.hs +++ b/src/Text/Pandoc/Readers/Txt2Tags.hs @@ -34,7 +34,7 @@ module Text.Pandoc.Readers.Txt2Tags ( readTxt2Tags import qualified Text.Pandoc.Builder as B import Text.Pandoc.Builder ( Inlines, Blocks, trimInlines ) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared (escapeURI,compactify', compactify'DL) @@ -49,7 +49,7 @@ import Control.Monad.Reader (Reader, runReader, asks) import Text.Pandoc.Error import Data.Time.LocalTime (getZonedTime) -import Text.Pandoc.Compat.Directory(getModificationTime) +import System.Directory(getModificationTime) import Data.Time.Format (formatTime) import Text.Pandoc.Compat.Time (defaultTimeLocale) import System.IO.Error (catchIOError) diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs index bd299a802..04752a194 100644 --- a/src/Text/Pandoc/Shared.hs +++ b/src/Text/Pandoc/Shared.hs @@ -132,7 +132,7 @@ import System.IO (stderr) import System.IO.Temp import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..), renderOptions) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as B8 import Data.ByteString.Base64 (decodeLenient) @@ -152,16 +152,7 @@ import Paths_pandoc (getDataFileName) #ifdef HTTP_CLIENT import Network.HTTP.Client (httpLbs, responseBody, responseHeaders, Request(port,host)) -#if MIN_VERSION_http_client(0,4,30) -import Network.HTTP.Client (parseRequest) -#else -import Network.HTTP.Client (parseUrl) -#endif -#if MIN_VERSION_http_client(0,4,18) -import Network.HTTP.Client (newManager) -#else -import Network.HTTP.Client (withManager) -#endif +import Network.HTTP.Client (parseRequest, newManager) import Network.HTTP.Client.Internal (addProxy) import Network.HTTP.Client.TLS (tlsManagerSettings) import System.Environment (getEnv) diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs index 925925872..d111b3efa 100644 --- a/src/Text/Pandoc/Templates.hs +++ b/src/Text/Pandoc/Templates.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, CPP, +{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings, GeneralizedNewtypeDeriving #-} {- Copyright (C) 2009-2016 John MacFarlane <jgm@berkeley.edu> @@ -98,7 +98,7 @@ import Control.Monad (guard, when) import Data.Aeson (ToJSON(..), Value(..)) import qualified Text.Parsec as P import Text.Parsec.Text (Parser) -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import qualified Data.Text as T import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) @@ -108,12 +108,8 @@ import qualified Data.Map as M import qualified Data.HashMap.Strict as H import Data.Foldable (toList) import qualified Control.Exception.Extensible as E (try, IOException) -#if MIN_VERSION_blaze_html(0,5,0) import Text.Blaze.Html (Html) import Text.Blaze.Internal (preEscapedText) -#else -import Text.Blaze (preEscapedText, Html) -#endif import Data.ByteString.Lazy (ByteString, fromChunks) import Text.Pandoc.Shared (readDataFileUTF8, ordNub) import Data.Vector ((!?)) diff --git a/src/Text/Pandoc/UTF8.hs b/src/Text/Pandoc/UTF8.hs index 87ed5312b..62a662029 100644 --- a/src/Text/Pandoc/UTF8.hs +++ b/src/Text/Pandoc/UTF8.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {- Copyright (C) 2010-2016 John MacFarlane <jgm@berkeley.edu> @@ -116,11 +115,7 @@ fromStringLazy :: String -> BL.ByteString fromStringLazy = TL.encodeUtf8 . TL.pack encodePath :: FilePath -> FilePath -decodeArg :: String -> String -#if MIN_VERSION_base(4,4,0) encodePath = id + +decodeArg :: String -> String decodeArg = id -#else -encodePath = B.unpack . fromString -decodeArg = toString . B.pack -#endif diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs index 9b1c70166..8bb0810e4 100644 --- a/src/Text/Pandoc/Writers/Docbook.hs +++ b/src/Text/Pandoc/Writers/Docbook.hs @@ -176,7 +176,11 @@ blockToDocbook opts (Div (ident,_,_) [Para lst]) = then flush $ nowrap $ inTags False "literallayout" attribs $ inlinesToDocbook opts lst else inTags True "para" attribs $ inlinesToDocbook opts lst -blockToDocbook opts (Div _ bs) = blocksToDocbook opts $ map plainToPara bs +blockToDocbook opts (Div (ident,_,_) bs) = + (if null ident + then mempty + else selfClosingTag "anchor" [("id", ident)]) $$ + blocksToDocbook opts (map plainToPara bs) blockToDocbook _ (Header _ _ _) = empty -- should not occur after hierarchicalize blockToDocbook opts (Plain lst) = inlinesToDocbook opts lst -- title beginning with fig: indicates that the image is a figure @@ -313,7 +317,10 @@ inlineToDocbook opts (Quoted _ lst) = inTagsSimple "quote" $ inlinesToDocbook opts lst inlineToDocbook opts (Cite _ lst) = inlinesToDocbook opts lst -inlineToDocbook opts (Span _ ils) = +inlineToDocbook opts (Span (ident,_,_) ils) = + (if null ident + then mempty + else selfClosingTag "anchor" [("id", ident)]) <> inlinesToDocbook opts ils inlineToDocbook _ (Code _ str) = inTagsSimple "literal" $ text (escapeStringForXML str) diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index 5b8b44326..d31928b01 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -60,7 +60,7 @@ import Data.Unique (hashUnique, newUnique) import System.Random (randomRIO) import Text.Printf (printf) import qualified Control.Exception as E -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.MIME (MimeType, getMimeType, getMimeTypeDef, extensionFromMimeType) import Control.Applicative ((<|>)) diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs index 433e28bf2..db8c301ef 100644 --- a/src/Text/Pandoc/Writers/HTML.hs +++ b/src/Text/Pandoc/Writers/HTML.hs @@ -31,7 +31,7 @@ Conversion of 'Pandoc' documents to HTML. -} module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where import Text.Pandoc.Definition -import Text.Pandoc.Compat.Monoid ((<>)) +import Data.Monoid ((<>)) import Text.Pandoc.Shared import Text.Pandoc.Writers.Shared import Text.Pandoc.Options diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index b7db64aec..a88ff303f 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -276,6 +276,7 @@ stringToLaTeX ctx (x:xs) = do '€' -> "\\euro{}" ++ rest '{' -> "\\{" ++ rest '}' -> "\\}" ++ rest + '`' | ctx == CodeString -> "\\textasciigrave{}" ++ rest '$' | not isUrl -> "\\$" ++ rest '%' -> "\\%" ++ rest '&' -> "\\&" ++ rest @@ -296,6 +297,7 @@ stringToLaTeX ctx (x:xs) = do ']' -> "{]}" ++ rest -- optional arguments '\'' | ctx == CodeString -> "\\textquotesingle{}" ++ rest '\160' -> "~" ++ rest + '\x202F' -> "\\," ++ rest '\x2026' -> "\\ldots{}" ++ rest '\x2018' | ligatures -> "`" ++ rest '\x2019' | ligatures -> "'" ++ rest diff --git a/src/Text/Pandoc/XML.hs b/src/Text/Pandoc/XML.hs index 4cc2141b4..e105aee91 100644 --- a/src/Text/Pandoc/XML.hs +++ b/src/Text/Pandoc/XML.hs @@ -38,7 +38,7 @@ module Text.Pandoc.XML ( escapeCharForXML, import Text.Pandoc.Pretty import Data.Char (ord, isAscii, isSpace) -import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) +import Text.HTML.TagSoup.Entity (lookupEntity) -- | Escape one character as needed for XML. escapeCharForXML :: Char -> String @@ -101,7 +101,7 @@ toEntities (c:cs) fromEntities :: String -> String fromEntities ('&':xs) = case lookupEntity ent' of - Just c -> c : fromEntities rest + Just c -> c ++ fromEntities rest Nothing -> '&' : fromEntities xs where (ent, rest) = case break (\c -> isSpace c || c == ';') xs of (zs,';':ys) -> (zs,ys) diff --git a/stack.full.yaml b/stack.full.yaml index 7d01d279c..e405a4c27 100644 --- a/stack.full.yaml +++ b/stack.full.yaml @@ -22,8 +22,4 @@ packages: extra-deps: - http-client-0.5.0 - http-client-tls-0.3.0 -- data-default-instances-base-0.1.0.1 -- cmark-0.5.3.1 -- aeson-pretty-0.8.1 -- texmath-0.8.6.5 -resolver: nightly-2016-07-11 +resolver: lts-7.0 diff --git a/stack.yaml b/stack.yaml index e9b91905c..b1d68af03 100644 --- a/stack.yaml +++ b/stack.yaml @@ -10,7 +10,4 @@ packages: extra-deps: - http-client-0.5.0 - http-client-tls-0.3.0 -- data-default-instances-base-0.1.0.1 -- cmark-0.5.3.1 -- texmath-0.8.6.5 -resolver: nightly-2016-07-11 +resolver: lts-7.0 diff --git a/tests/Tests/Readers/Docx.hs b/tests/Tests/Readers/Docx.hs index a9a9094f1..8ae0532e4 100644 --- a/tests/Tests/Readers/Docx.hs +++ b/tests/Tests/Readers/Docx.hs @@ -182,6 +182,10 @@ tests = [ testGroup "inlines" "docx/already_auto_ident.docx" "docx/already_auto_ident.native" , testCompare + "nested anchor spans in header" + "docx/nested_anchors_in_header.docx" + "docx/nested_anchors_in_header.native" + , testCompare "single numbered item not made into list" "docx/numbered_header.docx" "docx/numbered_header.native" diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs index 0a3f9c222..d4fedc797 100644 --- a/tests/Tests/Readers/Org.hs +++ b/tests/Tests/Readers/Org.hs @@ -467,7 +467,14 @@ tests = , "Author" =: "#+author: Albert /Emacs-Fanboy/ Krewinkel" =?> let author = toList . spcSep $ [ "Albert", emph "Emacs-Fanboy", "Krewinkel" ] - meta = setMeta "author" (MetaInlines author) $ nullMeta + meta = setMeta "author" (MetaList [MetaInlines author]) $ nullMeta + in Pandoc meta mempty + + , "Multiple authors" =: + "#+author: James Dewey Watson, Francis Harry Compton Crick " =?> + let watson = MetaInlines $ toList "James Dewey Watson" + crick = MetaInlines $ toList "Francis Harry Compton Crick" + meta = setMeta "author" (MetaList [watson, crick]) $ nullMeta in Pandoc meta mempty , "Date" =: @@ -478,8 +485,8 @@ tests = , "Description" =: "#+DESCRIPTION: Explanatory text" =?> - let description = toList . spcSep $ [ "Explanatory", "text" ] - meta = setMeta "description" (MetaInlines description) $ nullMeta + let description = "Explanatory text" + meta = setMeta "description" (MetaString description) $ nullMeta in Pandoc meta mempty , "Properties drawer" =: @@ -489,6 +496,38 @@ tests = ] =?> (mempty::Blocks) + , "LaTeX_headers options are translated to header-includes" =: + "#+LaTeX_header: \\usepackage{tikz}" =?> + let latexInlines = rawInline "latex" "\\usepackage{tikz}" + inclList = MetaList [MetaInlines (toList latexInlines)] + meta = setMeta "header-includes" inclList nullMeta + in Pandoc meta mempty + + , "LaTeX_class option is translated to documentclass" =: + "#+LATEX_CLASS: article" =?> + let meta = setMeta "documentclass" (MetaString "article") nullMeta + in Pandoc meta mempty + + , "LaTeX_class_options is translated to classoption" =: + "#+LATEX_CLASS_OPTIONS: [a4paper]" =?> + let meta = setMeta "classoption" (MetaString "a4paper") nullMeta + in Pandoc meta mempty + + , "LaTeX_class_options is translated to classoption" =: + "#+html_head: <meta/>" =?> + let html = rawInline "html" "<meta/>" + inclList = MetaList [MetaInlines (toList html)] + meta = setMeta "header-includes" inclList nullMeta + in Pandoc meta mempty + + , "later meta definitions take precedence" =: + unlines [ "#+AUTHOR: this will not be used" + , "#+author: Max" + ] =?> + let author = MetaInlines [Str "Max"] + meta = setMeta "author" (MetaList [author]) $ nullMeta + in Pandoc meta mempty + , "Logbook drawer" =: unlines [ " :LogBook:" , " - State \"DONE\" from \"TODO\" [2014-03-03 Mon 11:00]" @@ -563,69 +602,91 @@ tests = ] =?> (para (link "http://example.com/foo" "" "bar")) - , "Export option: Disable simple sub/superscript syntax" =: - unlines [ "#+OPTIONS: ^:nil" - , "a^b" - ] =?> - para "a^b" - , "Export option: directly select drawers to be exported" =: - unlines [ "#+OPTIONS: d:(\"IMPORTANT\")" - , ":IMPORTANT:" - , "23" - , ":END:" - , ":BORING:" - , "very boring" - , ":END:" - ] =?> - divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "23") - - , "Export option: exclude drawers from being exported" =: - unlines [ "#+OPTIONS: d:(not \"BORING\")" - , ":IMPORTANT:" - , "5" - , ":END:" - , ":BORING:" - , "very boring" - , ":END:" - ] =?> - divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "5") - - , "Export option: don't include archive trees" =: - unlines [ "#+OPTIONS: arch:nil" - , "* old :ARCHIVE:" - ] =?> - (mempty ::Blocks) + , testGroup "export options" + + [ "disable simple sub/superscript syntax" =: + unlines [ "#+OPTIONS: ^:nil" + , "a^b" + ] =?> + para "a^b" + + , "directly select drawers to be exported" =: + unlines [ "#+OPTIONS: d:(\"IMPORTANT\")" + , ":IMPORTANT:" + , "23" + , ":END:" + , ":BORING:" + , "very boring" + , ":END:" + ] =?> + divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "23") + + , "exclude drawers from being exported" =: + unlines [ "#+OPTIONS: d:(not \"BORING\")" + , ":IMPORTANT:" + , "5" + , ":END:" + , ":BORING:" + , "very boring" + , ":END:" + ] =?> + divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "5") + + , "don't include archive trees" =: + unlines [ "#+OPTIONS: arch:nil" + , "* old :ARCHIVE:" + ] =?> + (mempty ::Blocks) + + , "include complete archive trees" =: + unlines [ "#+OPTIONS: arch:t" + , "* old :ARCHIVE:" + , " boring" + ] =?> + let tagSpan t = spanWith ("", ["tag"], [("data-tag-name", t)]) mempty + in mconcat [ headerWith ("old", [], mempty) 1 ("old" <> tagSpan "ARCHIVE") + , para "boring" + ] - , "Export option: include complete archive trees" =: - unlines [ "#+OPTIONS: arch:t" - , "* old :ARCHIVE:" - , " boring" - ] =?> - let tagSpan t = spanWith ("", ["tag"], [("data-tag-name", t)]) mempty - in mconcat [ headerWith ("old", [], mempty) 1 ("old" <> tagSpan "ARCHIVE") - , para "boring" - ] + , "include archive tree header only" =: + unlines [ "#+OPTIONS: arch:headline" + , "* old :ARCHIVE:" + , " boring" + ] =?> + let tagSpan t = spanWith ("", ["tag"], [("data-tag-name", t)]) mempty + in headerWith ("old", [], mempty) 1 ("old" <> tagSpan "ARCHIVE") + + , "limit headline depth" =: + unlines [ "#+OPTIONS: H:2" + , "* section" + , "** subsection" + , "*** list item 1" + , "*** list item 2" + ] =?> + mconcat [ headerWith ("section", [], []) 1 "section" + , headerWith ("subsection", [], []) 2 "subsection" + , orderedList [ para "list item 1", para "list item 2" ] + ] - , "Export option: include archive tree header only" =: - unlines [ "#+OPTIONS: arch:headline" - , "* old :ARCHIVE:" - , " boring" - ] =?> - let tagSpan t = spanWith ("", ["tag"], [("data-tag-name", t)]) mempty - in headerWith ("old", [], mempty) 1 ("old" <> tagSpan "ARCHIVE") - - , "Export option: limit headline depth" =: - unlines [ "#+OPTIONS: H:2" - , "* section" - , "** subsection" - , "*** list item 1" - , "*** list item 2" - ] =?> - mconcat [ headerWith ("section", [], []) 1 "section" - , headerWith ("subsection", [], []) 2 "subsection" - , orderedList [ para "list item 1", para "list item 2" ] - ] + , "disable author export" =: + unlines [ "#+OPTIONS: author:nil" + , "#+AUTHOR: ShyGuy" + ] =?> + Pandoc nullMeta mempty + + , "disable creator export" =: + unlines [ "#+OPTIONS: creator:nil" + , "#+creator: The Architect" + ] =?> + Pandoc nullMeta mempty + + , "disable email export" =: + unlines [ "#+OPTIONS: email:nil" + , "#+email: no-mail-please@example.com" + ] =?> + Pandoc nullMeta mempty + ] ] , testGroup "Basic Blocks" $ @@ -757,6 +818,15 @@ tests = ] =?> headerWith ("fubar", [], [("bar", "baz")]) 1 "foo" + + , "Headers marked with a unnumbered property get a class of the same name" =: + unlines [ "* Not numbered" + , " :PROPERTIES:" + , " :UNNUMBERED: t" + , " :END:" + ] =?> + headerWith ("not-numbered", ["unnumbered"], []) 1 "Not numbered" + , "Paragraph starting with an asterisk" =: "*five" =?> para "*five" diff --git a/tests/Tests/Writers/LaTeX.hs b/tests/Tests/Writers/LaTeX.hs index 4a1232db2..3dacaacd5 100644 --- a/tests/Tests/Writers/LaTeX.hs +++ b/tests/Tests/Writers/LaTeX.hs @@ -75,5 +75,7 @@ tests = [ testGroup "code blocks" "\\sout{\\texttt{foo} bar}" , "single quotes" =: code "dog's" =?> "\\texttt{dog\\textquotesingle{}s}" + , "backtick" =: + code "`nu?`" =?> "\\texttt{\\textasciigrave{}nu?\\textasciigrave{}}" ] ] diff --git a/tests/docx/nested_anchors_in_header.docx b/tests/docx/nested_anchors_in_header.docx Binary files differnew file mode 100644 index 000000000..ddebb7ff4 --- /dev/null +++ b/tests/docx/nested_anchors_in_header.docx diff --git a/tests/docx/nested_anchors_in_header.native b/tests/docx/nested_anchors_in_header.native new file mode 100644 index 000000000..e2b6eb1ef --- /dev/null +++ b/tests/docx/nested_anchors_in_header.native @@ -0,0 +1,10 @@ +[Header 1 ("short-instructions",[],[]) [Str "Short",Space,Str "instructions"] +,Para [Link ("",[],[]) [Str "Open",Space,Str "remote",Space,Str "folder"] ("#remote-folder-or-longlonglonglonglong-file-with-manymanymanymany-letters-inside-opening","")] +,Para [Str "Do",Space,Str "staff"] +,Para [Link ("",[],[]) [Str "Close",Space,Str "remote",Space,Str "folder"] ("#remote-folder-or-longlonglonglonglong-file-with-manymanymanymany-letters-inside-closing","")] +,Header 1 ("some-instructions",[],[]) [Str "Some",Space,Str "instructions"] +,Para [Str "Lines"] +,Header 2 ("remote-folder-or-longlonglonglonglong-file-with-manymanymanymany-letters-inside-opening",[],[]) [Str "Remote",Space,Str "folder",Space,Str "or",Space,Str "longlonglonglonglong",Space,Str "file",Space,Str "with",Space,Str "manymanymanymany",Space,Str "letters",Space,Str "inside",Space,Str "opening"] +,Para [Str "Open",Space,Str "folder"] +,Header 2 ("remote-folder-or-longlonglonglonglong-file-with-manymanymanymany-letters-inside-closing",[],[]) [Str "Remote",Space,Str "folder",Space,Str "or",Space,Str "longlonglonglonglong",Space,Str "file",Space,Str "with",Space,Str "manymanymanymany",Space,Str "letters",Space,Str "inside",Space,Str "closing"] +,Para [Str "Close",Space,Str "folder"]] diff --git a/windows/stack.yaml b/windows/stack.yaml index a071d413a..cfb8f8f0b 100644 --- a/windows/stack.yaml +++ b/windows/stack.yaml @@ -14,11 +14,7 @@ flags: packages: - '..' extra-deps: -- 'data-default-0.6.0' -- 'pandoc-citeproc-0.10.1' - 'http-client-0.5.0' - 'http-client-tls-0.3.0' -- 'cmark-0.5.3.1' -- 'aeson-pretty-0.8.1' -- 'texmath-0.8.6.5' -resolver: lts-6.5 +- pandoc-citeproc-0.10.1.1 +resolver: lts-7.0 |