packages feed

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 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),+    }   } }