From 672a4bdd1d4a587feaa38613fce64335adaad76d Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Wed, 15 Jan 2020 23:26:00 +0100 Subject: Lua filters: allow filtering of element lists (#6040) Lists of Inline and Block elements can now be filtered via `Inlines` and `Blocks` functions, respectively. This is helpful if a filter conversion depends on the order of elements rather than a single element. For example, the following filter can be used to remove all spaces before a citation: function isSpaceBeforeCite (spc, cite) return spc and spc.t == 'Space' and cite and cite.t == 'Cite' end function Inlines (inlines) for i = #inlines-1,1,-1 do if isSpaceBeforeCite(inlines[i], inlines[i+1]) then inlines:remove(i) end end return inlines end Closes: #6038 --- test/Tests/Lua.hs | 25 ++++++++++++++++++++++++- test/lua/blocks-filter.lua | 8 ++++++++ test/lua/inlines-filter.lua | 19 +++++++++++++++++++ test/lua/meta.lua | 6 ++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/lua/blocks-filter.lua create mode 100644 test/lua/inlines-filter.lua create mode 100644 test/lua/meta.lua (limited to 'test') diff --git a/test/Tests/Lua.hs b/test/Tests/Lua.hs index 7683df09f..5e01266c0 100644 --- a/test/Tests/Lua.hs +++ b/test/Tests/Lua.hs @@ -23,7 +23,8 @@ import Text.Pandoc.Arbitrary () import Text.Pandoc.Builder (bulletList, definitionList, displayMath, divWith, doc, doubleQuoted, emph, header, lineBlock, linebreak, math, orderedList, para, plain, rawBlock, - singleQuoted, space, str, strong) + singleQuoted, space, str, strong, + HasMeta (setMeta)) import Text.Pandoc.Class (runIOorExplode, setUserDataDir) import Text.Pandoc.Definition (Block (BlockQuote, Div, Para), Inline (Emph, Str), Attr, Meta, Pandoc, pandocTypesVersion) @@ -129,6 +130,28 @@ tests = map (localOption (QuickCheckTests 20)) (doc $ divWith ("", [], kv_before) (para "nil")) (doc $ divWith ("", [], kv_after) (para "nil")) + , testCase "Filter list of inlines" $ + assertFilterConversion "List of inlines" + "inlines-filter.lua" + (doc $ para ("Hello," <> linebreak <> "World! Wassup?")) + (doc $ para "Hello, World! Wassup?") + + , testCase "Filter list of blocks" $ + assertFilterConversion "List of blocks" + "blocks-filter.lua" + (doc $ para "one." <> para "two." <> para "three.") + (doc $ plain "3") + + , testCase "Filter Meta" $ + let setMetaBefore = setMeta "old" ("old" :: T.Text) + . setMeta "bool" False + setMetaAfter = setMeta "new" ("new" :: T.Text) + . setMeta "bool" True + in assertFilterConversion "Meta filtering" + "meta.lua" + (setMetaBefore . doc $ mempty) + (setMetaAfter . doc $ mempty) + , testCase "Script filename is set" $ assertFilterConversion "unexpected script name" "script-name.lua" diff --git a/test/lua/blocks-filter.lua b/test/lua/blocks-filter.lua new file mode 100644 index 000000000..4e944e922 --- /dev/null +++ b/test/lua/blocks-filter.lua @@ -0,0 +1,8 @@ +function Blocks (blks) + -- verify that this looks like a `pandoc.List` + if not blks.find or not blks.map or not blks.filter then + error("table doesn't seem to be an instance of pandoc.List") + end + -- return plain block containing the number of elements in the list + return {pandoc.Plain {pandoc.Str(tostring(#blks))}} +end diff --git a/test/lua/inlines-filter.lua b/test/lua/inlines-filter.lua new file mode 100644 index 000000000..69608bd77 --- /dev/null +++ b/test/lua/inlines-filter.lua @@ -0,0 +1,19 @@ +function isWorldAfterSpace (fst, snd) + return fst and fst.t == 'LineBreak' + and snd and snd.t == 'Str' and snd.text == 'World!' +end + +function Inlines (inlns) + -- verify that this looks like a `pandoc.List` + if not inlns.find or not inlns.map or not inlns.filter then + error("table doesn't seem to be an instance of pandoc.List") + end + + -- Remove spaces before string "World" + for i = #inlns-1,1,-1 do + if isWorldAfterSpace(inlns[i], inlns[i+1]) then + inlns[i] = pandoc.Space() + end + end + return inlns +end diff --git a/test/lua/meta.lua b/test/lua/meta.lua new file mode 100644 index 000000000..5e2946203 --- /dev/null +++ b/test/lua/meta.lua @@ -0,0 +1,6 @@ +function Meta (meta) + meta.old = nil + meta.new = "new" + meta.bool = (meta.bool == false) + return meta +end -- cgit v1.2.3