diff options
Diffstat (limited to 'Master/texmf-dist/source/generic/markdown')
-rw-r--r-- | Master/texmf-dist/source/generic/markdown/markdown.dtx | 1420 |
1 files changed, 1118 insertions, 302 deletions
diff --git a/Master/texmf-dist/source/generic/markdown/markdown.dtx b/Master/texmf-dist/source/generic/markdown/markdown.dtx index 5b3f73cb8e2..1a391e223fe 100644 --- a/Master/texmf-dist/source/generic/markdown/markdown.dtx +++ b/Master/texmf-dist/source/generic/markdown/markdown.dtx @@ -275,6 +275,15 @@ pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; + counter-reset: line; +} + +.sourceCode.linenos > span { + counter-increment: line; +} + +.sourceCode.linenos > span:before{ + content: counter(line) " "; } b, strong { @@ -1213,7 +1222,8 @@ local md5 = require("md5") % %: A package that provides the `compactitem`, `compactenum`, and % `compactdesc` macros for the typesetting of tight bulleted lists, -% ordered lists, and definition lists. +% ordered lists, and definition lists as well as the rendering of +% fancy lists. % % \pkg{ifthen} % @@ -1263,13 +1273,24 @@ local md5 = require("md5") %: A package that is used to polyfill the general hook management system in % the default renderer prototypes for \acro{yaml} metadata, see Section % <#sec:latexyamlmetadata>, and also in the default renderer prototype -% for attribute identifiers. +% for identifier attributes. % % \pkg{soulutf8} % %: A package that is used in the default renderer prototype for % strike-throughs. % +% \pkg{ltxcmds} +% +%: A package that is used to detect whether the \pkg{minted} and +% \pkg{listings} packages are loaded in the default renderer prototype +% for fenced code blocks. +% +% \pkg{verse} +% +%: A package that is used in the default renderer prototypes for +% line blocks. +% % \end{markdown} % \begin{macrocode} \RequirePackage{expl3} @@ -1312,7 +1333,7 @@ local md5 = require("md5") % Extensive user documentation for the Markdown package was kindly written by % Lian Tze Lim and published by Overleaf. % -% Funding by the the Faculty of Informatics at the Masaryk~University +% Funding by the Faculty of Informatics at the Masaryk~University % in~Brno~[@novotny15] is gratefully acknowledged. % % Support for content slicing (Lua options \Opt{shiftHeadings} and \Opt{slice}) @@ -3290,6 +3311,7 @@ following content: \begin{markdown} A paragraph. + ::: {.identifier} A fenced div. ::: @@ -3297,9 +3319,10 @@ A fenced div. \begin{markdown*}{blankBeforeDivFence} A paragraph. -``` + +::: {.identifier} Not a fenced div. -``` +::: \end{markdown*} \end{document} @@ -3315,7 +3338,9 @@ following text: > > A fenced div. > -> A paragraph. ::: {.identifier} Not a fenced div. ::: +> A paragraph. +> +> ::: {.identifier} Not a fenced div. ::: %</manual-options> %<*tex> @@ -3612,10 +3637,10 @@ following content: renderers = { attributeKeyValue = { \str_if_eq:nnT - { #1 } + { ##1 } { color } { - \color_select:n { #2 } + \color_select:n { ##2 } } }, }, @@ -3636,12 +3661,12 @@ Here is some [colored text]{color=red}. ``````` Next, invoke LuaTeX from the terminal: ``` sh -lualatex --shell-escape document.tex +lualatex document.tex `````` A PDF document named `document.pdf` should be produced and contain the following text: -> Here is some [colored text]{color=red}. +> Here is some <span style="color: red">colored text</span>. %</manual-options> %<*tex> @@ -5409,30 +5434,30 @@ defaultOptions.fencedCode = false %</lua,lua-cli> %<*manual-options> -#### Option `fencedDivs` +#### Option `fencedCodeAttributes` -`fencedDivs` (default value: `false`) +`fencedCodeAttributes` (default value: `false`) % \fi % \begin{markdown} % -% \Optitem[false]{fencedDivs}{\opt{true}, \opt{false}} +% \Optitem[false]{fencedCodeAttributes}{\opt{true}, \opt{false}} % : true - : Enable the Pandoc fenced divs extension: - - ``` md - ::::: {#special .sidebar} - Here is a paragraph. + : Enable the Pandoc fenced code attribute extension: - And another. - ::::: - `````` + ```````` md + ~~~~ {#mycode .haskell .numberLines startFrom="100"} + qsort [] = [] + qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ + qsort (filter (>= x) xs) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ``````````` : false - : Disable the Pandoc fenced divs extension: + : Disable the Pandoc fenced code attribute extension. % \end{markdown} % \iffalse @@ -5443,16 +5468,33 @@ Using a text editor, create a text document named `document.tex` with the following content: ```` tex \documentclass{article} -\usepackage[fencedDivs]{markdown} +\usepackage[fencedCode, + fencedCodeAttributes]{markdown} +\usepackage{minted} +\markdownSetup{ + renderers = { + fencedCodeAttributeContextBegin = {% + \begingroup + \markdownSetup{ + renderers = { + attributeKeyValue = {% + \setminted{{#1} = {#2}}% + }, + }, + }% + }, + fencedCodeAttributeContextEnd = {% + \endgroup + }, + }, +} \begin{document} -\begin{markdown}{slice=special} -Here is a regular paragraph. - -::::: {#special} -Here is a special paragraph. -::::: - -And here is another regular paragraph. +\begin{markdown} +``` js {linenos=true} +if (a > 3) { + moveShip(5 * gravity, DOWN); +} +`````` \end{markdown} \end{document} ``````` @@ -5463,13 +5505,65 @@ lualatex --shell-escape document.tex A PDF document named `document.pdf` should be produced and contain the following text: -> Here is a special paragraph. +> ``` js {.linenos} +> 1. if (a > 3) { +> 2. moveShip(5 * gravity, DOWN); +> 3. } +> `````` %</manual-options> %<*tex> % \fi % \begin{macrocode} \@@_add_lua_option:nnn + { fencedCodeAttributes } + { boolean } + { false } +% \end{macrocode} +% \iffalse +%</tex> +%<*lua,lua-cli> +% \fi +% \begin{macrocode} +defaultOptions.fencedCodeAttributes = false +% \end{macrocode} +% \par +% \iffalse +%</lua,lua-cli> +%<*manual-options> + +#### Option `fencedDivs` + +`fencedDivs` (default value: `false`) + +% \fi +% \begin{markdown} +% +% \Optitem[false]{fencedDivs}{\opt{true}, \opt{false}} +% +: true + + : Enable the Pandoc fenced divs extension: + + ``` md + ::::: {#special .sidebar} + Here is a paragraph. + + And another. + ::::: + `````` + +: false + + : Disable the Pandoc fenced divs extension: + +% \end{markdown} +% \iffalse +%</manual-options> +%<*tex> +% \fi +% \begin{macrocode} +\@@_add_lua_option:nnn { fencedDivs } { boolean } { false } @@ -6726,6 +6820,138 @@ defaultOptions.jekyllData = false %</lua,lua-cli> %<*manual-options> +#### Option `lineBlocks` + +`lineBlocks` (default value: `false`) + +% \fi +% \begin{markdown} +% +% \Optitem[false]{lineBlocks}{\opt{true}, \opt{false}} +% +: true + + : Enable the Pandoc line block syntax extension. + + ``` md + | this is a line block that + | spans multiple + | even + discontinuous + | lines + `````` + +: false + + : Disable the Pandoc line block syntax extension. + +% \end{markdown} +% \iffalse + +##### Plain \TeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\input markdown +\def\markdownOptionLineBlocks{true} +\markdownBegin +| I would spread the cloths under your feet: +| But I, being poor, have only my dreams; +| I have spread my dreams under your feet; +| Tread softly because you tread on my dreams. +\markdownEnd +\bye +``````` +Next, invoke LuaTeX from the terminal: +``` sh +luatex document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> | I would spread the cloths under your feet: +> | But I, being poor, have only my dreams; +> | I have spread my dreams under your feet; +> | Tread softly because you tread on my dreams. + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\documentclass{article} +\usepackage[lineBlocks]{markdown} +\begin{document} +\begin{markdown} +| I would spread the cloths under your feet: +| But I, being poor, have only my dreams; +| I have spread my dreams under your feet; +| Tread softly because you tread on my dreams. +\end{markdown} +\end{document} +``````` +Next, invoke LuaTeX from the terminal: +``` sh +lualatex document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> | I would spread the cloths under your feet: +> | But I, being poor, have only my dreams; +> | I have spread my dreams under your feet; +> | Tread softly because you tread on my dreams. + +##### \Hologo{ConTeXt} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\usemodule[t][markdown] +\setupmarkdown[lineBlocks = yes] +\starttext +\startmarkdown +| I would spread the cloths under your feet: +| But I, being poor, have only my dreams; +| I have spread my dreams under your feet; +| Tread softly because you tread on my dreams. +\stopmarkdown +\stoptext +``````` +Next, invoke LuaTeX from the terminal: +``` sh +context document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> | I would spread the cloths under your feet: +> | But I, being poor, have only my dreams; +> | I have spread my dreams under your feet; +> | Tread softly because you tread on my dreams. + +%</manual-options> +%<*tex> +% \fi +% \begin{macrocode} +\@@_add_lua_option:nnn + { lineBlocks } + { boolean } + { false } +% \end{macrocode} +% \iffalse +%</tex> +%<*lua,lua-cli> +% \fi +% \begin{macrocode} +defaultOptions.lineBlocks = false +% \end{macrocode} +% \par +% \iffalse +%</lua,lua-cli> +%<*manual-options> + #### Option `notes` `notes` (default value: `false`) @@ -8480,7 +8706,7 @@ defaultOptions.tableCaptions = false : true : Enable the Pandoc `task_lists` syntax extension. - + ``` md - [ ] an unticked task list item @@ -9256,7 +9482,7 @@ following text: > \$\\sqrt{-1}\$ *equals* \$i\$. > > √-̅1̅ *equals* $i$. - + Invoking pdfTeX should have the same effect: ``` sh pdftex --shell-escape document.tex @@ -10249,7 +10475,7 @@ following text: % % \begin{markdown} -#### Bracketed Spans Context Renderers +#### Bracketed Spans Attribute Context Renderers The following macros are only produced, when the \Opt{bracketedSpans} option is enabled. @@ -10271,8 +10497,8 @@ following content: \usepackage[bracketedSpans]{markdown} \markdownSetup{ renderers = { - fencedDivAttributeContextBegin = {(}, - fencedDivAttributeContextEnd = {)}, + bracketedSpanAttributeContextBegin = {(}, + bracketedSpanAttributeContextEnd = {)}, }, } \begin{document} @@ -12157,7 +12383,106 @@ corresponds to the emphasized span of text. % % \begin{markdown} -#### Fenced Div Context Renderers +#### Fenced Code Attribute Context Renderers +The following macros are only produced, when the \Opt{fencedCode} option is +enabled. + +The \mdef{markdownRendererFencedCodeAttributeContextBegin} and +\mdef{markdownRendererFencedCodeAttributeContextEnd} macros represent the +beginning and the end of a context in which the attributes of a fenced code +apply. The macros receive no arguments. + +% \end{markdown} +% +% \iffalse + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +```` tex +\documentclass{article} +\usepackage[fencedCode, + fencedCodeAttributes]{markdown} +\usepackage{minted} +\markdownSetup{ + renderers = { + fencedCodeAttributeContextBegin = {% + \begingroup + \markdownSetup{ + renderers = { + attributeKeyValue = {% + \setminted{{#1} = {#2}}% + }, + }, + }% + }, + fencedCodeAttributeContextEnd = {% + \endgroup + }, + }, +} +\begin{document} +\begin{markdown} +``` js {linenos=true} +if (a > 3) { + moveShip(5 * gravity, DOWN); +} +`````` +\end{markdown} +\end{document} +``````` +Next, invoke LuaTeX from the terminal: +``` sh +lualatex --shell-escape document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> ``` js {.linenos} +> 1. if (a > 3) { +> 2. moveShip(5 * gravity, DOWN); +> 3. } +> `````` + +%</manual-tokens> +%<*tex> +% \fi +% +% \begin{macrocode} +\def\markdownRendererFencedCodeAttributeContextBegin{% + \markdownRendererFencedCodeAttributeContextBeginPrototype}% +\ExplSyntaxOn +\seq_gput_right:Nn + \g_@@_renderers_seq + { fencedCodeAttributeContextBegin } +\prop_gput:Nnn + \g_@@_renderer_arities_prop + { fencedCodeAttributeContextBegin } + { 0 } +\ExplSyntaxOff +\def\markdownRendererFencedCodeAttributeContextEnd{% + \markdownRendererFencedCodeAttributeContextEndPrototype}% +\ExplSyntaxOn +\seq_gput_right:Nn + \g_@@_renderers_seq + { fencedCodeAttributeContextEnd } +\prop_gput:Nnn + \g_@@_renderer_arities_prop + { fencedCodeAttributeContextEnd } + { 0 } +\ExplSyntaxOff +% \end{macrocode} +% \par +% +% \iffalse +%</tex> +%<*manual-tokens> +% \fi +% +% \begin{markdown} + +#### Fenced Div Attribute Context Renderers The following macros are only produced, when the \Opt{fencedDiv} option is enabled. @@ -12176,7 +12501,7 @@ Using a text editor, create a text document named `document.tex` with the following content: ``` tex \documentclass{article} -\usepackage[fencedDiv]{markdown} +\usepackage[fencedDivs]{markdown} \markdownSetup{ renderers = { fencedDivAttributeContextBegin = {% @@ -13108,6 +13433,137 @@ following text: % % \begin{markdown} +#### Line Block Renderer +The following macros are only produced, when the \Opt{lineBlocks} option +is enabled. + +The \mdef{markdownRendererLineBlockBegin} and \mdef{markdownRendererLineBlockEnd} macros +represent the beginning and the end of a line block. The macros receive no arguments. + +% \end{markdown} +% +% \iffalse + +##### Plain \TeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\input markdown +\def\markdownOptionLineBlocks{true} +\markdownBegin +| I would spread the cloths under your feet: +| But I, being poor, have only my dreams; +| I have spread my dreams under your feet; +| Tread softly because you tread on my dreams. +\markdownEnd +\bye +``````` +Next, invoke LuaTeX from the terminal: +``` sh +luatex document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> | I would spread the cloths under your feet: +> | But I, being poor, have only my dreams; +> | I have spread my dreams under your feet; +> | Tread softly because you tread on my dreams. + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\documentclass{article} +\usepackage[lineBlocks]{markdown} +\begin{document} +\begin{markdown} +| I would spread the cloths under your feet: +| But I, being poor, have only my dreams; +| I have spread my dreams under your feet; +| Tread softly because you tread on my dreams. +\end{markdown} +\end{document} +``````` +Next, invoke LuaTeX from the terminal: +``` sh +lualatex document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> | I would spread the cloths under your feet: +> | But I, being poor, have only my dreams; +> | I have spread my dreams under your feet; +> | Tread softly because you tread on my dreams. + +##### \Hologo{ConTeXt} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\usemodule[t][markdown] +\setupmarkdown[lineBlocks = yes] +\starttext +\startmarkdown +| I would spread the cloths under your feet: +| But I, being poor, have only my dreams; +| I have spread my dreams under your feet; +| Tread softly because you tread on my dreams. +\stopmarkdown +\stoptext +``````` +Next, invoke LuaTeX from the terminal: +``` sh +context document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the +following text: + +> | I would spread the cloths under your feet: +> | But I, being poor, have only my dreams; +> | I have spread my dreams under your feet; +> | Tread softly because you tread on my dreams. + +%</manual-tokens> +%<*tex> +% \fi +% +% \begin{macrocode} +\def\markdownRendererLineBlockBegin{% + \markdownRendererLineBlockBeginPrototype}% +\ExplSyntaxOn +\seq_gput_right:Nn + \g_@@_renderers_seq + { lineBlockBegin } +\prop_gput:Nnn + \g_@@_renderer_arities_prop + { lineBlockBegin } + { 0 } +\ExplSyntaxOff +\def\markdownRendererLineBlockEnd{% + \markdownRendererLineBlockEndPrototype}% +\ExplSyntaxOn +\seq_gput_right:Nn + \g_@@_renderers_seq + { lineBlockEnd } +\prop_gput:Nnn + \g_@@_renderer_arities_prop + { lineBlockEnd } + { 0 } +\ExplSyntaxOff +% \end{macrocode} +% \par +% +% \iffalse +%</tex> +%<*manual-tokens> +% \fi +% +% \begin{markdown} + #### Line Break Renderer The \mdef{markdownRendererLineBreak} macro represents a forced line break. The macro receives no arguments. @@ -14733,6 +15189,39 @@ following text: % % \begin{markdown} +#### Replacement Character Renderers +The \mdef{markdownRendererReplacementCharacter} macro represents the U+0000 +and U+FFFD Unicode characters. The macro receives no arguments. + +% \end{markdown} +% +% \iffalse +%</manual-tokens> +%<*tex> +% \fi +% +% \begin{macrocode} +\def\markdownRendererReplacementCharacter{% + \markdownRendererReplacementCharacterPrototype}% +\ExplSyntaxOn +\seq_gput_right:Nn + \g_@@_renderers_seq + { replacementCharacter } +\prop_gput:Nnn + \g_@@_renderer_arities_prop + { replacementCharacter } + { 0 } +\ExplSyntaxOff +% \end{macrocode} +% \par +% +% \iffalse +%</tex> +%<*manual-tokens> +% \fi +% +% \begin{markdown} + #### Special Character Renderers The following macros replace any special plain \TeX{} characters, including % \iffalse @@ -17918,7 +18407,7 @@ following text: > \$\\sqrt{-1}\$ *equals* \$i\$. > > √-̅1̅ *equals* $i$. - + Invoking pdfTeX should have the same effect: ``` sh texexec --passon=--shell-escape document.tex @@ -18262,7 +18751,6 @@ end % \end{markdown} % \begin{macrocode} function util.cache_verbatim(dir, string) - string = string:gsub('[\r\n%s]*$', '') local name = util.cache(dir, string, nil, nil, ".verbatim") return name end @@ -20789,7 +21277,7 @@ function M.writer.new(options) % \end{markdown} % \begin{macrocode} function self.pack(name) - return [[\input ]] .. name .. [[\relax]] + return [[\input{]] .. name .. [[}\relax]] end % \end{macrocode} % \par @@ -20846,40 +21334,53 @@ function M.writer.new(options) % % \end{markdown} % \begin{macrocode} - self.escaped_uri_chars = { - ["{"] = "\\markdownRendererLeftBrace{}", - ["}"] = "\\markdownRendererRightBrace{}", - ["\\"] = "\\markdownRendererBackslash{}", - } - self.escaped_minimal_strings = { - ["^^"] = "\\markdownRendererCircumflex\\markdownRendererCircumflex ", - ["☒"] = "\\markdownRendererTickedBox{}", - ["⌛"] = "\\markdownRendererHalfTickedBox{}", - ["☐"] = "\\markdownRendererUntickedBox{}", - } + self.escaped_uri_chars = { + ["{"] = "\\markdownRendererLeftBrace{}", + ["}"] = "\\markdownRendererRightBrace{}", + ["\\"] = "\\markdownRendererBackslash{}", + } + self.escaped_minimal_strings = { + ["^^"] = "\\markdownRendererCircumflex\\markdownRendererCircumflex ", + ["☒"] = "\\markdownRendererTickedBox{}", + ["⌛"] = "\\markdownRendererHalfTickedBox{}", + ["☐"] = "\\markdownRendererUntickedBox{}", + [entities.hex_entity('FFFD')] = "\\markdownRendererReplacementCharacter{}", + } +% \end{macrocode} +% \par +% \begin{markdown} +% +% Define table \luamdef{writer->escaped_strings} containing the mapping from +% character strings that need to be escaped in typeset content. +% +% \end{markdown} +% \begin{macrocode} + self.escaped_strings = util.table_copy(self.escaped_minimal_strings) + self.escaped_strings[entities.hex_entity('00A0')] = self.nbsp % \end{macrocode} % \par % \begin{markdown} % % Define a table \luamdef{writer->escaped_chars} containing the mapping from % special plain \TeX{} characters (including the active pipe character (`|`) -% of \Hologo{ConTeXt}) that need to be escaped for typeset content. +% of \Hologo{ConTeXt}) that need to be escaped in typeset content. % % \end{markdown} % \begin{macrocode} self.escaped_chars = { - ["{"] = "\\markdownRendererLeftBrace{}", - ["}"] = "\\markdownRendererRightBrace{}", - ["%"] = "\\markdownRendererPercentSign{}", - ["\\"] = "\\markdownRendererBackslash{}", - ["#"] = "\\markdownRendererHash{}", - ["$"] = "\\markdownRendererDollarSign{}", - ["&"] = "\\markdownRendererAmpersand{}", - ["_"] = "\\markdownRendererUnderscore{}", - ["^"] = "\\markdownRendererCircumflex{}", - ["~"] = "\\markdownRendererTilde{}", - ["|"] = "\\markdownRendererPipe{}", - } + ["{"] = "\\markdownRendererLeftBrace{}", + ["}"] = "\\markdownRendererRightBrace{}", + ["%"] = "\\markdownRendererPercentSign{}", + ["\\"] = "\\markdownRendererBackslash{}", + ["#"] = "\\markdownRendererHash{}", + ["$"] = "\\markdownRendererDollarSign{}", + ["&"] = "\\markdownRendererAmpersand{}", + ["_"] = "\\markdownRendererUnderscore{}", + ["^"] = "\\markdownRendererCircumflex{}", + ["~"] = "\\markdownRendererTilde{}", + ["|"] = "\\markdownRendererPipe{}", + [entities.hex_entity('0000')] = "\\markdownRendererReplacementCharacter{}", + } % \end{macrocode} % \par % \begin{markdown} @@ -20891,7 +21392,7 @@ function M.writer.new(options) % % \end{markdown} % \begin{macrocode} - self.escape = util.escaper(self.escaped_chars, self.escaped_minimal_strings) + self.escape = util.escaper(self.escaped_chars, self.escaped_strings) self.escape_uri = util.escaper(self.escaped_uri_chars, self.escaped_minimal_strings) self.escape_minimal = util.escaper({}, self.escaped_minimal_strings) % \end{macrocode} @@ -21170,6 +21671,7 @@ function M.writer.new(options) % \begin{macrocode} function self.verbatim(s) if not self.is_writing then return "" end + s = s:gsub("\n$", "") local name = util.cache_verbatim(options.cacheDir, s) return {"\\markdownRendererInputVerbatim{",name,"}"} end @@ -21621,6 +22123,14 @@ parsers.attributes = parsers.lbrace * parsers.optionalspace * parsers.rbrace + +parsers.raw_attribute = parsers.lbrace + * parsers.optionalspace + * parsers.equal + * C(parsers.attribute_key) + * parsers.optionalspace + * parsers.rbrace + -- block followed by 0 or more optionally -- indented blocks with first line indented. parsers.indented_blocks = function(bl) @@ -21687,73 +22197,6 @@ parsers.inticks = parsers.openticks * parsers.space^-1 % \par % \begin{markdown} % -%#### Parsers Used for Fenced Code Blocks -% -% \end{markdown} -% \begin{macrocode} -local function captures_geq_length(_,i,a,b) - return #a >= #b and i -end - -parsers.tilde_infostring - = C((parsers.linechar - - (parsers.spacechar^1 * parsers.newline))^0) - * parsers.optionalspace - * (parsers.newline + parsers.eof) - -parsers.backtick_infostring - = C((parsers.linechar - - (parsers.backtick - + parsers.spacechar^1 * parsers.newline))^0) - * parsers.optionalspace - * (parsers.newline + parsers.eof) - -local fenceindent -parsers.fencehead = function(char, infostring) - return C(parsers.nonindentspace) / function(s) fenceindent = #s end - * Cg(char^3, "fencelength") - * parsers.optionalspace * infostring -end - -parsers.fencehead_with_attributes - = function(char) - return C(parsers.nonindentspace) / function(s) fenceindent = #s end - * Cg(char^3, "fencelength") - * parsers.optionalspace * Ct(parsers.attributes) - * parsers.optionalspace * (parsers.newline + parsers.eof) -end - -parsers.fencetail = function(char) - return parsers.nonindentspace - * Cmt(C(char^3) * Cb("fencelength"), captures_geq_length) - * parsers.optionalspace * (parsers.newline + parsers.eof) - + parsers.eof -end - -parsers.fencedline = function(char) - return C(parsers.line - parsers.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 -% \end{macrocode} -% \par -% \begin{markdown} -% %#### Parsers Used for Markdown Tags and Links % % \end{markdown} @@ -21982,18 +22425,6 @@ parsers.urlchar = parsers.anyescaped - parsers.newline - parsers.more % % \end{markdown} % \begin{macrocode} -parsers.TildeFencedCode - = parsers.fencehead(parsers.tilde, - parsers.tilde_infostring) - * Cs(parsers.fencedline(parsers.tilde)^0) - * parsers.fencetail(parsers.tilde) - -parsers.BacktickFencedCode - = parsers.fencehead(parsers.backtick, - parsers.backtick_infostring) - * 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 @@ -22274,8 +22705,7 @@ function M.reader.new(writer, options) -- strip off leading > and indents, and run through blocks parsers.blockquote_body = ((parsers.leader * parsers.more * parsers.space^-1)/"" * parsers.linechar^0 * parsers.newline)^1 - * (-(parsers.leader * parsers.more - + parsers.blankline) * parsers.linechar^1 + * (-V("BlockquoteExceptions") * parsers.linechar^1 * parsers.newline)^0 if not options.breakableBlockquotes then @@ -22511,14 +22941,14 @@ function M.reader.new(writer, options) / writer.string parsers.EscapedChar = parsers.backslash * C(parsers.escapable) / writer.string - + parsers.InlineHtml = parsers.emptyelt_any / writer.inline_html_tag + (parsers.htmlcomment / self.parser_functions.parse_inlines_no_html) / writer.inline_html_comment + parsers.htmlinstruction + parsers.openelt_any / writer.inline_html_tag + parsers.closeelt_any / writer.inline_html_tag - + parsers.HtmlEntity = parsers.hexentity / entities.hex_entity / writer.string + parsers.decentity / entities.dec_entity / writer.string + parsers.tagentity / entities.char_entity / writer.string @@ -22541,6 +22971,9 @@ function M.reader.new(writer, options) * ((parsers.indentedline - parsers.blankline))^1)^1 ) / self.expandtabs / writer.verbatim + parsers.BlockquoteExceptions = parsers.leader * parsers.more + + parsers.blankline + parsers.Blockquote = Cs(parsers.blockquote_body^1) / self.parser_functions.parse_blocks_nested / writer.blockquote @@ -22796,7 +23229,9 @@ function M.reader.new(writer, options) DisplayHtml = parsers.DisplayHtml, Paragraph = parsers.Paragraph, Plain = parsers.Plain, + EndlineExceptions = parsers.EndlineExceptions, + BlockquoteExceptions = parsers.BlockquoteExceptions, Str = parsers.Str, Space = parsers.Space, @@ -22868,7 +23303,6 @@ function M.reader.new(writer, options) end self.add_special_character("*") - self.add_special_character("`") self.add_special_character("[") self.add_special_character("]") self.add_special_character("<") @@ -23025,6 +23459,8 @@ function M.reader.new(writer, options) if not options.codeSpans then syntax.Code = parsers.fail + else + self.add_special_character("`") end if not options.html then @@ -23086,13 +23522,22 @@ function M.reader.new(writer, options) % \begin{markdown} % % Return a function that converts markdown string `input` into a plain \TeX{} -% output and returns it. Note that the converter assumes that the input has -% \acro{unix} line endings. +% output and returns it.. % % \end{markdown} % \begin{macrocode} return function(input) - references = {} +% \end{macrocode} +% \begin{markdown} +% Since the Lua converter expects \acro{unix} line endings, normalize the +% input. Also add a line ending at the end of the file in case the input file +% has none. +% \end{markdown} +% \begin{macrocode} + input = input:gsub("\r\n?", "\n") + if input:sub(-1) ~= "\n" then + input = input .. "\n" + end % \end{macrocode} % \begin{markdown} % When determining the name of the cache file, create salt for the hashing @@ -23101,6 +23546,7 @@ function M.reader.new(writer, options) % is disregarded. % \end{markdown} % \begin{macrocode} + references = {} local opt_string = {} for k, _ in pairs(defaultOptions) do local v = options[k] @@ -23906,9 +24352,16 @@ end % parameter is `true`, the syntax extension requires a blank line between a % paragraph and the following fenced code block. % +% When the `allow_attributes` option is `true`, the syntax extension permits +% attributes following the infostring. When the `allow_raw_blocks` option is +% `true`, the syntax extension permits the specification of raw blocks using +% Pandoc's raw attribute syntax extension. +% % \end{markdown} % \begin{macrocode} -M.extensions.fenced_code = function(blank_before_code_fence) +M.extensions.fenced_code = function(blank_before_code_fence, + allow_attributes, + allow_raw_blocks) return { name = "built-in fenced_code syntax extension", extend_writer = function(self) @@ -23918,29 +24371,141 @@ M.extensions.fenced_code = function(blank_before_code_fence) % \par % \begin{markdown} % -% Define \luamdef{writer->codeFence} as a function that will transform an -% input fenced code block `s` with the infostring `i` to the output -% format. +% Define \luamdef{writer->fencedCode} as a function that will transform an +% input fenced code block `s` with the infostring `i` and optional attributes +% `attr` to the output format. % % \end{markdown} % \begin{macrocode} - function self.fencedCode(s, i) + function self.fencedCode(s, i, attr) if not self.is_writing then return "" end + s = s:gsub("\n$", "") + local buf = {} + if attr ~= nil then + table.insert(buf, {"\\markdownRendererFencedCodeAttributeContextBegin", + self.attributes(attr)}) + end local name = util.cache_verbatim(options.cacheDir, s) - return {"\\markdownRendererInputFencedCode{", - name,"}{",self.string(i),"}"} + table.insert(buf, {"\\markdownRendererInputFencedCode{", + name,"}{",self.string(i),"}"}) + if attr ~= nil then + table.insert(buf, "\\markdownRendererFencedCodeAttributeContextEnd") + end + return buf + end + +% \end{macrocode} +% \par +% \begin{markdown} +% +% Define \luamdef{writer->rawBlock} as a function that will transform an +% input raw block `s` with the raw attribute `attr` to the output format. +% +% \end{markdown} +% \begin{macrocode} + if allow_raw_blocks then + function self.rawBlock(s, attr) + if not self.is_writing then return "" end + s = s:gsub("\n$", "") + local name = util.cache_verbatim(options.cacheDir, s) + return {"\\markdownRendererInputRawBlock{", + name,"}{", self.string(attr),"}"} + end end end, extend_reader = function(self) local parsers = self.parsers local writer = self.writer - local FencedCode = (parsers.TildeFencedCode - + parsers.BacktickFencedCode) - / function(infostring, code) - local expanded_code = self.expandtabs(code) - return writer.fencedCode(expanded_code, - infostring) - end + local function captures_geq_length(_,i,a,b) + return #a >= #b and i + end + + local tilde_infostring + = C((parsers.linechar + - (parsers.spacechar^1 * parsers.newline))^0) + + local backtick_infostring + = C((parsers.linechar + - (parsers.backtick + + parsers.spacechar^1 * parsers.newline))^0) + + local fenceindent + local fencehead = function(char, infostring) + return C(parsers.nonindentspace) / function(s) fenceindent = #s end + * Cg(char^3, "fencelength") + * parsers.optionalspace + * infostring + * (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, tilde_infostring) + * Cs(fencedline(parsers.tilde)^0) + * fencetail(parsers.tilde) + + local BacktickFencedCode + = fencehead(parsers.backtick, backtick_infostring) + * Cs(fencedline(parsers.backtick)^0) + * fencetail(parsers.backtick) + + local infostring_with_attributes + = Ct(C((parsers.linechar + - ( parsers.optionalspace + * parsers.attributes))^0) + * parsers.optionalspace + * Ct(parsers.attributes)) + + local FencedCode + = (TildeFencedCode + BacktickFencedCode) + / function(infostring, code) + local expanded_code = self.expandtabs(code) + + if allow_raw_blocks then + local raw_attr = lpeg.match(parsers.raw_attribute, + infostring) + if raw_attr then + return writer.rawBlock(expanded_code, raw_attr) + end + end + + local attr = nil + if allow_attributes then + local match = lpeg.match(infostring_with_attributes, + infostring) + if match then + infostring, attr = table.unpack(match) + end + end + return writer.fencedCode(expanded_code, infostring, attr) + end self.insert_pattern("Block after Verbatim", FencedCode, "FencedCode") @@ -23949,10 +24514,8 @@ M.extensions.fenced_code = function(blank_before_code_fence) if blank_before_code_fence then fencestart = parsers.fail else - fencestart = parsers.fencehead(parsers.backtick, - parsers.backtick_infostring) - + parsers.fencehead(parsers.tilde, - parsers.tilde_infostring) + fencestart = fencehead(parsers.backtick, backtick_infostring) + + fencehead(parsers.tilde, tilde_infostring) end self.update_rule("EndlineExceptions", function(previous_pattern) @@ -23962,6 +24525,7 @@ M.extensions.fenced_code = function(blank_before_code_fence) return previous_pattern + fencestart end) + self.add_special_character("`") self.add_special_character("~") end } @@ -24071,6 +24635,31 @@ M.extensions.fenced_divs = function(blank_before_div_fence) FencedDiv, "FencedDiv") self.add_special_character(":") + +% \end{macrocode} +% \par +% \begin{markdown} +% +% Patch blockquotes, so that they allow the end of a fenced div immediately +% afterwards. +% +% \end{markdown} +% \begin{macrocode} + local function check_div_level(s, i, current_level) -- luacheck: ignore s i + current_level = tonumber(current_level) + return current_level > 0 + end + + local is_inside_div = Cmt(Cb("div_level"), check_div_level) + local fencestart = is_inside_div * fenced_div_end + + self.update_rule("BlockquoteExceptions", function(previous_pattern) + if previous_pattern == nil then + previous_pattern = parsers.BlockquoteExceptions + end + return previous_pattern + fencestart + end) + % \end{macrocode} % \par % \begin{markdown} @@ -24082,13 +24671,6 @@ M.extensions.fenced_divs = function(blank_before_div_fence) % \end{markdown} % \begin{macrocode} if not blank_before_div_fence then - local function check_div_level(s, i, current_level) -- luacheck: ignore s i - current_level = tonumber(current_level) - return current_level > 0 - end - - local is_inside_div = Cmt(Cb("div_level"), check_div_level) - local fencestart = is_inside_div * fenced_div_end self.update_rule("EndlineExceptions", function(previous_pattern) if previous_pattern == nil then previous_pattern = parsers.EndlineExceptions @@ -24167,6 +24749,64 @@ end % \end{macrocode} % \begin{markdown} % +%#### Line Blocks +% +% The \luamdef{extensions.line_blocks} function implements the Pandoc line blocks +% syntax extension. +% +% \end{markdown} +% \begin{macrocode} +M.extensions.line_blocks = function() + return { + name = "built-in line_blocks syntax extension", + extend_writer = function(self) +% \end{macrocode} +% \par +% \begin{markdown} +% +% Define \luamdef{writer->lineblock} as a function that will transform +% a line block consisted of `lines` to the output format, with +% all but the last newline rendered as a line break. +% +% \end{markdown} +% \begin{macrocode} + function self.lineblock(lines) + if not self.is_writing then return "" end + local buffer = {} + for i = 1, #lines - 1 do + buffer[#buffer + 1] = { lines[i], self.linebreak } + end + buffer[#buffer + 1] = lines[#lines] + + return {"\\markdownRendererLineBlockBegin\n" + ,buffer, + "\n\\markdownRendererLineBlockEnd "} + end + end, extend_reader = function(self) + local parsers = self.parsers + local writer = self.writer + + local LineBlock = Ct( + (Cs( + ( (parsers.pipe * parsers.space)/"" + * ((parsers.space)/entities.char_entity("nbsp"))^0 + * parsers.linechar^0 * (parsers.newline/"")) + * (-parsers.pipe + * (parsers.space^1/" ") + * parsers.linechar^1 + * (parsers.newline/"") + )^0 + * (parsers.blankline/"")^0 + ) / self.parser_functions.parse_inlines)^1) / writer.lineblock + + self.insert_pattern("Block after Blockquote", + LineBlock, "LineBlock") + end + } +end +% \end{macrocode} +% \begin{markdown} +% %#### Notes % % The \luamdef{extensions.notes} function implements the Pandoc note @@ -24423,14 +25063,14 @@ end % %#### Raw Attributes % -% The \luamdef{extensions.raw_attribute} function implements the Pandoc -% raw attribute syntax extension. +% The \luamdef{extensions.raw_inline} function implements the Pandoc +% raw attribute syntax extension for inline code spans. % % \end{markdown} % \begin{macrocode} -M.extensions.raw_attribute = function() +M.extensions.raw_inline = function() return { - name = "built-in raw_attribute syntax extension", + name = "built-in raw_inline syntax extension", extend_writer = function(self) local options = self.options @@ -24449,59 +25089,15 @@ M.extensions.raw_attribute = function() return {"\\markdownRendererInputRawInline{", name,"}{", self.string(attr),"}"} end - - if options.fencedCode then -% \end{macrocode} -% \par -% \begin{markdown} -% -% Define \luamdef{writer->rawBlock} as a function that will transform an -% input raw block `s` with the raw attribute `attr` to the output format. -% -% \end{markdown} -% \begin{macrocode} - 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 + * parsers.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 @@ -24837,7 +25433,9 @@ function M.new(options) if options.fencedCode then local fenced_code_extension = M.extensions.fenced_code( - options.blankBeforeCodeFence) + options.blankBeforeCodeFence, + options.fencedCodeAttributes, + options.rawAttribute) table.insert(extensions, fenced_code_extension) end @@ -24865,8 +25463,8 @@ function M.new(options) end if options.rawAttribute then - local raw_attribute_extension = M.extensions.raw_attribute() - table.insert(extensions, raw_attribute_extension) + local raw_inline_extension = M.extensions.raw_inline() + table.insert(extensions, raw_inline_extension) end if options.strikeThrough then @@ -24884,6 +25482,11 @@ function M.new(options) table.insert(extensions, superscript_extension) end + if options.lineBlocks then + local line_block_extension = M.extensions.line_blocks() + table.insert(extensions, line_block_extension) + end + % \end{macrocode} % \begin{markdown} % @@ -25072,14 +25675,7 @@ if metadata.version ~= md.metadata.version then "markdown.lua " .. md.metadata.version .. ".") end local convert = md.new(options) -% \end{macrocode} -% \begin{markdown} -% Since the Lua converter expects \acro{unix} line endings, normalize the -% input. Also add a line ending at the end of the file in case the input file -% has none. -% \end{markdown} -% \begin{macrocode} -local output = convert(input:gsub("\r\n?", "\n") .. "\n") +local output = convert(input) if output_filename then local output_file = assert(io.open(output_filename, "w"), @@ -25186,12 +25782,14 @@ end \def\markdownRendererDlEndTightPrototype{}% \def\markdownRendererEmphasisPrototype#1{{\it#1}}% \def\markdownRendererStrongEmphasisPrototype#1{{\bf#1}}% -\def\markdownRendererBlockQuoteBeginPrototype{\par\begingroup\it}% +\def\markdownRendererBlockQuoteBeginPrototype{\begingroup\it}% \def\markdownRendererBlockQuoteEndPrototype{\endgroup\par}% +\def\markdownRendererLineBlockBeginPrototype{\begingroup\parindent=0pt}% +\def\markdownRendererLineBlockEndPrototype{\endgroup}% \def\markdownRendererInputVerbatimPrototype#1{% \par{\tt\input#1\relax{}}\par}% \def\markdownRendererInputFencedCodePrototype#1#2{% - \markdownRendererInputVerbatimPrototype{#1}}% + \markdownRendererInputVerbatim{#1}}% \def\markdownRendererHeadingOnePrototype#1{#1}% \def\markdownRendererHeadingTwoPrototype#1{#1}% \def\markdownRendererHeadingThreePrototype#1{#1}% @@ -25208,6 +25806,46 @@ end \def\markdownRendererStrikeThroughPrototype#1{#1}% \def\markdownRendererSuperscriptPrototype#1{#1}% \def\markdownRendererSubscriptPrototype#1{#1}% +\ExplSyntaxOn +\cs_gset:Npn + \markdownRendererHeaderAttributeContextBeginPrototype + { + \group_begin: + \color_group_begin: + } +\cs_gset:Npn + \markdownRendererHeaderAttributeContextEndPrototype + { + \color_group_end: + \group_end: + } +\cs_gset_eq:NN + \markdownRendererBracketedSpanAttributeContextBeginPrototype + \markdownRendererHeaderAttributeContextBeginPrototype +\cs_gset_eq:NN + \markdownRendererBracketedSpanAttributeContextEndPrototype + \markdownRendererHeaderAttributeContextEndPrototype +\cs_gset_eq:NN + \markdownRendererFencedDivAttributeContextBeginPrototype + \markdownRendererHeaderAttributeContextBeginPrototype +\cs_gset_eq:NN + \markdownRendererFencedDivAttributeContextEndPrototype + \markdownRendererHeaderAttributeContextEndPrototype +\cs_gset_eq:NN + \markdownRendererFencedCodeAttributeContextBeginPrototype + \markdownRendererHeaderAttributeContextBeginPrototype +\cs_gset_eq:NN + \markdownRendererFencedCodeAttributeContextEndPrototype + \markdownRendererHeaderAttributeContextEndPrototype +\cs_gset:Npn + \markdownRendererReplacementCharacterPrototype + { + % TODO: Replace with `\codepoint_generate:nn` in TeX Live 2023 + \sys_if_engine_pdftex:TF + { ^^ef^^bf^^bd } + { ^^^^fffd } + } +\ExplSyntaxOff % \end{macrocode} % \par % \begin{markdown} @@ -25221,19 +25859,40 @@ end % \end{markdown} % \begin{macrocode} \ExplSyntaxOn -\cs_gset:Npn - \markdownRendererInputRawInlinePrototype#1#2 +\cs_new:Nn + \@@_plain_tex_default_input_raw_inline_renderer_prototype:nn { \str_case:nn { #2 } { - { tex } { \markdownEscape{#1} } { md } { \markdownInput{#1} } + { tex } { \markdownEscape{#1} \unskip } } } -\cs_gset_eq:NN - \markdownRendererInputRawBlockPrototype - \markdownRendererInputRawInlinePrototype +\cs_new:Nn + \@@_plain_tex_default_input_raw_block_renderer_prototype:nn + { + \str_case:nn + { #2 } + { + { md } { \markdownInput{#1} } + { tex } { \markdownEscape{#1} } + } + } +\cs_gset:Npn + \markdownRendererInputRawInlinePrototype#1#2 + { + \@@_plain_tex_default_input_raw_inline_renderer_prototype:nn + { #1 } + { #2 } + } +\cs_gset:Npn + \markdownRendererInputRawBlockPrototype#1#2 + { + \@@_plain_tex_default_input_raw_block_renderer_prototype:nn + { #1 } + { #2 } + } \ExplSyntaxOff % \end{macrocode} % \par @@ -25878,7 +26537,7 @@ end % whether the shell access is enabled (`1`), disabled (`0`), or restricted % (`2`). % -% Inherit the value of the the `\pdfshellescape` (Lua\TeX{}, \Hologo{pdfTeX}) +% Inherit the value of the `\pdfshellescape` (Lua\TeX{}, \Hologo{pdfTeX}) % or the `\shellescape` (\Hologo{XeTeX}) commands. If neither of these % commands is defined and Lua is available, attempt to access the % `status.shell_escape` configuration item. @@ -26150,7 +26809,7 @@ end % has none. % \end{markdown} % \begin{macrocode} - print(convert(input:gsub("\r\n?", "\n") .. "\n"))}% + print(convert(input))}% % \end{macrocode} % \begin{markdown} % In case we were finalizing the frozen cache, increment \Opt{frozenCacheCounter}. @@ -26362,7 +27021,7 @@ end % % \end{markdown} % \begin{macrocode} -\renewcommand\markdownRendererInputFencedCode[2]{% +\renewcommand\markdownRendererInputFencedCodePrototype[2]{% \def\next##1 ##2\relax{% \ifthenelse{\equal{##1}{dot}}{% \markdownIfOption{frozenCache}{}{% @@ -26690,14 +27349,16 @@ end % \end{macrocode} % \par % \begin{markdown}% -% If the \Opt{tightLists} Lua option is disabled or the current document class -% is \pkg{beamer}, do not load the \pkg{paralist} package. +% If either the \Opt{tightLists} or the \Opt{fancyLists} Lua option is enabled +% and the current document class is not \pkg{beamer}, then load the +% \pkg{paralist} package. % % \end{markdown} % \begin{macrocode} -\markdownIfOption{tightLists}{ - \@ifclassloaded{beamer}{}{\RequirePackage{paralist}}% -}{} +\@ifclassloaded{beamer}{}{% + \markdownIfOption{tightLists}{\RequirePackage{paralist}}{}% + \markdownIfOption{fancyLists}{\RequirePackage{paralist}}{}% +} % \end{macrocode} % \par % \begin{markdown} @@ -26956,7 +27617,7 @@ end % % \end{markdown} % \begin{macrocode} - headerAttributeContextBegin = { + headerAttributeContextBegin = {% \markdownSetup{ rendererPrototypes = { attributeIdentifier = {% @@ -26978,46 +27639,92 @@ end }, }% }, + headerAttributeContextEnd = {}, superscript = {\textsuperscript{#1}}, subscript = {\textsubscript{#1}}, blockQuoteBegin = {\begin{quotation}}, blockQuoteEnd = {\end{quotation}}, inputVerbatim = {\VerbatimInput{#1}}, - inputFencedCode = {% - \ifx\relax#2\relax - \VerbatimInput{#1}% - \else - \@ifundefined{minted@code}{% - \@ifundefined{lst@version}{% - \markdownRendererInputFencedCode{#1}{}% + thematicBreak = {\noindent\rule[0.5ex]{\linewidth}{1pt}}, + note = {\footnote{#1}}}} % \end{macrocode} % \par % \begin{markdown} % -% When the \pkg{listings} package is loaded, use it for syntax highlighting. +%#### Fenced Code +% When no infostring has been specified, default to the indented code block +% renderer. % % \end{markdown} % \begin{macrocode} - }{% - \lstinputlisting[language=#2]{#1}% - }% +\RequirePackage{ltxcmds} +\ExplSyntaxOn +\cs_gset:Npn + \markdownRendererInputFencedCodePrototype#1#2 + { + \tl_if_empty:nTF + { #2 } + { \markdownRendererInputVerbatim{#1} } +% \end{macrocode} +% \begin{markdown} +% +% Otherwise, extract the first word of the infostring and treat it as the name +% of the programming language in which the code block is written. +% +% \end{markdown} +% \begin{macrocode} + { + \regex_extract_once:nnN + { \w* } + { #2 } + \l_tmpa_seq + \seq_pop_left:NN + \l_tmpa_seq + \l_tmpa_tl % \end{macrocode} % \par % \begin{markdown} % % When the \pkg{minted} package is loaded, use it for syntax highlighting. -% The \pkg{minted} package is preferred over \pkg{listings}. % % \end{markdown} % \begin{macrocode} - }{% - \catcode`\#=6\relax - \inputminted{#2}{#1}% - \catcode`\#=12\relax - }% - \fi}, - thematicBreak = {\noindent\rule[0.5ex]{\linewidth}{1pt}}, - note = {\footnote{#1}}}} + \ltx@ifpackageloaded + { minted } + { + \catcode`\#=6\relax + \exp_args:NV + \inputminted + \l_tmpa_tl + { #1 } + \catcode`\#=12\relax + } + { +% \end{macrocode} +% \par +% \begin{markdown} +% +% When the \pkg{listings} package is loaded, use it for syntax highlighting. +% +% \end{markdown} +% \begin{macrocode} + \ltx@ifpackageloaded + { listings } + { \lstinputlisting[language=\l_tmpa_tl]{#1} } +% \end{macrocode} +% \par +% \begin{markdown} +% +% When neither the \pkg{listings} package nor the \pkg{minted} package is +% loaded, act as though no infostring were given. +% +% \end{markdown} +% \begin{macrocode} + { \markdownRendererInputFencedCode{#1}{} } + } + } + } +\ExplSyntaxOff % \end{macrocode} % \par % \begin{markdown} @@ -27544,6 +28251,32 @@ end % \par % \begin{markdown} % +%#### Line Blocks +% Here is a basic implementation of line blocks. If the \pkg{verse} package is +% loaded, then it is used to produce the verses. +% +% \end{markdown} +% \begin{macrocode} + +\markdownIfOption{lineBlocks}{% + \RequirePackage{verse} + \markdownSetup{rendererPrototypes={ + lineBlockBegin = {% + \begingroup + \def\markdownRendererLineBreak{\\}% + \begin{verse}% + }, + lineBlockEnd = {% + \end{verse}% + \endgroup + }, + }} +}{} + +% \end{macrocode} +% \par +% \begin{markdown} +% %#### YAML Metadata {#latexyamlmetadata} % % The default setup of \acro{yaml} metadata will invoke the `\title`, @@ -27621,9 +28354,8 @@ end % %#### Raw Attribute Renderer Prototypes % -% In the raw block and inline raw span renderer prototypes, execute the content -% with TeX when the raw attribute is `tex` or `latex`, display the content as -% markdown when the raw attribute is `md`, and ignore the content otherwise. +% In the raw block and inline raw span renderer prototypes, default to the +% plain TeX renderer prototypes, translating raw attribute `latex` to `tex`. % % \end{markdown} % \begin{macrocode} @@ -27631,17 +28363,41 @@ end \cs_gset:Npn \markdownRendererInputRawInlinePrototype#1#2 { - \str_case:nn + \str_case:nnF { #2 } { - { tex } { \markdownEscape{#1} } - { latex } { \markdownEscape{#1} } - { md } { \markdownInput{#1} } + { latex } + { + \@@_plain_tex_default_input_raw_inline_renderer_prototype:nn + { #1 } + { tex } + } + } + { + \@@_plain_tex_default_input_raw_inline_renderer_prototype:nn + { #1 } + { #2 } + } + } +\cs_gset:Npn + \markdownRendererInputRawBlockPrototype#1#2 + { + \str_case:nnF + { #2 } + { + { latex } + { + \@@_plain_tex_default_input_raw_block_renderer_prototype:nn + { #1 } + { tex } + } + } + { + \@@_plain_tex_default_input_raw_block_renderer_prototype:nn + { #1 } + { #2 } } } -\cs_gset_eq:NN - \markdownRendererInputRawBlockPrototype - \markdownRendererInputRawInlinePrototype \ExplSyntaxOff \fi % Closes `\markdownIfOption{Plain}{\iffalse}{iftrue}` % \end{macrocode} @@ -27856,18 +28612,42 @@ end \def\markdownRendererStrongEmphasisPrototype#1{{\bf#1}}% \def\markdownRendererBlockQuoteBeginPrototype{\startquotation}% \def\markdownRendererBlockQuoteEndPrototype{\stopquotation}% +\def\markdownRendererLineBlockBeginPrototype{% + \begingroup + \def\markdownRendererLineBreak{ + }% + \startlines +}% +\def\markdownRendererLineBlockEndPrototype{% + \stoplines + \endgroup +}% \def\markdownRendererInputVerbatimPrototype#1{\typefile{#1}}% -\def\markdownRendererInputFencedCodePrototype#1#2{% - \ifx\relax#2\relax - \typefile{#1}% - \else % \end{macrocode} % \par % \begin{markdown} % -% The code fence infostring is used as a name from the \Hologo{ConTeXt} -% `\definetyping` macro. This allows the user to set up code highlighting -% mapping as follows: +%#### Fenced Code +% When no infostring has been specified, default to the indented code block +% renderer. +% +% \end{markdown} +% \begin{macrocode} +\ExplSyntaxOn +\cs_gset:Npn + \markdownRendererInputFencedCodePrototype#1#2 + { + \tl_if_empty:nTF + { #2 } + { \markdownRendererInputVerbatim{#1} } +% \end{macrocode} +% \par +% \begin{markdown} +% +% Otherwise, extract the first word of the infostring and treat it as the name +% of the programming language in which the code block is written. +% This name is then used in the \Hologo{ConTeXt} `\definetyping` macro, which +% allows the user to set up code highlighting mapping as follows: % ````` tex % % Map the `TEX` syntax highlighter to the `latex` infostring. % \definetyping [latex] @@ -27887,8 +28667,18 @@ end % % \end{markdown} % \begin{macrocode} - \typefile[#2][]{#1}% - \fi}% + { + \regex_extract_once:nnN + { \w* } + { #2 } + \l_tmpa_seq + \seq_pop_left:NN + \l_tmpa_seq + \l_tmpa_tl + \typefile[\l_tmpa_tl][]{#1} + } + } +\ExplSyntaxOff \def\markdownRendererHeadingOnePrototype#1{\chapter{#1}}% \def\markdownRendererHeadingTwoPrototype#1{\section{#1}}% \def\markdownRendererHeadingThreePrototype#1{\subsection{#1}}% @@ -27984,9 +28774,8 @@ end % %#### Raw Attribute Renderer Prototypes % -% In the raw block and inline raw span renderer prototypes, execute the content -% with TeX when the raw attribute is `tex` or `context`, display the content as -% markdown when the raw attribute is `md`, and ignore the content otherwise. +% In the raw block and inline raw span renderer prototypes, default to the +% plain TeX renderer prototypes, translating raw attribute `context` to `tex`. % % \end{markdown} % \begin{macrocode} @@ -27994,12 +28783,39 @@ end \cs_gset:Npn \markdownRendererInputRawInlinePrototype#1#2 { - \str_case:nn + \str_case:nnF { #2 } { - { tex } { \markdownEscape{#1} } - { context } { \markdownEscape{#1} } - { md } { \markdownInput{#1} } + { latex } + { + \@@_plain_tex_default_input_raw_inline_renderer_prototype:nn + { #1 } + { context } + } + } + { + \@@_plain_tex_default_input_raw_inline_renderer_prototype:nn + { #1 } + { #2 } + } + } +\cs_gset:Npn + \markdownRendererInputRawBlockPrototype#1#2 + { + \str_case:nnF + { #2 } + { + { context } + { + \@@_plain_tex_default_input_raw_block_renderer_prototype:nn + { #1 } + { tex } + } + } + { + \@@_plain_tex_default_input_raw_block_renderer_prototype:nn + { #1 } + { #2 } } } \cs_gset_eq:NN |