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 +19/−50
- MANUAL.txt +20/−1
- app/pandoc.hs +15/−2
- cabal.project +0/−1
- changelog.md +81/−0
- data/templates/default.latex +2/−1
- data/templates/default.org +5/−0
- man/pandoc.1 +16/−2
- pandoc.cabal +17/−27
- src/Text/Pandoc/App.hs +250/−243
- src/Text/Pandoc/App/CommandLineOptions.hs +3/−19
- src/Text/Pandoc/App/Opt.hs +86/−3
- src/Text/Pandoc/App/OutputSettings.hs +4/−3
- src/Text/Pandoc/Class/IO.hs +2/−2
- src/Text/Pandoc/Highlighting.hs +23/−0
- src/Text/Pandoc/Lua/Module/Utils.hs +11/−1
- src/Text/Pandoc/PDF.hs +5/−4
- src/Text/Pandoc/Readers/CommonMark.hs +38/−9
- src/Text/Pandoc/Readers/FB2.hs +2/−2
- src/Text/Pandoc/Readers/HTML.hs +2/−3
- src/Text/Pandoc/Readers/Haddock.hs +10/−0
- src/Text/Pandoc/Readers/Org/Blocks.hs +11/−0
- src/Text/Pandoc/SelfContained.hs +2/−2
- src/Text/Pandoc/Server.hs +357/−0
- src/Text/Pandoc/Writers/FB2.hs +2/−3
- src/Text/Pandoc/Writers/HTML.hs +1/−1
- src/Text/Pandoc/Writers/LaTeX/Table.hs +16/−16
- src/Text/Pandoc/Writers/LaTeX/Util.hs +1/−1
- stack.yaml +2/−3
- test/command/1710.md +3/−3
- test/command/8204.md +39/−0
- test/command/8216.md +51/−0
- test/command/8219.md +14/−0
- test/tables/nordics.latex +1/−1
- test/tables/planets.latex +4/−4
- test/tables/students.latex +4/−4
- trypandoc/Makefile +0/−14
- trypandoc/index.html +65/−74
- trypandoc/trypandoc.hs +0/−76
- trypandoc/trypandoc.js +161/−0
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> <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();++})();+