Lua: marshal Inline elements as userdata
This includes the following user-facing changes: - Deprecated inline constructors are removed. These are `DoubleQuoted`, `SingleQuoted`, `DisplayMath`, and `InlineMath`. - Attr values are no longer normalized when assigned to an Inline element property. - It's no longer possible to access parts of Inline elements via numerical indexes. E.g., `pandoc.Span('test')[2]` used to give `pandoc.Str 'test'`, but yields `nil` now. This was undocumented behavior not intended to be used in user scripts. Use named properties instead. - Accessing `.c` to get a JSON-like tuple of all components no longer works. This was undocumented behavior. - Only known properties can be set on an element value. Trying to set a different property will now raise an error.
This commit is contained in:
parent
8523bb01b2
commit
6a03aca906
3 changed files with 345 additions and 334 deletions
271
data/pandoc.lua
271
data/pandoc.lua
|
@ -539,273 +539,6 @@ M.Table = M.Block:create_constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
-- Inline
|
|
||||||
-- @section Inline
|
|
||||||
|
|
||||||
--- Inline element class
|
|
||||||
M.Inline = AstElement:make_subtype'Inline'
|
|
||||||
M.Inline.behavior.clone = M.types.clone.Inline
|
|
||||||
|
|
||||||
--- Creates a Cite inline element
|
|
||||||
-- @function Cite
|
|
||||||
-- @tparam {Inline,...} content List of inlines
|
|
||||||
-- @tparam {Citation,...} citations List of citations
|
|
||||||
-- @treturn Inline citations element
|
|
||||||
M.Cite = M.Inline:create_constructor(
|
|
||||||
"Cite",
|
|
||||||
function(content, citations)
|
|
||||||
return {c = {ensureList(citations), ensureInlineList(content)}}
|
|
||||||
end,
|
|
||||||
{"citations", "content"}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Code inline element
|
|
||||||
-- @function Code
|
|
||||||
-- @tparam string text code string
|
|
||||||
-- @tparam[opt] Attr attr additional attributes
|
|
||||||
-- @treturn Inline code element
|
|
||||||
M.Code = M.Inline:create_constructor(
|
|
||||||
"Code",
|
|
||||||
function(text, attr) return {c = {ensureAttr(attr), text}} end,
|
|
||||||
{{attr = {"identifier", "classes", "attributes"}}, "text"}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates an inline element representing emphasised text.
|
|
||||||
-- @function Emph
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline emphasis element
|
|
||||||
M.Emph = M.Inline:create_constructor(
|
|
||||||
"Emph",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Image inline element
|
|
||||||
-- @function Image
|
|
||||||
-- @tparam {Inline,..} caption text used to describe the image
|
|
||||||
-- @tparam string src path to the image file
|
|
||||||
-- @tparam[opt] string title brief image description
|
|
||||||
-- @tparam[opt] Attr attr additional attributes
|
|
||||||
-- @treturn Inline image element
|
|
||||||
M.Image = M.Inline:create_constructor(
|
|
||||||
"Image",
|
|
||||||
function(caption, src, title, attr)
|
|
||||||
title = title or ""
|
|
||||||
return {c = {ensureAttr(attr), ensureInlineList(caption), {src, title}}}
|
|
||||||
end,
|
|
||||||
{{attr = {"identifier", "classes", "attributes"}}, "caption", {"src", "title"}}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Create a LineBreak inline element
|
|
||||||
-- @function LineBreak
|
|
||||||
-- @treturn Inline linebreak element
|
|
||||||
M.LineBreak = M.Inline:create_constructor(
|
|
||||||
"LineBreak",
|
|
||||||
function() return {} end
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a link inline element, usually a hyperlink.
|
|
||||||
-- @function Link
|
|
||||||
-- @tparam {Inline,..} content text for this link
|
|
||||||
-- @tparam string target the link target
|
|
||||||
-- @tparam[opt] string title brief link description
|
|
||||||
-- @tparam[opt] Attr attr additional attributes
|
|
||||||
-- @treturn Inline image element
|
|
||||||
M.Link = M.Inline:create_constructor(
|
|
||||||
"Link",
|
|
||||||
function(content, target, title, attr)
|
|
||||||
title = title or ""
|
|
||||||
attr = ensureAttr(attr)
|
|
||||||
return {c = {attr, ensureInlineList(content), {target, title}}}
|
|
||||||
end,
|
|
||||||
{{attr = {"identifier", "classes", "attributes"}}, "content", {"target", "title"}}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Math element, either inline or displayed.
|
|
||||||
-- @function Math
|
|
||||||
-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
|
|
||||||
-- @tparam string text Math content
|
|
||||||
-- @treturn Inline Math element
|
|
||||||
M.Math = M.Inline:create_constructor(
|
|
||||||
"Math",
|
|
||||||
function(mathtype, text)
|
|
||||||
return {c = {mathtype, text}}
|
|
||||||
end,
|
|
||||||
{"mathtype", "text"}
|
|
||||||
)
|
|
||||||
--- Creates a DisplayMath element (DEPRECATED).
|
|
||||||
-- @function DisplayMath
|
|
||||||
-- @tparam string text Math content
|
|
||||||
-- @treturn Inline Math element
|
|
||||||
M.DisplayMath = M.Inline:create_constructor(
|
|
||||||
"DisplayMath",
|
|
||||||
function(text) return M.Math("DisplayMath", text) end,
|
|
||||||
{"mathtype", "text"}
|
|
||||||
)
|
|
||||||
--- Creates an InlineMath inline element (DEPRECATED).
|
|
||||||
-- @function InlineMath
|
|
||||||
-- @tparam string text Math content
|
|
||||||
-- @treturn Inline Math element
|
|
||||||
M.InlineMath = M.Inline:create_constructor(
|
|
||||||
"InlineMath",
|
|
||||||
function(text) return M.Math("InlineMath", text) end,
|
|
||||||
{"mathtype", "text"}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Note inline element
|
|
||||||
-- @function Note
|
|
||||||
-- @tparam {Block,...} content footnote block content
|
|
||||||
M.Note = M.Inline:create_constructor(
|
|
||||||
"Note",
|
|
||||||
function(content) return {c = ensureList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Quoted inline element given the quote type and quoted content.
|
|
||||||
-- @function Quoted
|
|
||||||
-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline quoted element
|
|
||||||
M.Quoted = M.Inline:create_constructor(
|
|
||||||
"Quoted",
|
|
||||||
function(quotetype, content)
|
|
||||||
return {c = {quotetype, ensureInlineList(content)}}
|
|
||||||
end,
|
|
||||||
{"quotetype", "content"}
|
|
||||||
)
|
|
||||||
--- Creates a single-quoted inline element (DEPRECATED).
|
|
||||||
-- @function SingleQuoted
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline quoted element
|
|
||||||
-- @see Quoted
|
|
||||||
M.SingleQuoted = M.Inline:create_constructor(
|
|
||||||
"SingleQuoted",
|
|
||||||
function(content) return M.Quoted(M.SingleQuote, content) end,
|
|
||||||
{"quotetype", "content"}
|
|
||||||
)
|
|
||||||
--- Creates a single-quoted inline element (DEPRECATED).
|
|
||||||
-- @function DoubleQuoted
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline quoted element
|
|
||||||
-- @see Quoted
|
|
||||||
M.DoubleQuoted = M.Inline:create_constructor(
|
|
||||||
"DoubleQuoted",
|
|
||||||
function(content) return M.Quoted("DoubleQuote", content) end,
|
|
||||||
{"quotetype", "content"}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a RawInline inline element
|
|
||||||
-- @function RawInline
|
|
||||||
-- @tparam string format format of the contents
|
|
||||||
-- @tparam string text string content
|
|
||||||
-- @treturn Inline raw inline element
|
|
||||||
M.RawInline = M.Inline:create_constructor(
|
|
||||||
"RawInline",
|
|
||||||
function(format, text) return {c = {format, text}} end,
|
|
||||||
{"format", "text"}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates text rendered in small caps
|
|
||||||
-- @function SmallCaps
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline smallcaps element
|
|
||||||
M.SmallCaps = M.Inline:create_constructor(
|
|
||||||
"SmallCaps",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a SoftBreak inline element.
|
|
||||||
-- @function SoftBreak
|
|
||||||
-- @treturn Inline softbreak element
|
|
||||||
M.SoftBreak = M.Inline:create_constructor(
|
|
||||||
"SoftBreak",
|
|
||||||
function() return {} end
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Create a Space inline element
|
|
||||||
-- @function Space
|
|
||||||
-- @treturn Inline space element
|
|
||||||
M.Space = M.Inline:create_constructor(
|
|
||||||
"Space",
|
|
||||||
function() return {} end
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Span inline element
|
|
||||||
-- @function Span
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @tparam[opt] Attr attr additional attributes
|
|
||||||
-- @treturn Inline span element
|
|
||||||
M.Span = M.Inline:create_constructor(
|
|
||||||
"Span",
|
|
||||||
function(content, attr)
|
|
||||||
return {c = {ensureAttr(attr), ensureInlineList(content)}}
|
|
||||||
end,
|
|
||||||
{{attr = {"identifier", "classes", "attributes"}}, "content"}
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Str inline element
|
|
||||||
-- @function Str
|
|
||||||
-- @tparam string text content
|
|
||||||
-- @treturn Inline string element
|
|
||||||
M.Str = M.Inline:create_constructor(
|
|
||||||
"Str",
|
|
||||||
function(text) return {c = text} end,
|
|
||||||
"text"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates text which is striked out.
|
|
||||||
-- @function Strikeout
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline strikeout element
|
|
||||||
M.Strikeout = M.Inline:create_constructor(
|
|
||||||
"Strikeout",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Strong element, whose text is usually displayed in a bold font.
|
|
||||||
-- @function Strong
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline strong element
|
|
||||||
M.Strong = M.Inline:create_constructor(
|
|
||||||
"Strong",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Subscript inline element
|
|
||||||
-- @function Subscript
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline subscript element
|
|
||||||
M.Subscript = M.Inline:create_constructor(
|
|
||||||
"Subscript",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates a Superscript inline element
|
|
||||||
-- @function Superscript
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline superscript element
|
|
||||||
M.Superscript = M.Inline:create_constructor(
|
|
||||||
"Superscript",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Creates an Underline inline element
|
|
||||||
-- @function Underline
|
|
||||||
-- @tparam {Inline,..} content inline content
|
|
||||||
-- @treturn Inline underline element
|
|
||||||
M.Underline = M.Inline:create_constructor(
|
|
||||||
"Underline",
|
|
||||||
function(content) return {c = ensureInlineList(content)} end,
|
|
||||||
"content"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Element components
|
-- Element components
|
||||||
-- @section components
|
-- @section components
|
||||||
|
@ -823,10 +556,6 @@ end
|
||||||
for _, blk in pairs(M.Block.constructor) do
|
for _, blk in pairs(M.Block.constructor) do
|
||||||
augment_attr_setter(blk.behavior.setters)
|
augment_attr_setter(blk.behavior.setters)
|
||||||
end
|
end
|
||||||
for _, inln in pairs(M.Inline.constructor) do
|
|
||||||
augment_attr_setter(inln.behavior.setters)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Citation
|
-- Citation
|
||||||
M.Citation = AstElement:make_subtype'Citation'
|
M.Citation = AstElement:make_subtype'Citation'
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{- |
|
{- |
|
||||||
Module : Text.Pandoc.Lua.Marshaling.AST
|
Module : Text.Pandoc.Lua.Marshaling.AST
|
||||||
|
@ -21,12 +22,18 @@ module Text.Pandoc.Lua.Marshaling.AST
|
||||||
, peekBlocks
|
, peekBlocks
|
||||||
, peekCaption
|
, peekCaption
|
||||||
, peekCitation
|
, peekCitation
|
||||||
|
, peekFormat
|
||||||
, peekInline
|
, peekInline
|
||||||
, peekInlines
|
, peekInlines
|
||||||
, peekListAttributes
|
, peekListAttributes
|
||||||
, peekMeta
|
, peekMeta
|
||||||
, peekMetaValue
|
, peekMetaValue
|
||||||
, peekPandoc
|
, peekPandoc
|
||||||
|
, peekMathType
|
||||||
|
, peekQuoteType
|
||||||
|
|
||||||
|
, peekFuzzyInlines
|
||||||
|
, peekFuzzyBlocks
|
||||||
|
|
||||||
, pushAttr
|
, pushAttr
|
||||||
, pushBlock
|
, pushBlock
|
||||||
|
@ -37,9 +44,13 @@ module Text.Pandoc.Lua.Marshaling.AST
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Applicative ((<|>), optional)
|
import Control.Applicative ((<|>), optional)
|
||||||
|
import Control.Monad.Catch (throwM)
|
||||||
import Control.Monad ((<$!>), (>=>))
|
import Control.Monad ((<$!>), (>=>))
|
||||||
|
import Data.Data (showConstr, toConstr)
|
||||||
|
import Data.Text (Text)
|
||||||
import HsLua hiding (Operation (Div))
|
import HsLua hiding (Operation (Div))
|
||||||
import Text.Pandoc.Definition
|
import Text.Pandoc.Definition
|
||||||
|
import Text.Pandoc.Error (PandocError (PandocLuaError))
|
||||||
import Text.Pandoc.Lua.Util (pushViaConstr', pushViaConstructor)
|
import Text.Pandoc.Lua.Util (pushViaConstr', pushViaConstructor)
|
||||||
import Text.Pandoc.Lua.Marshaling.Attr (peekAttr, pushAttr)
|
import Text.Pandoc.Lua.Marshaling.Attr (peekAttr, pushAttr)
|
||||||
import Text.Pandoc.Lua.Marshaling.List (pushPandocList)
|
import Text.Pandoc.Lua.Marshaling.List (pushPandocList)
|
||||||
|
@ -94,10 +105,13 @@ instance Pushable Inline where
|
||||||
|
|
||||||
-- Citation
|
-- Citation
|
||||||
instance Pushable Citation where
|
instance Pushable Citation where
|
||||||
push (Citation cid prefix suffix mode noteNum hash) =
|
push = pushCitation
|
||||||
pushViaConstr' "Citation"
|
|
||||||
[ push cid, push mode, push prefix, push suffix, push noteNum, push hash
|
pushCitation :: LuaError e => Pusher e Citation
|
||||||
]
|
pushCitation (Citation cid prefix suffix mode noteNum hash) =
|
||||||
|
pushViaConstr' "Citation"
|
||||||
|
[ push cid, push mode, push prefix, push suffix, push noteNum, push hash
|
||||||
|
]
|
||||||
|
|
||||||
peekCitation :: LuaError e => Peeker e Citation
|
peekCitation :: LuaError e => Peeker e Citation
|
||||||
peekCitation = fmap (retrieving "Citation")
|
peekCitation = fmap (retrieving "Citation")
|
||||||
|
@ -119,7 +133,10 @@ instance Pushable CitationMode where
|
||||||
push = Lua.push . show
|
push = Lua.push . show
|
||||||
|
|
||||||
instance Pushable Format where
|
instance Pushable Format where
|
||||||
push (Format f) = Lua.push f
|
push = pushFormat
|
||||||
|
|
||||||
|
pushFormat :: LuaError e => Pusher e Format
|
||||||
|
pushFormat (Format f) = pushText f
|
||||||
|
|
||||||
peekFormat :: LuaError e => Peeker e Format
|
peekFormat :: LuaError e => Peeker e Format
|
||||||
peekFormat idx = Format <$!> peekText idx
|
peekFormat idx = Format <$!> peekText idx
|
||||||
|
@ -134,7 +151,19 @@ instance Pushable MathType where
|
||||||
push = Lua.push . show
|
push = Lua.push . show
|
||||||
|
|
||||||
instance Pushable QuoteType where
|
instance Pushable QuoteType where
|
||||||
push = Lua.push . show
|
push = pushQuoteType
|
||||||
|
|
||||||
|
pushMathType :: LuaError e => Pusher e MathType
|
||||||
|
pushMathType = pushString . show
|
||||||
|
|
||||||
|
peekMathType :: LuaError e => Peeker e MathType
|
||||||
|
peekMathType = peekRead
|
||||||
|
|
||||||
|
pushQuoteType :: LuaError e => Pusher e QuoteType
|
||||||
|
pushQuoteType = pushString . show
|
||||||
|
|
||||||
|
peekQuoteType :: LuaError e => Peeker e QuoteType
|
||||||
|
peekQuoteType = peekRead
|
||||||
|
|
||||||
-- | Push an meta value element to the top of the lua stack.
|
-- | Push an meta value element to the top of the lua stack.
|
||||||
pushMetaValue :: LuaError e => MetaValue -> LuaE e ()
|
pushMetaValue :: LuaError e => MetaValue -> LuaE e ()
|
||||||
|
@ -354,66 +383,213 @@ peekCell = fmap (retrieving "Cell")
|
||||||
blks <- peekFieldRaw peekBlocks "contents" idx
|
blks <- peekFieldRaw peekBlocks "contents" idx
|
||||||
return $! Cell attr algn rs cs blks
|
return $! Cell attr algn rs cs blks
|
||||||
|
|
||||||
|
getInlineText :: Inline -> Possible Text
|
||||||
|
getInlineText = \case
|
||||||
|
Code _ lst -> Actual lst
|
||||||
|
Math _ str -> Actual str
|
||||||
|
RawInline _ raw -> Actual raw
|
||||||
|
Str s -> Actual s
|
||||||
|
_ -> Absent
|
||||||
|
|
||||||
|
setInlineText :: Inline -> Text -> Possible Inline
|
||||||
|
setInlineText = \case
|
||||||
|
Code attr _ -> Actual . Code attr
|
||||||
|
Math mt _ -> Actual . Math mt
|
||||||
|
RawInline f _ -> Actual . RawInline f
|
||||||
|
Str _ -> Actual . Str
|
||||||
|
_ -> const Absent
|
||||||
|
|
||||||
|
data Content
|
||||||
|
= ContentBlocks [Block]
|
||||||
|
| ContentInlines [Inline]
|
||||||
|
|
||||||
|
setInlineContent :: Inline -> Content -> Possible Inline
|
||||||
|
setInlineContent = \case
|
||||||
|
-- inline content
|
||||||
|
Cite cs _ -> Actual . Cite cs . inlineContent
|
||||||
|
Emph _ -> Actual . Emph . inlineContent
|
||||||
|
Quoted qt _ -> Actual . Quoted qt . inlineContent
|
||||||
|
SmallCaps _ -> Actual . SmallCaps . inlineContent
|
||||||
|
Span attr _ -> Actual . Span attr . inlineContent
|
||||||
|
Strong _ -> Actual . Strong . inlineContent
|
||||||
|
Subscript _ -> Actual . Subscript . inlineContent
|
||||||
|
Superscript _ -> Actual . Superscript . inlineContent
|
||||||
|
Underline _ -> Actual . Underline . inlineContent
|
||||||
|
-- block content
|
||||||
|
Note _ -> Actual . Note . blockContent
|
||||||
|
_ -> const Absent
|
||||||
|
where
|
||||||
|
inlineContent = \case
|
||||||
|
ContentInlines inlns -> inlns
|
||||||
|
ContentBlocks _ -> throwM $
|
||||||
|
PandocLuaError "expected Inlines, got Blocks"
|
||||||
|
blockContent = \case
|
||||||
|
ContentBlocks blks -> blks
|
||||||
|
ContentInlines [] -> []
|
||||||
|
ContentInlines _ -> throwM $
|
||||||
|
PandocLuaError "expected Blocks, got Inlines"
|
||||||
|
|
||||||
|
getInlineContent :: Inline -> Possible Content
|
||||||
|
getInlineContent = \case
|
||||||
|
Cite _ inlns -> Actual $ ContentInlines inlns
|
||||||
|
Emph inlns -> Actual $ ContentInlines inlns
|
||||||
|
Quoted _ inlns -> Actual $ ContentInlines inlns
|
||||||
|
SmallCaps inlns -> Actual $ ContentInlines inlns
|
||||||
|
Span _ inlns -> Actual $ ContentInlines inlns
|
||||||
|
Strong inlns -> Actual $ ContentInlines inlns
|
||||||
|
Subscript inlns -> Actual $ ContentInlines inlns
|
||||||
|
Superscript inlns -> Actual $ ContentInlines inlns
|
||||||
|
Underline inlns -> Actual $ ContentInlines inlns
|
||||||
|
Note blks -> Actual $ ContentBlocks blks
|
||||||
|
_ -> Absent
|
||||||
|
|
||||||
|
-- title
|
||||||
|
getInlineTitle :: Inline -> Possible Text
|
||||||
|
getInlineTitle = \case
|
||||||
|
Image _ _ (_, tit) -> Actual tit
|
||||||
|
Link _ _ (_, tit) -> Actual tit
|
||||||
|
_ -> Absent
|
||||||
|
|
||||||
|
setInlineTitle :: Inline -> Text -> Possible Inline
|
||||||
|
setInlineTitle = \case
|
||||||
|
Image attr capt (src, _) -> Actual . Image attr capt . (src,)
|
||||||
|
Link attr capt (src, _) -> Actual . Link attr capt . (src,)
|
||||||
|
_ -> const Absent
|
||||||
|
|
||||||
|
-- attr
|
||||||
|
getInlineAttr :: Inline -> Possible Attr
|
||||||
|
getInlineAttr = \case
|
||||||
|
Code attr _ -> Actual attr
|
||||||
|
Image attr _ _ -> Actual attr
|
||||||
|
Link attr _ _ -> Actual attr
|
||||||
|
Span attr _ -> Actual attr
|
||||||
|
_ -> Absent
|
||||||
|
|
||||||
|
setInlineAttr :: Inline -> Attr -> Possible Inline
|
||||||
|
setInlineAttr = \case
|
||||||
|
Code _ cs -> Actual . (`Code` cs)
|
||||||
|
Image _ cpt tgt -> Actual . \attr -> Image attr cpt tgt
|
||||||
|
Link _ cpt tgt -> Actual . \attr -> Link attr cpt tgt
|
||||||
|
Span _ inlns -> Actual . (`Span` inlns)
|
||||||
|
_ -> const Absent
|
||||||
|
|
||||||
|
showInline :: LuaError e => DocumentedFunction e
|
||||||
|
showInline = defun "show"
|
||||||
|
### liftPure (show @Inline)
|
||||||
|
<#> parameter peekInline "inline" "Inline" "Object"
|
||||||
|
=#> functionResult pushString "string" "stringified Inline"
|
||||||
|
|
||||||
|
pushContent :: LuaError e => Pusher e Content
|
||||||
|
pushContent = \case
|
||||||
|
ContentBlocks blks -> pushPandocList pushBlock blks
|
||||||
|
ContentInlines inlns -> pushPandocList pushInline inlns
|
||||||
|
|
||||||
|
peekContent :: LuaError e => Peeker e Content
|
||||||
|
peekContent idx =
|
||||||
|
(ContentInlines <$!> peekList peekInline idx) <|>
|
||||||
|
(ContentBlocks <$!> peekList peekBlock idx)
|
||||||
|
|
||||||
|
typeInline :: LuaError e => DocumentedType e Inline
|
||||||
|
typeInline = deftype "Inline"
|
||||||
|
[ operation Tostring showInline
|
||||||
|
, operation Eq $ defun "__eq"
|
||||||
|
### liftPure2 (==)
|
||||||
|
<#> parameter peekInline "a" "Inline" ""
|
||||||
|
<#> parameter peekInline "b" "Inline" ""
|
||||||
|
=#> functionResult pushBool "boolean" "whether the two are equal"
|
||||||
|
]
|
||||||
|
[ possibleProperty "attr" "element attributes"
|
||||||
|
(pushAttr, getInlineAttr)
|
||||||
|
(peekAttr, setInlineAttr)
|
||||||
|
, possibleProperty "caption" "image caption"
|
||||||
|
(pushPandocList pushInline, \case
|
||||||
|
Image _ capt _ -> Actual capt
|
||||||
|
_ -> Absent)
|
||||||
|
(peekInlines, \case
|
||||||
|
Image attr _ target -> Actual . (\capt -> Image attr capt target)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "citations" "list of citations"
|
||||||
|
(pushPandocList pushCitation, \case {Cite cs _ -> Actual cs; _ -> Absent})
|
||||||
|
(peekList peekCitation, \case
|
||||||
|
Cite _ inlns -> Actual . (`Cite` inlns)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "content" "element contents"
|
||||||
|
(pushContent, getInlineContent)
|
||||||
|
(peekContent, setInlineContent)
|
||||||
|
, possibleProperty "format" "format of raw text"
|
||||||
|
(pushFormat, \case {RawInline fmt _ -> Actual fmt; _ -> Absent})
|
||||||
|
(peekFormat, \case
|
||||||
|
RawInline _ txt -> Actual . (`RawInline` txt)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "mathtype" "math rendering method"
|
||||||
|
(pushMathType, \case {Math mt _ -> Actual mt; _ -> Absent})
|
||||||
|
(peekMathType, \case
|
||||||
|
Math _ txt -> Actual . (`Math` txt)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "quotetype" "type of quotes (single or double)"
|
||||||
|
(pushQuoteType, \case {Quoted qt _ -> Actual qt; _ -> Absent})
|
||||||
|
(peekQuoteType, \case
|
||||||
|
Quoted _ inlns -> Actual . (`Quoted` inlns)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "src" "image source"
|
||||||
|
(pushText, \case
|
||||||
|
Image _ _ (src, _) -> Actual src
|
||||||
|
_ -> Absent)
|
||||||
|
(peekText, \case
|
||||||
|
Image attr capt (_, title) -> Actual . Image attr capt . (,title)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "target" "link target URL"
|
||||||
|
(pushText, \case
|
||||||
|
Link _ _ (tgt, _) -> Actual tgt
|
||||||
|
_ -> Absent)
|
||||||
|
(peekText, \case
|
||||||
|
Link attr capt (_, title) -> Actual . Image attr capt . (,title)
|
||||||
|
_ -> const Absent)
|
||||||
|
, possibleProperty "title" "title text"
|
||||||
|
(pushText, getInlineTitle)
|
||||||
|
(peekText, setInlineTitle)
|
||||||
|
, possibleProperty "text" "text contents"
|
||||||
|
(pushText, getInlineText)
|
||||||
|
(peekText, setInlineText)
|
||||||
|
, readonly "tag" "type of Inline"
|
||||||
|
(pushString, showConstr . toConstr )
|
||||||
|
|
||||||
|
, alias "t" "tag" ["tag"]
|
||||||
|
, alias "c" "content" ["content"]
|
||||||
|
, alias "identifier" "element identifier" ["attr", "identifier"]
|
||||||
|
, alias "classes" "element classes" ["attr", "classes"]
|
||||||
|
, alias "attributes" "other element attributes" ["attr", "attributes"]
|
||||||
|
|
||||||
|
, method $ defun "clone"
|
||||||
|
### return
|
||||||
|
<#> parameter peekInline "inline" "Inline" "self"
|
||||||
|
=#> functionResult pushInline "Inline" "cloned Inline"
|
||||||
|
]
|
||||||
|
|
||||||
-- | Push an inline element to the top of the lua stack.
|
-- | Push an inline element to the top of the lua stack.
|
||||||
pushInline :: forall e. LuaError e => Inline -> LuaE e ()
|
pushInline :: forall e. LuaError e => Inline -> LuaE e ()
|
||||||
pushInline = \case
|
pushInline = pushUD typeInline
|
||||||
Cite citations lst -> pushViaConstructor @e "Cite" lst citations
|
|
||||||
Code attr lst -> pushViaConstr' @e "Code"
|
|
||||||
[push lst, pushAttr attr]
|
|
||||||
Emph inlns -> pushViaConstructor @e "Emph" inlns
|
|
||||||
Underline inlns -> pushViaConstructor @e "Underline" inlns
|
|
||||||
Image attr alt (src,tit) -> pushViaConstr' @e "Image"
|
|
||||||
[push alt, push src, push tit, pushAttr attr]
|
|
||||||
LineBreak -> pushViaConstructor @e "LineBreak"
|
|
||||||
Link attr lst (src,tit) -> pushViaConstr' @e "Link"
|
|
||||||
[push lst, push src, push tit, pushAttr attr]
|
|
||||||
Note blcks -> pushViaConstructor @e "Note" blcks
|
|
||||||
Math mty str -> pushViaConstructor @e "Math" mty str
|
|
||||||
Quoted qt inlns -> pushViaConstructor @e "Quoted" qt inlns
|
|
||||||
RawInline f cs -> pushViaConstructor @e "RawInline" f cs
|
|
||||||
SmallCaps inlns -> pushViaConstructor @e "SmallCaps" inlns
|
|
||||||
SoftBreak -> pushViaConstructor @e "SoftBreak"
|
|
||||||
Space -> pushViaConstructor @e "Space"
|
|
||||||
Span attr inlns -> pushViaConstr' @e "Span"
|
|
||||||
[push inlns, pushAttr attr]
|
|
||||||
Str str -> pushViaConstructor @e "Str" str
|
|
||||||
Strikeout inlns -> pushViaConstructor @e "Strikeout" inlns
|
|
||||||
Strong inlns -> pushViaConstructor @e "Strong" inlns
|
|
||||||
Subscript inlns -> pushViaConstructor @e "Subscript" inlns
|
|
||||||
Superscript inlns -> pushViaConstructor @e "Superscript" inlns
|
|
||||||
|
|
||||||
-- | Return the value at the given index as inline if possible.
|
-- | Return the value at the given index as inline if possible.
|
||||||
peekInline :: forall e. LuaError e => Peeker e Inline
|
peekInline :: forall e. LuaError e => Peeker e Inline
|
||||||
peekInline = retrieving "Inline" . \idx -> do
|
peekInline = retrieving "Inline" . \idx -> peekUD typeInline idx
|
||||||
-- Get the contents of an AST element.
|
|
||||||
let mkBlock :: (a -> Inline) -> Peeker e a -> Peek e Inline
|
-- | Try extra-hard to return the value at the given index as a list of
|
||||||
mkBlock f p = f <$!> peekFieldRaw p "c" idx
|
-- inlines.
|
||||||
LuaUtil.getTag idx >>= \case
|
peekFuzzyInlines :: LuaError e => Peeker e [Inline]
|
||||||
"Cite" -> mkBlock (uncurry Cite) $
|
peekFuzzyInlines = choice
|
||||||
peekPair (peekList peekCitation) peekInlines
|
[ peekList peekInline
|
||||||
"Code" -> mkBlock (uncurry Code) (peekPair peekAttr peekText)
|
, fmap pure . peekInline
|
||||||
"Emph" -> mkBlock Emph peekInlines
|
, \idx -> pure . Str <$!> peekText idx
|
||||||
"Underline" -> mkBlock Underline peekInlines
|
]
|
||||||
"Image" -> mkBlock (\(attr, lst, tgt) -> Image attr lst tgt)
|
|
||||||
$ peekTriple peekAttr peekInlines
|
peekFuzzyBlocks :: LuaError e => Peeker e [Block]
|
||||||
(peekPair peekText peekText)
|
peekFuzzyBlocks = choice
|
||||||
"Link" -> mkBlock (\(attr, lst, tgt) -> Link attr lst tgt) $
|
[ peekList peekBlock
|
||||||
peekTriple peekAttr peekInlines (peekPair peekText peekText)
|
, fmap pure . peekBlock
|
||||||
"LineBreak" -> return LineBreak
|
, \idx -> pure . Plain . pure . Str <$!> peekText idx
|
||||||
"Note" -> mkBlock Note peekBlocks
|
]
|
||||||
"Math" -> mkBlock (uncurry Math) (peekPair peekRead peekText)
|
|
||||||
"Quoted" -> mkBlock (uncurry Quoted) (peekPair peekRead peekInlines)
|
|
||||||
"RawInline" -> mkBlock (uncurry RawInline) (peekPair peekFormat peekText)
|
|
||||||
"SmallCaps" -> mkBlock SmallCaps peekInlines
|
|
||||||
"SoftBreak" -> return SoftBreak
|
|
||||||
"Space" -> return Space
|
|
||||||
"Span" -> mkBlock (uncurry Span) (peekPair peekAttr peekInlines)
|
|
||||||
"Str" -> mkBlock Str peekText
|
|
||||||
"Strikeout" -> mkBlock Strikeout peekInlines
|
|
||||||
"Strong" -> mkBlock Strong peekInlines
|
|
||||||
"Subscript" -> mkBlock Subscript peekInlines
|
|
||||||
"Superscript"-> mkBlock Superscript peekInlines
|
|
||||||
Name tag -> Lua.failPeek ("Unknown inline type: " <> tag)
|
|
||||||
|
|
||||||
pushListAttributes :: forall e. LuaError e => ListAttributes -> LuaE e ()
|
pushListAttributes :: forall e. LuaError e => ListAttributes -> LuaE e ()
|
||||||
pushListAttributes (start, style, delimiter) =
|
pushListAttributes (start, style, delimiter) =
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{- |
|
{- |
|
||||||
Module : Text.Pandoc.Lua.Module.Pandoc
|
Module : Text.Pandoc.Lua.Module.Pandoc
|
||||||
Copyright : Copyright © 2017-2021 Albert Krewinkel
|
Copyright : Copyright © 2017-2021 Albert Krewinkel
|
||||||
|
@ -16,7 +17,7 @@ module Text.Pandoc.Lua.Module.Pandoc
|
||||||
|
|
||||||
import Prelude hiding (read)
|
import Prelude hiding (read)
|
||||||
import Control.Applicative (optional)
|
import Control.Applicative (optional)
|
||||||
import Control.Monad ((>=>), when)
|
import Control.Monad ((>=>), forM_, when)
|
||||||
import Control.Monad.Except (throwError)
|
import Control.Monad.Except (throwError)
|
||||||
import Data.Default (Default (..))
|
import Data.Default (Default (..))
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
@ -54,11 +55,116 @@ pushModule = do
|
||||||
addFunction "walk_block" (walkElement peekBlock pushBlock)
|
addFunction "walk_block" (walkElement peekBlock pushBlock)
|
||||||
addFunction "walk_inline" (walkElement peekInline pushInline)
|
addFunction "walk_inline" (walkElement peekInline pushInline)
|
||||||
-- Constructors
|
-- Constructors
|
||||||
addFunction "Pandoc" mkPandoc
|
|
||||||
addFunction "Attr" (liftPandocLua mkAttr)
|
addFunction "Attr" (liftPandocLua mkAttr)
|
||||||
addFunction "AttributeList" (liftPandocLua mkAttributeList)
|
addFunction "AttributeList" (liftPandocLua mkAttributeList)
|
||||||
|
addFunction "Pandoc" mkPandoc
|
||||||
|
liftPandocLua $ do
|
||||||
|
let addConstr fn = do
|
||||||
|
pushName (functionName fn)
|
||||||
|
pushDocumentedFunction fn
|
||||||
|
rawset (nth 3)
|
||||||
|
forM_ inlineConstructors addConstr
|
||||||
|
-- add constructors to Inlines.constructor
|
||||||
|
newtable -- constructor
|
||||||
|
forM_ (inlineConstructors @PandocError) $ \fn -> do
|
||||||
|
let name = functionName fn
|
||||||
|
pushName name
|
||||||
|
pushName name
|
||||||
|
rawget (nth 4)
|
||||||
|
rawset (nth 3)
|
||||||
|
-- set as pandoc.Inline.constructor
|
||||||
|
pushName "Inline"
|
||||||
|
newtable *> pushName "constructor" *> pushvalue (nth 4) *> rawset (nth 3)
|
||||||
|
rawset (nth 4)
|
||||||
|
pop 1 -- remaining constructor table
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
inlineConstructors :: LuaError e => [DocumentedFunction e]
|
||||||
|
inlineConstructors =
|
||||||
|
[ defun "Cite"
|
||||||
|
### liftPure2 Cite
|
||||||
|
<#> parameter (peekList peekCitation) "citations" "list of Citations" ""
|
||||||
|
<#> parameter peekFuzzyInlines "content" "Inline" "placeholder content"
|
||||||
|
=#> functionResult pushInline "Inline" "cite element"
|
||||||
|
, defun "Code"
|
||||||
|
### liftPure2 (flip Code)
|
||||||
|
<#> parameter peekText "code" "string" "code string"
|
||||||
|
<#> parameter peekAttr "attr" "Attr" "additional attributes"
|
||||||
|
=#> functionResult pushInline "Inline" "code element"
|
||||||
|
, mkInlinesConstr "Emph" Emph
|
||||||
|
, defun "Image"
|
||||||
|
### liftPure4 (\caption src mtitle mattr ->
|
||||||
|
let attr = fromMaybe nullAttr mattr
|
||||||
|
title = fromMaybe mempty mtitle
|
||||||
|
in Image attr caption (src, title))
|
||||||
|
<#> parameter peekFuzzyInlines "Inlines" "caption" "image caption / alt"
|
||||||
|
<#> parameter peekText "string" "src" "path/URL of the image file"
|
||||||
|
<#> optionalParameter peekText "string" "title" "brief image description"
|
||||||
|
<#> optionalParameter peekAttr "Attr" "attr" "image attributes"
|
||||||
|
=#> functionResult pushInline "Inline" "image element"
|
||||||
|
, defun "LineBreak"
|
||||||
|
### return LineBreak
|
||||||
|
=#> functionResult pushInline "Inline" "line break"
|
||||||
|
, defun "Link"
|
||||||
|
### liftPure4 (\content target mtitle mattr ->
|
||||||
|
let attr = fromMaybe nullAttr mattr
|
||||||
|
title = fromMaybe mempty mtitle
|
||||||
|
in Link attr content (target, title))
|
||||||
|
<#> parameter peekFuzzyInlines "Inlines" "content" "text for this link"
|
||||||
|
<#> parameter peekText "string" "target" "the link target"
|
||||||
|
<#> optionalParameter peekText "string" "title" "brief link description"
|
||||||
|
<#> optionalParameter peekAttr "Attr" "attr" "link attributes"
|
||||||
|
=#> functionResult pushInline "Inline" "link element"
|
||||||
|
, defun "Math"
|
||||||
|
### liftPure2 Math
|
||||||
|
<#> parameter peekMathType "quotetype" "Math" "rendering method"
|
||||||
|
<#> parameter peekText "text" "string" "math content"
|
||||||
|
=#> functionResult pushInline "Inline" "math element"
|
||||||
|
, defun "Note"
|
||||||
|
### liftPure Note
|
||||||
|
<#> parameter peekFuzzyBlocks "content" "Blocks" "note content"
|
||||||
|
=#> functionResult pushInline "Inline" "note"
|
||||||
|
, defun "Quoted"
|
||||||
|
### liftPure2 Quoted
|
||||||
|
<#> parameter peekQuoteType "quotetype" "QuoteType" "type of quotes"
|
||||||
|
<#> parameter peekFuzzyInlines "content" "Inlines" "inlines in quotes"
|
||||||
|
=#> functionResult pushInline "Inline" "quoted element"
|
||||||
|
, defun "RawInline"
|
||||||
|
### liftPure2 RawInline
|
||||||
|
<#> parameter peekFormat "format" "Format" "format of content"
|
||||||
|
<#> parameter peekText "text" "string" "string content"
|
||||||
|
=#> functionResult pushInline "Inline" "raw inline element"
|
||||||
|
, mkInlinesConstr "SmallCaps" SmallCaps
|
||||||
|
, defun "SoftSpace"
|
||||||
|
### return SoftBreak
|
||||||
|
=#> functionResult pushInline "Inline" "soft break"
|
||||||
|
, defun "Space"
|
||||||
|
### return Space
|
||||||
|
=#> functionResult pushInline "Inline" "new space"
|
||||||
|
, defun "Span"
|
||||||
|
### liftPure2 (\inlns mattr -> Span (fromMaybe nullAttr mattr) inlns)
|
||||||
|
<#> parameter peekFuzzyInlines "content" "Inlines" "inline content"
|
||||||
|
<#> optionalParameter peekAttr "attr" "Attr" "additional attributes"
|
||||||
|
=#> functionResult pushInline "Inline" "span element"
|
||||||
|
, defun "Str"
|
||||||
|
### liftPure (\s -> s `seq` Str s)
|
||||||
|
<#> parameter peekText "text" "string" ""
|
||||||
|
=#> functionResult pushInline "Inline" "new Str object"
|
||||||
|
, mkInlinesConstr "Strong" Strong
|
||||||
|
, mkInlinesConstr "Strikeout" Strikeout
|
||||||
|
, mkInlinesConstr "Subscript" Subscript
|
||||||
|
, mkInlinesConstr "Superscript" Superscript
|
||||||
|
, mkInlinesConstr "Underline" Underline
|
||||||
|
]
|
||||||
|
|
||||||
|
mkInlinesConstr :: LuaError e
|
||||||
|
=> Name -> ([Inline] -> Inline) -> DocumentedFunction e
|
||||||
|
mkInlinesConstr name constr = defun name
|
||||||
|
### liftPure (\x -> x `seq` constr x)
|
||||||
|
<#> parameter peekFuzzyInlines "content" "Inlines" ""
|
||||||
|
=#> functionResult pushInline "Inline" "new object"
|
||||||
|
|
||||||
|
|
||||||
walkElement :: (Walkable (SingletonsList Inline) a,
|
walkElement :: (Walkable (SingletonsList Inline) a,
|
||||||
Walkable (SingletonsList Block) a,
|
Walkable (SingletonsList Block) a,
|
||||||
Walkable (List Inline) a,
|
Walkable (List Inline) a,
|
||||||
|
|
Loading…
Reference in a new issue