summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/markdown/markdown.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/markdown/markdown.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/markdown/markdown.lua202
1 files changed, 172 insertions, 30 deletions
diff --git a/Master/texmf-dist/tex/luatex/markdown/markdown.lua b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
index 85900563718..eb68cc175d5 100644
--- a/Master/texmf-dist/tex/luatex/markdown/markdown.lua
+++ b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
@@ -58,12 +58,12 @@
-- those in the standard .ins files.
--
local metadata = {
- version = "2.10.1",
+ version = "2.11.0-0-g4505824",
comment = "A module for the conversion from markdown to plain TeX",
author = "John MacFarlane, Hans Hagen, Vít Novotný",
copyright = {"2009-2016 John MacFarlane, Hans Hagen",
"2016-2021 Vít Novotný"},
- license = "LPPL 1.3"
+ license = "LPPL 1.3c"
}
if not modules then modules = { } end
@@ -97,6 +97,7 @@ defaultOptions.headerAttributes = false
defaultOptions.html = false
defaultOptions.hybrid = false
defaultOptions.inlineFootnotes = false
+defaultOptions.jekyllData = false
defaultOptions.pipeTables = false
defaultOptions.preserveTabs = false
defaultOptions.shiftHeadings = 0
@@ -105,6 +106,7 @@ defaultOptions.smartEllipses = false
defaultOptions.startNumber = true
defaultOptions.stripIndent = false
defaultOptions.tableCaptions = false
+defaultOptions.taskLists = false
defaultOptions.texComments = false
defaultOptions.tightLists = true
defaultOptions.underscores = true
@@ -2346,19 +2348,6 @@ function M.writer.new(options)
if not self.is_writing then return "" end
return "\\markdownRendererHorizontalRule{}"
end
- local escaped_chars = {
- ["{"] = "\\markdownRendererLeftBrace{}",
- ["}"] = "\\markdownRendererRightBrace{}",
- ["$"] = "\\markdownRendererDollarSign{}",
- ["%"] = "\\markdownRendererPercentSign{}",
- ["&"] = "\\markdownRendererAmpersand{}",
- ["_"] = "\\markdownRendererUnderscore{}",
- ["#"] = "\\markdownRendererHash{}",
- ["^"] = "\\markdownRendererCircumflex{}",
- ["\\"] = "\\markdownRendererBackslash{}",
- ["~"] = "\\markdownRendererTilde{}",
- ["|"] = "\\markdownRendererPipe{}",
- }
local escaped_uri_chars = {
["{"] = "\\markdownRendererLeftBrace{}",
["}"] = "\\markdownRendererRightBrace{}",
@@ -2369,20 +2358,37 @@ function M.writer.new(options)
["{"] = "\\markdownRendererLeftBrace{}",
["}"] = "\\markdownRendererRightBrace{}",
["%"] = "\\markdownRendererPercentSign{}",
- ["#"] = "\\markdownRendererHash{}",
["\\"] = "\\markdownRendererBackslash{}",
+ ["#"] = "\\markdownRendererHash{}",
}
local escaped_minimal_strings = {
["^^"] = "\\markdownRendererCircumflex\\markdownRendererCircumflex ",
+ ["☒"] = "\\markdownRendererTickedBox{}",
+ ["⌛"] = "\\markdownRendererHalfTickedBox{}",
+ ["☐"] = "\\markdownRendererUntickedBox{}",
+ }
+ local escaped_chars = {
+ ["{"] = "\\markdownRendererLeftBrace{}",
+ ["}"] = "\\markdownRendererRightBrace{}",
+ ["%"] = "\\markdownRendererPercentSign{}",
+ ["\\"] = "\\markdownRendererBackslash{}",
+ ["#"] = "\\markdownRendererHash{}",
+ ["$"] = "\\markdownRendererDollarSign{}",
+ ["&"] = "\\markdownRendererAmpersand{}",
+ ["_"] = "\\markdownRendererUnderscore{}",
+ ["^"] = "\\markdownRendererCircumflex{}",
+ ["~"] = "\\markdownRendererTilde{}",
+ ["|"] = "\\markdownRendererPipe{}",
}
- local escape = util.escaper(escaped_chars)
+ local escape = util.escaper(escaped_chars, escaped_minimal_strings)
local escape_citation = util.escaper(escaped_citation_chars,
escaped_minimal_strings)
local escape_uri = util.escaper(escaped_uri_chars, escaped_minimal_strings)
+ local escape_minimal = util.escaper({}, escaped_minimal_strings)
if options.hybrid then
- self.string = function(s) return s end
- self.citation = function(c) return c end
- self.uri = function(u) return u end
+ self.string = escape_minimal
+ self.citation = escape_minimal
+ self.uri = escape_minimal
else
self.string = escape
self.citation = escape_citation
@@ -2556,6 +2562,15 @@ function M.writer.new(options)
function self.emphasis(s)
return {"\\markdownRendererEmphasis{",s,"}"}
end
+ function self.tickbox(f)
+ if f == 1.0 then
+ return "☒ "
+ elseif f == 0.0 then
+ return "☐ "
+ else
+ return "⌛ "
+ end
+ end
function self.strong(s)
return {"\\markdownRendererStrongEmphasis{",s,"}"}
end
@@ -2576,6 +2591,88 @@ function M.writer.new(options)
local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
return {"\\markdownRendererInputFencedCode{",name,"}{",i,"}"}
end
+ function self.jekyllData(d, t, p)
+ if not self.is_writing then return "" end
+
+ local buf = {}
+
+ local keys = {}
+ for k, _ in pairs(d) do
+ table.insert(keys, k)
+ end
+ table.sort(keys)
+
+ if not p then
+ table.insert(buf, "\\markdownRendererJekyllDataBegin")
+ end
+
+ if #d > 0 then
+ table.insert(buf, "\\markdownRendererJekyllDataSequenceBegin{")
+ table.insert(buf, self.uri(p or "null"))
+ table.insert(buf, "}{")
+ table.insert(buf, #keys)
+ table.insert(buf, "}")
+ else
+ table.insert(buf, "\\markdownRendererJekyllDataMappingBegin{")
+ table.insert(buf, self.uri(p or "null"))
+ table.insert(buf, "}{")
+ table.insert(buf, #keys)
+ table.insert(buf, "}")
+ end
+
+ for _, k in ipairs(keys) do
+ local v = d[k]
+ local typ = type(v)
+ k = tostring(k or "null")
+ if typ == "table" and next(v) ~= nil then
+ table.insert(
+ buf,
+ self.jekyllData(v, t, k)
+ )
+ else
+ k = self.uri(k)
+ v = tostring(v)
+ if typ == "boolean" then
+ table.insert(buf, "\\markdownRendererJekyllDataBoolean{")
+ table.insert(buf, k)
+ table.insert(buf, "}{")
+ table.insert(buf, v)
+ table.insert(buf, "}")
+ elseif typ == "number" then
+ table.insert(buf, "\\markdownRendererJekyllDataNumber{")
+ table.insert(buf, k)
+ table.insert(buf, "}{")
+ table.insert(buf, v)
+ table.insert(buf, "}")
+ elseif typ == "string" then
+ table.insert(buf, "\\markdownRendererJekyllDataString{")
+ table.insert(buf, k)
+ table.insert(buf, "}{")
+ table.insert(buf, t(v))
+ table.insert(buf, "}")
+ elseif typ == "table" then
+ table.insert(buf, "\\markdownRendererJekyllDataEmpty{")
+ table.insert(buf, k)
+ table.insert(buf, "}")
+ else
+ error(format("Unexpected type %s for value of " ..
+ "YAML key %s", typ, k))
+ end
+ end
+ end
+
+ if #d > 0 then
+ table.insert(buf, "\\markdownRendererJekyllDataSequenceEnd")
+ else
+ table.insert(buf, "\\markdownRendererJekyllDataMappingEnd")
+ end
+
+ if not p then
+ table.insert(buf, "\\markdownRendererJekyllDataEnd")
+ end
+
+ return buf
+ end
self.active_headings = {}
function self.heading(s,level,attributes)
local active_headings = self.active_headings
@@ -2660,16 +2757,16 @@ function M.writer.new(options)
}
end
function self.set_state(s)
- previous_state = self.get_state()
- for key, value in pairs(state) do
+ local previous_state = self.get_state()
+ for key, value in pairs(s) do
self[key] = value
end
return previous_state
end
function self.defer_call(f)
- state = self.get_state()
+ local previous_state = self.get_state()
return function(...)
- state = self.set_state(state)
+ local state = self.set_state(previous_state)
local return_value = f(...)
self.set_state(state)
return return_value
@@ -2764,7 +2861,6 @@ parsers.spnl = parsers.optionalspace
* (parsers.newline * parsers.optionalspace)^-1
parsers.line = parsers.linechar^0 * parsers.newline
parsers.nonemptyline = parsers.line - parsers.blankline
-
parsers.commented_line_letter = parsers.linechar
+ parsers.newline
- parsers.backslash
@@ -2803,7 +2899,9 @@ parsers.commented_line = Cg(Cc(""), "backslashes")
+ parsers.percent -- comment
* parsers.line
* parsers.optionalspace) -- leading tabs and spaces
- + C(parsers.newline))
+ + #(parsers.newline)
+ * Cb("backslashes")
+ * C(parsers.newline))
parsers.chunk = parsers.line * (parsers.optionallyindentedline
- parsers.blankline)^0
@@ -2843,6 +2941,16 @@ parsers.bullet = ( parsers.bulletchar * #parsers.spacing
+ parsers.space * parsers.space * parsers.space
* parsers.bulletchar * #parsers.spacing
)
+
+local function tickbox(interior)
+ return parsers.optionalspace * parsers.lbracket
+ * interior * parsers.rbracket * parsers.spacechar^1
+end
+
+parsers.ticked_box = tickbox(S("xX")) * Cc(1.0)
+parsers.halfticked_box = tickbox(S("./")) * Cc(0.5)
+parsers.unticked_box = tickbox(parsers.spacechar^1) * Cc(0.0)
+
parsers.openticks = Cg(parsers.backtick^1, "ticks")
local function captures_equal_length(s,i,a,b)
@@ -3309,6 +3417,11 @@ parsers.BacktickFencedCode
* Cs(parsers.fencedline(parsers.backtick)^0)
* parsers.fencetail(parsers.backtick)
+parsers.JekyllFencedCode
+ = parsers.fencehead(parsers.dash)
+ * Cs(parsers.fencedline(parsers.dash)^0)
+ * parsers.fencetail(parsers.dash)
+
parsers.lineof = function(c)
return (parsers.leader * (P(c) * parsers.optionalspace)^3
* (parsers.newline * parsers.blankline^1
@@ -3797,6 +3910,19 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline
expandtabs(code))
end
+ larsers.JekyllData = P("---")
+ * parsers.blankline / 0
+ * #(-parsers.blankline) -- if followed by blank, it's an hrule
+ * C((parsers.line - P("---") - P("..."))^0)
+ * (P("---") + P("..."))
+ / function(text)
+ local tinyyaml = require("markdown-tinyyaml")
+ data = tinyyaml.parse(text)
+ return writer.jekyllData(data, function(s)
+ return parse_blocks(s)
+ end, nil)
+ end
+
larsers.Blockquote = Cs(larsers.blockquote_body^1)
/ parse_blocks_toplevel / writer.blockquote
@@ -3830,6 +3956,15 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline
/ writer.plain
larsers.starter = parsers.bullet + larsers.enumerator
+ if options.taskLists then
+ larsers.tickbox = ( parsers.ticked_box
+ + parsers.halfticked_box
+ + parsers.unticked_box
+ ) / writer.tickbox
+ else
+ larsers.tickbox = parsers.fail
+ end
+
-- we use \001 as a separator between a tight list item and a
-- nested list under it.
larsers.NestedList = Cs((parsers.optionallyindentedline
@@ -3847,14 +3982,14 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline
larsers.TightListItem = function(starter)
return -larsers.HorizontalRule
- * (Cs(starter / "" * larsers.ListBlock * larsers.NestedList^-1)
+ * (Cs(starter / "" * larsers.tickbox^-1 * larsers.ListBlock * larsers.NestedList^-1)
/ parse_blocks)
* -(parsers.blanklines * parsers.indent)
end
larsers.LooseListItem = function(starter)
return -larsers.HorizontalRule
- * Cs( starter / "" * larsers.ListBlock * Cc("\n")
+ * Cs( starter / "" * larsers.tickbox^-1 * larsers.ListBlock * Cc("\n")
* (larsers.NestedList + larsers.ListContinuationBlock^0)
* (parsers.blanklines / "\n\n")
) / parse_blocks
@@ -3981,7 +4116,10 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline
Blank = larsers.Blank,
+ JekyllData = larsers.JekyllData,
+
Block = V("ContentBlock")
+ + V("JekyllData")
+ V("Blockquote")
+ V("PipeTable")
+ V("Verbatim")
@@ -4105,8 +4243,8 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline
syntax.InlineNote = parsers.fail
end
- if not options.smartEllipses then
- syntax.Smart = parsers.fail
+ if not options.jekyllData then
+ syntax.JekyllData = parsers.fail
end
if options.preserveTabs then
@@ -4117,6 +4255,10 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline
syntax.PipeTable = parsers.fail
end
+ if not options.smartEllipses then
+ syntax.Smart = parsers.fail
+ end
+
local blocks_toplevel_t = util.table_copy(syntax)
blocks_toplevel_t.Paragraph = larsers.ToplevelParagraph
larsers.blocks_toplevel = Ct(blocks_toplevel_t)