summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/markdown/markdown.lua
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2019-04-05 21:09:01 +0000
committerKarl Berry <karl@freefriends.org>2019-04-05 21:09:01 +0000
commitd559ccaca60acb46c6a12c256ea2a1dcc867d0f8 (patch)
tree919f27f11992e782235c38a4f7d9a3b4fbb2edb2 /Master/texmf-dist/tex/luatex/markdown/markdown.lua
parent22e129ab927e016254a610d8682ea25095aacee6 (diff)
markdown (5apr19)
git-svn-id: svn://tug.org/texlive/trunk@50784 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/markdown/markdown.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/markdown/markdown.lua253
1 files changed, 207 insertions, 46 deletions
diff --git a/Master/texmf-dist/tex/luatex/markdown/markdown.lua b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
index 25d45c32da2..9614434b81f 100644
--- a/Master/texmf-dist/tex/luatex/markdown/markdown.lua
+++ b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
@@ -20,7 +20,7 @@
-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--
--- Copyright (C) 2018 Vít Novotný
+-- Copyright (C) 2016-2019 Vít Novotný
--
-- This work may be distributed and/or modified under the
-- conditions of the LaTeX Project Public License, either version 1.3
@@ -58,11 +58,11 @@
-- those in the standard .ins files.
--
local metadata = {
- version = "2.5.6",
+ version = "2.7.0",
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-2018 Vít Novotný"},
+ "2016-2019 Vít Novotný"},
license = "LPPL 1.3"
}
@@ -87,10 +87,12 @@ defaultOptions.definitionLists = false
defaultOptions.fencedCode = false
defaultOptions.footnotes = false
defaultOptions.hashEnumerators = false
+defaultOptions.headerAttributes = false
defaultOptions.html = false
defaultOptions.hybrid = false
defaultOptions.inlineFootnotes = false
defaultOptions.preserveTabs = false
+defaultOptions.slice = "^ $"
defaultOptions.smartEllipses = false
defaultOptions.startNumber = true
defaultOptions.tightLists = true
@@ -498,6 +500,31 @@ function M.writer.new(options)
options = options or {}
setmetatable(options, { __index = function (_, key)
return defaultOptions[key] end })
+ local slice_specifiers = {}
+ for specifier in options.slice:gmatch("[^%s]+") do
+ table.insert(slice_specifiers, specifier)
+ end
+
+ if #slice_specifiers == 2 then
+ self.slice_begin, self.slice_end = table.unpack(slice_specifiers)
+ local slice_begin_type = self.slice_begin:sub(1, 1)
+ if slice_begin_type ~= "^" and slice_begin_type ~= "$" then
+ self.slice_begin = "^" .. self.slice_begin
+ end
+ local slice_end_type = self.slice_end:sub(1, 1)
+ if slice_end_type ~= "^" and slice_end_type ~= "$" then
+ self.slice_end = "$" .. self.slice_end
+ end
+ elseif #slice_specifiers == 1 then
+ self.slice_begin = "^" .. slice_specifiers[1]
+ self.slice_end = "$" .. slice_specifiers[1]
+ end
+
+ if self.slice_begin == "^" and self.slice_end ~= "^" then
+ self.is_writing = true
+ else
+ self.is_writing = false
+ end
self.suffix = ".tex"
self.space = " "
self.nbsp = "\\markdownRendererNbsp{}"
@@ -505,16 +532,23 @@ function M.writer.new(options)
return s
end
function self.paragraph(s)
+ if not self.is_writing then return "" end
return s
end
function self.pack(name)
- return [[\input"]] .. name .. [["\relax{}]]
+ return [[\input ]] .. name .. [[\relax{}]]
+ end
+ function self.interblocksep()
+ if not self.is_writing then return "" end
+ return "\\markdownRendererInterblockSeparator\n{}"
end
- self.interblocksep = "\\markdownRendererInterblockSeparator\n{}"
self.eof = [[\relax]]
self.linebreak = "\\markdownRendererLineBreak\n{}"
self.ellipsis = "\\markdownRendererEllipsis{}"
- self.hrule = "\\markdownRendererHorizontalRule{}"
+ function self.hrule()
+ if not self.is_writing then return "" end
+ return "\\markdownRendererHorizontalRule{}"
+ end
local escaped_chars = {
["{"] = "\\markdownRendererLeftBrace{}",
["}"] = "\\markdownRendererRightBrace{}",
@@ -572,30 +606,31 @@ function M.writer.new(options)
"{",self.uri(src),"}",
"{",self.string(tit or ""),"}"}
end
-local languages_json = (function()
- local kpse = require("kpse")
- kpse.set_program_name("luatex")
- local base, prev, curr
- for _, file in ipairs{kpse.lookup(options.contentBlocksLanguageMap,
- { all=true })} do
- json = io.open(file, "r"):read("*all")
- :gsub('("[^\n]-"):','[%1]=')
- curr = (function()
- local _ENV={ json=json, load=load } -- run in sandbox
- return load("return "..json)()
- end)()
- if type(curr) == "table" then
- if base == nil then
- base = curr
- else
- setmetatable(prev, { __index = curr })
+ local languages_json = (function()
+ local kpse = require("kpse")
+ kpse.set_program_name("luatex")
+ local base, prev, curr
+ for _, file in ipairs{kpse.lookup(options.contentBlocksLanguageMap,
+ { all=true })} do
+ json = io.open(file, "r"):read("*all")
+ :gsub('("[^\n]-"):','[%1]=')
+ curr = (function()
+ local _ENV={ json=json, load=load } -- run in sandbox
+ return load("return "..json)()
+ end)()
+ if type(curr) == "table" then
+ if base == nil then
+ base = curr
+ else
+ setmetatable(prev, { __index = curr })
+ end
+ prev = curr
end
- prev = curr
end
- end
- return base or {}
-end)()
+ return base or {}
+ end)()
function self.contentblock(src,suf,type,tit)
+ if not self.is_writing then return "" end
src = src.."."..suf
suf = suf:lower()
if type == "onlineimage" then
@@ -622,6 +657,7 @@ end)()
end
function self.bulletlist(items,tight)
+ if not self.is_writing then return "" end
local buffer = {}
for _,item in ipairs(items) do
buffer[#buffer + 1] = ulitem(item)
@@ -646,6 +682,7 @@ end)()
end
function self.orderedlist(items,tight,startnum)
+ if not self.is_writing then return "" end
local buffer = {}
local num = startnum
for _,item in ipairs(items) do
@@ -676,6 +713,7 @@ end)()
end
function self.definitionlist(items,tight)
+ if not self.is_writing then return "" end
local buffer = {}
for _,item in ipairs(items) do
buffer[#buffer + 1] = dlitem(item.term, item.definitions)
@@ -695,18 +733,66 @@ end)()
return {"\\markdownRendererStrongEmphasis{",s,"}"}
end
function self.blockquote(s)
+ if #util.rope_to_string(s) == 0 then return "" end
return {"\\markdownRendererBlockQuoteBegin\n",s,
"\n\\markdownRendererBlockQuoteEnd "}
end
function self.verbatim(s)
+ if not self.is_writing then return "" end
local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
return {"\\markdownRendererInputVerbatim{",name,"}"}
end
function self.fencedCode(i, s)
+ if not self.is_writing then return "" end
local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
return {"\\markdownRendererInputFencedCode{",name,"}{",i,"}"}
end
- function self.heading(s,level)
+ self.active_headings = {}
+ function self.heading(s,level,attributes)
+ local active_headings = self.active_headings
+ local slice_begin_type = self.slice_begin:sub(1, 1)
+ local slice_begin_identifier = self.slice_begin:sub(2) or ""
+ local slice_end_type = self.slice_end:sub(1, 1)
+ local slice_end_identifier = self.slice_end:sub(2) or ""
+
+ while #active_headings < level do
+ -- push empty identifiers for implied sections
+ table.insert(active_headings, {})
+ end
+
+ while #active_headings >= level do
+ -- pop identifiers for sections that have ended
+ local active_identifiers = active_headings[#active_headings]
+ if active_identifiers[slice_begin_identifier] ~= nil
+ and slice_begin_type == "$" then
+ self.is_writing = true
+ end
+ if active_identifiers[slice_end_identifier] ~= nil
+ and slice_end_type == "$" then
+ self.is_writing = false
+ end
+ table.remove(active_headings, #active_headings)
+ end
+
+ -- push identifiers for the new section
+ attributes = attributes or {}
+ local identifiers = {}
+ for index = 1, #attributes do
+ attribute = attributes[index]
+ identifiers[attribute:sub(2)] = true
+ end
+ if identifiers[slice_begin_identifier] ~= nil
+ and slice_begin_type == "^" then
+ self.is_writing = true
+ end
+ if identifiers[slice_end_identifier] ~= nil
+ and slice_end_type == "^" then
+ self.is_writing = false
+ end
+ table.insert(active_headings, identifiers)
+
+ if not self.is_writing then return "" end
+
local cmd
if level == 1 then
cmd = "\\markdownRendererHeadingOne"
@@ -761,6 +847,8 @@ parsers.lparent = P("(")
parsers.rparent = P(")")
parsers.lbracket = P("[")
parsers.rbracket = P("]")
+parsers.lbrace = P("{")
+parsers.rbrace = P("}")
parsers.circumflex = P("^")
parsers.slash = P("/")
parsers.equal = P("=")
@@ -827,6 +915,22 @@ parsers.nonemptyline = parsers.line - parsers.blankline
parsers.chunk = parsers.line * (parsers.optionallyindentedline
- parsers.blankline)^0
+parsers.css_identifier_char = R("AZ", "az", "09") + S("-_")
+parsers.css_identifier = (parsers.hash + parsers.period)
+ * (((parsers.css_identifier_char
+ - parsers.dash - parsers.digit)
+ * parsers.css_identifier_char^1)
+ + (parsers.dash
+ * (parsers.css_identifier_char
+ - parsers.digit)
+ * parsers.css_identifier_char^0))
+parsers.attribute_name_char = parsers.any - parsers.space
+ - parsers.squote - parsers.dquote
+ - parsers.more - parsers.slash
+ - parsers.equal
+parsers.attribute_value_char = parsers.any - parsers.dquote
+ - parsers.more
+
-- block followed by 0 or more optionally
-- indented blocks with first line indented.
parsers.indented_blocks = function(bl)
@@ -1063,9 +1167,8 @@ parsers.citation_body_postnote
parsers.citation_body_chunk
= parsers.citation_body_prenote
* parsers.spnl * parsers.citation_name
- * ((parsers.internal_punctuation - parsers.semicolon)
- * parsers.spnl)^-1
- * parsers.citation_body_postnote
+ * (parsers.internal_punctuation - parsers.semicolon)^-1
+ * parsers.spnl * parsers.citation_body_postnote
parsers.citation_body
= parsers.citation_body_chunk
@@ -1255,6 +1358,18 @@ parsers.defstart = ( parsers.defstartchar * #parsers.spacing
)
parsers.dlchunk = Cs(parsers.line * (parsers.indentedline - parsers.blankline)^0)
+parsers.heading_attribute = C(parsers.css_identifier)
+ + C((parsers.attribute_name_char
+ - parsers.rbrace)^1
+ * parsers.equal
+ * (parsers.attribute_value_char
+ - parsers.rbrace)^1)
+parsers.HeadingAttributes = parsers.lbrace
+ * parsers.heading_attribute
+ * (parsers.spacechar^1
+ * parsers.heading_attribute)^0
+ * parsers.rbrace
+
-- parse Atx heading start and return level
parsers.HeadingStart = #parsers.hash * C(parsers.hash^-6)
* -parsers.hash / length
@@ -1721,6 +1836,9 @@ function M.reader.new(writer, options)
local function ordered_list(items,tight,startNumber)
if options.startNumber then
startNumber = tonumber(startNumber) or 1 -- fallback for '#'
+ if startNumber ~= nil then
+ startNumber = math.floor(startNumber)
+ end
else
startNumber = nil
end
@@ -1761,27 +1879,70 @@ function M.reader.new(writer, options)
+ larsers.Reference
+ (parsers.tightblocksep / "\n")
-- parse atx header
- larsers.AtxHeading = Cg(parsers.HeadingStart,"level")
- * parsers.optionalspace
- * (C(parsers.line) / strip_atx_end / parse_inlines)
- * Cb("level")
- / writer.heading
-
- -- parse setext header
- larsers.SetextHeading = #(parsers.line * S("=-"))
- * Ct(parsers.line / parse_inlines)
- * parsers.HeadingLevel
- * parsers.optionalspace * parsers.newline
- / writer.heading
+ if options.headerAttributes then
+ larsers.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)
+ / parse_inlines)
+ * Cg(Ct(parsers.newline
+ + (parsers.hash^1
+ * parsers.optionalspace
+ * parsers.HeadingAttributes^-1
+ + parsers.HeadingAttributes)
+ * parsers.optionalspace
+ * parsers.newline), "attributes")
+ * Cb("level")
+ * Cb("attributes")
+ / writer.heading
+
+ larsers.SetextHeading = #(parsers.line * S("=-"))
+ * (C(((parsers.linechar
+ - (parsers.HeadingAttributes
+ * parsers.optionalspace
+ * parsers.newline))
+ * (parsers.linechar
+ - parsers.lbrace)^0)^1)
+ / parse_inlines)
+ * Cg(Ct(parsers.newline
+ + (parsers.HeadingAttributes
+ * parsers.optionalspace
+ * parsers.newline)), "attributes")
+ * parsers.HeadingLevel
+ * Cb("attributes")
+ * parsers.optionalspace
+ * parsers.newline
+ / writer.heading
+ else
+ larsers.AtxHeading = Cg(parsers.HeadingStart,"level")
+ * parsers.optionalspace
+ * (C(parsers.line) / strip_atx_end / parse_inlines)
+ * Cb("level")
+ / writer.heading
+
+ larsers.SetextHeading = #(parsers.line * S("=-"))
+ * Ct(parsers.linechar^1 / parse_inlines)
+ * parsers.newline
+ * parsers.HeadingLevel
+ * parsers.optionalspace
+ * parsers.newline
+ / writer.heading
+ end
larsers.Heading = larsers.AtxHeading + larsers.SetextHeading
local syntax =
{ "Blocks",
Blocks = larsers.Blank^0 * parsers.Block^-1
- * (larsers.Blank^0 / function()
- return writer.interblocksep
- end
+ * (larsers.Blank^0 / writer.interblocksep
* parsers.Block)^0
* larsers.Blank^0 * parsers.eof,