diff options
| author | John MacFarlane <jgm@berkeley.edu> | 2021-11-05 22:10:29 -0700 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-05 22:10:29 -0700 | 
| commit | ee2f0021f9b59f0bca6eabf4884641da7a09e21d (patch) | |
| tree | f29d5325d1d89c736093534d27b62c98a674df57 /src/Text | |
| parent | bac6ae9607582233336984c30bba3c586eba6844 (diff) | |
| download | pandoc-ee2f0021f9b59f0bca6eabf4884641da7a09e21d.tar.gz | |
Add interface for custom readers written in Lua. (#7671)
New module Text.Pandoc.Readers.Custom, exporting
readCustom [API change].
Users can now do `-f myreader.lua` and pandoc will treat the
script myreader.lua as a custom reader, which parses an input
string to a pandoc AST, using the pandoc module defined for
Lua filters.
A sample custom reader can be found in data/reader.lua.
Closes #7669.
Diffstat (limited to 'src/Text')
| -rw-r--r-- | src/Text/Pandoc/App.hs | 13 | ||||
| -rw-r--r-- | src/Text/Pandoc/Readers/Custom.hs | 55 | 
2 files changed, 63 insertions, 5 deletions
| diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs index 20e647456..9eb9c2cf3 100644 --- a/src/Text/Pandoc/App.hs +++ b/src/Text/Pandoc/App.hs @@ -68,6 +68,7 @@ import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,           defaultUserDataDir, tshow)  import Text.Pandoc.Writers.Shared (lookupMetaString)  import Text.Pandoc.Readers.Markdown (yamlToMeta) +import Text.Pandoc.Readers.Custom (readCustom)  import qualified Text.Pandoc.UTF8 as UTF8  #ifndef _WINDOWS  import System.Posix.IO (stdOutput) @@ -154,11 +155,13 @@ convertWithOpts opts = do                              -> ByteStringReader $ \o t -> sandbox files (r o t)      (reader, readerExts) <- -      if optSandbox opts -         then case runPure (getReader readerName) of -                Left e -> throwError e -                Right (r, rexts) -> return (makeSandboxed r, rexts) -         else getReader readerName +      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      outputSettings <- optToOutputSettings opts      let format = outputFormat outputSettings diff --git a/src/Text/Pandoc/Readers/Custom.hs b/src/Text/Pandoc/Readers/Custom.hs new file mode 100644 index 000000000..83d82a9cc --- /dev/null +++ b/src/Text/Pandoc/Readers/Custom.hs @@ -0,0 +1,55 @@ +{-# LANGUAGE FlexibleContexts    #-} +{-# LANGUAGE FlexibleInstances   #-} +{-# LANGUAGE OverloadedStrings   #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications    #-} +{- | +   Module      : Text.Pandoc.Readers.Custom +   Copyright   : Copyright (C) 2021 John MacFarlane +   License     : GNU GPL, version 2 or above + +   Maintainer  : John MacFarlane <jgm@berkeley.edu> +   Stability   : alpha +   Portability : portable + +Supports custom parsers written in Lua which produce a Pandoc AST. +-} +module Text.Pandoc.Readers.Custom ( readCustom ) where +import Control.Exception +import Control.Monad (when) +import Data.Text (Text) +import HsLua as Lua hiding (Operation (Div), render) +import HsLua.Class.Peekable (PeekError) +import Control.Monad.IO.Class (MonadIO) +import Text.Pandoc.Definition +import Text.Pandoc.Lua (Global (..), runLua, setGlobals) +import Text.Pandoc.Lua.Util (dofileWithTraceback) +import Text.Pandoc.Options +import Text.Pandoc.Class (PandocMonad) +import Text.Pandoc.Sources (ToSources(..), sourcesToText) + +-- | Convert custom markup to Pandoc. +readCustom :: (PandocMonad m, MonadIO m, ToSources s) +            => FilePath -> ReaderOptions -> s -> m Pandoc +readCustom luaFile opts sources = do +  let input = sourcesToText $ toSources sources +  let globals = [ PANDOC_SCRIPT_FILE luaFile +                , PANDOC_READER_OPTIONS opts +                ] +  res <- runLua $ do +    setGlobals globals +    stat <- dofileWithTraceback luaFile +    -- check for error in lua script (later we'll change the return type +    -- to handle this more gracefully): +    when (stat /= Lua.OK) +      Lua.throwErrorAsException +    parseCustom input +  case res of +    Left msg -> throw msg +    Right doc -> return doc + +parseCustom :: forall e. PeekError e +            => Text +            -> LuaE e Pandoc +parseCustom = invoke @e "Reader" + | 
