@@ -1,7 +1,7 @@
11--[[
22pandoc.lua
33
4−Copyright (c) 2017 Albert Krewinkel
4+Copyright © 2017 Albert Krewinkel
55
66Permission to use, copy, modify, and/or distribute this software for any purpose
77with or without fee is hereby granted, provided that the above copyright notice
@@ -16,21 +16,78 @@ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
1616THIS SOFTWARE.
1717]]
1818
19−--- The module
19+---
20+-- Lua functions for pandoc scripts.
21+--
22+-- @author Albert Krewinkel
23+-- @copyright © 2017 Albert Krewinkel
24+-- @license MIT
2025local M = {
21− _version = "0.1.0"
26+ _VERSION = "0.2.0"
2227}
2328
29+--- Attributes
30+-- @type Attributes
31+M.Attributes = {}
32+setmetatable(M.Attributes, M.Attributes)
33+
34+M.Attributes.__index = function(t, k)
35+ if k == "id" then
36+ return t[1]
37+ elseif k == "class" then
38+ return table.concat(t[2], ' ')
39+ else
40+ return t.kv[k]
41+ end
42+end
43+
2444--- Create a new set of attributes (Attr).
25−function M.Attributes(id, classes, key_values)
26− return {id, classes, key_values}
45+-- @function Attributes
46+M.Attributes.__call = function(t, key_values, id, classes)
47+ local kv = {}
48+ for i = 1, #key_values do
49+ kv[key_values[i][1]] = key_values[i][2]
50+ end
51+ id = id or ''
52+ classes = classes or {}
53+ local attr = {id, classes, key_values, kv = kv}
54+ setmetatable(attr, t)
55+ return attr
56+end
57+M.Attributes.empty = M.Attributes('', {}, {})
58+
59+
60+--- Creates a single citation.
61+-- @function Citation
62+-- @tparam string id citation identifier (like a bibtex key)
63+-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
64+-- @tparam[opt] {Inline,...} prefix citation prefix
65+-- @tparam[opt] {Inline,...} suffix citation suffix
66+-- @tparam[opt] int note_num note number
67+-- @tparam[opt] int note_num hash number
68+M.Citation = function(id, mode, prefix, suffix, note_num, hash)
69+ prefix = prefix or {}
70+ suffix = suffix or {}
71+ note_num = note_num or 0
72+ hash = hash or 0
73+ return {
74+ citationId = id,
75+ citationPrefix = prefix,
76+ citationSuffix = suffix,
77+ citationMode = mode,
78+ citationNoteNum = note_num,
79+ citationHash = hash,
80+ }
2781end
2882
2983------------------------------------------------------------------------
30−--- Document AST elements
84+-- The base class for pandoc's AST elements.
85+-- @type Element
86+-- @local
3187local Element = {}
3288
3389--- Create a new element subtype
90+-- @local
3491function Element:make_subtype(o)
3592 o = o or {}
3693 setmetatable(o, self)
@@ -39,6 +96,7 @@ function Element:make_subtype(o)
3996end
4097
4198--- Create a new element given its tag and arguments
99+-- @local
42100function Element:new(tag, ...)
43101 local element = { t = tag }
44102 local content = {...}
@@ -56,6 +114,7 @@ function Element:new(tag, ...)
56114end
57115
58116--- Create a new constructor
117+-- @local
59118-- @param tag Tag used to identify the constructor
60119-- @param fn Function to be called when constructing a new element
61120-- @return function that constructs a new element
@@ -75,222 +134,338 @@ function Element:create_constructor(tag, fn)
75134 end
76135 return obj
77136 end
137+ self.constructor = self.constructor or {}
138+ self.constructor[tag] = constr
78139 return constr
79140end
80141
142+--- Calls the constructor, creating a new element.
143+-- @local
81144function Element.__call(t, ...)
82145 return t:new(...)
83146end
84147
85148------------------------------------------------------------------------
86−-- Document
87−local function Doc(blocks, meta)
149+--- Pandoc Document
150+-- @section document
151+
152+--- A complete pandoc document
153+-- @function Doc
154+-- @tparam {Block,...} blocks document content
155+-- @tparam[opt] Meta meta document meta data
156+function M.Doc(blocks, meta)
157+ meta = meta or {}
88158 return {
89159 ["blocks"] = blocks,
90160 ["meta"] = meta,
91161 ["pandoc-api-version"] = {1,17,0,5},
92162 }
93163end
94−local Inline = Element:make_subtype{}
95−function Inline.__call(t, ...)
164+
165+
166+--- Inline element class
167+-- @type Inline
168+M.Inline = Element:make_subtype{}
169+M.Inline.__call = function (t, ...)
96170 return t:new(...)
97171end
98172
99−local Block = Element:make_subtype{}
100−
101173------------------------------------------------------------------------
102−-- Inline element constructors
103−-- @section
174+-- Inline
175+-- @section Inline
104176
105−--- Create a Cite inline element
106−-- @function Inline.Cite
107−Inline.Cite = Inline:create_constructor(
177+--- Creates a Cite inline element
178+-- @function Cite
179+-- @tparam {Inline,...} content List of inlines
180+-- @tparam {Citation,...} citations List of citations
181+-- @treturn Inline citations element
182+M.Cite = M.Inline:create_constructor(
108183 "Cite",
109− function(lst, cs) return {c = {cs, lst}} end
184+ function(content, citations) return {c = {citations, content}} end
110185)
111−--- Create a Code inline element
112−-- @function Inline.Code
113−Inline.Code = Inline:create_constructor(
186+
187+--- Creates a Code inline element
188+-- @function Code
189+-- @tparam string code brief image description
190+-- @tparam[opt] Attributes attributes additional attributes
191+-- @treturn Inline code element
192+M.Code = M.Inline:create_constructor(
114193 "Code",
115− function(code, attr) return {c = {attr, code}} end
194+ function(code, attributes) return {c = {attributes, code}} end
116195)
117−--- Create a Emph inline element
118−-- @function Inline.Emph
119−Inline.Emph = Inline:create_constructor(
196+
197+--- Creates an inline element representing emphasised text.
198+-- @function Emph
199+-- @tparam {Inline,..} content inline content
200+-- @treturn Inline emphasis element
201+M.Emph = M.Inline:create_constructor(
120202 "Emph",
121− function(xs) return {c = xs} end
203+ function(content) return {c = content} end
122204)
123−--- Create a Image inline element
124−-- @function Inline.Image
125−Inline.Image = Inline:create_constructor(
205+
206+--- Creates a Image inline element
207+-- @function Image
208+-- @tparam {Inline,..} caption text used to describe the image
209+-- @tparam string src path to the image file
210+-- @tparam[opt] string title brief image description
211+-- @tparam[opt] Attributes attributes additional attributes
212+-- @treturn Inline image element
213+M.Image = M.Inline:create_constructor(
126214 "Image",
127− function(capt, src, tit, attr) return {c = {attr, capt, {src, tit}}} end
215+ function(caption, src, title, attributes)
216+ title = title or ""
217+ attributes = attributes or Attribute.empty
218+ return {c = {attributes, caption, {src, title}}}
219+ end
128220)
221+
129222--- Create a LineBreak inline element
130−-- @function Inline.LineBreak
131−Inline.LineBreak = Inline:create_constructor(
223+-- @function LineBreak
224+-- @treturn Inline linebreak element
225+M.LineBreak = M.Inline:create_constructor(
132226 "LineBreak",
133227 function() return {} end
134228)
135−--- Create a Link inline element
136−-- @function Inline.Link
137−Inline.Link = Inline:create_constructor(
229+
230+--- Creates a link inline element, usually a hyperlink.
231+-- @function Link
232+-- @tparam {Inline,..} content text for this link
233+-- @tparam string target the link target
234+-- @tparam[opt] string title brief link description
235+-- @tparam[opt] Attributes attributes additional attributes
236+-- @treturn Inline image element
237+M.Link = M.Inline:create_constructor(
138238 "Link",
139− function(txt, src, tit, attr) return {c = {attr, txt, {src, tit}}} end
239+ function(content, target, title, attributes)
240+ title = title or ""
241+ attributes = attributes or Attribute.empty
242+ return {c = {attributes, content, {target, title}}}
243+ end
140244)
141−--- Create a Math inline element
142−-- @function Inline.Math
143−Inline.Math = Inline:create_constructor(
245+
246+--- Creates a Math inline element
247+-- @function Math
248+-- @tparam InlineMath|DisplayMath mathtype Display specifier
249+-- @tparam string text Math content
250+-- @treturn Inline Math element
251+M.Math = M.Inline:create_constructor(
144252 "Math",
145− function(m, str) return {c = {m, str}} end
253+ function(mathtype, text)
254+ return {c = {mathtype, text}}
255+ end
146256)
147−--- Create a Note inline element
148−-- @function Inline.Note
149−Inline.Note = Inline:create_constructor(
257+
258+--- Creates a Note inline element
259+-- @function Note
260+-- @tparam {Block,...} content footnote block content
261+M.Note = M.Inline:create_constructor(
150262 "Note",
151263 function(contents) return {c = contents} end
152264)
153−--- Create a Quoted inline element
154−-- @function Inline.Quoted
155−Inline.Quoted = Inline:create_constructor(
265+
266+--- Creates a Quoted inline element
267+-- @function Quoted
268+-- @tparam DoubleQuote|SingleQuote quotetype type of quotes to be used
269+-- @tparam {Inline,..} content inline content
270+-- @treturn Inline quoted element
271+M.Quoted = M.Inline:create_constructor(
156272 "Quoted",
157− function(qt, lst) return {c = {qt, lst}} end
273+ function(quotetype, content) return {c = {quotetype, content}} end
158274)
159−--- Create a RawInline inline element
160−-- @function Inline.RawInline
161−Inline.RawInline = Inline:create_constructor(
275+--- Creates a RawInline inline element
276+-- @function RawInline
277+-- @tparam string format format of the contents
278+-- @tparam string text string content
279+-- @treturn Inline raw inline element
280+M.RawInline = M.Inline:create_constructor(
162281 "RawInline",
163− function(f, xs) return {c = {f, xs}} end
282+ function(format, text) return {c = {format, text}} end
164283)
165−--- Create a SmallCaps inline element
166−-- @function Inline.SmallCaps
167−Inline.SmallCaps = Inline:create_constructor(
284+
285+--- Creates text rendered in small caps
286+-- @function SmallCaps
287+-- @tparam {Inline,..} content inline content
288+-- @treturn Inline smallcaps element
289+M.SmallCaps = M.Inline:create_constructor(
168290 "SmallCaps",
169− function(xs) return {c = xs} end
291+ function(content) return {c = content} end
170292)
171−--- Create a SoftBreak inline element
172−-- @function Inline.SoftBreak
173−Inline.SoftBreak = Inline:create_constructor(
293+
294+--- Creates a SoftBreak inline element.
295+-- @function SoftBreak
296+-- @treturn Inline softbreak element
297+M.SoftBreak = M.Inline:create_constructor(
174298 "SoftBreak",
175299 function() return {} end
176300)
301+
177302--- Create a Space inline element
178−-- @function Inline.Space
179−Inline.Space = Inline:create_constructor(
303+-- @function Space
304+-- @treturn Inline space element
305+M.Space = M.Inline:create_constructor(
180306 "Space",
181307 function() return {} end
182308)
183−--- Create a Span inline element
184−-- @function Inline.Span
185−Inline.Span = Inline:create_constructor(
309+
310+--- Creates a Span inline element
311+-- @function Span
312+-- @tparam {Inline,..} content inline content
313+-- @tparam[opt] Attributes attributes additional attributes
314+-- @treturn Inline span element
315+M.Span = M.Inline:create_constructor(
186316 "Span",
187− function(ls, attr) return {c = {attr, xs}} end
317+ function(content, attributes) return {c = {attributes, content}} end
188318)
189−--- Create a Str inline element
190−-- @function Inline.Str
191−Inline.Str = Inline:create_constructor(
319+
320+--- Creates a Str inline element
321+-- @function Str
322+-- @tparam string text content
323+-- @treturn Inline string element
324+M.Str = M.Inline:create_constructor(
192325 "Str",
193− function(str) return {c = str} end
326+ function(text) return {c = text} end
194327)
195−--- Create a Strikeout inline element
196−-- @function Inline.Strikeout
197−Inline.Strikeout = Inline:create_constructor(
328+
329+--- Creates text which is striked out.
330+-- @function Strikeout
331+-- @tparam {Inline,..} content inline content
332+-- @treturn Inline strikeout element
333+M.Strikeout = M.Inline:create_constructor(
198334 "Strikeout",
199− function(xs) return {c = xs} end
335+ function(content) return {c = content} end
200336)
201−--- Create a Strong inline element
202−-- @function Inline.Strong
203−Inline.Strong = Inline:create_constructor(
337+
338+--- Creates a Strong element, whose text is usually displayed in a bold font.
339+-- @function Strong
340+-- @tparam {Inline,..} content inline content
341+-- @treturn Inline strong element
342+M.Strong = M.Inline:create_constructor(
204343 "Strong",
205− function(xs) return {c = xs} end
344+ function(content) return {c = content} end
206345)
207−--- Create a Subscript inline element
208−-- @function Inline.Subscript
209−Inline.Subscript = Inline:create_constructor(
346+
347+--- Creates a Subscript inline element
348+-- @function Subscript
349+-- @tparam {Inline,..} content inline content
350+-- @treturn Inline subscript element
351+M.Subscript = M.Inline:create_constructor(
210352 "Subscript",
211− function(xs) return {c = xs} end
353+ function(content) return {c = content} end
212354)
213−--- Create a Superscript inline element
214−-- @function Inline.Superscript
215−Inline.Superscript = Inline:create_constructor(
355+
356+--- Creates a Superscript inline element
357+-- @function Superscript
358+-- @tparam {Inline,..} content inline content
359+-- @treturn Inline strong element
360+M.Superscript = M.Inline:create_constructor(
216361 "Superscript",
217− function(xs) return {c = xs} end
362+ function(content) return {c = content} end
218363)
219364
220−M.block_types = {
221− "BlockQuote",
222− "BulletList",
223− "CodeBlock",
224− "DefinitionList",
225− "Div",
226− "Header",
227− "HorizontalRule",
228− "HorizontalRule",
229− "LineBlock",
230− "Null",
231− "OrderedList",
232− "Para",
233− "Plain",
234− "RawBlock",
235− "Table",
236−}
237365
238−M.inline_types = {
239− "Cite",
240− "Code",
241− "Emph",
242− "Image",
243− "LineBreak",
244− "Link",
245− "Math",
246− "Note",
247− "Quoted",
248− "RawInline",
249− "SmallCaps",
250− "SoftBreak",
251− "Space",
252− "Span",
253− "Str",
254− "Strikeout",
255− "Strong",
256− "Subscript",
257− "Superscript"
366+------------------------------------------------------------------------
367+-- Block elements
368+-- @type Block
369+M.Block = Element:make_subtype{}
370+
371+--- Block constructors
372+M.Block.constructors = {
373+ BlockQuote = true,
374+ BulletList = true,
375+ CodeBlock = true,
376+ DefinitionList = true,
377+ Div = true,
378+ Header = true,
379+ HorizontalRule = true,
380+ HorizontalRule = true,
381+ LineBlock = true,
382+ Null = true,
383+ OrderedList = true,
384+ Para = true,
385+ Plain = true,
386+ RawBlock = true,
387+ Table = true,
258388}
259389
390+local set_of_inline_types = {}
391+for k, _ in pairs(M.Inline.constructor) do
392+ set_of_inline_types[k] = true
393+end
260394
261−for _, block_type in pairs(M.block_types) do
395+for block_type, _ in pairs(M.Block.constructors) do
262396 M[block_type] = function(...)
263− return Block:new(block_type, ...)
397+ return M.Block:new(block_type, ...)
264398 end
265399end
266400
267−for _, inline_type in pairs(M.inline_types) do
268− M[inline_type] = Inline[inline_type]
269−end
270401
271−--- Arrays to provide fast lookup of element types
272−local set_of_inline_types = {}
273−local set_of_block_types = {}
402+------------------------------------------------------------------------
403+-- Constants
404+-- @section constants
274405
275−for i = 1, #M.inline_types do
276− set_of_inline_types[M.inline_types[i]] = true
277−end
278−for i = 1, #M.block_types do
279− set_of_block_types[M.block_types[i]] = true
280−end
406+--- Math content is to be displayed on a separate line.
407+-- @see Math
408+M.DisplayMath = {}
409+M.DisplayMath.t = "DisplayMath"
410+--- Math content is to be displayed inline within the paragraph
411+-- @see Math
412+M.InlineMath = {}
413+M.InlineMath.t = "InlineMath"
414+
415+--- Double quoted content.
416+-- @see Quoted
417+M.DoubleQuote = {}
418+M.DoubleQuote.t = "DoubleQuote"
281419
420+--- Single quoted content.
421+-- @see Quoted
422+M.SingleQuote = {}
423+M.SingleQuote.t = "SingleQuote"
424+
425+--- Author name is mentioned in the text.
426+-- @see Citation
427+-- @see Cite
428+M.AuthorInText = {}
429+M.AuthorInText.t = "AuthorInText"
430+
431+--- Author name is suppressed.
432+-- @see Citation
433+-- @see Cite
434+M.SuppressAuthor = {}
435+M.SuppressAuthor.t = "SuppressAuthor"
436+
437+--- Default citation style is used.
438+-- @see Citation
439+-- @see Cite
440+M.NormalCitation = {}
441+M.NormalCitation.t = "NormalCitation"
442+
443+
444+------------------------------------------------------------------------
445+-- Helper Functions
446+-- @section helpers
447+
448+--- Use functions defined in the global namespace to create a pandoc filter.
449+-- All globally defined functions which have names of pandoc elements are
450+-- collected into a new table.
451+-- @return A list of filter functions
452+-- @usage
453+-- -- within a file defining a pandoc filter:
454+-- function Str(text)
455+-- return pandoc.Str(utf8.upper(text))
456+-- end
457+--
458+-- return {pandoc.global_filter()}
459+-- -- the above is equivallent to
460+-- -- return {{Str = Str}}
282461function M.global_filter()
283462 local res = {}
284463 for k, v in pairs(_G) do
285− if set_of_inline_types[k] or set_of_block_types[k] or k == "Doc" then
464+ if M.Inline.constructor[k] or M.Block.constructors[k] or k == "Doc" then
286465 res[k] = v
287466 end
288467 end
289468 return res
290469end
291470
292−M["Doc"] = Doc
293−M["Inline"] = Inline
294−M["Block"] = Block
295−
296471return M