From d0d20a6ba7cff5159a2f78b414326262f45b0542 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 7 Aug 2021 20:19:27 +0000 Subject: markdown (7aug21) git-svn-id: svn://tug.org/texlive/trunk@60182 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/generic/markdown/docstrip.cfg | 4 +- .../source/generic/markdown/markdown.dtx | 1880 ++++++++++++++++---- .../source/generic/markdown/markdown.ins | 3 + 3 files changed, 1576 insertions(+), 311 deletions(-) (limited to 'Master/texmf-dist/source') diff --git a/Master/texmf-dist/source/generic/markdown/docstrip.cfg b/Master/texmf-dist/source/generic/markdown/docstrip.cfg index 60f15d39350..b1672cc2987 100644 --- a/Master/texmf-dist/source/generic/markdown/docstrip.cfg +++ b/Master/texmf-dist/source/generic/markdown/docstrip.cfg @@ -22,7 +22,7 @@ -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE^^J% -- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.^^J% -- ^^J% --- Copyright (C) 2016-2020 Vít Novotný^^J% +-- Copyright (C) 2016-2021 Vít Novotný^^J% -- ^^J% -- This work may be distributed and/or modified under the^^J% -- conditions of the LaTeX Project Public License, either version 1.3^^J% @@ -62,7 +62,7 @@ \let\luapostamble\empty \declarepreamble\texpreamble -Copyright (C) 2016-2020 Vít Novotný +Copyright (C) 2016-2021 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/source/generic/markdown/markdown.dtx b/Master/texmf-dist/source/generic/markdown/markdown.dtx index a3ebaecd88d..f035985ca80 100644 --- a/Master/texmf-dist/source/generic/markdown/markdown.dtx +++ b/Master/texmf-dist/source/generic/markdown/markdown.dtx @@ -2,7 +2,7 @@ %<*driver> \documentclass{ltxdockit} \usepackage[american]{babel} -\usepackage{amsmath,btxdockit,doc,fancyvrb,hologo,microtype,minted} +\usepackage{amsmath,btxdockit,doc,fancyvrb,graphicx,hologo,microtype,minted} \usepackage{fontspec} \defaultfontfeatures[\rmfamily,\sffamily,\ttfamily]{} @@ -21,6 +21,12 @@ \hypersetup{citecolor=spot} \let\oldCodelineNo\theCodelineNo \def\theCodelineNo{\textcolor[gray]{0.5}{\oldCodelineNo}} +\makeatletter\renewcommand\fps@figure{htbp}\makeatother +\setkeys{Gin}{ + width = \columnwidth, + height = 0.65\paperheight, + keepaspectratio, +} % Define some markup. \let\pkg\relax % A package name @@ -58,6 +64,8 @@ html, stripPercentSigns, underscores=false, + theme=witiko/dot, + theme=witiko/graphicx/http, ]{markdown} \markdownSetup{ renderers = { @@ -93,6 +101,12 @@ % Set up the bibliography. \begin{filecontents}[overwrite,nosearch,noheader]{markdown.bib} +@book{tantau21, + author = {Till Tantau and Joseph Wright and Vedran Miletić}, + title = {The Beamer class}, + date = {2021-02-10}, + url = {http://mirrors.ctan.org/macros/latex/contrib/beamer/doc/beameruserguide.pdf}, + urldate = {2021-02-11}} @online{sotkov17, author = {Sotkov, Anton}, title = {File transclusion syntax for Markdown}, @@ -153,6 +167,12 @@ isbn = {0-201-13447-0}, pagetotal = {ix, 479}, publisher = {Addison-Wesley}} +@online{novotny21, + author = {Novotný, Vít}, + title = {\Hologo{LaTeX2e} no longer keys packages by pathnames}, + date = {2021-02-20}, + url = {https://github.com/latex3/latex2e/issues/510}, + urldate = {2021-02-21}} \end{filecontents} \usepackage[ backend=biber, @@ -577,11 +597,11 @@ documentation][techdoc]. % \fi % \begin{macrocode} local metadata = { - version = "2.9.0", + version = "2.10.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-2020 Vít Novotný"}, + "2016-2021 Vít Novotný"}, license = "LPPL 1.3" } @@ -660,7 +680,10 @@ This should produce the following files: * `markdown.lua`, the Lua module, * `markdown-cli.lua`, the Lua command-line interface, * `markdown.tex`, the plain \TeX{} macro package, - * `markdown.sty`, the \LaTeX{} package, and + * `markdown.sty`, the \LaTeX{} package, + * `markdownthemewitiko_dot.sty`, the `witiko/dot` \LaTeX{} theme, + * `markdownthemewitiko_graphicx_http.sty`, the `witiko/graphicx/http` \LaTeX{} theme, + * `markdownthemewitiko_tilde.sty`, the `witiko/tilde` \LaTeX{} theme, and * `t-markdown.tex`, the \Hologo{ConTeXt} module. ### Local Installation @@ -673,6 +696,9 @@ placed: * `/scripts/markdown/markdown-cli.lua` * `/tex/generic/markdown/markdown.tex` * `/tex/latex/markdown/markdown.sty` + * `/tex/latex/markdown/markdownthemewitiko_dot.sty` + * `/tex/latex/markdown/markdownthemewitiko_graphicx_http.sty` + * `/tex/latex/markdown/markdownthemewitiko_tilde.sty` * `/tex/context/third/markdown/t-markdown.tex` where `` corresponds to a root of your \TeX{} distribution, such as @@ -686,6 +712,11 @@ Alternatively, you can also store the above files in the same folder as your \TeX{} document and distribute them together. This way your document can be portably typeset on legacy \TeX{} distributions. +Since Markdown version 2.10.0, the file `markdown.tex` must be placed in +a directory named `markdown` due to [issue #74][issue-74]. + + [issue-74]: https://github.com/witiko/markdown/issues/74 (Does not compile if user names own document markdown.tex) + % %<*lua> % \fi @@ -726,7 +757,18 @@ local lpeg = require("lpeg") % % \end{markdown} % \begin{macrocode} -local unicode = require("unicode") +local ran_ok, unicode = pcall(require, "unicode") +% \end{macrocode} +% \begin{markdown} +% +% If the Selene Unicode library is unavailable and we are using +% Lua${}\geq{}$5.3, we will use the built-in support for Unicode. +% +% \end{markdown} +% \begin{macrocode} +if not ran_ok then + unicode = {["utf8"]={char=utf8.char}} +end % \end{macrocode} % \par % \begin{markdown} @@ -801,12 +843,19 @@ local md5 = require("md5") % The \LaTeX{} part of the package requires that the \Hologo{LaTeX2e} format is % loaded, % \end{markdown} +% \iffalse +%<*latex-themes-witiko-dot,latex-themes-witiko-graphicx-http,latex-themes-witiko-tilde> +% \fi % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}% % \end{macrocode} +% \iffalse +% +% \fi % \begin{markdown} -% all the plain \TeX{} prerequisites (see Section \ref{sec:texprerequisites}), -% and the following \Hologo{LaTeX2e} packages: +% a \TeX{} engine that extends \Hologo{eTeX}, all the plain \TeX{} +% prerequisites (see Section \ref{sec:texprerequisites}), and the following +% \Hologo{LaTeX2e} packages: % % \pkg{keyval} % @@ -822,37 +871,38 @@ local md5 = require("md5") % \par % \begin{markdown} % -% \pkg{url} +% \pkg{xstring} % -%: A package that provides the \m{url} macro for the typesetting of -% \acro{url}s. It is used to provide the default token renderer prototype -% (see Section \ref{sec:texrendererprototypes}) for links. +%: A package that provides useful macros for manipulating strings of tokens. % % \end{markdown} % \begin{macrocode} -\RequirePackage{url} +\RequirePackage{xstring} % \end{macrocode} % \par % \begin{markdown} % +% The following packages are soft prerequisites and will not be loaded +% if the `plain` package option has been enabled (see Section +% \ref{sec:latexplain}): +% +% \pkg{url} +% +%: A package that provides the \m{url} macro for the typesetting of +% \acro{url}s. It is used to provide the default token renderer +% prototype (see Section \ref{sec:texrendererprototypes}) for links. +% % \pkg{graphicx} % %: A package that provides the \m{includegraphics} macro for the typesetting % of images. It is used to provide the corresponding default token renderer % prototype (see Section \ref{sec:texrendererprototypes}). % -% \end{markdown} -% \begin{macrocode} -\RequirePackage{graphicx} -% \end{macrocode} -% \par -% \begin{markdown} -% % \pkg{paralist} % %: A package that provides the \envm{compactitem}, \envm{compactenum}, and % \envm{compactdesc} macros for the typesetting of tight bulleted lists, -% ordered lists, and definition lists. It is used to provide the +% ordered lists, and definition lists. It is used to provide the % corresponding default token renderer prototypes (see Section % \ref{sec:texrendererprototypes}). % @@ -860,14 +910,9 @@ local md5 = require("md5") % %: A package that provides a concise syntax for the inspection of macro % values. It is used to determine whether or not the \pkg{paralist} package -% should be loaded based on the user options. -% -% \end{markdown} -% \begin{macrocode} -\RequirePackage{ifthen} -% \end{macrocode} -% \par -% \begin{markdown} +% should be loaded based on the user options, in the `witiko/dot` \LaTeX{} +% theme (see Section \ref{sec:latexthemes}), and to provide default token +% renderer prototypes (see Section \ref{sec:texrendererprototypes}). % % \pkg{fancyvrb} % @@ -876,34 +921,19 @@ local md5 = require("md5") % corresponding default token renderer prototype (see Section % \ref{sec:texrendererprototypes}). % -% \end{markdown} -% \begin{macrocode} -\RequirePackage{fancyvrb} -% \end{macrocode} -% \par -% \begin{markdown} -% % \pkg{csvsimple} % %: A package that provides the default token renderer prototype for % iA\,Writer content blocks with the \acro{csv} filename extension (see % Section \ref{sec:texrendererprototypes}). % -% \end{markdown} -% \begin{macrocode} -\RequirePackage{csvsimple} -% \end{macrocode} -% \par -% \begin{markdown} -% % \pkg{gobble} % -%: A package that provides the \m{\@gobblethree} \TeX{} command. +%: A package that provides the \m{\@gobblethree} \TeX{} command that +% is used in the default renderer prototype for citations (see +% Section \ref{sec:texrendererprototypes}). % % \end{markdown} -% \begin{macrocode} -\RequirePackage{gobble} -% \end{macrocode} % \iffalse % %<*context> @@ -963,8 +993,8 @@ Using a text editor, create a text document named `hello.lua` with the following content: ``` lua #!/usr/bin/env texlua -local kpse = require("kpse") -kpse.set_program_name("luatex") +local ran_ok, kpse = pcall(require, "kpse") +if ran_ok then kpse.set_program_name("luatex") end local markdown = require("markdown") local convert = markdown.new() print(convert("Hello *world*!")) @@ -1220,8 +1250,8 @@ Using a text editor, create a text document named `example.lua` with the following content: ``` lua #!/usr/bin/env texlua -local kpse = require("kpse") -kpse.set_program_name("luatex") +local ran_ok, kpse = pcall(require, "kpse") +if ran_ok then kpse.set_program_name("luatex") end local markdown = require("markdown") local input, convert_safe, convert_unsafe, paragraph @@ -1308,7 +1338,10 @@ following content: \input lmfonts \input safe +\begingroup +\catcode`\%=12 \input unsafe +\endgroup \bye ``````` Using a text editor, create a text document named `example.md` with the @@ -2677,13 +2710,13 @@ defaultOptions.breakableBlockquotes = false % : true - : Replace regular spaces with non-breakable spaces inside the prenotes + : Replace regular spaces with non-breaking spaces inside the prenotes and postnotes of citations produced via the pandoc citation syntax extension. false - : Do not replace regular spaces with non-breakable spaces inside the + : Do not replace regular spaces with non-breaking spaces inside the prenotes and postnotes of citations produced via the pandoc citation syntax extension. @@ -2729,7 +2762,7 @@ lualatex document.tex lualatex document.tex `````` A PDF document named `document.pdf` should be produced and contain the -following text, where the middot (`·`) denotes a non-breakable space: +following text, where the middot (`·`) denotes a non-breaking space: > The TeXbook [1, p.·123·and·130] is good. > @@ -4506,7 +4539,10 @@ following content: \input lmfonts \input optionfalse +\begingroup +\catcode`\%=12 \input optiontrue +\endgroup \bye ``````` Using a text editor, create a text document named `content.md` with the @@ -4666,7 +4702,7 @@ Using a text editor, create a text document named `document.tex` with the following content: ``` tex \documentclass{article} -\usepackage[footnotes, inlineFootnotes]{markdown} +\usepackage[inlineFootnotes]{markdown} \begin{document} \begin{markdown} Here is an inline note.^[Inlines notes are easier to @@ -4692,7 +4728,6 @@ Using a text editor, create a text document named `document.tex` with the following content: ``` tex \usemodule[t][markdown] -\def\markdownOptionFootnotes{true} \def\markdownOptionInlineFootnotes{true} \starttext \startmarkdown @@ -4920,10 +4955,9 @@ following content: ``` tex \documentclass{article} \usepackage{markdown} -\usepackage{filecontents} -\begin{filecontents*}{example.md} +\begin{filecontents}[overwrite,nosearch,noheader]{example.md} ## A section -\end{filecontents*} +\end{filecontents} \begin{document} \markdownInput[shiftHeadings=-1]{example.md} \markdownInput{example.md} @@ -5092,8 +5126,7 @@ following content: ``` tex \documentclass{article} \usepackage[headerAttributes]{markdown} -\usepackage{filecontents} -\begin{filecontents*}{hamlet.md} +\begin{filecontents}[overwrite,nosearch,noheader]{hamlet.md} # The Tragedy of Hamlet Shakespeare's longest play. @@ -5105,7 +5138,7 @@ Hamlet dies. ## Act I {#act-1} Hamlet talks to ghost. -\end{filecontents*} +\end{filecontents} \begin{document} \markdownInput[slice=^ ^act-3]{hamlet.md} \markdownInput[slice=act-1]{hamlet.md} @@ -5328,7 +5361,9 @@ following content: \usepackage{markdown} \markdownSetup{ renderers = { - ellipsis = {. . .} }} + ellipsis = {. . .} + } +} \begin{document} \begin{markdown} @@ -5520,6 +5555,109 @@ defaultOptions.startNumber = true % %<*manual-options> +#### Option `stripIndent` + +`stripIndent` (default value: `false`) + +% \fi +% \markdownBegin +% +% \Optitem[false]{stripIndent}{\opt{true}, \opt{false}} +% +: true + + : Strip the minimal indentation of non-blank lines from all + lines in a markdown document. Requires that the + \Opt{preserveTabs} Lua option is \opt{false}: + + ``` tex + \documentclass{article} + \usepackage[stripIndent]{markdown} + \begin{document} + \begin{markdown} + Hello *world*! + \end{markdown} + \end{document} + ``````` + +: false + + : Do not strip any indentation from the lines in a markdown + document. + +% \markdownEnd +% \iffalse + +##### Plain \TeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\input markdown +\def\markdownOptionStripIndent{true} +\markdownBegin + Hello *world*! +\markdownEnd +\bye +``````` +Next, invoke LuaTeX from the terminal: +``` sh +luatex document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the text +“Hello *world*!” + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\documentclass{article} +\usepackage[stripIndent]{markdown} +\begin{document} + \begin{markdown} + Hello *world*! + \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 +text “Hello *world*!” + +##### \Hologo{ConTeXt} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\usemodule[t][markdown] +\def\markdownOptionStripIndent{true} +\starttext + \startmarkdown + Hello *world*! + \stopmarkdown +\stoptext +```````` +Next, invoke LuaTeX from the terminal: +``` sh +context document.tex +````` +A PDF document named `document.pdf` should be produced and contain the +text “Hello *world*!” + +% +%<*lua,lua-cli> +% \fi +% \begin{macrocode} +defaultOptions.stripIndent = false +% \end{macrocode} +% \par +% \iffalse +% +%<*manual-options> + #### Option `tableCaptions` `tableCaptions` (default value: `false`) @@ -5634,6 +5772,110 @@ defaultOptions.tableCaptions = false % %<*manual-options> +#### Option `texComments` + +`texComments` (default value: `false`) + +% \fi +% \markdownBegin +% +% \Optitem[false]{texComments}{\opt{true}, \opt{false}} +% +: true + + : Strip \TeX{}-style comments. + + ``` tex + \documentclass{article} + \usepackage[texComments]{markdown} + \begin{document} + \begin{markdown} + Hel% this is a comment + lo *world*! + \end{markdown} + \end{document} + ``````` + +: false + + : Do not strip \TeX{}-style comments. + +% \markdownEnd +% \iffalse + +##### Plain \TeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\input markdown +\def\markdownOptionTeXComments{true} +\markdownBegin +Hel% this is a comment + lo *world*! +\markdownEnd +\bye +``````` +Next, invoke LuaTeX from the terminal: +``` sh +luatex document.tex +`````` +A PDF document named `document.pdf` should be produced and contain the text +“Hello *world*!” + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\documentclass{article} +\usepackage[texComments]{markdown} +\begin{document} +\begin{markdown} +Hel% this is a comment + lo *world*! +\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 +text “Hello *world*!” + +##### \Hologo{ConTeXt} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\usemodule[t][markdown] +\def\markdownOptionTeXComments{true} +\starttext +\startmarkdown +Hel% this is a comment + lo *world*! +\stopmarkdown +\stoptext +```````` +Next, invoke LuaTeX from the terminal: +``` sh +context document.tex +````` +A PDF document named `document.pdf` should be produced and contain the +text “Hello *world*!” + +% +%<*lua,lua-cli> +% \fi +% \begin{macrocode} +defaultOptions.texComments = false +% \end{macrocode} +% \par +% \iffalse +% +%<*manual-options> + #### Option `tightLists` @@ -6096,8 +6338,8 @@ pdftex --shell-escape document.tex % % \end{markdown} % \begin{macrocode} -\def\markdownLastModified{2020/09/14}% -\def\markdownVersion{2.9.0}% +\def\markdownLastModified{2021/08/06}% +\def\markdownVersion{2.10.0}% % \end{macrocode} % \par % \begin{markdown} @@ -6483,7 +6725,9 @@ bug](https://github.com/witiko/markdown/issues). \let\markdownOptionSlice\undefined \let\markdownOptionSmartEllipses\undefined \let\markdownOptionStartNumber\undefined +\let\markdownOptionStripIndent\undefined \let\markdownOptionTableCaptions\undefined +\let\markdownOptionTeXComments\undefined \let\markdownOptionTightLists\undefined % \end{macrocode} % \par @@ -7062,7 +7306,7 @@ Next, invoke LuaTeX from the terminal: luatex document.tex `````` A PDF document named `document.pdf` should be produced and contain the -following text, where the middot (`·`) denotes a non-breakable space: +following text, where the middot (`·`) denotes a non-breaking space: > Bartel·Leendert van·der·Waerden @@ -7090,7 +7334,7 @@ Next, invoke LuaTeX from the terminal: lualatex document.tex `````` A PDF document named `document.pdf` should be produced and contain the -following text, where the middot (`·`) denotes a non-breakable space: +following text, where the middot (`·`) denotes a non-breaking space: > Bartel·Leendert van·der·Waerden @@ -7113,7 +7357,7 @@ Next, invoke LuaTeX from the terminal: context document.tex `````` A PDF document named `document.pdf` should be produced and contain the -following text, where the middot (`·`) denotes a non-breakable space: +following text, where the middot (`·`) denotes a non-breaking space: > Bartel·Leendert van·der·Waerden @@ -7619,12 +7863,11 @@ Using a text editor, create a text document named `document.tex` with the following content: ``` tex \documentclass{article} -\usepackage{filecontents} -\begin{filecontents*}{markdown-languages.json} +\begin{filecontents}[overwrite,nosearch,noheader]{markdown-languages.json} { "json": "JavaScript Object Notation", } -\end{filecontents*} +\end{filecontents} \usepackage[contentBlocks]{markdown} \markdownSetup{ renderers = { @@ -8171,7 +8414,8 @@ an ordered list. The macro receives no arguments. The \mdef{markdownRendererOlItemWithNumber} macro represents an item in an ordered list. This macro will only be produced, when the \Opt{startNumber} -option is enabled. The macro receives no arguments. +option is enabled. The macro receives a single numeric argument that +corresponds to the item number. % \end{markdown} % @@ -9997,7 +10241,7 @@ A PDF document named `document.pdf` should be produced and contain the following text: > This is a parenthesized citation *abrahams90* with a prefix see -> and a postfix *pp. > 12*, and a citation *eijkhout91* with a +> and a postfix *pp. 12*, and a citation *eijkhout91* with a > postfix *pp. 34*. % @@ -10180,8 +10424,6 @@ following content: : Demonstration of pipe table syntax \end{markdown} \end{document} -\end{markdown} -\end{document} ``````` Next, invoke LuaTeX from the terminal: ``` sh @@ -10220,47 +10462,110 @@ following text: % % \begin{markdown} -### Token Renderer Prototypes +#### Inline HTML Comment Renderer +The \mdef{markdownRendererInlineHtmlComment} macro represents the contents of an +inline \acro{HTML} comment. This macro will only be produced, when the +\Opt{html} option is enabled. The macro receives a single argument that +corresponds to the contents of the \acro{HTML} comment. -% \label{sec:texrendererprototypes} -% % \end{markdown} -% \iffalse - -By default, token renderers point to package-defined \TeX{} macros, further -referred to as *prototypes*, which provide useful default definitions. - -% \fi % % \iffalse -##### Plain \TeX{} Example {.unnumbered} +##### \LaTeX{} Example {.unnumbered} Using a text editor, create a text document named `document.tex` with the following content: ``` tex -\input markdown -\def\markdownRendererTildePrototype{% - Packages can specify token renderer prototypes.% -} -\markdownBegin -~ -\markdownEnd - -\def\markdownRendererTilde{% - User-defined token renderers take precedence.% +\documentclass{article} +\usepackage[html]{markdown} +\usepackage{marginnote} +\markdownSetup{ + renderers = { + inlineHtmlComment = {\marginnote{#1}}, + }, } -\markdownBegin -~ -\markdownEnd -\bye +\begin{document} +\begin{markdown} +A useful use of HTML comments are side notes. + +\end{markdown} +\end{document} ``````` Next, invoke LuaTeX from the terminal: ``` sh -luatex document.tex +lualatex document.tex +lualatex document.tex `````` A PDF document named `document.pdf` should be produced and contain the -following text: +following body text: + +> A useful use of HTML comments are side notes. + +The horizontal margins should contain the following text: + +> Side notes are displayed in the horizontal margins next to the relevant +> passages, which makes them easier for the reader to find than footnotes. + +% +%<*tex> +% \fi +% +% \begin{macrocode} +\def\markdownRendererInlineHtmlComment{% + \markdownRendererInlineHtmlCommentPrototype}% +% \end{macrocode} +% \par +% +% \iffalse +% +%<*manual-tokens> +% \fi +% +% \begin{markdown} + +### Token Renderer Prototypes + +% \label{sec:texrendererprototypes} +% +% \end{markdown} +% \iffalse + +By default, token renderers point to package-defined \TeX{} macros, further +referred to as *prototypes*, which provide useful default definitions. + +% \fi +% +% \iffalse + +##### Plain \TeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\input markdown +\def\markdownRendererTildePrototype{% + Packages can specify token renderer prototypes.% +} +\markdownBegin +~ +\markdownEnd + +\def\markdownRendererTilde{% + User-defined token renderers take precedence.% +} +\markdownBegin +~ +\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: > Packages can specify token renderer prototypes. > @@ -10410,6 +10715,7 @@ following text: \def\markdownRendererCitePrototype#1{}% \def\markdownRendererTextCitePrototype#1{}% \def\markdownRendererTablePrototype#1#2#3{}% +\def\markdownRendererInlineHtmlCommentPrototype#1{}% % \end{macrocode} % \par % \begin{markdown} @@ -10418,27 +10724,9 @@ following text: % The \mdef{markdownInfo}, \mdef{markdownWarning}, and \mdef{markdownError} % macros perform logging for the Markdown package. Their first argument % specifies the text of the info, warning, or error message. -% -% \end{markdown} -% \begin{macrocode} -\def\markdownInfo#1{}% -\def\markdownWarning#1{}% -% \end{macrocode} -% \par -% \begin{markdown} -% % The \m{markdownError} macro receives a second argument that provides a help -% text. -% -% \end{markdown} -% \begin{macrocode} -\def\markdownError#1#2{}% -% \end{macrocode} -% \par -% \begin{markdown} -% -% You may redefine these macros to redirect and process the info, warning, and -% error messages. +% text. You may redefine these macros to redirect and process the info, +% warning, and error messages. % %### Miscellanea % The \mdef{markdownMakeOther} macro is used by the package, when a \TeX{} @@ -10677,31 +10965,566 @@ pdflatex --shell-escape document.tex % % The \LaTeX{} options are represented by a comma-delimited list of % \meta{key}`=`\meta{value} pairs. For boolean options, the `=`\meta{value} -% part is optional, and \meta{key} will be interpreted as \meta{key}`=true`. +% part is optional, and \meta{key} will be interpreted as \meta{key}`=true` +% if the `=`\meta{value} part has been omitted. % -% The \LaTeX{} options map directly to the options recognized by the plain +% Except for the `plain` option described in Section \ref{sec:latexplain}, and +% the \LaTeX{} themes described in Section \ref{sec:latexthemes}, and the +% \LaTeX{} setup snippets described in Section \ref{sec:latexsetupsnippets}, +% \LaTeX{} options map directly to the options recognized by the plain % \TeX{} interface (see Section \ref{sec:texoptions}) and to the markdown token % renderers and their prototypes recognized by the plain \TeX{} interface (see % Sections \ref{sec:texrenderersuser} and \ref{sec:texrendererprototypes}). % -% The \LaTeX{} options may be specified when loading the \LaTeX{} package (see -% Section \ref{sec:latexinterface}), when using the \envm{markdown*} \LaTeX{} -% environment, or via the \mdef{markdownSetup} macro. The \m{markdownSetup} -% macro receives the options to set up as its only argument. +% The \LaTeX{} options may be specified when loading the \LaTeX{} package, when +% using the \envm{markdown*} \LaTeX{} environment or the \m{markdownInput} +% macro (see Section \ref{sec:latexinterface}), or via the \mdef{markdownSetup} +% macro. The \m{markdownSetup} macro receives the options to set up as its only +% argument: % % \markdownEnd % \begin{macrocode} \newcommand\markdownSetup[1]{% \setkeys{markdownOptions}{#1}}% % \end{macrocode} +% \begin{markdown} +% +% We may also store \LaTeX{} options as *setup snippets* and invoke them later +% using the \mdef{markdownSetupSnippet} macro. The \m{markdownSetupSnippet} +% macro receives two arguments: the name of the setup snippet and the options +% to store: +% +% \end{markdown} +% \begin{macrocode} +\newcommand\markdownSetupSnippet[2]{% + \@ifundefined + {markdownLaTeXSetupSnippet\markdownLaTeXThemeName#1}{% + \newtoks\next + \next={#2}% + \expandafter\let\csname markdownLaTeXSetupSnippet% + \markdownLaTeXThemeName#1\endcsname=\next + }{% + \markdownWarning + {Redefined setup snippet \markdownLaTeXThemeName#1}% + \csname markdownLaTeXSetupSnippet% + \markdownLaTeXThemeName#1\endcsname={#2}% + }}% +% \end{macrocode} +% \begin{markdown} +% +% See Section \ref{sec:latexthemes} for information on interactions between +% setup snippets and \LaTeX{} themes. See Section \ref{sec:latexsetupsnippets} +% for information about invoking the stored setup snippets. +% +% \end{markdown} +% \iffalse +% +%<*manual-options> + +### \LaTeX{} + +\LaTeX{} options allow us to disable the redefinition of the default renderer +prototypes from plain \TeX{}, load user-contributed themes, and invoke +user-defined setup snippets. + +% \fi +% \par +% \begin{markdown} + +#### No default token renderer prototypes +% \label{sec:latexplain} +Default token renderer prototypes require \LaTeX{} packages that may clash with +other packages used in a document. Additionally, if we redefine token +renderers and renderer prototypes ourselves, the default definitions will bring +no benefit to us. Using the `plain` package option, we can keep the default +definitions from the plain \TeX{} implementation (see Section +\ref{sec:textokenrendererprototypes}) and prevent the soft \LaTeX{} +prerequisites in Section \ref{sec:latexprerequisites} from being loaded: + +``` tex +\usepackage[plain]{markdown} +``````` + +% \end{markdown} +% \iffalse +% +%<*latex> +% \fi +% \begin{macrocode} +\newif\ifmarkdownLaTeXPlain + \markdownLaTeXPlainfalse +\define@key{markdownOptions}{plain}[true]{% + \ifmarkdownLaTeXLoaded + \markdownWarning + {The plain option must be specified when loading the package}% + \else + \markdownLaTeXPlaintrue + \fi} +% \end{macrocode} +% \iffalse +% +%<*manual-options> +% \fi +% \begin{markdown} + +#### \LaTeX{} themes +% \label{sec:latexthemes} + +User-contributed \LaTeX{} themes for the Markdown package provide a +domain-specific interpretation of some Markdown tokens. Similarly to \LaTeX{} +packages, themes allow the authors to achieve a specific look and other +high-level goals without low-level programming. + +% The \LaTeX{} option with key `theme` loads a \LaTeX{} package (further +% referred to as *a theme*) named `markdowntheme`\meta{munged theme +% name}`.sty`, where the *munged theme name* is the *theme name* after a +% substitution of all forward slashes (\texttt{/}) for an underscore +% (\texttt{_}), the theme name is a value that is *qualified* and contains no +% underscores, and a value is qualified if and only if it contains at least one +% forward slash. Themes are inspired by the Beamer \LaTeX{} package, which +% provides similar functionality with its \m{usetheme} macro [@tantau21, +% Section 15.1]. +% +% Theme names must be qualified to minimize naming conflicts between different +% themes intended for a single \LaTeX{} document class or for a single \LaTeX{} +% package. The preferred format of a theme name is \meta{theme author}`/`\meta{target \LaTeX{} document class or package}`/`\meta{private naming +% scheme}, where the *private naming scheme* may contain additional forward +% slashes. For example, a theme by a user `witiko` for the MU theme of the +% Beamer document class may have the name `witiko/beamer/MU`. +% +% Theme names are munged, because \LaTeX{} packages are identified only by +% their filenames, not by their pathnames. [@novotny21] Therefore, we can't +% store the qualified theme names directly using directories, but we must +% encode the individual segments of the qualified theme in the filename. For +% example, loading a theme named `witiko/beamer/MU` would load a \LaTeX{} +% package named `markdownthemewitiko_beamer_MU.sty`. +% +% If the \LaTeX{} option with key `theme` is (repeatedly) specified in the +% \m{usepackage} macro, the loading of the theme(s) will be postponed in +% first-in-first-out order until after the Markdown \LaTeX{} package has been +% loaded. Otherwise, the theme(s) will be loaded immediately. For example, +% there is a theme named `witiko/dot`, which typesets fenced code blocks with +% the `dot` infostring as images of directed graphs rendered by the Graphviz +% tools. The following code would first load the Markdown package, then the +% `markdownthemewitiko_beamer_MU.sty` \LaTeX{} package, and finally the +% `markdownthemewitiko_dot.sty` \LaTeX{} package: +% \end{markdown} +% \iffalse + +For example, to load themes named `witiko/beamer/MU` and `witiko/dot`, you +would use the following code in the preamble of your document: + +% \fi % \par % \begin{markdown} + +``` tex +\usepackage[ + theme = witiko/beamer/MU, + theme = witiko/dot, +]{markdown} +``````` + +% \end{markdown} +% \iffalse +% +%<*latex> +% \fi +% \begin{macrocode} +\newif\ifmarkdownLaTeXLoaded + \markdownLaTeXLoadedfalse +\AtEndOfPackage{\markdownLaTeXLoadedtrue}% +\define@key{markdownOptions}{theme}{% + \IfSubStr{#1}{/}{}{% + \markdownError + {Won't load theme with unqualified name #1}% + {Theme names must contain at least one forward slash}}% + \StrSubstitute{#1}{/}{_}[\markdownLaTeXThemePackageName]% + \edef\markdownLaTeXThemePackageName{% + markdowntheme\markdownLaTeXThemePackageName}% + \expandafter\markdownLaTeXThemeLoad\expandafter{% + \markdownLaTeXThemePackageName}{#1/}}% +\newcommand\markdownLaTeXThemeName{}% +\newcommand\markdownLaTeXThemeLoad[2]{% + \ifmarkdownLaTeXLoaded + \def\markdownLaTeXThemeName{#2}% + \RequirePackage{#1}% + \def\markdownLaTeXThemeName{}% + \else + \AtEndOfPackage{% + \def\markdownLaTeXThemeName{#2}% + \RequirePackage{#1}% + \def\markdownLaTeXThemeName{}}% + \fi}% +% \end{macrocode} +% \begin{markdown} +% +% The \LaTeX{} themes have a useful synergy with the setup snippets (see +% Section \ref{sec:latexoptions}): To make it less likely that different +% themes will define setup snippets with the same name, we will prepend +% \meta{theme name}`/` before the snippet name and use the result as the +% snippet name. For example, if the `witiko/dot` theme defines the `product` +% setup snippet, the setup snippet will be available under the name +% `witiko/dot/product`. % +% \end{markdown} +% \iffalse +% +%<*manual-options> +% \fi +% \begin{markdown} + +Due to limitations of \LaTeX{}, themes may not be loaded after the +beginning of a \LaTeX{} document. + +% \end{markdown} +% \iffalse +% +%<*latex> +% \fi +% \begin{macrocode} +\@onlypreamble\KV@markdownOptions@theme +% \end{macrocode} +% \iffalse +% +%<*manual-options> +% \fi +% \par +% \markdownBegin + +Example themes provided with the Markdown package include: + +\pkg{witiko/dot} + +: A theme that typesets fenced code blocks with the `dot …` infostring + as images of directed graphs rendered by the Graphviz tools. The + right tail of the infostring is used as the image title. +% ```` tex +% \documentclass{article} +% \usepackage[theme=witiko/dot]{markdown} +% \setkeys{Gin}{ +% width = \columnwidth, +% height = 0.65\paperheight, +% keepaspectratio} +% \begin{document} +% \begin{markdown} +% ``` dot Various formats of mathemathical formulae +% digraph tree { +% margin = 0; +% rankdir = "LR"; +% +% latex -> pmml; +% latex -> cmml; +% pmml -> slt; +% cmml -> opt; +% cmml -> prefix; +% cmml -> infix; +% pmml -> mterms [style=dashed]; +% cmml -> mterms; +% +% latex [label = "LaTeX"]; +% pmml [label = "Presentation MathML"]; +% cmml [label = "Content MathML"]; +% slt [label = "Symbol Layout Tree"]; +% opt [label = "Operator Tree"]; +% prefix [label = "Prefix"]; +% infix [label = "Infix"]; +% mterms [label = "M-Terms"]; +% } +% ``` +% \end{markdown} +% \end{document} +% ```````` +% Typesetting the above document produces the output shown in +% Figure~\ref{fig:witiko/dot}. +% ``` dot Various formats of mathemathical formulae \label{fig:witiko/dot} +% digraph tree { +% margin = 0; +% rankdir = "LR"; +% +% latex -> pmml; +% latex -> cmml; +% pmml -> slt; +% cmml -> opt; +% cmml -> prefix; +% cmml -> infix; +% pmml -> mterms [style=dashed]; +% cmml -> mterms; +% +% latex [label = "LaTeX"]; +% pmml [label = "Presentation MathML"]; +% cmml [label = "Content MathML"]; +% slt [label = "Symbol Layout Tree"]; +% opt [label = "Operator Tree"]; +% prefix [label = "Prefix"]; +% infix [label = "Infix"]; +% mterms [label = "M-Terms"]; +% } +% ``` + The theme requires a Unix-like operating system with GNU Diffutils and + Graphviz installed. The theme also requires shell access unless the + \m{markdownOptionFrozenCache} plain \TeX{} option is enabled. + +% \markdownEnd +% \iffalse + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +```` tex +\documentclass{article} +\usepackage[theme=witiko/dot]{markdown} +\setkeys{Gin}{ + width=\columnwidth, + height=0.65\paperheight, + keepaspectratio} +\begin{document} +\begin{markdown} +``` dot Various formats of mathemathical formulae +digraph tree { + margin = 0; + rankdir = "LR"; + + latex -> pmml; + latex -> cmml; + pmml -> slt; + cmml -> opt; + cmml -> prefix; + cmml -> infix; + pmml -> mterms [style=dashed]; + cmml -> mterms; + + latex [label = "LaTeX"]; + pmml [label = "Presentation MathML"]; + cmml [label = "Content MathML"]; + slt [label = "Symbol Layout Tree"]; + opt [label = "Operator Tree"]; + prefix [label = "Prefix"]; + infix [label = "Infix"]; + mterms [label = "M-Terms"]; +} +``` +\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 +a drawing of a directed graph similar to Figure 1 from the following +conference article: + +> NOVOTNÝ, Vít, Petr SOJKA, Michal ŠTEFÁNIK and Dávid LUPTÁK. Three is Better +> than One: Ensembling Math Information Retrieval Systems. *CEUR Workshop +> Proceedings*. Thessaloniki, Greece: M. Jeusfeld c/o Redaktion Sun SITE, +> Informatik V, RWTH Aachen., 2020, vol. 2020, No 2696, p. 1-30. ISSN 1613-0073. +> + +% +%<*latex-themes-witiko-dot> +% \fi +% \begin{macrocode} +\ProvidesPackage{markdownthemewitiko_dot}[2021/03/09]% +% \end{macrocode} +% \iffalse +% +%<*manual-options> +% \fi +% \par +% \markdownBegin + +\pkg{witiko/graphicx/http} + +: A theme that adds support for downloading images whose URL has the + http or https protocol. +% ``` tex +% \documentclass{article} +% \usepackage[theme=witiko/graphicx/http]{markdown} +% \begin{document} +% \begin{markdown} +% ![img](https://github.com/witiko/markdown/raw/master/banner.png +% "The banner of the Markdown package") +% \end{markdown} +% \end{document} +% ``````` +% Typesetting the above document produces the output shown in +% Figure~\ref{fig:witiko/graphicx/http}. +% ![img](https://github.com/witiko/markdown/raw/master/banner.png +% "The banner of the Markdown package \label{fig:witiko/graphicx/http}") + The theme requires the \pkg{catchfile} \LaTeX{} package and a Unix-like + operating system with GNU Coreutils `md5sum` and either GNU Wget or cURL + installed. The theme also requires shell access unless the + \m{markdownOptionFrozenCache} plain \TeX{} option is enabled. + +% \markdownEnd +% \iffalse + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\documentclass{article} +\usepackage[theme=witiko/graphicx/http]{markdown} +\begin{document} +\begin{markdown} +![img](https://github.com/witiko/markdown/raw/master/banner.png + "The banner of the Markdown package") +\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 image: + +> ![img](https://github.com/witiko/markdown/raw/master/banner.png +> "The banner of the Markdown package") + +% +%<*latex-themes-witiko-graphicx-http> +% \fi +% \begin{macrocode} +\ProvidesPackage{markdownthemewitiko_graphicx_http}[2021/03/22]% +\RequirePackage{catchfile} +% \end{macrocode} +% \iffalse +% +%<*manual-options> +% \fi +% \par +% \markdownBegin + +\pkg{witiko/tilde} + +: A theme that makes tilde (`~`) always typeset the non-breaking space even + when the \Opt{hybrid} Lua option is `false`. +% ``` tex +% \documentclass{article} +% \usepackage[theme=witiko/tilde]{markdown} +% \begin{document} +% \begin{markdown} +% Bartel~Leendert van~der~Waerden +% \end{markdown} +% \end{document} +% ``````` +% Typesetting the above document produces the following text: +% “Bartel~Leendert van~der~Waerden”. +% +% \markdownEnd +% \iffalse + +##### \LaTeX{} Example {.unnumbered} + +Using a text editor, create a text document named `document.tex` with the +following content: +``` tex +\documentclass{article} +\usepackage[theme=witiko/tilde]{markdown} +\begin{document} +\begin{markdown} +Bartel~Leendert van~der~Waerden +\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, where the middot (`·`) denotes a non-breaking space: + +> Bartel·Leendert van·der·Waerden + +% +%<*latex-themes-witiko-tilde> +% \fi +% \begin{macrocode} +\ProvidesPackage{markdownthemewitiko_tilde}[2021/03/22]% +% \end{macrocode} +% \iffalse +% +%<*manual-options> +% \fi +% \par +% \begin{markdown} +% +% Please, see Section~\ref{sec:latexthemesimplementation} for implementation +% details of the example themes. + +#### \LaTeX{} setup snippets +% \label{sec:latexsetupsnippets} +% \end{markdown} +% \iffalse + +User-contributed \LaTeX{} themes provide global control over high-level goals. +However, it is often desirable to change only some local aspects of a document. +\LaTeX{} setup snippets provide syntactic sugar for defining and invoking +various options locally. + +% \fi +% \begin{markdown} +% The \LaTeX{} option with key `snippet` invokes a snippet named \meta{value}: +% \end{markdown} +% \iffalse +% +%<*latex> +% \fi +% \begin{macrocode} +\define@key{markdownOptions}{snippet}{% + \expandafter\markdownSetup\expandafter{% + \the\csname markdownLaTeXSetupSnippet#1\endcsname}}% +% \end{macrocode} +% \iffalse +% +%<*manual-options> +% \fi +% \par +% \markdownBegin + +Here is how we can use setup snippets to store options and invoke them later: + +``` tex +\markdownSetupSnippet{romanNumerals}{ + renderers = { + olItemWithNumber = {% + \item[\romannumeral#1\relax.]% + }, + }, +} +\begin{markdown} + +The following ordered list will be preceded by arabic numerals: + +1. wahid +2. aithnayn + +\end{markdown} +\begin{markdown*}{snippet=romanNumerals} + +The following ordered list will be preceded by roman numerals: + +3. tres +4. quattuor + +\end{markdown*} + +``````` + %#### Plain \TeX{} Interface Options % The following options map directly to the option macros exposed by the plain % \TeX{} interface (see Section \ref{sec:texoptions}). % -% \end{markdown} +% \markdownEnd +% \iffalse +% +%<*latex> +% \fi % \begin{macrocode} \define@key{markdownOptions}{helperScriptFileName}{% \def\markdownOptionHelperScriptFileName{#1}}% @@ -10761,8 +11584,12 @@ pdflatex --shell-escape document.tex \def\markdownOptionSlice{#1}}% \define@key{markdownOptions}{startNumber}[true]{% \def\markdownOptionStartNumber{#1}}% +\define@key{markdownOptions}{stripIndent}[true]{% + \def\markdownOptionStripIndent{#1}}% \define@key{markdownOptions}{tableCaptions}[true]{% \def\markdownOptionTableCaptions{#1}}% +\define@key{markdownOptions}{texComments}[true]{% + \def\markdownOptionTeXComments{#1}}% \define@key{markdownOptions}{tightLists}[true]{% \def\markdownOptionTightLists{#1}}% \define@key{markdownOptions}{underscores}[true]{% @@ -10949,6 +11776,8 @@ pdflatex --shell-escape document.tex \renewcommand\markdownRendererTextCite[1]{#1}}% \define@key{markdownRenderers}{table}{% \renewcommand\markdownRendererTable[3]{#1}}% +\define@key{markdownRenderers}{inlineHtmlComment}{% + \renewcommand\markdownRendererInlineHtmlComment[1]{#1}}% % \end{macrocode} % \par % \begin{markdown} @@ -11092,6 +11921,8 @@ pdflatex --shell-escape document.tex \renewcommand\markdownRendererTextCitePrototype[1]{#1}}% \define@key{markdownRendererPrototypes}{table}{% \renewcommand\markdownRendererTablePrototype[3]{#1}}% +\define@key{markdownRendererPrototypes}{inlineHtmlComment}{% + \renewcommand\markdownRendererInlineHtmlCommentPrototype[1]{#1}}% % \end{macrocode} % \par % \begin{markdown} @@ -11175,6 +12006,7 @@ texexec --passon=--shell-escape document.tex % \end{markdown} % \begin{macrocode} \writestatus{loading}{ConTeXt User Module / markdown}% +\startmodule[markdown] \unprotect % \end{macrocode} % \par @@ -11294,7 +12126,8 @@ function util.cache(dir, string, salt, transform, suffix) local name = util.pathname(dir, digest .. suffix) local file = io.open(name, "r") if file == nil then -- If no cache entry exists, then create a new one. - local file = assert(io.open(name, "w")) + local file = assert(io.open(name, "w"), + [[could not open file "]] .. name .. [[" for writing]]) local result = string if transform ~= nil then result = transform(result) @@ -13671,7 +14504,8 @@ M.writer = {} % % The objects produced by the \luam{writer.new} method expose instance methods % and variables of their own. As a convention, I will refer to these -% \meta{member}s as `writer->`\meta{member}. +% \meta{member}s as `writer->`\meta{member}. All member variables are +% immutable unless explicitly stated otherwise. % % \end{markdown} % \begin{macrocode} @@ -13693,7 +14527,8 @@ function M.writer.new(options) % \begin{markdown} % % Parse the \Opt{slice} option and define \luamdef{writer->slice\_begin} -% \luamdef{writer->slice\_end}, and \luamdef{writer->is\_writing}. +% \luamdef{writer->slice\_end}, and \luamdef{writer->is\_writing}. The +% \luam{writer->is\_writing} member variable is mutable. % % \end{markdown} % \begin{macrocode} @@ -13847,9 +14682,10 @@ function M.writer.new(options) % Define a table \luamdef{escaped_chars} containing the mapping from special % plain \TeX{} characters (including the active pipe character (`|`) of % \Hologo{ConTeXt}) to their escaped variants. Define tables -% \luamdef{escaped_minimal_chars} and \luamdef{escaped_minimal_strings} -% containing the mapping from special plain characters and character strings -% that need to be escaped even in content that will not be typeset. +% \luamdef{escaped_uri_chars}, \luamdef{escaped_citation_chars}, and +% \luamdef{escaped_minimal_strings} containing the mapping from special plain +% characters and character strings that need to be escaped even in content +% that will not be typeset. % % \end{markdown} % \begin{macrocode} @@ -13886,10 +14722,10 @@ function M.writer.new(options) % \par % \begin{markdown} % -% Use the \luam{escaped_chars} table to create an escaper function -% \luamdef{escape} and the \luam{escaped_minimal_chars} and -% \luam{escaped_minimal_strings} tables to create an escaper function -% \luamdef{escape_minimal}. +% Use the \luam{escaped_chars}, \luam{escaped_uri_chars}, +% \luam{escaped_citation_chars}, and \luam{escaped_minimal_strings} tables +% to create the \luamdef{escape}, \luamdef{escape_citation}, and +% \luamdef{escape_uri} escaper functions. % % \end{markdown} % \begin{macrocode} @@ -13902,10 +14738,12 @@ function M.writer.new(options) % \begin{markdown} % % Define \luamdef{writer->string} as a function that will transform an input -% plain text span `s` to the output format and \luamdef{writer->uri} as a -% function that will transform an input \acro{uri} `u` to the output format. -% If the \Opt{hybrid} option is enabled, use identity functions. Otherwise, -% use the \luam{escape} and \luam{escape_minimal} functions. +% plain text span `s` to the output format, \luamdef{writer->citation} as a +% function that will transform an input citation name `c` to the output format, +% and \luamdef{writer->uri} as a function that will transform an input +% \acro{uri} `u` to the output format. If the \Opt{hybrid} option is enabled, +% use identity functions. Otherwise, use the \luam{escape}, +% \luam{escape_citation}, and \luam{escape_uri} functions. % % \end{markdown} % \begin{macrocode} @@ -13922,13 +14760,25 @@ function M.writer.new(options) % \par % \begin{markdown} % +% Define \luamdef{writer->escape} as a function that will transform an input +% plain text span to the output format. Unlike the \luam{writer->string} +% function, \luam{writer->escape} always uses the \luam{escape} function, +% even when the \Opt{hybrid} option is enabled. +% +% \end{markdown} +% \begin{macrocode} + self.escape = escape +% \end{macrocode} +% \par +% \begin{markdown} +% % Define \luamdef{writer->code} as a function that will transform an input % inlined code span `s` to the output format. % % \end{markdown} % \begin{macrocode} function self.code(s) - return {"\\markdownRendererCodeSpan{",escape(s),"}"} + return {"\\markdownRendererCodeSpan{",self.escape(s),"}"} end % \end{macrocode} % \par @@ -13942,7 +14792,7 @@ function M.writer.new(options) % \begin{macrocode} function self.link(lab,src,tit) return {"\\markdownRendererLink{",lab,"}", - "{",self.string(src),"}", + "{",self.escape(src),"}", "{",self.uri(src),"}", "{",self.string(tit or ""),"}"} end @@ -13957,6 +14807,7 @@ function M.writer.new(options) % \end{markdown} % \begin{macrocode} function self.table(rows, caption) + if not self.is_writing then return "" end local buffer = {"\\markdownRendererTable{", caption or "", "}{", #rows - 1, "}{", #rows[1], "}"} local temp = rows[2] -- put alignments on the first row @@ -13970,10 +14821,10 @@ function M.writer.new(options) end table.insert(buffer, column) if i > 1 then - table.insert(buffer, "}%\n") + table.insert(buffer, "}") end end - table.insert(buffer, "}%\n") + table.insert(buffer, "}") end return buffer end @@ -13999,20 +14850,34 @@ function M.writer.new(options) % % The \luamdef{languages_json} table maps programming language filename % extensions to fence infostrings. All \luam{options.contentBlocksLanguageMap} -% files located by \pkg{kpathsea} are loaded into a chain of tables. +% files located by the KPathSea library are loaded into a chain of tables. % \luam{languages_json} corresponds to the first table and is chained with % the rest via Lua metatables. % % \end{markdown} % \begin{macrocode} local languages_json = (function() - local kpse = require("kpse") - kpse.set_program_name("luatex") + local ran_ok, kpse = pcall(require, "kpse") + if ran_ok then + kpse.set_program_name("luatex") +% \end{macrocode} +% \begin{markdown} +% +% If the KPathSea library is unavailable, perhaps because we are using +% LuaMeta\TeX, we will only locate the \luam{options.contentBlocksLanguageMap} +% in the current working directory: +% +% \end{markdown} +% \begin{macrocode} + else + kpse = {lookup=function(filename, options) return filename end} + end 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]=') + for _, filename in ipairs{kpse.lookup(options.contentBlocksLanguageMap, + { all=true })} do + local file = io.open(filename, "r") + if not file then goto continue end + json = file:read("*all"):gsub('("[^\n]-"):','[%1]=') curr = (function() local _ENV={ json=json, load=load } -- run in sandbox return load("return "..json)() @@ -14025,6 +14890,7 @@ function M.writer.new(options) end prev = curr end + ::continue:: end return base or {} end)() @@ -14137,15 +15003,15 @@ function M.writer.new(options) % \par % \begin{markdown} % -% Define \luamdef{writer->inline_html} and \luamdef{writer->display_html} -% as functions that will transform an inline or block \acro{html} element -% respectively to the output format, where `html` is the \acro{html} -% input. +% Define \luamdef{writer->inline_html_comment} as a function that will +% transform the contents of an inline \acro{HTML} comment, to the output +% format, where `contents` are the contents of the \acro{HTML} comment. % % \end{markdown} % \begin{macrocode} - function self.inline_html(html) return "" end - function self.display_html(html) return "" end + function self.inline_html_comment(contents) + return {"\\markdownRendererInlineHtmlComment{",contents,"}"} + end % \end{macrocode} % \par % \begin{markdown} @@ -14255,8 +15121,9 @@ function M.writer.new(options) % \par % \begin{markdown} % -% Define \luamdef{writer->active_headings} as a stack of identifiers -% of the headings that are currently active. +% Define \luamdef{writer->active\_headings} as a stack of identifiers +% of the headings that are currently active. The +% \luam{writer->active\_headings} member variable is mutable. % % \end{markdown} % \begin{macrocode} @@ -14339,42 +15206,93 @@ function M.writer.new(options) % \par % \begin{markdown} % -% Define \luamdef{writer->note} as a function that will transform an -% input footnote `s` to the output format. +% Define \luamdef{writer->note} as a function that will transform an +% input footnote `s` to the output format. +% +% \end{markdown} +% \begin{macrocode} + function self.note(s) + return {"\\markdownRendererFootnote{",s,"}"} + end +% \end{macrocode} +% \par +% \begin{markdown} +% +% Define \luamdef{writer->citations} as a function that will transform an +% input array of citations `cites` to the output format. If `text_cites` +% is enabled, the citations should be rendered in-text, when applicable. +% The `cites` array contains tables with the following keys and values: +% \begin{itemize} +% \item`suppress_author` -- If the value of the key is true, then the +% author of the work should be omitted in the citation, when applicable. +% \item`prenote` -- The value of the key is either `nil` or a rope +% that should be inserted before the citation. +% \item`postnote` -- The value of the key is either `nil` or a rope +% that should be inserted after the citation. +% \item`name` -- The value of this key is the citation name. +% \end{itemize} +% +% \end{markdown} +% \begin{macrocode} + function self.citations(text_cites, cites) + local buffer = {"\\markdownRenderer", text_cites and "TextCite" or "Cite", + "{", #cites, "}"} + for _,cite in ipairs(cites) do + buffer[#buffer+1] = {cite.suppress_author and "-" or "+", "{", + cite.prenote or "", "}{", cite.postnote or "", "}{", cite.name, "}"} + end + return buffer + end +% \end{macrocode} +% \par +% \begin{markdown} +% +% Define \luamdef{writer->get_state} as a function that returns the current +% state of the writer, where the state of a writer are its mutable member +% variables. +% +% \end{markdown} +% \begin{macrocode} + function self.get_state() + return { + is_writing=self.is_writing, + active_headings={table.unpack(self.active_headings)}, + } + end +% \end{macrocode} +% \par +% \begin{markdown} +% +% Define \luamdef{writer->set_state} as a function that restores the input +% state `s` and returns the previous state of the writer. % % \end{markdown} % \begin{macrocode} - function self.note(s) - return {"\\markdownRendererFootnote{",s,"}"} + function self.set_state(s) + previous_state = self.get_state() + for key, value in pairs(state) do + self[key] = value + end + return previous_state end % \end{macrocode} % \par % \begin{markdown} % -% Define \luamdef{writer->citations} as a function that will transform an -% input array of citations `cites` to the output format. If `text_cites` -% is enabled, the citations should be rendered in-text, when applicable. -% The `cites` array contains tables with the following keys and values: -% \begin{itemize} -% \item`suppress_author` -- If the value of the key is true, then the -% author of the work should be omitted in the citation, when applicable. -% \item`prenote` -- The value of the key is either `nil` or a rope -% that should be inserted before the citation. -% \item`postnote` -- The value of the key is either `nil` or a rope -% that should be inserted after the citation. -% \item`name` -- The value of this key is the citation name. -% \end{itemize} +% Define \luamdef{writer->defer_call} as a function that will encapsulate the +% input function `f`, so that `f` is called with the state of the writer at the +% time of calling \luam{writer->defer_call}. % % \end{markdown} % \begin{macrocode} - function self.citations(text_cites, cites) - local buffer = {"\\markdownRenderer", text_cites and "TextCite" or "Cite", - "{", #cites, "}"} - for _,cite in ipairs(cites) do - buffer[#buffer+1] = {cite.suppress_author and "-" or "+", "{", - cite.prenote or "", "}{", cite.postnote or "", "}{", cite.name, "}"} + function self.defer_call(f) + state = self.get_state() + return function(...) + state = self.set_state(state) + local return_value = f(...) + self.set_state(state) + return return_value end - return buffer end return self @@ -14428,6 +15346,7 @@ parsers.semicolon = P(";") parsers.exclamation = P("!") parsers.pipe = P("|") parsers.tilde = P("~") +parsers.backslash = P("\\") parsers.tab = P("\t") parsers.newline = P("\n") parsers.tightblocksep = P("\001") @@ -14450,7 +15369,7 @@ parsers.any = P(1) parsers.fail = parsers.any - 1 parsers.escapable = S("\\`*_{}[]()+_.!<>#-~:^@;") -parsers.anyescaped = P("\\") / "" * parsers.escapable +parsers.anyescaped = parsers.backslash / "" * parsers.escapable + parsers.any parsers.spacechar = S("\t ") @@ -14483,6 +15402,30 @@ parsers.spnl = parsers.optionalspace parsers.line = parsers.linechar^0 * parsers.newline parsers.nonemptyline = parsers.line - parsers.blankline +parsers.commented_line = Cs(((parsers.linechar -- initial + - parsers.backslash + - parsers.percent)^1 + + (parsers.backslash -- even backslash + * parsers.backslash)^1 + + (parsers.backslash -- odd backslash + * parsers.backslash)^0 + * (parsers.backslash / "" + * parsers.percent + + parsers.backslash + * (parsers.linechar -- initial + + parsers.newline + - parsers.backslash + - parsers.percent)) + )^0) + * ((parsers.percent -- comment + * parsers.line + * #parsers.blankline) -- blank line + / "\n" + + parsers.percent -- comment + * parsers.line + * parsers.optionalspace -- leading tabs and spaces + + C(parsers.newline)) + parsers.chunk = parsers.line * (parsers.optionallyindentedline - parsers.blankline)^0 @@ -14959,9 +15902,13 @@ parsers.htmlattribute = parsers.spacing^1 * parsers.sp * parsers.equal * parsers.sp * parsers.htmlattributevalue -parsers.htmlcomment = P(""))^0 * P("-->") +parsers.htmlcomment = P(""))^0) + * parsers.optionalspace + * P("-->") -parsers.htmlinstruction = P("" ))^0 * P("?>" ) +parsers.htmlinstruction = P(""))^0 * P("?>") parsers.openelt_any = parsers.less * parsers.keyword * parsers.htmlattribute^0 * parsers.sp * parsers.more @@ -15008,17 +15955,11 @@ end parsers.in_matched_block_tags = parsers.less * Cmt(#parsers.openelt_block, parse_matched_tags) -parsers.displayhtml = parsers.htmlcomment +parsers.displayhtml = parsers.htmlcomment / "" + parsers.emptyelt_block + parsers.openelt_exact("hr") + parsers.in_matched_block_tags + parsers.htmlinstruction - -parsers.inlinehtml = parsers.emptyelt_any - + parsers.htmlcomment - + parsers.htmlinstruction - + parsers.openelt_any - + parsers.closeelt_any % \end{macrocode} % \par % \begin{markdown} @@ -15204,15 +16145,29 @@ function M.reader.new(writer, options) % \end{markdown} % \begin{macrocode} local function normalize_tag(tag) - return unicode.utf8.lower( + return string.lower( gsub(util.rope_to_string(tag), "[ \n\r\t]+", " ")) end % \end{macrocode} % \par % \begin{markdown} % +% Define \luamdef{iterlines} as a function that iterates over the lines of +% the input string `s`, transforms them using an input function `f`, and +% reassembles them into a new string, which it returns. +% +% \end{markdown} +% \begin{macrocode} + local function iterlines(s, f) + rope = lpeg.match(Ct((parsers.line / f)^1), s) + return util.rope_to_string(rope) + end +% \end{macrocode} +% \par +% \begin{markdown} +% % Define \luamdef{expandtabs} either as an identity function, when the -% \Opt{preserveTabs} Lua inrerface option is enabled, or to a function that +% \Opt{preserveTabs} Lua interface option is enabled, or to a function that % expands tabs into spaces otherwise. % % \end{markdown} @@ -15223,7 +16178,7 @@ function M.reader.new(writer, options) else expandtabs = function(s) if s:find("\t") then - return s:gsub("[^\n]*", util.expand_tabs_in_line) + return iterlines(s, util.expand_tabs_in_line) else return s end @@ -15248,8 +16203,52 @@ function M.reader.new(writer, options) % % \end{markdown} % \begin{macrocode} - local function create_parser(name, grammar) + local function create_parser(name, grammar, toplevel) return function(str) +% \end{macrocode} +% \par +% \begin{markdown} +% +% If the parser is top-level and the \Opt{stripIndent} Lua option is enabled, +% we will first expand tabs in the input string `str` into spaces and then we +% will count the minimum indent across all lines, skipping blank lines. Next, +% we will remove the minimum indent from all lines. +% +% \end{markdown} +% \begin{macrocode} + if toplevel and options.stripIndent then + local min_prefix_length, min_prefix = nil, '' + str = iterlines(str, function(line) + if lpeg.match(parsers.nonemptyline, line) == nil then + return line + end + line = util.expand_tabs_in_line(line) + prefix = lpeg.match(C(parsers.optionalspace), line) + local prefix_length = #prefix + local is_shorter = min_prefix_length == nil + is_shorter = is_shorter or prefix_length < min_prefix_length + if is_shorter then + min_prefix_length, min_prefix = prefix_length, prefix + end + return line + end) + str = str:gsub('^' .. min_prefix, '') + end +% \end{macrocode} +% \par +% \begin{markdown} +% +% If the parser is top-level and the \Opt{texComments} Lua option is +% enabled, we will strip all plain \TeX{} comments from the input string `str` +% together with the trailing newline characters. +% +% \end{markdown} +% \begin{macrocode} + if toplevel and options.texComments then + str = lpeg.match(Ct(parsers.commented_line^1), str) + str = util.rope_to_string(str) + print(str) + end local res = lpeg.match(grammar(), str) if res == nil then error(format("%s failed on:\n%s", name, str:sub(1,20))) @@ -15263,37 +16262,43 @@ function M.reader.new(writer, options) = create_parser("parse_blocks", function() return larsers.blocks - end) + end, false) local parse_blocks_toplevel = create_parser("parse_blocks_toplevel", function() return larsers.blocks_toplevel - end) + end, true) local parse_inlines = create_parser("parse_inlines", function() return larsers.inlines - end) + end, false) local parse_inlines_no_link = create_parser("parse_inlines_no_link", function() return larsers.inlines_no_link - end) + end, false) local parse_inlines_no_inline_note = create_parser("parse_inlines_no_inline_note", function() return larsers.inlines_no_inline_note - end) + end, false) + + local parse_inlines_no_html + = create_parser("parse_inlines_no_html", + function() + return larsers.inlines_no_html + end, false) local parse_inlines_nbsp = create_parser("parse_inlines_nbsp", function() return larsers.inlines_nbsp - end) + end, false) % \end{macrocode} % \par % \begin{markdown} @@ -15381,14 +16386,14 @@ function M.reader.new(writer, options) -- like indirect_link local function lookup_note(ref) - return function() + return writer.defer_call(function() local found = rawnotes[normalize_tag(ref)] if found then return writer.note(parse_blocks_toplevel(found)) else return {"[", parse_inlines("^" .. ref), "]"} end - end + end) end local function register_note(ref,rawnote) @@ -15480,27 +16485,27 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline -- lookup link reference and return a link, if the reference is found, -- or a bracketed label otherwise. local function indirect_link(label,sps,tag) - return function() + return writer.defer_call(function() local r,fallback = lookup_reference(label,sps,tag) if r then return writer.link(parse_inlines_no_link(label), r.url, r.title) else return fallback end - end + end) end -- lookup image reference and return an image, if the reference is found, -- or a bracketed label otherwise. local function indirect_image(label,sps,tag) - return function() + return writer.defer_call(function() local r,fallback = lookup_reference(label,sps,tag) if r then return writer.image(writer.string(label), r.url, r.title) else return {"!", fallback} end - end + end) end % \end{macrocode} % \par @@ -15602,7 +16607,7 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline * C(parsers.alphanumeric^1 * P("://") * parsers.urlchar^1) * parsers.more / function(url) - return writer.link(writer.string(url), url) + return writer.link(writer.escape(url), url) end larsers.AutoLinkEmail = parsers.less @@ -15610,7 +16615,7 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline * P("@") * parsers.urlchar^1) * parsers.more / function(email) - return writer.link(writer.string(email), + return writer.link(writer.escape(email), "mailto:"..email) end @@ -15642,20 +16647,22 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline larsers.Image = larsers.DirectImage + larsers.IndirectImage - larsers.TextCitations = Ct(Cc("") + larsers.TextCitations = Ct((parsers.spnl + * Cc("") * parsers.citation_name * ((parsers.spnl * parsers.lbracket * parsers.citation_headless_body - * parsers.rbracket) + Cc(""))) + * parsers.rbracket) + Cc("")))^1) / function(raw_cites) return larsers.citations(true, raw_cites) end larsers.ParenthesizedCitations - = Ct(parsers.lbracket + = Ct((parsers.spnl + * parsers.lbracket * parsers.citation_body - * parsers.rbracket) + * parsers.rbracket)^1) / function(raw_cites) return larsers.citations(false, raw_cites) end @@ -15666,9 +16673,14 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline larsers.UlOrStarLine = parsers.asterisk^4 + parsers.underscore^4 / writer.string - larsers.EscapedChar = S("\\") * C(parsers.escapable) / writer.string + larsers.EscapedChar = parsers.backslash * C(parsers.escapable) / writer.string - larsers.InlineHtml = C(parsers.inlinehtml) / writer.inline_html + larsers.InlineHtml = parsers.emptyelt_any + + (parsers.htmlcomment / parse_inlines_no_html) + / writer.inline_html_comment + + parsers.htmlinstruction + + parsers.openelt_any + + parsers.closeelt_any larsers.HtmlEntity = parsers.hexentity / entities.hex_entity / writer.string + parsers.decentity / entities.dec_entity / writer.string @@ -15686,8 +16698,7 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline * parsers.contentblock_tail / writer.contentblock - larsers.DisplayHtml = C(parsers.displayhtml) - / expandtabs / writer.display_html + larsers.DisplayHtml = parsers.displayhtml larsers.Verbatim = Cs( (parsers.blanklines * ((parsers.indentedline - parsers.blankline))^1)^1 @@ -16044,6 +17055,10 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline syntax.Smart = parsers.fail end + if options.preserveTabs then + options.stripIndent = false + end + if not options.pipeTables then syntax.PipeTable = parsers.fail end @@ -16067,6 +17082,12 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline inlines_no_inline_note_t.InlineNote = parsers.fail larsers.inlines_no_inline_note = Ct(inlines_no_inline_note_t) + local inlines_no_html_t = util.table_copy(inlines_t) + inlines_no_html_t.DisplayHtml = parsers.fail + inlines_no_html_t.InlineHtml = parsers.fail + inlines_no_html_t.HtmlEntity = parsers.fail + larsers.inlines_no_html = Ct(inlines_no_html_t) + local inlines_nbsp_t = util.table_copy(inlines_t) inlines_nbsp_t.Endline = larsers.NonbreakingEndline inlines_nbsp_t.Space = larsers.NonbreakingSpace @@ -16125,10 +17146,12 @@ larsers.PipeTable = Ct(larsers.table_row * parsers.newline else mode = "w" end - file = assert(io.open(options.frozenCacheFileName, mode)) - assert(file:write([[\expandafter\def\csname markdownFrozenCache]] .. - options.frozenCacheCounter .. [[\endcsname{]] .. output .. [[}]] .. - "\n")) + file = assert(io.open(options.frozenCacheFileName, mode), + [[could not open file "]] .. options.frozenCacheFileName + .. [[" for writing]]) + assert(file:write([[\expandafter\global\expandafter\def\csname ]] + .. [[markdownFrozenCache]] .. options.frozenCacheCounter + .. [[\endcsname{]] .. output .. [[}]] .. "\n")) assert(file:close()) end return output @@ -16172,7 +17195,8 @@ return M local input if input_filename then - local input_file = assert(io.open(input_filename, "r")) + local input_file = assert(io.open(input_filename, "r"), + [[could not open file "]] .. input_filename .. [[" for reading]]) input = assert(input_file:read("*a")) assert(input_file:close()) else @@ -16189,8 +17213,8 @@ if options.cacheDir and not lfs.isdir(options.cacheDir) then assert(lfs.mkdir(options["cacheDir"])) end -local kpse = require("kpse") -kpse.set_program_name("luatex") +local ran_ok, kpse = pcall(require, "kpse") +if ran_ok then kpse.set_program_name("luatex") end local md = require("markdown") % \end{macrocode} % \begin{markdown} @@ -16214,7 +17238,8 @@ local convert = md.new(options) local output = convert(input:gsub("\r\n?", "\n") .. "\n") if output_filename then - local output_file = assert(io.open(output_filename, "w")) + local output_file = assert(io.open(output_filename, "w"), + [[could not open file "]] .. output_filename .. [[" for writing]]) assert(output_file:write(output)) assert(output_file:close()) else @@ -16241,13 +17266,19 @@ end % % \end{markdown} % \begin{macrocode} -\def\markdownInfo#1{% - \immediate\write-1{(l.\the\inputlineno) markdown.tex info: #1.}}% -\def\markdownWarning#1{% - \immediate\write16{(l.\the\inputlineno) markdown.tex warning: #1}}% -\def\markdownError#1#2{% - \errhelp{#2.}% - \errmessage{(l.\the\inputlineno) markdown.tex error: #1}}% +\ifx\markdownInfo\undefined + \def\markdownInfo#1{% + \immediate\write-1{(l.\the\inputlineno) markdown.tex info: #1.}}% +\fi +\ifx\markdownWarning\undefined + \def\markdownWarning#1{% + \immediate\write16{(l.\the\inputlineno) markdown.tex warning: #1}}% +\fi +\ifx\markdownError\undefined + \def\markdownError#1#2{% + \errhelp{#2.}% + \errmessage{(l.\the\inputlineno) markdown.tex error: #1}}% +\fi % \end{macrocode} % \par % \begin{markdown} @@ -16270,6 +17301,7 @@ end % \begin{markdown} % %### Token Renderer Prototypes +% \label{sec:textokenrendererprototypes} % The following definitions should be considered placeholder. % % \end{markdown} @@ -16425,9 +17457,15 @@ end \ifx\markdownOptionStartNumber\undefined\else startNumber = \markdownOptionStartNumber, \fi +\ifx\markdownOptionStripIndent\undefined\else + stripIndent = \markdownOptionStripIndent, +\fi \ifx\markdownOptionTableCaptions\undefined\else tableCaptions = \markdownOptionTableCaptions, \fi +\ifx\markdownOptionTeXComments\undefined\else + texComments = \markdownOptionTeXComments, +\fi \ifx\markdownOptionTightLists\undefined\else tightLists = \markdownOptionTightLists, \fi @@ -16793,8 +17831,8 @@ end "|markdownOptionHelperScriptFileName"}% |immediate|write|markdownOutputFileStream{% local ran_ok, error = pcall(function() - local kpse = require("kpse") - kpse.set_program_name("luatex") + local ran_ok, kpse = pcall(require, "kpse") + if ran_ok then kpse.set_program_name("luatex") end #1 end) % \end{macrocode} @@ -16891,6 +17929,15 @@ end |gdef|markdownInput#1{% % \end{macrocode} % \begin{markdown} +% Change the category code of the percent sign (`%`) to other, so that a user +% of the \Opt{hybrid} Lua option or a malevolent actor can't produce TeX +% comments in the plain TeX output of the Markdown package. +% \end{markdown} +% \begin{macrocode} + |begingroup + |catcode`|%=12 +% \end{macrocode} +% \begin{markdown} % If we are reading from the frozen cache, input it, expand the corresponding % `\markdownFrozenCache`\meta{number} macro, and increment % \m{markdownFrozenCacheCounter}. @@ -16905,7 +17952,7 @@ end |markdownInfo{Including markdown document number "|the|markdownFrozenCacheCounter" from frozen cache}% |csname markdownFrozenCache|the|markdownFrozenCacheCounter|endcsname - |advance|markdownFrozenCacheCounter by 1|relax + |global|advance|markdownFrozenCacheCounter by 1|relax }{% |markdownInfo{Including markdown document "#1"}% % \end{macrocode} @@ -16919,7 +17966,8 @@ end |closein|markdownInputFileStream |markdownLuaExecute{% |markdownPrepare - local file = assert(io.open("#1", "r")) + local file = assert(io.open("#1", "r"), + [[could not open file "#1" for reading]]) local input = assert(file:read("*a")) assert(file:close()) % \end{macrocode} @@ -16937,9 +17985,10 @@ end % \end{markdown} % \begin{macrocode} |markdownIfOption{FinalizeCache}{% - |advance|markdownFrozenCacheCounter by 1|relax + |global|advance|markdownFrozenCacheCounter by 1|relax }% }% + |endgroup }% |endgroup % \end{macrocode} @@ -16958,9 +18007,16 @@ end % format~[@latex17, Section 9]. As a consequence, we can directly reuse the % existing plain \TeX{} implementation. % +% The \LaTeX{} implementation redefines the plain \TeX{} logging macros (see +% Section \ref{sec:texinterfacelogging}) to use the \LaTeX{} \m{PackageInfo}, +% \m{PackageWarning}, and \m{PackageError} macros. +% % \end{markdown} % \begin{macrocode} -\input markdown +\newcommand\markdownInfo[1]{\PackageInfo{markdown}{#1}}% +\newcommand\markdownWarning[1]{\PackageWarning{markdown}{#1}}% +\newcommand\markdownError[2]{\PackageError{markdown}{#1}{#2.}}% +\input markdown/markdown \def\markdownVersionSpace{ }% \ProvidesPackage{markdown}[\markdownLastModified\markdownVersionSpace v% \markdownVersion\markdownVersionSpace markdown renderer]% @@ -16975,9 +18031,6 @@ end % % \end{markdown} % \begin{macrocode} -\renewcommand\markdownInfo[1]{\PackageInfo{markdown}{#1}}% -\renewcommand\markdownWarning[1]{\PackageWarning{markdown}{#1}}% -\renewcommand\markdownError[2]{\PackageError{markdown}{#1}{#2.}}% % \end{macrocode} % \par % \begin{markdown} @@ -17041,7 +18094,6 @@ end \expandafter\markdownSetup\expandafter{\CurrentOption}}% \ProcessOptions\relax % \end{macrocode} -% \par % \begin{markdown} % % After processing the options, activate the `renderers` and @@ -17059,8 +18111,229 @@ end % \par % \begin{markdown} % +%#### \LaTeX{} Themes +% \label{sec:latexthemesimplementation} +% This section implements example themes provided with the Markdown package. +% +% The `witiko/dot` theme enables the \Opt{fencedCode} Lua option: +% +% \end{markdown} +% \iffalse +% +%<*latex-themes-witiko-dot> +% \fi +% \begin{macrocode} +\markdownSetup{fencedCode}% +% \end{macrocode} +% \begin{markdown} +% +% We store the previous definition of the fenced code token renderer prototype: +% +% \end{markdown} +% \begin{macrocode} +\let\markdown@witiko@dot@oldRendererInputFencedCodePrototype + \markdownRendererInputFencedCodePrototype +% \end{macrocode} +% \begin{markdown} +% +% If the infostring starts with `dot …`, we redefine the fenced code block +% token renderer prototype, so that it typesets the code block via Graphviz +% tools if and only if the \m{markdownOptionFrozenCache} plain \TeX{} option is +% disabled and the code block has not been previously typeset: +% +% \end{markdown} +% \begin{macrocode} +\RequirePackage{ifthen} +\renewcommand\markdownRendererInputFencedCode[2]{% + \def\next##1 ##2\relax{% + \ifthenelse{\equal{##1}{dot}}{% + \markdownIfOption{FrozenCache}{}{% + \immediate\write18{% + if ! test -e #1.pdf.source || ! diff #1 #1.pdf.source; + then + dot -Tpdf -o #1.pdf #1; + cp #1 #1.pdf.source; + fi}}% +% \end{macrocode} +% \begin{markdown} +% +% We include the typeset image using the image token renderer: +% +% \end{markdown} +% \begin{macrocode} + \markdownRendererImage{Graphviz image}{#1.pdf}{#1.pdf}{##2}% +% \end{macrocode} +% \begin{markdown} +% +% If the infostring does not start with `dot …`, we use the previous definition +% of the fenced code token renderer prototype: +% +% \end{markdown} +% \begin{macrocode} + }{% + \markdown@witiko@dot@oldRendererInputFencedCodePrototype{#1}{#2}% + }% + }% + \next#2 \relax}% +% \end{macrocode} +% \iffalse +% +%<*latex-themes-witiko-graphicx-http> +% \fi +% \par +% \begin{markdown} +% +% The `witiko/graphicx/http` theme stores the previous definition of the image +% token renderer prototype: +% +% \end{markdown} +% \begin{macrocode} +\let\markdown@witiko@graphicx@http@oldRendererImagePrototype + \markdownRendererImagePrototype +% \end{macrocode} +% \begin{markdown} +% +% We define the \m{markdown@witiko@graphicx@http@counter} counter to enumerate +% the images for caching and the \m{markdown@witiko@graphicx@http@filename} +% command, which will store the pathname of the file containing the pathname +% of the downloaded image file. +% +% \end{markdown} +% \begin{macrocode} +\newcount\markdown@witiko@graphicx@http@counter +\markdown@witiko@graphicx@http@counter=0 +\newcommand\markdown@witiko@graphicx@http@filename{% + \markdownOptionCacheDir/witiko_graphicx_http% + .\the\markdown@witiko@graphicx@http@counter}% +% \end{macrocode} +% \begin{markdown} +% +% We define the \m{markdown@witiko@graphicx@http@download} command, which will +% receive two arguments that correspond to the URL of the online image and to +% the pathname, where the online image should be downloaded. The command will +% produce a shell command that tries to downloads the online image to the +% pathname. +% +% \end{markdown} +% \begin{macrocode} +\newcommand\markdown@witiko@graphicx@http@download[2]{% + wget -O #2 #1 || curl --location -o #2 #1 || rm -f #2} +% \end{macrocode} +% \begin{markdown} +% +% We locally swap the category code of the percentage sign with the line feed +% control character, so that we can use percentage signs in the shell code: +% +% \end{markdown} +% \begin{macrocode} +\begingroup +\catcode`\%=12 +\catcode`\^^A=14 +% \end{macrocode} +% \begin{markdown} +% +% We redefine the image token renderer prototype, so that it tries to download +% an online image. +% +% \end{markdown} +% \begin{macrocode} +\global\def\markdownRendererImagePrototype#1#2#3#4{^^A + \begingroup + \edef\filename{\markdown@witiko@graphicx@http@filename}^^A +% \end{macrocode} +% \begin{markdown} +% +% The image will be downloaded only if the image URL has the http or https +% protocols and the \m{markdownOptionFrozenCache} plain \TeX{} option is disabled: +% +% \end{markdown} +% \begin{macrocode} + \markdownIfOption{FrozenCache}{}{^^A + \immediate\write18{^^A + if printf '%s' "#3" | grep -q -E '^https?:'; + then +% \end{macrocode} +% \begin{markdown} +% +% The image will be downloaded to the pathname \m{markdownOptionCacheDir}`/`\meta{the MD5 digest of the image URL}`.`\meta{the suffix of the +% image URL}: +% +% \end{markdown} +% \begin{macrocode} + OUTPUT_PREFIX="\markdownOptionCacheDir"; + OUTPUT_BODY="$(printf '%s' '#3' | md5sum | cut -d' ' -f1)"; + OUTPUT_SUFFIX="$(printf '%s' '#3' | sed 's/.*[.]//')"; + OUTPUT="$OUTPUT_PREFIX/$OUTPUT_BODY.$OUTPUT_SUFFIX"; +% \end{macrocode} +% \begin{markdown} +% +% The image will be downloaded only if it has not already been downloaded: +% +% \end{markdown} +% \begin{macrocode} + if ! [ -e "$OUTPUT" ]; + then + \markdown@witiko@graphicx@http@download{'#3'}{"$OUTPUT"}; + printf '%s' "$OUTPUT" > "\filename"; + fi; +% \end{macrocode} +% \begin{markdown} +% +% If the image does not have the http or https protocols or the image has +% already been downloaded, the URL will be stored as-is: +% +% \end{markdown} +% \begin{macrocode} + else + printf '%s' '#3' > "\filename"; + fi}}^^A +% \end{macrocode} +% \begin{markdown} +% +% We load the pathname of the downloaded image and we typeset the image using +% the previous definition of the image renderer prototype: +% +% \end{markdown} +% \begin{macrocode} + \CatchFileDef{\filename}{\filename}{}^^A + \markdown@witiko@graphicx@http@oldRendererImagePrototype^^A + {#1}{#2}{\filename}{#4}^^A + \endgroup + \global\advance\markdown@witiko@graphicx@http@counter by 1\relax}^^A +\endgroup +% \end{macrocode} +% \iffalse +% +%<*latex-themes-witiko-tilde> +% \fi +% \par +% \begin{markdown} +% +% The `witiko/tilde` theme redefines the tilde token renderer prototype, +% so that it expands to a non-breaking space: +% +% \end{markdown} +% \begin{macrocode} +\renewcommand\markdownRendererTildePrototype{~}% +% \end{macrocode} +% \iffalse +% +%<*latex> +% \fi +% \par +% \begin{markdown} +% %### Token Renderer Prototypes -% The following configuration should be considered placeholder. +% The following configuration should be considered placeholder. If the `plain` +% package option has been enabled (see Section \ref{sec:latexplain}), none of +% it will take effect. +% \end{markdown} +% \begin{macrocode} +\ifmarkdownLaTeXPlain\else +% \end{macrocode} +% \par +% \begin{markdown} % % If the \m{markdownOptionTightLists} macro expands to `false`, do not load % the \pkg{paralist} package. This is necessary for \Hologo{LaTeX2e} document @@ -17070,13 +18343,14 @@ end % % \end{markdown} % \begin{macrocode} -\ifx\markdownOptionTightLists\undefined - \@ifclassloaded{beamer}{}{ - \RequirePackage{paralist}} -\else - \ifthenelse{\equal{\markdownOptionTightLists}{false}}{}{ - \RequirePackage{paralist}} -\fi +\RequirePackage{ifthen} +\@ifundefined{markdownOptionTightLists}{% + \@ifclassloaded{beamer}{}{% + \RequirePackage{paralist}}% +}{% + \ifthenelse{\equal{\markdownOptionTightLists}{false}}{}{% + \RequirePackage{paralist}}% +}% % \end{macrocode} % \par % \begin{markdown} @@ -17104,6 +18378,9 @@ end olEndTight = {\markdownRendererOlEnd}, dlBeginTight = {\markdownRendererDlBegin}, dlEndTight = {\markdownRendererDlEnd}}}} +\RequirePackage{csvsimple} +\RequirePackage{fancyvrb} +\RequirePackage{graphicx} \markdownSetup{rendererPrototypes={ lineBreak = {\\}, leftBrace = {\textbraceleft}, @@ -17137,10 +18414,10 @@ end \label{fig:#1}% \end{figure}}, ulBegin = {\begin{itemize}}, - ulItem = {\item}, + ulItem = {\item{}}, ulEnd = {\end{itemize}}, olBegin = {\begin{enumerate}}, - olItem = {\item}, + olItem = {\item{}}, olItemWithNumber = {\item[#1.]}, olEnd = {\end{enumerate}}, dlBegin = {\begin{description}}, @@ -17154,8 +18431,8 @@ end \ifx\relax#2\relax \VerbatimInput{#1}% \else - \ifx\minted@code\undefined - \ifx\lst@version\undefined + \@ifundefined{minted@code}{% + \@ifundefined{lst@version}{% \markdownRendererInputFencedCode{#1}{}% % \end{macrocode} % \par @@ -17165,9 +18442,9 @@ end % % \end{markdown} % \begin{macrocode} - \else + }{% \lstinputlisting[language=#2]{#1}% - \fi + }% % \end{macrocode} % \par % \begin{markdown} @@ -17177,9 +18454,9 @@ end % % \end{markdown} % \begin{macrocode} - \else + }{% \inputminted{#2}{#1}% - \fi + }% \fi}, horizontalRule = {\noindent\rule[0.5ex]{\linewidth}{1pt}}, footnote = {\footnote{#1}}}} @@ -17191,19 +18468,10 @@ end % % \end{markdown} % \begin{macrocode} -\newif\ifmarkdownLATEXStrongEmphasisNested -\markdownLATEXStrongEmphasisNestedfalse -\markdownSetup{rendererPrototypes={ - strongEmphasis = {% - \ifmarkdownLATEXStrongEmphasisNested - \markdownLATEXStrongEmphasisNestedfalse - \textmd{#1}% - \markdownLATEXStrongEmphasisNestedtrue - \else - \markdownLATEXStrongEmphasisNestedtrue - \textbf{#1}% - \markdownLATEXStrongEmphasisNestedfalse - \fi}}} +\def\markdownLATEXStrongEmphasis#1{% + \IfSubStr\f@series{b}{\textnormal{#1}}{\textbf{#1}}} +\markdownSetup{rendererPrototypes={strongEmphasis={% + \protect\markdownLATEXStrongEmphasis{#1}}}} % \end{macrocode} % \par % \begin{markdown} @@ -17212,14 +18480,14 @@ end % % \end{markdown} % \begin{macrocode} -\ifx\chapter\undefined +\@ifundefined{chapter}{% \markdownSetup{rendererPrototypes = { headingOne = {\section{#1}}, headingTwo = {\subsection{#1}}, headingThree = {\subsubsection{#1}}, headingFour = {\paragraph{#1}\leavevmode}, headingFive = {\subparagraph{#1}\leavevmode}}} -\else +}{% \markdownSetup{rendererPrototypes = { headingOne = {\chapter{#1}}, headingTwo = {\section{#1}}, @@ -17227,7 +18495,7 @@ end headingFour = {\subsubsection{#1}}, headingFive = {\paragraph{#1}\leavevmode}, headingSix = {\subparagraph{#1}\leavevmode}}} -\fi +}% % \end{macrocode} % \par % \begin{markdown} @@ -17243,6 +18511,7 @@ end \newcount\markdownLaTeXCitationsCounter % Basic implementation +\RequirePackage{gobble} \def\markdownLaTeXBasicCitations#1#2#3#4#5#6{% \advance\markdownLaTeXCitationsCounter by 1\relax \ifx\relax#4\relax @@ -17417,47 +18686,47 @@ end cite = {% \markdownLaTeXCitationsCounter=1% \def\markdownLaTeXCitationsTotal{#1}% - \ifx\autocites\undefined - \ifx\citep\undefined + \@ifundefined{autocites}{% + \@ifundefined{citep}{% \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 \expandafter{\expandafter}% - \fi}, + }}, textCite = {% \markdownLaTeXCitationsCounter=1% \def\markdownLaTeXCitationsTotal{#1}% - \ifx\autocites\undefined - \ifx\citep\undefined + \@ifundefined{autocites}{% + \@ifundefined{citep}{% \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 \expandafter{\expandafter}% - \fi}}} + }}}} % \end{macrocode} % \par % \begin{markdown} @@ -17469,6 +18738,7 @@ end % % \end{markdown} % \begin{macrocode} +\RequirePackage{url} \def\markdownRendererLinkPrototype{% \begingroup \catcode`\#=12 @@ -17540,8 +18810,6 @@ end \fi \advance\markdownLaTeXRowCounter by 1\relax \ifnum\markdownLaTeXRowCounter>\markdownLaTeXRowTotal\relax - \markdownInfo{\the\markdownLaTeXTable} - \markdownInfo{\the\markdownLaTeXTableEnd} \the\markdownLaTeXTable \the\markdownLaTeXTableEnd \expandafter\@gobble @@ -17564,6 +18832,7 @@ end \addto@hook\markdownLaTeXTable{#1\\}% \expandafter\@gobble \fi\markdownLaTeXRenderTableCell} +\fi % \end{macrocode} % \par % \begin{markdown} @@ -17600,11 +18869,17 @@ end % consequence, we can directly reuse the existing plain \TeX{} implementation % after supplying the missing plain \TeX{} macros. % +% The \Hologo{ConTeXt} implementation redefines the plain \TeX{} logging macros +% (see Section \ref{sec:texinterfacelogging}) to use the \Hologo{ConTeXt} +% \m{writestatus} macro. +% % \end{markdown} % \begin{macrocode} +\def\markdownInfo#1{\writestatus{markdown}{#1.}}% +\def\markdownWarning#1{\writestatus{markdown\space warn}{#1.}}% \def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\_\do\%\do\~}% -\input markdown +\input markdown/markdown % \end{macrocode} % \par % \begin{markdown} @@ -17637,19 +18912,6 @@ end % \par % \begin{markdown} % -%### Logging Facilities -% The \Hologo{ConTeXt} implementation redefines the plain \TeX{} logging macros (see -% Section \ref{sec:texinterfacelogging}) to use the \Hologo{ConTeXt} -% \m{writestatus} macro. -% -% \end{markdown} -% \begin{macrocode} -\def\markdownInfo#1{\writestatus{markdown}{#1.}}% -\def\markdownWarning#1{\writestatus{markdown\space warn}{#1.}}% -% \end{macrocode} -% \par -% \begin{markdown} -% %### Typesetting Markdown % The \m{startmarkdown} and \m{stopmarkdown} macros are implemented using the % \m{markdownReadAndConvert} macro. @@ -17704,12 +18966,12 @@ end \def\markdownConTeXtCSV{csv} \def\markdownRendererContentBlockPrototype#1#2#3#4{% \def\markdownConTeXtCSV@arg{#1}% - \ifx\markdownConTeXtCSV@arg\markdownConTeXtCSV + \ifx\markdownConTeXtCSV@arg\markdownConTeXtCSV \placetable[][tab:#1]{#4}{% \processseparatedfile[MarkdownConTeXtCSV][#3]}% - \else - \markdownInput{#3}% - \fi}% + \else + \markdownInput{#3}% + \fi}% \def\markdownRendererImagePrototype#1#2#3#4{% \placefigure[][fig:#1]{#4}{\externalfigure[#3]}}% \def\markdownRendererUlBeginPrototype{\startitemize}% diff --git a/Master/texmf-dist/source/generic/markdown/markdown.ins b/Master/texmf-dist/source/generic/markdown/markdown.ins index b7436c37fcf..0e71d55d554 100644 --- a/Master/texmf-dist/source/generic/markdown/markdown.ins +++ b/Master/texmf-dist/source/generic/markdown/markdown.ins @@ -6,6 +6,9 @@ \file{markdown.tex}{\from{markdown.dtx}{tex}} \file{markdown.sty}{\from{markdown.dtx}{latex}} \file{t-markdown.tex}{\from{markdown.dtx}{context}} + \file{markdownthemewitiko_dot.sty}{\from{markdown.dtx}{latex-themes-witiko-dot}} + \file{markdownthemewitiko_graphicx_http.sty}{\from{markdown.dtx}{latex-themes-witiko-graphicx-http}} + \file{markdownthemewitiko_tilde.sty}{\from{markdown.dtx}{latex-themes-witiko-tilde}} \usepreamble\empty\usepostamble\empty \file{markdown.md}{\from{markdown.dtx}{manual}} \file{markdown-interfaces.md}{\from{markdown.dtx}{manual-interfaces}} -- cgit v1.2.3