aboutsummaryrefslogtreecommitdiff
path: root/data/pandoc.lua
diff options
context:
space:
mode:
Diffstat (limited to 'data/pandoc.lua')
-rw-r--r--data/pandoc.lua1169
1 files changed, 0 insertions, 1169 deletions
diff --git a/data/pandoc.lua b/data/pandoc.lua
deleted file mode 100644
index 35ca20a84..000000000
--- a/data/pandoc.lua
+++ /dev/null
@@ -1,1169 +0,0 @@
---[[
-pandoc.lua
-
-Copyright © 2017–2019 Albert Krewinkel
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-]]
-
----
--- Lua functions for pandoc scripts.
---
--- @author Albert Krewinkel
--- @copyright © 2017–2019 Albert Krewinkel
--- @license MIT
-local M = {}
-
--- Re-export bundled modules
-M.List = require 'pandoc.List'
-M.mediabag = require 'pandoc.mediabag'
-M.system = require 'pandoc.system'
-M.types = require 'pandoc.types'
-M.utils = require 'pandoc.utils'
-M.text = require 'text'
-
--- Local names for modules which this module depends on.
-local List = M.List
-local utils = M.utils
-
-
-------------------------------------------------------------------------
--- Accessor objects
---
--- Create metatables which allow to access numerical indices via accessor
--- methods.
--- @section
--- @local
-
---- Create a new indexing function.
--- @param template function template
--- @param indices list of indices, starting with the most deeply nested
--- @return newly created function
--- @local
-function make_indexing_function(template, ...)
- local indices = {...}
- local loadstring = loadstring or load
- local bracketed = {}
- for i = 1, #indices do
- local idx = indices[#indices - i + 1]
- bracketed[i] = type(idx) == 'number'
- and string.format('[%d]', idx)
- or string.format('.%s', idx)
- end
- local fnstr = string.format('return ' .. template, table.concat(bracketed))
- return assert(loadstring(fnstr))()
-end
-
---- Create accessor functions using a function template.
--- @param fn_template function template in which '%s' is replacd with indices
--- @param accessors list of accessors
--- @return mapping from accessor names to accessor functions
--- @local
-local function create_accessor_functions (fn_template, accessors)
- local res = {}
- function add_accessors(acc, ...)
- if type(acc) == 'string' then
- res[acc] = make_indexing_function(fn_template, ...)
- elseif type(acc) == 'table' and #acc == 0 and next(acc) then
- -- Named substructure: the given names are accessed via the substructure,
- -- but the accessors are also added to the result table, enabling direct
- -- access from the parent element. Mainly used for `attr`.
- local name, substructure = next(acc)
- res[name] = make_indexing_function(fn_template, ...)
- for _, subname in ipairs(substructure) do
- res[subname] = make_indexing_function(fn_template, subname, ...)
- end
- else
- for i = 1, #(acc or {}) do
- add_accessors(acc[i], i, ...)
- end
- end
- end
- add_accessors(accessors)
- return res
-end
-
---- Get list of top-level fields from field descriptor table.
--- E.g.: `top_level_fields{'foo', {bar='baz'}, {'qux', 'quux'}}`
--- gives {'foo, 'bar', 'qux', 'quux'}
--- @local
-local function top_level_fields (fields)
- local result = List:new{}
- for _, v in ipairs(fields) do
- if type(v) == 'string' then
- table.insert(result, v)
- elseif type(v) == 'table' and #v == 0 and next(v) then
- table.insert(result, (next(v)))
- else
- result:extend(top_level_fields(v))
- end
- end
- return result
-end
-
---- Creates a function which behaves like next, but respects field names.
--- @local
-local function make_next_function (fields)
- local field_indices = {}
- for i, f in ipairs(fields) do
- field_indices[f] = i
- end
-
- return function (t, field)
- local raw_idx = field == nil and 0 or field_indices[field]
- local next_field = fields[raw_idx + 1]
- return next_field, t[next_field]
- end
-end
-
---- Create a new table which allows to access numerical indices via accessor
--- functions.
--- @local
-local function create_accessor_behavior (tag, accessors)
- local behavior = {tag = tag}
- behavior.getters = create_accessor_functions(
- 'function (x) return x.c%s end',
- accessors
- )
- behavior.setters = create_accessor_functions(
- 'function (x, v) x.c%s = v end',
- accessors
- )
- behavior.__eq = utils.equals
- behavior.__index = function(t, k)
- if getmetatable(t).getters[k] then
- return getmetatable(t).getters[k](t)
- elseif k == "t" then
- return getmetatable(t)["tag"]
- else
- return getmetatable(t)[k]
- end
- end
- behavior.__newindex = function(t, k, v)
- if getmetatable(t).setters[k] then
- getmetatable(t).setters[k](t, v)
- else
- rawset(t, k, v)
- end
- end
- behavior.__pairs = function (t)
- if accessors == nil then
- return next, t
- end
- local iterable_fields = type(accessors) == 'string'
- and {accessors}
- or top_level_fields(accessors)
- return make_next_function(iterable_fields), t
- end
- return behavior
-end
-
-
-------------------------------------------------------------------------
--- The base class for types
--- @type Type
--- @local
-local Type = {}
-Type.name = 'Type'
-Type.__index = Type
-Type.behavior = {
- __type = Type,
- new = function (obj)
- obj = obj or {}
- setmetatable(obj, self)
- return obj
- end
-}
-Type.behavior.__index = Type.behavior
-
---- Set a new behavior for the type, inheriting that of the parent type if none
---- is specified explicitly
--- @param behavior the behavior object for this type.
--- @local
-function Type:set_behavior (behavior)
- behavior = behavior or {}
- behavior.__index = rawget(behavior, '__index') or behavior
- behavior.__type = self
- if not getmetatable(behavior) and getmetatable(self) then
- setmetatable(behavior, getmetatable(self).behavior)
- end
- self.behavior = behavior
-end
-
---- Create a new subtype, using the given table as base.
--- @param name name of the new type
--- @param[opt] behavior behavioral object for the new type.
--- @return a new type
--- @local
-function Type:make_subtype(name, behavior)
- local newtype = setmetatable({}, self)
- newtype.name = name
- newtype.__index = newtype
- newtype:set_behavior(behavior)
- return newtype
-end
-
-
-------------------------------------------------------------------------
--- The base class for pandoc's AST elements.
--- @type AstElement
--- @local
-local AstElement = Type:make_subtype 'AstElement'
-AstElement.__call = function(t, ...)
- local success, ret = pcall(t.new, t, ...)
- if success then
- return setmetatable(ret, t.behavior)
- else
- error(string.format('Constructor for %s failed: %s\n', t.name, ret))
- end
-end
-
---- Make a new subtype which constructs a new value when called.
--- @local
-function AstElement:make_subtype(...)
- local newtype = Type.make_subtype(self, ...)
- newtype.__call = self.__call
- return newtype
-end
-
---- Create a new constructor
--- @local
--- @param tag Tag used to identify the constructor
--- @param fn Function to be called when constructing a new element
--- @param accessors names to use as accessors for numerical fields
--- @return function that constructs a new element
-function AstElement:create_constructor(tag, fn, accessors)
- local constr = self:make_subtype(tag, create_accessor_behavior(tag, accessors))
- function constr:new(...)
- return setmetatable(fn(...), self.behavior)
- end
- self.constructor = self.constructor or {}
- self.constructor[tag] = constr
- return constr
-end
-
---- Convert AstElement input into a list if necessary.
--- @local
-local function ensureList (x)
- if x.tag then
- -- Lists are not tagged, but all elements are
- return List:new{x}
- else
- return List:new(x)
- end
-end
-
---- Ensure a given object is an Inline element, or convert it into one.
--- @local
-local function ensureInlineList (x)
- if type(x) == 'string' then
- return List:new{M.Str(x)}
- else
- return ensureList(x)
- end
-end
-
---- Ensure that the given object is a definition pair, convert if necessary.
--- @local
-local function ensureDefinitionPairs (pair)
- local inlines = ensureInlineList(pair[1] or {})
- local blocks = ensureList(pair[2] or {}):map(ensureList)
- return {inlines, blocks}
-end
-
---- Split a string into it's words, using whitespace as separators.
-local function words (str)
- local ws = {}
- for w in str:gmatch("([^%s]+)") do ws[#ws + 1] = w end
- return ws
-end
-
---- Try hard to turn the arguments into an Attr object.
-local function ensureAttr(attr)
- if type(attr) == 'table' then
- if #attr > 0 then return M.Attr(table.unpack(attr)) end
-
- -- assume HTML-like key-value pairs
- local ident = attr.id or ''
- local classes = words(attr.class or '')
- local attributes = attr
- attributes.id = nil
- attributes.class = nil
- return M.Attr(ident, classes, attributes)
- elseif attr == nil then
- return M.Attr()
- elseif type(attr) == 'string' then
- -- treat argument as ID
- return M.Attr(attr)
- end
- -- print(arg, ...)
- error('Could not convert to Attr')
-end
-
-------------------------------------------------------------------------
---- Pandoc Document
--- @section document
-
---- A complete pandoc document
--- @function Pandoc
--- @tparam {Block,...} blocks document content
--- @tparam[opt] Meta meta document meta data
-M.Pandoc = AstElement:make_subtype'Pandoc'
-M.Pandoc.behavior.clone = M.types.clone.Pandoc
-function M.Pandoc:new (blocks, meta)
- return {
- blocks = ensureList(blocks),
- meta = meta or {},
- }
-end
-
--- DEPRECATED synonym:
-M.Doc = M.Pandoc
-
-------------------------------------------------------------------------
--- Meta
--- @section Meta
-
---- Create a new Meta object. It sets the metatable of the given table to
---- `Meta`.
--- @function Meta
--- @tparam meta table table containing document meta information
-M.Meta = AstElement:make_subtype'Meta'
-M.Meta.behavior.clone = M.types.clone.Meta
-function M.Meta:new (meta) return meta end
-
-
-------------------------------------------------------------------------
--- MetaValue
--- @section MetaValue
-M.MetaValue = AstElement:make_subtype('MetaValue')
-M.MetaValue.behavior.clone = M.types.clone.MetaValue
-
---- Meta blocks
--- @function MetaBlocks
--- @tparam {Block,...} blocks blocks
-M.MetaBlocks = M.MetaValue:create_constructor(
- 'MetaBlocks',
- function (content) return ensureList(content) end
-)
-
---- Meta inlines
--- @function MetaInlines
--- @tparam {Inline,...} inlines inlines
-M.MetaInlines = M.MetaValue:create_constructor(
- 'MetaInlines',
- function (content) return ensureInlineList(content) end
-)
-
---- Meta list
--- @function MetaList
--- @tparam {MetaValue,...} meta_values list of meta values
-M.MetaList = M.MetaValue:create_constructor(
- 'MetaList',
- function (content)
- if content.tag == 'MetaList' then
- return content
- end
- return ensureList(content)
- end
-)
-for k, v in pairs(List) do
- M.MetaList.behavior[k] = v
-end
-
---- Meta map
--- @function MetaMap
--- @tparam table key_value_map a string-indexed map of meta values
-M.MetaMap = M.MetaValue:create_constructor(
- "MetaMap",
- function (mm) return mm end
-)
-
---- Creates string to be used in meta data.
--- Does nothing, lua strings are meta strings.
--- @function MetaString
--- @tparam string str string value
-function M.MetaString(str)
- return str
-end
-
---- Creates boolean to be used in meta data.
--- Does nothing, lua booleans are meta booleans.
--- @function MetaBool
--- @tparam boolean bool boolean value
-function M.MetaBool(bool)
- return bool
-end
-
-------------------------------------------------------------------------
--- Blocks
--- @section Block
-
---- Block elements
-M.Block = AstElement:make_subtype'Block'
-M.Block.behavior.clone = M.types.clone.Block
-
---- Creates a block quote element
--- @function BlockQuote
--- @tparam {Block,...} content block content
--- @treturn Block block quote element
-M.BlockQuote = M.Block:create_constructor(
- "BlockQuote",
- function(content) return {c = ensureList(content)} end,
- "content"
-)
-
---- Creates a bullet (i.e. unordered) list.
--- @function BulletList
--- @tparam {{Block,...},...} content list of items
--- @treturn Block bullet list element
-M.BulletList = M.Block:create_constructor(
- "BulletList",
- function(content) return {c = ensureList(content):map(ensureList)} end,
- "content"
-)
-
---- Creates a code block element
--- @function CodeBlock
--- @tparam string text code string
--- @tparam[opt] Attr attr element attributes
--- @treturn Block code block element
-M.CodeBlock = M.Block:create_constructor(
- "CodeBlock",
- function(text, attr) return {c = {ensureAttr(attr), text}} end,
- {{attr = {"identifier", "classes", "attributes"}}, "text"}
-)
-
---- Creates a definition list, containing terms and their explanation.
--- @function DefinitionList
--- @tparam {{{Inline,...},{{Block,...}}},...} content list of items
--- @treturn Block definition list element
-M.DefinitionList = M.Block:create_constructor(
- "DefinitionList",
- function(content)
- return {c = ensureList(content):map(ensureDefinitionPairs)}
- end,
- "content"
-)
-
---- Creates a div element
--- @function Div
--- @tparam {Block,...} content block content
--- @tparam[opt] Attr attr element attributes
--- @treturn Block div element
-M.Div = M.Block:create_constructor(
- "Div",
- function(content, attr)
- return {c = {ensureAttr(attr), ensureList(content)}}
- end,
- {{attr = {"identifier", "classes", "attributes"}}, "content"}
-)
-
---- Creates a header element.
--- @function Header
--- @tparam int level header level
--- @tparam {Inline,...} content inline content
--- @tparam[opt] Attr attr element attributes
--- @treturn Block header element
-M.Header = M.Block:create_constructor(
- "Header",
- function(level, content, attr)
- return {c = {level, ensureAttr(attr), ensureInlineList(content)}}
- end,
- {"level", {attr = {"identifier", "classes", "attributes"}}, "content"}
-)
-
---- Creates a horizontal rule.
--- @function HorizontalRule
--- @treturn Block horizontal rule
-M.HorizontalRule = M.Block:create_constructor(
- "HorizontalRule",
- function() return {} end
-)
-
---- Creates a line block element.
--- @function LineBlock
--- @tparam {{Inline,...},...} content inline content
--- @treturn Block line block element
-M.LineBlock = M.Block:create_constructor(
- "LineBlock",
- function(content) return {c = ensureList(content):map(ensureInlineList)} end,
- "content"
-)
-
---- Creates a null element.
--- @function Null
--- @treturn Block null element
-M.Null = M.Block:create_constructor(
- "Null",
- function() return {} end
-)
-
---- Creates an ordered list.
--- @function OrderedList
--- @tparam {{Block,...},...} items list items
--- @param[opt] listAttributes list parameters
--- @treturn Block ordered list element
-M.OrderedList = M.Block:create_constructor(
- "OrderedList",
- function(items, listAttributes)
- listAttributes = listAttributes or M.ListAttributes()
- return {c = {listAttributes, ensureList(items):map(ensureList)}}
- end,
- {{listAttributes = {"start", "style", "delimiter"}}, "content"}
-)
-
---- Creates a para element.
--- @function Para
--- @tparam {Inline,...} content inline content
--- @treturn Block paragraph element
-M.Para = M.Block:create_constructor(
- "Para",
- function(content) return {c = ensureInlineList(content)} end,
- "content"
-)
-
---- Creates a plain element.
--- @function Plain
--- @tparam {Inline,...} content inline content
--- @treturn Block plain element
-M.Plain = M.Block:create_constructor(
- "Plain",
- function(content) return {c = ensureInlineList(content)} end,
- "content"
-)
-
---- Creates a raw content block of the specified format.
--- @function RawBlock
--- @tparam string format format of content
--- @tparam string text string content
--- @treturn Block raw block element
-M.RawBlock = M.Block:create_constructor(
- "RawBlock",
- function(format, text) return {c = {format, text}} end,
- {"format", "text"}
-)
-
---- Creates a table element.
--- @function Table
--- @tparam Caption caption table caption
--- @tparam {ColSpec,...} colspecs column alignments and widths
--- @tparam TableHead head table head
--- @tparam {TableBody,..} bodies table bodies
--- @treturn TableFoot foot table foot
--- @tparam[opt] Attr attr attributes
-M.Table = M.Block:create_constructor(
- "Table",
- function(caption, colspecs, head, bodies, foot, attr)
- return {
- c = {
- ensureAttr(attr),
- caption,
- List:new(colspecs),
- head,
- List:new(bodies),
- foot
- }
- }
- end,
- {"attr", "caption", "colspecs", "head", "bodies", "foot"}
-)
-
-
-------------------------------------------------------------------------
--- 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
--- @section components
-
---- Check if the first element of a pair matches the given value.
--- @param x key value to be checked
--- @return function returning true iff first element of its argument matches x
--- @local
-local function assoc_key_equals (x)
- return function (y) return y[1] == x end
-end
-
---- Lookup a value in an associative list
--- @function lookup
--- @local
--- @tparam {{key, value},...} alist associative list
--- @param key key for which the associated value is to be looked up
-local function lookup(alist, key)
- return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
-end
-
---- Return an iterator which returns key-value pairs of an associative list.
--- @function apairs
--- @local
--- @tparam {{key, value},...} alist associative list
-local apairs = function (alist)
- local i = 1
- local cur
- function nxt ()
- cur = rawget(alist, i)
- if cur then
- i = i + 1
- return cur[1], cur[2]
- end
- return nil
- end
- return nxt, nil, nil
-end
-
---- AttributeList, a metatable to allow table-like access to attribute lists
--- represented by associative lists.
--- @local
-local AttributeList = {
- __index = function (t, k)
- if type(k) == "number" then
- return rawget(t, k)
- else
- return lookup(t, k)
- end
- end,
-
- __newindex = function (t, k, v)
- local cur, idx = List.find_if(t, assoc_key_equals(k))
- if v == nil and not cur then
- -- deleted key does not exists in list
- return
- elseif v == nil then
- table.remove(t, idx)
- elseif cur then
- cur[2] = v
- elseif type(k) == "number" then
- rawset(t, k, v)
- else
- rawset(t, #t + 1, {k, v})
- end
- end,
-
- __pairs = apairs
-}
-
---- Convert a table to an associative list. The order of key-value pairs in the
--- alist is undefined. The table should either contain no numeric keys or
--- already be an associative list.
--- @local
--- @tparam table tbl associative list or table without numeric keys.
--- @treturn table associative list
-local to_alist = function (tbl)
- if #tbl ~= 0 or next(tbl) == nil then
- -- probably already an alist
- return tbl
- end
- local alist = {}
- local i = 1
- for k, v in pairs(tbl) do
- alist[i] = {k, v}
- i = i + 1
- end
- return alist
-end
-
--- Attr
-
---- Create a new set of attributes (Attr).
--- @function Attr
--- @tparam[opt] string identifier element identifier
--- @tparam[opt] {string,...} classes element classes
--- @tparam[opt] table attributes table containing string keys and values
--- @return element attributes
-M.Attr = AstElement:make_subtype'Attr'
-function M.Attr:new (identifier, classes, attributes)
- identifier = identifier or ''
- classes = ensureList(classes or {})
- attributes = setmetatable(to_alist(attributes or {}), AttributeList)
- return setmetatable({identifier, classes, attributes}, self.behavior)
-end
-M.Attr.behavior.clone = M.types.clone.Attr
-M.Attr.behavior.tag = 'Attr'
-M.Attr.behavior._field_names = {identifier = 1, classes = 2, attributes = 3}
-M.Attr.behavior.__eq = utils.equals
-M.Attr.behavior.__index = function(t, k)
- return (k == 't' and t.tag) or
- rawget(t, getmetatable(t)._field_names[k]) or
- getmetatable(t)[k]
-end
-M.Attr.behavior.__newindex = function(t, k, v)
- if k == 'attributes' then
- rawset(t, 3, setmetatable(to_alist(v or {}), AttributeList))
- elseif getmetatable(t)._field_names[k] then
- rawset(t, getmetatable(t)._field_names[k], v)
- else
- rawset(t, k, v)
- end
-end
-M.Attr.behavior.__pairs = function(t)
- local field_names = M.Attr.behavior._field_names
- local fields = {}
- for name, i in pairs(field_names) do
- fields[i] = name
- end
- return make_next_function(fields), t, nil
-end
-
--- Monkey-patch setters for `attr` fields to be more forgiving in the input that
--- results in a valid Attr value.
-function augment_attr_setter (setters)
- if setters.attr then
- local orig = setters.attr
- setters.attr = function(k, v)
- orig(k, ensureAttr(v))
- end
- end
-end
-for _, blk in pairs(M.Block.constructor) do
- augment_attr_setter(blk.behavior.setters)
-end
-for _, inln in pairs(M.Inline.constructor) do
- augment_attr_setter(inln.behavior.setters)
-end
-
-
--- Citation
-M.Citation = AstElement:make_subtype'Citation'
-M.Citation.behavior.clone = M.types.clone.Citation
-
---- Creates a single citation.
--- @function Citation
--- @tparam string id citation identifier (like a bibtex key)
--- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
--- @tparam[opt] {Inline,...} prefix citation prefix
--- @tparam[opt] {Inline,...} suffix citation suffix
--- @tparam[opt] int note_num note number
--- @tparam[opt] int hash hash number
-function M.Citation:new (id, mode, prefix, suffix, note_num, hash)
- return {
- id = id,
- mode = mode,
- prefix = ensureList(prefix or {}),
- suffix = ensureList(suffix or {}),
- note_num = note_num or 0,
- hash = hash or 0,
- }
-end
-
--- ListAttributes
-M.ListAttributes = AstElement:make_subtype 'ListAttributes'
-M.ListAttributes.behavior.clone = M.types.clone.ListAttributes
-
---- Creates a set of list attributes.
--- @function ListAttributes
--- @tparam[opt] integer start number of the first list item
--- @tparam[opt] string style style used for list numbering
--- @tparam[opt] DefaultDelim|Period|OneParen|TwoParens delimiter delimiter of list numbers
--- @treturn table list attributes table
-function M.ListAttributes:new (start, style, delimiter)
- start = start or 1
- style = style or 'DefaultStyle'
- delimiter = delimiter or 'DefaultDelim'
- return {start, style, delimiter}
-end
-M.ListAttributes.behavior._field_names = {start = 1, style = 2, delimiter = 3}
-M.ListAttributes.behavior.__eq = utils.equals
-M.ListAttributes.behavior.__index = function (t, k)
- return rawget(t, getmetatable(t)._field_names[k]) or
- getmetatable(t)[k]
-end
-M.ListAttributes.behavior.__newindex = function (t, k, v)
- if getmetatable(t)._field_names[k] then
- rawset(t, getmetatable(t)._field_names[k], v)
- else
- rawset(t, k, v)
- end
-end
-M.ListAttributes.behavior.__pairs = function(t)
- local field_names = M.ListAttributes.behavior._field_names
- local fields = {}
- for name, i in pairs(field_names) do
- fields[i] = name
- end
- return make_next_function(fields), t, nil
-end
-
---
--- Legacy and compatibility types
---
-
---- Creates a simple (old style) table element.
--- @function SimpleTable
--- @tparam {Inline,...} caption table caption
--- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
--- @tparam {int,...} widths column widths
--- @tparam {Block,...} headers header row
--- @tparam {{Block,...}} rows table rows
--- @treturn Block table element
-M.SimpleTable = function(caption, aligns, widths, headers, rows)
- return {
- caption = ensureInlineList(caption),
- aligns = List:new(aligns),
- widths = List:new(widths),
- headers = List:new(headers),
- rows = List:new(rows),
- tag = "SimpleTable",
- t = "SimpleTable",
- }
-end
-
-
-------------------------------------------------------------------------
--- Constants
--- @section constants
-
---- Author name is mentioned in the text.
--- @see Citation
--- @see Cite
-M.AuthorInText = "AuthorInText"
-
---- Author name is suppressed.
--- @see Citation
--- @see Cite
-M.SuppressAuthor = "SuppressAuthor"
-
---- Default citation style is used.
--- @see Citation
--- @see Cite
-M.NormalCitation = "NormalCitation"
-
---- Table cells aligned left.
--- @see Table
-M.AlignLeft = "AlignLeft"
-
---- Table cells right-aligned.
--- @see Table
-M.AlignRight = "AlignRight"
-
---- Table cell content is centered.
--- @see Table
-M.AlignCenter = "AlignCenter"
-
---- Table cells are alignment is unaltered.
--- @see Table
-M.AlignDefault = "AlignDefault"
-
---- Default list number delimiters are used.
--- @see OrderedList
-M.DefaultDelim = "DefaultDelim"
-
---- List numbers are delimited by a period.
--- @see OrderedList
-M.Period = "Period"
-
---- List numbers are delimited by a single parenthesis.
--- @see OrderedList
-M.OneParen = "OneParen"
-
---- List numbers are delimited by a double parentheses.
--- @see OrderedList
-M.TwoParens = "TwoParens"
-
---- List are numbered in the default style
--- @see OrderedList
-M.DefaultStyle = "DefaultStyle"
-
---- List items are numbered as examples.
--- @see OrderedList
-M.Example = "Example"
-
---- List are numbered using decimal integers.
--- @see OrderedList
-M.Decimal = "Decimal"
-
---- List are numbered using lower-case roman numerals.
--- @see OrderedList
-M.LowerRoman = "LowerRoman"
-
---- List are numbered using upper-case roman numerals
--- @see OrderedList
-M.UpperRoman = "UpperRoman"
-
---- List are numbered using lower-case alphabetic characters.
--- @see OrderedList
-M.LowerAlpha = "LowerAlpha"
-
---- List are numbered using upper-case alphabetic characters.
--- @see OrderedList
-M.UpperAlpha = "UpperAlpha"
-
-------------------------------------------------------------------------
--- Functions which have moved to different modules
-M.sha1 = utils.sha1
-
-return M