2017-03-20 15:17:03 +01:00
|
|
|
|
--[[
|
|
|
|
|
pandoc.lua
|
|
|
|
|
|
2019-02-09 09:52:51 +01:00
|
|
|
|
Copyright © 2017–2019 Albert Krewinkel
|
2017-03-20 15:17:03 +01:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
]]
|
|
|
|
|
|
2017-04-13 19:10:51 +02:00
|
|
|
|
---
|
|
|
|
|
-- Lua functions for pandoc scripts.
|
|
|
|
|
--
|
|
|
|
|
-- @author Albert Krewinkel
|
2019-02-09 09:52:51 +01:00
|
|
|
|
-- @copyright © 2017–2019 Albert Krewinkel
|
2017-04-13 19:10:51 +02:00
|
|
|
|
-- @license MIT
|
2018-01-13 23:05:42 +01:00
|
|
|
|
local M = {}
|
2017-03-20 15:17:03 +01:00
|
|
|
|
|
2019-02-09 09:52:51 +01:00
|
|
|
|
-- Re-export bundled modules
|
|
|
|
|
M.List = require 'pandoc.List'
|
|
|
|
|
M.mediabag = require 'pandoc.mediabag'
|
2021-11-01 13:48:36 +01:00
|
|
|
|
M.path = require 'pandoc.path'
|
2019-05-04 07:06:30 +02:00
|
|
|
|
M.system = require 'pandoc.system'
|
2019-06-12 18:58:38 +02:00
|
|
|
|
M.types = require 'pandoc.types'
|
2019-02-09 09:52:51 +01:00
|
|
|
|
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
|
2017-11-29 01:20:01 +01:00
|
|
|
|
|
2019-02-07 09:50:06 +01:00
|
|
|
|
|
2018-01-08 23:26:38 +01:00
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
|
-- Accessor objects
|
|
|
|
|
--
|
|
|
|
|
-- Create metatables which allow to access numerical indices via accessor
|
|
|
|
|
-- methods.
|
|
|
|
|
-- @section
|
|
|
|
|
-- @local
|
|
|
|
|
|
|
|
|
|
--- Create a new table which allows to access numerical indices via accessor
|
|
|
|
|
-- functions.
|
|
|
|
|
-- @local
|
2021-10-29 17:08:03 +02:00
|
|
|
|
local function create_accessor_behavior (tag)
|
2018-01-08 23:26:38 +01:00
|
|
|
|
local behavior = {tag = tag}
|
2018-11-19 21:36:02 +01:00
|
|
|
|
behavior.__eq = utils.equals
|
2018-01-08 23:26:38 +01:00
|
|
|
|
behavior.__index = function(t, k)
|
2021-10-29 17:08:03 +02:00
|
|
|
|
if k == "t" then
|
2018-01-08 23:26:38 +01:00
|
|
|
|
return getmetatable(t)["tag"]
|
|
|
|
|
end
|
2021-11-01 08:14:44 +01:00
|
|
|
|
return getmetatable(t)[k]
|
2018-01-08 23:26:38 +01:00
|
|
|
|
end
|
2018-10-20 15:06:16 +02:00
|
|
|
|
behavior.__pairs = function (t)
|
2021-10-29 17:08:03 +02:00
|
|
|
|
return next, t
|
2018-10-20 15:06:16 +02:00
|
|
|
|
end
|
2018-01-08 23:26:38 +01:00
|
|
|
|
return behavior
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
2017-04-12 21:21:25 +02:00
|
|
|
|
------------------------------------------------------------------------
|
2018-01-06 23:25:08 +01:00
|
|
|
|
-- The base class for types
|
|
|
|
|
-- @type Type
|
2017-04-13 19:10:51 +02:00
|
|
|
|
-- @local
|
2018-01-06 23:25:08 +01:00
|
|
|
|
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
|
2017-04-12 21:21:25 +02:00
|
|
|
|
|
2018-01-06 23:25:08 +01:00
|
|
|
|
--- Set a new behavior for the type, inheriting that of the parent type if none
|
2018-06-09 00:15:36 +02:00
|
|
|
|
--- is specified explicitly
|
2018-01-06 23:25:08 +01:00
|
|
|
|
-- @param behavior the behavior object for this type.
|
2017-04-13 19:10:51 +02:00
|
|
|
|
-- @local
|
2018-01-06 23:25:08 +01:00
|
|
|
|
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
|
2017-03-20 15:17:03 +01:00
|
|
|
|
end
|
2017-04-12 21:21:25 +02:00
|
|
|
|
|
2018-01-06 23:25:08 +01:00
|
|
|
|
--- Create a new subtype, using the given table as base.
|
2018-01-07 22:41:59 +01:00
|
|
|
|
-- @param name name of the new type
|
|
|
|
|
-- @param[opt] behavior behavioral object for the new type.
|
|
|
|
|
-- @return a new type
|
2017-04-13 19:10:51 +02:00
|
|
|
|
-- @local
|
2018-01-06 23:25:08 +01:00
|
|
|
|
function Type:make_subtype(name, behavior)
|
|
|
|
|
local newtype = setmetatable({}, self)
|
|
|
|
|
newtype.name = name
|
|
|
|
|
newtype.__index = newtype
|
|
|
|
|
newtype:set_behavior(behavior)
|
|
|
|
|
return newtype
|
2017-03-20 15:17:03 +01:00
|
|
|
|
end
|
|
|
|
|
|
2018-01-06 23:25:08 +01:00
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
|
-- The base class for pandoc's AST elements.
|
|
|
|
|
-- @type AstElement
|
|
|
|
|
-- @local
|
|
|
|
|
local AstElement = Type:make_subtype 'AstElement'
|
2018-01-07 11:22:53 +01:00
|
|
|
|
AstElement.__call = function(t, ...)
|
2018-01-08 23:26:38 +01:00
|
|
|
|
local success, ret = pcall(t.new, t, ...)
|
2018-01-07 11:22:53 +01:00
|
|
|
|
if success then
|
|
|
|
|
return setmetatable(ret, t.behavior)
|
|
|
|
|
else
|
|
|
|
|
error(string.format('Constructor for %s failed: %s\n', t.name, ret))
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-01-06 23:25:08 +01:00
|
|
|
|
|
2018-01-09 07:29:56 +01:00
|
|
|
|
--- Make a new subtype which constructs a new value when called.
|
|
|
|
|
-- @local
|
2018-01-08 23:26:38 +01:00
|
|
|
|
function AstElement:make_subtype(...)
|
|
|
|
|
local newtype = Type.make_subtype(self, ...)
|
|
|
|
|
newtype.__call = self.__call
|
|
|
|
|
return newtype
|
|
|
|
|
end
|
|
|
|
|
|
2017-04-12 21:21:25 +02:00
|
|
|
|
--- Create a new constructor
|
2017-04-13 19:10:51 +02:00
|
|
|
|
-- @local
|
2017-04-12 21:21:25 +02:00
|
|
|
|
-- @param tag Tag used to identify the constructor
|
|
|
|
|
-- @param fn Function to be called when constructing a new element
|
2017-08-21 17:47:54 +02:00
|
|
|
|
-- @param accessors names to use as accessors for numerical fields
|
2017-04-12 21:21:25 +02:00
|
|
|
|
-- @return function that constructs a new element
|
2021-10-29 17:08:03 +02:00
|
|
|
|
function AstElement:create_constructor(tag, fn)
|
|
|
|
|
local constr = self:make_subtype(tag, create_accessor_behavior(tag))
|
2017-04-12 21:21:25 +02:00
|
|
|
|
function constr:new(...)
|
2018-01-06 23:25:08 +01:00
|
|
|
|
return setmetatable(fn(...), self.behavior)
|
2017-04-12 21:21:25 +02:00
|
|
|
|
end
|
2017-04-13 19:10:51 +02:00
|
|
|
|
self.constructor = self.constructor or {}
|
|
|
|
|
self.constructor[tag] = constr
|
2017-04-12 21:21:25 +02:00
|
|
|
|
return constr
|
|
|
|
|
end
|
|
|
|
|
|
2018-01-13 22:29:16 +01:00
|
|
|
|
--- 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
|
|
|
|
|
|
2018-01-13 18:52:17 +01:00
|
|
|
|
--- Ensure a given object is an Inline element, or convert it into one.
|
2018-01-13 22:29:16 +01:00
|
|
|
|
-- @local
|
2018-01-13 18:52:17 +01:00
|
|
|
|
local function ensureInlineList (x)
|
2018-01-13 22:29:16 +01:00
|
|
|
|
if type(x) == 'string' then
|
2018-01-13 18:52:17 +01:00
|
|
|
|
return List:new{M.Str(x)}
|
|
|
|
|
else
|
2018-01-13 22:29:16 +01:00
|
|
|
|
return ensureList(x)
|
2018-01-13 18:52:17 +01:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-12-01 17:58:12 +01:00
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
|
-- 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
|
2018-01-07 11:22:53 +01:00
|
|
|
|
M.Meta = AstElement:make_subtype'Meta'
|
2019-06-12 18:58:38 +02:00
|
|
|
|
M.Meta.behavior.clone = M.types.clone.Meta
|
2018-01-08 23:26:38 +01:00
|
|
|
|
function M.Meta:new (meta) return meta end
|
2017-12-01 17:58:12 +01:00
|
|
|
|
|
|
|
|
|
|
2017-04-13 22:57:50 +02:00
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
|
-- MetaValue
|
|
|
|
|
-- @section MetaValue
|
2018-01-07 11:22:53 +01:00
|
|
|
|
M.MetaValue = AstElement:make_subtype('MetaValue')
|
2019-06-12 18:58:38 +02:00
|
|
|
|
M.MetaValue.behavior.clone = M.types.clone.MetaValue
|
2018-01-07 11:22:53 +01:00
|
|
|
|
|
2017-04-13 22:57:50 +02:00
|
|
|
|
--- Meta blocks
|
|
|
|
|
-- @function MetaBlocks
|
|
|
|
|
-- @tparam {Block,...} blocks blocks
|
2018-01-09 07:29:56 +01:00
|
|
|
|
M.MetaBlocks = M.MetaValue:create_constructor(
|
|
|
|
|
'MetaBlocks',
|
2018-01-13 22:29:16 +01:00
|
|
|
|
function (content) return ensureList(content) end
|
2018-01-09 07:29:56 +01:00
|
|
|
|
)
|
2017-04-14 10:33:38 +02:00
|
|
|
|
|
2017-04-13 22:57:50 +02:00
|
|
|
|
--- Meta inlines
|
|
|
|
|
-- @function MetaInlines
|
|
|
|
|
-- @tparam {Inline,...} inlines inlines
|
2018-01-09 07:29:56 +01:00
|
|
|
|
M.MetaInlines = M.MetaValue:create_constructor(
|
|
|
|
|
'MetaInlines',
|
2018-01-13 18:52:17 +01:00
|
|
|
|
function (content) return ensureInlineList(content) end
|
2018-01-09 07:29:56 +01:00
|
|
|
|
)
|
2017-04-14 10:33:38 +02:00
|
|
|
|
|
2017-04-13 22:57:50 +02:00
|
|
|
|
--- Meta list
|
|
|
|
|
-- @function MetaList
|
|
|
|
|
-- @tparam {MetaValue,...} meta_values list of meta values
|
2018-01-09 07:29:56 +01:00
|
|
|
|
M.MetaList = M.MetaValue:create_constructor(
|
|
|
|
|
'MetaList',
|
2018-10-15 21:00:50 +02:00
|
|
|
|
function (content)
|
|
|
|
|
if content.tag == 'MetaList' then
|
|
|
|
|
return content
|
|
|
|
|
end
|
|
|
|
|
return ensureList(content)
|
|
|
|
|
end
|
2018-01-09 07:29:56 +01:00
|
|
|
|
)
|
2018-10-15 21:08:39 +02:00
|
|
|
|
for k, v in pairs(List) do
|
|
|
|
|
M.MetaList.behavior[k] = v
|
|
|
|
|
end
|
2017-04-13 22:57:50 +02:00
|
|
|
|
|
2017-12-01 18:47:33 +01:00
|
|
|
|
--- Meta map
|
|
|
|
|
-- @function MetaMap
|
|
|
|
|
-- @tparam table key_value_map a string-indexed map of meta values
|
2017-12-19 09:12:16 +01:00
|
|
|
|
M.MetaMap = M.MetaValue:create_constructor(
|
|
|
|
|
"MetaMap",
|
|
|
|
|
function (mm) return mm end
|
|
|
|
|
)
|
2017-12-01 18:47:33 +01:00
|
|
|
|
|
2017-04-16 21:00:01 +02:00
|
|
|
|
--- 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
|
|
|
|
|
|
2017-03-20 15:17:03 +01:00
|
|
|
|
return M
|