git.iko.soy/typeable/pandoc
on a29fa15 help sign in
typeable/pandoc/data/pandoc.lua
817 lines 23 kB history raw
1--[[
2pandoc.lua
4Copyright © 2017 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 Albert Krewinkel
24-- @license MIT
25local M = {
26 _VERSION = "0.2.0"
29------------------------------------------------------------------------
30-- The base class for pandoc's AST elements.
31-- @type Element
32-- @local
33local Element = {}
35--- Create a new element subtype
36-- @local
37function Element:make_subtype(o)
38 o = o or {}
39 setmetatable(o, self)
40 self.__index = self
41 return o
42end
44--- Create a new element given its tag and arguments
45-- @local
46function Element:new(tag, ...)
47 local element = { t = tag }
48 local content = {...}
49 -- special case for unary constructors
50 if #content == 1 then
51 element.c = content[1]
52 -- Don't set 'c' field if no further arguments were given. This is important
53 -- for nullary constructors like `Space` and `HorizontalRule`.
54 elseif #content > 0 then
55 element.c = content
56 end
57 setmetatable(element, self)
58 self.__index = self
59 return element
60end
62--- Create a new constructor
63-- @local
64-- @param tag Tag used to identify the constructor
65-- @param fn Function to be called when constructing a new element
66-- @return function that constructs a new element
67function Element:create_constructor(tag, fn, accessors)
68 local constr = self:make_subtype({tag = tag, getters = {}, setters = {}})
70 -- Add accessors to the metatable
71 if type(accessors) == "string" then
72 constr.getters[accessors] = function(elem)
73 return elem.c
74 end
75 constr.setters[accessors] = function(elem, v)
76 elem.c = v
77 end
78 else
79 for i = 1, #(accessors or {}) do
80 if type(accessors[i]) == "string" then
81 constr.getters[accessors[i]] = function(elem)
82 return elem.c[i]
83 end
84 constr.setters[accessors[i]] = function(elem, v)
85 elem.c[i] = v
86 end
87 else -- only two levels of nesting are supported
88 for k, v in ipairs(accessors[i]) do
89 constr.getters[v] = function(elem)
90 return elem.c[i][k]
91 end
92 constr.setters[v] = function(elem, v)
93 elem.c[i][k] = v
94 end
95 end
96 end
97 end
98 end
100 function constr:new(...)
101 local obj = fn(...)
102 setmetatable(obj, self)
103 self.__index = function(t, k)
104 if getmetatable(t).getters[k] then
105 return getmetatable(t).getters[k](t)
106 elseif k == "t" then
107 return getmetatable(t)["tag"]
108 else
109 return getmetatable(t)[k]
110 end
111 end
112 self.__newindex = function(t, k, v)
113 if getmetatable(t).setters[k] then
114 getmetatable(t).setters[k](t, v)
115 else
116 rawset(t, k, v)
117 end
118 end
119 return obj
120 end
121 self.constructor = self.constructor or {}
122 self.constructor[tag] = constr
123 return constr
124end
126--- Calls the constructor, creating a new element.
127-- @local
128function Element.__call(t, ...)
129 return t:new(...)
130end
132------------------------------------------------------------------------
133--- Pandoc Document
134-- @section document
136--- A complete pandoc document
137-- @function Doc
138-- @tparam {Block,...} blocks document content
139-- @tparam[opt] Meta meta document meta data
140function M.Doc(blocks, meta)
141 meta = meta or {}
142 return {
143 ["blocks"] = blocks,
144 ["meta"] = meta,
145 ["pandoc-api-version"] = {1,17,0,5},
146 }
147end
150------------------------------------------------------------------------
151-- MetaValue
152-- @section MetaValue
153M.MetaValue = Element:make_subtype{}
154M.MetaValue.__call = function(t, ...)
155 return t:new(...)
156end
157--- Meta blocks
158-- @function MetaBlocks
159-- @tparam {Block,...} blocks blocks
161--- Meta inlines
162-- @function MetaInlines
163-- @tparam {Inline,...} inlines inlines
165--- Meta list
166-- @function MetaList
167-- @tparam {MetaValue,...} meta_values list of meta values
169--- Meta boolean
170-- @function MetaBool
171-- @tparam boolean bool boolean value
173--- Meta map
174-- @function MetaMap
175-- @tparam table a string-index map of meta values
177--- Meta string
178-- @function MetaString
179-- @tparam string str string value
180M.meta_value_types = {
181 "MetaBlocks",
182 "MetaBool",
183 "MetaInlines",
184 "MetaList",
185 "MetaMap",
186 "MetaString"
188for i = 1, #M.meta_value_types do
189 M[M.meta_value_types[i]] = M.MetaValue:create_constructor(
190 M.meta_value_types[i],
191 function(content)
192 return {c = content}
193 end,
194 "content"
195 )
196end
198------------------------------------------------------------------------
199-- Blocks
200-- @section Block
202--- Block elements
203M.Block = Element:make_subtype{}
204M.Block.__call = function (t, ...)
205 return t:new(...)
206end
208--- Creates a block quote element
209-- @function BlockQuote
210-- @tparam {Block,...} content block content
211-- @treturn Block block quote element
212M.BlockQuote = M.Block:create_constructor(
213 "BlockQuote",
214 function(content) return {c = content} end,
215 "content"
218--- Creates a bullet (i.e. unordered) list.
219-- @function BulletList
220-- @tparam {{Block,...},...} content list of items
221-- @treturn Block block quote element
222M.BulletList = M.Block:create_constructor(
223 "BulletList",
224 function(content) return {c = content} end,
225 "content"
228--- Creates a code block element
229-- @function CodeBlock
230-- @tparam string text code string
231-- @tparam[opt] Attributes attributes element attributes
232-- @treturn Block code block element
233M.CodeBlock = M.Block:create_constructor(
234 "CodeBlock",
235 function(text, attributes) return {c = {attributes, text}} end,
236 {{"identifier", "classes", "attributes"}, "text"}
239--- Creates a definition list, containing terms and their explanation.
240-- @function DefinitionList
241-- @tparam {{{Inline,...},{Block,...}},...} content list of items
242-- @treturn Block block quote element
243M.DefinitionList = M.Block:create_constructor(
244 "DefinitionList",
245 function(content) return {c = content} end,
246 "content"
249--- Creates a div element
250-- @function Div
251-- @tparam {Block,...} content block content
252-- @tparam[opt] Attributes attributes element attributes
253-- @treturn Block code block element
254M.Div = M.Block:create_constructor(
255 "Div",
256 function(content, attributes) return {c = {attributes, content}} end,
257 {{"identifier", "classes", "attributes"}, "content"}
260--- Creates a block quote element.
261-- @function Header
262-- @tparam int level header level
263-- @tparam Attributes attributes element attributes
264-- @tparam {Inline,...} content inline content
265-- @treturn Block header element
266M.Header = M.Block:create_constructor(
267 "Header",
268 function(level, attributes, content)
269 return {c = {level, attributes, content}}
270 end,
271 {"level", {"identifier", "classes", "attributes"}, "content"}
274--- Creates a horizontal rule.
275-- @function HorizontalRule
276-- @treturn Block horizontal rule
277M.HorizontalRule = M.Block:create_constructor(
278 "HorizontalRule",
279 function() return {} end
282--- Creates a line block element.
283-- @function LineBlock
284-- @tparam {{Inline,...},...} content inline content
285-- @treturn Block block quote element
286M.LineBlock = M.Block:create_constructor(
287 "LineBlock",
288 function(content) return {c = content} end,
289 "content"
292--- Creates a null element.
293-- @function Null
294-- @treturn Block null element
295M.Null = M.Block:create_constructor(
296 "Null",
297 function() return {} end
300--- Creates an ordered list.
301-- @function OrderedList
302-- @tparam {{Block,...},...} items list items
303-- @param[opt] listAttributes list parameters
304-- @treturn Block
305M.OrderedList = M.Block:create_constructor(
306 "OrderedList",
307 function(items, listAttributes)
308 return {c = {listAttributes,items}}
309 end,
310 {{"start", "style", "delimiter"}, "content"}
313--- Creates a para element.
314-- @function Para
315-- @tparam {Inline,...} content inline content
316-- @treturn Block block quote element
317M.Para = M.Block:create_constructor(
318 "Para",
319 function(content) return {c = content} end,
320 "content"
323--- Creates a plain element.
324-- @function Plain
325-- @tparam {Inline,...} content inline content
326-- @treturn Block block quote element
327M.Plain = M.Block:create_constructor(
328 "Plain",
329 function(content) return {c = content} end,
330 "content"
333--- Creates a raw content block of the specified format.
334-- @function RawBlock
335-- @tparam string format format of content
336-- @tparam string text string content
337-- @treturn Block block quote element
338M.RawBlock = M.Block:create_constructor(
339 "RawBlock",
340 function(format, text) return {c = {format, text}} end,
341 {"format", "text"}
344--- Creates a table element.
345-- @function Table
346-- @tparam {Inline,...} caption table caption
347-- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
348-- @tparam {int,...} widths column widths
349-- @tparam {Block,...} headers header row
350-- @tparam {{Block,...}} rows table rows
351-- @treturn Block block quote element
352M.Table = M.Block:create_constructor(
353 "Table",
354 function(caption, aligns, widths, headers, rows)
355 return {c = {caption, aligns, widths, headers, rows}}
356 end
360------------------------------------------------------------------------
361-- Inline
362-- @section Inline
364--- Inline element class
365M.Inline = Element:make_subtype{}
366M.Inline.__call = function (t, ...)
367 return t:new(...)
368end
370--- Creates a Cite inline element
371-- @function Cite
372-- @tparam {Inline,...} content List of inlines
373-- @tparam {Citation,...} citations List of citations
374-- @treturn Inline citations element
375M.Cite = M.Inline:create_constructor(
376 "Cite",
377 function(content, citations) return {c = {citations, content}} end,
378 {"citations", "content"}
381--- Creates a Code inline element
382-- @function Code
383-- @tparam string text brief image description
384-- @tparam[opt] Attributes attributes additional attributes
385-- @treturn Inline code element
386M.Code = M.Inline:create_constructor(
387 "Code",
388 function(text, attributes) return {c = {attributes, text}} end,
389 {{"identifier", "classes", "attributes"}, "text"}
392--- Creates an inline element representing emphasised text.
393-- @function Emph
394-- @tparam {Inline,..} content inline content
395-- @treturn Inline emphasis element
396M.Emph = M.Inline:create_constructor(
397 "Emph",
398 function(content) return {c = content} end,
399 "content"
402--- Creates a Image inline element
403-- @function Image
404-- @tparam {Inline,..} caption text used to describe the image
405-- @tparam string src path to the image file
406-- @tparam[opt] string title brief image description
407-- @tparam[opt] Attributes attributes additional attributes
408-- @treturn Inline image element
409M.Image = M.Inline:create_constructor(
410 "Image",
411 function(caption, src, title, attributes)
412 title = title or ""
413 attributes = attributes or Attribute.empty
414 return {c = {attributes, caption, {src, title}}}
415 end,
416 {"attributes", "caption", {"src", "title"}}
419--- Create a LineBreak inline element
420-- @function LineBreak
421-- @treturn Inline linebreak element
422M.LineBreak = M.Inline:create_constructor(
423 "LineBreak",
424 function() return {} end
427--- Creates a link inline element, usually a hyperlink.
428-- @function Link
429-- @tparam {Inline,..} content text for this link
430-- @tparam string target the link target
431-- @tparam[opt] string title brief link description
432-- @tparam[opt] Attributes attributes additional attributes
433-- @treturn Inline image element
434M.Link = M.Inline:create_constructor(
435 "Link",
436 function(content, target, title, attributes)
437 title = title or ""
438 attributes = attributes or Attribute.empty
439 return {c = {attributes, content, {target, title}}}
440 end,
441 {"attributes", "content", {"target", "title"}}
444--- Creates a Math element, either inline or displayed. It is usually simpler to
445-- use one of the specialized functions @{InlineMath} or @{DisplayMath} instead.
446-- @function Math
447-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
448-- @tparam string text Math content
449-- @treturn Inline Math element
450M.Math = M.Inline:create_constructor(
451 "Math",
452 function(mathtype, text)
453 return {c = {mathtype, text}}
454 end,
455 {"mathtype", "text"}
457--- Creates a DisplayMath element.
458-- @function DisplayMath
459-- @tparam string text Math content
460-- @treturn Inline Math element
461M.DisplayMath = M.Inline:create_constructor(
462 "DisplayMath",
463 function(text) return M.Math("DisplayMath", text) end,
464 {"mathtype", "text"}
466--- Creates an InlineMath inline element.
467-- @function InlineMath
468-- @tparam string text Math content
469-- @treturn Inline Math element
470M.InlineMath = M.Inline:create_constructor(
471 "InlineMath",
472 function(text) return M.Math("InlineMath", text) end,
473 {"mathtype", "text"}
476--- Creates a Note inline element
477-- @function Note
478-- @tparam {Block,...} content footnote block content
479M.Note = M.Inline:create_constructor(
480 "Note",
481 function(content) return {c = content} end,
482 "content"
485--- Creates a Quoted inline element given the quote type and quoted content. It
486-- is usually simpler to use one of the specialized functions @{SingleQuoted} or
487-- @{DoubleQuoted} instead.
488-- @function Quoted
489-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
490-- @tparam {Inline,..} content inline content
491-- @treturn Inline quoted element
492M.Quoted = M.Inline:create_constructor(
493 "Quoted",
494 function(quotetype, content) return {c = {quotetype, content}} end,
495 {"quotetype", "content"}
497--- Creates a single-quoted inline element.
498-- @function SingleQuoted
499-- @tparam {Inline,..} content inline content
500-- @treturn Inline quoted element
501-- @see Quoted
502M.SingleQuoted = M.Inline:create_constructor(
503 "SingleQuoted",
504 function(content) return M.Quoted(M.SingleQuote, content) end,
505 {"quotetype", "content"}
507--- Creates a single-quoted inline element.
508-- @function DoubleQuoted
509-- @tparam {Inline,..} content inline content
510-- @treturn Inline quoted element
511-- @see Quoted
512M.DoubleQuoted = M.Inline:create_constructor(
513 "DoubleQuoted",
514 function(content) return M.Quoted("DoubleQuote", content) end,
515 {"quotetype", "content"}
518--- Creates a RawInline inline element
519-- @function RawInline
520-- @tparam string format format of the contents
521-- @tparam string text string content
522-- @treturn Inline raw inline element
523M.RawInline = M.Inline:create_constructor(
524 "RawInline",
525 function(format, text) return {c = {format, text}} end,
526 {"format", "text"}
529--- Creates text rendered in small caps
530-- @function SmallCaps
531-- @tparam {Inline,..} content inline content
532-- @treturn Inline smallcaps element
533M.SmallCaps = M.Inline:create_constructor(
534 "SmallCaps",
535 function(content) return {c = content} end,
536 "content"
539--- Creates a SoftBreak inline element.
540-- @function SoftBreak
541-- @treturn Inline softbreak element
542M.SoftBreak = M.Inline:create_constructor(
543 "SoftBreak",
544 function() return {} end
547--- Create a Space inline element
548-- @function Space
549-- @treturn Inline space element
550M.Space = M.Inline:create_constructor(
551 "Space",
552 function() return {} end
555--- Creates a Span inline element
556-- @function Span
557-- @tparam {Inline,..} content inline content
558-- @tparam[opt] Attributes attributes additional attributes
559-- @treturn Inline span element
560M.Span = M.Inline:create_constructor(
561 "Span",
562 function(content, attributes) return {c = {attributes, content}} end,
563 {{"identifier", "classes", "attributes"}, "content"}
566--- Creates a Str inline element
567-- @function Str
568-- @tparam string text content
569-- @treturn Inline string element
570M.Str = M.Inline:create_constructor(
571 "Str",
572 function(text) return {c = text} end,
573 "text"
576--- Creates text which is striked out.
577-- @function Strikeout
578-- @tparam {Inline,..} content inline content
579-- @treturn Inline strikeout element
580M.Strikeout = M.Inline:create_constructor(
581 "Strikeout",
582 function(content) return {c = content} end,
583 "content"
586--- Creates a Strong element, whose text is usually displayed in a bold font.
587-- @function Strong
588-- @tparam {Inline,..} content inline content
589-- @treturn Inline strong element
590M.Strong = M.Inline:create_constructor(
591 "Strong",
592 function(content) return {c = content} end,
593 "content"
596--- Creates a Subscript inline element
597-- @function Subscript
598-- @tparam {Inline,..} content inline content
599-- @treturn Inline subscript element
600M.Subscript = M.Inline:create_constructor(
601 "Subscript",
602 function(content) return {c = content} end,
603 "content"
606--- Creates a Superscript inline element
607-- @function Superscript
608-- @tparam {Inline,..} content inline content
609-- @treturn Inline strong element
610M.Superscript = M.Inline:create_constructor(
611 "Superscript",
612 function(content) return {c = content} end,
613 "content"
617------------------------------------------------------------------------
618-- Helpers
619-- @section helpers
621-- Attributes
622M.Attributes = {}
623--- Create a new set of attributes (Attr).
624-- @function Attributes
625-- @tparam table key_values table containing string keys and values
626-- @tparam[opt] string id element identifier
627-- @tparam[opt] {string,...} classes element classes
628-- @return element attributes
629M.Attributes.__call = function(t, key_values, id, classes)
630 id = id or ''
631 classes = classes or {}
632 local attr = {id, classes, key_values}
633 setmetatable(attr, t)
634 return attr
635end
636M.Attributes.__index = function(t, k)
637 if rawget(t, k) then
638 return rawget(t, k)
639 elseif k == "id" then
640 if rawget(t, 1) == '' then
641 return nil
642 else
643 return rawget(t, 1)
644 end
645 elseif k == "class" then
646 if #(rawget(t, 2)) == 0 then
647 return nil
648 else
649 return table.concat(t[2], ' ')
650 end
651 else
652 for _, p in ipairs(t[3]) do
653 if k == p[1] then
654 return p[2]
655 end
656 end
657 return nil
658 end
659end
660M.Attributes.__newindex = function(t, k, v)
661 if rawget(t, k) then
662 rawset(t, k, v)
663 elseif k == "id" then
664 rawset(t, 1, v)
665 elseif k == "class" then
666 if type(v) == "string" then
667 rawset(t, 2, {v})
668 else
669 rawset(t, 2, v)
670 end
671 else
672 for _, p in ipairs(rawget(t, 3)) do
673 if k == p[1] then
674 p[2] = v
675 return
676 end
677 end
678 kv = rawget(t, 3)
679 kv[#kv + 1] = {k, v}
680 rawset(t, 3, kv)
681 end
682end
683setmetatable(M.Attributes, M.Attributes)
686--- Creates a single citation.
687-- @function Citation
688-- @tparam string id citation identifier (like a bibtex key)
689-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
690-- @tparam[opt] {Inline,...} prefix citation prefix
691-- @tparam[opt] {Inline,...} suffix citation suffix
692-- @tparam[opt] int note_num note number
693-- @tparam[opt] int note_num hash number
694M.Citation = function(id, mode, prefix, suffix, note_num, hash)
695 prefix = prefix or {}
696 suffix = suffix or {}
697 note_num = note_num or 0
698 hash = hash or 0
699 return {
700 citationId = id,
701 citationPrefix = prefix,
702 citationSuffix = suffix,
703 citationMode = mode,
704 citationNoteNum = note_num,
705 citationHash = hash,
706 }
707end
710------------------------------------------------------------------------
711-- Constants
712-- @section constants
714--- Author name is mentioned in the text.
715-- @see Citation
716-- @see Cite
717M.AuthorInText = "AuthorInText"
719--- Author name is suppressed.
720-- @see Citation
721-- @see Cite
722M.SuppressAuthor = "SuppressAuthor"
724--- Default citation style is used.
725-- @see Citation
726-- @see Cite
727M.NormalCitation = "NormalCitation"
729--- Table cells aligned left.
730-- @see Table
731M.AlignLeft = "AlignLeft"
733--- Table cells right-aligned.
734-- @see Table
735M.AlignRight = "AlignRight"
737--- Table cell content is centered.
738-- @see Table
739M.AlignCenter = "AlignCenter"
741--- Table cells are alignment is unaltered.
742-- @see Table
743M.AlignDefault = "AlignDefault"
745--- Default list number delimiters are used.
746-- @see OrderedList
747M.DefaultDelim = "DefaultDelim"
749--- List numbers are delimited by a period.
750-- @see OrderedList
751M.Period = "Period"
753--- List numbers are delimited by a single parenthesis.
754-- @see OrderedList
755M.OneParen = "OneParen"
757--- List numbers are delimited by a double parentheses.
758-- @see OrderedList
759M.TwoParens = "TwoParens"
761--- List are numbered in the default style
762-- @see OrderedList
763M.DefaultStyle = "DefaultStyle"
765--- List items are numbered as examples.
766-- @see OrderedList
767M.Example = "Example"
769--- List are numbered using decimal integers.
770-- @see OrderedList
771M.Decimal = "Decimal"
773--- List are numbered using lower-case roman numerals.
774-- @see OrderedList
775M.LowerRoman = "LowerRoman"
777--- List are numbered using upper-case roman numerals
778-- @see OrderedList
779M.UpperRoman = "UpperRoman"
781--- List are numbered using lower-case alphabetic characters.
782-- @see OrderedList
783M.LowerAlpha = "LowerAlpha"
785--- List are numbered using upper-case alphabetic characters.
786-- @see OrderedList
787M.UpperAlpha = "UpperAlpha"
790------------------------------------------------------------------------
791-- Helper Functions
792-- @section helpers
794--- Use functions defined in the global namespace to create a pandoc filter.
795-- All globally defined functions which have names of pandoc elements are
796-- collected into a new table.
797-- @return A list of filter functions
798-- @usage
799-- -- within a file defining a pandoc filter:
800-- function Str(text)
801-- return pandoc.Str(utf8.upper(text))
802-- end
803--
804-- return {pandoc.global_filter()}
805-- -- the above is equivallent to
806-- -- return {{Str = Str}}
807function M.global_filter()
808 local res = {}
809 for k, v in pairs(_G) do
810 if M.Inline.constructor[k] or M.Block.constructor[k] or M.Block.constructors[k] or k == "Doc" then
811 res[k] = v
812 end
813 end
814 return res
815end
817return M