diff options
author | Karl Berry <karl@freefriends.org> | 2022-03-01 21:48:37 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-03-01 21:48:37 +0000 |
commit | 079a61be47724dece2e21f4c6c3259207da5bc65 (patch) | |
tree | f1e66dd422de438fc8aea3194527491f4afa0e44 /Master/texmf-dist/tex/luatex | |
parent | cd83186b6a2e004ec7ca663b8ee2013ffdfbf78e (diff) |
markdown (1mar22)
git-svn-id: svn://tug.org/texlive/trunk@62316 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex')
-rw-r--r-- | Master/texmf-dist/tex/luatex/markdown/markdown.lua | 196 |
1 files changed, 147 insertions, 49 deletions
diff --git a/Master/texmf-dist/tex/luatex/markdown/markdown.lua b/Master/texmf-dist/tex/luatex/markdown/markdown.lua index aac73da3c9f..161a0d39a29 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) 2016-2021 Vít Novotný +-- Copyright (C) 2016-2022 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.13.0-0-g1f680a8", + version = "2.14.0-0-g9635d76", 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ý"}, + "2016-2022 Vít Novotný"}, license = "LPPL 1.3c" } @@ -102,6 +102,7 @@ defaultOptions.inlineFootnotes = false defaultOptions.jekyllData = false defaultOptions.pipeTables = false defaultOptions.preserveTabs = false +defaultOptions.relativeReferences = false defaultOptions.shiftHeadings = 0 defaultOptions.slice = "^ $" defaultOptions.smartEllipses = false @@ -2527,15 +2528,28 @@ function M.writer.new(options) local contents = util.intersperse(buffer,"\n") if tight and options.tightLists then return {"\\markdownRendererOlBeginTight\n",contents, - "\n\\markdownRendererOlEndTight "} + "\n\\markdownRendererOlEndTight "} else return {"\\markdownRendererOlBegin\n",contents, - "\n\\markdownRendererOlEnd "} + "\n\\markdownRendererOlEnd "} end end function self.inline_html_comment(contents) return {"\\markdownRendererInlineHtmlComment{",contents,"}"} end + function self.block_html_comment(contents) + if not self.is_writing then return "" end + return {"\\markdownRendererBlockHtmlCommentBegin\n",contents, + "\n\\markdownRendererBlockHtmlCommentEnd "} + end + function self.inline_html_tag(contents) + return {"\\markdownRendererInlineHtmlTag{",self.string(contents),"}"} + end + function self.block_html_element(s) + if not self.is_writing then return "" end + local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim") + return {"\\markdownRendererInputBlockHtmlElement{",name,"}"} + end local function dlitem(term, defs) local retVal = {"\\markdownRendererDlItem{",term,"}"} for _, def in ipairs(defs) do @@ -2593,8 +2607,23 @@ function M.writer.new(options) return {"\\markdownRendererInputFencedCode{",name,"}{",i,"}"} end function self.document(d) - return {"\\markdownRendererDocumentBegin\n", d, - "\\markdownRendererDocumentEnd"} + local active_attributes = self.active_attributes + local buf = {"\\markdownRendererDocumentBegin\n", d} + + -- pop attributes for sections that have ended + if options.headerAttributes and self.is_writing then + while #active_attributes > 0 do + local attributes = active_attributes[#active_attributes] + if #attributes > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextEnd") + end + table.remove(active_attributes, #active_attributes) + end + end + + table.insert(buf, "\\markdownRendererDocumentEnd") + + return buf end function self.jekyllData(d, t, p) if not self.is_writing then return "" end @@ -2678,51 +2707,100 @@ function M.writer.new(options) return buf end - self.active_headings = {} - function self.heading(s,level,attributes) - local active_headings = self.active_headings + self.active_attributes = {} + function self.heading(s, level, attributes) + attributes = attributes or {} + for i = 1, #attributes do + attributes[attributes[i]] = true + end + + local active_attributes = self.active_attributes 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, {}) + local buf = {} + + -- push empty attributes for implied sections + while #active_attributes < level-1 do + table.insert(active_attributes, {}) 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 + -- pop attributes for sections that have ended + while #active_attributes >= level do + local active_identifiers = active_attributes[#active_attributes] + -- tear down all active attributes at slice end + if active_identifiers["#" .. slice_end_identifier] ~= nil + and slice_end_type == "$" then + for header_level = #active_attributes, 1, -1 do + if options.headerAttributes and #active_attributes[header_level] > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextEnd") + end + end + self.is_writing = false + end + table.remove(active_attributes, #active_attributes) + if self.is_writing and options.headerAttributes and #active_identifiers > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextEnd") + end + -- apply all active attributes at slice beginning + if active_identifiers["#" .. slice_begin_identifier] ~= nil and slice_begin_type == "$" then + for header_level = 1, #active_attributes do + if options.headerAttributes and #active_attributes[header_level] > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextBegin") + end + end self.is_writing = true end - if active_identifiers[slice_end_identifier] ~= nil - and slice_end_type == "$" then - self.is_writing = false + end + + -- tear down all active attributes at slice end + if attributes["#" .. slice_end_identifier] ~= nil + and slice_end_type == "^" then + for header_level = #active_attributes, 1, -1 do + if options.headerAttributes and #active_attributes[header_level] > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextEnd") + end end - table.remove(active_headings, #active_headings) + self.is_writing = false 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 + -- push attributes for the new section + table.insert(active_attributes, attributes) + if self.is_writing and options.headerAttributes and #attributes > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextBegin") end - if identifiers[slice_begin_identifier] ~= nil + + -- apply all active attributes at slice beginning + if attributes["#" .. slice_begin_identifier] ~= nil and slice_begin_type == "^" then + for header_level = 1, #active_attributes do + if options.headerAttributes and #active_attributes[header_level] > 0 then + table.insert(buf, "\\markdownRendererHeaderAttributeContextBegin") + end + end 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 + if self.is_writing then + table.sort(attributes) + local key, value + for i = 1, #attributes do + if attributes[i]:sub(1, 1) == "#" then + table.insert(buf, {"\\markdownRendererAttributeIdentifier{", + attributes[i]:sub(2), "}"}) + elseif attributes[i]:sub(1, 1) == "." then + table.insert(buf, {"\\markdownRendererAttributeClassName{", + attributes[i]:sub(2), "}"}) + else + key, value = attributes[i]:match("(%w+)=(%w+)") + table.insert(buf, {"\\markdownRendererAttributeKeyValue{", + key, "}{", value, "}"}) + end + end + end local cmd level = level + options.shiftHeadings @@ -2741,7 +2819,11 @@ function M.writer.new(options) else cmd = "" end - return {cmd,"{",s,"}"} + if self.is_writing then + table.insert(buf, {cmd, "{", s, "}"}) + end + + return buf end function self.note(s) return {"\\markdownRendererFootnote{",s,"}"} @@ -2758,7 +2840,7 @@ function M.writer.new(options) function self.get_state() return { is_writing=self.is_writing, - active_headings={table.unpack(self.active_headings)}, + active_attributes={table.unpack(self.active_attributes)}, } end function self.set_state(s) @@ -2920,12 +3002,12 @@ parsers.css_identifier = (parsers.hash + parsers.period) * (parsers.css_identifier_char - parsers.digit) * parsers.css_identifier_char^0)) -parsers.attribute_name_char = parsers.any - parsers.space +parsers.attribute_key_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 +parsers.attribute_value_char = parsers.any - parsers.space + - parsers.dquote - parsers.more -- block followed by 0 or more optionally -- indented blocks with first line indented. @@ -3375,11 +3457,6 @@ end parsers.in_matched_block_tags = parsers.less * Cmt(#parsers.openelt_block, parse_matched_tags) -parsers.displayhtml = parsers.htmlcomment / "" - + parsers.emptyelt_block - + parsers.openelt_exact("hr") - + parsers.in_matched_block_tags - + parsers.htmlinstruction parsers.hexentity = parsers.ampersand * parsers.hash * S("Xx") * C(parsers.hexdigit^1) * parsers.semicolon parsers.decentity = parsers.ampersand * parsers.hash @@ -3446,7 +3523,7 @@ 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 + + C((parsers.attribute_key_char - parsers.rbrace)^1 * parsers.equal * (parsers.attribute_value_char @@ -3845,6 +3922,14 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline "mailto:"..email) end + larsers.AutoLinkRelativeReference + = parsers.less + * C(parsers.urlchar^1) + * parsers.more + / function(url) + return writer.link(writer.escape(url), url) + end + larsers.DirectLink = (parsers.tag / parse_inlines_no_link) -- no links inside links * parsers.spnl * parsers.lparent @@ -3901,12 +3986,12 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline larsers.EscapedChar = parsers.backslash * C(parsers.escapable) / writer.string - larsers.InlineHtml = parsers.emptyelt_any + larsers.InlineHtml = parsers.emptyelt_any / writer.inline_html_tag + (parsers.htmlcomment / parse_inlines_no_html) / writer.inline_html_comment + parsers.htmlinstruction - + parsers.openelt_any - + parsers.closeelt_any + + parsers.openelt_any / writer.inline_html_tag + + parsers.closeelt_any / writer.inline_html_tag larsers.HtmlEntity = parsers.hexentity / entities.hex_entity / writer.string + parsers.decentity / entities.dec_entity / writer.string @@ -3916,7 +4001,12 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline * parsers.contentblock_tail / writer.contentblock - larsers.DisplayHtml = parsers.displayhtml + larsers.DisplayHtml = (parsers.htmlcomment / parse_blocks) + / writer.block_html_comment + + parsers.emptyelt_block / writer.block_html_element + + parsers.openelt_exact("hr") / writer.block_html_element + + parsers.in_matched_block_tags / writer.block_html_element + + parsers.htmlinstruction larsers.Verbatim = Cs( (parsers.blanklines * ((parsers.indentedline - parsers.blankline))^1)^1 @@ -4180,6 +4270,7 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline + V("Code") + V("AutoLinkUrl") + V("AutoLinkEmail") + + V("AutoLinkRelativeReference") + V("InlineHtml") + V("HtmlEntity") + V("EscapedChar") @@ -4200,6 +4291,7 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline + V("Code") + V("AutoLinkUrl") + V("AutoLinkEmail") + + V("AutoLinkRelativeReference") + V("InlineHtml") + V("HtmlEntity") + V("EscapedChar") @@ -4221,6 +4313,8 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline Code = larsers.Code, AutoLinkUrl = larsers.AutoLinkUrl, AutoLinkEmail = larsers.AutoLinkEmail, + AutoLinkRelativeReference + = larsers.AutoLinkRelativeReference, InlineHtml = larsers.InlineHtml, HtmlEntity = larsers.HtmlEntity, EscapedChar = larsers.EscapedChar, @@ -4278,6 +4372,10 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline syntax.Smart = parsers.fail end + if not options.relativeReferences then + syntax.AutoLinkRelativeReference = parsers.fail + end + local blocks_toplevel_t = util.table_copy(syntax) blocks_toplevel_t.Paragraph = larsers.ToplevelParagraph larsers.blocks_toplevel = Ct(blocks_toplevel_t) |