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, t)
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.MetaMap = M.MetaValue:create_constructor(
207 function (mm) return mm end
210--- Creates string to be used in meta data.
211-- Does nothing, lua strings are meta strings.
212-- @function MetaString
213-- @tparam string str string value
214function M.MetaString(str)
218--- Creates boolean to be used in meta data.
219-- Does nothing, lua booleans are meta booleans.
221-- @tparam boolean bool boolean value
222function M.MetaBool(bool)
226------------------------------------------------------------------------
231M.Block = Element:make_subtype{}
232M.Block.__call = function (t, ...)
236--- Creates a block quote element
237-- @function BlockQuote
238-- @tparam {Block,...} content block content
239-- @treturn Block block quote element
240M.BlockQuote = M.Block:create_constructor(
242 function(content) return {c = content} end,
246--- Creates a bullet (i.e. unordered) list.
247-- @function BulletList
248-- @tparam {{Block,...},...} content list of items
249-- @treturn Block block quote element
250M.BulletList = M.Block:create_constructor(
252 function(content) return {c = content} end,
256--- Creates a code block element
257-- @function CodeBlock
258-- @tparam string text code string
259-- @tparam[opt] Attr attr element attributes
260-- @treturn Block code block element
261M.CodeBlock = M.Block:create_constructor(
263 function(text, attr) return {c = {attr or M.Attr(), text}} end,
264 {{"identifier", "classes", "attributes"}, "text"}
267--- Creates a definition list, containing terms and their explanation.
268-- @function DefinitionList
269-- @tparam {{{Inline,...},{Block,...}},...} content list of items
270-- @treturn Block block quote element
271M.DefinitionList = M.Block:create_constructor(
273 function(content) return {c = List:new(content)} end,
277--- Creates a div element
279-- @tparam {Block,...} content block content
280-- @tparam[opt] Attr attr element attributes
281-- @treturn Block code block element
282M.Div = M.Block:create_constructor(
284 function(content, attr)
285 return {c = {attr or M.Attr(), List:new(content)}}
287 {{"identifier", "classes", "attributes"}, "content"}
290--- Creates a block quote element.
292-- @tparam int level header level
293-- @tparam {Inline,...} content inline content
294-- @tparam[opt] Attr attr element attributes
295-- @treturn Block header element
296M.Header = M.Block:create_constructor(
298 function(level, content, attr)
299 return {c = {level, attr or M.Attr(), content}}
301 {"level", {"identifier", "classes", "attributes"}, "content"}
304--- Creates a horizontal rule.
305-- @function HorizontalRule
306-- @treturn Block horizontal rule
307M.HorizontalRule = M.Block:create_constructor(
309 function() return {} end
312--- Creates a line block element.
313-- @function LineBlock
314-- @tparam {{Inline,...},...} content inline content
315-- @treturn Block block quote element
316M.LineBlock = M.Block:create_constructor(
318 function(content) return {c = List:new(content)} end,
322--- Creates a null element.
324-- @treturn Block null element
325M.Null = M.Block:create_constructor(
327 function() return {} end
330--- Creates an ordered list.
331-- @function OrderedList
332-- @tparam {{Block,...},...} items list items
333-- @param[opt] listAttributes list parameters
335M.OrderedList = M.Block:create_constructor(
337 function(items, listAttributes)
338 listAttributes = listAttributes or {1, M.DefaultStyle, M.DefaultDelim}
339 return {c = {listAttributes, List:new(items)}}
341 {{"start", "style", "delimiter"}, "content"}
344--- Creates a para element.
346-- @tparam {Inline,...} content inline content
347-- @treturn Block block quote element
348M.Para = M.Block:create_constructor(
350 function(content) return {c = List:new(content)} end,
354--- Creates a plain element.
356-- @tparam {Inline,...} content inline content
357-- @treturn Block block quote element
358M.Plain = M.Block:create_constructor(
360 function(content) return {c = List:new(content)} end,
364--- Creates a raw content block of the specified format.
366-- @tparam string format format of content
367-- @tparam string text string content
368-- @treturn Block block quote element
369M.RawBlock = M.Block:create_constructor(
371 function(format, text) return {c = {format, text}} end,
375--- Creates a table element.
377-- @tparam {Inline,...} caption table caption
378-- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
379-- @tparam {int,...} widths column widths
380-- @tparam {Block,...} headers header row
381-- @tparam {{Block,...}} rows table rows
382-- @treturn Block block quote element
383M.Table = M.Block:create_constructor(
385 function(caption, aligns, widths, headers, rows)
396 {"caption", "aligns", "widths", "headers", "rows"}
400------------------------------------------------------------------------
404--- Inline element class
405M.Inline = Element:make_subtype{}
406M.Inline.__call = function (t, ...)
410--- Creates a Cite inline element
412-- @tparam {Inline,...} content List of inlines
413-- @tparam {Citation,...} citations List of citations
414-- @treturn Inline citations element
415M.Cite = M.Inline:create_constructor(
417 function(content, citations)
418 return {c = {List:new(citations), List:new(content)}}
420 {"citations", "content"}
423--- Creates a Code inline element
425-- @tparam string text brief image description
426-- @tparam[opt] Attr attr additional attributes
427-- @treturn Inline code element
428M.Code = M.Inline:create_constructor(
430 function(text, attr) return {c = {attr or M.Attr(), text}} end,
431 {{"identifier", "classes", "attributes"}, "text"}
434--- Creates an inline element representing emphasised text.
436-- @tparam {Inline,..} content inline content
437-- @treturn Inline emphasis element
438M.Emph = M.Inline:create_constructor(
440 function(content) return {c = List:new(content)} end,
444--- Creates a Image inline element
446-- @tparam {Inline,..} caption text used to describe the image
447-- @tparam string src path to the image file
448-- @tparam[opt] string title brief image description
449-- @tparam[opt] Attr attr additional attributes
450-- @treturn Inline image element
451M.Image = M.Inline:create_constructor(
453 function(caption, src, title, attr)
455 attr = attr or M.Attr()
456 return {c = {attr, List:new(caption), {src, title}}}
458 {{"identifier", "classes", "attributes"}, "caption", {"src", "title"}}
461--- Create a LineBreak inline element
462-- @function LineBreak
463-- @treturn Inline linebreak element
464M.LineBreak = M.Inline:create_constructor(
466 function() return {} end
469--- Creates a link inline element, usually a hyperlink.
471-- @tparam {Inline,..} content text for this link
472-- @tparam string target the link target
473-- @tparam[opt] string title brief link description
474-- @tparam[opt] Attr attr additional attributes
475-- @treturn Inline image element
476M.Link = M.Inline:create_constructor(
478 function(content, target, title, attr)
480 attr = attr or M.Attr()
481 return {c = {attr, List:new(content), {target, title}}}
483 {{"identifier", "classes", "attributes"}, "content", {"target", "title"}}
486--- Creates a Math element, either inline or displayed.
488-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
489-- @tparam string text Math content
490-- @treturn Inline Math element
491M.Math = M.Inline:create_constructor(
493 function(mathtype, text)
494 return {c = {mathtype, text}}
498--- Creates a DisplayMath element (DEPRECATED).
499-- @function DisplayMath
500-- @tparam string text Math content
501-- @treturn Inline Math element
502M.DisplayMath = M.Inline:create_constructor(
504 function(text) return M.Math("DisplayMath", text) end,
507--- Creates an InlineMath inline element (DEPRECATED).
508-- @function InlineMath
509-- @tparam string text Math content
510-- @treturn Inline Math element
511M.InlineMath = M.Inline:create_constructor(
513 function(text) return M.Math("InlineMath", text) end,
517--- Creates a Note inline element
519-- @tparam {Block,...} content footnote block content
520M.Note = M.Inline:create_constructor(
522 function(content) return {c = List:new(content)} end,
526--- Creates a Quoted inline element given the quote type and quoted content.
528-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
529-- @tparam {Inline,..} content inline content
530-- @treturn Inline quoted element
531M.Quoted = M.Inline:create_constructor(
533 function(quotetype, content) return {c = {quotetype, List:new(content)}} end,
534 {"quotetype", "content"}
536--- Creates a single-quoted inline element (DEPRECATED).
537-- @function SingleQuoted
538-- @tparam {Inline,..} content inline content
539-- @treturn Inline quoted element
541M.SingleQuoted = M.Inline:create_constructor(
543 function(content) return M.Quoted(M.SingleQuote, content) end,
544 {"quotetype", "content"}
546--- Creates a single-quoted inline element (DEPRECATED).
547-- @function DoubleQuoted
548-- @tparam {Inline,..} content inline content
549-- @treturn Inline quoted element
551M.DoubleQuoted = M.Inline:create_constructor(
553 function(content) return M.Quoted("DoubleQuote", content) end,
554 {"quotetype", "content"}
557--- Creates a RawInline inline element
558-- @function RawInline
559-- @tparam string format format of the contents
560-- @tparam string text string content
561-- @treturn Inline raw inline element
562M.RawInline = M.Inline:create_constructor(
564 function(format, text) return {c = {format, text}} end,
568--- Creates text rendered in small caps
569-- @function SmallCaps
570-- @tparam {Inline,..} content inline content
571-- @treturn Inline smallcaps element
572M.SmallCaps = M.Inline:create_constructor(
574 function(content) return {c = List:new(content)} end,
578--- Creates a SoftBreak inline element.
579-- @function SoftBreak
580-- @treturn Inline softbreak element
581M.SoftBreak = M.Inline:create_constructor(
583 function() return {} end
586--- Create a Space inline element
588-- @treturn Inline space element
589M.Space = M.Inline:create_constructor(
591 function() return {} end
594--- Creates a Span inline element
596-- @tparam {Inline,..} content inline content
597-- @tparam[opt] Attr attr additional attributes
598-- @treturn Inline span element
599M.Span = M.Inline:create_constructor(
601 function(content, attr)
602 return {c = {attr or M.Attr(), List:new(content)}}
604 {{"identifier", "classes", "attributes"}, "content"}
607--- Creates a Str inline element
609-- @tparam string text content
610-- @treturn Inline string element
611M.Str = M.Inline:create_constructor(
613 function(text) return {c = text} end,
617--- Creates text which is striked out.
618-- @function Strikeout
619-- @tparam {Inline,..} content inline content
620-- @treturn Inline strikeout element
621M.Strikeout = M.Inline:create_constructor(
623 function(content) return {c = List:new(content)} end,
627--- Creates a Strong element, whose text is usually displayed in a bold font.
629-- @tparam {Inline,..} content inline content
630-- @treturn Inline strong element
631M.Strong = M.Inline:create_constructor(
633 function(content) return {c = List:new(content)} end,
637--- Creates a Subscript inline element
638-- @function Subscript
639-- @tparam {Inline,..} content inline content
640-- @treturn Inline subscript element
641M.Subscript = M.Inline:create_constructor(
643 function(content) return {c = List:new(content)} end,
647--- Creates a Superscript inline element
648-- @function Superscript
649-- @tparam {Inline,..} content inline content
650-- @treturn Inline strong element
651M.Superscript = M.Inline:create_constructor(
653 function(content) return {c = List:new(content)} end,
658------------------------------------------------------------------------
662local function assoc_key_equals (x)
663 return function (y) return y[1] == x end
666-- Lookup a value in an associative list
668-- @tparam {{key, value},...} alist associative list
669-- @param key key for which the associated value is to be looked up
670local function lookup(alist, key)
671 return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
674--- Return an iterator which returns key-value pairs of an associative list.
676-- @tparam {{key, value},...} alist associative list
677local apairs = function (alist)
681 cur = rawget(alist, i)
684 return cur[1], cur[2]
691-- AttributeList, a metatable to allow table-like access to attribute lists
692-- represented by associative lists.
693local AttributeList = {
694 __index = function (t, k)
695 if type(k) == "number" then
702 __newindex = function (t, k, v)
703 local cur, idx = List.find_if(t, assoc_key_equals(k))
708 elseif type(k) == "number" then
711 rawset(t, #t + 1, {k, v})
718-- convert a table to an associative list. The order of key-value pairs in the
719-- alist is undefined. The table should either contain no numeric keys or
720-- already be an associative list.
721-- @tparam table associative list or table without numeric keys.
722-- @treturn table associative list
723local to_alist = function (tbl)
724 if #tbl ~= 0 or next(tbl) == nil then
725 -- probably already an alist
730 for k, v in pairs(tbl) do
739M.Attr._field_names = {identifier = 1, classes = 2, attributes = 3}
740--- Create a new set of attributes (Attr).
742-- @tparam[opt] string identifier element identifier
743-- @tparam[opt] {string,...} classes element classes
744-- @tparam[opt] table attributes table containing string keys and values
745-- @return element attributes
746M.Attr.__call = function(t, identifier, classes, attributes)
747 identifier = identifier or ''
748 classes = List:new(classes or {})
749 attributes = setmetatable(to_alist(attributes or {}), AttributeList)
750 local attr = {identifier, classes, attributes}
751 setmetatable(attr, t)
754M.Attr.__index = function(t, k)
755 return rawget(t, k) or
756 rawget(t, M.Attr._field_names[k]) or
757 rawget(getmetatable(t), k)
759M.Attr.__newindex = function(t, k, v)
760 if M.Attr._field_names[k] then
761 rawset(t, M.Attr._field_names[k], v)
766setmetatable(M.Attr, M.Attr)
769--- Creates a single citation.
771-- @tparam string id citation identifier (like a bibtex key)
772-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
773-- @tparam[opt] {Inline,...} prefix citation prefix
774-- @tparam[opt] {Inline,...} suffix citation suffix
775-- @tparam[opt] int note_num note number
776-- @tparam[opt] int hash hash number
777M.Citation = function(id, mode, prefix, suffix, note_num, hash)
778 prefix = prefix or {}
779 suffix = suffix or {}
780 note_num = note_num or 0
784 citationPrefix = prefix,
785 citationSuffix = suffix,
787 citationNoteNum = note_num,
793------------------------------------------------------------------------
797--- Author name is mentioned in the text.
800M.AuthorInText = "AuthorInText"
802--- Author name is suppressed.
805M.SuppressAuthor = "SuppressAuthor"
807--- Default citation style is used.
810M.NormalCitation = "NormalCitation"
812--- Table cells aligned left.
814M.AlignLeft = "AlignLeft"
816--- Table cells right-aligned.
818M.AlignRight = "AlignRight"
820--- Table cell content is centered.
822M.AlignCenter = "AlignCenter"
824--- Table cells are alignment is unaltered.
826M.AlignDefault = "AlignDefault"
828--- Default list number delimiters are used.
830M.DefaultDelim = "DefaultDelim"
832--- List numbers are delimited by a period.
836--- List numbers are delimited by a single parenthesis.
838M.OneParen = "OneParen"
840--- List numbers are delimited by a double parentheses.
842M.TwoParens = "TwoParens"
844--- List are numbered in the default style
846M.DefaultStyle = "DefaultStyle"
848--- List items are numbered as examples.
852--- List are numbered using decimal integers.
856--- List are numbered using lower-case roman numerals.
858M.LowerRoman = "LowerRoman"
860--- List are numbered using upper-case roman numerals
862M.UpperRoman = "UpperRoman"
864--- List are numbered using lower-case alphabetic characters.
866M.LowerAlpha = "LowerAlpha"
868--- List are numbered using upper-case alphabetic characters.
870M.UpperAlpha = "UpperAlpha"
873------------------------------------------------------------------------
877--- Parse the given string into a Pandoc document.
878-- The method used to interpret input is specified by *format*. Acceptable
879-- values for this parameter are equal to those that can be given to the
880-- `--from` command line option.
881-- @tparam string markup the markup to be parsed
882-- @tparam[opt] string format format specification, defaults to "markdown".
883-- @treturn Pandoc pandoc document
885-- local org_markup = "/emphasis/" -- Input to be read
886-- local document = pandoc.read(org_markup, "org")
887-- -- Get the first block of the document
888-- local block = document.blocks[1]
889-- -- The inline element in that block is an `Emph`
890-- assert(block.content[1].t == "Emph")
891function M.read(markup, format)
892 format = format or "markdown"
893 local pd = pandoc._read(format, markup)
894 if type(pd) == "string" then
901--- Runs command with arguments, passing it some input, and returns the output.
902-- @treturn string Output of command.
903-- @raise A table containing the keys `command`, `error_code`, and `output` is
904-- thrown if the command exits with a non-zero error code.
906-- local ec, output = pandoc.pipe("sed", {"-e","s/a/b/"}, "abc")
907function M.pipe (command, args, input)
908 local ec, output = pandoc._pipe(command, args, input)
911 { command = command, error_code = ec, output = output},
912 { __tostring = function(e)
913 return "Error running " .. e.command
914 .. " (error code " .. e.error_code .. "): "
924--- Use functions defined in the global namespace to create a pandoc filter.
925-- All globally defined functions which have names of pandoc elements are
926-- collected into a new table.
927-- @return A list of filter functions
929-- -- within a file defining a pandoc filter:
931-- return pandoc.Str(utf8.upper(text))
934-- return {pandoc.global_filter()}
935-- -- the above is equivallent to
936-- -- return {{Str = Str}}
937function M.global_filter()
939 function is_filter_function(k)
940 return M.Inline.constructor[k] or
941 M.Block.constructor[k] or
942 k == "Meta" or k == "Doc" or k == "Pandoc" or
943 k == "Block" or k == "Inline"
945 for k, v in pairs(_G) do
946 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