summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/markdown
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2022-10-31 19:44:45 +0000
committerKarl Berry <karl@freefriends.org>2022-10-31 19:44:45 +0000
commitb85211b0d457e8ea4625ba00efe5133ba6f42350 (patch)
tree5fe5a427c680f122e0292cfd107fbdea47125f90 /Master/texmf-dist/tex/luatex/markdown
parent32a5e5c9e3c474a4be7e4ea8ab3101d0d6f208fe (diff)
markdown (31oct22)
git-svn-id: svn://tug.org/texlive/trunk@64879 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/markdown')
-rw-r--r--Master/texmf-dist/tex/luatex/markdown/markdown.lua343
1 files changed, 187 insertions, 156 deletions
diff --git a/Master/texmf-dist/tex/luatex/markdown/markdown.lua b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
index 9ad26df6dbe..3afe0a924d4 100644
--- a/Master/texmf-dist/tex/luatex/markdown/markdown.lua
+++ b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
@@ -58,7 +58,7 @@
-- those in the standard .ins files.
--
local metadata = {
- version = "2.17.1-0-g8ca83f5",
+ version = "2.18.0-0-gd8ae860",
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",
@@ -83,7 +83,7 @@ local walkable_syntax = {
Block = {
"Blockquote",
"Verbatim",
- "HorizontalRule",
+ "ThematicBreak",
"BulletList",
"OrderedList",
"Heading",
@@ -128,13 +128,14 @@ defaultOptions.debugExtensions = false
defaultOptions.definitionLists = false
defaultOptions.eagerCache = true
metadata.user_extension_api_version = 2
-metadata.grammar_version = 1
+metadata.grammar_version = 2
defaultOptions.extensions = {}
defaultOptions.expectJekyllData = false
defaultOptions.fancyLists = false
defaultOptions.fencedCode = false
defaultOptions.finalizeCache = false
defaultOptions.footnotes = false
+defaultOptions.notes = false
defaultOptions.frozenCacheCounter = 0
defaultOptions.hardLineBreaks = false
defaultOptions.hashEnumerators = false
@@ -142,9 +143,11 @@ defaultOptions.headerAttributes = false
defaultOptions.html = false
defaultOptions.hybrid = false
defaultOptions.inlineFootnotes = false
+defaultOptions.inlineNotes = false
defaultOptions.jekyllData = false
defaultOptions.pipeTables = false
defaultOptions.preserveTabs = false
+defaultOptions.rawAttribute = true
defaultOptions.relativeReferences = false
defaultOptions.shiftHeadings = 0
defaultOptions.slice = "^ $"
@@ -185,6 +188,11 @@ function util.cache(dir, string, salt, transform, suffix)
end
return name
end
+function util.cache_verbatim(dir, string)
+ string = string:gsub('[\r\n%s]*$', '')
+ local name = util.cache(dir, string, nil, nil, ".verbatim")
+ return name
+end
function util.table_copy(t)
local u = { }
for k, v in pairs(t) do u[k] = v end
@@ -2408,9 +2416,9 @@ function M.writer.new(options)
end
self.linebreak = "\\markdownRendererLineBreak\n{}"
self.ellipsis = "\\markdownRendererEllipsis{}"
- function self.hrule()
+ function self.thematic_break()
if not self.is_writing then return "" end
- return "\\markdownRendererHorizontalRule{}"
+ return "\\markdownRendererThematicBreak{}"
end
self.escaped_uri_chars = {
["{"] = "\\markdownRendererLeftBrace{}",
@@ -2547,8 +2555,7 @@ function M.writer.new(options)
end
function self.verbatim(s)
if not self.is_writing then return "" end
- s = string.gsub(s, '[\r\n%s]*$', '')
- local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
+ local name = util.cache_verbatim(options.cacheDir, s)
return {"\\markdownRendererInputVerbatim{",name,"}"}
end
function self.document(d)
@@ -2851,6 +2858,20 @@ parsers.attribute_value = ( (parsers.dquote / "")
+ ( parsers.anyescaped - parsers.dquote - parsers.rbrace
- parsers.space)^0
+parsers.attribute = (parsers.dash * Cc(".unnumbered"))
+ + C((parsers.hash + parsers.period)
+ * parsers.attribute_key)
+ + Cs( parsers.attribute_key
+ * parsers.optionalspace * parsers.equal * parsers.optionalspace
+ * parsers.attribute_value)
+parsers.attributes = parsers.lbrace
+ * parsers.optionalspace
+ * parsers.attribute
+ * (parsers.spacechar^1
+ * parsers.attribute)^0
+ * parsers.optionalspace
+ * parsers.rbrace
+
-- block followed by 0 or more optionally
-- indented blocks with first line indented.
parsers.indented_blocks = function(bl)
@@ -2901,8 +2922,8 @@ local function captures_geq_length(_,i,a,b)
return #a >= #b and i
end
-parsers.infostring = (parsers.linechar - (parsers.backtick
- + parsers.space^1 * (parsers.newline + parsers.eof)))^0
+parsers.infostring = (parsers.linechar - (parsers.backtick
+ + parsers.space^1 * (parsers.newline + parsers.eof)))^0
local fenceindent
parsers.fencehead = function(char)
@@ -3123,31 +3144,27 @@ parsers.between = function(p, starter, ender)
end
parsers.urlchar = parsers.anyescaped - parsers.newline - parsers.more
+parsers.TildeFencedCode
+ = parsers.fencehead(parsers.tilde)
+ * Cs(parsers.fencedline(parsers.tilde)^0)
+ * parsers.fencetail(parsers.tilde)
+
+parsers.BacktickFencedCode
+ = parsers.fencehead(parsers.backtick)
+ * Cs(parsers.fencedline(parsers.backtick)^0)
+ * parsers.fencetail(parsers.backtick)
+
parsers.lineof = function(c)
return (parsers.leader * (P(c) * parsers.optionalspace)^3
* (parsers.newline * parsers.blankline^1
+ parsers.newline^-1 * parsers.eof))
end
-parsers.heading_attribute = (parsers.dash * Cc(".unnumbered"))
- + C((parsers.hash + parsers.period)
- * parsers.attribute_key)
- + Cs( parsers.attribute_key
- * parsers.optionalspace * parsers.equal * parsers.optionalspace
- * parsers.attribute_value)
-parsers.HeadingAttributes = parsers.lbrace
- * parsers.optionalspace
- * parsers.heading_attribute
- * (parsers.spacechar^1
- * parsers.heading_attribute)^0
- * parsers.optionalspace
- * parsers.rbrace
-
-- parse Atx heading start and return level
-parsers.HeadingStart = #parsers.hash * C(parsers.hash^-6)
- * -parsers.hash / length
+parsers.heading_start = #parsers.hash * C(parsers.hash^-6)
+ * -parsers.hash / length
-- parse setext header ending and return level
-parsers.HeadingLevel = parsers.equal^1 * Cc(1) + parsers.dash^1 * Cc(2)
+parsers.heading_level = parsers.equal^1 * Cc(1) + parsers.dash^1 * Cc(2)
local function strip_atx_end(s)
return s:gsub("[#%s]*\n$","")
@@ -3207,8 +3224,8 @@ function M.reader.new(writer, options)
str = str:gsub('^' .. min_prefix, '')
end
if toplevel and (options.texComments or options.hybrid) then
- str = lpeg.match(Ct(parsers.commented_line^1), str)
- str = util.rope_to_string(str)
+ str = lpeg.match(Ct(parsers.commented_line^1), str)
+ str = util.rope_to_string(str)
end
local res = lpeg.match(grammar(), str)
if res == nil then
@@ -3521,10 +3538,10 @@ function M.reader.new(writer, options)
/ self.parser_functions.parse_blocks_nested
/ writer.blockquote
- parsers.HorizontalRule = ( parsers.lineof(parsers.asterisk)
- + parsers.lineof(parsers.dash)
- + parsers.lineof(parsers.underscore)
- ) / writer.hrule
+ parsers.ThematicBreak = ( parsers.lineof(parsers.asterisk)
+ + parsers.lineof(parsers.dash)
+ + parsers.lineof(parsers.underscore)
+ ) / writer.thematic_break
parsers.Reference = parsers.define_reference_parser / register_link
@@ -3567,14 +3584,14 @@ function M.reader.new(writer, options)
* parsers.ListBlock
parsers.TightListItem = function(starter)
- return -parsers.HorizontalRule
+ return -parsers.ThematicBreak
* (Cs(starter / "" * parsers.tickbox^-1 * parsers.ListBlock * parsers.NestedList^-1)
/ self.parser_functions.parse_blocks_nested)
* -(parsers.blanklines * parsers.indent)
end
parsers.LooseListItem = function(starter)
- return -parsers.HorizontalRule
+ return -parsers.ThematicBreak
* Cs( starter / "" * parsers.tickbox^-1 * parsers.ListBlock * Cc("\n")
* (parsers.NestedList + parsers.ListContinuationBlock^0)
* (parsers.blanklines / "\n\n")
@@ -3611,7 +3628,7 @@ function M.reader.new(writer, options)
+ parsers.Reference
+ (parsers.tightblocksep / "\n")
-- parse atx header
- parsers.AtxHeading = Cg(parsers.HeadingStart,"level")
+ parsers.AtxHeading = Cg(parsers.heading_start, "level")
* parsers.optionalspace
* (C(parsers.line)
/ strip_atx_end
@@ -3623,7 +3640,7 @@ function M.reader.new(writer, options)
* Ct(parsers.linechar^1
/ self.parser_functions.parse_inlines)
* parsers.newline
- * parsers.HeadingLevel
+ * parsers.heading_level
* parsers.optionalspace
* parsers.newline
/ writer.heading
@@ -3696,7 +3713,7 @@ function M.reader.new(writer, options)
Blockquote = parsers.Blockquote,
Verbatim = parsers.Verbatim,
- HorizontalRule = parsers.HorizontalRule,
+ ThematicBreak = parsers.ThematicBreak,
BulletList = parsers.BulletList,
OrderedList = parsers.OrderedList,
Heading = parsers.Heading,
@@ -4285,74 +4302,22 @@ M.extensions.fenced_code = function(blank_before_code_fence)
extend_writer = function(self)
local options = self.options
- function self.fencedCode(i, s)
+ function self.fencedCode(s, i)
if not self.is_writing then return "" end
- s = string.gsub(s, '[\r\n%s]*$', '')
- local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
- return {"\\markdownRendererInputFencedCode{",name,"}{",i,"}"}
+ local name = util.cache_verbatim(options.cacheDir, s)
+ return {"\\markdownRendererInputFencedCode{",
+ name,"}{",self.string(i),"}"}
end
end, extend_reader = function(self)
local parsers = self.parsers
local writer = self.writer
- local function captures_geq_length(_,i,a,b)
- return #a >= #b and i
- end
-
- local infostring = (parsers.linechar - (parsers.backtick
- + parsers.space^1 * (parsers.newline + parsers.eof)))^0
-
- local fenceindent
- local fencehead = function(char)
- return C(parsers.nonindentspace) / function(s) fenceindent = #s end
- * Cg(char^3, "fencelength")
- * parsers.optionalspace * C(infostring)
- * parsers.optionalspace * (parsers.newline + parsers.eof)
- end
-
- local fencetail = function(char)
- return parsers.nonindentspace
- * Cmt(C(char^3) * Cb("fencelength"), captures_geq_length)
- * parsers.optionalspace * (parsers.newline + parsers.eof)
- + parsers.eof
- end
-
- local fencedline = function(char)
- return C(parsers.line - fencetail(char))
- / function(s)
- local i = 1
- local remaining = fenceindent
- while true do
- local c = s:sub(i, i)
- if c == " " and remaining > 0 then
- remaining = remaining - 1
- i = i + 1
- elseif c == "\t" and remaining > 3 then
- remaining = remaining - 4
- i = i + 1
- else
- break
- end
- end
- return s:sub(i)
- end
- end
-
- local TildeFencedCode
- = fencehead(parsers.tilde)
- * Cs(fencedline(parsers.tilde)^0)
- * fencetail(parsers.tilde)
-
- local BacktickFencedCode
- = fencehead(parsers.backtick)
- * Cs(fencedline(parsers.backtick)^0)
- * fencetail(parsers.backtick)
-
- local FencedCode = (TildeFencedCode
- + BacktickFencedCode)
+ local FencedCode = (parsers.TildeFencedCode
+ + parsers.BacktickFencedCode)
/ function(infostring, code)
- return writer.fencedCode(writer.string(infostring),
- self.expandtabs(code))
+ local expanded_code = self.expandtabs(code)
+ return writer.fencedCode(expanded_code,
+ infostring)
end
self.insert_pattern("Block after Verbatim",
@@ -4362,8 +4327,8 @@ M.extensions.fenced_code = function(blank_before_code_fence)
if blank_before_code_fence then
fencestart = parsers.fail
else
- fencestart = fencehead(parsers.backtick)
- + fencehead(parsers.tilde)
+ fencestart = parsers.fencehead(parsers.backtick)
+ + parsers.fencehead(parsers.tilde)
end
local EndlineExceptions = parsers.EndlineExceptions + fencestart
@@ -4373,19 +4338,19 @@ M.extensions.fenced_code = function(blank_before_code_fence)
end
}
end
-M.extensions.footnotes = function(footnotes, inline_footnotes)
- assert(footnotes or inline_footnotes)
+M.extensions.notes = function(notes, inline_notes)
+ assert(notes or inline_notes)
return {
- name = "built-in footnotes syntax extension",
+ name = "built-in notes syntax extension",
extend_writer = function(self)
function self.note(s)
- return {"\\markdownRendererFootnote{",s,"}"}
+ return {"\\markdownRendererNote{",s,"}"}
end
end, extend_reader = function(self)
local parsers = self.parsers
local writer = self.writer
- if inline_footnotes then
+ if inline_notes then
local InlineNote
= parsers.circumflex
* (parsers.tag / self.parser_functions.parse_inlines_no_inline_note)
@@ -4394,7 +4359,7 @@ M.extensions.footnotes = function(footnotes, inline_footnotes)
self.insert_pattern("Inline after Emph",
InlineNote, "InlineNote")
end
- if footnotes then
+ if notes then
local function strip_first_char(s)
return s:sub(2)
end
@@ -4450,49 +4415,49 @@ M.extensions.header_attributes = function()
local parsers = self.parsers
local writer = self.writer
- parsers.AtxHeading = Cg(parsers.HeadingStart,"level")
- * parsers.optionalspace
- * (C(((parsers.linechar
- - ((parsers.hash^1
- * parsers.optionalspace
- * parsers.HeadingAttributes^-1
- + parsers.HeadingAttributes)
- * parsers.optionalspace
- * parsers.newline))
- * (parsers.linechar
- - parsers.hash
- - parsers.lbrace)^0)^1)
- / self.parser_functions.parse_inlines)
- * Cg(Ct(parsers.newline
- + (parsers.hash^1
- * parsers.optionalspace
- * parsers.HeadingAttributes^-1
- + parsers.HeadingAttributes)
+ local AtxHeading = Cg(parsers.heading_start, "level")
+ * parsers.optionalspace
+ * (C(((parsers.linechar
+ - ((parsers.hash^1
* parsers.optionalspace
- * parsers.newline), "attributes")
- * Cb("level")
- * Cb("attributes")
- / writer.heading
-
- parsers.SetextHeading = #(parsers.line * S("=-"))
- * (C(((parsers.linechar
- - (parsers.HeadingAttributes
- * parsers.optionalspace
- * parsers.newline))
- * (parsers.linechar
- - parsers.lbrace)^0)^1)
- / self.parser_functions.parse_inlines)
- * Cg(Ct(parsers.newline
- + (parsers.HeadingAttributes
- * parsers.optionalspace
- * parsers.newline)), "attributes")
- * parsers.HeadingLevel
- * Cb("attributes")
- * parsers.optionalspace
- * parsers.newline
- / writer.heading
-
- local Heading = parsers.AtxHeading + parsers.SetextHeading
+ * parsers.attributes^-1
+ + parsers.attributes)
+ * parsers.optionalspace
+ * parsers.newline))
+ * (parsers.linechar
+ - parsers.hash
+ - parsers.lbrace)^0)^1)
+ / self.parser_functions.parse_inlines)
+ * Cg(Ct(parsers.newline
+ + (parsers.hash^1
+ * parsers.optionalspace
+ * parsers.attributes^-1
+ + parsers.attributes)
+ * parsers.optionalspace
+ * parsers.newline), "attributes")
+ * Cb("level")
+ * Cb("attributes")
+ / writer.heading
+
+ local SetextHeading = #(parsers.line * S("=-"))
+ * (C(((parsers.linechar
+ - (parsers.attributes
+ * parsers.optionalspace
+ * parsers.newline))
+ * (parsers.linechar
+ - parsers.lbrace)^0)^1)
+ / self.parser_functions.parse_inlines)
+ * Cg(Ct(parsers.newline
+ + (parsers.attributes
+ * parsers.optionalspace
+ * parsers.newline)), "attributes")
+ * parsers.heading_level
+ * Cb("attributes")
+ * parsers.optionalspace
+ * parsers.newline
+ / writer.heading
+
+ local Heading = AtxHeading + SetextHeading
self.update_rule("Heading", Heading)
end
}
@@ -4608,14 +4573,14 @@ M.extensions.jekyll_data = function(expect_jekyll_data)
local UnexpectedJekyllData
= P("---")
* parsers.blankline / 0
- * #(-parsers.blankline) -- if followed by blank, it's an hrule
+ * #(-parsers.blankline) -- if followed by blank, it's thematic break
* JekyllData
* (P("---") + P("..."))
local ExpectedJekyllData
= ( P("---")
* parsers.blankline / 0
- * #(-parsers.blankline) -- if followed by blank, it's an hrule
+ * #(-parsers.blankline) -- if followed by blank, it's thematic break
)^-1
* JekyllData
* (P("---") + P("..."))^-1
@@ -4769,6 +4734,65 @@ M.extensions.pipe_tables = function(table_captions)
end
}
end
+M.extensions.raw_attribute = function()
+ return {
+ name = "built-in raw_attribute syntax extension",
+ extend_writer = function(self)
+ local options = self.options
+
+ function self.rawInline(s, attr)
+ if not self.is_writing then return "" end
+ local name = util.cache_verbatim(options.cacheDir, s)
+ return {"\\markdownRendererInputRawInline{",
+ name,"}{", self.string(attr),"}"}
+ end
+
+ if options.fencedCode then
+ function self.rawBlock(s, attr)
+ if not self.is_writing then return "" end
+ local name = util.cache_verbatim(options.cacheDir, s)
+ return {"\\markdownRendererInputRawBlock{",
+ name,"}{", self.string(attr),"}"}
+ end
+ end
+ end, extend_reader = function(self)
+ local options = self.options
+ local writer = self.writer
+
+ local raw_attribute = parsers.lbrace
+ * parsers.optionalspace
+ * parsers.equal
+ * C(parsers.attribute_key)
+ * parsers.optionalspace
+ * parsers.rbrace
+
+ local RawInline = parsers.inticks
+ * raw_attribute
+ / writer.rawInline
+
+ self.insert_pattern("Inline before Code",
+ RawInline, "RawInline")
+
+ if options.fencedCode then
+ local RawBlock = (parsers.TildeFencedCode
+ + parsers.BacktickFencedCode)
+ / function(infostring, code)
+ local expanded_code = self.expandtabs(code)
+ local attr = lpeg.match(raw_attribute, infostring)
+ if attr then
+ return writer.rawBlock(expanded_code, attr)
+ else
+ return writer.fencedCode(expanded_code,
+ infostring)
+ end
+ end
+
+ self.insert_pattern("Block after Verbatim",
+ RawBlock, "RawBlock")
+ end
+ end
+ }
+end
M.extensions.strike_through = function()
return {
name = "built-in strike_through syntax extension",
@@ -4906,14 +4930,14 @@ M.extensions.fancy_lists = function()
* ListBlock
local TightListItem = function(starter)
- return -parsers.HorizontalRule
+ return -parsers.ThematicBreak
* (Cs(starter / "" * parsers.tickbox^-1 * ListBlock * NestedList^-1)
/ self.parser_functions.parse_blocks_nested)
* -(parsers.blanklines * parsers.indent)
end
local LooseListItem = function(starter)
- return -parsers.HorizontalRule
+ return -parsers.ThematicBreak
* Cs( starter / "" * parsers.tickbox^-1 * ListBlock * Cc("\n")
* (NestedList + ListContinuationBlock^0)
* (parsers.blanklines / "\n\n")
@@ -5034,6 +5058,11 @@ function M.new(options)
table.insert(extensions, pipe_tables_extension)
end
+ if options.rawAttribute then
+ local raw_attribute_extension = M.extensions.raw_attribute()
+ table.insert(extensions, raw_attribute_extension)
+ end
+
if options.strikeThrough then
local strike_through_extension = M.extensions.strike_through()
table.insert(extensions, strike_through_extension)
@@ -5049,10 +5078,12 @@ function M.new(options)
table.insert(extensions, superscript_extension)
end
- if options.footnotes or options.inlineFootnotes then
- local footnotes_extension = M.extensions.footnotes(
- options.footnotes, options.inlineFootnotes)
- table.insert(extensions, footnotes_extension)
+ if options.footnotes or options.inlineFootnotes or
+ options.notes or options.inlineNotes then
+ local notes_extension = M.extensions.notes(
+ options.footnotes or options.notes,
+ options.inlineFootnotes or options.inlineNotes)
+ table.insert(extensions, notes_extension)
end
if options.citations then