diff options
| author | Albert Krewinkel <albert@zeitkraut.de> | 2022-09-29 17:24:31 +0200 |
|---|---|---|
| committer | John MacFarlane <jgm@berkeley.edu> | 2022-09-30 08:33:40 -0700 |
| commit | 5be9052f5fb7283372b3d5497bef499718a34992 (patch) | |
| tree | 80e5805786ef7ab08f363135861e1aa9c8868f6f /src/Text/Pandoc/Lua/Module | |
| parent | 79980eee4a1854921d7fb8b14848894b53cc21a7 (diff) | |
[API Change] Extract Lua code into new package pandoc-lua-engine
The flag 'lua53` must now be used with that package if pandoc is to be
compiled against Lua 5.3.
Diffstat (limited to 'src/Text/Pandoc/Lua/Module')
| -rw-r--r-- | src/Text/Pandoc/Lua/Module/MediaBag.hs | 142 | ||||
| -rw-r--r-- | src/Text/Pandoc/Lua/Module/Pandoc.hs | 320 | ||||
| -rw-r--r-- | src/Text/Pandoc/Lua/Module/System.hs | 41 | ||||
| -rw-r--r-- | src/Text/Pandoc/Lua/Module/Template.hs | 61 | ||||
| -rw-r--r-- | src/Text/Pandoc/Lua/Module/Types.hs | 42 | ||||
| -rw-r--r-- | src/Text/Pandoc/Lua/Module/Utils.hs | 239 |
6 files changed, 0 insertions, 845 deletions
diff --git a/src/Text/Pandoc/Lua/Module/MediaBag.hs b/src/Text/Pandoc/Lua/Module/MediaBag.hs deleted file mode 100644 index ca028f444..000000000 --- a/src/Text/Pandoc/Lua/Module/MediaBag.hs +++ /dev/null @@ -1,142 +0,0 @@ -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedStrings #-} -{- | - Module : Text.Pandoc.Lua.Module.MediaBag - Copyright : Copyright © 2017-2022 Albert Krewinkel - License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> - -The Lua module @pandoc.mediabag@. --} -module Text.Pandoc.Lua.Module.MediaBag - ( documentedModule - ) where - -import Prelude hiding (lookup) -import Data.Maybe (fromMaybe) -import HsLua ( LuaE, DocumentedFunction, Module (..) - , (<#>), (###), (=#>), (=?>), (#?), defun, functionResult - , opt, parameter, stringParam, textParam) -import Text.Pandoc.Class ( CommonState (..), fetchItem, fillMediaBag - , getMediaBag, modifyCommonState, setMediaBag) -import Text.Pandoc.Error (PandocError) -import Text.Pandoc.Lua.Marshal.Pandoc (peekPandoc, pushPandoc) -import Text.Pandoc.Lua.Marshal.List (pushPandocList) -import Text.Pandoc.Lua.Orphans () -import Text.Pandoc.Lua.PandocLua (unPandocLua) -import Text.Pandoc.MIME (MimeType) - -import qualified Data.ByteString.Lazy as BL -import qualified HsLua as Lua -import qualified Text.Pandoc.MediaBag as MB - --- --- MediaBag submodule --- -documentedModule :: Module PandocError -documentedModule = Module - { moduleName = "pandoc.mediabag" - , moduleDescription = "mediabag access" - , moduleFields = [] - , moduleFunctions = - [ delete - , empty - , fetch - , fill - , insert - , items - , list - , lookup - ] - , moduleOperations = [] - } - --- | Delete a single item from the media bag. -delete :: DocumentedFunction PandocError -delete = defun "delete" - ### (\fp -> unPandocLua $ modifyCommonState - (\st -> st { stMediaBag = MB.deleteMedia fp (stMediaBag st) })) - <#> stringParam "filepath" "filename of item to delete" - =#> [] - - --- | Delete all items from the media bag. -empty :: DocumentedFunction PandocError -empty = defun "empty" - ### unPandocLua (modifyCommonState (\st -> st { stMediaBag = mempty })) - =#> [] - --- | Fill the mediabag with all images in the document that aren't --- present yet. -fill :: DocumentedFunction PandocError -fill = defun "fill" - ### unPandocLua . fillMediaBag - <#> parameter peekPandoc "Pandoc" "doc" - "document from which to fill the mediabag" - =#> functionResult pushPandoc "Pandoc" "modified document" - #? ("Fills the mediabag with the images in the given document.\n" <> - "An image that cannot be retrieved will be replaced with a Span\n" <> - "of class \"image\" that contains the image description.\n" <> - "" <> - "Images for which the mediabag already contains an item will\n" <> - "not be processed again.") - --- | Insert a new item into the media bag. -insert :: DocumentedFunction PandocError -insert = defun "insert" - ### (\fp mmime contents -> unPandocLua $ do - mb <- getMediaBag - setMediaBag $ MB.insertMedia fp mmime contents mb - return (Lua.NumResults 0)) - <#> stringParam "filepath" "item file path" - <#> opt (textParam "mimetype" "the item's MIME type") - <#> parameter Lua.peekLazyByteString "string" "contents" "binary contents" - =#> [] - --- | Returns iterator values to be used with a Lua @for@ loop. -items :: DocumentedFunction PandocError -items = defun "items" - ### (do - mb <-unPandocLua getMediaBag - let pushItem (fp, mimetype, contents) = do - Lua.pushString fp - Lua.pushText mimetype - Lua.pushByteString $ BL.toStrict contents - return (Lua.NumResults 3) - Lua.pushIterator pushItem (MB.mediaItems mb)) - =?> "Iterator triple" - --- | Function to lookup a value in the mediabag. -lookup :: DocumentedFunction PandocError -lookup = defun "lookup" - ### (\fp -> unPandocLua (MB.lookupMedia fp <$> getMediaBag) >>= \case - Nothing -> 1 <$ Lua.pushnil - Just item -> 2 <$ do - Lua.pushText $ MB.mediaMimeType item - Lua.pushLazyByteString $ MB.mediaContents item) - <#> stringParam "filepath" "path of item to lookup" - =?> "MIME type and contents" - --- | Function listing all mediabag items. -list :: DocumentedFunction PandocError -list = defun "list" - ### (unPandocLua (MB.mediaDirectory <$> getMediaBag)) - =#> functionResult (pushPandocList pushEntry) "table" "list of entry triples" - where - pushEntry :: (FilePath, MimeType, Int) -> LuaE PandocError () - pushEntry (fp, mimeType, contentLength) = do - Lua.newtable - Lua.pushName "path" *> Lua.pushString fp *> Lua.rawset (-3) - Lua.pushName "type" *> Lua.pushText mimeType *> Lua.rawset (-3) - Lua.pushName "length" *> Lua.pushIntegral contentLength *> Lua.rawset (-3) - --- | Lua function to retrieve a new item. -fetch :: DocumentedFunction PandocError -fetch = defun "fetch" - ### (\src -> do - (bs, mimeType) <- unPandocLua $ fetchItem src - Lua.pushText $ fromMaybe "" mimeType - Lua.pushByteString bs - return 2) - <#> textParam "src" "URI to fetch" - =?> "Returns two string values: the fetched contents and the mimetype." diff --git a/src/Text/Pandoc/Lua/Module/Pandoc.hs b/src/Text/Pandoc/Lua/Module/Pandoc.hs deleted file mode 100644 index e708f4345..000000000 --- a/src/Text/Pandoc/Lua/Module/Pandoc.hs +++ /dev/null @@ -1,320 +0,0 @@ -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{- | - Module : Text.Pandoc.Lua.Module.Pandoc - Copyright : Copyright © 2017-2022 Albert Krewinkel - License : GNU GPL, version 2 or above - - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> - Stability : alpha - -Pandoc module for lua. --} -module Text.Pandoc.Lua.Module.Pandoc - ( pushModule - , documentedModule - ) where - -import Prelude hiding (read) -import Control.Applicative ((<|>)) -import Control.Monad (forM_, when) -import Control.Monad.Catch (catch, throwM) -import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr) -import Data.Default (Default (..)) -import Data.Maybe (fromMaybe) -import Data.Proxy (Proxy (Proxy)) -import HsLua hiding (pushModule) -import System.Exit (ExitCode (..)) -import Text.Pandoc.Definition -import Text.Pandoc.Error (PandocError (..)) -import Text.Pandoc.Lua.Orphans () -import Text.Pandoc.Lua.Marshal.AST -import Text.Pandoc.Lua.Marshal.Filter (peekFilter) -import Text.Pandoc.Lua.Marshal.ReaderOptions ( peekReaderOptions - , pushReaderOptions) -import Text.Pandoc.Lua.Marshal.Sources (peekSources) -import Text.Pandoc.Lua.Marshal.WriterOptions ( peekWriterOptions - , pushWriterOptions) -import Text.Pandoc.Lua.Module.Utils (sha1) -import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua), liftPandocLua) -import Text.Pandoc.Options ( ReaderOptions (readerExtensions) - , WriterOptions (writerExtensions) ) -import Text.Pandoc.Process (pipeProcess) -import Text.Pandoc.Readers (Reader (..), getReader, readers) -import Text.Pandoc.Sources (toSources) -import Text.Pandoc.Writers (Writer (..), getWriter, writers) - -import qualified HsLua as Lua -import qualified Data.ByteString.Lazy as BL -import qualified Data.ByteString.Lazy.Char8 as BSL -import qualified Data.Set as Set -import qualified Data.Text as T -import qualified Text.Pandoc.UTF8 as UTF8 - --- | Push the "pandoc" package to the Lua stack. Requires the `List` --- module to be loadable. -pushModule :: PandocLua NumResults -pushModule = do - liftPandocLua $ Lua.pushModule documentedModule - return 1 - -documentedModule :: Module PandocError -documentedModule = Module - { moduleName = "pandoc" - , moduleDescription = T.unlines - [ "Lua functions for pandoc scripts; includes constructors for" - , "document elements, functions to parse text in a given" - , "format, and functions to filter and modify a subtree." - ] - , moduleFields = readersField : writersField : - stringConstants ++ [inlineField, blockField] - , moduleOperations = [] - , moduleFunctions = mconcat - [ functions - , otherConstructors - , blockConstructors - , inlineConstructors - , metaValueConstructors - ] - } - --- | Set of input formats accepted by @read@. -readersField :: Field PandocError -readersField = Field - { fieldName = "readers" - , fieldDescription = T.unlines - [ "Set of formats that pandoc can parse. All keys in this table can" - , "be used as the `format` value in `pandoc.read`." - ] - , fieldPushValue = pushSet pushText $ - Set.fromList (map fst (readers @PandocLua)) - } - --- | Set of input formats accepted by @write@. -writersField :: Field PandocError -writersField = Field - { fieldName = "writers" - , fieldDescription = T.unlines - [ "Set of formats that pandoc can generate. All keys in this table" - , "can be used as the `format` value in `pandoc.write`." - ] - , fieldPushValue = pushSet pushText $ - Set.fromList (map fst (writers @PandocLua)) - } - --- | Inline table field -inlineField :: Field PandocError -inlineField = Field - { fieldName = "Inline" - , fieldDescription = "Inline constructors, nested under 'constructors'." - -- the nesting happens for historical reasons and should probably be - -- changed. - , fieldPushValue = pushWithConstructorsSubtable inlineConstructors - } - --- | @Block@ module field -blockField :: Field PandocError -blockField = Field - { fieldName = "Block" - , fieldDescription = "Inline constructors, nested under 'constructors'." - -- the nesting happens for historical reasons and should probably be - -- changed. - , fieldPushValue = pushWithConstructorsSubtable blockConstructors - } - -pushWithConstructorsSubtable :: [DocumentedFunction PandocError] - -> LuaE PandocError () -pushWithConstructorsSubtable constructors = do - newtable -- Field table - newtable -- constructor table - pushName "constructor" *> pushvalue (nth 2) *> rawset (nth 4) - forM_ constructors $ \fn -> do - pushName (functionName fn) - pushDocumentedFunction fn - rawset (nth 3) - pop 1 -- pop constructor table - -otherConstructors :: LuaError e => [DocumentedFunction e] -otherConstructors = - [ mkPandoc - , mkMeta - , mkAttr - , mkAttributeList - , mkBlocks - , mkCitation - , mkCell - , mkRow - , mkTableHead - , mkTableFoot - , mkInlines - , mkListAttributes - , mkSimpleTable - - , defun "ReaderOptions" - ### liftPure id - <#> parameter peekReaderOptions "ReaderOptions|table" "opts" "reader options" - =#> functionResult pushReaderOptions "ReaderOptions" "new object" - #? "Creates a new ReaderOptions value." - - , defun "WriterOptions" - ### liftPure id - <#> parameter peekWriterOptions "WriterOptions|table" "opts" - "writer options" - =#> functionResult pushWriterOptions "WriterOptions" "new object" - #? "Creates a new WriterOptions value." - ] - -stringConstants :: [Field e] -stringConstants = - let constrs :: forall a. Data a => Proxy a -> [String] - constrs _ = map showConstr . dataTypeConstrs . dataTypeOf @a $ undefined - nullaryConstructors = mconcat - [ constrs (Proxy @ListNumberStyle) - , constrs (Proxy @ListNumberDelim) - , constrs (Proxy @QuoteType) - , constrs (Proxy @MathType) - , constrs (Proxy @Alignment) - , constrs (Proxy @CitationMode) - ] - toField s = Field - { fieldName = T.pack s - , fieldDescription = T.pack s - , fieldPushValue = pushString s - } - in map toField nullaryConstructors - -functions :: [DocumentedFunction PandocError] -functions = - [ defun "pipe" - ### (\command args input -> do - (ec, output) <- Lua.liftIO $ pipeProcess Nothing command args input - `catch` (throwM . PandocIOError "pipe") - case ec of - ExitSuccess -> 1 <$ Lua.pushLazyByteString output - ExitFailure n -> do - pushPipeError (PipeError (T.pack command) n output) - Lua.error) - <#> parameter peekString "string" "command" "path to executable" - <#> parameter (peekList peekString) "{string,...}" "args" - "list of arguments" - <#> parameter peekLazyByteString "string" "input" - "input passed to process via stdin" - =?> "output string, or error triple" - - , defun "read" - ### (\content mformatspec mreaderOptions -> do - let formatSpec = fromMaybe "markdown" mformatspec - readerOpts = fromMaybe def mreaderOptions - readAction = getReader formatSpec >>= \case - (TextReader r, es) -> - r readerOpts{readerExtensions = es} - (case content of - Left bs -> toSources $ UTF8.toText bs - Right sources -> sources) - (ByteStringReader r, es) -> - case content of - Left bs -> r readerOpts{readerExtensions = es} - (BSL.fromStrict bs) - Right _ -> liftPandocLua $ Lua.failLua - "Cannot use bytestring reader with Sources" - try (unPandocLua readAction) >>= \case - Right pd -> - -- success, got a Pandoc document - return pd - Left (PandocUnknownReaderError f) -> - Lua.failLua . T.unpack $ "Unknown reader: " <> f - Left (PandocUnsupportedExtensionError e f) -> - Lua.failLua . T.unpack $ - "Extension " <> e <> " not supported for " <> f - Left e -> - throwM e) - <#> parameter (\idx -> (Left <$> peekByteString idx) - <|> (Right <$> peekSources idx)) - "string|Sources" "content" "text to parse" - <#> opt (textParam "formatspec" "format and extensions") - <#> opt (parameter peekReaderOptions "ReaderOptions" "reader_options" - "reader options") - =#> functionResult pushPandoc "Pandoc" "result document" - - , sha1 - - , defun "walk_block" - ### walkElement - <#> parameter peekBlockFuzzy "Block" "block" "element to traverse" - <#> parameter peekFilter "Filter" "lua_filter" "filter functions" - =#> functionResult pushBlock "Block" "modified Block" - - , defun "walk_inline" - ### walkElement - <#> parameter peekInlineFuzzy "Inline" "inline" "element to traverse" - <#> parameter peekFilter "Filter" "lua_filter" "filter functions" - =#> functionResult pushInline "Inline" "modified Inline" - - , defun "write" - ### (\doc mformatspec mwriterOpts -> do - let formatSpec = fromMaybe "html" mformatspec - writerOpts = fromMaybe def mwriterOpts - unPandocLua $ getWriter formatSpec >>= \case - (TextWriter w, es) -> Right <$> - w writerOpts{ writerExtensions = es } doc - (ByteStringWriter w, es) -> Left <$> - w writerOpts{ writerExtensions = es } doc) - <#> parameter peekPandoc "Pandoc" "doc" "document to convert" - <#> opt (textParam "formatspec" "format and extensions") - <#> opt (parameter peekWriterOptions "WriterOptions" "writer_options" - "writer options") - =#> functionResult (either pushLazyByteString pushText) "string" - "result document" - ] - where - walkElement x f = - walkInlineSplicing f x - >>= walkInlinesStraight f - >>= walkBlockSplicing f - >>= walkBlocksStraight f - -data PipeError = PipeError - { pipeErrorCommand :: T.Text - , pipeErrorCode :: Int - , pipeErrorOutput :: BL.ByteString - } - -peekPipeError :: LuaError e => StackIndex -> LuaE e PipeError -peekPipeError idx = - PipeError - <$> (Lua.getfield idx "command" *> Lua.peek (-1) <* Lua.pop 1) - <*> (Lua.getfield idx "error_code" *> Lua.peek (-1) <* Lua.pop 1) - <*> (Lua.getfield idx "output" *> Lua.peek (-1) <* Lua.pop 1) - -pushPipeError :: LuaError e => Pusher e PipeError -pushPipeError pipeErr = do - pushAsTable [ ("command" , pushText . pipeErrorCommand) - , ("error_code" , pushIntegral . pipeErrorCode) - , ("output" , pushLazyByteString . pipeErrorOutput) - ] pipeErr - pushPipeErrorMetaTable - Lua.setmetatable (nth 2) - where - pushPipeErrorMetaTable :: LuaError e => LuaE e () - pushPipeErrorMetaTable = do - v <- Lua.newmetatable "pandoc pipe error" - when v $ do - pushName "__tostring" - pushHaskellFunction pipeErrorMessage - rawset (nth 3) - - pipeErrorMessage :: LuaError e => LuaE e NumResults - pipeErrorMessage = do - (PipeError cmd errorCode output) <- peekPipeError (nthBottom 1) - pushByteString . BSL.toStrict . BSL.concat $ - [ BSL.pack "Error running " - , BSL.pack $ T.unpack cmd - , BSL.pack " (error code " - , BSL.pack $ show errorCode - , BSL.pack "): " - , if output == mempty then BSL.pack "<no output>" else output - ] - return (NumResults 1) diff --git a/src/Text/Pandoc/Lua/Module/System.hs b/src/Text/Pandoc/Lua/Module/System.hs deleted file mode 100644 index 70ef1b315..000000000 --- a/src/Text/Pandoc/Lua/Module/System.hs +++ /dev/null @@ -1,41 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{- | - Module : Text.Pandoc.Lua.Module.System - Copyright : © 2019-2022 Albert Krewinkel - License : GNU GPL, version 2 or above - - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> - Stability : alpha - -Pandoc's system Lua module. --} -module Text.Pandoc.Lua.Module.System - ( documentedModule - ) where - -import HsLua -import HsLua.Module.System - (arch, env, getwd, ls, mkdir, os, rmdir, with_env, with_tmpdir, with_wd) - --- | Push the pandoc.system module on the Lua stack. -documentedModule :: LuaError e => Module e -documentedModule = Module - { moduleName = "pandoc.system" - , moduleDescription = "system functions" - , moduleFields = - [ arch - , os - ] - , moduleFunctions = - [ setName "environment" env - , setName "get_working_directory" getwd - , setName "list_directory" ls - , setName "make_directory" mkdir - , setName "remove_directory" rmdir - , setName "with_environment" with_env - , setName "with_temporary_directory" with_tmpdir - , setName "with_working_directory" with_wd - ] - , moduleOperations = [] - } diff --git a/src/Text/Pandoc/Lua/Module/Template.hs b/src/Text/Pandoc/Lua/Module/Template.hs deleted file mode 100644 index 967fe31a8..000000000 --- a/src/Text/Pandoc/Lua/Module/Template.hs +++ /dev/null @@ -1,61 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} -{- | - Module : Text.Pandoc.Lua.Module.Template - Copyright : Copyright © 2022 Albert Krewinkel, John MacFarlane - License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> - -Lua module to handle pandoc templates. --} -module Text.Pandoc.Lua.Module.Template - ( documentedModule - ) where - -import HsLua -import Text.Pandoc.Error (PandocError) -import Text.Pandoc.Lua.Marshal.Template (pushTemplate) -import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua), liftPandocLua) -import Text.Pandoc.Templates - (compileTemplate, getDefaultTemplate, runWithPartials, runWithDefaultPartials) - -import qualified Data.Text as T - --- | The "pandoc.template" module. -documentedModule :: Module PandocError -documentedModule = Module - { moduleName = "pandoc.template" - , moduleDescription = T.unlines - [ "Lua functions for pandoc templates." - ] - , moduleFields = [] - , moduleOperations = [] - , moduleFunctions = functions - } - --- | Template module functions. -functions :: [DocumentedFunction PandocError] -functions = - [ defun "compile" - ### (\template mfilepath -> unPandocLua $ - case mfilepath of - Just fp -> runWithPartials (compileTemplate fp template) - Nothing -> runWithDefaultPartials - (compileTemplate "templates/default" template)) - <#> parameter peekText "string" "template" "template string" - <#> opt (stringParam "templ_path" "template path") - =#> functionResult (either failLua pushTemplate) "pandoc Template" - "compiled template" - - , defun "default" - ### (\mformat -> unPandocLua $ do - let getFORMAT = liftPandocLua $ do - getglobal "FORMAT" - forcePeek $ peekText top `lastly` pop 1 - format <- maybe getFORMAT pure mformat - getDefaultTemplate format) - <#> opt (textParam "writer" - "writer for which the template should be returned.") - =#> functionResult pushText "string" - "string representation of the writer's default template" - - ] diff --git a/src/Text/Pandoc/Lua/Module/Types.hs b/src/Text/Pandoc/Lua/Module/Types.hs deleted file mode 100644 index b8d45d93e..000000000 --- a/src/Text/Pandoc/Lua/Module/Types.hs +++ /dev/null @@ -1,42 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} -{- | - Module : Text.Pandoc.Lua.Module.Types - Copyright : © 2019-2022 Albert Krewinkel - License : GNU GPL, version 2 or above - - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> - Stability : alpha - -Pandoc data type constructors. --} -module Text.Pandoc.Lua.Module.Types - ( documentedModule - ) where - -import HsLua ( Module (..), (###), (<#>), (=#>) - , defun, functionResult, parameter) -import HsLua.Module.Version (peekVersionFuzzy, pushVersion) -import Text.Pandoc.Error (PandocError) -import Text.Pandoc.Lua.ErrorConversion () - --- | Push the pandoc.types module on the Lua stack. -documentedModule :: Module PandocError -documentedModule = Module - { moduleName = "pandoc.types" - , moduleDescription = - "Constructors for types that are not part of the pandoc AST." - , moduleFields = [] - , moduleFunctions = - [ defun "Version" - ### return - <#> parameter peekVersionFuzzy "string|integer|{integer,...}|Version" - "version_specifier" - (mconcat [ "either a version string like `'2.7.3'`, " - , "a single integer like `2`, " - , "list of integers like `{2,7,3}`, " - , "or a Version object" - ]) - =#> functionResult pushVersion "Version" "A new Version object." - ] - , moduleOperations = [] - } diff --git a/src/Text/Pandoc/Lua/Module/Utils.hs b/src/Text/Pandoc/Lua/Module/Utils.hs deleted file mode 100644 index 33349870c..000000000 --- a/src/Text/Pandoc/Lua/Module/Utils.hs +++ /dev/null @@ -1,239 +0,0 @@ -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{- | - Module : Text.Pandoc.Lua.Module.Utils - Copyright : Copyright © 2017-2022 Albert Krewinkel - License : GNU GPL, version 2 or above - - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> - Stability : alpha - -Utility module for Lua, exposing internal helper functions. --} -module Text.Pandoc.Lua.Module.Utils - ( documentedModule - , sha1 - ) where - -import Control.Applicative ((<|>)) -import Control.Monad ((<$!>)) -import Data.Data (showConstr, toConstr) -import Data.Default (def) -import Data.Maybe (fromMaybe) -import Data.Version (Version) -import HsLua as Lua -import HsLua.Module.Version (peekVersionFuzzy, pushVersion) -import Text.Pandoc.Citeproc (getReferences, processCitations) -import Text.Pandoc.Definition -import Text.Pandoc.Error (PandocError) -import Text.Pandoc.Filter (applyJSONFilter) -import Text.Pandoc.Lua.Marshal.AST -import Text.Pandoc.Lua.Marshal.Reference -import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua)) - -import qualified Data.Digest.Pure.SHA as SHA -import qualified Data.ByteString.Lazy as BSL -import qualified Data.Map as Map -import qualified Data.Text as T -import qualified Text.Pandoc.Builder as B -import qualified Text.Pandoc.Shared as Shared -import qualified Text.Pandoc.UTF8 as UTF8 -import qualified Text.Pandoc.Writers.Shared as Shared - --- | Push the "pandoc.utils" module to the Lua stack. -documentedModule :: Module PandocError -documentedModule = Module - { moduleName = "pandoc.utils" - , moduleDescription = "pandoc utility functions" - , moduleFields = [] - , moduleOperations = [] - , moduleFunctions = - [ defun "blocks_to_inlines" - ### (\blks mSep -> do - let sep = maybe Shared.defaultBlocksSeparator B.fromList mSep - return $ B.toList (Shared.blocksToInlinesWithSep sep blks)) - <#> parameter (peekList peekBlock) "list of blocks" - "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 - <#> parameter pure "AST element" "elem1" "" - <#> parameter pure "AST element" "elem2" "" - =#> functionResult pushBool "boolean" "true iff elem1 == elem2" - - , defun "make_sections" - ### liftPure3 Shared.makeSections - <#> parameter peekBool "boolean" "numbering" "add header numbers" - <#> parameter (\i -> (Nothing <$ peekNil i) <|> (Just <$!> peekIntegral i)) - "integer or nil" "baselevel" "" - <#> parameter (peekList peekBlock) "list of blocks" - "blocks" "document blocks to process" - =#> functionResult pushBlocks "list of Blocks" - "processes blocks" - - , defun "normalize_date" - ### liftPure Shared.normalizeDate - <#> parameter peekText "string" "date" "the date string" - =#> functionResult (maybe pushnil pushText) "string or nil" - "normalized date, or nil if normalization failed." - #? T.unwords - [ "Parse a date and convert (if possible) to \"YYYY-MM-DD\" format. We" - , "limit years to the range 1601-9999 (ISO 8601 accepts greater than" - , "or equal to 1583, but MS Word only accepts dates starting 1601)." - , "Returns nil instead of a string if the conversion failed." - ] - - , sha1 - - , defun "Version" - ### liftPure (id @Version) - <#> parameter peekVersionFuzzy - "version string, list of integers, or integer" - "v" "version description" - =#> functionResult pushVersion "Version" "new Version object" - #? "Creates a Version object." - - , defun "references" - ### (unPandocLua . getReferences Nothing) - <#> parameter peekPandoc "Pandoc" "doc" "document" - =#> functionResult (pushPandocList pushReference) "table" - "lift of references" - #? mconcat - [ "Get references defined inline in the metadata and via an external " - , "bibliography. Only references that are actually cited in the " - , "document (either with a genuine citation or with `nocite`) are " - , "returned. URL variables are converted to links." - ] - - , defun "run_json_filter" - ### (\doc filterPath margs -> do - args <- case margs of - Just xs -> return xs - Nothing -> do - Lua.getglobal "FORMAT" - (forcePeek ((:[]) <$!> peekString top) <* pop 1) - applyJSONFilter def args filterPath doc - ) - <#> parameter peekPandoc "Pandoc" "doc" "input document" - <#> parameter peekString "filepath" "filter_path" "path to filter" - <#> opt (parameter (peekList peekString) "list of strings" - "args" "arguments to pass to the filter") - =#> functionResult pushPandoc "Pandoc" "filtered document" - - , defun "stringify" - ### stringify - <#> parameter pure "AST element" "elem" "some pandoc AST element" - =#> functionResult pushText "string" "stringified element" - - , defun "from_simple_table" - ### from_simple_table - <#> parameter peekSimpleTable "SimpleTable" "simple_tbl" "" - =?> "Simple table" - - , defun "to_roman_numeral" - ### liftPure Shared.toRomanNumeral - <#> parameter (peekIntegral @Int) "integer" "n" "number smaller than 4000" - =#> functionResult pushText "string" "roman numeral" - #? "Converts a number < 4000 to uppercase roman numeral." - - , defun "to_simple_table" - ### to_simple_table - <#> parameter peekTable "Block" "tbl" "a table" - =#> functionResult pushSimpleTable "SimpleTable" "SimpleTable object" - #? "Converts a table into an old/simple table." - - , defun "type" - ### (\idx -> getmetafield idx "__name" >>= \case - TypeString -> fromMaybe mempty <$> tostring top - _ -> ltype idx >>= typename) - <#> parameter pure "any" "object" "" - =#> functionResult pushByteString "string" "type of the given value" - #? ("Pandoc-friendly version of Lua's default `type` function, " <> - "returning the type of a value. If the argument has a " <> - "string-valued metafield `__name`, then it gives that string. " <> - "Otherwise it behaves just like the normal `type` function.") - ] - } - --- | Documented Lua function to compute the hash of a string. -sha1 :: DocumentedFunction e -sha1 = defun "sha1" - ### liftPure (SHA.showDigest . SHA.sha1) - <#> parameter (fmap BSL.fromStrict . peekByteString) "string" "input" "" - =#> functionResult pushString "string" "hexadecimal hash value" - #? "Compute the hash of the given string value." - - --- | Convert pandoc structure to a string with formatting removed. --- Footnotes are skipped (since we don't want their contents in link --- labels). -stringify :: LuaError e => StackIndex -> LuaE e T.Text -stringify idx = forcePeek . retrieving "stringifyable element" $ - choice - [ (fmap Shared.stringify . peekPandoc) - , (fmap Shared.stringify . peekInline) - , (fmap Shared.stringify . peekBlock) - , (fmap Shared.stringify . peekCitation) - , (fmap stringifyMetaValue . peekMetaValue) - , (fmap (const "") . peekAttr) - , (fmap (const "") . peekListAttributes) - ] idx - where - stringifyMetaValue :: MetaValue -> T.Text - stringifyMetaValue mv = case mv of - MetaBool b -> T.toLower $ T.pack (show b) - MetaString s -> s - MetaList xs -> mconcat $ map stringifyMetaValue xs - MetaMap m -> mconcat $ map (stringifyMetaValue . snd) (Map.toList m) - _ -> Shared.stringify mv - --- | Converts an old/simple table into a normal table block element. -from_simple_table :: SimpleTable -> LuaE PandocError NumResults -from_simple_table (SimpleTable capt aligns widths head' body) = do - Lua.push $ Table - nullAttr - (Caption Nothing [Plain capt | not (null capt)]) - (zipWith (\a w -> (a, toColWidth w)) aligns widths) - (TableHead nullAttr [blockListToRow head' | not (null head') ]) - [TableBody nullAttr 0 [] $ map blockListToRow body | not (null body)] - (TableFoot nullAttr []) - return (NumResults 1) - where - blockListToRow :: [[Block]] -> Row - blockListToRow = Row nullAttr . map (B.simpleCell . B.fromList) - - toColWidth :: Double -> ColWidth - toColWidth 0 = ColWidthDefault - toColWidth w = ColWidth w - --- | Converts a table into an old/simple table. -to_simple_table :: Block -> LuaE PandocError SimpleTable -to_simple_table = \case - Table _attr caption specs thead tbodies tfoot -> do - let (capt, aligns, widths, headers, rows) = - Shared.toLegacyTable caption specs thead tbodies tfoot - return $ SimpleTable capt aligns widths headers rows - blk -> Lua.failLua $ mconcat - [ "Expected Table, got ", showConstr (toConstr blk), "." ] - -peekTable :: LuaError e => Peeker e Block -peekTable idx = peekBlock idx >>= \case - t@(Table {}) -> return t - b -> Lua.failPeek $ mconcat - [ "Expected Table, got " - , UTF8.fromString $ showConstr (toConstr b) - , "." ] |
