From d559ccaca60acb46c6a12c256ea2a1dcc867d0f8 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 5 Apr 2019 21:09:01 +0000 Subject: markdown (5apr19) git-svn-id: svn://tug.org/texlive/trunk@50784 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/context/third/markdown/t-markdown.tex | 2 +- .../texmf-dist/tex/generic/markdown/markdown.tex | 24 +- Master/texmf-dist/tex/latex/markdown/markdown.sty | 196 +++++++++++++++- Master/texmf-dist/tex/luatex/markdown/markdown.lua | 253 +++++++++++++++++---- 4 files changed, 410 insertions(+), 65 deletions(-) (limited to 'Master/texmf-dist/tex') diff --git a/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex b/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex index 40f891b19bd..f114a6d267a 100644 --- a/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex +++ b/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex @@ -6,7 +6,7 @@ %% %% markdown.dtx (with options: `context') %% -%% 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 diff --git a/Master/texmf-dist/tex/generic/markdown/markdown.tex b/Master/texmf-dist/tex/generic/markdown/markdown.tex index 8b33ee045de..6091f6ea530 100644 --- a/Master/texmf-dist/tex/generic/markdown/markdown.tex +++ b/Master/texmf-dist/tex/generic/markdown/markdown.tex @@ -6,7 +6,7 @@ %% %% markdown.dtx (with options: `tex') %% -%% 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 @@ -45,8 +45,8 @@ %% %% The names of the source files used are shown above. %% -\def\markdownLastModified{2018/04/08}% -\def\markdownVersion{2.5.6}% +\def\markdownLastModified{2019/04/04}% +\def\markdownVersion{2.7.0}% \let\markdownBegin\relax \let\markdownEnd\relax \let\markdownInput\relax @@ -54,8 +54,8 @@ \def\markdownOptionInputTempFileName{\jobname.markdown.in}% \def\markdownOptionOutputTempFileName{\jobname.markdown.out}% \def\markdownOptionErrorTempFileName{\jobname.markdown.err}% -\def\markdownOptionCacheDir{\markdownOptionOutputDir/_markdown_\jobname}% \def\markdownOptionOutputDir{.}% +\def\markdownOptionCacheDir{\markdownOptionOutputDir/_markdown_\jobname}% \let\markdownOptionBlankBeforeBlockquote\undefined \let\markdownOptionBlankBeforeCodeFence\undefined \let\markdownOptionBlankBeforeHeading\undefined @@ -68,10 +68,12 @@ \let\markdownOptionFootnotes\undefined \let\markdownOptionFencedCode\undefined \let\markdownOptionHashEnumerators\undefined +\let\markdownOptionHeaderAttributes\undefined \let\markdownOptionHtml\undefined \let\markdownOptionHybrid\undefined \let\markdownOptionInlineFootnotes\undefined \let\markdownOptionPreserveTabs\undefined +\let\markdownOptionSlice\undefined \let\markdownOptionSmartEllipses\undefined \let\markdownOptionStartNumber\undefined \let\markdownOptionTightLists\undefined @@ -338,7 +340,7 @@ \def\markdownRendererBlockQuoteBeginPrototype{\par\begingroup\it}% \def\markdownRendererBlockQuoteEndPrototype{\endgroup\par}% \def\markdownRendererInputVerbatimPrototype#1{% - \par{\tt\input"#1"\relax{}}\par}% + \par{\tt\input#1\relax{}}\par}% \def\markdownRendererInputFencedCodePrototype#1#2{% \markdownRendererInputVerbatimPrototype{#1}}% \def\markdownRendererHeadingOnePrototype#1{#1}% @@ -393,6 +395,9 @@ \ifx\markdownOptionHashEnumerators\undefined\else hashEnumerators = \markdownOptionHashEnumerators, \fi +\ifx\markdownOptionHeaderAttributes\undefined\else + headerAttributes = \markdownOptionHeaderAttributes, +\fi \ifx\markdownOptionHtml\undefined\else html = \markdownOptionHtml, \fi @@ -405,6 +410,9 @@ \ifx\markdownOptionPreserveTabs\undefined\else preserveTabs = \markdownOptionPreserveTabs, \fi +\ifx\markdownOptionSlice\undefined\else + slice = "\markdownOptionSlice", +\fi \ifx\markdownOptionSmartEllipses\undefined\else smartEllipses = \markdownOptionSmartEllipses, \fi @@ -443,7 +451,7 @@ local convert = md.new(\markdownLuaOptions) |gdef|markdownReadAndConvert#1#2{@ |begingroup@ |immediate|openout|markdownOutputFileStream@ - |markdownOptionInputTempFileName@ + |markdownOptionInputTempFileName|relax@ |markdownInfo{Buffering markdown input into the temporary @ input file "|markdownOptionInputTempFileName" and scanning @ for the closing token sequence "#1"}@ @@ -570,7 +578,9 @@ local convert = md.new(\markdownLuaOptions) |closein|markdownInputFileStream |markdownLuaExecute{% |markdownPrepare - local input = assert(io.open("#1", "r"):read("*a")) + local input = assert(io.open("% + |markdownOptionOutputDir + /#1", "r"):read("*a")) print(convert(input:gsub("\r\n?", "\n")))}}% |endgroup \endinput diff --git a/Master/texmf-dist/tex/latex/markdown/markdown.sty b/Master/texmf-dist/tex/latex/markdown/markdown.sty index 251a2f62d74..f21cb15b81d 100644 --- a/Master/texmf-dist/tex/latex/markdown/markdown.sty +++ b/Master/texmf-dist/tex/latex/markdown/markdown.sty @@ -6,7 +6,7 @@ %% %% markdown.dtx (with options: `latex') %% -%% 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 @@ -52,6 +52,7 @@ \RequirePackage{ifthen} \RequirePackage{fancyvrb} \RequirePackage{csvsimple} +\RequirePackage{gobble} \newenvironment{markdown}\relax\relax \newenvironment{markdown*}[1]\relax\relax \newcommand\markdownSetup[1]{% @@ -94,6 +95,8 @@ \def\markdownOptionFencedCode{#1}}% \define@key{markdownOptions}{hashEnumerators}[true]{% \def\markdownOptionHashEnumerators{#1}}% +\define@key{markdownOptions}{headerAttributes}[true]{% + \def\markdownOptionHeaderAttributes{#1}}% \define@key{markdownOptions}{html}[true]{% \def\markdownOptionHtml{#1}}% \define@key{markdownOptions}{hybrid}[true]{% @@ -104,6 +107,8 @@ \def\markdownOptionPreserveTabs{#1}}% \define@key{markdownOptions}{smartEllipses}[true]{% \def\markdownOptionSmartEllipses{#1}}% +\define@key{markdownOptions}{slice}[true]{% + \def\markdownOptionSlice{#1}}% \define@key{markdownOptions}{startNumber}[true]{% \def\markdownOptionStartNumber{#1}}% \define@key{markdownOptions}{tightLists}[true]{% @@ -495,14 +500,161 @@ \fi \newcount\markdownLaTeXCitationsCounter -\def\markdownLaTeXBasicCitations#1#2#3#4{% +\def\markdownLaTeXBasicCitations#1#2#3#4#5#6{% \advance\markdownLaTeXCitationsCounter by 1\relax - \ifx\relax#2\relax\else#2~\fi\cite[#3]{#4}% - \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax - \expandafter\@gobble - \fi\markdownLaTeXBasicCitations} + \ifx\relax#4\relax + \ifx\relax#5\relax + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \cite{#1#2#6}% Without prenotes and postnotes, just accumulate cites + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \@gobblethree + \fi + \else% Before a postnote (#5), dump the accumulator + \ifx\relax#1\relax\else + \cite{#1}% + \fi + \cite[#5]{#6}% + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \else + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \markdownLaTeXBasicCitations + \fi + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter + \@gobblethree + \fi + \else% Before a prenote (#4), dump the accumulator + \ifx\relax#1\relax\else + \cite{#1}% + \fi + \ifnum\markdownLaTeXCitationsCounter>1\relax + \space % Insert a space before the prenote in later citations + \fi + #4~\expandafter\cite\ifx\relax#5\relax{#6}\else[#5]{#6}\fi + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \else + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \markdownLaTeXBasicCitations + \fi + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \expandafter + \@gobblethree + \fi\markdownLaTeXBasicCitations{#1#2#6},} \let\markdownLaTeXBasicTextCitations\markdownLaTeXBasicCitations +\def\markdownLaTeXNatbibCitations#1#2#3#4#5{% + \advance\markdownLaTeXCitationsCounter by 1\relax + \ifx\relax#3\relax + \ifx\relax#4\relax + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \citep{#1,#5}% Without prenotes and postnotes, just accumulate cites + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \@gobbletwo + \fi + \else% Before a postnote (#4), dump the accumulator + \ifx\relax#1\relax\else + \citep{#1}% + \fi + \citep[][#4]{#5}% + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \else + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \markdownLaTeXNatbibCitations + \fi + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter + \@gobbletwo + \fi + \else% Before a prenote (#3), dump the accumulator + \ifx\relax#1\relax\relax\else + \citep{#1}% + \fi + \citep[#3][#4]{#5}% + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \else + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \markdownLaTeXNatbibCitations + \fi + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \expandafter + \@gobbletwo + \fi\markdownLaTeXNatbibCitations{#1,#5}} +\def\markdownLaTeXNatbibTextCitations#1#2#3#4#5{% + \advance\markdownLaTeXCitationsCounter by 1\relax + \ifx\relax#3\relax + \ifx\relax#4\relax + \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax + \citet{#1,#5}% Without prenotes and postnotes, just accumulate cites + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \@gobbletwo + \fi + \else% After a prenote or a postnote, dump the accumulator + \ifx\relax#1\relax\else + \citet{#1}% + \fi + , \citet[#3][#4]{#5}% + \ifnum\markdownLaTeXCitationsCounter<\markdownLaTeXCitationsTotal\relax + , + \else + \ifnum\markdownLaTeXCitationsCounter=\markdownLaTeXCitationsTotal\relax + , + \fi + \fi + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + \markdownLaTeXNatbibTextCitations + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter + \@gobbletwo + \fi + \else% After a prenote or a postnote, dump the accumulator + \ifx\relax#1\relax\relax\else + \citet{#1}% + \fi + , \citet[#3][#4]{#5}% + \ifnum\markdownLaTeXCitationsCounter<\markdownLaTeXCitationsTotal\relax + , + \else + \ifnum\markdownLaTeXCitationsCounter=\markdownLaTeXCitationsTotal\relax + , + \fi + \fi + \expandafter\expandafter\expandafter + \markdownLaTeXNatbibTextCitations + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \expandafter + \@gobbletwo + \fi\markdownLaTeXNatbibTextCitations{#1,#5}} + \def\markdownLaTeXBibLaTeXCitations#1#2#3#4#5{% \advance\markdownLaTeXCitationsCounter by 1\relax \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax @@ -521,8 +673,19 @@ \markdownLaTeXCitationsCounter=1% \def\markdownLaTeXCitationsTotal{#1}% \ifx\autocites\undefined - \expandafter - \markdownLaTeXBasicCitations + \ifx\citep\undefined + \expandafter\expandafter\expandafter + \markdownLaTeXBasicCitations + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \else + \expandafter\expandafter\expandafter + \markdownLaTeXNatbibCitations + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \fi \else \expandafter\expandafter\expandafter \markdownLaTeXBibLaTeXCitations @@ -531,9 +694,20 @@ textCite = {% \markdownLaTeXCitationsCounter=1% \def\markdownLaTeXCitationsTotal{#1}% - \ifx\textcites\undefined - \expandafter - \markdownLaTeXBasicTextCitations + \ifx\autocites\undefined + \ifx\citep\undefined + \expandafter\expandafter\expandafter + \markdownLaTeXBasicTextCitations + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \else + \expandafter\expandafter\expandafter + \markdownLaTeXNatbibTextCitations + \expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter}% + \fi \else \expandafter\expandafter\expandafter \markdownLaTeXBibLaTeXTextCitations 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, -- cgit v1.2.3