packages feed

pandoc 2.19 → 2.19.1

raw patch · 40 files changed

+1345/−575 lines, 40 filesdep +base64dep +servant-serverdep +warpdep −base64-bytestringdep ~aesondep ~gridtablesdep ~haddock-libraryPVP ok

version bump matches the API change (PVP)

Dependencies added: base64, servant-server, warp

Dependencies removed: base64-bytestring

Dependency ranges changed: aeson, gridtables, haddock-library, http-types, safe, text, unix

API changes (from Hackage documentation)

+ Text.Pandoc.Highlighting: lookupHighlightingStyle :: PandocMonad m => String -> m Style
+ Text.Pandoc.Server: Blob :: ByteString -> Blob
+ Text.Pandoc.Server: Params :: Opt -> Text -> Maybe (Map FilePath Blob) -> Params
+ Text.Pandoc.Server: ServerOpts :: Int -> Int -> ServerOpts
+ Text.Pandoc.Server: [files] :: Params -> Maybe (Map FilePath Blob)
+ Text.Pandoc.Server: [options] :: Params -> Opt
+ Text.Pandoc.Server: [serverPort] :: ServerOpts -> Int
+ Text.Pandoc.Server: [serverTimeout] :: ServerOpts -> Int
+ Text.Pandoc.Server: [text] :: Params -> Text
+ Text.Pandoc.Server: app :: Application
+ Text.Pandoc.Server: data Params
+ Text.Pandoc.Server: data ServerOpts
+ Text.Pandoc.Server: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Server.Blob
+ Text.Pandoc.Server: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Server.Params
+ Text.Pandoc.Server: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Server.Blob
+ Text.Pandoc.Server: instance Data.Default.Class.Default Text.Pandoc.Server.Params
+ Text.Pandoc.Server: instance GHC.Classes.Eq Text.Pandoc.Server.Blob
+ Text.Pandoc.Server: instance GHC.Show.Show Text.Pandoc.Server.Blob
+ Text.Pandoc.Server: instance GHC.Show.Show Text.Pandoc.Server.Params
+ Text.Pandoc.Server: instance GHC.Show.Show Text.Pandoc.Server.ServerOpts
+ Text.Pandoc.Server: newtype Blob
+ Text.Pandoc.Server: parseServerOpts :: IO ServerOpts

Files

