git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #3550 from tarleb/lua-readers-submodule

Lua module: add readers submodule

commite62fbc1c3cad8ce504ccf0538ad9f065d46e223b authorJohn MacFarlane <jgm@berkeley.edu> dateMon 3 Apr 2017, 09:47 (10 years ago) parente281a7ce7eb21e
6 files changed+172−32
pandoc.cabal+4−2 src/Text/Pandoc/Lua.hs+3−28 src/Text/Pandoc/Lua/PandocModule.hs+72−2 src/Text/Pandoc/Lua/StackInstances.hs+75 test/Tests/Lua.hs+6 test/lua/markdown-reader.lua+12
pandoc.cabal+4−2
@@ -247,9 +247,10 @@ Extra-Source-Files:
247247 test/odt/odt/*.odt
248248 test/odt/markdown/*.md
249249 test/odt/native/*.native
250− test/lua/strmacro.lua
251− test/lua/plain-to-para.lua
252250 test/lua/hello-world-doc.lua
251+ test/lua/markdown-reader.lua
252+ test/lua/plain-to-para.lua
253+ test/lua/strmacro.lua
253254Source-repository head
254255 type: git
255256 location: git://github.com/jgm/pandoc.git
@@ -457,6 +458,7 @@ Library
457458 Text.Pandoc.Readers.Org.Shared,
458459 Text.Pandoc.Lua.Compat,
459460 Text.Pandoc.Lua.PandocModule,
461+ Text.Pandoc.Lua.StackInstances,
460462 Text.Pandoc.CSS,
461463 Text.Pandoc.UUID,
462464 Text.Pandoc.Slides,
src/Text/Pandoc/Lua.hs+3−28
@@ -15,11 +15,7 @@ You should have received a copy of the GNU General Public License
1515along with this program; if not, write to the Free Software
1616Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1717-}
18−{-# LANGUAGE FlexibleContexts #-}
19−{-# LANGUAGE LambdaCase #-}
2018{-# LANGUAGE OverloadedStrings #-}
21−{-# LANGUAGE ScopedTypeVariables #-}
22−{-# OPTIONS_GHC -fno-warn-orphans #-}
2319{- |
2420 Module : Text.Pandoc.Lua
2521 Copyright : Copyright © 2017 Albert Krewinkel
@@ -34,24 +30,23 @@ module Text.Pandoc.Lua ( runLuaFilter ) where
3430
3531import Control.Monad ( (>=>), when )
3632import Control.Monad.Trans ( MonadIO(..) )
37−import Data.Aeson ( FromJSON(..), ToJSON(..), Result(..), Value, fromJSON )
3833import Data.HashMap.Lazy ( HashMap )
3934import Data.Text ( Text, pack, unpack )
4035import Data.Text.Encoding ( decodeUtf8 )
4136import Scripting.Lua ( LuaState, StackValue(..) )
42−import Scripting.Lua.Aeson ()
37+import Scripting.Lua.Aeson ( newstate )
4338import Text.Pandoc.Definition ( Block(..), Inline(..), Pandoc(..) )
4439import Text.Pandoc.Lua.PandocModule
40+import Text.Pandoc.Lua.StackInstances ()
4541import Text.Pandoc.Walk
4642
4743import qualified Data.HashMap.Lazy as HashMap
4844import qualified Scripting.Lua as Lua
49−import qualified Scripting.Lua as LuaAeson
5045
5146runLuaFilter :: (MonadIO m)
5247 => FilePath -> [String] -> Pandoc -> m Pandoc
5348runLuaFilter filterPath args pd = liftIO $ do
54− lua <- LuaAeson.newstate
49+ lua <- newstate
5550 Lua.openlibs lua
5651 Lua.newtable lua
5752 Lua.setglobal lua "PANDOC_FILTER_FUNCTIONS" -- hack, store functions here
@@ -204,23 +199,3 @@ isLuaFunction lua fnName = do
204199 res <- Lua.isfunction lua (-1)
205200 Lua.pop lua (-1)
206201 return res
207−
208−maybeFromJson :: (FromJSON a) => Maybe Value -> Maybe a
209−maybeFromJson mv = fromJSON <$> mv >>= \case
210− Success x -> Just x
211− _ -> Nothing
212−
213−instance StackValue Pandoc where
214− push lua = Lua.push lua . toJSON
215− peek lua i = maybeFromJson <$> peek lua i
216− valuetype _ = Lua.TTABLE
217−
218−instance StackValue Block where
219− push lua = Lua.push lua . toJSON
220− peek lua i = maybeFromJson <$> peek lua i
221− valuetype _ = Lua.TTABLE
222−
223−instance StackValue Inline where
224− push lua = Lua.push lua . toJSON
225− peek lua i = maybeFromJson <$> peek lua i
226− valuetype _ = Lua.TTABLE
src/Text/Pandoc/Lua/PandocModule.hs+72−2
@@ -28,11 +28,25 @@ Pandoc module for lua.
2828module Text.Pandoc.Lua.PandocModule ( pushPandocModule ) where
2929
3030import Data.ByteString.Char8 ( unpack )
31−import Scripting.Lua ( LuaState, call)
31+import Data.Default ( Default(..) )
32+import Scripting.Lua ( LuaState, call, newtable, push, pushhsfunction, rawset)
33+import Text.Pandoc.Class hiding ( readDataFile )
34+import Text.Pandoc.Definition ( Pandoc(..), Block(..) )
3235import Text.Pandoc.Lua.Compat ( loadstring )
36+import Text.Pandoc.Lua.StackInstances ()
37+import Text.Pandoc.Readers.DocBook ( readDocBook )
38+import Text.Pandoc.Readers.HTML ( readHtml )
39+import Text.Pandoc.Readers.LaTeX ( readLaTeX )
40+import Text.Pandoc.Readers.Native ( readNative )
41+import Text.Pandoc.Readers.Markdown ( readMarkdown )
42+import Text.Pandoc.Readers.MediaWiki ( readMediaWiki )
43+import Text.Pandoc.Readers.Org ( readOrg )
44+import Text.Pandoc.Readers.RST ( readRST )
45+import Text.Pandoc.Readers.Textile ( readTextile )
46+import Text.Pandoc.Readers.TWiki ( readTWiki )
47+import Text.Pandoc.Readers.Txt2Tags ( readTxt2Tags )
3348import Text.Pandoc.Shared ( readDataFile )
3449
35−
3650-- | Push the "pandoc" on the lua stack.
3751pushPandocModule :: LuaState -> IO ()
3852pushPandocModule lua = do
@@ -42,7 +56,63 @@ pushPandocModule lua = do
4256 then return ()
4357 else do
4458 call lua 0 1
59+ push lua "reader"
60+ pushReadersModule lua readers
61+ rawset lua (-3)
62+
63+readers :: [(String, String -> PandocIO Pandoc)]
64+readers =
65+ [ ("docbook", readDocBook def)
66+ , ("html", readHtml def)
67+ , ("latex", readLaTeX def)
68+ , ("native", readNative def)
69+ , ("markdown", readMarkdown def)
70+ , ("mediawiki", readMediaWiki def)
71+ , ("org", readOrg def)
72+ , ("rst", readRST def)
73+ , ("textile", readTextile def)
74+ , ("twiki", readTWiki def)
75+ , ("txt2tags", readTxt2Tags def)
76+ ]
4577
4678-- | Get the string representation of the pandoc module
4779pandocModuleScript :: IO String
4880pandocModuleScript = unpack <$> readDataFile Nothing "pandoc.lua"
81+
82+-- | Push a lua table containing readers of the given formats.
83+pushReadersModule :: LuaState
84+ -> [(String, String -> PandocIO Pandoc)]
85+ -> IO ()
86+pushReadersModule lua readerFns = do
87+ newtable lua
88+ mapM_ (uncurry $ addReaderTable) readerFns
89+ where
90+ addReaderTable :: String
91+ -> (String -> PandocIO Pandoc)
92+ -> IO ()
93+ addReaderTable formatName readerFn = do
94+ let readDoc :: String -> IO Pandoc
95+ readDoc s = do
96+ res <- runIO $ readerFn s
97+ case res of
98+ (Left x) -> error (show x)
99+ (Right x) -> return x
100+ let readBlock :: String -> IO Block
101+ readBlock s = do
102+ Pandoc _ blks <- readDoc s
103+ return $ case blks of
104+ x:_ -> x
105+ _ -> Null
106+ -- Push table containing all functions for this format
107+ push lua formatName
108+ newtable lua
109+ -- set document-reading function
110+ push lua "read_doc"
111+ pushhsfunction lua readDoc
112+ rawset lua (-3)
113+ -- set block-reading function
114+ push lua "read_block"
115+ pushhsfunction lua readBlock
116+ rawset lua (-3)
117+ -- store table in readers module
118+ rawset lua (-3)
src/Text/Pandoc/Lua/StackInstances.hsnew file+75
@@ -0,0 +1,75 @@
1+{-
2+Copyright © 2012-2015 John MacFarlane <jgm@berkeley.edu>
3+ 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
4+
5+This program is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 2 of the License, or
8+(at your option) any later version.
9+
10+This program is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with this program; if not, write to the Free Software
17+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18+-}
19+{-# LANGUAGE CPP #-}
20+{-# LANGUAGE FlexibleInstances #-}
21+{-# LANGUAGE LambdaCase #-}
22+#if !MIN_VERSION_base(4,8,0)
23+{-# LANGUAGE OverlappingInstances #-}
24+#endif
25+{-# OPTIONS_GHC -fno-warn-orphans #-}
26+{- |
27+ Module : Text.Pandoc.Lua.StackInstances
28+ Copyright : Copyright © 2017 Albert Krewinkel
29+ License : GNU GPL, version 2 or above
30+
31+ Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
32+ Stability : alpha
33+
34+StackValue instances for pandoc types.
35+-}
36+module Text.Pandoc.Lua.StackInstances () where
37+
38+import Data.Aeson ( FromJSON(..), ToJSON(..), Result(..), Value, fromJSON )
39+import Scripting.Lua ( StackValue(..) )
40+import Scripting.Lua.Aeson ()
41+import Text.Pandoc.Definition ( Block(..), Inline(..), Pandoc(..) )
42+
43+import qualified Scripting.Lua as Lua
44+import qualified Text.Pandoc.UTF8 as UTF8
45+
46+maybeFromJson :: (FromJSON a) => Maybe Value -> Maybe a
47+maybeFromJson mv = fromJSON <$> mv >>= \case
48+ Success x -> Just x
49+ _ -> Nothing
50+
51+instance StackValue Pandoc where
52+ push lua = Lua.push lua . toJSON
53+ peek lua i = maybeFromJson <$> peek lua i
54+ valuetype _ = Lua.TTABLE
55+
56+instance StackValue Block where
57+ push lua = Lua.push lua . toJSON
58+ peek lua i = maybeFromJson <$> peek lua i
59+ valuetype _ = Lua.TTABLE
60+
61+instance StackValue Inline where
62+ push lua = Lua.push lua . toJSON
63+ peek lua i = maybeFromJson <$> peek lua i
64+ valuetype _ = Lua.TTABLE
65+
66+#if MIN_VERSION_base(4,8,0)
67+instance {-# OVERLAPS #-} StackValue [Char] where
68+#else
69+instance StackValue [Char] where
70+#endif
71+ push lua cs = Lua.push lua (UTF8.fromString cs)
72+ peek lua i = do
73+ res <- Lua.peek lua i
74+ return $ UTF8.toString `fmap` res
75+ valuetype _ = Lua.TSTRING
test/Tests/Lua.hs+6
@@ -26,6 +26,12 @@ tests =
2626 "hello-world-doc.lua"
2727 (doc . para $ str "Hey!" <> linebreak <> str "What's up?")
2828 (doc . para $ str "Hello," <> space <> str "World!")
29+
30+ , testCase "parse raw markdown blocks" $
31+ assertFilterConversion "raw markdown block is converted"
32+ "markdown-reader.lua"
33+ (doc $ rawBlock "markdown" "*charly* **delta**")
34+ (doc . para $ emph "charly" <> space <> strong "delta")
2935 ]
3036
3137assertFilterConversion :: String -> FilePath -> Pandoc -> Pandoc -> Assertion
test/lua/markdown-reader.luanew file+12
@@ -0,0 +1,12 @@
1+return {
2+ {
3+ RawBlock = function (blk)
4+ local format, content = unpack(blk.c)
5+ if format == "markdown" then
6+ return pandoc.reader.markdown.read_block(content)
7+ else
8+ return blk
9+ end
10+ end,
11+ }
12+}