git.iko.soy/typeable/pandoc
on eb13f76 help sign in
typeable/pandoc/data/pandoc.lua
1039 lines 31 kB history raw
1--[[
2pandoc.lua
4Copyright © 2017–2018 Albert Krewinkel
6Permission to use, copy, modify, and/or distribute this software for any purpose
7with or without fee is hereby granted, provided that the above copyright notice
8and this permission notice appear in all copies.
10THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
12FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
16THIS SOFTWARE.
17]]
19---
20-- Lua functions for pandoc scripts.
21--
22-- @author Albert Krewinkel
23-- @copyright © 2017–2018 Albert Krewinkel
24-- @license MIT
25local M = {}
27local List = require 'pandoc.List'
29------------------------------------------------------------------------
30-- Accessor objects
31--
32-- Create metatables which allow to access numerical indices via accessor
33-- methods.
34-- @section
35-- @local
37--- Create a new indexing function.
38-- @param template function template
39-- @param indices list of indices, starting with the most deeply nested
40-- @return newly created function
41-- @local
42function make_indexing_function(template, indices)
43 local loadstring = loadstring or load
44 local bracketed = {}
45 for i = 1, #indices do
46 bracketed[i] = string.format('[%d]', indices[#indices - i + 1])
47 end
48 local fnstr = string.format('return ' .. template, table.concat(bracketed))
49 return assert(loadstring(fnstr))()
50end
52--- Create accessor functions using a function template.
53-- @param fn_template function template in which '%s' is replacd with indices
54-- @param accessors list of accessors
55-- @return mapping from accessor names to accessor functions
56-- @local
57local function create_accessor_functions (fn_template, accessors)
58 local res = {}
59 function add_accessors(acc, ...)
60 if type(acc) == 'string' then
61 res[acc] = make_indexing_function(fn_template, {...})
62 elseif type(acc) == 'table' and #acc == 0 and next(acc) then
63 local name, substructure = next(acc)
64 res[name] = make_indexing_function(fn_template, {...})
65 add_accessors(substructure, ...)
66 else
67 for i = 1, #(acc or {}) do
68 add_accessors(acc[i], i, ...)
69 end
70 end
71 end
72 add_accessors(accessors)
73 return res
74end
76--- Get list of top-level fields from field descriptor table.
77-- E.g.: `top_level_fields{'foo', {bar='baz'}, {'qux', 'quux'}}`
78-- gives {'foo, 'bar', 'qux', 'quux'}
79-- @local
80local function top_level_fields (fields)
81 local result = List:new{}
82 for _, v in ipairs(fields) do
83 if type(v) == 'string' then
84 table.insert(result, v)
85 elseif type(v) == 'table' and #v == 0 and next(v) then
86 table.insert(result, (next(v)))
87 else
88 result:extend(top_level_fields(v))
89 end
90 end
91 return result
92end
94--- Creates a function which behaves like next, but respects field names.
95-- @local
96local function make_next_function (fields)
97 local field_indices = {}
98 for i, f in ipairs(fields) do
99 field_indices[f] = i
100 end
102 return function (t, field)
103 local raw_idx = field == nil and 0 or field_indices[field]
104 local next_field = fields[raw_idx + 1]
105 return next_field, t[next_field]
106 end
107end
109--- Create a new table which allows to access numerical indices via accessor
110-- functions.
111-- @local
112local function create_accessor_behavior (tag, accessors)
113 local behavior = {tag = tag}
114 behavior.getters = create_accessor_functions(
115 'function (x) return x.c%s end',
116 accessors
117 )
118 behavior.setters = create_accessor_functions(
119 'function (x, v) x.c%s = v end',
120 accessors
121 )
122 behavior.__index = function(t, k)
123 if getmetatable(t).getters[k] then
124 return getmetatable(t).getters[k](t)
125 elseif k == "t" then
126 return getmetatable(t)["tag"]
127 else
128 return getmetatable(t)[k]
129 end
130 end
131 behavior.__newindex = function(t, k, v)
132 if getmetatable(t).setters[k] then
133 getmetatable(t).setters[k](t, v)
134 else
135 rawset(t, k, v)
136 end
137 end
138 behavior.__pairs = function (t)
139 if accessors == nil then
140 return next, t
141 end
142 local iterable_fields = type(accessors) == 'string'
143 and {accessors}
144 or top_level_fields(accessors)
145 return make_next_function(iterable_fields), t
146 end
147 return behavior
148end
151------------------------------------------------------------------------
152-- The base class for types
153-- @type Type
154-- @local
155local Type = {}
156Type.name = 'Type'
157Type.__index = Type
158Type.behavior = {
159 __type = Type,
160 new = function (obj)
161 obj = obj or {}
162 setmetatable(obj, self)
163 return obj
164 end
166Type.behavior.__index = Type.behavior
168--- Set a new behavior for the type, inheriting that of the parent type if none
169--- is specified explicitly
170-- @param behavior the behavior object for this type.
171-- @local
172function Type:set_behavior (behavior)
173 behavior = behavior or {}
174 behavior.__index = rawget(behavior, '__index') or behavior
175 behavior.__type = self
176 if not getmetatable(behavior) and getmetatable(self) then
177 setmetatable(behavior, getmetatable(self).behavior)
178 end
179 self.behavior = behavior
180end
182--- Create a new subtype, using the given table as base.
183-- @param name name of the new type
184-- @param[opt] behavior behavioral object for the new type.
185-- @return a new type
186-- @local
187function Type:make_subtype(name, behavior)
188 local newtype = setmetatable({}, self)
189 newtype.name = name
190 newtype.__index = newtype
191 newtype:set_behavior(behavior)
192 return newtype
193end
196------------------------------------------------------------------------
197-- The base class for pandoc's AST elements.
198-- @type AstElement
199-- @local
200local AstElement = Type:make_subtype 'AstElement'
201AstElement.__call = function(t, ...)
202 local success, ret = pcall(t.new, t, ...)
203 if success then
204 return setmetatable(ret, t.behavior)
205 else
206 error(string.format('Constructor for %s failed: %s\n', t.name, ret))
207 end
208end
210--- Make a new subtype which constructs a new value when called.
211-- @local
212function AstElement:make_subtype(...)
213 local newtype = Type.make_subtype(self, ...)
214 newtype.__call = self.__call
215 return newtype
216end
218--- Create a new constructor
219-- @local
220-- @param tag Tag used to identify the constructor
221-- @param fn Function to be called when constructing a new element
222-- @param accessors names to use as accessors for numerical fields
223-- @return function that constructs a new element
224function AstElement:create_constructor(tag, fn, accessors)
225 local constr = self:make_subtype(tag, create_accessor_behavior(tag, accessors))
226 function constr:new(...)
227 return setmetatable(fn(...), self.behavior)
228 end
229 self.constructor = self.constructor or {}
230 self.constructor[tag] = constr
231 return constr
232end
234--- Convert AstElement input into a list if necessary.
235-- @local
236local function ensureList (x)
237 if x.tag then
238 -- Lists are not tagged, but all elements are
239 return List:new{x}
240 else
241 return List:new(x)
242 end
243end
245--- Ensure a given object is an Inline element, or convert it into one.
246-- @local
247local function ensureInlineList (x)
248 if type(x) == 'string' then
249 return List:new{M.Str(x)}
250 else
251 return ensureList(x)
252 end
253end
255------------------------------------------------------------------------
256--- Pandoc Document
257-- @section document
259--- A complete pandoc document
260-- @function Pandoc
261-- @tparam {Block,...} blocks document content
262-- @tparam[opt] Meta meta document meta data
263M.Pandoc = AstElement:make_subtype'Pandoc'
264function M.Pandoc:new (blocks, meta)
265 return {
266 blocks = ensureList(blocks),
267 meta = meta or {},
268 }
269end
271-- DEPRECATED synonym:
272M.Doc = M.Pandoc
274------------------------------------------------------------------------
275-- Meta
276-- @section Meta
278--- Create a new Meta object. It sets the metatable of the given table to
279--- `Meta`.
280-- @function Meta
281-- @tparam meta table table containing document meta information
282M.Meta = AstElement:make_subtype'Meta'
283function M.Meta:new (meta) return meta end
286------------------------------------------------------------------------
287-- MetaValue
288-- @section MetaValue
289M.MetaValue = AstElement:make_subtype('MetaValue')
291--- Meta blocks
292-- @function MetaBlocks
293-- @tparam {Block,...} blocks blocks
294M.MetaBlocks = M.MetaValue:create_constructor(
295 'MetaBlocks',
296 function (content) return ensureList(content) end
299--- Meta inlines
300-- @function MetaInlines
301-- @tparam {Inline,...} inlines inlines
302M.MetaInlines = M.MetaValue:create_constructor(
303 'MetaInlines',
304 function (content) return ensureInlineList(content) end
307--- Meta list
308-- @function MetaList
309-- @tparam {MetaValue,...} meta_values list of meta values
310M.MetaList = M.MetaValue:create_constructor(
311 'MetaList',
312 function (content)
313 if content.tag == 'MetaList' then
314 return content
315 end
316 return ensureList(content)
317 end
319for k, v in pairs(List) do
320 M.MetaList.behavior[k] = v
321end
323--- Meta map
324-- @function MetaMap
325-- @tparam table key_value_map a string-indexed map of meta values
326M.MetaMap = M.MetaValue:create_constructor(
327 "MetaMap",
328 function (mm) return mm end
331--- Creates string to be used in meta data.
332-- Does nothing, lua strings are meta strings.
333-- @function MetaString
334-- @tparam string str string value
335function M.MetaString(str)
336 return str
337end
339--- Creates boolean to be used in meta data.
340-- Does nothing, lua booleans are meta booleans.
341-- @function MetaBool
342-- @tparam boolean bool boolean value
343function M.MetaBool(bool)
344 return bool
345end
347------------------------------------------------------------------------
348-- Blocks
349-- @section Block
351--- Block elements
352M.Block = AstElement:make_subtype'Block'
354--- Creates a block quote element
355-- @function BlockQuote
356-- @tparam {Block,...} content block content
357-- @treturn Block block quote element
358M.BlockQuote = M.Block:create_constructor(
359 "BlockQuote",
360 function(content) return {c = ensureList(content)} end,
361 "content"
364--- Creates a bullet (i.e. unordered) list.
365-- @function BulletList
366-- @tparam {{Block,...},...} content list of items
367-- @treturn Block bullet list element
368M.BulletList = M.Block:create_constructor(
369 "BulletList",
370 function(content) return {c = ensureList(content)} end,
371 "content"
374--- Creates a code block element
375-- @function CodeBlock
376-- @tparam string text code string
377-- @tparam[opt] Attr attr element attributes
378-- @treturn Block code block element
379M.CodeBlock = M.Block:create_constructor(
380 "CodeBlock",
381 function(text, attr) return {c = {attr or M.Attr(), text}} end,
382 {{attr = {"identifier", "classes", "attributes"}}, "text"}
385--- Creates a definition list, containing terms and their explanation.
386-- @function DefinitionList
387-- @tparam {{{Inline,...},{Block,...}},...} content list of items
388-- @treturn Block definition list element
389M.DefinitionList = M.Block:create_constructor(
390 "DefinitionList",
391 function(content) return {c = ensureList(content)} end,
392 "content"
395--- Creates a div element
396-- @function Div
397-- @tparam {Block,...} content block content
398-- @tparam[opt] Attr attr element attributes
399-- @treturn Block div element
400M.Div = M.Block:create_constructor(
401 "Div",
402 function(content, attr)
403 return {c = {attr or M.Attr(), ensureList(content)}}
404 end,
405 {{attr = {"identifier", "classes", "attributes"}}, "content"}
408--- Creates a header element.
409-- @function Header
410-- @tparam int level header level
411-- @tparam {Inline,...} content inline content
412-- @tparam[opt] Attr attr element attributes
413-- @treturn Block header element
414M.Header = M.Block:create_constructor(
415 "Header",
416 function(level, content, attr)
417 return {c = {level, attr or M.Attr(), ensureInlineList(content)}}
418 end,
419 {"level", {attr = {"identifier", "classes", "attributes"}}, "content"}
422--- Creates a horizontal rule.
423-- @function HorizontalRule
424-- @treturn Block horizontal rule
425M.HorizontalRule = M.Block:create_constructor(
426 "HorizontalRule",
427 function() return {} end
430--- Creates a line block element.
431-- @function LineBlock
432-- @tparam {{Inline,...},...} content inline content
433-- @treturn Block line block element
434M.LineBlock = M.Block:create_constructor(
435 "LineBlock",
436 function(content) return {c = ensureList(content)} end,
437 "content"
440--- Creates a null element.
441-- @function Null
442-- @treturn Block null element
443M.Null = M.Block:create_constructor(
444 "Null",
445 function() return {} end
448--- Creates an ordered list.
449-- @function OrderedList
450-- @tparam {{Block,...},...} items list items
451-- @param[opt] listAttributes list parameters
452-- @treturn Block ordered list element
453M.OrderedList = M.Block:create_constructor(
454 "OrderedList",
455 function(items, listAttributes)
456 listAttributes = listAttributes or M.ListAttributes()
457 return {c = {listAttributes, ensureList(items)}}
458 end,
459 {{listAttributes = {"start", "style", "delimiter"}}, "content"}
462--- Creates a para element.
463-- @function Para
464-- @tparam {Inline,...} content inline content
465-- @treturn Block paragraph element
466M.Para = M.Block:create_constructor(
467 "Para",
468 function(content) return {c = ensureInlineList(content)} end,
469 "content"
472--- Creates a plain element.
473-- @function Plain
474-- @tparam {Inline,...} content inline content
475-- @treturn Block plain element
476M.Plain = M.Block:create_constructor(
477 "Plain",
478 function(content) return {c = ensureInlineList(content)} end,
479 "content"
482--- Creates a raw content block of the specified format.
483-- @function RawBlock
484-- @tparam string format format of content
485-- @tparam string text string content
486-- @treturn Block raw block element
487M.RawBlock = M.Block:create_constructor(
488 "RawBlock",
489 function(format, text) return {c = {format, text}} end,
490 {"format", "text"}
493--- Creates a table element.
494-- @function Table
495-- @tparam {Inline,...} caption table caption
496-- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
497-- @tparam {int,...} widths column widths
498-- @tparam {Block,...} headers header row
499-- @tparam {{Block,...}} rows table rows
500-- @treturn Block table element
501M.Table = M.Block:create_constructor(
502 "Table",
503 function(caption, aligns, widths, headers, rows)
504 return {
505 c = {
506 ensureInlineList(caption),
507 List:new(aligns),
508 List:new(widths),
509 List:new(headers),
510 List:new(rows)
511 }
512 }
513 end,
514 {"caption", "aligns", "widths", "headers", "rows"}
518------------------------------------------------------------------------
519-- Inline
520-- @section Inline
522--- Inline element class
523M.Inline = AstElement:make_subtype'Inline'
525--- Creates a Cite inline element
526-- @function Cite
527-- @tparam {Inline,...} content List of inlines
528-- @tparam {Citation,...} citations List of citations
529-- @treturn Inline citations element
530M.Cite = M.Inline:create_constructor(
531 "Cite",
532 function(content, citations)
533 return {c = {ensureList(citations), ensureInlineList(content)}}
534 end,
535 {"citations", "content"}
538--- Creates a Code inline element
539-- @function Code
540-- @tparam string text code string
541-- @tparam[opt] Attr attr additional attributes
542-- @treturn Inline code element
543M.Code = M.Inline:create_constructor(
544 "Code",
545 function(text, attr) return {c = {attr or M.Attr(), text}} end,
546 {{attr = {"identifier", "classes", "attributes"}}, "text"}
549--- Creates an inline element representing emphasised text.
550-- @function Emph
551-- @tparam {Inline,..} content inline content
552-- @treturn Inline emphasis element
553M.Emph = M.Inline:create_constructor(
554 "Emph",
555 function(content) return {c = ensureInlineList(content)} end,
556 "content"
559--- Creates a Image inline element
560-- @function Image
561-- @tparam {Inline,..} caption text used to describe the image
562-- @tparam string src path to the image file
563-- @tparam[opt] string title brief image description
564-- @tparam[opt] Attr attr additional attributes
565-- @treturn Inline image element
566M.Image = M.Inline:create_constructor(
567 "Image",
568 function(caption, src, title, attr)
569 title = title or ""
570 attr = attr or M.Attr()
571 return {c = {attr, ensureInlineList(caption), {src, title}}}
572 end,
573 {{attr = {"identifier", "classes", "attributes"}}, "caption", {"src", "title"}}
576--- Create a LineBreak inline element
577-- @function LineBreak
578-- @treturn Inline linebreak element
579M.LineBreak = M.Inline:create_constructor(
580 "LineBreak",
581 function() return {} end
584--- Creates a link inline element, usually a hyperlink.
585-- @function Link
586-- @tparam {Inline,..} content text for this link
587-- @tparam string target the link target
588-- @tparam[opt] string title brief link description
589-- @tparam[opt] Attr attr additional attributes
590-- @treturn Inline image element
591M.Link = M.Inline:create_constructor(
592 "Link",
593 function(content, target, title, attr)
594 title = title or ""
595 attr = attr or M.Attr()
596 return {c = {attr, ensureInlineList(content), {target, title}}}
597 end,
598 {{attr = {"identifier", "classes", "attributes"}}, "content", {"target", "title"}}
601--- Creates a Math element, either inline or displayed.
602-- @function Math
603-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
604-- @tparam string text Math content
605-- @treturn Inline Math element
606M.Math = M.Inline:create_constructor(
607 "Math",
608 function(mathtype, text)
609 return {c = {mathtype, text}}
610 end,
611 {"mathtype", "text"}
613--- Creates a DisplayMath element (DEPRECATED).
614-- @function DisplayMath
615-- @tparam string text Math content
616-- @treturn Inline Math element
617M.DisplayMath = M.Inline:create_constructor(
618 "DisplayMath",
619 function(text) return M.Math("DisplayMath", text) end,
620 {"mathtype", "text"}
622--- Creates an InlineMath inline element (DEPRECATED).
623-- @function InlineMath
624-- @tparam string text Math content
625-- @treturn Inline Math element
626M.InlineMath = M.Inline:create_constructor(
627 "InlineMath",
628 function(text) return M.Math("InlineMath", text) end,
629 {"mathtype", "text"}
632--- Creates a Note inline element
633-- @function Note
634-- @tparam {Block,...} content footnote block content
635M.Note = M.Inline:create_constructor(
636 "Note",
637 function(content) return {c = ensureList(content)} end,
638 "content"
641--- Creates a Quoted inline element given the quote type and quoted content.
642-- @function Quoted
643-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
644-- @tparam {Inline,..} content inline content
645-- @treturn Inline quoted element
646M.Quoted = M.Inline:create_constructor(
647 "Quoted",
648 function(quotetype, content) return {c = {quotetype, ensureInlineList(content)}} end,
649 {"quotetype", "content"}
651--- Creates a single-quoted inline element (DEPRECATED).
652-- @function SingleQuoted
653-- @tparam {Inline,..} content inline content
654-- @treturn Inline quoted element
655-- @see Quoted
656M.SingleQuoted = M.Inline:create_constructor(
657 "SingleQuoted",
658 function(content) return M.Quoted(M.SingleQuote, content) end,
659 {"quotetype", "content"}
661--- Creates a single-quoted inline element (DEPRECATED).
662-- @function DoubleQuoted
663-- @tparam {Inline,..} content inline content
664-- @treturn Inline quoted element
665-- @see Quoted
666M.DoubleQuoted = M.Inline:create_constructor(
667 "DoubleQuoted",
668 function(content) return M.Quoted("DoubleQuote", content) end,
669 {"quotetype", "content"}
672--- Creates a RawInline inline element
673-- @function RawInline
674-- @tparam string format format of the contents
675-- @tparam string text string content
676-- @treturn Inline raw inline element
677M.RawInline = M.Inline:create_constructor(
678 "RawInline",
679 function(format, text) return {c = {format, text}} end,
680 {"format", "text"}
683--- Creates text rendered in small caps
684-- @function SmallCaps
685-- @tparam {Inline,..} content inline content
686-- @treturn Inline smallcaps element
687M.SmallCaps = M.Inline:create_constructor(
688 "SmallCaps",
689 function(content) return {c = ensureInlineList(content)} end,
690 "content"
693--- Creates a SoftBreak inline element.
694-- @function SoftBreak
695-- @treturn Inline softbreak element
696M.SoftBreak = M.Inline:create_constructor(
697 "SoftBreak",
698 function() return {} end
701--- Create a Space inline element
702-- @function Space
703-- @treturn Inline space element
704M.Space = M.Inline:create_constructor(
705 "Space",
706 function() return {} end
709--- Creates a Span inline element
710-- @function Span
711-- @tparam {Inline,..} content inline content
712-- @tparam[opt] Attr attr additional attributes
713-- @treturn Inline span element
714M.Span = M.Inline:create_constructor(
715 "Span",
716 function(content, attr)
717 return {c = {attr or M.Attr(), ensureInlineList(content)}}
718 end,
719 {{attr = {"identifier", "classes", "attributes"}}, "content"}
722--- Creates a Str inline element
723-- @function Str
724-- @tparam string text content
725-- @treturn Inline string element
726M.Str = M.Inline:create_constructor(
727 "Str",
728 function(text) return {c = text} end,
729 "text"
732--- Creates text which is striked out.
733-- @function Strikeout
734-- @tparam {Inline,..} content inline content
735-- @treturn Inline strikeout element
736M.Strikeout = M.Inline:create_constructor(
737 "Strikeout",
738 function(content) return {c = ensureInlineList(content)} end,
739 "content"
742--- Creates a Strong element, whose text is usually displayed in a bold font.
743-- @function Strong
744-- @tparam {Inline,..} content inline content
745-- @treturn Inline strong element
746M.Strong = M.Inline:create_constructor(
747 "Strong",
748 function(content) return {c = ensureInlineList(content)} end,
749 "content"
752--- Creates a Subscript inline element
753-- @function Subscript
754-- @tparam {Inline,..} content inline content
755-- @treturn Inline subscript element
756M.Subscript = M.Inline:create_constructor(
757 "Subscript",
758 function(content) return {c = ensureInlineList(content)} end,
759 "content"
762--- Creates a Superscript inline element
763-- @function Superscript
764-- @tparam {Inline,..} content inline content
765-- @treturn Inline strong element
766M.Superscript = M.Inline:create_constructor(
767 "Superscript",
768 function(content) return {c = ensureInlineList(content)} end,
769 "content"
773------------------------------------------------------------------------
774-- Element components
775-- @section components
777--- Check if the first element of a pair matches the given value.
778-- @param x key value to be checked
779-- @return function returning true iff first element of its argument matches x
780-- @local
781local function assoc_key_equals (x)
782 return function (y) return y[1] == x end
783end
785--- Lookup a value in an associative list
786-- @function lookup
787-- @local
788-- @tparam {{key, value},...} alist associative list
789-- @param key key for which the associated value is to be looked up
790local function lookup(alist, key)
791 return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
792end
794--- Return an iterator which returns key-value pairs of an associative list.
795-- @function apairs
796-- @local
797-- @tparam {{key, value},...} alist associative list
798local apairs = function (alist)
799 local i = 1
800 local cur
801 function nxt ()
802 cur = rawget(alist, i)
803 if cur then
804 i = i + 1
805 return cur[1], cur[2]
806 end
807 return nil
808 end
809 return nxt, nil, nil
810end
812--- AttributeList, a metatable to allow table-like access to attribute lists
813-- represented by associative lists.
814-- @local
815local AttributeList = {
816 __index = function (t, k)
817 if type(k) == "number" then
818 return rawget(t, k)
819 else
820 return lookup(t, k)
821 end
822 end,
824 __newindex = function (t, k, v)
825 local cur, idx = List.find_if(t, assoc_key_equals(k))
826 if v == nil then
827 table.remove(t, idx)
828 elseif cur then
829 cur[2] = v
830 elseif type(k) == "number" then
831 rawset(t, k, v)
832 else
833 rawset(t, #t + 1, {k, v})
834 end
835 end,
837 __pairs = apairs
840--- Convert a table to an associative list. The order of key-value pairs in the
841-- alist is undefined. The table should either contain no numeric keys or
842-- already be an associative list.
843-- @local
844-- @tparam table tbl associative list or table without numeric keys.
845-- @treturn table associative list
846local to_alist = function (tbl)
847 if #tbl ~= 0 or next(tbl) == nil then
848 -- probably already an alist
849 return tbl
850 end
851 local alist = {}
852 local i = 1
853 for k, v in pairs(tbl) do
854 alist[i] = {k, v}
855 i = i + 1
856 end
857 return alist
858end
860-- Attr
862--- Create a new set of attributes (Attr).
863-- @function Attr
864-- @tparam[opt] string identifier element identifier
865-- @tparam[opt] {string,...} classes element classes
866-- @tparam[opt] table attributes table containing string keys and values
867-- @return element attributes
868M.Attr = AstElement:make_subtype'Attr'
869function M.Attr:new (identifier, classes, attributes)
870 identifier = identifier or ''
871 classes = ensureList(classes or {})
872 attributes = setmetatable(to_alist(attributes or {}), AttributeList)
873 return {identifier, classes, attributes}
874end
875M.Attr.behavior._field_names = {identifier = 1, classes = 2, attributes = 3}
876M.Attr.behavior.__index = function(t, k)
877 return rawget(t, getmetatable(t)._field_names[k]) or
878 getmetatable(t)[k]
879end
880M.Attr.behavior.__newindex = function(t, k, v)
881 if getmetatable(t)._field_names[k] then
882 rawset(t, getmetatable(t)._field_names[k], v)
883 else
884 rawset(t, k, v)
885 end
886end
887M.Attr.behavior.__pairs = function(t)
888 local field_names = M.Attr.behavior._field_names
889 local fields = {}
890 for name, i in pairs(field_names) do
891 fields[i] = name
892 end
893 return make_next_function(fields), t, nil
894end
896-- Citation
897M.Citation = AstElement:make_subtype'Citation'
899--- Creates a single citation.
900-- @function Citation
901-- @tparam string id citation identifier (like a bibtex key)
902-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
903-- @tparam[opt] {Inline,...} prefix citation prefix
904-- @tparam[opt] {Inline,...} suffix citation suffix
905-- @tparam[opt] int note_num note number
906-- @tparam[opt] int hash hash number
907function M.Citation:new (id, mode, prefix, suffix, note_num, hash)
908 return {
909 id = id,
910 mode = mode,
911 prefix = ensureList(prefix or {}),
912 suffix = ensureList(suffix or {}),
913 note_num = note_num or 0,
914 hash = hash or 0,
915 }
916end
918-- ListAttributes
919M.ListAttributes = AstElement:make_subtype 'ListAttributes'
921--- Creates a set of list attributes.
922-- @function ListAttributes
923-- @tparam[opt] integer start number of the first list item
924-- @tparam[opt] string style style used for list numbering
925-- @tparam[opt] DefaultDelim|Period|OneParen|TwoParens delimiter delimiter of list numbers
926-- @treturn table list attributes table
927function M.ListAttributes:new (start, style, delimiter)
928 start = start or 1
929 style = style or 'DefaultStyle'
930 delimiter = delimiter or 'DefaultDelim'
931 return {start, style, delimiter}
932end
933M.ListAttributes.behavior._field_names = {start = 1, style = 2, delimiter = 3}
934M.ListAttributes.behavior.__index = function (t, k)
935 return rawget(t, getmetatable(t)._field_names[k]) or
936 getmetatable(t)[k]
937end
938M.ListAttributes.behavior.__newindex = function (t, k, v)
939 if getmetatable(t)._field_names[k] then
940 rawset(t, getmetatable(t)._field_names[k], v)
941 else
942 rawset(t, k, v)
943 end
944end
945M.ListAttributes.behavior.__pairs = function(t)
946 local field_names = M.ListAttributes.behavior._field_names
947 local fields = {}
948 for name, i in pairs(field_names) do
949 fields[i] = name
950 end
951 return make_next_function(fields), t, nil
952end
955------------------------------------------------------------------------
956-- Constants
957-- @section constants
959--- Author name is mentioned in the text.
960-- @see Citation
961-- @see Cite
962M.AuthorInText = "AuthorInText"
964--- Author name is suppressed.
965-- @see Citation
966-- @see Cite
967M.SuppressAuthor = "SuppressAuthor"
969--- Default citation style is used.
970-- @see Citation
971-- @see Cite
972M.NormalCitation = "NormalCitation"
974--- Table cells aligned left.
975-- @see Table
976M.AlignLeft = "AlignLeft"
978--- Table cells right-aligned.
979-- @see Table
980M.AlignRight = "AlignRight"
982--- Table cell content is centered.
983-- @see Table
984M.AlignCenter = "AlignCenter"
986--- Table cells are alignment is unaltered.
987-- @see Table
988M.AlignDefault = "AlignDefault"
990--- Default list number delimiters are used.
991-- @see OrderedList
992M.DefaultDelim = "DefaultDelim"
994--- List numbers are delimited by a period.
995-- @see OrderedList
996M.Period = "Period"
998--- List numbers are delimited by a single parenthesis.
999-- @see OrderedList
1000M.OneParen = "OneParen"
1002--- List numbers are delimited by a double parentheses.
1003-- @see OrderedList
1004M.TwoParens = "TwoParens"
1006--- List are numbered in the default style
1007-- @see OrderedList
1008M.DefaultStyle = "DefaultStyle"
1010--- List items are numbered as examples.
1011-- @see OrderedList
1012M.Example = "Example"
1014--- List are numbered using decimal integers.
1015-- @see OrderedList
1016M.Decimal = "Decimal"
1018--- List are numbered using lower-case roman numerals.
1019-- @see OrderedList
1020M.LowerRoman = "LowerRoman"
1022--- List are numbered using upper-case roman numerals
1023-- @see OrderedList
1024M.UpperRoman = "UpperRoman"
1026--- List are numbered using lower-case alphabetic characters.
1027-- @see OrderedList
1028M.LowerAlpha = "LowerAlpha"
1030--- List are numbered using upper-case alphabetic characters.
1031-- @see OrderedList
1032M.UpperAlpha = "UpperAlpha"
1034------------------------------------------------------------------------
1035-- Functions which have moved to different modules
1036local utils = require 'pandoc.utils'
1037M.sha1 = utils.sha1
1039return M