git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #4227 from tarleb/lua-run-json-filter
f114153John MacFarlane
doc/lua-filters.md+31
@@ -1433,6 +1433,37 @@ functions.
1433 print(table.concat(elements[1].numbering, '.')) -- 0.1
1433 print(table.concat(elements[1].numbering, '.')) -- 0.1
1434 print(table.concat(elements[2].numbering, '.')) -- 0.2
1434 print(table.concat(elements[2].numbering, '.')) -- 0.2
1435
1435
1436+[`run_json_filter (doc, filter[, args])`]{#utils-run_json_filter}
1437+
1438+: Filter the given doc by passing it through the a JSON filter.
1439+
1440+ Parameters:
1441+
1442+ `doc`:
1443+ : the Pandoc document to filter
1444+
1445+ `filter`:
1446+ : filter to run
1447+
1448+ `args`:
1449+ : list of arguments passed to the filter. Defaults to
1450+ `{FORMAT}`.
1451+
1452+ Returns:
1453+
1454+ - ([Pandoc](#Pandoc)) Filtered document
1455+
1456+ Usage:
1457+
1458+ -- Assumes `some_blocks` contains blocks for which a
1459+ -- separate literature section is required.
1460+ local sub_doc = pandoc.Pandoc(some_blocks, metadata)
1461+ sub_doc_with_bib = pandoc.utils.run_json_filter(
1462+ sub_doc,
1463+ 'pandoc-citeproc'
1464+ )
1465+ some_blocks = sub_doc.blocks -- some blocks with bib
1466+
1436[`normalize_date (date_string)`]{#utils-normalize_date}
1467[`normalize_date (date_string)`]{#utils-normalize_date}
1437
1468
1438: Parse a date and convert (if possible) to "YYYY-MM-DD"
1469: Parse a date and convert (if possible) to "YYYY-MM-DD"
pandoc.cabal+5−1
@@ -499,7 +499,11 @@ library
499 Text.Pandoc.ImageSize,
499 Text.Pandoc.ImageSize,
500 Text.Pandoc.BCP47,
500 Text.Pandoc.BCP47,
501 Text.Pandoc.Class
501 Text.Pandoc.Class
502− other-modules: Text.Pandoc.Readers.Docx.Lists,
502+ other-modules: Text.Pandoc.Filter,
503+ Text.Pandoc.Filter.Json,
504+ Text.Pandoc.Filter.Lua,
505+ Text.Pandoc.Filter.Path,
506+ Text.Pandoc.Readers.Docx.Lists,
503 Text.Pandoc.Readers.Docx.Combine,
507 Text.Pandoc.Readers.Docx.Combine,
504 Text.Pandoc.Readers.Docx.Parse,
508 Text.Pandoc.Readers.Docx.Parse,
505 Text.Pandoc.Readers.Docx.Util,
509 Text.Pandoc.Readers.Docx.Util,
src/Text/Pandoc/App.hs+5−95
@@ -46,12 +46,11 @@ import qualified Control.Exception as E
46import Control.Monad
46import Control.Monad
47import Control.Monad.Except (catchError, throwError)
47import Control.Monad.Except (catchError, throwError)
48import Control.Monad.Trans
48import Control.Monad.Trans
49−import Data.Aeson (defaultOptions, eitherDecode', encode)
49+import Data.Aeson (defaultOptions)
50import Data.Aeson.TH (deriveJSON)
50import Data.Aeson.TH (deriveJSON)
51import qualified Data.ByteString as BS
51import qualified Data.ByteString as BS
52import qualified Data.ByteString.Lazy as B
52import qualified Data.ByteString.Lazy as B
53import Data.Char (toLower, toUpper)
53import Data.Char (toLower, toUpper)
54−import Data.Foldable (foldrM)
55import Data.List (find, intercalate, isPrefixOf, isSuffixOf, sort)
54import Data.List (find, intercalate, isPrefixOf, isSuffixOf, sort)
56import qualified Data.Map as M
55import qualified Data.Map as M
57import Data.Maybe (fromMaybe, isJust, isNothing)
56import Data.Maybe (fromMaybe, isJust, isNothing)
@@ -73,10 +72,9 @@ import Skylighting (Style, Syntax (..), defaultSyntaxMap, parseTheme,
73 pygments)
72 pygments)
74import Skylighting.Parser (addSyntaxDefinition, parseSyntaxDefinition)
73import Skylighting.Parser (addSyntaxDefinition, parseSyntaxDefinition)
75import System.Console.GetOpt
74import System.Console.GetOpt
76−import System.Directory (Permissions (..), doesFileExist, findExecutable,
77− getAppUserDataDirectory, getPermissions)
75+import System.Directory (getAppUserDataDirectory)
78−import System.Environment (getArgs, getEnvironment, getProgName)
76+import System.Environment (getArgs, getProgName)
79−import System.Exit (ExitCode (..), exitSuccess)
77+import System.Exit (exitSuccess)
80import System.FilePath
78import System.FilePath
81import System.IO (nativeNewline, stdout)
79import System.IO (nativeNewline, stdout)
82import qualified System.IO as IO (Newline (..))
80import qualified System.IO as IO (Newline (..))
@@ -84,10 +82,9 @@ import System.IO.Error (isDoesNotExistError)
84import Text.Pandoc
82import Text.Pandoc
85import Text.Pandoc.BCP47 (Lang (..), parseBCP47)
83import Text.Pandoc.BCP47 (Lang (..), parseBCP47)
86import Text.Pandoc.Builder (setMeta, deleteMeta)
84import Text.Pandoc.Builder (setMeta, deleteMeta)
85+import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), applyFilters)
87import Text.Pandoc.Highlighting (highlightingStyles)
86import Text.Pandoc.Highlighting (highlightingStyles)
88−import Text.Pandoc.Lua (LuaException (..), runLuaFilter)
89import Text.Pandoc.PDF (makePDF)
87import Text.Pandoc.PDF (makePDF)
90−import Text.Pandoc.Process (pipeProcess)
91import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)
88import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)
92import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
89import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
93 headerShift, isURI, ordNub, safeRead, tabFilter)
90 headerShift, isURI, ordNub, safeRead, tabFilter)
@@ -538,48 +535,6 @@ type Transform = Pandoc -> Pandoc
538isTextFormat :: String -> Bool
535isTextFormat :: String -> Bool
539isTextFormat s = s `notElem` ["odt","docx","epub2","epub3","epub","pptx"]
536isTextFormat s = s `notElem` ["odt","docx","epub2","epub3","epub","pptx"]
540
537
541−externalFilter :: MonadIO m
542− => ReaderOptions -> FilePath -> [String] -> Pandoc -> m Pandoc
543−externalFilter ropts f args' d = liftIO $ do
544− exists <- doesFileExist f
545− isExecutable <- if exists
546− then executable <$> getPermissions f
547− else return True
548− let (f', args'') = if exists
549− then case map toLower (takeExtension f) of
550− _ | isExecutable -> ("." </> f, args')
551− ".py" -> ("python", f:args')
552− ".hs" -> ("runhaskell", f:args')
553− ".pl" -> ("perl", f:args')
554− ".rb" -> ("ruby", f:args')
555− ".php" -> ("php", f:args')
556− ".js" -> ("node", f:args')
557− ".r" -> ("Rscript", f:args')
558− _ -> (f, args')
559− else (f, args')
560− unless (exists && isExecutable) $ do
561− mbExe <- findExecutable f'
562− when (isNothing mbExe) $
563− E.throwIO $ PandocFilterError f ("Could not find executable " ++ f')
564− env <- getEnvironment
565− let env' = Just
566− ( ("PANDOC_VERSION", pandocVersion)
567− : ("PANDOC_READER_OPTIONS", UTF8.toStringLazy (encode ropts))
568− : env )
569− (exitcode, outbs) <- E.handle filterException $
570− pipeProcess env' f' args'' $ encode d
571− case exitcode of
572− ExitSuccess -> either (E.throwIO . PandocFilterError f)
573− return $ eitherDecode' outbs
574− ExitFailure ec -> E.throwIO $ PandocFilterError f
575− ("Filter returned error status " ++ show ec)
576− where filterException :: E.SomeException -> IO a
577− filterException e = E.throwIO $ PandocFilterError f (show e)
578−
579−data Filter = LuaFilter FilePath
580− | JSONFilter FilePath
581− deriving (Show)
582−
583-- | Data structure for command line options.
538-- | Data structure for command line options.
584data Opt = Opt
539data Opt = Opt
585 { optTabStop :: Int -- ^ Number of spaces per tab
540 { optTabStop :: Int -- ^ Number of spaces per tab
@@ -824,50 +779,6 @@ defaultWriterName x =
824applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc
779applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc
825applyTransforms transforms d = return $ foldr ($) d transforms
780applyTransforms transforms d = return $ foldr ($) d transforms
826
781
827− -- First we check to see if a filter is found. If not, and if it's
828− -- not an absolute path, we check to see whether it's in `userdir/filters`.
829− -- If not, we leave it unchanged.
830−expandFilterPath :: PandocMonad m => FilePath -> m FilePath
831−expandFilterPath fp = do
832− mbDatadir <- getUserDataDir
833− fpExists <- fileExists fp
834− if fpExists
835− then return fp
836− else case mbDatadir of
837− Just datadir | isRelative fp -> do
838− let filterPath = datadir </> "filters" </> fp
839− filterPathExists <- fileExists filterPath
840− if filterPathExists
841− then return filterPath
842− else return fp
843− _ -> return fp
844−
845−applyFilters :: ReaderOptions
846− -> [Filter]
847− -> [String]
848− -> Pandoc
849− -> PandocIO Pandoc
850−applyFilters ropts filters args d = do
851− foldrM ($) d $ map (applyFilter ropts args) filters
852−
853−applyFilter :: ReaderOptions
854− -> [String]
855− -> Filter
856− -> Pandoc
857− -> PandocIO Pandoc
858−applyFilter ropts args (LuaFilter f) d = do
859− f' <- expandFilterPath f
860− let format = case args of
861− (x:_) -> x
862− _ -> error "Format not supplied for lua filter"
863− res <- runLuaFilter ropts f' format d
864− case res of
865− Right x -> return x
866− Left (LuaException s) -> E.throw (PandocFilterError f s)
867−applyFilter ropts args (JSONFilter f) d = do
868− f' <- expandFilterPath f
869− liftIO $ externalFilter ropts f' args d
870−
871readSource :: FilePath -> PandocIO Text
782readSource :: FilePath -> PandocIO Text
872readSource "-" = liftIO (UTF8.toText <$> BS.getContents)
783readSource "-" = liftIO (UTF8.toText <$> BS.getContents)
873readSource src = case parseURI src of
784readSource src = case parseURI src of
@@ -1722,5 +1633,4 @@ deprecatedOption o msg =
1722-- see https://github.com/jgm/pandoc/pull/4083
1633-- see https://github.com/jgm/pandoc/pull/4083
1723-- using generic deriving caused long compilation times
1634-- using generic deriving caused long compilation times
1724$(deriveJSON defaultOptions ''LineEnding)
1635$(deriveJSON defaultOptions ''LineEnding)
1725−$(deriveJSON defaultOptions ''Filter)
1726$(deriveJSON defaultOptions ''Opt)
1636$(deriveJSON defaultOptions ''Opt)
src/Text/Pandoc/Filter.hsnew file+60
@@ -0,0 +1,60 @@
1+{-
2+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>
3+
4+This program is free software; you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation; either version 2 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program; if not, write to the Free Software
16+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+-}
18+{-# LANGUAGE TemplateHaskell #-}
19+
20+{- |
21+ Module : Text.Pandoc.Filter
22+ Copyright : Copyright (C) 2006-2017 John MacFarlane
23+ License : GNU GPL, version 2 or above
24+
25+ Maintainer : John MacFarlane <jgm@berkeley@edu>
26+ Stability : alpha
27+ Portability : portable
28+
29+Programmatically modifications of pandoc documents.
30+-}
31+module Text.Pandoc.Filter
32+ ( Filter (..)
33+ , applyFilters
34+ ) where
35+
36+import Data.Aeson (defaultOptions)
37+import Data.Aeson.TH (deriveJSON)
38+import Data.Foldable (foldrM)
39+import Text.Pandoc.Class (PandocIO)
40+import Text.Pandoc.Definition (Pandoc)
41+import Text.Pandoc.Options (ReaderOptions)
42+import qualified Text.Pandoc.Filter.Json as JsonFilter
43+import qualified Text.Pandoc.Filter.Lua as LuaFilter
44+
45+data Filter = LuaFilter FilePath
46+ | JSONFilter FilePath
47+ deriving (Show)
48+
49+applyFilters :: ReaderOptions
50+ -> [Filter]
51+ -> [String]
52+ -> Pandoc
53+ -> PandocIO Pandoc
54+applyFilters ropts filters args d = do
55+ foldrM ($) d $ map applyFilter filters
56+ where
57+ applyFilter (JSONFilter f) = JsonFilter.apply ropts args f
58+ applyFilter (LuaFilter f) = LuaFilter.apply ropts args f
59+
60+$(deriveJSON defaultOptions ''Filter)
src/Text/Pandoc/Filter/Json.hsnew file+97
@@ -0,0 +1,97 @@
1+{-
2+Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
3+
4+This program is free software; you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation; either version 2 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program; if not, write to the Free Software
16+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+-}
18+
19+{- |
20+ Module : Text.Pandoc.Filter
21+ Copyright : Copyright (C) 2006-2018 John MacFarlane
22+ License : GNU GPL, version 2 or above
23+
24+ Maintainer : John MacFarlane <jgm@berkeley@edu>
25+ Stability : alpha
26+ Portability : portable
27+
28+Programmatically modifications of pandoc documents via JSON filters.
29+-}
30+module Text.Pandoc.Filter.Json (apply) where
31+
32+import Control.Monad (unless, when)
33+import Control.Monad.Trans (MonadIO (liftIO))
34+import Data.Aeson (eitherDecode', encode)
35+import Data.Char (toLower)
36+import Data.Maybe (isNothing)
37+import System.Directory (executable, doesFileExist, findExecutable,
38+ getPermissions)
39+import System.Environment (getEnvironment)
40+import System.Exit (ExitCode (..))
41+import System.FilePath ((</>), takeExtension)
42+import Text.Pandoc.Class (PandocIO)
43+import Text.Pandoc.Error (PandocError (PandocFilterError))
44+import Text.Pandoc.Definition (Pandoc)
45+import Text.Pandoc.Filter.Path (expandFilterPath)
46+import Text.Pandoc.Options (ReaderOptions)
47+import Text.Pandoc.Process (pipeProcess)
48+import Text.Pandoc.Shared (pandocVersion)
49+import qualified Control.Exception as E
50+import qualified Text.Pandoc.UTF8 as UTF8
51+
52+apply :: ReaderOptions
53+ -> [String]
54+ -> FilePath
55+ -> Pandoc
56+ -> PandocIO Pandoc
57+apply ropts args f d = do
58+ f' <- expandFilterPath f
59+ liftIO $ externalFilter ropts f' args d
60+
61+externalFilter :: MonadIO m
62+ => ReaderOptions -> FilePath -> [String] -> Pandoc -> m Pandoc
63+externalFilter ropts f args' d = liftIO $ do
64+ exists <- doesFileExist f
65+ isExecutable <- if exists
66+ then executable <$> getPermissions f
67+ else return True
68+ let (f', args'') = if exists
69+ then case map toLower (takeExtension f) of
70+ _ | isExecutable -> ("." </> f, args')
71+ ".py" -> ("python", f:args')
72+ ".hs" -> ("runhaskell", f:args')
73+ ".pl" -> ("perl", f:args')
74+ ".rb" -> ("ruby", f:args')
75+ ".php" -> ("php", f:args')
76+ ".js" -> ("node", f:args')
77+ ".r" -> ("Rscript", f:args')
78+ _ -> (f, args')
79+ else (f, args')
80+ unless (exists && isExecutable) $ do
81+ mbExe <- findExecutable f'
82+ when (isNothing mbExe) $
83+ E.throwIO $ PandocFilterError f ("Could not find executable " ++ f')
84+ env <- getEnvironment
85+ let env' = Just
86+ ( ("PANDOC_VERSION", pandocVersion)
87+ : ("PANDOC_READER_OPTIONS", UTF8.toStringLazy (encode ropts))
88+ : env )
89+ (exitcode, outbs) <- E.handle filterException $
90+ pipeProcess env' f' args'' $ encode d
91+ case exitcode of
92+ ExitSuccess -> either (E.throwIO . PandocFilterError f)
93+ return $ eitherDecode' outbs
94+ ExitFailure ec -> E.throwIO $ PandocFilterError f
95+ ("Filter returned error status " ++ show ec)
96+ where filterException :: E.SomeException -> IO a
97+ filterException e = E.throwIO $ PandocFilterError f (show e)
src/Text/Pandoc/Filter/Lua.hsnew file+53
@@ -0,0 +1,53 @@
1+{-
2+Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
3+
4+This program is free software; you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation; either version 2 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program; if not, write to the Free Software
16+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+-}
18+
19+{- |
20+ Module : Text.Pandoc.Filter.Lua
21+ Copyright : Copyright (C) 2006-2018 John MacFarlane
22+ License : GNU GPL, version 2 or above
23+
24+ Maintainer : John MacFarlane <jgm@berkeley@edu>
25+ Stability : alpha
26+ Portability : portable
27+
28+Apply Lua filters to modify a pandoc documents programmatically.
29+-}
30+module Text.Pandoc.Filter.Lua (apply) where
31+
32+import Control.Exception (throw)
33+import Text.Pandoc.Class (PandocIO)
34+import Text.Pandoc.Definition (Pandoc)
35+import Text.Pandoc.Error (PandocError (PandocFilterError))
36+import Text.Pandoc.Filter.Path (expandFilterPath)
37+import Text.Pandoc.Lua (LuaException (..), runLuaFilter)
38+import Text.Pandoc.Options (ReaderOptions)
39+
40+apply :: ReaderOptions
41+ -> [String]
42+ -> FilePath
43+ -> Pandoc
44+ -> PandocIO Pandoc
45+apply ropts args f d = do
46+ f' <- expandFilterPath f
47+ let format = case args of
48+ (x:_) -> x
49+ _ -> error "Format not supplied for lua filter"
50+ res <- runLuaFilter ropts f' format d
51+ case res of
52+ Right x -> return x
53+ Left (LuaException s) -> throw (PandocFilterError f s)
src/Text/Pandoc/Filter/Path.hsnew file+53
@@ -0,0 +1,53 @@
1+{-
2+Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
3+
4+This program is free software; you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation; either version 2 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program; if not, write to the Free Software
16+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+-}
18+
19+{- |
20+ Module : Text.Pandoc.Filter.Path
21+ Copyright : Copyright (C) 2006-2018 John MacFarlane
22+ License : GNU GPL, version 2 or above
23+
24+ Maintainer : John MacFarlane <jgm@berkeley@edu>
25+ Stability : alpha
26+ Portability : portable
27+
28+Expand paths of filters, searching the data directory.
29+-}
30+module Text.Pandoc.Filter.Path
31+ ( expandFilterPath
32+ ) where
33+
34+import Text.Pandoc.Class (PandocMonad, fileExists, getUserDataDir)
35+import System.FilePath ((</>), isRelative)
36+
37+ -- First we check to see if a filter is found. If not, and if it's
38+ -- not an absolute path, we check to see whether it's in `userdir/filters`.
39+ -- If not, we leave it unchanged.
40+expandFilterPath :: PandocMonad m => FilePath -> m FilePath
41+expandFilterPath fp = do
42+ mbDatadir <- getUserDataDir
43+ fpExists <- fileExists fp
44+ if fpExists
45+ then return fp
46+ else case mbDatadir of
47+ Just datadir | isRelative fp -> do
48+ let filterPath = datadir </> "filters" </> fp
49+ filterPathExists <- fileExists filterPath
50+ if filterPathExists
51+ then return filterPath
52+ else return fp
53+ _ -> return fp
src/Text/Pandoc/Lua/Module/Utils.hs+26−3
@@ -30,22 +30,26 @@ module Text.Pandoc.Lua.Module.Utils
30 ) where
30 ) where
31
31
32import Control.Applicative ((<|>))
32import Control.Applicative ((<|>))
33+import Data.Default (def)
33import Foreign.Lua (FromLuaStack, Lua, LuaInteger, NumResults)
34import Foreign.Lua (FromLuaStack, Lua, LuaInteger, NumResults)
35+import Text.Pandoc.Class (runIO, setUserDataDir)
34import Text.Pandoc.Definition (Pandoc, Meta, MetaValue, Block, Inline)
36import Text.Pandoc.Definition (Pandoc, Meta, MetaValue, Block, Inline)
35import Text.Pandoc.Lua.StackInstances ()
37import Text.Pandoc.Lua.StackInstances ()
36−import Text.Pandoc.Lua.Util (addFunction)
38+import Text.Pandoc.Lua.Util (addFunction, popValue)
37
39
38import qualified Data.Digest.Pure.SHA as SHA
40import qualified Data.Digest.Pure.SHA as SHA
39import qualified Data.ByteString.Lazy as BSL
41import qualified Data.ByteString.Lazy as BSL
40import qualified Foreign.Lua as Lua
42import qualified Foreign.Lua as Lua
43+import qualified Text.Pandoc.Filter.Json as JsonFilter
41import qualified Text.Pandoc.Shared as Shared
44import qualified Text.Pandoc.Shared as Shared
42
45
43-- | Push the "pandoc.utils" module to the lua stack.
46-- | Push the "pandoc.utils" module to the lua stack.
44−pushModule :: Lua NumResults
47+pushModule :: Maybe FilePath -> Lua NumResults
45−pushModule = do
48+pushModule mbDatadir = do
46 Lua.newtable
49 Lua.newtable
47 addFunction "hierarchicalize" hierarchicalize
50 addFunction "hierarchicalize" hierarchicalize
48 addFunction "normalize_date" normalizeDate
51 addFunction "normalize_date" normalizeDate
52+ addFunction "run_json_filter" (runJsonFilter mbDatadir)
49 addFunction "sha1" sha1
53 addFunction "sha1" sha1
50 addFunction "stringify" stringify
54 addFunction "stringify" stringify
51 addFunction "to_roman_numeral" toRomanNumeral
55 addFunction "to_roman_numeral" toRomanNumeral
@@ -62,6 +66,25 @@ hierarchicalize = return . Shared.hierarchicalize
62normalizeDate :: String -> Lua (Lua.Optional String)
66normalizeDate :: String -> Lua (Lua.Optional String)
63normalizeDate = return . Lua.Optional . Shared.normalizeDate
67normalizeDate = return . Lua.Optional . Shared.normalizeDate
64
68
69+-- | Run a JSON filter on the given document.
70+runJsonFilter :: Maybe FilePath
71+ -> Pandoc
72+ -> FilePath
73+ -> Lua.Optional [String]
74+ -> Lua NumResults
75+runJsonFilter mbDatadir doc filterFile optArgs = do
76+ args <- case Lua.fromOptional optArgs of
77+ Just x -> return x
78+ Nothing -> do
79+ Lua.getglobal "FORMAT"
80+ (:[]) <$> popValue
81+ filterRes <- Lua.liftIO . runIO $ do
82+ setUserDataDir mbDatadir
83+ JsonFilter.apply def args filterFile doc
84+ case filterRes of
85+ Left err -> Lua.raiseError (show err)
86+ Right d -> (1 :: NumResults) <$ Lua.push d
87+
65-- | Calculate the hash of the given contents.
88-- | Calculate the hash of the given contents.
66sha1 :: BSL.ByteString
89sha1 :: BSL.ByteString
67 -> Lua String
90 -> Lua String
src/Text/Pandoc/Lua/Packages.hs+2−1
@@ -78,7 +78,8 @@ pandocPackageSearcher luaPkgParams pkgName =
78 "pandoc.mediabag" -> let st = luaPkgCommonState luaPkgParams
78 "pandoc.mediabag" -> let st = luaPkgCommonState luaPkgParams
79 mbRef = luaPkgMediaBag luaPkgParams
79 mbRef = luaPkgMediaBag luaPkgParams
80 in pushWrappedHsFun (MediaBag.pushModule st mbRef)
80 in pushWrappedHsFun (MediaBag.pushModule st mbRef)
81+ "pandoc.utils" -> let datadirMb = luaPkgDataDir luaPkgParams
81− "pandoc.utils" -> pushWrappedHsFun Utils.pushModule
82+ in pushWrappedHsFun (Utils.pushModule datadirMb)
82 _ -> searchPureLuaLoader
83 _ -> searchPureLuaLoader
83 where
84 where
84 pushWrappedHsFun f = do
85 pushWrappedHsFun f = do