INSTALL.md view
@@ -215,66 +215,46 @@     `pandoc` executable into `~/.local/bin`, which you should     add to your `PATH`.  This process will take a while, and     will consume a considerable amount of disk space.+    If you also want the `pandoc-server` executable, add+    `--flag pandoc:server` to the above command. + ### Quick cabal method -1.  Install the [Haskell platform].  This will give you [GHC] and-    the [cabal-install] build tool.  Note that pandoc requires-    GHC >= 7.10 and cabal >= 2.0.+1.  Install [ghcup](https://www.haskell.org/ghcup/install/).+    This will give you `ghc` and `cabal`.  2.  Update your package database:          cabal update -3.  Check your cabal version with--        cabal --version--    If you have a version less than 2.0, install the latest with:--        cabal install cabal-install--4.  Use `cabal` to install pandoc and its dependencies:+3.  Use `cabal` to install pandoc and its dependencies:          cabal install pandoc      This procedure will install the released version of pandoc,     which will be downloaded automatically from HackageDB.+    The `pandoc` executable will be placed in `$HOME/.cabal/bin`+    on linux/unix/macOS and in `%APPDATA%\cabal\bin` on Windows.+    Make sure this directory is in your path. +    If you also want the `pandoc-server` executable, add+    `-fserver` to the above command.+     If you want to install a modified or development version     of pandoc instead, switch to the source directory and do     as above, but without the 'pandoc':          cabal install -5.  Make sure the `$CABALDIR/bin` directory is in your path.  You should-    now be able to run `pandoc`:+4.  You should now be able to run `pandoc`:          pandoc --help -    [Not sure where `$CABALDIR` is?](https://wiki.haskell.org/Cabal-Install#The_cabal-install_configuration_file)--5.  By default `pandoc` uses the "i;unicode-casemap" method-    to sort bibliography entries (RFC 5051).  If you would like to-    use the locale-sensitive unicode collation algorithm instead,-    specify the `icu` flag (which affects the dependency `citeproc`):--        cabal install pandoc -ficu--    Note that this requires the `text-icu` library, which in turn-    depends on the C library `icu4c`.  Installation directions-    vary by platform.  Here is how it might work on macOS with Homebrew:--        brew install icu4c-        stack install pandoc \-          --flag "citeproc:icu" \-          --extra-lib-dirs=/usr/local/opt/icu4c/lib \-          --extra-include-dirs=/usr/local/opt/icu4c/include--6.  The `pandoc.1` man page will be installed automatically.  cabal shows-    you where it is installed: you may need to set your `MANPATH`-    accordingly. If `MANUAL.txt` has been modified, the man page can be-    rebuilt: `make man/pandoc.1`.+5.  Cabal does not install the `pandoc.1` man page, but you can+    copy it from the `man/` directory of the source code to+    `/usr/local/share/man/man1/` or wherever man pages go on+    your system.   ### Custom cabal method@@ -312,6 +292,8 @@      - `lua53`: embed support for Lua 5.3 instead of 5.4. +    - `server`:  build the `pandoc-server` executable.+ 3.  Build:          cabal build@@ -321,19 +303,6 @@          cabal haddock --html-location=URL --hyperlink-source -5.  Copy the files:--        cabal copy --destdir=PATH--    The default destdir is `/`.--6.  Register pandoc as a GHC package:--        cabal register--    Package managers may want to use the `--gen-script` option to-    generate a script that can be run to register the package at-    install time.  ### Creating a relocatable binary 
MANUAL.txt view
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: August 3, 2022+date: August 18, 2022 ---  # Synopsis@@ -7050,6 +7050,25 @@ Some document formats also include a unique identifier.  For EPUB, this can be set explicitly by setting the `identifier` metadata field (see [EPUB Metadata], above).++# Running pandoc as a web server++If you rename (or symlink) the pandoc executable to+`pandoc-server`, it will start up a web server with a JSON+API. This server exposes most of the conversion functionality+of pandoc.  For full documentation, see the [pandoc-server]+man page.++If you rename (or symlink) the pandoc executable to+`pandoc-server.cgi`, it will function as a CGI program+exposing the same API as `pandoc-server`.++`pandoc-server` is designed to be maximally secure; it uses+Haskell's type system to provide strong guarantees that no I/O+will be performed on the server during pandoc conversions.++[pandoc-server]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-server.md+  # A note on security 
app/pandoc.hs view
@@ -14,7 +14,20 @@ import qualified Control.Exception as E import Text.Pandoc.App (convertWithOpts, defaultOpts, options, parseOptions) import Text.Pandoc.Error (handleError)+import Text.Pandoc.Server (ServerOpts(..), parseServerOpts, app)+import Safe (readDef)+import System.Environment (getProgName, lookupEnv)+import qualified Network.Wai.Handler.CGI as CGI+import qualified Network.Wai.Handler.Warp as Warp+import Network.Wai.Middleware.Timeout (timeout)  main :: IO ()-main = E.catch (parseOptions options defaultOpts >>= convertWithOpts)-          (handleError . Left)+main = E.handle (handleError . Left) $ do+  prg <- getProgName+  cgiTimeout <- maybe 2 (readDef 2) <$> lookupEnv "PANDOC_SERVER_TIMEOUT"+  case prg of+    "pandoc-server.cgi" -> CGI.run (timeout cgiTimeout app)+    "pandoc-server" -> do+      sopts <- parseServerOpts+      Warp.run (serverPort sopts) (timeout (serverTimeout sopts) app)+    _ -> parseOptions options defaultOpts >>= convertWithOpts
cabal.project view
@@ -2,4 +2,3 @@ tests: True flags: +embed_data_files constraints: aeson >= 2.0.1.0-
changelog.md view
@@ -1,5 +1,86 @@ # Revision history for pandoc +## pandoc 2.19.1 (2022-08-18)++  * Add server capabilities.++    + New exported module Text.Pandoc.Server [API change].+    + The pandoc executable now starts up a web server when renamed or+      symlinked as `pandoc-server`, and functions as a CGI program when+      renamed or symlinked as `pandoc-server.cgi`.  See the man page for+      `pandoc-server` for full documentation.++  * Text.Pandoc.App.Opts: Redo `FromJSON` for `Opt` so that optional+    values can be omitted (in which case the values from+    `defaultOptions` are used).++  * Org reader: treat "abstract" block as metadata (Albert Krewinkel, #8204).+    A block of type "abstract" is assumed to define the document's abstract.+    It is transferred from the main text to the metadata.++  * Org template: add abstract from metadata as block of type "abstract"+    (#8204).++  * HTML writer: use `flex` property for column widths+    (Albert Krewinkel, #8232).++  * LaTeX writer:++    + Add label to tables that have an identifier (Albert Krewinkel, #8219).+      Tables with an identifier are marked with a `\label`. A caption is+      always included in this case, even if the caption is empty.+    + Use `\textquotesingle` for straight quotes in text.+    + Fix widths of multicolumn cells (#8218).++  * LaTeX template: fix behavior of `colorlinks` variable (Albert+    Krewinkel, #8226). Fixes a regression in 2.19 that required the+    `boxlinks` variable to be set in addition to the usual link coloring+    variables. Otherwise links were never colored in LaTeX PDF output.++  * Text.Pandoc.Highlighting: Export `lookupHighlightingStyle`+    [API change]. Previously this lived in an unexported module+    Text.Pandoc.App.CommandLineOptions, under the name+    `lookupHighlightStyle`.++  * Text.Pandoc.App:++    + Remove unneeded MonadIO constraints in readSources.+    + Factor out `convertWithOpts'` from `convertWithOpts`.+      This runs in any PandocMonad, MonadIO, MonadMask instance.+      So far it is not exported, but it might find a use later.++  * Support `--strip-comments` in commonmark/gfm (#8222).+    This change makes the commonmark reader sensitive to+    `readerStripComments`.++  * Lua: add function `pandoc.utils.citeproc` (Albert Krewinkel).+    The function runs the *citeproc* processor on a Pandoc document.+    Exposing this functionality to Lua allows to make citation processing+    part of a filter or writer, simplifies the creation of multiple+    bibliographies, and enables the use of varying citation styles in+    different parts of a document.++  * Refactor `linux/make_artifacts.sh`.++  * Update INSTALL.md installation from source instructions.++  * Use base64 package instead of base64-bytestring. It is supposed to be+    faster and more standards-compliant.++  * trypandoc improvements:++    + Add dropdown with canned examples.+    + Add citeproc support.+    + Support csv, bibliographic and binary formats.+    + Add load from file.+    + Add permalink.  Don't always reload page.+    + Use vanilla JS and CSS + the new `pandoc-server.cgi`.++  * Allow haddock-library-1.11.0.++  * Convert `tool/extract-changes.hs` to a Lua filter.++ ## pandoc 2.19 (2022-08-03)    * Add `--embed-resources` flag (Elliot Bobrow, #7331).  This can be
data/templates/default.latex view
@@ -403,10 +403,11 @@   filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$},   citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$},   urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$},-$endif$+$else$ $if(boxlinks)$ $else$   hidelinks,+$endif$ $endif$   pdfcreator={LaTeX via pandoc}} 
data/templates/default.org view
@@ -13,6 +13,11 @@ $header-includes$  $endfor$+$if(abstract)$+#+begin_abstract+$abstract$+#+end_abstract+$endif$ $for(include-before)$ $include-before$ 
man/pandoc.1 view
@@ -1,4 +1,4 @@-.\" Automatically generated by Pandoc 2.18+.\" Automatically generated by Pandoc 2.19 .\" .\" Define V font for inline verbatim, using C font in formats .\" that render this, and otherwise B font.@@ -14,7 +14,7 @@ . ftr VB CB . ftr VBI CBI .\}-.TH "Pandoc User\[cq]s Guide" "" "August 3, 2022" "pandoc 2.19" ""+.TH "Pandoc User\[cq]s Guide" "" "August 18, 2022" "pandoc 2.19.1" "" .hy .SH NAME pandoc - general markup converter@@ -7960,6 +7960,20 @@ Some document formats also include a unique identifier. For EPUB, this can be set explicitly by setting the \f[V]identifier\f[R] metadata field (see EPUB Metadata, above).+.SH RUNNING PANDOC AS A WEB SERVER+.PP+If you rename (or symlink) the pandoc executable to+\f[V]pandoc-server\f[R], it will start up a web server with a JSON API.+This server exposes most of the conversion functionality of pandoc.+For full documentation, see the pandoc-server man page.+.PP+If you rename (or symlink) the pandoc executable to+\f[V]pandoc-server.cgi\f[R], it will function as a CGI program exposing+the same API as \f[V]pandoc-server\f[R].+.PP+\f[V]pandoc-server\f[R] is designed to be maximally secure; it uses+Haskell\[cq]s type system to provide strong guarantees that no I/O will+be performed on the server during pandoc conversions. .SH A NOTE ON SECURITY .IP "1." 3 Although pandoc itself will not create or modify any files other than
pandoc.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            pandoc-version:         2.19+version:         2.19.1 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md@@ -28,7 +28,8 @@                  - TeX formats (LaTeX, ConTeXt)                  - XML formats (DocBook 4 and 5, JATS, TEI Simple, OpenDocument)                  - Outline formats (OPML)-                 - Bibliography formats (BibTeX, BibLaTeX, CSL JSON, CSL YAML)+                 - Bibliography formats (BibTeX, BibLaTeX, CSL JSON, CSL YAML,+                   RIS)                  - Word processor formats (Docx, RTF, ODT)                  - Interactive notebook formats (Jupyter notebook ipynb)                  - Page layout formats (InDesign ICML)@@ -36,7 +37,7 @@                    Vimwiki, XWiki, ZimWiki, Jira wiki, Creole)                  - Slide show formats (LaTeX Beamer, PowerPoint, Slidy,                    reveal.js, Slideous, S5, DZSlides)-                 - Data formats (CSV tables)+                 - Data formats (CSV and TSV tables)                  - PDF (via external programs such as pdflatex or wkhtmltopdf)                  .                  Pandoc can convert mathematical content in documents@@ -205,8 +206,8 @@                  man/pandoc.1.before                  man/pandoc.1.after                  -- trypandoc-                 trypandoc/Makefile                  trypandoc/index.html+                 trypandoc/trypandoc.js                  -- tests                  test/bodybg.gif                  test/*.native@@ -428,10 +429,6 @@   Description:   Embed Lua 5.3 instead of 5.4.   Default:       False -flag trypandoc-  Description:   Build trypandoc cgi executable.-  Default:       False- flag nightly   Description:   Add '-nightly-COMPILEDATE' to the output of '--version'.   Default:       False@@ -474,7 +471,6 @@                  aeson-pretty          >= 0.8.9    && < 0.9,                  array                 >= 0.5      && < 0.6,                  attoparsec            >= 0.12     && < 0.15,-                 base64-bytestring     >= 0.1      && < 1.3,                  binary                >= 0.7      && < 0.11,                  blaze-html            >= 0.9      && < 0.10,                  blaze-markup          >= 0.8      && < 0.9,@@ -491,12 +487,13 @@                  directory             >= 1.2.3    && < 1.4,                  doclayout             >= 0.4      && < 0.5,                  doctemplates          >= 0.10     && < 0.11,+                 base64                >= 0.4      && < 0.5,                  emojis                >= 0.1      && < 0.2,                  exceptions            >= 0.8      && < 0.11,                  file-embed            >= 0.0      && < 0.1,                  filepath              >= 1.1      && < 1.5,-                 gridtables            >= 0.0.2    && < 0.1,-                 haddock-library       >= 1.10     && < 1.11,+                 gridtables            >= 0.0.3    && < 0.1,+                 haddock-library       >= 1.10     && < 1.12,                  hslua-module-doclayout>= 1.0.4    && < 1.1,                  hslua-module-path     >= 1.0      && < 1.1,                  hslua-module-system   >= 1.0      && < 1.1,@@ -537,9 +534,12 @@                  xml-types             >= 0.3      && < 0.4,                  yaml                  >= 0.11     && < 0.12,                  zip-archive           >= 0.2.3.4  && < 0.5,-                 zlib                  >= 0.5      && < 0.7+                 zlib                  >= 0.5      && < 0.7,+                 servant-server,+                 wai                   >= 0.3+   if !os(windows)-    build-depends:  unix >= 2.4 && < 2.8+    build-depends:  unix >= 2.4 && < 2.9   if flag(nightly)     cpp-options:    -DNIGHTLY     build-depends:  template-haskell@@ -563,6 +563,7 @@                    Text.Pandoc.MediaBag,                    Text.Pandoc.Error,                    Text.Pandoc.Filter,+                   Text.Pandoc.Server,                    Text.Pandoc.Readers,                    Text.Pandoc.Readers.HTML,                    Text.Pandoc.Readers.LaTeX,@@ -788,20 +789,9 @@   main-is:         pandoc.hs   buildable:       True   other-modules:   Paths_pandoc--executable trypandoc-  import:          common-executable-  main-is:         trypandoc.hs-  hs-source-dirs:  trypandoc-  if flag(trypandoc)-    build-depends: aeson,-                   http-types,-                   text,-                   wai >= 0.3,-                   wai-extra >= 3.0.24-    buildable:     True-  else-    buildable:     False+  build-depends:   wai-extra             >= 3.0.24,+                   warp,+                   safe  test-suite test-pandoc   import:         common-executable
src/Text/Pandoc/App.hs view
@@ -28,6 +28,7 @@ import qualified Control.Exception as E import Control.Monad ( (>=>), when, forM_ ) import Control.Monad.Trans ( MonadIO(..) )+import Control.Monad.Catch ( MonadMask ) import Control.Monad.Except (throwError, catchError) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as B8@@ -77,6 +78,7 @@  convertWithOpts :: Opt -> IO () convertWithOpts opts = do+  let outputFile = fromMaybe "-" (optOutputFile opts)   datadir <- case optDataDir opts of                   Nothing   -> do                     d <- defaultUserDataDir@@ -86,292 +88,297 @@                                 else Nothing                   Just _    -> return $ optDataDir opts -  let outputFile = fromMaybe "-" (optOutputFile opts)-  let filters = optFilters opts-  let verbosity = optVerbosity opts-   when (optDumpArgs opts) $     do UTF8.hPutStrLn stdout (T.pack outputFile)        mapM_ (UTF8.hPutStrLn stdout . T.pack)              (fromMaybe ["-"] $ optInputFiles opts)        exitSuccess -  let sources = case optInputFiles opts of-                     Just xs | not (optIgnoreArgs opts) -> xs-                     _ -> ["-"] #ifdef _WINDOWS   let istty = True #else   istty <- liftIO $ queryTerminal stdOutput #endif -  res <- runIO $ do+  res <- runIO $ convertWithOpts' istty datadir opts+  case res of+    Left e -> E.throwIO e+    Right (output, reports) -> do+      case optLogFile opts of+           Nothing      -> return ()+           Just logfile -> BL.writeFile logfile (encodeLogMessages reports)+      let isWarning msg = messageVerbosity msg == WARNING+      when (optFailIfWarnings opts && any isWarning reports) $+          E.throwIO PandocFailOnWarningError+      let eol = case optEol opts of+                     CRLF   -> IO.CRLF+                     LF     -> IO.LF+                     Native -> nativeNewline+      case output of+        TextOutput t    -> writerFn eol outputFile t+        BinaryOutput bs -> writeFnBinary outputFile bs -    setTrace (optTrace opts)-    setVerbosity verbosity-    setUserDataDir datadir-    setResourcePath (optResourcePath opts)+convertWithOpts' :: (PandocMonad m, MonadIO m, MonadMask m)+                 => Bool+                 -> Maybe FilePath+                 -> Opt+                 -> m (PandocOutput, [LogMessage])+convertWithOpts' istty datadir opts = do+  let outputFile = fromMaybe "-" (optOutputFile opts)+  let filters = optFilters opts+  let verbosity = optVerbosity opts -    setInputFiles (fromMaybe ["-"] (optInputFiles opts))-    setOutputFile (optOutputFile opts)+  let sources = case optInputFiles opts of+                     Just xs | not (optIgnoreArgs opts) -> xs+                     _ -> ["-"]+  setTrace (optTrace opts)+  setVerbosity verbosity+  setUserDataDir datadir+  setResourcePath (optResourcePath opts) -    -- assign reader and writer based on options and filenames-    readerName <- case optFrom opts of-                       Just f  -> return f-                       Nothing -> case formatFromFilePaths sources of-                           Just f' -> return f'-                           Nothing | sources == ["-"] -> return "markdown"-                                   | any (isURI . T.pack) sources -> return "html"-                                   | otherwise -> do-                             report $ CouldNotDeduceFormat-                                 (map (T.pack . takeExtension) sources) "markdown"-                             return "markdown"+  setInputFiles (fromMaybe ["-"] (optInputFiles opts))+  setOutputFile (optOutputFile opts) -    let readerNameBase = T.takeWhile (\c -> c /= '+' && c /= '-') readerName+  -- assign reader and writer based on options and filenames+  readerName <- case optFrom opts of+                     Just f  -> return f+                     Nothing -> case formatFromFilePaths sources of+                         Just f' -> return f'+                         Nothing | sources == ["-"] -> return "markdown"+                                 | any (isURI . T.pack) sources -> return "html"+                                 | otherwise -> do+                           report $ CouldNotDeduceFormat+                               (map (T.pack . takeExtension) sources) "markdown"+                           return "markdown" -    let makeSandboxed pureReader =-          let files = maybe id (:) (optReferenceDoc opts) .-                      maybe id (:) (optEpubMetadata opts) .-                      maybe id (:) (optEpubCoverImage opts) .-                      maybe id (:) (optCSL opts) .-                      maybe id (:) (optCitationAbbreviations opts) $-                      optEpubFonts opts ++-                      optBibliography opts-           in  case pureReader of-                 TextReader r -> TextReader $ \o t -> sandbox files (r o t)-                 ByteStringReader r-                            -> ByteStringReader $ \o t -> sandbox files (r o t)+  let readerNameBase = T.takeWhile (\c -> c /= '+' && c /= '-') readerName -    (reader, readerExts) <--      if ".lua" `T.isSuffixOf` readerName-         then return (TextReader (readCustom (T.unpack readerName)), mempty)-         else if optSandbox opts-                 then case runPure (getReader readerName) of-                        Left e -> throwError e-                        Right (r, rexts) -> return (makeSandboxed r, rexts)-                 else getReader readerName+  let makeSandboxed pureReader =+        let files = maybe id (:) (optReferenceDoc opts) .+                    maybe id (:) (optEpubMetadata opts) .+                    maybe id (:) (optEpubCoverImage opts) .+                    maybe id (:) (optCSL opts) .+                    maybe id (:) (optCitationAbbreviations opts) $+                    optEpubFonts opts +++                    optBibliography opts+         in  case pureReader of+               TextReader r -> TextReader $ \o t -> sandbox files (r o t)+               ByteStringReader r+                          -> ByteStringReader $ \o t -> sandbox files (r o t) -    outputSettings <- optToOutputSettings opts-    let format = outputFormat outputSettings-    let writer = outputWriter outputSettings-    let writerName = outputWriterName outputSettings-    let writerNameBase = T.takeWhile (\c -> c /= '+' && c /= '-') writerName-    let writerOptions = outputWriterOptions outputSettings+  (reader, readerExts) <-+    if ".lua" `T.isSuffixOf` readerName+       then return (TextReader (readCustom (T.unpack readerName)), mempty)+       else if optSandbox opts+               then case runPure (getReader readerName) of+                      Left e -> throwError e+                      Right (r, rexts) -> return (makeSandboxed r, rexts)+               else getReader readerName -    let pdfOutput = isJust $ outputPdfProgram outputSettings+  outputSettings <- optToOutputSettings opts+  let format = outputFormat outputSettings+  let writer = outputWriter outputSettings+  let writerName = outputWriterName outputSettings+  let writerNameBase = T.takeWhile (\c -> c /= '+' && c /= '-') writerName+  let writerOptions = outputWriterOptions outputSettings -    let bibOutput = writerNameBase == "bibtex" ||-                    writerNameBase == "biblatex" ||-                    writerNameBase == "csljson"+  let pdfOutput = isJust $ outputPdfProgram outputSettings -    let standalone = optStandalone opts ||-                     not (isTextFormat format) ||-                     pdfOutput ||-                     bibOutput+  let bibOutput = writerNameBase == "bibtex" ||+                  writerNameBase == "biblatex" ||+                  writerNameBase == "csljson" -    when (pdfOutput && readerNameBase == "latex") $-      case optInputFiles opts of-        Just (inputFile:_) -> report $ UnusualConversion $ T.pack $-          "to convert a .tex file to PDF, you get better results by using pdflatex "-            <> "(or lualatex or xelatex) directly, try `pdflatex " <> inputFile-            <> "` instead of `pandoc " <> inputFile <> " -o " <> outputFile <> "`."-        _ -> return ()+  let standalone = optStandalone opts ||+                   not (isTextFormat format) ||+                   pdfOutput ||+                   bibOutput -    -- We don't want to send output to the terminal if the user-    -- does 'pandoc -t docx input.txt'; though we allow them to-    -- force this with '-o -'.  On posix systems, we detect-    -- when stdout is being piped and allow output to stdout-    -- in that case, but on Windows we can't.-    when ((pdfOutput || not (isTextFormat format)) &&-             istty && isNothing ( optOutputFile opts)) $-      throwError $ PandocAppError $-              "Cannot write " <> (if pdfOutput then "pdf" else format) <>-              " output to terminal.\n" <>-              "Specify an output file using the -o option, or " <>-              "use '-o -' to force output to stdout."+  when (pdfOutput && readerNameBase == "latex") $+    case optInputFiles opts of+      Just (inputFile:_) -> report $ UnusualConversion $ T.pack $+        "to convert a .tex file to PDF, you get better results by using pdflatex "+          <> "(or lualatex or xelatex) directly, try `pdflatex " <> inputFile+          <> "` instead of `pandoc " <> inputFile <> " -o " <> outputFile <> "`."+      _ -> return () +  -- We don't want to send output to the terminal if the user+  -- does 'pandoc -t docx input.txt'; though we allow them to+  -- force this with '-o -'.  On posix systems, we detect+  -- when stdout is being piped and allow output to stdout+  -- in that case, but on Windows we can't.+  when ((pdfOutput || not (isTextFormat format)) &&+           istty && isNothing ( optOutputFile opts)) $+    throwError $ PandocAppError $+            "Cannot write " <> (if pdfOutput then "pdf" else format) <>+            " output to terminal.\n" <>+            "Specify an output file using the -o option, or " <>+            "use '-o -' to force output to stdout." -    abbrevs <- Set.fromList . filter (not . T.null) . T.lines . UTF8.toText <$>-               case optAbbreviations opts of-                    Nothing -> readDataFile "abbreviations"-                    Just f  -> readFileStrict f -    case lookupMetaString "lang" (optMetadata opts) of-           ""      -> setTranslations $ Lang "en" Nothing (Just "US") [] [] []-           l       -> case parseLang l of-                           Left _   -> report $ InvalidLang l-                           Right l' -> setTranslations l'+  abbrevs <- Set.fromList . filter (not . T.null) . T.lines . UTF8.toText <$>+             case optAbbreviations opts of+                  Nothing -> readDataFile "abbreviations"+                  Just f  -> readFileStrict f -    let readerOpts = def{-            readerStandalone = standalone-          , readerColumns = optColumns opts-          , readerTabStop = optTabStop opts-          , readerIndentedCodeClasses = optIndentedCodeClasses opts-          , readerDefaultImageExtension =-             optDefaultImageExtension opts-          , readerTrackChanges = optTrackChanges opts-          , readerAbbreviations = abbrevs-          , readerExtensions = readerExts-          , readerStripComments = optStripComments opts-          }+  case lookupMetaString "lang" (optMetadata opts) of+         ""      -> setTranslations $ Lang "en" Nothing (Just "US") [] [] []+         l       -> case parseLang l of+                         Left _   -> report $ InvalidLang l+                         Right l' -> setTranslations l' -    metadataFromFile <--      case optMetadataFiles opts of-        []    -> return mempty-        paths -> do-          -- If format is markdown or commonmark, use the enabled extensions,-          -- otherwise treat metadata as pandoc markdown (see #7926, #6832)-          let readerOptsMeta =-                if readerNameBase == "markdown" || readerNameBase == "commonmark"-                   then readerOpts-                   else readerOpts{ readerExtensions = pandocExtensions }-          mconcat <$> mapM-                (\path -> do raw <- readMetadataFile path-                             yamlToMeta readerOptsMeta (Just path) raw) paths+  let readerOpts = def{+          readerStandalone = standalone+        , readerColumns = optColumns opts+        , readerTabStop = optTabStop opts+        , readerIndentedCodeClasses = optIndentedCodeClasses opts+        , readerDefaultImageExtension =+           optDefaultImageExtension opts+        , readerTrackChanges = optTrackChanges opts+        , readerAbbreviations = abbrevs+        , readerExtensions = readerExts+        , readerStripComments = optStripComments opts+        } -    let transforms = (case optShiftHeadingLevelBy opts of-                          0             -> id-                          x             -> (headerShift x :)) .-                     (if optStripEmptyParagraphs opts-                         then (stripEmptyParagraphs :)-                         else id) .-                     (if extensionEnabled Ext_east_asian_line_breaks-                            readerExts &&-                         not (extensionEnabled Ext_east_asian_line_breaks-                              (writerExtensions writerOptions) &&-                              writerWrapText writerOptions == WrapPreserve)-                         then (eastAsianLineBreakFilter :)-                         else id) .-                     (case optIpynbOutput opts of-                       _ | readerNameBase /= "ipynb" -> id-                       IpynbOutputAll  -> id-                       IpynbOutputNone -> (filterIpynbOutput Nothing :)-                       IpynbOutputBest -> (filterIpynbOutput (Just $-                                     if htmlFormat format-                                        then Format "html"-                                        else-                                          case format of-                                            "latex"  -> Format "latex"-                                            "beamer" -> Format "latex"-                                            _        -> Format format) :))-                     $ []+  metadataFromFile <-+    case optMetadataFiles opts of+      []    -> return mempty+      paths -> do+        -- If format is markdown or commonmark, use the enabled extensions,+        -- otherwise treat metadata as pandoc markdown (see #7926, #6832)+        let readerOptsMeta =+              if readerNameBase == "markdown" || readerNameBase == "commonmark"+                 then readerOpts+                 else readerOpts{ readerExtensions = pandocExtensions }+        mconcat <$> mapM+              (\path -> do raw <- readMetadataFile path+                           yamlToMeta readerOptsMeta (Just path) raw) paths -    let convertTabs = tabFilter (if optPreserveTabs opts ||-                                      readerNameBase == "t2t" ||-                                      readerNameBase == "man" ||-                                      readerNameBase == "tsv"-                                    then 0-                                    else optTabStop opts)+  let transforms = (case optShiftHeadingLevelBy opts of+                        0             -> id+                        x             -> (headerShift x :)) .+                   (if optStripEmptyParagraphs opts+                       then (stripEmptyParagraphs :)+                       else id) .+                   (if extensionEnabled Ext_east_asian_line_breaks+                          readerExts &&+                       not (extensionEnabled Ext_east_asian_line_breaks+                            (writerExtensions writerOptions) &&+                            writerWrapText writerOptions == WrapPreserve)+                       then (eastAsianLineBreakFilter :)+                       else id) .+                   (case optIpynbOutput opts of+                     _ | readerNameBase /= "ipynb" -> id+                     IpynbOutputAll  -> id+                     IpynbOutputNone -> (filterIpynbOutput Nothing :)+                     IpynbOutputBest -> (filterIpynbOutput (Just $+                                   if htmlFormat format+                                      then Format "html"+                                      else+                                        case format of+                                          "latex"  -> Format "latex"+                                          "beamer" -> Format "latex"+                                          _        -> Format format) :))+                   $ [] +  let convertTabs = tabFilter (if optPreserveTabs opts ||+                                    readerNameBase == "t2t" ||+                                    readerNameBase == "man" ||+                                    readerNameBase == "tsv"+                                  then 0+                                  else optTabStop opts) -    when (readerNameBase == "markdown_github" ||-          writerNameBase == "markdown_github") $-      report $ Deprecated "markdown_github" "Use gfm instead." -    mapM_ (uncurry setRequestHeader) (optRequestHeaders opts)+  when (readerNameBase == "markdown_github" ||+        writerNameBase == "markdown_github") $+    report $ Deprecated "markdown_github" "Use gfm instead." -    setNoCheckCertificate (optNoCheckCertificate opts)+  mapM_ (uncurry setRequestHeader) (optRequestHeaders opts) -    let isPandocCiteproc (JSONFilter f) = takeBaseName f == "pandoc-citeproc"-        isPandocCiteproc _              = False+  setNoCheckCertificate (optNoCheckCertificate opts) -    when (any isPandocCiteproc filters) $-      report $ Deprecated "pandoc-citeproc filter"-               "Use --citeproc instead."+  let isPandocCiteproc (JSONFilter f) = takeBaseName f == "pandoc-citeproc"+      isPandocCiteproc _              = False -    let cslMetadata =-          maybe id (setMeta "csl") (optCSL opts) .-          (case optBibliography opts of-             [] -> id-             xs -> setMeta "bibliography" xs) .-          maybe id (setMeta "citation-abbreviations")-                         (optCitationAbbreviations opts) $ mempty+  when (any isPandocCiteproc filters) $+    report $ Deprecated "pandoc-citeproc filter"+             "Use --citeproc instead." -    let filterEnv = Environment readerOpts writerOptions+  let cslMetadata =+        maybe id (setMeta "csl") (optCSL opts) .+        (case optBibliography opts of+           [] -> id+           xs -> setMeta "bibliography" xs) .+        maybe id (setMeta "citation-abbreviations")+                       (optCitationAbbreviations opts) $ mempty -    inputs <- readSources sources+  let filterEnv = Environment readerOpts writerOptions -    doc <- (case reader of-             TextReader r-               | readerNameBase == "json" ->-                   mconcat <$>-                      mapM (inputToText convertTabs-                             >=> r readerOpts . (:[])) inputs-               | optFileScope opts  ->-                   mconcat <$> mapM-                      (inputToText convertTabs-                             >=> r readerOpts . (:[]))-                      inputs-               | otherwise -> mapM (inputToText convertTabs) inputs-                                >>= r readerOpts-             ByteStringReader r ->-               mconcat <$> mapM (r readerOpts . inputToLazyByteString) inputs)-            >>= ( return . adjustMetadata (metadataFromFile <>)-              >=> return . adjustMetadata (<> optMetadata opts)-              >=> return . adjustMetadata (<> cslMetadata)-              >=> applyTransforms transforms-              >=> applyFilters filterEnv filters [T.unpack format]-              >=> (if not (optSandbox opts) &&-                      (isJust (optExtractMedia opts)-                       || writerNameBase == "docx") -- for fallback pngs-                   then fillMediaBag-                   else return)-              >=> maybe return extractMedia (optExtractMedia opts)-              )+  inputs <- readSources sources -    when (writerNameBase == "docx" && not (optSandbox opts)) $ do-      -- create fallback pngs for svgs-      items <- mediaItems <$> getMediaBag-      forM_ items $ \(fp, mt, bs) ->-        case T.takeWhile (/=';') mt of-          "image/svg+xml" -> do-            res <- svgToPng (writerDpi writerOptions) bs-            case res of-              Right bs' -> do-                let fp' = fp <> ".png"-                insertMedia fp' (Just "image/png") bs'-              Left e -> report $ CouldNotConvertImage (T.pack fp) (tshow e)-          _ -> return ()+  doc <- (case reader of+           TextReader r+             | readerNameBase == "json" ->+                 mconcat <$>+                    mapM (inputToText convertTabs+                           >=> r readerOpts . (:[])) inputs+             | optFileScope opts  ->+                 mconcat <$> mapM+                    (inputToText convertTabs+                           >=> r readerOpts . (:[]))+                    inputs+             | otherwise -> mapM (inputToText convertTabs) inputs+                              >>= r readerOpts+           ByteStringReader r ->+             mconcat <$> mapM (r readerOpts . inputToLazyByteString) inputs)+          >>= ( return . adjustMetadata (metadataFromFile <>)+            >=> return . adjustMetadata (<> optMetadata opts)+            >=> return . adjustMetadata (<> cslMetadata)+            >=> applyTransforms transforms+            >=> applyFilters filterEnv filters [T.unpack format]+            >=> (if not (optSandbox opts) &&+                    (isJust (optExtractMedia opts)+                     || writerNameBase == "docx") -- for fallback pngs+                 then fillMediaBag+                 else return)+            >=> maybe return extractMedia (optExtractMedia opts)+            ) -    output <- case writer of-      ByteStringWriter f -> BinaryOutput <$> f writerOptions doc-      TextWriter f -> case outputPdfProgram outputSettings of-        Just pdfProg -> do-                res <- makePDF pdfProg (optPdfEngineOpts opts) f-                        writerOptions doc-                case res of-                     Right pdf -> return $ BinaryOutput pdf-                     Left err' -> throwError $ PandocPDFError $-                                     TL.toStrict (TE.decodeUtf8With TE.lenientDecode err')+  when (writerNameBase == "docx" && not (optSandbox opts)) $ do+    -- create fallback pngs for svgs+    items <- mediaItems <$> getMediaBag+    forM_ items $ \(fp, mt, bs) ->+      case T.takeWhile (/=';') mt of+        "image/svg+xml" -> do+          res <- svgToPng (writerDpi writerOptions) bs+          case res of+            Right bs' -> do+              let fp' = fp <> ".png"+              insertMedia fp' (Just "image/png") bs'+            Left e -> report $ CouldNotConvertImage (T.pack fp) (tshow e)+        _ -> return () -        Nothing -> do-                let ensureNl t-                      | standalone = t-                      | T.null t || T.last t /= '\n' = t <> T.singleton '\n'-                      | otherwise = t-                textOutput <- ensureNl <$> f writerOptions doc-                if (optSelfContained opts || optEmbedResources opts) && htmlFormat format-                   then TextOutput <$> makeSelfContained textOutput-                   else return $ TextOutput textOutput-    reports <- getLog-    return (output, reports)+  output <- case writer of+    ByteStringWriter f -> BinaryOutput <$> f writerOptions doc+    TextWriter f -> case outputPdfProgram outputSettings of+      Just pdfProg -> do+              res <- makePDF pdfProg (optPdfEngineOpts opts) f+                      writerOptions doc+              case res of+                   Right pdf -> return $ BinaryOutput pdf+                   Left err' -> throwError $ PandocPDFError $+                                   TL.toStrict (TE.decodeUtf8With TE.lenientDecode err') -  case res of-    Left e -> E.throwIO e-    Right (output, reports) -> do-      case optLogFile opts of-           Nothing      -> return ()-           Just logfile -> BL.writeFile logfile (encodeLogMessages reports)-      let isWarning msg = messageVerbosity msg == WARNING-      when (optFailIfWarnings opts && any isWarning reports) $-          E.throwIO PandocFailOnWarningError-      let eol = case optEol opts of-                     CRLF   -> IO.CRLF-                     LF     -> IO.LF-                     Native -> nativeNewline-      case output of-        TextOutput t    -> writerFn eol outputFile t-        BinaryOutput bs -> writeFnBinary outputFile bs+      Nothing -> do+              let ensureNl t+                    | standalone = t+                    | T.null t || T.last t /= '\n' = t <> T.singleton '\n'+                    | otherwise = t+              textOutput <- ensureNl <$> f writerOptions doc+              if (optSelfContained opts || optEmbedResources opts) && htmlFormat format+                 then TextOutput <$> makeSelfContained textOutput+                 else return $ TextOutput textOutput+  reports <- getLog+  return (output, reports)  data PandocOutput = TextOutput Text | BinaryOutput BL.ByteString   deriving (Show)@@ -393,13 +400,13 @@ applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc applyTransforms transforms d = return $ foldr ($) d transforms -readSources :: (PandocMonad m, MonadIO m)+readSources :: PandocMonad m             => [FilePath] -> m [(FilePath, (BS.ByteString, Maybe MimeType))] readSources srcs =   mapM (\fp -> do t <- readSource fp                   return (if fp == "-" then "" else fp, t)) srcs -readSource :: (PandocMonad m, MonadIO m)+readSource :: PandocMonad m            => FilePath -> m (BS.ByteString, Maybe MimeType) readSource "-" = (,Nothing) <$> readStdinStrict readSource src =
src/Text/Pandoc/App/CommandLineOptions.hs view
@@ -22,12 +22,10 @@           , parseOptionsFromArgs           , options           , engines-          , lookupHighlightStyle           , setVariable           ) where import Control.Monad import Control.Monad.Trans-import Control.Monad.Except (throwError) import Control.Monad.State.Strict import Data.Aeson.Encode.Pretty (encodePretty', Config(..), keyOrder,          defConfig, Indent(..), NumberFormat(..))@@ -41,7 +39,7 @@ import Data.Text (Text) import HsLua (Exception, getglobal, openlibs, peek, run, top) import Safe (tailDef)-import Skylighting (Style, Syntax (..), defaultSyntaxMap, parseTheme)+import Skylighting (Syntax (..), defaultSyntaxMap) import System.Console.GetOpt import System.Environment (getArgs, getProgName) import System.Exit (exitSuccess)@@ -54,7 +52,7 @@                             DefaultsState (..), applyDefaults,                             fullDefaultsPath) import Text.Pandoc.Filter (Filter (..))-import Text.Pandoc.Highlighting (highlightingStyles)+import Text.Pandoc.Highlighting (highlightingStyles, lookupHighlightingStyle) import Text.Pandoc.Shared (ordNub, elemText, safeStrRead, defaultUserDataDir) import Text.Printf @@ -946,7 +944,7 @@                  (ReqArg                   (\arg opt -> do                      let write = maybe B.putStr B.writeFile $ optOutputFile opt-                     sty <- runIOorExplode $ lookupHighlightStyle arg+                     sty <- runIOorExplode $ lookupHighlightingStyle arg                      write $ encodePretty'                        defConfig{confIndent = Spaces 4                                 ,confCompare = keyOrder@@ -1058,20 +1056,6 @@  splitField :: String -> (String, String) splitField = second (tailDef "true") . break (`elemText` ":=")--lookupHighlightStyle :: PandocMonad m => String -> m Style-lookupHighlightStyle s-  | takeExtension s == ".theme" = -- attempt to load KDE theme-    do contents <- readFileLazy s-       case parseTheme contents of-            Left _    -> throwError $ PandocOptionError $ T.pack $-                           "Could not read highlighting theme " ++ s-            Right sty -> return sty-  | otherwise =-  case lookup (T.toLower $ T.pack s) highlightingStyles of-       Just sty -> return sty-       Nothing  -> throwError $ PandocOptionError $ T.pack $-                      "Unknown highlight-style " ++ s  deprecatedOption :: String -> String -> IO () deprecatedOption o msg =
src/Text/Pandoc/App/Opt.hs view
@@ -54,7 +54,8 @@ import qualified Data.Map as M import qualified Data.ByteString.Char8 as B8 import Text.Pandoc.Definition (Meta(..), MetaValue(..))-import Data.Aeson (defaultOptions, Options(..), Result(..), fromJSON, camelTo2)+import Data.Aeson (defaultOptions, Options(..), Result(..), camelTo2,+                   genericToJSON, fromJSON) import Data.Aeson.TH (deriveJSON) import Control.Applicative ((<|>)) import Data.Yaml@@ -156,8 +157,90 @@     , optSandbox               :: Bool     } deriving (Generic, Show) -$(deriveJSON-   defaultOptions{ fieldLabelModifier = camelTo2 '-' . drop 3 } ''Opt)+instance FromJSON Opt where+   parseJSON = withObject "Opt" $ \o ->+     Opt+       <$> o .:? "tab-stop" .!= optTabStop defaultOpts+       <*> o .:? "preserve-tabs" .!= optPreserveTabs defaultOpts+       <*> o .:? "standalone" .!= optStandalone defaultOpts+       <*> o .:? "from"+       <*> o .:? "to"+       <*> o .:? "table-of-contents" .!= optTableOfContents defaultOpts+       <*> o .:? "shift-heading-level-by" .!= optShiftHeadingLevelBy defaultOpts+       <*> o .:? "template"+       <*> o .:? "variables" .!= optVariables defaultOpts+       <*> o .:? "metadata" .!= optMetadata defaultOpts+       <*> o .:? "metadata-files" .!= optMetadataFiles defaultOpts+       <*> o .:? "output-file"+       <*> o .:? "input-files"+       <*> o .:? "number-sections" .!= optNumberSections defaultOpts+       <*> o .:? "number-offset" .!= optNumberOffset defaultOpts+       <*> o .:? "section-divs" .!= optSectionDivs defaultOpts+       <*> o .:? "incremental" .!= optIncremental defaultOpts+       <*> o .:? "self-contained" .!= optSelfContained defaultOpts+       <*> o .:? "embed-resources" .!= optEmbedResources defaultOpts+       <*> o .:? "html-q-tags" .!= optHtmlQTags defaultOpts+       <*> o .:? "highlight-style"+       <*> o .:? "syntax-definitions" .!= optSyntaxDefinitions defaultOpts+       <*> o .:? "top-level-division" .!= optTopLevelDivision defaultOpts+       <*> o .:? "html-math-method" .!= optHTMLMathMethod defaultOpts+       <*> o .:? "abbreviations"+       <*> o .:? "reference-doc"+       <*> o .:? "epub-subdirectory" .!= optEpubSubdirectory defaultOpts+       <*> o .:? "epub-metadata"+       <*> o .:? "epub-fonts" .!= optEpubFonts defaultOpts+       <*> o .:? "epub-chapter-level" .!= optEpubChapterLevel defaultOpts+       <*> o .:? "epub-cover-image"+       <*> o .:? "toc-depth" .!= optTOCDepth defaultOpts+       <*> o .:? "dump-args" .!= optDumpArgs defaultOpts+       <*> o .:? "ignore-args" .!= optIgnoreArgs defaultOpts+       <*> o .:? "verbosity" .!= optVerbosity defaultOpts+       <*> o .:? "trace" .!= optTrace defaultOpts+       <*> o .:? "log-file"+       <*> o .:? "fail-if-warnings" .!= optFailIfWarnings defaultOpts+       <*> o .:? "reference-links" .!= optReferenceLinks defaultOpts+       <*> o .:? "reference-location" .!= optReferenceLocation defaultOpts+       <*> o .:? "dpi" .!= optDpi defaultOpts+       <*> o .:? "wrap" .!= optWrap defaultOpts+       <*> o .:? "columns" .!= optColumns defaultOpts+       <*> o .:? "filters" .!= optFilters defaultOpts+       <*> o .:? "email-obfuscation" .!= optEmailObfuscation defaultOpts+       <*> o .:? "identifier-prefix" .!= optIdentifierPrefix defaultOpts+       <*> o .:? "strip-empty-paragraphs" .!= optStripEmptyParagraphs defaultOpts+       <*> o .:? "indented-code-classes" .!= optIndentedCodeClasses defaultOpts+       <*> o .:? "data-dir"+       <*> o .:? "cite-method" .!= optCiteMethod defaultOpts+       <*> o .:? "listings" .!= optListings defaultOpts+       <*> o .:? "pdf-engine"+       <*> o .:? "pdf-engine-opts" .!= optPdfEngineOpts defaultOpts+       <*> o .:? "slide-level"+       <*> o .:? "setext-headers" .!= optSetextHeaders defaultOpts+       <*> o .:? "ascii" .!= optAscii defaultOpts+       <*> o .:? "default-image-extension" .!= optDefaultImageExtension defaultOpts+       <*> o .:? "extract-media"+       <*> o .:? "track-changes" .!= optTrackChanges defaultOpts+       <*> o .:? "file-scope" .!= optFileScope defaultOpts+       <*> o .:? "title-prefix" .!= optTitlePrefix defaultOpts+       <*> o .:? "css" .!= optCss defaultOpts+       <*> o .:? "ipynb-output" .!= optIpynbOutput defaultOpts+       <*> o .:? "include-before-body" .!= optIncludeBeforeBody defaultOpts+       <*> o .:? "include-after-body" .!= optIncludeAfterBody defaultOpts+       <*> o .:? "include-in-header" .!= optIncludeInHeader defaultOpts+       <*> o .:? "resource-path" .!= optResourcePath defaultOpts+       <*> o .:? "request-headers" .!= optRequestHeaders defaultOpts+       <*> o .:? "no-check-certificate" .!= optNoCheckCertificate defaultOpts+       <*> o .:? "eol" .!= optEol defaultOpts+       <*> o .:? "strip-comments" .!= optStripComments defaultOpts+       <*> o .:? "csl"+       <*> o .:? "bibliography" .!= optBibliography defaultOpts+       <*> o .:? "citation-abbreviations"+       <*> o .:? "sandbox" .!= optSandbox defaultOpts++instance ToJSON Opt where+ toJSON = genericToJSON defaultOptions{+                                 fieldLabelModifier = camelTo2 '-' . drop 3,+                                 omitNothingFields = True }+  instance FromJSON (Opt -> Opt) where   parseJSON (Object m) =
src/Text/Pandoc/App/OutputSettings.hs view
@@ -37,8 +37,8 @@ import Text.Pandoc import Text.Pandoc.App.FormatHeuristics (formatFromFilePaths) import Text.Pandoc.App.Opt (Opt (..))-import Text.Pandoc.App.CommandLineOptions (engines, lookupHighlightStyle,-                                          setVariable)+import Text.Pandoc.App.CommandLineOptions (engines, setVariable)+import Text.Pandoc.Highlighting (lookupHighlightingStyle) import Text.Pandoc.Writers.Custom (writeCustom) import qualified Text.Pandoc.UTF8 as UTF8 @@ -128,7 +128,8 @@   syntaxMap <- foldM addSyntaxMap defaultSyntaxMap                      (optSyntaxDefinitions opts) -  hlStyle <- traverse (lookupHighlightStyle . T.unpack) $ optHighlightStyle opts+  hlStyle <- traverse (lookupHighlightingStyle . T.unpack) $+               optHighlightStyle opts    let setVariableM k v = return . setVariable k v 
src/Text/Pandoc/Class/IO.hs view
@@ -36,7 +36,7 @@  import Control.Monad.Except (throwError) import Control.Monad.IO.Class (MonadIO, liftIO)-import Data.ByteString.Base64 (decodeLenient)+import Data.ByteString.Base64.URL (decodeBase64Lenient) import Data.ByteString.Lazy (toChunks) import Data.Text (Text, pack, unpack) import Data.Time (TimeZone, UTCTime)@@ -125,7 +125,7 @@      let mime     = T.takeWhile (/=',') u''      let contents = UTF8.fromString $                      unEscapeString $ T.unpack $ T.drop 1 $ T.dropWhile (/=',') u''-     return (decodeLenient contents, Just mime)+     return (decodeBase64Lenient contents, Just mime)  | otherwise = do      let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v)      customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders
src/Text/Pandoc/Highlighting.hs view
@@ -30,6 +30,7 @@                                 , breezeDark                                 , haddock                                 , Style+                                , lookupHighlightingStyle                                 , fromListingsLanguage                                 , toListingsLanguage                                 ) where@@ -39,6 +40,10 @@ import qualified Data.Text as T import Skylighting import Text.Pandoc.Definition+import Text.Pandoc.Class (PandocMonad, readFileLazy)+import Text.Pandoc.Error (PandocError(..))+import Control.Monad.Except (throwError)+import System.FilePath (takeExtension) import Text.Pandoc.Shared (safeRead)  highlightingStyles :: [(T.Text, Style)]@@ -214,3 +219,21 @@ -- | Determine skylighting language name from listings language name. fromListingsLanguage :: T.Text -> Maybe T.Text fromListingsLanguage lang = M.lookup lang listingsToLangMap++-- | Lookup style from a name. If the name is a standard style,+-- load it; if it ends in ".theme", attempt to load a KDE theme+-- from the file path specified.+lookupHighlightingStyle :: PandocMonad m => String -> m Style+lookupHighlightingStyle s+  | takeExtension s == ".theme" = -- attempt to load KDE theme+    do contents <- readFileLazy s+       case parseTheme contents of+            Left _    -> throwError $ PandocOptionError $ T.pack $+                           "Could not read highlighting theme " ++ s+            Right sty -> return sty+  | otherwise =+  case lookup (T.toLower $ T.pack s) highlightingStyles of+       Just sty -> return sty+       Nothing  -> throwError $ PandocOptionError $ T.pack $+                      "Unknown highlight-style " ++ s+
src/Text/Pandoc/Lua/Module/Utils.hs view
@@ -25,7 +25,7 @@ import Data.Version (Version) import HsLua as Lua import HsLua.Module.Version (peekVersionFuzzy, pushVersion)-import Text.Pandoc.Citeproc (getReferences)+import Text.Pandoc.Citeproc (getReferences, processCitations) import Text.Pandoc.Definition import Text.Pandoc.Error (PandocError) import Text.Pandoc.Lua.Marshal.AST@@ -58,6 +58,16 @@             "blocks" ""       <#> opt (parameter (peekList peekInline) "list of inlines" "inline" "")       =#> functionResult pushInlines "list of inlines" ""++    , defun "citeproc"+      ### unPandocLua . processCitations+      <#> parameter peekPandoc "Pandoc" "doc" "document"+      =#> functionResult pushPandoc "Pandoc" "processed document"+      #?  T.unwords+          [ "Process the citations in the file, replacing them with "+          , "rendered citations and adding a bibliography. "+          , "See the manual section on citation rendering for details."+          ]      , defun "equals"       ### equal
src/Text/Pandoc/PDF.hs view
@@ -58,6 +58,7 @@ #endif import Data.List (isPrefixOf, find) import Text.Pandoc.Class (fillMediaBag, getVerbosity,+                          readFileLazy, readFileStrict, fileExists,                           report, extractMedia, PandocMonad) import Text.Pandoc.Logging @@ -335,21 +336,21 @@                 => Maybe String -> String                 -> m (Maybe ByteString, Maybe ByteString) getResultingPDF logFile pdfFile = do-    pdfExists <- liftIO $ doesFileExist pdfFile+    pdfExists <- fileExists pdfFile     pdf <- if pdfExists               -- We read PDF as a strict bytestring to make sure that the               -- temp directory is removed on Windows.               -- See https://github.com/jgm/pandoc/issues/1192.               then (Just . BL.fromChunks . (:[])) `fmap`-                   liftIO (BS.readFile pdfFile)+                   (readFileStrict pdfFile)               else return Nothing     -- Note that some things like Missing character warnings     -- appear in the log but not on stderr, so we prefer the log:     log' <- case logFile of               Just logFile' -> do-                logExists <- liftIO $ doesFileExist logFile'+                logExists <- fileExists logFile'                 if logExists-                  then liftIO $ Just <$> BL.readFile logFile'+                  then Just <$> readFileLazy logFile'                   else return Nothing               Nothing -> return Nothing     return (log', pdf)
src/Text/Pandoc/Readers/CommonMark.hs view
@@ -34,7 +34,10 @@                             runF, defaultParserState, option, many1, anyChar,                             Sources(..), ToSources(..), ParserT, Future,                             sourceName, sourceLine, incSourceLine)+import Text.Pandoc.Walk (walk) import qualified Data.Text as T+import qualified Data.Attoparsec.Text as A+import Control.Applicative ((<|>))  -- | Parse a CommonMark formatted string into a 'Pandoc' structure. readCommonMark :: (PandocMonad m, ToSources a)@@ -86,15 +89,41 @@      Right (Cm bls :: Cm () Blocks) -> return $ return $ B.toMetaValue bls  readCommonMarkBody :: PandocMonad m => ReaderOptions -> Sources -> [Tok] -> m Pandoc-readCommonMarkBody opts s toks-  | isEnabled Ext_sourcepos opts =-    case runIdentity (parseCommonmarkWith (specFor opts) toks) of-      Left err -> throwError $ PandocParsecError s err-      Right (Cm bls :: Cm SourceRange Blocks) -> return $ B.doc bls-  | otherwise =-    case runIdentity (parseCommonmarkWith (specFor opts) toks) of-      Left err -> throwError $ PandocParsecError s err-      Right (Cm bls :: Cm () Blocks) -> return $ B.doc bls+readCommonMarkBody opts s toks =+  (if readerStripComments opts+      then walk stripBlockComments . walk stripInlineComments+      else id) <$>+  if isEnabled Ext_sourcepos opts+     then case runIdentity (parseCommonmarkWith (specFor opts) toks) of+            Left err -> throwError $ PandocParsecError s err+            Right (Cm bls :: Cm SourceRange Blocks) -> return $ B.doc bls+     else case runIdentity (parseCommonmarkWith (specFor opts) toks) of+            Left err -> throwError $ PandocParsecError s err+            Right (Cm bls :: Cm () Blocks) -> return $ B.doc bls++stripBlockComments :: Block -> Block+stripBlockComments (RawBlock (B.Format "html") s) =+  RawBlock (B.Format "html") (removeComments s)+stripBlockComments x = x++stripInlineComments :: Inline -> Inline+stripInlineComments (RawInline (B.Format "html") s) =+  RawInline (B.Format "html") (removeComments s)+stripInlineComments x = x++removeComments :: Text -> Text+removeComments s =+  either (const s) id $ A.parseOnly pRemoveComments s+ where+  pRemoveComments = mconcat <$> A.many'+    ("" <$ (A.string "<!--" *> A.scan (0 :: Int) scanChar <* A.char '>') <|>+     (A.takeWhile1 (/= '<')) <|>+     (A.string "<"))+  scanChar st c =+    case c of+      '-' -> Just (st + 1)+      '>' | st >= 2 -> Nothing+      _ -> Just 0  specFor :: (Monad m, Typeable m, Typeable a,             Rangeable (Cm a Inlines), Rangeable (Cm a Blocks))
src/Text/Pandoc/Readers/FB2.hs view
@@ -25,7 +25,7 @@ module Text.Pandoc.Readers.FB2 ( readFB2 ) where import Control.Monad.Except (throwError) import Control.Monad.State.Strict-import Data.ByteString.Base64.Lazy+import Data.ByteString.Lazy.Base64.URL import Data.Functor import Data.List (intersperse) import qualified Data.Map as M@@ -202,7 +202,7 @@       report $ IgnoredElement "binary without content-type attribute"     (Just filename, contentType) ->       insertMedia (T.unpack filename) contentType-                    (decodeLenient+                    (decodeBase64Lenient                       (UTF8.fromTextLazy . TL.fromStrict . strContent $ e))  -- * Type parsers
src/Text/Pandoc/Readers/HTML.hs view
@@ -27,7 +27,7 @@ import Control.Monad (guard, msum, mzero, unless, void) import Control.Monad.Except (throwError, catchError) import Control.Monad.Reader (ask, asks, lift, local, runReaderT)-import Data.ByteString.Base64 (encode)+import Data.Text.Encoding.Base64.URL (encodeBase64) import Data.Char (isAlphaNum, isLetter) import Data.Default (Default (..), def) import Data.Foldable (for_)@@ -785,8 +785,7 @@   contents <- many (notFollowedBy (pCloses "svg") >> pAny)   closet <- TagClose "svg" <$ (pCloses "svg" <|> eof)   let rawText = T.strip $ renderTags' (opent : contents ++ [closet])-  let svgData = "data:image/svg+xml;base64," <>-                   UTF8.toText (encode $ UTF8.fromText rawText)+  let svgData = "data:image/svg+xml;base64," <> encodeBase64 rawText   return $ B.imageWith (ident,cls,[]) svgData mempty mempty  pCodeWithClass :: PandocMonad m => Text -> Text -> TagParser m Inlines
src/Text/Pandoc/Readers/Haddock.hs view
@@ -72,7 +72,17 @@     DocHeader h -> B.header (headerLevel h)                            (docHToInlines False $ headerTitle h)     DocUnorderedList items -> B.bulletList (map docHToBlocks items)+#if MIN_VERSION_haddock_library(1,11,0)+    DocOrderedList items ->+      B.orderedListWith attr (map (docHToBlocks . snd) items)+     where+      attr = (start, DefaultStyle, DefaultDelim)+      start = case items of+                [] -> 1+                ((n,_):_) -> n+#else     DocOrderedList items -> B.orderedList (map docHToBlocks items)+#endif     DocDefList items -> B.definitionList (map (\(d,t) ->                                (docHToInlines False d,                                 [consolidatePlains $ docHToBlocks t])) items)
src/Text/Pandoc/Readers/Org/Blocks.hs view
@@ -191,6 +191,7 @@       "quote"   -> parseBlockLines (fmap B.blockQuote)       "verse"   -> verseBlock       "src"     -> codeBlock blockAttrs+      "abstract"-> metadataBlock       _         -> parseBlockLines $                    let (ident, classes, kv) = attrFromBlockAttributes blockAttrs                    in fmap $ B.divWith (ident, classes ++ [blkType], kv)@@ -289,6 +290,16 @@                       else B.str $ T.map (const '\160') initialSpaces      line <- parseFromString inlines (indentedLine <> "\n")      return (trimInlinesF $ pure nbspIndent <> line)++-- | Parses an environment of the given name and adds the result to the document+-- metadata under a key of the same name.+metadataBlock :: PandocMonad m => Text -> OrgParser m (F Blocks)+metadataBlock blockType = try $ do+  content <- parseBlockLines id blockType+  meta'   <- orgStateMeta <$> getState+  updateState $ \st ->+    st { orgStateMeta = B.setMeta blockType <$> content <*> meta' }+  return mempty  -- | Read a code block and the associated results block if present.  Which of -- the blocks is included in the output is determined using the "exports"
src/Text/Pandoc/SelfContained.hs view
@@ -19,7 +19,7 @@ import Control.Applicative ((<|>)) import Control.Monad.Trans (lift) import Data.ByteString (ByteString)-import Data.ByteString.Base64+import Data.ByteString.Base64.URL (encodeBase64) import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy as L import qualified Data.Text as T@@ -45,7 +45,7 @@ makeDataURI (mime, raw) =   if textual      then "data:" <> mime' <> "," <> T.pack (escapeURIString isOk (toString raw))-     else "data:" <> mime' <> ";base64," <> toText (encode raw)+     else "data:" <> mime' <> ";base64," <> encodeBase64 raw   where textual = "text/" `T.isPrefixOf` mime         mime' = if textual && T.any (== ';') mime                    then mime <> ";charset=utf-8"
+ src/Text/Pandoc/Server.hs view
@@ -0,0 +1,357 @@+{-# LANGUAGE DataKinds       #-}+{-# LANGUAGE TypeOperators   #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Pandoc.Server+    ( app+    , ServerOpts(..)+    , Params(..)+    , Blob(..)+    , parseServerOpts+    ) where++import Data.Aeson+import Network.Wai+import Servant+import Text.DocTemplates as DocTemplates+import Text.Pandoc+import Text.Pandoc.Citeproc (processCitations)+import Text.Pandoc.Highlighting (lookupHighlightingStyle)+import qualified Text.Pandoc.UTF8 as UTF8+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TLE+import Data.Maybe (fromMaybe)+import Data.Char (isAlphaNum)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BL+import Data.ByteString.Base64 (decodeBase64, encodeBase64)+import Data.Default+import Control.Monad (when, foldM)+import qualified Data.Set as Set+import Skylighting (defaultSyntaxMap)+import qualified Data.Map as M+import System.Console.GetOpt+import System.Environment (getArgs, getProgName)+import qualified Control.Exception as E+import Text.Pandoc.Shared (safeStrRead, headerShift, filterIpynbOutput,+                           eastAsianLineBreakFilter, stripEmptyParagraphs)+import Text.Pandoc.App.Opt ( IpynbOutput (..), Opt(..), defaultOpts )+import Text.Pandoc.Filter (Filter(..))+import Text.Pandoc.Builder (setMeta)+import Text.Pandoc.SelfContained (makeSelfContained)+import System.Exit++data ServerOpts =+  ServerOpts+    { serverPort    :: Int+    , serverTimeout :: Int }+  deriving (Show)++defaultServerOpts :: ServerOpts+defaultServerOpts = ServerOpts { serverPort = 3030, serverTimeout = 2 }++cliOptions :: [OptDescr (ServerOpts -> IO ServerOpts)]+cliOptions =+  [ Option ['p'] ["port"]+      (ReqArg (\s opts -> case safeStrRead s of+                            Just i -> return opts{ serverPort = i }+                            Nothing ->+                              E.throwIO $ PandocOptionError $ T.pack+                                s <> " is not a number") "NUMBER")+      "port number"+  , Option ['t'] ["timeout"]+      (ReqArg (\s opts -> case safeStrRead s of+                            Just i -> return opts{ serverTimeout = i }+                            Nothing ->+                              E.throwIO $ PandocOptionError $ T.pack+                                s <> " is not a number") "NUMBER")+      "timeout (seconds)"++  , Option ['h'] ["help"]+      (NoArg (\_ -> do+        prg <- getProgName+        let header = "Usage: " <> prg <> " [OPTION...]"+        putStrLn $ usageInfo header cliOptions+        exitWith ExitSuccess))+      "help message"++  , Option ['v'] ["version"]+      (NoArg (\_ -> do+        prg <- getProgName+        putStrLn $ prg <> " " <> T.unpack pandocVersion+        exitWith ExitSuccess))+      "version info"++  ]++parseServerOpts :: IO ServerOpts+parseServerOpts = do+  args <- getArgs+  let handleUnknownOpt x = "Unknown option: " <> x+  case getOpt' Permute cliOptions args of+    (os, ns, unrecognizedOpts, es) -> do+      when (not (null es) || not (null unrecognizedOpts)) $+        E.throwIO $ PandocOptionError $ T.pack $+          concat es ++ unlines (map handleUnknownOpt unrecognizedOpts) +++          ("Try --help for more information.")+      when (not (null ns)) $+        E.throwIO $ PandocOptionError $ T.pack $+                     "Unknown arguments: " <> unwords ns+      foldM (flip ($)) defaultServerOpts os++newtype Blob = Blob BL.ByteString+  deriving (Show, Eq)++instance ToJSON Blob where+  toJSON (Blob bs) = toJSON (encodeBase64 $ BL.toStrict bs)++instance FromJSON Blob where+ parseJSON = withText "Blob" $ \t -> do+   let inp = UTF8.fromText t+   case decodeBase64 inp of+        Right bs -> return $ Blob $ BL.fromStrict bs+        Left _ -> -- treat as regular text+                    return $ Blob $ BL.fromStrict inp++-- This is the data to be supplied by the JSON payload+-- of requests.  Maybe values may be omitted and will be+-- given default values.+data Params = Params+  { options               :: Opt+  , text                  :: Text+  , files                 :: Maybe (M.Map FilePath Blob)+  } deriving (Show)++instance Default Params where+  def = Params+    { options = defaultOpts+    , text = mempty+    , files = Nothing+    }++-- Automatically derive code to convert to/from JSON.+instance FromJSON Params where+ parseJSON = withObject "Params" $ \o ->+   Params+     <$> parseJSON (Object o)+     <*> o .: "text"+     <*> o .:? "files"+++-- This is the API.  The "/convert" endpoint takes a request body+-- consisting of a JSON-encoded Params structure and responds to+-- Get requests with either plain text or JSON, depending on the+-- Accept header.+type API =+  ReqBody '[JSON] Params :> Post '[PlainText, JSON] Text+  :<|>+  ReqBody '[JSON] Params :> Post '[OctetStream] BS.ByteString+  :<|>+  "batch" :> ReqBody '[JSON] [Params] :> Post '[JSON] [Text]+  :<|>+  "babelmark" :> QueryParam' '[Required] "text" Text :> QueryParam "from" Text :> QueryParam "to" Text :> QueryFlag "standalone" :> Get '[JSON] Value+  :<|>+  "version" :> Get '[PlainText, JSON] Text++app :: Application+app = serve api server++api :: Proxy API+api = Proxy++server :: Server API+server = convert+    :<|> convertBytes+    :<|> mapM convert+    :<|> babelmark  -- for babelmark which expects {"html": "", "version": ""}+    :<|> pure pandocVersion+ where+  babelmark text' from' to' standalone' = do+    res <- convert def{ text = text',+                        options = defaultOpts{+                          optFrom = from',+                          optTo = to',+                          optStandalone = standalone' }+                      }+    return $ toJSON $ object [ "html" .= res, "version" .= pandocVersion ]++  -- We use runPure for the pandoc conversions, which ensures that+  -- they will do no IO.  This makes the server safe to use.  However,+  -- it will mean that features requiring IO, like RST includes, will not work.+  -- Changing this to+  --    handleErr =<< liftIO (runIO (convert' params))+  -- will allow the IO operations.+  convert params = handleErr $+    runPure (convert' id (encodeBase64 . BL.toStrict) params)++  convertBytes params = handleErr $+    runPure (convert' UTF8.fromText BL.toStrict params)++  convert' :: (Text -> a) -> (BL.ByteString -> a) -> Params -> PandocPure a+  convert' textHandler bsHandler params = do+    curtime <- getCurrentTime+    -- put files params in ersatz file system+    let addFile :: FilePath -> Blob -> FileTree -> FileTree+        addFile fp (Blob lbs) =+          insertInFileTree fp FileInfo{ infoFileMTime = curtime+                                      , infoFileContents = BL.toStrict lbs }+    case files params of+      Nothing -> return ()+      Just fs -> do+        let filetree = M.foldrWithKey addFile mempty fs+        modifyPureState $ \st -> st{ stFiles = filetree }++    let opts = options params+    let readerFormat = fromMaybe "markdown" $ optFrom opts+    let writerFormat = fromMaybe "html" $ optTo opts+    (readerSpec, readerExts) <- getReader readerFormat+    (writerSpec, writerExts) <- getWriter writerFormat++    let isStandalone = optStandalone opts+    let toformat = T.toLower $ T.takeWhile isAlphaNum $ writerFormat+    hlStyle <- traverse (lookupHighlightingStyle . T.unpack)+                  $ optHighlightStyle opts++    mbTemplate <- if isStandalone+                     then case optTemplate opts of+                            Nothing -> Just <$>+                              compileDefaultTemplate toformat+                            Just t  -> Just <$>+                              compileCustomTemplate toformat t+                     else return Nothing++    abbrevs <- Set.fromList . filter (not . T.null) . T.lines . UTF8.toText <$>+                 case optAbbreviations opts of+                      Nothing -> readDataFile "abbreviations"+                      Just f  -> readFileStrict f++    let readeropts = def{ readerExtensions = readerExts+                        , readerStandalone = isStandalone+                        , readerTabStop = optTabStop opts+                        , readerIndentedCodeClasses =+                            optIndentedCodeClasses opts+                        , readerAbbreviations = abbrevs+                        , readerDefaultImageExtension =+                            optDefaultImageExtension opts+                        , readerTrackChanges = optTrackChanges opts+                        , readerStripComments = optStripComments opts+                        }+    let writeropts =+          def{ writerExtensions = writerExts+             , writerTabStop = optTabStop opts+             , writerWrapText = optWrap opts+             , writerColumns = optColumns opts+             , writerTemplate = mbTemplate+             , writerSyntaxMap = defaultSyntaxMap+             , writerVariables = optVariables opts+             , writerTableOfContents = optTableOfContents opts+             , writerIncremental = optIncremental opts+             , writerHTMLMathMethod = optHTMLMathMethod opts+             , writerNumberSections = optNumberSections opts+             , writerNumberOffset = optNumberOffset opts+             , writerSectionDivs = optSectionDivs opts+             , writerReferenceLinks = optReferenceLinks opts+             , writerDpi = optDpi opts+             , writerEmailObfuscation = optEmailObfuscation opts+             , writerIdentifierPrefix = optIdentifierPrefix opts+             , writerCiteMethod = optCiteMethod opts+             , writerHtmlQTags = optHtmlQTags opts+             , writerSlideLevel = optSlideLevel opts+             , writerTopLevelDivision = optTopLevelDivision opts+             , writerListings = optListings opts+             , writerHighlightStyle = hlStyle+             , writerSetextHeaders = optSetextHeaders opts+             , writerEpubSubdirectory = T.pack $ optEpubSubdirectory opts+             , writerEpubMetadata = T.pack <$> optEpubMetadata opts+             , writerEpubFonts = optEpubFonts opts+             , writerEpubChapterLevel = optEpubChapterLevel opts+             , writerTOCDepth = optTOCDepth opts+             , writerReferenceDoc = optReferenceDoc opts+             , writerReferenceLocation = optReferenceLocation opts+             , writerPreferAscii = optAscii opts+             }+    let reader = case readerSpec of+                TextReader r -> r readeropts+                ByteStringReader r -> \t -> do+                  let eitherbs = decodeBase64 $ UTF8.fromText t+                  case eitherbs of+                    Left errt -> throwError $ PandocSomeError errt+                    Right bs -> r readeropts $ BL.fromStrict bs+    let writer = case writerSpec of+                TextWriter w ->+                  fmap textHandler .+                  (\d -> w writeropts d >>=+                         if optEmbedResources opts && htmlFormat (optTo opts)+                            then makeSelfContained+                            else return)+                ByteStringWriter w -> fmap bsHandler . w writeropts++    let transforms :: Pandoc -> Pandoc+        transforms = (case optShiftHeadingLevelBy opts of+                        0             -> id+                        x             -> headerShift x) .+                   (case optStripEmptyParagraphs opts of+                        True          -> stripEmptyParagraphs+                        False         -> id) .+                   (if extensionEnabled Ext_east_asian_line_breaks+                          readerExts &&+                       not (extensionEnabled Ext_east_asian_line_breaks+                              writerExts &&+                            optWrap opts == WrapPreserve)+                       then eastAsianLineBreakFilter+                       else id) .+                   (case optIpynbOutput opts of+                     IpynbOutputAll  -> id+                     IpynbOutputNone -> filterIpynbOutput Nothing+                     IpynbOutputBest -> filterIpynbOutput (Just $+                       case optTo opts of+                            Just "latex"  -> Format "latex"+                            Just "beamer" -> Format "latex"+                            Nothing       -> Format "html"+                            Just f+                              | htmlFormat (optTo opts) -> Format "html"+                              | otherwise -> Format f))++    let meta =   (case optBibliography opts of+                   [] -> id+                   fs -> setMeta "bibliography" (MetaList+                            (map (MetaString . T.pack) fs))) .+                 maybe id (setMeta "csl" . MetaString . T.pack)+                   (optCSL opts) .+                 maybe id (setMeta "citation-abbreviations" . MetaString .+                              T.pack)+                   (optCitationAbbreviations opts) $+                 optMetadata opts++    let addMetadata m' (Pandoc m bs) = Pandoc (m <> m') bs++    let hasCiteprocFilter [] = False+        hasCiteprocFilter (CiteprocFilter:_) = True+        hasCiteprocFilter (_:xs) = hasCiteprocFilter xs++    reader (text params) >>=+      return . transforms . addMetadata meta >>=+      (if hasCiteprocFilter (optFilters opts)+          then processCitations+          else return) >>=+      writer++  htmlFormat :: Maybe Text -> Bool+  htmlFormat Nothing = True+  htmlFormat (Just f) =+    any (`T.isPrefixOf` f)+      ["html","html4","html5","s5","slidy", "slideous","dzslides","revealjs"]++  handleErr (Right t) = return t+  handleErr (Left err) = throwError $+    err500 { errBody = TLE.encodeUtf8 $ TL.fromStrict $ renderError err }++  compileCustomTemplate toformat t = do+    res <- runWithPartials $ compileTemplate ("custom." <> T.unpack toformat)+               (T.pack t)+    case res of+      Left e -> throwError $ PandocTemplateError (T.pack e)+      Right tpl -> return tpl+
src/Text/Pandoc/Writers/FB2.hs view
@@ -21,14 +21,13 @@ import Control.Monad (zipWithM) import Control.Monad.Except (catchError, throwError) import Control.Monad.State.Strict (StateT, evalStateT, get, gets, lift, liftM, modify)-import Data.ByteString.Base64 (encode)+import Data.ByteString.Base64.URL (encodeBase64) import Data.Char (isAscii, isControl, isSpace) import Data.Either (lefts, rights) import Data.List (intercalate) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import qualified Data.Text.Encoding as TE import Text.Pandoc.Network.HTTP (urlEncode) import Text.Pandoc.XML.Light as X @@ -237,7 +236,7 @@                                report $ CouldNotDetermineMimeType link                                return Nothing                              Just mime -> return $ Just (mime,-                                                      TE.decodeUtf8 $ encode bs))+                                                        encodeBase64 bs))                     (\e ->                        do report $ CouldNotFetchResource link (tshow e)                           return Nothing)
src/Text/Pandoc/Writers/HTML.hs view
@@ -876,7 +876,7 @@   let isCslBibEntry = "csl-entry" `elem` classes   let kvs = [(k,v) | (k,v) <- kvs'                    , k /= "width" || "column" `notElem` classes] ++-            [("style", "width:" <> w <> ";") | "column" `elem` classes+            [("style", "flex:" <> w <> ";")  | "column" `elem` classes                                              , ("width", w) <- kvs'] ++             [("role", "doc-bibliography") | isCslBibBody && html5] ++             [("role", "doc-biblioentry") | isCslBibEntry && html5]
src/Text/Pandoc/Writers/LaTeX/Table.hs view
@@ -33,6 +33,7 @@ import Text.Pandoc.Writers.LaTeX.Types   ( LW, WriterState (stBeamer, stExternalNotes, stInMinipage, stMultiRow                     , stNotes, stTable) )+import Text.Pandoc.Writers.LaTeX.Util (labelFor) import Text.Printf (printf) import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Writers.AnnotatedTable as Ann@@ -43,8 +44,8 @@              -> Ann.Table              -> LW m (Doc Text) tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do-  let (Ann.Table _attr caption specs thead tbodies tfoot) = tbl-  CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption+  let (Ann.Table (ident, _, _) caption specs thead tbodies tfoot) = tbl+  CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption ident   let removeNote (Note _) = Span ("", [], []) []       removeNote x        = x   let colCount = ColumnCount $ length specs@@ -144,16 +145,20 @@ captionToLaTeX :: PandocMonad m                => ([Inline] -> LW m (Doc Text))                -> Caption+               -> Text     -- ^ table identifier (label)                -> LW m CaptionDocs-captionToLaTeX inlnsToLaTeX (Caption _maybeShort longCaption) = do+captionToLaTeX inlnsToLaTeX (Caption _maybeShort longCaption) ident = do   let caption = blocksToInlines longCaption-  (captionText, captForLof, captNotes) <- getCaption inlnsToLaTeX False caption+  (captionText, captForLot, captNotes) <- getCaption inlnsToLaTeX False caption+  label <- labelFor ident   return $ CaptionDocs     { captionNotes = captNotes-    , captionCommand = if isEmpty captionText+    , captionCommand = if isEmpty captionText && isEmpty label                        then empty-                       else "\\caption" <> captForLof <>-                            braces captionText <> "\\tabularnewline"+                       else "\\caption" <> captForLot <>+                            braces captionText+                            <> label+                            <> "\\tabularnewline"     }  type BlocksWriter m = [Block] -> LW m (Doc Text)@@ -330,20 +335,15 @@       width = sum $ NonEmpty.map toWidth colWidths        -- no column separators at beginning of first and end of last column.-      numseps = (case colnum + 1 of-                   1 -> 0  -- Not sure why this case is needed (tarleb)-                   _ -> -- the final cell has only one tabcolsep-                        if colnum + colspan == numcols-                        then 1-                        else 2) :: Int       skipColSep = "@{}" :: String   in T.pack $-     printf "%s>{%s\\arraybackslash}p{%0.4f\\columnwidth - %d\\tabcolsep}%s"+     printf "%s>{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"             (if colnum == 0 then skipColSep else "")             (T.unpack (alignCommand align))+            (2 * (numcols - 1))             width-            numseps-            (if colnum + colspan == numcols then skipColSep else "")+            (2 * (colspan - 1))+            (if colnum + colspan >= numcols then skipColSep else "")  -- | Perform a conversion, assuming that the context is a minipage. inMinipage :: Monad m => LW m a -> LW m a
src/Text/Pandoc/Writers/LaTeX/Util.hs view
@@ -120,7 +120,7 @@          '>' -> emitcseq "\\textgreater"          '[' -> emits "{[}"  -- to avoid interpretation as          ']' -> emits "{]}"  -- optional arguments-         '\'' | ctx == CodeString -> emitcseq "\\textquotesingle"+         '\'' -> emitcseq "\\textquotesingle"          '\160' -> emits "~"          '\x200B' -> emits "\\hspace{0pt}"  -- zero-width space          '\x202F' -> emits "\\,"
stack.yaml view
@@ -1,6 +1,5 @@ flags:   pandoc:-    trypandoc: false     embed_data_files: true   QuickCheck:     old-random: false@@ -13,7 +12,7 @@ - skylighting-format-latex-0.1 - skylighting-format-blaze-html-0.1 - emojis-0.1.2-- gridtables-0.0.2.0+- gridtables-0.0.3.0 - lpeg-1.0.3 - hslua-2.2.1 - hslua-aeson-2.2.1@@ -37,7 +36,7 @@ - unicode-data-0.3.0 - commonmark-pandoc-0.2.1.2 - ipynb-0.2-- pandoc-types-1.22.2+- pandoc-types-1.22.2.1 - commonmark-0.2.2 - commonmark-extensions-0.2.3.2 - doclayout-0.4
test/command/1710.md view
@@ -19,17 +19,17 @@ <section id="slide-one" class="slide level1"> <h1>Slide one</h1> <div class="columns">-<div class="column" style="width:40%;">+<div class="column" style="flex:40%;"> <ul> <li>a</li> <li>b</li> </ul>-</div><div class="column" style="width:40%;">+</div><div class="column" style="flex:40%;"> <ul> <li>c</li> <li>d</li> </ul>-</div><div class="column" style="width:10%;">+</div><div class="column" style="flex:10%;"> <p>ok</p> </div> </div>
+ test/command/8204.md view
@@ -0,0 +1,39 @@+Include abstract in Org output.+```+% pandoc --to=org --standalone+---+abstract: |+  This is an *abstract*.++  It has multiple paragraphs.+---+^D+#+begin_abstract+This is an /abstract/.++It has multiple paragraphs.++#+end_abstract+```++Parse abstract environment as *abstract* metadata field.+```+% pandoc --from=org --to=markdown --standalone+#+begin_abstract++This is an /abstract/.++It has multiple paragraphs.+#+end_abstract++Main text+^D+---+abstract: |+  This is an *abstract*.++  It has multiple paragraphs.+---++Main text+```
+ test/command/8216.md view
@@ -0,0 +1,51 @@+Misaligned separators in grid table+```+% pandoc -f markdown -t html+: Grid Table+++-----------------+:-:++|Some text        |[text]{.class1 .class2 .class3}|++-----------------+---++|Some text        |[text]{.class1 .class2 .class3}|++-----------------+---++|Some text        |[text]{.class1 .class2 .class3}|++-----------------+---++^D+<table style="width:69%;">+<caption>Grid Table</caption>+<colgroup>+<col style="width: 25%" />+<col style="width: 44%" />+</colgroup>+<tbody>+<tr class="odd">+<td>Some text</td>+<td><span class="class1 class2 class3">text</span></td>+</tr>+<tr class="even">+<td>Some text</td>+<td><span class="class1 class2 class3">text</span></td>+</tr>+<tr class="odd">+<td>Some text</td>+<td><span class="class1 class2 class3">text</span></td>+</tr>+</tbody>+</table>+```++Missing cell++```+% pandoc -f markdown -t gfm++------++| text |++------+---++| text | 1 |++------+---++^D+|      |     |+|------|-----|+| text |     |+| text | 1   |+```
+ test/command/8219.md view
@@ -0,0 +1,14 @@+```+% pandoc -f html -t latex+<table id="test">+  <tr><td>one</td><td>two</td></tr>+</table>+^D+\begin{longtable}[]{@{}ll@{}}+\caption{}\label{test}\tabularnewline+\toprule()+\endhead+one & two \\+\bottomrule()+\end{longtable}+```
test/tables/nordics.latex view
@@ -3,7 +3,7 @@   >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}   >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}   >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}@{}}-\caption{States belonging to the \emph{Nordics.}}\tabularnewline+\caption{States belonging to the \emph{Nordics.}}\label{nordics}\tabularnewline \toprule() \begin{minipage}[b]{\linewidth}\centering Name
test/tables/planets.latex view
@@ -1,20 +1,20 @@ \begin{longtable}[]{@{}cclrrrrrrrrl@{}} \caption{Data about the planets of our solar system.}\tabularnewline \toprule()-\multicolumn{2}{@{}>{\centering\arraybackslash}p{0.0000\columnwidth - 0\tabcolsep}}{%+\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{% } & Name & Mass (10\^{}24kg) & Diameter (km) & Density (kg/m\^{}3) & Gravity (m/s\^{}2) & Length of day (hours) & Distance from Sun (10\^{}6km) & Mean temperature (C) & Number of moons & Notes \\ \midrule() \endfirsthead \toprule()-\multicolumn{2}{@{}>{\centering\arraybackslash}p{0.0000\columnwidth - 0\tabcolsep}}{%+\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{% } & Name & Mass (10\^{}24kg) & Diameter (km) & Density (kg/m\^{}3) & Gravity (m/s\^{}2) & Length of day (hours) & Distance from Sun (10\^{}6km) & Mean temperature (C) & Number of moons & Notes \\ \midrule() \endhead-\multicolumn{2}{@{}>{\centering\arraybackslash}p{0.0000\columnwidth - 0\tabcolsep}}{%+\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{% \multirow{4}{*}{Terrestrial planets}} & Mercury & 0.330 & 4,879 & 5427 & 3.7 & 4222.6 & 57.9 & 167 & 0 & Closest to the Sun \\ & & Venus & 4.87 & 12,104 & 5243 & 8.9 & 2802.0 & 108.2 & 464 & 0 & \\@@ -27,7 +27,7 @@ & \multirow{2}{*}{Ice giants} & Uranus & 86.8 & 51,118 & 1271 & 8.7 & 17.2 & 2872.5 & -195 & 27 & \\ & & Neptune & 102 & 49,528 & 1638 & 11.0 & 16.1 & 4495.1 & -200 & 14 & \\-\multicolumn{2}{@{}>{\centering\arraybackslash}p{0.0000\columnwidth - 0\tabcolsep}}{%+\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{% Dwarf planets} & Pluto & 0.0146 & 2,370 & 2095 & 0.7 & 153.3 & 5906.4 & -225 & 5 & Declassified as a planet in 2006. \\ \bottomrule()
test/tables/students.latex view
@@ -1,7 +1,7 @@ \begin{longtable}[]{@{}   >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}   >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}@{}}-\caption{List of Students}\tabularnewline+\caption{List of Students}\label{students}\tabularnewline \toprule() \begin{minipage}[b]{\linewidth}\centering Student ID@@ -18,15 +18,15 @@ \end{minipage} \\ \midrule() \endhead-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{1.0000\columnwidth - 0\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Computer Science} \\ 3741255 & Jones, Martha \\ 4077830 & Pierce, Benjamin \\ 5151701 & Kirk, James \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{1.0000\columnwidth - 0\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Russian Literature} \\ 3971244 & Nim, Victor \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{1.0000\columnwidth - 0\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Astrophysics} \\ 4100332 & Petrov, Alexandra \\ 4100332 & Toyota, Hiroko \\
− trypandoc/Makefile
@@ -1,14 +0,0 @@-CGIBIN=/home/website/cgi-bin-TRYPANDOC=/home/website/pandoc.org/try/-CGI=${CGIBIN}/trypandoc-BIN=/home/jgm/.cabal/bin/trypandoc--install: ${CGI} ${TRYPANDOC}/index.html--${TRYPANDOC}/%: %-	cp $< $@ && chown website:www-data $@ && chmod a+r $@--${CGI}: ${BIN}-	cp $< $@ && chown website:www-data $@ && chmod a+rx $@--.PHONY: install
trypandoc/index.html view
@@ -9,94 +9,55 @@        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>        <![endif]-->-  <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>-  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">-  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>-  <script>-"use strict";-(function($) { // https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-	$.QueryString = (function(a) {-	    if (a == "") return {};-	    var b = {};-	    for (var i = 0; i < a.length; ++i)-	    {-		var p=a[i].split('=');-		if (p.length != 2) continue;-		b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));-	    }-	    return b;-        })(window.location.search.substr(1).split('&'))-})(jQuery);--function newpage() {-  var input = $("#text").val();-  var from = $("#from").val();-  var to = $("#to").val();-  var standalone = $("#standalone").is(':checked') ? "1" : "0";-  var href = window.location.href;-  window.location.href = href.replace(/([?].*)?$/,"?" + $.param({text: input, from: from, to: to, standalone: standalone}));-};--$(document).ready(function() {-    var text = $.QueryString["text"];-    $("#text").val(text);-    var from = $.QueryString["from"] || "markdown";-    $("#from").val(from);-    var to = $.QueryString["to"] || "html";-    $("#to").val(to);-    var standalone = ($.QueryString["standalone"] === "1") ? "1" : "0";-    $("#standalone").prop('checked', (standalone === "1"));-    if (text && text != "") {-       $.getJSON("/cgi-bin/trypandoc", { from: from, to: to, text: text, standalone: standalone },-         function(res) {-          $("#results").text(res.html);-          $("#version").text(res.version);-          var commandString = "pandoc"-            + ((standalone === "1") ? " --standalone" : "")-            + " --from " + from + " --to " + to;-          $("#command").text(commandString);-         });-    };-    $("#convert").click(newpage);-    $("#from").change(newpage);-    $("#to").change(newpage);-});-  </script>   <style>-    h1 { margin-bottom: 1em; }-    body { margin: auto; }-    textarea { height: auto; width: 100%; font-family: monospace; margin-top: 15px; }+    body { margin: auto; font-family: sans-serif; font-size: 10pt; color: #555; }+    #command { min-width: 26em; background-color: #555; color: #eee; border-radius: 9pt; margin: 6pt; padding: 6pt; }+    h1 { margin-bottom: 1em; font-size: 166%; margin: 0; padding: 6pt; }+    h1 a { text-decoration: none; color: inherit; }+    label { font-weight: 600; }+    textarea { height: auto; font-family: monospace; font-size: 10pt; margin-top: 15px; min-height: 65vh; width: 44vw; }     div.alert { margin: 1em; }-    h3 { margin-top: 0; margin-bottom: 0; padding: 0; font-size: 100%; }-    pre#results { width: 100%; margin-top: 15px; }+    pre#results { width: 100%; margin-top: 15px; min-height: 65vh; width: 44vw; }     footer { color: #555; text-align: center; margin: 1em; }     p.version { color: #555; }+    .container { margin: 12px; }+    .row { display: flex; flex-wrap: nowrap; justify-content: space-between; }+    #frompane { flex: 1; padding: 1em; }+    #topane { flex: 1; padding: 1em;  }+    #command { font-family: monospace; padding: 1em; }     button#convert { vertical-align: bottom; }     pre#command { margin-top: 1em; background-color: transparent; border: none; }   </style> </head> <body>-<div class="container-fluid">+<div class="container">   <div class="row">-    <div class="col-md-6">-      <h1>Try pandoc!</h1>+    <div id="title">+    <h1>Try <a href="https://pandoc.org">pandoc</a>!</h1>     </div>-    <div class="col-md-6">+    <div id="command">       <pre id="command"></pre>     </div>   </div>   <div class="row">-    <div class="col-md-6">-      <button class="btn btn-primary btn-xs" id="convert">Convert</button>+    <div id="frompane">+      <button id="convert">Convert</button>       &nbsp;       <label for="from">       from       </label>       <select id="from">+        <option value="bibtex">BibTeX</option>+        <option value="biblatex">BibLaTeX</option>         <option value="commonmark">CommonMark</option>+        <option value="commonmark_x">CommonMark (extended)</option>         <option value="creole">Creole</option>+        <option value="csljson">CSL JSON</option>+        <option value="csv">CSV</option>         <option value="docbook">DocBook</option>         <option value="dokuwiki">DokuWiki</option>+	<option value="docx">Docx (Word)</option>+	<option value="epub">EPUB</option>         <option value="fb2">FB2</option>         <option value="haddock">Haddock markup</option>         <option value="html">HTML</option>@@ -113,37 +74,53 @@         <option value="markdown_mmd">MultiMarkdown</option>         <option value="muse">Muse</option>         <option value="native">Native (Pandoc AST)</option>+	<option value="odt">ODT</option>         <option value="opml">OPML</option>         <option value="org">Org Mode</option>+        <option value="ris">RIS</option>         <option value="rst">reStructuredText</option>         <option value="t2t">Txt2Tags</option>         <option value="textile">Textile</option>         <option value="tikiwiki">TikiWiki</option>         <option value="twiki">TWiki</option>         <option value="vimwiki">Vimwiki</option>-      </select>-      <input type="checkbox" id="standalone" name="standalone">-      <label for="standalone">Generate standalone document-        <a href="https://pandoc.org/MANUAL.html#option--standalone" target="_blank">(?)</a>-      </label>+      </select><br/>+      <label for="loadfile">Load from file</label>+      <input id="loadfile" type="file" />       <br/>-      <textarea id="text" maxlength="3000" rows="15"></textarea>+      <textarea id="text" rows="15"></textarea>+      <br/>+      <label for="examples">+      Examples+      </label>+      <select id="examples">+        <option value="" selected disabled>Select an example</option>+        <option value="https://pandoc.org/try/?text=%40BOOK%7BWurm2011-ho%2C%0A++title+++++%3D+%22%7BSubstanz+und+Qualität+%3A+Ein+Beitrag+zur+Interpretation+der%0A+++++++++++++++plotinischen+Traktate+VI%2C1%2C+2+und+3%7D%22%2C%0A++author++++%3D+%22Wurm%2C+Klaus%22%2C%0A++publisher+%3D+%22De+Gruyter%22%2C%0A++series++++%3D+%22Quellen+und+Studien+zur+Philosophie%22%2C%0A++edition+++%3D+%22Reprint+2011%22%2C%0A++year++++++%3D++2011%2C%0A++address+++%3D+%22Berlin%22%2C%0A++keywords++%3D+%22%21%21%21+Plotinus+translation%22%2C%0A++language++%3D+%22de%22%0A%7D%0A&from=bibtex&to=csljson&standalone=false">BibTeX to CSL JSON</option>+        <option value="https://pandoc.org/try/?text=---%0Areferences%3A%0A-+author%3A%0A++-+family%3A+Salam%0A++++given%3A+Abdus%0A++container-title%3A+%22Elementary+particle+theory%3A+Relativistic+groups+and%0A++++analyticity.+Proceedings+of+the+eighth+Nobel+symposium%22%0A++editor%3A%0A++-+family%3A+Svartholm%0A++++given%3A+Nils%0A++event-date%3A+1968-05-19%2F1968-05-25%0A++event-place%3A+Aspenäsgarden%2C+Lerum%0A++id%3A+salam%0A++issued%3A+1968%0A++page%3A+367-377%0A++publisher%3A+Almquist+%26+Wiksell%0A++publisher-place%3A+Stockholm%0A++title%3A+Weak+and+electromagnetic+interactions%0A++type%3A+paper-conference%0A---%0A%0A%40salam+%5Bp.+370%5D+says+some+interesting+things.%0A&from=markdown&to=man&standalone=false&citeproc=true">Markdown to man with citation</option>+        <option value="https://pandoc.org/try/?text=%3D%3D+Definition+%3D%3D%0AAlthough+seemingly+different%2C+the+various+approaches+to+defining+tensors+describe+the+same+geometric+concept+using+different+language+and+at+different+levels+of+abstraction.%0A%0A%3D%3D%3D+As+multidimensional+arrays+%3D%3D%3D%0AA+tensor+may+be+represented+as+an+array+%28potentially+multidimensional%29.+Just+as+a+%5B%5BVector+space%7Cvector%5D%5D+in+an+%7B%7Bmvar%7Cn%7D%7D-%5B%5Bdimension+%28vector+space%29%7Cdimensional%5D%5D+space+is+represented+by+a+one-dimensional+array+with+%7B%7Bmvar%7Cn%7D%7D+components+with+respect+to+a+given+%5B%5BBasis+%28linear+algebra%29%23Ordered+bases+and+coordinates%7Cbasis%5D%5D%2C+any+tensor+with+respect+to+a+basis+is+represented+by+a+multidimensional+array.++For+example%2C+a+%5B%5Blinear+operator%5D%5D+is+represented+in+a+basis+as+a+two-dimensional+square+%7B%7Bmath%7C%27%27n%27%27+×+%27%27n%27%27%7D%7D+array.++The+numbers+in+the+multidimensional+array+are+known+as+the+%27%27scalar+components%27%27+of+the+tensor+or+simply+its+%27%27components%27%27.++They+are+denoted+by+indices+giving+their+position+in+the+array%2C+as+%5B%5Bsubscript+and+superscript%7Csubscripts+and+superscripts%5D%5D%2C+following+the+symbolic+name+of+the+tensor.++For+example%2C+the+components+of+an+order+%7B%7Bmath%7C2%7D%7D+tensor+%7B%7Bmvar%7CT%7D%7D+could+be+denoted+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D%E2%80%AF%2C+where+%7B%7Bmvar%7Ci%7D%7D+and+%7B%7Bmvar%7Cj%7D%7D+are+indices+running+from+%7B%7Bmath%7C1%7D%7D+to+%7B%7Bmvar%7Cn%7D%7D%2C+or+also+by+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D.++Whether+an+index+is+displayed+as+a+superscript+or+subscript+depends+on+the+transformation+properties+of+the+tensor%2C+described+below.+Thus+while+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D+and+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D+can+both+be+expressed+as+%27%27n%27%27+by+%27%27n%27%27+matrices%2C+and+are+numerically+related+via+%5B%5BRaising+and+lowering+indices%7Cindex+juggling%5D%5D%2C+the+difference+in+their+transformation+laws+indicates+it+would+be+improper+to+add+them+together.+The+total+number+of+indices+required+to+identify+each+component+uniquely+is+equal+to+the+%5B%5BArray+data+structure%23Dimension%7Cdimension%5D%5D+of+the+array%2C+and+is+called+the+%27%27order%27%27%2C+%27%27degree%27%27+or+%27%27rank%27%27+of+the+tensor.++However%2C+the+term+%22rank%22+generally+has+%5B%5Btensor+rank%7Canother+meaning%5D%5D+in+the+context+of+matrices+and+tensors.%0A%0AJust+as+the+components+of+a+vector+change+when+we+change+the+%5B%5Bbasis+%28linear+algebra%29%7Cbasis%5D%5D+of+the+vector+space%2C+the+components+of+a+tensor+also+change+under+such+a+transformation.++Each+type+of+tensor+comes+equipped+with+a+%27%27transformation+law%27%27+that+details+how+the+components+of+the+tensor+respond+to+a+%5B%5Bchange+of+basis%5D%5D.++The+components+of+a+vector+can+respond+in+two+distinct+ways+to+a+%5B%5Bchange+of+basis%5D%5D+%28see+%5B%5Bcovariance+and+contravariance+of+vectors%5D%5D%29%2C+where+the+new+%5B%5Bbasis+vectors%5D%5D+%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i%3C%2Fmath%3E+are+expressed+in+terms+of+the+old+basis+vectors+%3Cmath%3E%5Cmathbf%7Be%7D_j%3C%2Fmath%3E+as%2C%0A%3A%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i+%3D+%5Csum_%7Bj%3D1%7D%5En+%5Cmathbf%7Be%7D_j+R%5Ej_i+%3D+%5Cmathbf%7Be%7D_j+R%5Ej_i+.%3C%2Fmath%3E%0A%0AHere+%27%27R%27%27%3Csup%3E%27%27+j%27%27%3C%2Fsup%3E%3Csub%3E%27%27i%27%27%3C%2Fsub%3E+are+the+entries+of+the+change+of+basis+matrix%2C+and+in+the+rightmost+expression+the+%5B%5Bsummation%5D%5D+sign+was+suppressed%3A+this+is+the+%5B%5BEinstein+summation+convention%5D%5D%2C+which+will+be+used+throughout+this+article.%3Cref+group%3D%22Note%22%3EThe+Einstein+summation+convention%2C+in+brief%2C+requires+the+sum+to+be+taken+over+all+values+of+the+index+whenever+the+same+symbol+appears+as+a+subscript+and+superscript+in+the+same+term.++For+example%2C+under+this+convention+%3Cmath%3EB_i+C%5Ei+%3D+B_1+C%5E1+%2B+B_2+C%5E2+%2B+%5Ccdots+B_n+C%5En%3C%2Fmath%3E%3C%2Fref%3E++The+components+%27%27v%27%27%3Csup%3E%27%27i%27%27%3C%2Fsup%3E+of+a+column+vector+%27%27%27v%27%27%27+transform+with+the+%5B%5Bmatrix+inverse%7Cinverse%5D%5D+of+the+matrix+%27%27R%27%27%2C%0A%3A%3Cmath%3E%5Chat%7Bv%7D%5Ei+%3D+%5Cleft%28R%5E%7B-1%7D%5Cright%29%5Ei_j+v%5Ej%2C%3C%2Fmath%3E%0A%0Awhere+the+hat+denotes+the+components+in+the+new+basis.++This+is+called+a+%27%27contravariant%27%27+transformation+law%2C+because+the+vector+components+transform+by+the+%27%27inverse%27%27+of+the+change+of+basis.++In+contrast%2C+the+components%2C+%27%27w%27%27%3Csub%3E%27%27i%27%27%3C%2Fsub%3E%2C+of+a+covector+%28or+row+vector%29%2C+%27%27%27w%27%27%27%2C+transform+with+the+matrix+%27%27R%27%27+itself%2C%0A%3A%3Cmath%3E%5Chat%7Bw%7D_i+%3D+w_j+R%5Ej_i+.%3C%2Fmath%3E&from=mediawiki&to=docx&standalone=false">MediaWiki to docx with equations</option>+      </select>+     </div>-    <div class="col-md-6">+    <div id="topane">       <label for="to">       to       </label>       <select id="to">-        <option value="S5">S5</option>         <option value="asciidoc">AsciiDoc (original)</option>         <option value="asciidoctor">AsciiDoc (asciidoctor-flavored)</option>         <option value="beamer">LaTeX Beamer</option>+        <option value="bibtex">BibTeX</option>+        <option value="biblatex">BibLaTeX</option>         <option value="commonmark">CommonMark</option>         <option value="context">ConTeXt</option>+        <option value="csljson">CSL JSON</option>         <option value="docbook4">DocBook v4</option>         <option value="docbook5">DocBook v5</option>+        <option value="docx">Docx (Word)</option>         <option value="dokuwiki">DokuWiki</option>         <option value="dzslides">DZSlides</option>+        <option value="epub2">EPUB v2</option>+        <option value="epub3">EPUB v3</option>         <option value="haddock">Haddock markup</option>         <option value="html4">HTML 4</option>         <option value="html5" selected>HTML 5</option>@@ -163,13 +140,16 @@         <option value="markdown_mmd">MultiMarkdown</option>         <option value="muse">Muse</option>         <option value="native">Native (Pandoc AST)</option>+        <option value="odt">ODT</option>         <option value="opendocument">OpenDocument</option>         <option value="opml">OPML</option>         <option value="org">Org Mode</option>         <option value="plain">Plain text</option>+        <option value="pptx">Powerpoint</option>         <option value="revealjs">reveal.js</option>         <option value="rst">reStructuredText</option>         <option value="rtf">RTF</option>+        <option value="S5">S5</option>         <option value="slideous">Slideous</option>         <option value="slidy">Slidy</option>         <option value="tei">TEI</option>@@ -177,14 +157,25 @@         <option value="textile">Textile</option>         <option value="zimwiki">ZimWiki</option>       </select>+      <input type="checkbox" id="standalone" name="standalone">+      <label for="standalone">Standalone+        <a href="https://pandoc.org/MANUAL.html#option--standalone" target="_blank">(?)</a>+      </label>+      <input type="checkbox" id="citeproc" name="citeproc">+      <label for="citeproc">Citeproc+        <a href="https://pandoc.org/MANUAL.html#option--citeproc" target="_blank">(?)</a>+      </label>       <br/>+      <a id="permalink" title="link to this conversion" href="">permalink</a></br/>       <pre id="results"></pre>     </div>   </div> </div> <footer>- <p class="version">pandoc <span id="version"></span></p>- <p><a href="https://pandoc.org">https://pandoc.org</a></p>+ <p class="version">pandoc version <span id="version"></span></p> </footer>++<script src="trypandoc.js?202208182155"></script>+ </body> </html>
− trypandoc/trypandoc.hs
@@ -1,76 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |-   Module      : Main-   Copyright   : © 2014-2022 John MacFarlane <jgm@berkeley.edu>-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley.edu>-   Stability   : alpha-   Portability : portable--Provides a webservice which allows to try pandoc in the browser.--}-module Main where-import Network.Wai.Handler.CGI-import Network.Wai.Middleware.Timeout (timeout)-import Network.Wai-import Data.Maybe (fromMaybe)-import Network.HTTP.Types.Status (status200)-import Network.HTTP.Types.Header (hContentType)-import Network.HTTP.Types.URI (queryToQueryText)-import Text.Pandoc-import Text.Pandoc.Highlighting (pygments)-import Text.Pandoc.Shared (tabFilter)-import Data.Aeson-import qualified Data.Text as T-import Data.Text (Text)--main :: IO ()-main = run $ timeout 2 app--app :: Application-app req respond = do-  let query = queryToQueryText $ queryString req-  let getParam x = maybe (error $ T.unpack x ++ " parameter not set")-                       return $ lookup x query-  text <- getParam "text" >>= checkLength . fromMaybe T.empty-  fromFormat <- fromMaybe "" <$> getParam "from"-  toFormat <- fromMaybe "" <$> getParam "to"-  standalone <- (==) "1" . fromMaybe "" <$> getParam "standalone"-  compiledTemplate <- runIO . compileDefaultTemplate $ toFormat-  let template = if standalone then either (const Nothing) Just compiledTemplate else Nothing-  let reader = case runPure $ getReader fromFormat of-                    Right (TextReader r, es) -> r readerOpts{-                       readerExtensions = es }-                    _ -> error $ "could not find reader for "-                                  ++ T.unpack fromFormat-  let writer = case runPure $ getWriter toFormat of-                    Right (TextWriter w, es) -> w writerOpts{-                       writerExtensions = es, writerTemplate = template }-                    _ -> error $ "could not find writer for " ++-                           T.unpack toFormat-  let result = case runPure $ reader (tabFilter 4 text) >>= writer of-                    Right s   -> s-                    Left  err -> error (show err)-  let output = encode $ object [ "html" .= result-                               , "name" .=-                                  if fromFormat == "markdown_strict"-                                     then T.pack "pandoc (strict)"-                                     else T.pack "pandoc"-                               , "version" .= pandocVersion]-  respond $ responseLBS status200 [(hContentType,"text/json; charset=UTF-8")] output--checkLength :: Text -> IO Text-checkLength t =-  if T.length t > 10000-     then error "exceeds length limit of 10,000 characters"-     else return t--writerOpts :: WriterOptions-writerOpts = def { writerReferenceLinks = True,-                   writerEmailObfuscation = NoObfuscation,-                   writerHTMLMathMethod = MathJax defaultMathJaxURL,-                   writerHighlightStyle = Just pygments }--readerOpts :: ReaderOptions-readerOpts = def
+ trypandoc/trypandoc.js view
@@ -0,0 +1,161 @@+"use strict";++var params = {+  text: '"hello *world*"',+  to: 'html5',+  from: 'markdown',+  standalone: false,+  citeproc: false };++function permalink() {+  let input = document.getElementById("text").value;+  let from = document.getElementById("from").value;+  let to = document.getElementById("to").value;+  let standalone = document.getElementById("standalone").checked ? true : false;+  let citeproc = document.getElementById("citeproc").checked ? true : false;+  let href = window.location.href;+  const URLparams = new URLSearchParams(Object.entries({text: input, from: from, to: to, standalone: standalone, citeproc: citeproc}));+  return href.replace(/([?].*)?$/,"?" + URLparams);+}++const binaryFormats = {+   docx: { extension: "docx",+           mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },+    odt: { extension: "odt",+           mime: "application/vnd.oasis.opendocument.text" },+    pptx: { extension: "pptx",+            mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation" },+    epub:  { extension: "epub",+             mime: "application/epub+zip" },+    epub2: { extension: "epub",+             mime: "application/epub+zip" },+    epub3: { extension: "epub",+             mime: "application/epub+zip" }+};++const binaryMimeTypes = {+  ["application/epub+zip"]: true,+  ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]: true,+  ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]: true,+  ["application/vnd.oasis.opendocument.text"]: true+};++function paramsFromURL() {+  if (window.location.search.length > 0) {+    const uparams = new URLSearchParams(window.location.search);+    params.text = uparams.get("text") || "";+    params.from = uparams.get("from") || "markdown";+    params.to = uparams.get("to") || "html5";+    params.standalone = uparams.get("standalone") === "true";+    params.citeproc = uparams.get("citeproc") === "true";+  }+}++function handleErrors(response) {+    if (response.status == 503 || response.status == 500) {+        throw Error("Conversion timed out.")+    } else if (!response.ok) {+        throw Error(response.statusText);+    }+    return response;+}++function convert() {+    let text = document.getElementById("text").value;+    let from = document.getElementById("from").value;+    let to = document.getElementById("to").value;+    let standalone = document.getElementById("standalone").checked;+    let citeproc = document.getElementById("citeproc").checked;+    params = { text: text, from: from, to: to, standalone: standalone,+               citeproc: citeproc };++    if (text && text != "") {+       let commandString = "pandoc"+         + " --from " + from + " --to " + to+         + (standalone ? " --standalone" : "")+         + (citeproc ? " --citeproc" : "") ;+       document.getElementById("command").textContent = commandString;+       fetch("/cgi-bin/pandoc-server.cgi", {+         method: "POST",+         headers: {"Content-Type": "application/json"},+         body: JSON.stringify(params)+        })+       .then(handleErrors)+       .then(response => response.text())+       .then(restext => {+            let binary = binaryFormats[to];+            if (binary) {+            document.getElementById("results").innerHTML =+                '<a download="trypandoc.' + binary.extension ++                '" href="data:' + binary.mime + ';base64,' + restext ++                '">click to download trypandoc.' + binary.extension + '</a>';+          } else {+            document.getElementById("results").textContent = restext;+          }+          document.getElementById("permalink").href = permalink();+       })+       .catch(error => {+         document.getElementById("results").textContent = error;+       }+       );+    };+}++(function() {+    paramsFromURL();+    document.getElementById("text").value = params.text;+    document.getElementById("from").value = params.from;+    document.getElementById("to").value = params.to;+    document.getElementById("standalone").checked = params.standalone;+    document.getElementById("citeproc").checked = params.citeproc;++    document.getElementById("convert").onclick = convert;+    document.getElementById("from").onchange = convert;+    document.getElementById("to").onchange = convert;+    document.getElementById("standalone").onchange = convert;+    document.getElementById("citeproc").onchange = convert;++    document.getElementById("examples").onchange =+      (e => window.location.href = e.target.value );++    const fileInput = document.getElementById('loadfile');++    // Listen for the change event so we can capture the file+    fileInput.addEventListener('change', (e) => {+      // Get a reference to the file+      const file = e.target.files[0];+      const mimetype = file.type;+      let binary = binaryMimeTypes[mimetype];++      // Encode the file using the FileReader API+      const reader = new FileReader();+      let inputtext = document.getElementById("text");+      reader.onloadend = () => {+        // Use a regex to remove data url part+        if (binary) {+          const base64String = reader.result+           .replace('data:', '')+           .replace(/^.+,/, '');+          inputtext.value = base64String;+	} else {+          inputtext.value = reader.result;+        }+      };+      if (binary) {+        reader.readAsDataURL(file);+      } else {+        reader.readAsText(file);+      }+    });++    fetch("/cgi-bin/pandoc-server.cgi/version")+       .then(handleErrors)+       .then(response => response.text())+       .then(restext =>+           document.getElementById("version").textContent = restext+         );++    convert();++})();+