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
20-- Lua functions for pandoc scripts.
22-- @author Albert Krewinkel
23-- @copyright © 2017 Albert Krewinkel
29local List = require 'pandoc.List'
31------------------------------------------------------------------------
32-- The base class for pandoc's AST elements.
37--- Create a new element subtype
39function Element:make_subtype(o)
46--- Create a new element given its tag and arguments
48function Element:new(tag, ...)
49 local element = { t = tag }
51 -- special case for unary constructors
53 element.c = content[1]
54 -- Don't set 'c' field if no further arguments were given. This is important
55 -- for nullary constructors like `Space` and `HorizontalRule`.
56 elseif #content > 0 then
59 setmetatable(element, self)
64--- Create a new constructor
66-- @param tag Tag used to identify the constructor
67-- @param fn Function to be called when constructing a new element
68-- @param accessors names to use as accessors for numerical fields
69-- @return function that constructs a new element
70function Element:create_constructor(tag, fn, accessors)
71 local constr = self:make_subtype({tag = tag, getters = {}, setters = {}})
73 -- Add accessors to the metatable
74 if type(accessors) == "string" then
75 constr.getters[accessors] = function(elem)
78 constr.setters[accessors] = function(elem, v)
82 for i = 1, #(accessors or {}) do
83 if type(accessors[i]) == "string" then
84 constr.getters[accessors[i]] = function(elem)
87 constr.setters[accessors[i]] = function(elem, v)
90 else -- only two levels of nesting are supported
91 for k, v in ipairs(accessors[i]) do
92 constr.getters[v] = function(elem)
95 constr.setters[v] = function(elem, v)
103 function constr:new(...)
105 setmetatable(obj, self)
106 self.__index = function(t, k)
107 if getmetatable(t).getters[k] then
108 return getmetatable(t).getters[k](t)
110 return getmetatable(t)["tag"]
112 return getmetatable(t)[k]
115 self.__newindex = function(t, k, v)
116 if getmetatable(t).setters[k] then
117 getmetatable(t).setters[k](t, v)
124 self.constructor = self.constructor or {}
125 self.constructor[tag] = constr
129--- Calls the constructor, creating a new element.
131function Element.__call(t, ...)
135------------------------------------------------------------------------
139--- A complete pandoc document
141-- @tparam {Block,...} blocks document content
142-- @tparam[opt] Meta meta document meta data
143function M.Pandoc(blocks, meta)
146 ["blocks"] = List:new(blocks),
148 ["pandoc-api-version"] = {1,17,0,5},
152-- DEPRECATED synonym:
155------------------------------------------------------------------------
159--- Create a new Meta object. It sets the metatable of the given table to
162-- @tparam meta table table containing document meta information
164M.Meta.__call = function(t, meta)
165 return setmetatable(meta, self)
167setmetatable(M.Meta, M.Meta)
170------------------------------------------------------------------------
173M.MetaValue = Element:make_subtype{}
174M.MetaValue.__call = function(t, ...)
178-- @function MetaBlocks
179-- @tparam {Block,...} blocks blocks
182-- @function MetaInlines
183-- @tparam {Inline,...} inlines inlines
187-- @tparam {MetaValue,...} meta_values list of meta values
188M.meta_value_list_types = {
193for i = 1, #M.meta_value_list_types do
194 M[M.meta_value_list_types[i]] = M.MetaValue:create_constructor(
195 M.meta_value_list_types[i],
197 return List:new(content)
204-- @tparam table key_value_map a string-indexed map of meta values
205M.MetaValue:create_constructor("MetaMap", function (mm) return mm end)
207--- Creates string to be used in meta data.
208-- Does nothing, lua strings are meta strings.
209-- @function MetaString
210-- @tparam string str string value
211function M.MetaString(str)
215--- Creates boolean to be used in meta data.
216-- Does nothing, lua booleans are meta booleans.
218-- @tparam boolean bool boolean value
219function M.MetaBool(bool)
223------------------------------------------------------------------------
228M.Block = Element:make_subtype{}
229M.Block.__call = function (t, ...)
233--- Creates a block quote element
234-- @function BlockQuote
235-- @tparam {Block,...} content block content
236-- @treturn Block block quote element
237M.BlockQuote = M.Block:create_constructor(
239 function(content) return {c = content} end,
243--- Creates a bullet (i.e. unordered) list.
244-- @function BulletList
245-- @tparam {{Block,...},...} content list of items
246-- @treturn Block block quote element
247M.BulletList = M.Block:create_constructor(
249 function(content) return {c = content} end,
253--- Creates a code block element
254-- @function CodeBlock
255-- @tparam string text code string
256-- @tparam[opt] Attr attr element attributes
257-- @treturn Block code block element
258M.CodeBlock = M.Block:create_constructor(
260 function(text, attr) return {c = {attr or M.Attr(), text}} end,
261 {{"identifier", "classes", "attributes"}, "text"}
264--- Creates a definition list, containing terms and their explanation.
265-- @function DefinitionList
266-- @tparam {{{Inline,...},{Block,...}},...} content list of items
267-- @treturn Block block quote element
268M.DefinitionList = M.Block:create_constructor(
270 function(content) return {c = List:new(content)} end,
274--- Creates a div element
276-- @tparam {Block,...} content block content
277-- @tparam[opt] Attr attr element attributes
278-- @treturn Block code block element
279M.Div = M.Block:create_constructor(
281 function(content, attr)
282 return {c = {attr or M.Attr(), List:new(content)}}
284 {{"identifier", "classes", "attributes"}, "content"}
287--- Creates a block quote element.
289-- @tparam int level header level
290-- @tparam {Inline,...} content inline content
291-- @tparam[opt] Attr attr element attributes
292-- @treturn Block header element
293M.Header = M.Block:create_constructor(
295 function(level, content, attr)
296 return {c = {level, attr or M.Attr(), content}}
298 {"level", {"identifier", "classes", "attributes"}, "content"}
301--- Creates a horizontal rule.
302-- @function HorizontalRule
303-- @treturn Block horizontal rule
304M.HorizontalRule = M.Block:create_constructor(
306 function() return {} end
309--- Creates a line block element.
310-- @function LineBlock
311-- @tparam {{Inline,...},...} content inline content
312-- @treturn Block block quote element
313M.LineBlock = M.Block:create_constructor(
315 function(content) return {c = List:new(content)} end,
319--- Creates a null element.
321-- @treturn Block null element
322M.Null = M.Block:create_constructor(
324 function() return {} end
327--- Creates an ordered list.
328-- @function OrderedList
329-- @tparam {{Block,...},...} items list items
330-- @param[opt] listAttributes list parameters
332M.OrderedList = M.Block:create_constructor(
334 function(items, listAttributes)
335 listAttributes = listAttributes or {1, M.DefaultStyle, M.DefaultDelim}
336 return {c = {listAttributes, List:new(items)}}
338 {{"start", "style", "delimiter"}, "content"}
341--- Creates a para element.
343-- @tparam {Inline,...} content inline content
344-- @treturn Block block quote element
345M.Para = M.Block:create_constructor(
347 function(content) return {c = List:new(content)} end,
351--- Creates a plain element.
353-- @tparam {Inline,...} content inline content
354-- @treturn Block block quote element
355M.Plain = M.Block:create_constructor(
357 function(content) return {c = List:new(content)} end,
361--- Creates a raw content block of the specified format.
363-- @tparam string format format of content
364-- @tparam string text string content
365-- @treturn Block block quote element
366M.RawBlock = M.Block:create_constructor(
368 function(format, text) return {c = {format, text}} end,
372--- Creates a table element.
374-- @tparam {Inline,...} caption table caption
375-- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
376-- @tparam {int,...} widths column widths
377-- @tparam {Block,...} headers header row
378-- @tparam {{Block,...}} rows table rows
379-- @treturn Block block quote element
380M.Table = M.Block:create_constructor(
382 function(caption, aligns, widths, headers, rows)
393 {"caption", "aligns", "widths", "headers", "rows"}
397------------------------------------------------------------------------
401--- Inline element class
402M.Inline = Element:make_subtype{}
403M.Inline.__call = function (t, ...)
407--- Creates a Cite inline element
409-- @tparam {Inline,...} content List of inlines
410-- @tparam {Citation,...} citations List of citations
411-- @treturn Inline citations element
412M.Cite = M.Inline:create_constructor(
414 function(content, citations)
415 return {c = {List:new(citations), List:new(content)}}
417 {"citations", "content"}
420--- Creates a Code inline element
422-- @tparam string text brief image description
423-- @tparam[opt] Attr attr additional attributes
424-- @treturn Inline code element
425M.Code = M.Inline:create_constructor(
427 function(text, attr) return {c = {attr or M.Attr(), text}} end,
428 {{"identifier", "classes", "attributes"}, "text"}
431--- Creates an inline element representing emphasised text.
433-- @tparam {Inline,..} content inline content
434-- @treturn Inline emphasis element
435M.Emph = M.Inline:create_constructor(
437 function(content) return {c = List:new(content)} end,
441--- Creates a Image inline element
443-- @tparam {Inline,..} caption text used to describe the image
444-- @tparam string src path to the image file
445-- @tparam[opt] string title brief image description
446-- @tparam[opt] Attr attr additional attributes
447-- @treturn Inline image element
448M.Image = M.Inline:create_constructor(
450 function(caption, src, title, attr)
452 attr = attr or M.Attr()
453 return {c = {attr, List:new(caption), {src, title}}}
455 {{"identifier", "classes", "attributes"}, "caption", {"src", "title"}}
458--- Create a LineBreak inline element
459-- @function LineBreak
460-- @treturn Inline linebreak element
461M.LineBreak = M.Inline:create_constructor(
463 function() return {} end
466--- Creates a link inline element, usually a hyperlink.
468-- @tparam {Inline,..} content text for this link
469-- @tparam string target the link target
470-- @tparam[opt] string title brief link description
471-- @tparam[opt] Attr attr additional attributes
472-- @treturn Inline image element
473M.Link = M.Inline:create_constructor(
475 function(content, target, title, attr)
477 attr = attr or M.Attr()
478 return {c = {attr, List:new(content), {target, title}}}
480 {{"identifier", "classes", "attributes"}, "content", {"target", "title"}}
483--- Creates a Math element, either inline or displayed.
485-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
486-- @tparam string text Math content
487-- @treturn Inline Math element
488M.Math = M.Inline:create_constructor(
490 function(mathtype, text)
491 return {c = {mathtype, text}}
495--- Creates a DisplayMath element (DEPRECATED).
496-- @function DisplayMath
497-- @tparam string text Math content
498-- @treturn Inline Math element
499M.DisplayMath = M.Inline:create_constructor(
501 function(text) return M.Math("DisplayMath", text) end,
504--- Creates an InlineMath inline element (DEPRECATED).
505-- @function InlineMath
506-- @tparam string text Math content
507-- @treturn Inline Math element
508M.InlineMath = M.Inline:create_constructor(
510 function(text) return M.Math("InlineMath", text) end,
514--- Creates a Note inline element
516-- @tparam {Block,...} content footnote block content
517M.Note = M.Inline:create_constructor(
519 function(content) return {c = List:new(content)} end,
523--- Creates a Quoted inline element given the quote type and quoted content.
525-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
526-- @tparam {Inline,..} content inline content
527-- @treturn Inline quoted element
528M.Quoted = M.Inline:create_constructor(
530 function(quotetype, content) return {c = {quotetype, List:new(content)}} end,
531 {"quotetype", "content"}
533--- Creates a single-quoted inline element (DEPRECATED).
534-- @function SingleQuoted
535-- @tparam {Inline,..} content inline content
536-- @treturn Inline quoted element
538M.SingleQuoted = M.Inline:create_constructor(
540 function(content) return M.Quoted(M.SingleQuote, content) end,
541 {"quotetype", "content"}
543--- Creates a single-quoted inline element (DEPRECATED).
544-- @function DoubleQuoted
545-- @tparam {Inline,..} content inline content
546-- @treturn Inline quoted element
548M.DoubleQuoted = M.Inline:create_constructor(
550 function(content) return M.Quoted("DoubleQuote", content) end,
551 {"quotetype", "content"}
554--- Creates a RawInline inline element
555-- @function RawInline
556-- @tparam string format format of the contents
557-- @tparam string text string content
558-- @treturn Inline raw inline element
559M.RawInline = M.Inline:create_constructor(
561 function(format, text) return {c = {format, text}} end,
565--- Creates text rendered in small caps
566-- @function SmallCaps
567-- @tparam {Inline,..} content inline content
568-- @treturn Inline smallcaps element
569M.SmallCaps = M.Inline:create_constructor(
571 function(content) return {c = List:new(content)} end,
575--- Creates a SoftBreak inline element.
576-- @function SoftBreak
577-- @treturn Inline softbreak element
578M.SoftBreak = M.Inline:create_constructor(
580 function() return {} end
583--- Create a Space inline element
585-- @treturn Inline space element
586M.Space = M.Inline:create_constructor(
588 function() return {} end
591--- Creates a Span inline element
593-- @tparam {Inline,..} content inline content
594-- @tparam[opt] Attr attr additional attributes
595-- @treturn Inline span element
596M.Span = M.Inline:create_constructor(
598 function(content, attr)
599 return {c = {attr or M.Attr(), List:new(content)}}
601 {{"identifier", "classes", "attributes"}, "content"}
604--- Creates a Str inline element
606-- @tparam string text content
607-- @treturn Inline string element
608M.Str = M.Inline:create_constructor(
610 function(text) return {c = text} end,
614--- Creates text which is striked out.
615-- @function Strikeout
616-- @tparam {Inline,..} content inline content
617-- @treturn Inline strikeout element
618M.Strikeout = M.Inline:create_constructor(
620 function(content) return {c = List:new(content)} end,
624--- Creates a Strong element, whose text is usually displayed in a bold font.
626-- @tparam {Inline,..} content inline content
627-- @treturn Inline strong element
628M.Strong = M.Inline:create_constructor(
630 function(content) return {c = List:new(content)} end,
634--- Creates a Subscript inline element
635-- @function Subscript
636-- @tparam {Inline,..} content inline content
637-- @treturn Inline subscript element
638M.Subscript = M.Inline:create_constructor(
640 function(content) return {c = List:new(content)} end,
644--- Creates a Superscript inline element
645-- @function Superscript
646-- @tparam {Inline,..} content inline content
647-- @treturn Inline strong element
648M.Superscript = M.Inline:create_constructor(
650 function(content) return {c = List:new(content)} end,
655------------------------------------------------------------------------
659local function assoc_key_equals (x)
660 return function (y) return y[1] == x end
663-- Lookup a value in an associative list
665-- @tparam {{key, value},...} alist associative list
666-- @param key key for which the associated value is to be looked up
667local function lookup(alist, key)
668 return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
671--- Return an iterator which returns key-value pairs of an associative list.
673-- @tparam {{key, value},...} alist associative list
674local apairs = function (alist)
678 cur = rawget(alist, i)
681 return cur[1], cur[2]
688-- AttributeList, a metatable to allow table-like access to attribute lists
689-- represented by associative lists.
690local AttributeList = {
691 __index = function (t, k)
692 if type(k) == "number" then
699 __newindex = function (t, k, v)
700 local cur, idx = List.find_if(t, assoc_key_equals(k))
705 elseif type(k) == "number" then
708 rawset(t, #t + 1, {k, v})
715-- convert a table to an associative list. The order of key-value pairs in the
716-- alist is undefined. The table should either contain no numeric keys or
717-- already be an associative list.
718-- @tparam table associative list or table without numeric keys.
719-- @treturn table associative list
720local to_alist = function (tbl)
721 if #tbl ~= 0 or next(tbl) == nil then
722 -- probably already an alist
727 for k, v in pairs(tbl) do
736M.Attr._field_names = {identifier = 1, classes = 2, attributes = 3}
737--- Create a new set of attributes (Attr).
739-- @tparam[opt] string identifier element identifier
740-- @tparam[opt] {string,...} classes element classes
741-- @tparam[opt] table attributes table containing string keys and values
742-- @return element attributes
743M.Attr.__call = function(t, identifier, classes, attributes)
744 identifier = identifier or ''
745 classes = List:new(classes or {})
746 attributes = setmetatable(to_alist(attributes or {}), AttributeList)
747 local attr = {identifier, classes, attributes}
748 setmetatable(attr, t)
751M.Attr.__index = function(t, k)
752 return rawget(t, k) or
753 rawget(t, M.Attr._field_names[k]) or
754 rawget(getmetatable(t), k)
756M.Attr.__newindex = function(t, k, v)
757 if M.Attr._field_names[k] then
758 rawset(t, M.Attr._field_names[k], v)
763setmetatable(M.Attr, M.Attr)
766--- Creates a single citation.
768-- @tparam string id citation identifier (like a bibtex key)
769-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
770-- @tparam[opt] {Inline,...} prefix citation prefix
771-- @tparam[opt] {Inline,...} suffix citation suffix
772-- @tparam[opt] int note_num note number
773-- @tparam[opt] int hash hash number
774M.Citation = function(id, mode, prefix, suffix, note_num, hash)
775 prefix = prefix or {}
776 suffix = suffix or {}
777 note_num = note_num or 0
781 citationPrefix = prefix,
782 citationSuffix = suffix,
784 citationNoteNum = note_num,
790------------------------------------------------------------------------
794--- Author name is mentioned in the text.
797M.AuthorInText = "AuthorInText"
799--- Author name is suppressed.
802M.SuppressAuthor = "SuppressAuthor"
804--- Default citation style is used.
807M.NormalCitation = "NormalCitation"
809--- Table cells aligned left.
811M.AlignLeft = "AlignLeft"
813--- Table cells right-aligned.
815M.AlignRight = "AlignRight"
817--- Table cell content is centered.
819M.AlignCenter = "AlignCenter"
821--- Table cells are alignment is unaltered.
823M.AlignDefault = "AlignDefault"
825--- Default list number delimiters are used.
827M.DefaultDelim = "DefaultDelim"
829--- List numbers are delimited by a period.
833--- List numbers are delimited by a single parenthesis.
835M.OneParen = "OneParen"
837--- List numbers are delimited by a double parentheses.
839M.TwoParens = "TwoParens"
841--- List are numbered in the default style
843M.DefaultStyle = "DefaultStyle"
845--- List items are numbered as examples.
849--- List are numbered using decimal integers.
853--- List are numbered using lower-case roman numerals.
855M.LowerRoman = "LowerRoman"
857--- List are numbered using upper-case roman numerals
859M.UpperRoman = "UpperRoman"
861--- List are numbered using lower-case alphabetic characters.
863M.LowerAlpha = "LowerAlpha"
865--- List are numbered using upper-case alphabetic characters.
867M.UpperAlpha = "UpperAlpha"
870------------------------------------------------------------------------
874--- Parse the given string into a Pandoc document.
875-- The method used to interpret input is specified by *format*. Acceptable
876-- values for this parameter are equal to those that can be given to the
877-- `--from` command line option.
878-- @tparam string markup the markup to be parsed
879-- @tparam[opt] string format format specification, defaults to "markdown".
880-- @treturn Pandoc pandoc document
882-- local org_markup = "/emphasis/" -- Input to be read
883-- local document = pandoc.read(org_markup, "org")
884-- -- Get the first block of the document
885-- local block = document.blocks[1]
886-- -- The inline element in that block is an `Emph`
887-- assert(block.content[1].t == "Emph")
888function M.read(markup, format)
889 format = format or "markdown"
890 local pd = pandoc._read(format, markup)
891 if type(pd) == "string" then
898--- Runs command with arguments, passing it some input, and returns the output.
899-- @treturn string Output of command.
900-- @raise A table containing the keys `command`, `error_code`, and `output` is
901-- thrown if the command exits with a non-zero error code.
903-- local ec, output = pandoc.pipe("sed", {"-e","s/a/b/"}, "abc")
904function M.pipe (command, args, input)
905 local ec, output = pandoc._pipe(command, args, input)
908 { command = command, error_code = ec, output = output},
909 { __tostring = function(e)
910 return "Error running " .. e.command
911 .. " (error code " .. e.error_code .. "): "
921--- Use functions defined in the global namespace to create a pandoc filter.
922-- All globally defined functions which have names of pandoc elements are
923-- collected into a new table.
924-- @return A list of filter functions
926-- -- within a file defining a pandoc filter:
928-- return pandoc.Str(utf8.upper(text))
931-- return {pandoc.global_filter()}
932-- -- the above is equivallent to
933-- -- return {{Str = Str}}
934function M.global_filter()
936 function is_filter_function(k)
937 return M.Inline.constructor[k] or
938 M.Block.constructor[k] or
939 k == "Meta" or k == "Doc" or k == "Pandoc" or
940 k == "Block" or k == "Inline"
942 for k, v in pairs(_G) do
943 if is_filter_function(k) then
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list