83b5b79c0e
The first argument passed to Lua `Reader` functions is no longer a plain string but a richer data structure. The structure can easily be converted to a string by applying `tostring`, but is also a list with elements that contain each the *text* and *name* of each input source as a property of the respective name. A small example is added to the custom reader documentation, showcasing its use in a reader that creates a syntax-highlighted code block for each source code file passed as input. Existing readers must be updated.
190 lines
5.3 KiB
Lua
190 lines
5.3 KiB
Lua
-- A sample custom reader for Creole 1.0 (common wiki markup)
|
|
-- http://www.wikicreole.org/wiki/CheatSheet
|
|
|
|
-- For better performance we put these functions in local variables:
|
|
local P, S, R, Cf, Cc, Ct, V, Cs, Cg, Cb, B, C, Cmt =
|
|
lpeg.P, lpeg.S, lpeg.R, lpeg.Cf, lpeg.Cc, lpeg.Ct, lpeg.V,
|
|
lpeg.Cs, lpeg.Cg, lpeg.Cb, lpeg.B, lpeg.C, lpeg.Cmt
|
|
|
|
local whitespacechar = S(" \t\r\n")
|
|
local specialchar = S("/*~[]\\{}|")
|
|
local wordchar = (1 - (whitespacechar + specialchar))
|
|
local spacechar = S(" \t")
|
|
local newline = P"\r"^-1 * P"\n"
|
|
local blankline = spacechar^0 * newline
|
|
local endline = newline * #-blankline
|
|
local endequals = spacechar^0 * P"="^0 * spacechar^0 * newline
|
|
local cellsep = spacechar^0 * P"|"
|
|
|
|
local function trim(s)
|
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
|
end
|
|
|
|
local function ListItem(lev, ch)
|
|
local start
|
|
if ch == nil then
|
|
start = S"*#"
|
|
else
|
|
start = P(ch)
|
|
end
|
|
local subitem = function(c)
|
|
if lev < 6 then
|
|
return ListItem(lev + 1, c)
|
|
else
|
|
return (1 - 1) -- fails
|
|
end
|
|
end
|
|
local parser = spacechar^0
|
|
* start^lev
|
|
* #(- start)
|
|
* spacechar^0
|
|
* Ct((V"Inline" - (newline * spacechar^0 * S"*#"))^0)
|
|
* newline
|
|
* (Ct(subitem("*")^1) / pandoc.BulletList
|
|
+
|
|
Ct(subitem("#")^1) / pandoc.OrderedList
|
|
+
|
|
Cc(nil))
|
|
/ function (ils, sublist)
|
|
return { pandoc.Plain(ils), sublist }
|
|
end
|
|
return parser
|
|
end
|
|
|
|
-- Grammar
|
|
G = P{ "Doc",
|
|
Doc = Ct(V"Block"^0)
|
|
/ pandoc.Pandoc ;
|
|
Block = blankline^0
|
|
* ( V"Header"
|
|
+ V"HorizontalRule"
|
|
+ V"CodeBlock"
|
|
+ V"List"
|
|
+ V"Table"
|
|
+ V"Para") ;
|
|
Para = Ct(V"Inline"^1)
|
|
* newline
|
|
/ pandoc.Para ;
|
|
HorizontalRule = spacechar^0
|
|
* P"----"
|
|
* spacechar^0
|
|
* newline
|
|
/ pandoc.HorizontalRule;
|
|
Header = (P("=")^1 / string.len)
|
|
* spacechar^1
|
|
* Ct((V"Inline" - endequals)^1)
|
|
* endequals
|
|
/ pandoc.Header;
|
|
CodeBlock = P"{{{"
|
|
* blankline
|
|
* C((1 - (newline * P"}}}"))^0)
|
|
* newline
|
|
* P"}}}"
|
|
/ pandoc.CodeBlock;
|
|
Placeholder = P"<<<"
|
|
* C(P(1) - P">>>")^0
|
|
* P">>>"
|
|
/ function() return pandoc.Div({}) end;
|
|
List = V"BulletList"
|
|
+ V"OrderedList" ;
|
|
BulletList = Ct(ListItem(1,'*')^1)
|
|
/ pandoc.BulletList ;
|
|
OrderedList = Ct(ListItem(1,'#')^1)
|
|
/ pandoc.OrderedList ;
|
|
Table = (V"TableHeader" + Cc{})
|
|
* Ct(V"TableRow"^1)
|
|
/ function(headrow, bodyrows)
|
|
local numcolumns = #(bodyrows[1])
|
|
local aligns = {}
|
|
local widths = {}
|
|
for i = 1,numcolumns do
|
|
aligns[i] = pandoc.AlignDefault
|
|
widths[i] = 0
|
|
end
|
|
return pandoc.utils.from_simple_table(
|
|
pandoc.SimpleTable({}, aligns, widths, headrow, bodyrows))
|
|
end ;
|
|
TableHeader = Ct(V"HeaderCell"^1)
|
|
* cellsep^-1
|
|
* spacechar^0
|
|
* newline ;
|
|
TableRow = Ct(V"BodyCell"^1)
|
|
* cellsep^-1
|
|
* spacechar^0
|
|
* newline ;
|
|
HeaderCell = cellsep
|
|
* P"="
|
|
* spacechar^0
|
|
* Ct((V"Inline" - (newline + cellsep))^0)
|
|
/ function(ils) return { pandoc.Plain(ils) } end ;
|
|
BodyCell = cellsep
|
|
* spacechar^0
|
|
* Ct((V"Inline" - (newline + cellsep))^0)
|
|
/ function(ils) return { pandoc.Plain(ils) } end ;
|
|
Inline = V"Emph"
|
|
+ V"Strong"
|
|
+ V"LineBreak"
|
|
+ V"Link"
|
|
+ V"URL"
|
|
+ V"Image"
|
|
+ V"Str"
|
|
+ V"Space"
|
|
+ V"SoftBreak"
|
|
+ V"Escaped"
|
|
+ V"Placeholder"
|
|
+ V"Code"
|
|
+ V"Special" ;
|
|
Str = wordchar^1
|
|
/ pandoc.Str;
|
|
Escaped = P"~"
|
|
* C(P(1))
|
|
/ pandoc.Str ;
|
|
Special = specialchar
|
|
/ pandoc.Str;
|
|
Space = spacechar^1
|
|
/ pandoc.Space ;
|
|
SoftBreak = endline
|
|
* # -(V"HorizontalRule" + V"CodeBlock")
|
|
/ pandoc.SoftBreak ;
|
|
LineBreak = P"\\\\"
|
|
/ pandoc.LineBreak ;
|
|
Code = P"{{{"
|
|
* C((1 - P"}}}")^0)
|
|
* P"}}}"
|
|
/ trim / pandoc.Code ;
|
|
Link = P"[["
|
|
* C((1 - (P"]]" + P"|"))^0)
|
|
* (P"|" * Ct((V"Inline" - P"]]")^1))^-1 * P"]]"
|
|
/ function(url, desc)
|
|
local txt = desc or {pandoc.Str(url)}
|
|
return pandoc.Link(txt, url)
|
|
end ;
|
|
Image = P"{{"
|
|
* #-P"{"
|
|
* C((1 - (S"}"))^0)
|
|
* (P"|" * Ct((V"Inline" - P"}}")^1))^-1
|
|
* P"}}"
|
|
/ function(url, desc)
|
|
local txt = desc or ""
|
|
return pandoc.Image(txt, url)
|
|
end ;
|
|
URL = P"http"
|
|
* P"s"^-1
|
|
* P":"
|
|
* (1 - (whitespacechar + (S",.?!:;\"'" * #whitespacechar)))^1
|
|
/ function(url)
|
|
return pandoc.Link(pandoc.Str(url), url)
|
|
end ;
|
|
Emph = P"//"
|
|
* Ct((V"Inline" - P"//")^1)
|
|
* P"//"
|
|
/ pandoc.Emph ;
|
|
Strong = P"**"
|
|
* Ct((V"Inline" -P"**")^1)
|
|
* P"**"
|
|
/ pandoc.Strong ;
|
|
}
|
|
|
|
function Reader(input, reader_options)
|
|
return lpeg.match(G, tostring(input))
|
|
end
|