pandoc-lua-marshal 0.2.8 → 0.2.9
raw patch · 6 files changed
+138/−3 lines, 6 filesdep ~hslua-list
Dependency ranges changed: hslua-list
Files
- CHANGELOG.md +13/−0
- pandoc-lua-marshal.cabal +2/−2
- src/Text/Pandoc/Lua/Marshal/Block.hs +20/−0
- src/Text/Pandoc/Lua/Marshal/Inline.hs +21/−1
- test/test-block.lua +41/−0
- test/test-inline.lua +41/−0
CHANGELOG.md view
@@ -2,6 +2,19 @@ `pandoc-lua-marshal` uses [PVP Versioning][]. +## 0.2.9++Released 2024-10-01.++- Update list module, thereby introducing a new method `iter`;+ the function returns an iterator that steps through list+ values on each call.++- Added support for `__toinline` and `__toblock` metamethods. If+ the metamethods are available on a Lua object and return an+ appropriate value, then that returned value will be used+ during unmarshalling.+ ## 0.2.8 Released 2024-09-21.
pandoc-lua-marshal.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: pandoc-lua-marshal-version: 0.2.8+version: 0.2.9 synopsis: Use pandoc types in Lua description: This package provides functions to marshal and unmarshal pandoc document types to and from Lua.@@ -51,7 +51,7 @@ , containers >= 0.6 && < 0.8 , exceptions >= 0.8 && < 0.11 , hslua >= 2.2 && < 2.4- , hslua-list >= 1.1.2 && < 1.2+ , hslua-list >= 1.1.4 && < 1.2 , hslua-marshalling >= 2.2 && < 2.4 , pandoc-types >= 1.23 && < 1.24 , safe >= 0.3 && < 0.4
src/Text/Pandoc/Lua/Marshal/Block.hs view
@@ -109,12 +109,32 @@ setmetatable (nth 2) {-# INLINABLE pushBlocks #-} +-- | Unmarshal a table as Block value by calling the @__toblock@ metamethod+-- first.+peekBlockMetamethod :: LuaError e+ => Peeker e Block+peekBlockMetamethod idx = do+ absidx <- liftLua $ absindex idx+ liftLua (getmetafield absidx "__toblock") >>= \case+ TypeNil -> failPeek "object has no __toblock metamethod"+ TypeFunction -> do+ liftLua (pushvalue absidx)+ liftLua (pcall 1 1 Nothing) >>= \case+ OK -> peekBlock top `lastly` pop 1+ _err -> do+ msg <- peekByteString top `lastly` pop 1+ failPeek $ "failure in __toblock: " <> msg+ _otherType -> do+ liftLua (pop 1) -- drop "__toblock" field+ failPeek "__toblock metafield does not contain a function"+ -- | Try extra hard to retrieve an Block value from the stack. Treats -- bare strings as @Str@ values. peekBlockFuzzy :: LuaError e => Peeker e Block peekBlockFuzzy idx = peekBlock idx+ <|> peekBlockMetamethod idx <|> (Plain <$!> peekInlinesFuzzy idx) <|> (failPeek =<< typeMismatchMessage "Block or list of Inlines" idx)
src/Text/Pandoc/Lua/Marshal/Inline.hs view
@@ -103,12 +103,32 @@ setmetatable (nth 2) {-# INLINABLE pushInlines #-} +-- | Unmarshal a value as Inline object by first calling the @__toinline@+-- metamethod on that object.+peekInlineMetamethod :: LuaError e+ => Peeker e Inline+peekInlineMetamethod idx = do+ absidx <- liftLua $ absindex idx+ liftLua (getmetafield absidx "__toinline") >>= \case+ TypeNil -> failPeek "object has no __toinline metamethod"+ TypeFunction -> do+ liftLua (pushvalue absidx)+ liftLua (pcall 1 1 Nothing) >>= \case+ OK -> peekInline top `lastly` pop 1+ _err -> do+ msg <- peekByteString top `lastly` pop 1+ failPeek $ "failure in __toinline: " <> msg+ _otherType -> do+ liftLua (pop 1) -- drop "__toinline" field+ failPeek "__toinline metafield does not contain a function"+ -- | Try extra hard to retrieve an Inline value from the stack. Treats -- bare strings as @Str@ values. peekInlineFuzzy :: LuaError e => Peeker e Inline peekInlineFuzzy idx = retrieving "Inline" $ liftLua (ltype idx) >>= \case TypeString -> Str <$!> peekText idx- _ -> peekInline idx+ TypeTable -> peekInlineMetamethod idx <|> peekInline idx+ _ -> peekInline idx <|> peekInlineMetamethod idx {-# INLINABLE peekInlineFuzzy #-} -- | Try extra-hard to return the value at the given index as a list of
test/test-block.lua view
@@ -670,5 +670,46 @@ names ) end),+ },++ group 'Block marshalling' {+ test('Inlines are unmarshalled as Plain', function ()+ assert.are_equal(Blocks{Plain{'a'}}, Blocks{Inlines{Str 'a'}})+ end),++ group '__toblock metamethod' {+ test('metamethod __toblock is called when available', function ()+ local function toblock (t)+ return CodeBlock(t.code, {id = t.id, class = t.class})+ end+ local my_code = setmetatable(+ {code = 'open access', id='opn'},+ {__toblock = toblock}+ )+ assert.are_equal(+ Div{CodeBlock('open access', {'opn'})},+ Div{my_code}+ )+ end),++ test("metafield is ignored if it's not a function", function ()+ local bad_block = setmetatable({'a'}, {__toblock = true})+ assert.are_equal(+ Blocks{Plain{'a'}, Plain{'b'}},+ Blocks{bad_block, {'b'}}+ )+ end),++ test("non-Block return values are ignored", function ()+ local function toblock ()+ return "not a block"+ end+ local bad_block = setmetatable({'a'}, {__toblock = toblock})+ assert.are_equal(+ Blocks{Plain{'b'}, Plain{'a'}},+ Blocks{Plain{'b'}, bad_block}+ )+ end),+ } } }
test/test-inline.lua view
@@ -457,5 +457,46 @@ table.concat(names, ', ') ) end),+ },++ group 'marshalling' {+ test('bare strings become Str values', function ()+ assert.are_equal(Inlines{'a'}, Inlines{Str 'a'})+ end),++ group '__toinline metamethod' {+ test('metamethod __toinline is called when available', function ()+ local function toinline (t)+ return Code(t.code, {id = t.id, class = t.class})+ end+ local my_code = setmetatable(+ {code = 'open access', id='opn'},+ {__toinline = toinline}+ )+ assert.are_equal(+ Inlines{Code('open access', {'opn'})},+ Inlines{my_code}+ )+ end),++ test("metafield is ignored if it's not a function", function ()+ local bad_inline = setmetatable({'a'}, {__toinline = true})+ assert.are_equal(+ Inlines({'a'}),+ Inlines(bad_inline)+ )+ end),++ test("non-Inline return values are ignored", function ()+ local function toinline ()+ return "not an inline"+ end+ local bad_inline = setmetatable({'a'}, {__toinline = toinline})+ assert.are_equal(+ Inlines({'a'}),+ Inlines(bad_inline)+ )+ end),+ } } }