summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2016-08-29 21:19:56 +0000
committerKarl Berry <karl@freefriends.org>2016-08-29 21:19:56 +0000
commit835ae450df95b8a97500efebbe995d9950c4e2b2 (patch)
tree2f9de4b0d4669f42f478401ce48926bed745aca0
parent8d7f98b66885b8a8f5e0cccb43f7c97060affb01 (diff)
markdown (29aug16)
git-svn-id: svn://tug.org/texlive/trunk@41950 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/generic/markdown/markdown.pdfbin299789 -> 318364 bytes
-rw-r--r--Master/texmf-dist/source/generic/markdown/markdown.dtx995
-rw-r--r--Master/texmf-dist/tex/context/third/markdown/t-markdown.tex42
-rw-r--r--Master/texmf-dist/tex/generic/markdown/markdown.tex146
-rw-r--r--Master/texmf-dist/tex/latex/markdown/markdown.sty150
-rw-r--r--Master/texmf-dist/tex/luatex/markdown/markdown.lua344
6 files changed, 1292 insertions, 385 deletions
diff --git a/Master/texmf-dist/doc/generic/markdown/markdown.pdf b/Master/texmf-dist/doc/generic/markdown/markdown.pdf
index 36777fbd15b..8ef9dee5525 100644
--- a/Master/texmf-dist/doc/generic/markdown/markdown.pdf
+++ b/Master/texmf-dist/doc/generic/markdown/markdown.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/generic/markdown/markdown.dtx b/Master/texmf-dist/source/generic/markdown/markdown.dtx
index d657c7eeb20..e400439b93d 100644
--- a/Master/texmf-dist/source/generic/markdown/markdown.dtx
+++ b/Master/texmf-dist/source/generic/markdown/markdown.dtx
@@ -145,13 +145,15 @@
%<*lua>
% \fi
% \begin{macrocode}
-if not modules then modules = { } end modules ['markdown'] = {
- version = "1.0.2",
+local metadata = {
+ version = "2.1.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 Vít Novotný",
license = "LPPL 1.3"
}
+if not modules then modules = { } end
+modules['markdown'] = metadata
% \end{macrocode}
%
% \subsection{Feedback}
@@ -293,10 +295,10 @@ local md5 = require("md5")
%<*lua>
% \fi
% \subsection{Lua Interface}\label{sec:luainterface}
-% The Lua interface provides the conversion from markdown to plain \TeX{}.
-% This interface is used by the plain \TeX{} implementation (see Section
-% \ref{sec:teximplementation}) and will be of interest to the developers of
-% other packages and Lua modules.
+% The Lua interface provides the conversion from \acro{utf}-\oldstylenums8
+% encoded markdown to plain \TeX{}. This interface is used by the plain \TeX{}
+% implementation (see Section \ref{sec:teximplementation}) and will be of
+% interest to the developers of other packages and Lua modules.
%
% The Lua interface is implemented by the \t`markdown` Lua module.
%
@@ -340,6 +342,17 @@ local defaultOptions = {}
defaultOptions.blankBeforeBlockquote = false
% \end{macrocode}
%
+% \Optitem[false]{blankBeforeCodeFence}{\opt{true}, \opt{false}}
+% \begin{valuelist}
+% \item[true] Require a blank line between a paragraph and the following
+% fenced code block.
+% \item[false] Do not require a blank line between a paragraph and the
+% following fenced code block.
+% \end{valuelist}
+% \begin{macrocode}
+defaultOptions.blankBeforeCodeFence = false
+% \end{macrocode}
+%
% \Optitem[false]{blankBeforeHeading}{\opt{true}, \opt{false}}
% \begin{valuelist}
% \item[true] Require a blank line between a paragraph and the following
@@ -363,6 +376,43 @@ defaultOptions.blankBeforeHeading = false
defaultOptions.cacheDir = "."
% \end{macrocode}
%
+% \Optitem[false]{citationNbsps}{\opt{true}, \opt{false}}
+% \begin{valuelist}
+% \item[true] Replace regular spaces with non-breakable spaces inside the
+% prenotes and postnotes of citations produced via the pandoc citation
+% syntax extension.
+% \item[false] Do not replace regular spaces with non-breakable spaces
+% inside the prenotes and postnotes of citations produced via the pandoc
+% citation syntax extension.
+% \end{valuelist}
+% \begin{macrocode}
+defaultOptions.citationNbsps = true
+% \end{macrocode}
+%
+% \Optitem[false]{citations}{\opt{true}, \opt{false}}
+% \begin{valuelist}
+% \item[true] Enable the pandoc citation syntax extension:
+% \begin{Verbatim}
+% Here is a simple parenthetical citation [@doe99] and here
+% is a string of several [see @doe99, pp. 33-35; also
+% @smith04, chap. 1].
+%
+% A parenthetical citation can have a [prenote @doe99] and
+% a [@smith04 postnote]. The name of the author can be
+% suppressed by inserting a dash before the name of an
+% author as follows [-@smith04].
+%
+% Here is a simple text citation @doe99 and here is
+% a string of several @doe99 [pp. 33-35; also @smith04,
+% chap. 1]. Here is one with the name of the author
+% suppressed -@doe99.
+% \end{Verbatim}
+% \item[false] Disable the pandoc citation syntax extension.
+% \end{valuelist}
+% \begin{macrocode}
+defaultOptions.citations = false
+% \end{macrocode}
+%
% \Optitem[false]{definitionLists}{\opt{true}, \opt{false}}
% \begin{valuelist}
% \item[true] Enable the pandoc definition list syntax extension:
@@ -414,6 +464,33 @@ defaultOptions.hashEnumerators = false
defaultOptions.hybrid = false
% \end{macrocode}
%
+% \Optitem[false]{fencedCode}{\opt{true}, \opt{false}}
+% \begin{valuelist}
+% \item[true] Enable the commonmark fenced code block extension:
+% \begin{Verbatim}
+% ~~~ js
+% if (a > 3) {
+% moveShip(5 * gravity, DOWN);
+% }
+% ~~~~~~
+%
+% ``` html
+% <pre>
+% <code>
+% // Some comments
+% line 1 of code
+% line 2 of code
+% line 3 of code
+% </code>
+% </pre>
+% ```
+% \end{Verbatim}
+% \item[true] Disable the commonmark fenced code block extension.
+% \end{valuelist}
+% \begin{macrocode}
+defaultOptions.fencedCode = false
+% \end{macrocode}
+%
% \Optitem[false]{footnotes}{\opt{true}, \opt{false}}
% \begin{valuelist}
% \item[true] Enable the pandoc footnote syntax extension:
@@ -498,8 +575,8 @@ defaultOptions.tightLists = true
% \ref{sec:luaoptions}) used during the conversion from markdown to plain
% \TeX{}, and for changing the way markdown the tokens are rendered.
% \begin{macrocode}
-\def\markdownLastModified{2016/08/14}%
-\def\markdownVersion{1.0.2}%
+\def\markdownLastModified{2016/08/20}%
+\def\markdownVersion{2.1.0}%
% \end{macrocode}
%
% The plain \TeX{} interface is implemented by the \t`markdown.tex` file that
@@ -620,12 +697,12 @@ defaultOptions.tightLists = true
%
% The \mdef{markdownOptionCacheDir} macro corresponds to the Lua interface
% \Opt{cacheDir} option that sets the name of the directory that will contain
-% the produced cache files. The option defaults to \t`_markdown-`\m{jobname},
+% the produced cache files. The option defaults to \t`_markdown_`\m{jobname},
% which is a similar naming scheme to the one used by the \pkg{minted} \LaTeX{}
% package. The same limitations apply here as in the case of the
% \m{markdownOptionHelperScriptFileName} macro.
% \begin{macrocode}
-\def\markdownOptionCacheDir{_markdown-\jobname}%
+\def\markdownOptionCacheDir{_markdown_\jobname}%
% \end{macrocode}
%
% \paragraph{Lua Interface Options}
@@ -635,11 +712,15 @@ defaultOptions.tightLists = true
% makes them fall back to the default values provided by the Lua interface.
% \begin{macrocode}
\let\markdownOptionBlankBeforeBlockquote\undefined
+\let\markdownOptionBlankBeforeCodeFence\undefined
\let\markdownOptionBlankBeforeHeading\undefined
+\let\markdownOptionCitations\undefined
+\let\markdownOptionCitationNbsps\undefined
\let\markdownOptionDefinitionLists\undefined
+\let\markdownOptionFootnotes\undefined
+\let\markdownOptionFencedCode\undefined
\let\markdownOptionHashEnumerators\undefined
\let\markdownOptionHybrid\undefined
-\let\markdownOptionFootnotes\undefined
\let\markdownOptionPreserveTabs\undefined
\let\markdownOptionSmartEllipses\undefined
\let\markdownOptionStartNumber\undefined
@@ -654,6 +735,14 @@ defaultOptions.tightLists = true
% document. By default, they point to the corresponding prototypes (see Section
% \ref{sec:texrendererprototypes}).
%
+% \paragraph{Interblock Separator Renderer}
+% The \mdef{markdownRendererInterblockSeparator} macro represents a separator
+% between two markdown block elements. The macro receives no arguments.
+% \begin{macrocode}
+\def\markdownRendererInterblockSeparator{%
+ \markdownRendererInterblockSeparatorPrototype}%
+% \end{macrocode}
+%
% \paragraph{Line Break Renderer}
% The \mdef{markdownRendererLineBreak} macro represents a forced line break.
% The macro receives no arguments.
@@ -671,6 +760,13 @@ defaultOptions.tightLists = true
\markdownRendererEllipsisPrototype}%
% \end{macrocode}
%
+% \paragraph{Non-breaking Space Renderer}
+% The \mdef{markdownRendererNbsp} macro represents a non-breaking space.
+% \begin{macrocode}
+\def\markdownRendererNbsp{%
+ \markdownRendererNbspPrototype}%
+% \end{macrocode}
+%
% \paragraph{Special Character Renderers}
% The following macros replace any special plain \TeX{} characters (including
% the active pipe character (\t`|`) of \Hologo{ConTeXt}) in the input text.
@@ -749,13 +845,19 @@ defaultOptions.tightLists = true
% \end{macrocode}
%
% The \mdef{markdownRendererUlItem} macro represents an item in a bulleted
-% list.
-% The macro receives no arguments.
+% list. The macro receives no arguments.
% \begin{macrocode}
\def\markdownRendererUlItem{%
\markdownRendererUlItemPrototype}%
% \end{macrocode}
%
+% The \mdef{markdownRendererUlItemEnd} macro represents the end of an item in a
+% bulleted list. The macro receives no arguments.
+% \begin{macrocode}
+\def\markdownRendererUlItemEnd{%
+ \markdownRendererUlItemEndPrototype}%
+% \end{macrocode}
+%
% The \mdef{markdownRendererUlEnd} macro represents the end of a bulleted list
% that contains an item with several paragraphs of text (the list is not
% tight). The macro receives no arguments.
@@ -799,6 +901,13 @@ defaultOptions.tightLists = true
\markdownRendererOlItemPrototype}%
% \end{macrocode}
%
+% The \mdef{markdownRendererOlItemEnd} macro represents the end of an item in
+% an ordered list. The macro receives no arguments.
+% \begin{macrocode}
+\def\markdownRendererOlItemEnd{%
+ \markdownRendererOlItemEndPrototype}%
+% \end{macrocode}
+%
% The \mdef{markdownRendererOlItemWithNumber} macro represents an item in an
% ordered list. This macro will only be produced, when the \Opt{startNumber}
% option is \t`true`. The macro receives no arguments.
@@ -853,6 +962,13 @@ defaultOptions.tightLists = true
\markdownRendererDlItemPrototype}%
% \end{macrocode}
%
+% The \mdef{markdownRendererDlItemEnd} macro represents the end of a list of
+% definitions for a single term.
+% \begin{macrocode}
+\def\markdownRendererDlItemEnd{%
+ \markdownRendererDlItemEndPrototype}%
+% \end{macrocode}
+%
% The \mdef{markdownRendererDlDefinitionBegin} macro represents the beginning
% of a definition in a definition list. There can be several definitions for
% a single term.
@@ -918,15 +1034,24 @@ defaultOptions.tightLists = true
\markdownRendererBlockQuoteEndPrototype}%
% \end{macrocode}
%
-% \paragraph{Code Block Renderer}
+% \paragraph{Code Block Renderers}
% The \mdef{markdownRendererInputVerbatim} macro represents a code
% block. The macro receives a single argument that corresponds to the
-% filename of a file contaning the code block to input.
+% filename of a file contaning the code block contents.
% \begin{macrocode}
\def\markdownRendererInputVerbatim{%
\markdownRendererInputVerbatimPrototype}%
% \end{macrocode}
%
+% The \mdef{markdownRendererInputFencedCode} macro represents a fenced code
+% block. This macro will only be produced, when the \Opt{fencedCode} option is
+% \t`true`. The macro receives two arguments that correspond to the filename of
+% a file contaning the code block contents and to the code fence infostring.
+% \begin{macrocode}
+\def\markdownRendererInputFencedCode{%
+ \markdownRendererInputFencedCodePrototype}%
+% \end{macrocode}
+%
% \paragraph{Heading Renderers}
% The \mdef{markdownRendererHeadingOne} macro represents a first level heading.
% The macro receives a single argument that corresponds to the heading text.
@@ -992,6 +1117,31 @@ defaultOptions.tightLists = true
\markdownRendererFootnotePrototype}%
% \end{macrocode}
%
+% \paragraph{Parenthesized Citations Renderer}
+% The \mdef{markdownRendererCite} macro represents a string of one or more
+% parenthetical citations. This macro will only be produced, when the
+% \Opt{citations} option is \t`true`. The macro receives the parameter
+% \t`\textbraceleft`\meta{number of citations}\t`\textbraceright` followed by
+% \meta{suppress author}\t`\textbraceleft`\meta{prenote}\t`\textbraceright^^A
+% \textbraceleft`\meta{postnote}\t`\textbraceright\textbraceleft`\meta{name}^^A
+% \t`\textbraceright` repeated \meta{number of citations} times. The
+% \meta{suppress author} parameter is either the token \t`-`, when the author's
+% name is to be suppressed, or \t`+` otherwise.
+% \begin{macrocode}
+\def\markdownRendererCite{%
+ \markdownRendererCitePrototype}%
+% \end{macrocode}
+%
+% \paragraph{Text Citations Renderer}
+% The \mdef{markdownRendererTextCite} macro represents a string of one or more
+% text citations. This macro will only be produced, when the
+% \Opt{citations} option is \t`true`. The macro receives parameters in the same
+% format as the \m{markdownRendererCite} macro.
+% \begin{macrocode}
+\def\markdownRendererTextCite{%
+ \markdownRendererTextCitePrototype}%
+% \end{macrocode}
+%
% \subsubsection{Token Renderer Prototypes}\label{sec:texrendererprototypes}
% The following \TeX{} macros provide definitions for the token renderers (see
% Section \ref{sec:texrenderersuser}) that have not been redefined by the
@@ -1000,8 +1150,10 @@ defaultOptions.tightLists = true
% by the \LaTeX{} and \Hologo{ConTeXt} implementations (see sections
% \ref{sec:lateximplementation} and \ref{sec:contextimplementation}).
% \begin{macrocode}
+\def\markdownRendererInterblockSeparatorPrototype{}%
\def\markdownRendererLineBreakPrototype{}%
\def\markdownRendererEllipsisPrototype{}%
+\def\markdownRendererNbspPrototype{}%
\def\markdownRendererLeftBracePrototype{}%
\def\markdownRendererRightBracePrototype{}%
\def\markdownRendererDollarSignPrototype{}%
@@ -1013,40 +1165,46 @@ defaultOptions.tightLists = true
\def\markdownRendererBackslashPrototype{}%
\def\markdownRendererTildePrototype{}%
\def\markdownRendererPipePrototype{}%
-\long\def\markdownRendererCodeSpanPrototype#1{}%
-\long\def\markdownRendererLinkPrototype#1#2#3#4{}%
-\long\def\markdownRendererImagePrototype#1#2#3#4{}%
+\def\markdownRendererCodeSpanPrototype#1{}%
+\def\markdownRendererLinkPrototype#1#2#3#4{}%
+\def\markdownRendererImagePrototype#1#2#3#4{}%
\def\markdownRendererUlBeginPrototype{}%
\def\markdownRendererUlBeginTightPrototype{}%
\def\markdownRendererUlItemPrototype{}%
+\def\markdownRendererUlItemEndPrototype{}%
\def\markdownRendererUlEndPrototype{}%
\def\markdownRendererUlEndTightPrototype{}%
\def\markdownRendererOlBeginPrototype{}%
\def\markdownRendererOlBeginTightPrototype{}%
\def\markdownRendererOlItemPrototype{}%
-\long\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemEndPrototype{}%
\def\markdownRendererOlEndPrototype{}%
\def\markdownRendererOlEndTightPrototype{}%
\def\markdownRendererDlBeginPrototype{}%
\def\markdownRendererDlBeginTightPrototype{}%
-\long\def\markdownRendererDlItemPrototype#1{}%
+\def\markdownRendererDlItemPrototype#1{}%
+\def\markdownRendererDlItemEndPrototype{}%
\def\markdownRendererDlDefinitionBeginPrototype{}%
\def\markdownRendererDlDefinitionEndPrototype{}%
\def\markdownRendererDlEndPrototype{}%
\def\markdownRendererDlEndTightPrototype{}%
-\long\def\markdownRendererEmphasisPrototype#1{}%
-\long\def\markdownRendererStrongEmphasisPrototype#1{}%
+\def\markdownRendererEmphasisPrototype#1{}%
+\def\markdownRendererStrongEmphasisPrototype#1{}%
\def\markdownRendererBlockQuoteBeginPrototype{}%
\def\markdownRendererBlockQuoteEndPrototype{}%
-\long\def\markdownRendererInputVerbatimPrototype#1{}%
-\long\def\markdownRendererHeadingOnePrototype#1{}%
-\long\def\markdownRendererHeadingTwoPrototype#1{}%
-\long\def\markdownRendererHeadingThreePrototype#1{}%
-\long\def\markdownRendererHeadingFourPrototype#1{}%
-\long\def\markdownRendererHeadingFivePrototype#1{}%
-\long\def\markdownRendererHeadingSixPrototype#1{}%
+\def\markdownRendererInputVerbatimPrototype#1{}%
+\def\markdownRendererInputFencedCodePrototype#1#2{}%
+\def\markdownRendererHeadingOnePrototype#1{}%
+\def\markdownRendererHeadingTwoPrototype#1{}%
+\def\markdownRendererHeadingThreePrototype#1{}%
+\def\markdownRendererHeadingFourPrototype#1{}%
+\def\markdownRendererHeadingFivePrototype#1{}%
+\def\markdownRendererHeadingSixPrototype#1{}%
\def\markdownRendererHorizontalRulePrototype{}%
-\long\def\markdownRendererFootnotePrototype#1{}%
+\def\markdownRendererFootnotePrototype#1{}%
+\def\markdownRendererCitePrototype#1{}%
+\def\markdownRendererTextCitePrototype#1{}%
% \end{macrocode}
%
% \subsubsection{Logging Facilities}
@@ -1165,7 +1323,11 @@ defaultOptions.tightLists = true
% \textbackslash{}usepackage[\textrm{\meta{options}}]\{markdown\}
% \end{Verbatim}
% where \meta{options} are the \LaTeX{} interface options (see Section
-% \ref{sec:latexoptions}).
+% \ref{sec:latexoptions}). Note that \meta{options} inside the \m{usepackage}
+% macro may not set the \t`markdownRenderers` (see Section
+% \ref{sec:latexrenderers}) and \t`markdownRendererPrototypes` (see Section
+% \ref{sec:latexrendererprototypes}) keys. This limitation is due to the way
+% \Hologo{LaTeX2e} parses package options.
%
% \subsubsection{Typesetting Markdown}
% The interface exposes the \envmdef{markdown} and \envmdef{markdown*}
@@ -1256,18 +1418,26 @@ defaultOptions.tightLists = true
\def\markdownOptionOutputTempFileName{#1}}%
\define@key{markdownOptions}{blankBeforeBlockquote}[true]{%
\def\markdownOptionBlankBeforeBlockquote{#1}}%
+\define@key{markdownOptions}{blankBeforeCodeFence}[true]{%
+ \def\markdownOptionBlankBeforeCodeFence{#1}}%
\define@key{markdownOptions}{blankBeforeHeading}[true]{%
\def\markdownOptionBlankBeforeHeading{#1}}%
+\define@key{markdownOptions}{citations}[true]{%
+ \def\markdownOptionCitations{#1}}%
+\define@key{markdownOptions}{citationNbsps}[true]{%
+ \def\markdownOptionCitationNbsps{#1}}%
\define@key{markdownOptions}{cacheDir}{%
\def\markdownOptionCacheDir{#1}}%
\define@key{markdownOptions}{definitionLists}[true]{%
\def\markdownOptionDefinitionLists{#1}}%
+\define@key{markdownOptions}{footnotes}[true]{%
+ \def\markdownOptionFootnotes{#1}}%
+\define@key{markdownOptions}{fencedCode}[true]{%
+ \def\markdownOptionFencedCode{#1}}%
\define@key{markdownOptions}{hashEnumerators}[true]{%
\def\markdownOptionHashEnumerators{#1}}%
\define@key{markdownOptions}{hybrid}[true]{%
\def\markdownOptionHybrid{#1}}%
-\define@key{markdownOptions}{footnotes}[true]{%
- \def\markdownOptionFootnotes{#1}}%
\define@key{markdownOptions}{preserveTabs}[true]{%
\def\markdownOptionPreserveTabs{#1}}%
\define@key{markdownOptions}{smartEllipses}[true]{%
@@ -1278,7 +1448,7 @@ defaultOptions.tightLists = true
% If the \t`tightLists=false` option is specified, when loading the package,
% then the \pkg{paralist} package for typesetting tight lists will not be
% automatically loaded. This precaution is meant to minimize the footprint of
-% this package, since some documentclasses (\pkg{beamer}) do not play nice
+% this package, since some documentclasses (\pkg{beamer}) experience clashes
% with the \pkg{paralist} package.
% \begin{macrocode}
\define@key{markdownOptions}{tightLists}[true]{%
@@ -1296,18 +1466,20 @@ defaultOptions.tightLists = true
% }
% \end{Verbatim}
%
-% \paragraph{Plain \TeX{} Markdown Token Renderers}
+% \paragraph{Plain \TeX{} Markdown Token Renderers}\label{sec:latexrenderers}
% The \LaTeX{} interface recognizes an option with the \t`renderers` key,
% whose value must be a list of options that map directly to the markdown token
% renderer macros exposed by the plain \TeX{} interface (see Section
% \ref{sec:texrenderersuser}).
% \begin{macrocode}
-\define@key{markdownOptions}{renderers}{%
- \setkeys{markdownRenderers}{#1}}%
+\define@key{markdownRenderers}{interblockSeparator}{%
+ \renewcommand\markdownRendererInterblockSeparator{#1}}%
\define@key{markdownRenderers}{lineBreak}{%
\renewcommand\markdownRendererLineBreak{#1}}%
\define@key{markdownRenderers}{ellipsis}{%
\renewcommand\markdownRendererEllipsis{#1}}%
+\define@key{markdownRenderers}{nbsp}{%
+ \renewcommand\markdownRendererNbsp{#1}}%
\define@key{markdownRenderers}{leftBrace}{%
\renewcommand\markdownRendererLeftBrace{#1}}%
\define@key{markdownRenderers}{rightBrace}{%
@@ -1342,6 +1514,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererUlBeginTight{#1}}%
\define@key{markdownRenderers}{ulItem}{%
\renewcommand\markdownRendererUlItem{#1}}%
+\define@key{markdownRenderers}{ulItemEnd}{%
+ \renewcommand\markdownRendererUlItemEnd{#1}}%
\define@key{markdownRenderers}{ulEnd}{%
\renewcommand\markdownRendererUlEnd{#1}}%
\define@key{markdownRenderers}{ulEndTight}{%
@@ -1354,6 +1528,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererOlItem{#1}}%
\define@key{markdownRenderers}{olItemWithNumber}{%
\renewcommand\markdownRendererOlItemWithNumber[1]{#1}}%
+\define@key{markdownRenderers}{olItemEnd}{%
+ \renewcommand\markdownRendererOlItemEnd{#1}}%
\define@key{markdownRenderers}{olEnd}{%
\renewcommand\markdownRendererOlEnd{#1}}%
\define@key{markdownRenderers}{olEndTight}{%
@@ -1364,6 +1540,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererDlBeginTight{#1}}%
\define@key{markdownRenderers}{dlItem}{%
\renewcommand\markdownRendererDlItem[1]{#1}}%
+\define@key{markdownRenderers}{dlItemEnd}{%
+ \renewcommand\markdownRendererDlItemEnd{#1}}%
\define@key{markdownRenderers}{dlDefinitionBegin}{%
\renewcommand\markdownRendererDlDefinitionBegin{#1}}%
\define@key{markdownRenderers}{dlDefinitionEnd}{%
@@ -1382,6 +1560,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererBlockQuoteEnd{#1}}%
\define@key{markdownRenderers}{inputVerbatim}{%
\renewcommand\markdownRendererInputVerbatim[1]{#1}}%
+\define@key{markdownRenderers}{inputFencedCode}{%
+ \renewcommand\markdownRendererInputFencedCode[2]{#1}}%
\define@key{markdownRenderers}{headingOne}{%
\renewcommand\markdownRendererHeadingOne[1]{#1}}%
\define@key{markdownRenderers}{headingTwo}{%
@@ -1398,6 +1578,10 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererHorizontalRule{#1}}%
\define@key{markdownRenderers}{footnote}{%
\renewcommand\markdownRendererFootnote[1]{#1}}%
+\define@key{markdownRenderers}{cite}{%
+ \renewcommand\markdownRendererCite[1]{#1}}%
+\define@key{markdownRenderers}{textCite}{%
+ \renewcommand\markdownRendererTextCite[1]{#1}}%
% \end{macrocode}
%
% The following example \LaTeX{} code showcases a possible configuration of the
@@ -1413,17 +1597,20 @@ defaultOptions.tightLists = true
% \end{Verbatim}
%
% \paragraph{Plain \TeX{} Markdown Token Renderer Prototypes}
+% \label{sec:latexrendererprototypes}
% The \LaTeX{} interface recognizes an option with the \t`rendererPrototypes`
% key, whose value must be a list of options that map directly to the markdown
% token renderer prototype macros exposed by the plain \TeX{} interface (see
% Section \ref{sec:texrendererprototypes}).
% \begin{macrocode}
-\define@key{markdownOptions}{rendererPrototypes}{%
- \setkeys{markdownRendererPrototypes}{#1}}%
+\define@key{markdownRendererPrototypes}{interblockSeparator}{%
+ \renewcommand\markdownRendererInterblockSeparatorPrototype{#1}}%
\define@key{markdownRendererPrototypes}{lineBreak}{%
\renewcommand\markdownRendererLineBreakPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ellipsis}{%
\renewcommand\markdownRendererEllipsisPrototype{#1}}%
+\define@key{markdownRendererPrototypes}{nbsp}{%
+ \renewcommand\markdownRendererNbspPrototype{#1}}%
\define@key{markdownRendererPrototypes}{leftBrace}{%
\renewcommand\markdownRendererLeftBracePrototype{#1}}%
\define@key{markdownRendererPrototypes}{rightBrace}{%
@@ -1445,19 +1632,21 @@ defaultOptions.tightLists = true
\define@key{markdownRendererPrototypes}{tilde}{%
\renewcommand\markdownRendererTildePrototype{#1}}%
\define@key{markdownRendererPrototypes}{pipe}{%
- \renewcommand\markdownRendererPipe{#1}}%
+ \renewcommand\markdownRendererPipePrototype{#1}}%
\define@key{markdownRendererPrototypes}{codeSpan}{%
\renewcommand\markdownRendererCodeSpanPrototype[1]{#1}}%
\define@key{markdownRendererPrototypes}{link}{%
- \renewcommand\markdownRendererLink[4]{#1}}%
+ \renewcommand\markdownRendererLinkPrototype[4]{#1}}%
\define@key{markdownRendererPrototypes}{image}{%
- \renewcommand\markdownRendererImage[4]{#1}}%
+ \renewcommand\markdownRendererImagePrototype[4]{#1}}%
\define@key{markdownRendererPrototypes}{ulBegin}{%
\renewcommand\markdownRendererUlBeginPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulBeginTight}{%
\renewcommand\markdownRendererUlBeginTightPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulItem}{%
\renewcommand\markdownRendererUlItemPrototype{#1}}%
+\define@key{markdownRendererPrototypes}{ulItemEnd}{%
+ \renewcommand\markdownRendererUlItemEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulEnd}{%
\renewcommand\markdownRendererUlEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulEndTight}{%
@@ -1470,6 +1659,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererOlItemPrototype{#1}}%
\define@key{markdownRendererPrototypes}{olItemWithNumber}{%
\renewcommand\markdownRendererOlItemWithNumberPrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{olItemEnd}{%
+ \renewcommand\markdownRendererOlItemEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{olEnd}{%
\renewcommand\markdownRendererOlEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{olEndTight}{%
@@ -1480,6 +1671,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererDlBeginTightPrototype{#1}}%
\define@key{markdownRendererPrototypes}{dlItem}{%
\renewcommand\markdownRendererDlItemPrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{dlItemEnd}{%
+ \renewcommand\markdownRendererDlItemEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{dlDefinitionBegin}{%
\renewcommand\markdownRendererDlDefinitionBeginPrototype{#1}}%
\define@key{markdownRendererPrototypes}{dlDefinitionEnd}{%
@@ -1498,6 +1691,8 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererBlockQuoteEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{inputVerbatim}{%
\renewcommand\markdownRendererInputVerbatimPrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{inputFencedCode}{%
+ \renewcommand\markdownRendererInputFencedCodePrototype[2]{#1}}%
\define@key{markdownRendererPrototypes}{headingOne}{%
\renewcommand\markdownRendererHeadingOnePrototype[1]{#1}}%
\define@key{markdownRendererPrototypes}{headingTwo}{%
@@ -1514,6 +1709,10 @@ defaultOptions.tightLists = true
\renewcommand\markdownRendererHorizontalRulePrototype{#1}}%
\define@key{markdownRendererPrototypes}{footnote}{%
\renewcommand\markdownRendererFootnotePrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{cite}{%
+ \renewcommand\markdownRendererCitePrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{textCite}{%
+ \renewcommand\markdownRendererTextCitePrototype[1]{#1}}%
% \end{macrocode}
%
% The following example \LaTeX{} code showcases a possible configuration of the
@@ -1521,7 +1720,7 @@ defaultOptions.tightLists = true
% markdown token renderer prototypes.
% \begin{Verbatim}
% \markdownSetup{
-% renderers = {
+% rendererPrototypes = {
% image = {\includegraphics{#2}},
% codeSpan = {\texttt{#1}}, % Render inline code via `\texttt`.
% }
@@ -1885,6 +2084,12 @@ function M.writer.new(options)
self.space = " "
% \end{macrocode}
%
+% Define \luamdef{writer->nbsp} as the output format of a non-breaking space
+% character.
+% \begin{macrocode}
+ self.nbsp = "\\markdownRendererNbsp{}"
+% \end{macrocode}
+%
% Define \luamdef{writer->plain} as a function that will transform an input
% plain text block \t`s` to the output format.
% \begin{macrocode}
@@ -1913,13 +2118,7 @@ function M.writer.new(options)
% Define \luamdef{writer->interblocksep} as the output format of a block
% element separator.
% \begin{macrocode}
- self.interblocksep = "\n\n"
-% \end{macrocode}
-%
-% Define \luamdef{writer->containersep} as the output format of a container
-% separator.
-% \begin{macrocode}
- self.containersep = "\n\n"
+ self.interblocksep = "\\markdownRendererInterblockSeparator\n{}"
% \end{macrocode}
%
% Define \luamdef{writer->eof} as the end of file marker in the output format.
@@ -1929,7 +2128,7 @@ function M.writer.new(options)
%
% Define \luamdef{writer->linebreak} as the output format of a forced line break.
% \begin{macrocode}
- self.linebreak = "\\markdownRendererLineBreak "
+ self.linebreak = "\\markdownRendererLineBreak\n{}"
% \end{macrocode}
%
% Define \luamdef{writer->ellipsis} as the output format of an ellipsis.
@@ -1939,7 +2138,7 @@ function M.writer.new(options)
%
% Define \luamdef{writer->hrule} as the output format of a horizontal rule.
% \begin{macrocode}
- self.hrule = "\\markdownRendererHorizontalRule "
+ self.hrule = "\\markdownRendererHorizontalRule{}"
% \end{macrocode}
%
% Define a table \luamdef{escaped_chars} containing the mapping from special
@@ -2031,7 +2230,8 @@ function M.writer.new(options)
% items and \t`tight` specifies, whether the list is tight or not.
% \begin{macrocode}
local function ulitem(s)
- return {"\\markdownRendererUlItem ",s}
+ return {"\\markdownRendererUlItem ",s,
+ "\\markdownRendererUlItemEnd "}
end
function self.bulletlist(items,tight)
@@ -2058,9 +2258,11 @@ function M.writer.new(options)
% \begin{macrocode}
local function olitem(s,num)
if num ~= nil then
- return {"\\markdownRendererOlItemWithNumber{",num,"}",s}
+ return {"\\markdownRendererOlItemWithNumber{",num,"}",s,
+ "\\markdownRendererOlItemEnd "}
else
- return {"\\markdownRendererOlItem ",s}
+ return {"\\markdownRendererOlItem ",s,
+ "\\markdownRendererOlItemEnd "}
end
end
@@ -2096,6 +2298,7 @@ function M.writer.new(options)
retVal[#retVal+1] = {"\\markdownRendererDlDefinitionBegin ",def,
"\\markdownRendererDlDefinitionEnd "}
end
+ retVal[#retVal+1] = "\\markdownRendererDlItemEnd "
return retVal
end
@@ -2104,13 +2307,12 @@ function M.writer.new(options)
for _,item in ipairs(items) do
buffer[#buffer + 1] = dlitem(item.term, item.definitions)
end
- local contents = util.intersperse(buffer, self.containersep)
if tight and options.tightLists then
- return {"\\markdownRendererDlBeginTight\n\n", contents,
- "\n\n\\markdownRendererDlEndTight\n"}
+ return {"\\markdownRendererDlBeginTight\n", buffer,
+ "\n\\markdownRendererDlEndTight"}
else
- return {"\\markdownRendererDlBegin\n\n", contents,
- "\n\n\\markdownRendererDlEnd\n"}
+ return {"\\markdownRendererDlBegin\n", buffer,
+ "\n\\markdownRendererDlEnd"}
end
end
% \end{macrocode}
@@ -2149,6 +2351,16 @@ function M.writer.new(options)
end
% \end{macrocode}
%
+% Define \luamdef{writer->codeFence} as a function that will transform an
+% input fenced code block \t`s` with the infostring \t`i` to the output
+% format.
+% \begin{macrocode}
+ function self.fencedCode(i, s)
+ local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
+ return {"\\markdownRendererInputFencedCode{",name,"}{",i,"}"}
+ end
+% \end{macrocode}
+%
% Define \luamdef{writer->heading} as a function that will transform an
% input heading \t`s` at level \t`level` to the output format.
% \begin{macrocode}
@@ -2173,12 +2385,37 @@ function M.writer.new(options)
end
% \end{macrocode}
%
-% Define \luamdef{writer->footnote} as a function that will transform an
+% Define \luamdef{writer->note} as a function that will transform an
% input footnote \t`s` to the output format.
% \begin{macrocode}
function self.note(s)
return {"\\markdownRendererFootnote{",s,"}"}
end
+% \end{macrocode}
+%
+% Define \luamdef{writer->citations} as a function that will transform an
+% input array of citations \t`cites` to the output format. If \t`text_cites`
+% is \t`true`, the citations should be rendered in-text, when applicable.
+% The \t`cites` array contains tables with the following keys and values:
+% \begin{itemize}
+% \item\t`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\t`prenote` -- The value of the key is either \t`nil` or a string
+% that should be inserted before the citation.
+% \item\t`postnote` -- The value of the key is either \t`nil` or a string
+% that should be inserted after the citation.
+% \item\t`name` -- The value of this key is the citation name.
+% \end{itemize}
+% \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
return self
end
@@ -2249,44 +2486,36 @@ function M.reader.new(writer, options)
% \paragraph{Top Level Parsing Functions}
% \begin{macrocode}
local syntax
+ local blocks_toplevel
local blocks
- local inlines
-
- local parse_blocks =
- function(str)
- local res = lpeg.match(blocks, str)
- if res == nil then
- error(format("parse_blocks failed on:\n%s", str:sub(1,20)))
- else
- return res
- end
- end
+ local inlines, inlines_no_link, inlines_nbsp
- local parse_inlines =
- function(str)
- local res = lpeg.match(inlines, str)
+ local function create_parser(name, grammar)
+ return function(str)
+ local res = lpeg.match(grammar(), str)
if res == nil then
- error(format("parse_inlines failed on:\n%s",
- str:sub(1,20)))
- else
- return res
- end
- end
-
- local parse_inlines_no_link =
- function(str)
- local res = lpeg.match(inlines_no_link, str)
- if res == nil then
- error(format("parse_inlines_no_link failed on:\n%s",
- str:sub(1,20)))
+ error(format("%s failed on:\n%s", name, str:sub(1,20)))
else
return res
end
end
+ end
+
+ local parse_blocks = create_parser("parse_blocks",
+ function() return blocks end)
+ local parse_blocks_toplevel = create_parser("parse_blocks_toplevel",
+ function() return blocks_toplevel end)
+ local parse_inlines = create_parser("parse_inlines",
+ function() return inlines end)
+ local parse_inlines_no_link = create_parser("parse_inlines_no_link",
+ function() return inlines_no_link end)
+ local parse_inlines_nbsp = create_parser("parse_inlines_nbsp",
+ function() return inlines_nbsp end)
% \end{macrocode}
% \paragraph{Generic \acro{peg} Patterns}
% \begin{macrocode}
local percent = P("%")
+ local at = P("@")
local asterisk = P("*")
local dash = P("-")
local plus = P("+")
@@ -2310,12 +2539,14 @@ function M.reader.new(writer, options)
local colon = P(":")
local semicolon = P(";")
local exclamation = P("!")
+ local tilde = P("~")
local digit = R("09")
local hexdigit = R("09","af","AF")
local letter = R("AZ","az")
local alphanumeric = R("AZ","az","09")
local keyword = letter * alphanumeric^0
+ local punctuation = S("!?,.:;")
local doubleasterisks = P("**")
local doubleunderscores = P("__")
@@ -2325,7 +2556,8 @@ function M.reader.new(writer, options)
local fail = any - 1
local always = P("")
- local escapable = S("\\`*_{}[]()+_.!<>#-~:^")
+ local escapable = S("\\`*_{}[]()+_.!<>#-~:^@;")
+
local anyescaped = P("\\") / "" * escapable
+ any
@@ -2336,17 +2568,14 @@ function M.reader.new(writer, options)
local nonspacechar = any - spacing
local tightblocksep = P("\001")
- local specialchar
- if options.smartEllipses then
- specialchar = S("*_`&[]<!\\.")
- else
- specialchar = S("*_`&[]<!\\")
- end
+ local specialchar = S("*_`&[]<!\\.@-")
local normalchar = any -
(specialchar + spacing + tightblocksep)
local optionalspace = spacechar^0
- local spaces = spacechar^1
+ local optionalspaceor = function(pattern)
+ return (spacechar + pattern)^0
+ end
local eof = - any
local nonindentspace = space^-3 * - spacechar
local indent = space^-3 * tab
@@ -2360,6 +2589,10 @@ function M.reader.new(writer, options)
local optionallyindentedline = indent^-1 /"" * C(linechar^1 * newline^-1)
local sp = spacing^0
local spnl = optionalspace * (newline * optionalspace)^-1
+ local spnlor = function(pattern)
+ local optional = optionalspaceor(pattern)
+ return optional * (newline * optional)^-1
+ end
local line = linechar^0 * newline
+ linechar^1 * eof
local nonemptyline = line - blankline
@@ -2371,7 +2604,7 @@ function M.reader.new(writer, options)
local function indented_blocks(bl)
return Cs( bl
* (blankline^1 * indent * -blankline * bl)^0
- * blankline^1 )
+ * (blankline^1 + eof) )
end
% \end{macrocode}
% \paragraph{List \acro{peg} Patterns}
@@ -2413,7 +2646,38 @@ function M.reader.new(writer, options)
+ (space - closeticks)
+ (backtick^1 - closeticks)
- local inticks = openticks * space^-1 * C(intickschar^1) * closeticks
+ local inticks = openticks * space^-1 * C(intickschar^0) * closeticks
+% \paragraph{Fenced Code \acro{peg} Patterns}
+% \begin{macrocode}
+ local function captures_geq_length(s,i,a,b)
+ return #a >= #b and i
+ end
+
+ local infostring = (linechar - (backtick + space^1 * (newline + eof)))^0
+
+ local fenceindent
+ local function fencehead(char)
+ return C(nonindentspace) / function(s) fenceindent = #s end
+ * Cg(char^3, "fencelength")
+ * optionalspace * C(infostring) * optionalspace
+ * (newline + eof)
+ end
+
+ local function fencetail(char)
+ return nonindentspace
+ * Cmt(C(char^3) * Cb("fencelength"),
+ captures_geq_length)
+ * optionalspace * (newline + eof)
+ + eof
+ end
+
+ local function fencedline(char)
+ return C(line - fencetail(char))
+ / function(s)
+ return s:gsub("^" .. string.rep(" ?",
+ fenceindent), "")
+ end
+ end
% \end{macrocode}
% \paragraph{Tag \acro{peg} Patterns}
% \begin{macrocode}
@@ -2468,6 +2732,41 @@ function M.reader.new(writer, options)
local optionaltitle = spnl * title * spacechar^0
+ Cc("")
% \end{macrocode}
+% \paragraph{Citation \acro{peg} Patterns}
+% \begin{macrocode}
+ local citation_name = (Cs(dash^-1)
+ * at * Cs((anyescaped
+ - (rbracket + spacing + punctuation + semicolon))^1))
+
+ local citation_body_prenote
+ = Cs((alphanumeric^1
+ + bracketed
+ + inticks
+ + (anyescaped
+ - (rbracket + semicolon + blankline^2))
+ - (spnl * dash^-1 * at))^0)
+
+ local citation_body_postnote
+ = Cs((alphanumeric^1
+ + bracketed
+ + inticks
+ + (anyescaped
+ - (rbracket + semicolon + blankline^2))
+ - (spnl * rbracket))^0)
+
+ local citation_body_chunk
+ = citation_body_prenote
+ * spnl * citation_name
+ * spnlor(punctuation - (semicolon + rbracket))
+ * citation_body_postnote
+
+ local citation_body = citation_body_chunk
+ * (semicolon * spnl * citation_body_chunk)^0
+
+ local citation_headless_body
+ = citation_body_postnote
+ * (sp * semicolon * spnl * citation_body_chunk)^0
+% \end{macrocode}
% \paragraph{Footnote \acro{peg} Patterns}
% \begin{macrocode}
local rawnotes = {}
@@ -2481,7 +2780,7 @@ function M.reader.new(writer, options)
return function()
local found = rawnotes[normalize_tag(ref)]
if found then
- return writer.note(parse_blocks(found))
+ return writer.note(parse_blocks_toplevel(found))
else
return {"[", parse_inlines("^" .. ref), "]"}
end
@@ -2571,23 +2870,12 @@ function M.reader.new(writer, options)
end
end
% \end{macrocode}
-% \paragraph{Inline Element \acro{peg} Patterns}
+% \paragraph{Spacing \acro{peg} Patterns}
% \begin{macrocode}
- local Inline = V("Inline")
-
- local Str = normalchar^1 / writer.string
-
- local Ellipsis = P("...") / writer.ellipsis
-
- local Smart = Ellipsis
-
- local Symbol = (specialchar - tightblocksep) / writer.string
-
- local Code = inticks / writer.code
-
local bqstart = more
local headerstart = hash
+ (line * (equal^1 + dash^1) * optionalspace * newline)
+ local fencestart = fencehead(backtick) + fencehead(tilde)
if options.blankBeforeBlockquote then
bqstart = fail
@@ -2597,30 +2885,56 @@ function M.reader.new(writer, options)
headerstart = fail
end
+ if not options.fencedCode or options.blankBeforeCodeFence then
+ fencestart = fail
+ end
+% \end{macrocode}
+% \paragraph{String \acro{peg} Rules}
+% \begin{macrocode}
+ local Inline = V("Inline")
+
+ local Str = normalchar^1 / writer.string
+
+ local Symbol = (specialchar - tightblocksep) / writer.string
+% \end{macrocode}
+% \paragraph{Ellipsis \acro{peg} Rules}
+% \begin{macrocode}
+ local Ellipsis = P("...") / writer.ellipsis
+
+ local Smart = Ellipsis
+% \end{macrocode}
+% \paragraph{Inline Code Block \acro{peg} Rules}
+% \begin{macrocode}
+ local Code = inticks / writer.code
+% \end{macrocode}
+% \paragraph{Spacing \acro{peg} Rules}
+% \begin{macrocode}
local Endline = newline * -( -- newline, but not before...
blankline -- paragraph break
+ tightblocksep -- nested list
+ eof -- end of document
+ bqstart
+ headerstart
+ + fencestart
) * spacechar^0 / writer.space
-% \end{macrocode}
-% Make two and more trailing spaces before a newline produce a forced line
-% break, throw away one or more trailing spaces and an optional newline at the
-% end of a file, and reduce one or more spaces and an optional newline into a
-% single space.
-% \begin{macrocode}
local Space = spacechar^2 * Endline / writer.linebreak
+ spacechar^1 * Endline^-1 * eof / ""
+ spacechar^1 * Endline^-1 * optionalspace / writer.space
+ local NonbreakingSpace
+ = spacechar^2 * Endline / writer.linebreak
+ + spacechar^1 * Endline^-1 * eof / ""
+ + spacechar^1 * Endline^-1 * optionalspace / writer.nbsp
+
-- parse many p between starter and ender
local function between(p, starter, ender)
local ender2 = B(nonspacechar) * ender
return (starter * #nonspacechar * Ct(p * (p - ender2)^0) * ender2)
end
-
+% \end{macrocode}
+% \paragraph{Emphasis \acro{peg} Rules}
+% \begin{macrocode}
local Strong = ( between(Inline, doubleasterisks, doubleasterisks)
+ between(Inline, doubleunderscores, doubleunderscores)
) / writer.strong
@@ -2628,7 +2942,9 @@ function M.reader.new(writer, options)
local Emph = ( between(Inline, asterisk, asterisk)
+ between(Inline, underscore, underscore)
) / writer.emphasis
-
+% \end{macrocode}
+% \paragraph{Link \acro{peg} Rules}
+% \begin{macrocode}
local urlchar = anyescaped - newline - more
local AutoLinkUrl = less
@@ -2658,7 +2974,9 @@ function M.reader.new(writer, options)
-- parse a link or image (direct or indirect)
local Link = DirectLink + IndirectLink
-
+% \end{macrocode}
+% \paragraph{Image \acro{peg} Rules}
+% \begin{macrocode}
local DirectImage = exclamation
* (tag / parse_inlines)
* spnl
@@ -2672,48 +2990,106 @@ function M.reader.new(writer, options)
indirect_image
local Image = DirectImage + IndirectImage
-
+% \end{macrocode}
+% \paragraph{Miscellaneous Inline \acro{peg} Rules}
+% \begin{macrocode}
-- avoid parsing long strings of * or _ as emph/strong
local UlOrStarLine = asterisk^4 + underscore^4 / writer.string
local EscapedChar = S("\\") * C(escapable) / writer.string
% \end{macrocode}
-% \paragraph{Block Element \acro{peg} Patterns}
+% \paragraph{Citations \acro{peg} Rules}
+% \begin{macrocode}
+ local function citations(text_cites, raw_cites)
+ local function normalize(str)
+ if str == "" then
+ str = nil
+ else
+ str = (options.citationNbsps and parse_inlines_nbsp or
+ parse_inlines)(str)
+ end
+ return str
+ end
+
+ local cites = {}
+ for i = 1,#raw_cites,4 do
+ cites[#cites+1] = {
+ prenote = normalize(raw_cites[i]),
+ suppress_author = raw_cites[i+1] == "-",
+ name = writer.string(raw_cites[i+2]),
+ postnote = normalize(raw_cites[i+3]),
+ }
+ end
+ return writer.citations(text_cites, cites)
+ end
+
+ local TextCitations = Ct(Cc("")
+ * citation_name
+ * ((spnl
+ * lbracket
+ * citation_headless_body
+ * rbracket) + Cc(""))) /
+ function(raw_cites)
+ return citations(true, raw_cites)
+ end
+
+ local ParenthesizedCitations
+ = Ct(lbracket
+ * citation_body
+ * rbracket) /
+ function(raw_cites)
+ return citations(false, raw_cites)
+ end
+
+ local Citations = TextCitations + ParenthesizedCitations
+% \end{macrocode}
+% \paragraph{Code Block \acro{peg} Rules}
% \begin{macrocode}
local Block = V("Block")
local Verbatim = Cs( (blanklines
* ((indentedline - blankline))^1)^1
) / expandtabs / writer.verbatim
+
+ local TildeFencedCode
+ = fencehead(tilde)
+ * Cs(fencedline(tilde)^0)
+ * fencetail(tilde)
+
+ local BacktickFencedCode
+ = fencehead(backtick)
+ * Cs(fencedline(backtick)^0)
+ * fencetail(backtick)
+ local FencedCode = (TildeFencedCode + BacktickFencedCode)
+ / function(infostring, code)
+ return writer.fencedCode(
+ writer.string(infostring),
+ expandtabs(code))
+ end
+% \end{macrocode}
+% \paragraph{Blockquote \acro{peg} Patterns}
+% \begin{macrocode}
-- strip off leading > and indents, and run through blocks
local Blockquote = Cs((
((leader * more * space^-1)/"" * linechar^0 * newline)^1
* (-blankline * linechar^1 * newline)^0
- * blankline^0
- )^1) / parse_blocks / writer.blockquote
+ * (blankline^0 / "")
+ )^1) / parse_blocks_toplevel / writer.blockquote
local function lineof(c)
- return (leader * (P(c) * optionalspace)^3 * newline * blankline^1)
+ return (leader * (P(c) * optionalspace)^3 * (newline * blankline^1
+ + newline^-1 * eof))
end
-
+% \end{macrocode}
+% \paragraph{Horizontal Rule \acro{peg} Rules}
+% \begin{macrocode}
local HorizontalRule = ( lineof(asterisk)
+ lineof(dash)
+ lineof(underscore)
) / writer.hrule
-
- local Reference = define_reference_parser / register_link
-
- local Paragraph = nonindentspace * Ct(Inline^1) * newline
- * ( blankline^1
- + #hash
- + #(leader * more * space^-1)
- )
- / writer.paragraph
-
- local Plain = nonindentspace * Ct(Inline^1) / writer.plain
% \end{macrocode}
-% \paragraph{List \acro{peg} Patterns}
+% \paragraph{List \acro{peg} Rules}
% \begin{macrocode}
local starter = bullet + enumerator
@@ -2785,7 +3161,7 @@ function M.reader.new(writer, options)
local DefinitionListItemLoose = C(line) * skipblanklines
* Ct((defstart *
indented_blocks(dlchunk) /
- parse_blocks)^1)
+ parse_blocks_toplevel)^1)
* Cc(false)
/ definition_list_item
@@ -2801,14 +3177,36 @@ function M.reader.new(writer, options)
-DefinitionListItemLoose * Cc(true))
) / writer.definitionlist
% \end{macrocode}
-% \paragraph{Blank \acro{peg} Patterns}
+% \paragraph{Blank Line \acro{peg} Rules}
% \begin{macrocode}
+ local Reference = define_reference_parser / register_link
local Blank = blankline / ""
+ NoteBlock
+ Reference
+ (tightblocksep / "\n")
% \end{macrocode}
-% \paragraph{Heading \acro{peg} Patterns}
+% \paragraph{Paragraph \acro{peg} Rules}
+% \begin{macrocode}
+ local Paragraph = nonindentspace * Ct(Inline^1) * newline
+ * ( blankline^1
+ + #hash
+ + #(leader * more * space^-1)
+ )
+ / writer.paragraph
+
+ local ToplevelParagraph
+ = nonindentspace * Ct(Inline^1) * (newline
+ * ( blankline^1
+ + #hash
+ + #(leader * more * space^-1)
+ + eof
+ )
+ + eof )
+ / writer.paragraph
+
+ local Plain = nonindentspace * Ct(Inline^1) / writer.plain
+% \end{macrocode}
+% \paragraph{Heading \acro{peg} Rules}
% \begin{macrocode}
-- parse Atx heading start and return level
local HeadingStart = #hash * C(hash^-6) * -hash / length
@@ -2833,6 +3231,8 @@ function M.reader.new(writer, options)
* HeadingLevel
* optionalspace * newline
/ writer.heading
+
+ local Heading = AtxHeading + SetextHeading
% \end{macrocode}
% \paragraph{Top Level \acro{peg} Specification}
% \begin{macrocode}
@@ -2851,6 +3251,7 @@ function M.reader.new(writer, options)
Block = V("Blockquote")
+ V("Verbatim")
+ + V("FencedCode")
+ V("HorizontalRule")
+ V("BulletList")
+ V("OrderedList")
@@ -2861,10 +3262,11 @@ function M.reader.new(writer, options)
Blockquote = Blockquote,
Verbatim = Verbatim,
+ FencedCode = FencedCode,
HorizontalRule = HorizontalRule,
BulletList = BulletList,
OrderedList = OrderedList,
- Heading = AtxHeading + SetextHeading,
+ Heading = Heading,
DefinitionList = DefinitionList,
DisplayHtml = DisplayHtml,
Paragraph = Paragraph,
@@ -2877,6 +3279,7 @@ function M.reader.new(writer, options)
+ V("Strong")
+ V("Emph")
+ V("NoteRef")
+ + V("Citations")
+ V("Link")
+ V("Image")
+ V("Code")
@@ -2893,6 +3296,7 @@ function M.reader.new(writer, options)
Strong = Strong,
Emph = Emph,
NoteRef = NoteRef,
+ Citations = Citations,
Link = Link,
Image = Image,
Code = Code,
@@ -2909,6 +3313,14 @@ function M.reader.new(writer, options)
syntax.DefinitionList = fail
end
+ if not options.fencedCode then
+ syntax.FencedCode = fail
+ end
+
+ if not options.citations then
+ syntax.Citations = fail
+ end
+
if not options.footnotes then
syntax.NoteRef = fail
end
@@ -2917,6 +3329,10 @@ function M.reader.new(writer, options)
syntax.Smart = fail
end
+ local blocks_toplevel_t = util.table_copy(syntax)
+ blocks_toplevel_t.Paragraph = ToplevelParagraph
+ blocks_toplevel = Ct(blocks_toplevel_t)
+
blocks = Ct(syntax)
local inlines_t = util.table_copy(syntax)
@@ -2924,9 +3340,13 @@ function M.reader.new(writer, options)
inlines_t.Inlines = Inline^0 * (spacing^0 * eof / "")
inlines = Ct(inlines_t)
- inlines_no_link_t = util.table_copy(inlines_t)
+ local inlines_no_link_t = util.table_copy(inlines_t)
inlines_no_link_t.Link = fail
inlines_no_link = Ct(inlines_no_link_t)
+
+ local inlines_nbsp_t = util.table_copy(inlines_t)
+ inlines_nbsp_t.Space = NonbreakingSpace
+ inlines_nbsp = Ct(inlines_nbsp_t)
% \end{macrocode}
%
% \paragraph{Exported Conversion Function}
@@ -2938,8 +3358,9 @@ function M.reader.new(writer, options)
references = {}
% \end{macrocode}
% When determining the name of the cache file, create salt for the hashing
-% function out of the passed options recognized by the Lua interface (see
-% Section \ref{sec:luaoptions}). The \Opt{cacheDir} option is disregarded.
+% function out of the package version and the passed options recognized by the
+% Lua interface (see Section \ref{sec:luaoptions}). The \Opt{cacheDir} option
+% is disregarded.
% \begin{macrocode}
local opt_string = {}
for k,_ in pairs(defaultOptions) do
@@ -2949,13 +3370,13 @@ function M.reader.new(writer, options)
end
end
table.sort(opt_string)
- local salt = table.concat(opt_string, ",")
+ local salt = table.concat(opt_string, ",") .. "," .. metadata.version
% \end{macrocode}
% Produce the cache file, transform its filename via the \luam{writer->pack}
% method, and return the result.
% \begin{macrocode}
local name = util.cache(options.cacheDir, input, salt, function(input)
- return util.rope_to_string(parse_blocks(input)) .. writer.eof
+ return util.rope_to_string(parse_blocks_toplevel(input)) .. writer.eof
end, ".md" .. writer.suffix)
return writer.pack(name)
end
@@ -2997,11 +3418,13 @@ return M
\errmessage{(l.\the\inputlineno) markdown.tex error: #1}}%
% \end{macrocode}
%
-% \subsubsection{Token Renderers}
+% \subsubsection{Token Renderer Prototypes}
% The following definitions should be considered placeholder.
% \begin{macrocode}
+\def\markdownRendererInterblockSeparatorPrototype{\par}%
\def\markdownRendererLineBreakPrototype{\hfil\break}%
\let\markdownRendererEllipsisPrototype\dots
+\def\markdownRendererNbspPrototype{~}%
\def\markdownRendererLeftBracePrototype{\char`{}%
\def\markdownRendererRightBracePrototype{\char`}}%
\def\markdownRendererDollarSignPrototype{\char`$}%
@@ -3013,41 +3436,48 @@ return M
\def\markdownRendererBackslashPrototype{\char`\\}%
\def\markdownRendererTildePrototype{\char`~}%
\def\markdownRendererPipePrototype{|}%
-\long\def\markdownRendererCodeSpanPrototype#1{{\tt#1}}%
-\long\def\markdownRendererLinkPrototype#1#2#3#4{#2}%
-\long\def\markdownRendererImagePrototype#1#2#3#4{#2}%
+\def\markdownRendererCodeSpanPrototype#1{{\tt#1}}%
+\def\markdownRendererLinkPrototype#1#2#3#4{#2}%
+\def\markdownRendererImagePrototype#1#2#3#4{#2}%
\def\markdownRendererUlBeginPrototype{}%
\def\markdownRendererUlBeginTightPrototype{}%
\def\markdownRendererUlItemPrototype{}%
+\def\markdownRendererUlItemEndPrototype{}%
\def\markdownRendererUlEndPrototype{}%
\def\markdownRendererUlEndTightPrototype{}%
\def\markdownRendererOlBeginPrototype{}%
\def\markdownRendererOlBeginTightPrototype{}%
\def\markdownRendererOlItemPrototype{}%
-\long\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemEndPrototype{}%
\def\markdownRendererOlEndPrototype{}%
\def\markdownRendererOlEndTightPrototype{}%
\def\markdownRendererDlBeginPrototype{}%
\def\markdownRendererDlBeginTightPrototype{}%
-\long\def\markdownRendererDlItemPrototype#1{#1}%
+\def\markdownRendererDlItemPrototype#1{#1}%
+\def\markdownRendererDlItemEndPrototype{}%
\def\markdownRendererDlDefinitionBeginPrototype{}%
\def\markdownRendererDlDefinitionEndPrototype{\par}%
\def\markdownRendererDlEndPrototype{}%
\def\markdownRendererDlEndTightPrototype{}%
-\long\def\markdownRendererEmphasisPrototype#1{{\it#1}}%
-\long\def\markdownRendererStrongEmphasisPrototype#1{{\it#1}}%
+\def\markdownRendererEmphasisPrototype#1{{\it#1}}%
+\def\markdownRendererStrongEmphasisPrototype#1{{\it#1}}%
\def\markdownRendererBlockQuoteBeginPrototype{\par\begingroup\it}%
\def\markdownRendererBlockQuoteEndPrototype{\endgroup\par}%
-\long\def\markdownRendererInputVerbatimPrototype#1{%
-\par{\tt\input"#1"\relax}\par}%
-\long\def\markdownRendererHeadingOnePrototype#1{#1}%
-\long\def\markdownRendererHeadingTwoPrototype#1{#1}%
-\long\def\markdownRendererHeadingThreePrototype#1{#1}%
-\long\def\markdownRendererHeadingFourPrototype#1{#1}%
-\long\def\markdownRendererHeadingFivePrototype#1{#1}%
-\long\def\markdownRendererHeadingSixPrototype#1{#1}%
+\def\markdownRendererInputVerbatimPrototype#1{%
+ \par{\tt\input"#1"\relax}\par}%
+\def\markdownRendererInputFencedCodePrototype#1#2{%
+ \markdownRendererInputVerbatimPrototype{#1}}%
+\def\markdownRendererHeadingOnePrototype#1{#1}%
+\def\markdownRendererHeadingTwoPrototype#1{#1}%
+\def\markdownRendererHeadingThreePrototype#1{#1}%
+\def\markdownRendererHeadingFourPrototype#1{#1}%
+\def\markdownRendererHeadingFivePrototype#1{#1}%
+\def\markdownRendererHeadingSixPrototype#1{#1}%
\def\markdownRendererHorizontalRulePrototype{}%
-\long\def\markdownRendererFootnotePrototype#1{#1}%
+\def\markdownRendererFootnotePrototype#1{#1}%
+\def\markdownRendererCitePrototype#1{}%
+\def\markdownRendererTextCitePrototype#1{}%
% \end{macrocode}
%
% \subsubsection{Lua Snippets}
@@ -3061,24 +3491,36 @@ return M
\ifx\markdownOptionBlankBeforeBlockquote\undefined\else
blankBeforeBlockquote = \markdownOptionBlankBeforeBlockquote,
\fi
+\ifx\markdownOptionBlankBeforeCodeFence\undefined\else
+ blankBeforeCodeFence = \markdownOptionBlankBeforeCodeFence,
+\fi
\ifx\markdownOptionBlankBeforeHeading\undefined\else
blankBeforeHeading = \markdownOptionBlankBeforeHeading,
\fi
\ifx\markdownOptionCacheDir\undefined\else
cacheDir = "\markdownOptionCacheDir",
\fi
+\ifx\markdownOptionCitations\undefined\else
+ citations = \markdownOptionCitations,
+\fi
+\ifx\markdownOptionCitationNbsps\undefined\else
+ citationNbsps = \markdownOptionCitationNbsps,
+\fi
\ifx\markdownOptionDefinitionLists\undefined\else
definitionLists = \markdownOptionDefinitionLists,
\fi
+\ifx\markdownOptionFootnotes\undefined\else
+ footnotes = \markdownOptionFootnotes,
+\fi
+\ifx\markdownOptionFencedCode\undefined\else
+ fencedCode = \markdownOptionFencedCode,
+\fi
\ifx\markdownOptionHashEnumerators\undefined\else
hashEnumerators = \markdownOptionHashEnumerators,
\fi
\ifx\markdownOptionHybrid\undefined\else
hybrid = \markdownOptionHybrid,
\fi
-\ifx\markdownOptionFootnotes\undefined\else
- footnotes = \markdownOptionFootnotes,
-\fi
\ifx\markdownOptionPreserveTabs\undefined\else
preserveTabs = \markdownOptionPreserveTabs,
\fi
@@ -3154,28 +3596,26 @@ local convert = md.new(\markdownLuaOptions)
% whether the shell access is enabled (\t`1`), disabled (\t`0`), or restricted
% (\t`2`).
%
-% If Lua is unavailable, inherit the value of the the \m{pdfshellescape}
-% (Lua\TeX{}, \Hologo{pdfTeX}) or the \m{shellescape} (\Hologo{XeTeX})
-% commands. If neither of these commands is defined, act as if the shell access
-% were enabled.
+% Inherit the value of the the \m{pdfshellescape} (Lua\TeX{}, \Hologo{pdfTeX})
+% or the \m{shellescape} (\Hologo{XeTeX}) commands. If neither of these
+% commands is defined and Lua is available, attempt to access the
+% \luam{status.shell_escape} configuration item.
+%
+% If you cannot detect, whether the shell access is enabled, act as if it were.
% \begin{macrocode}
-\ifnum\markdownMode=0\relax
- \ifx\pdfshellescape\undefined
- \ifx\shellescape\undefined
+\ifx\pdfshellescape\undefined
+ \ifx\shellescape\undefined
+ \ifnum\markdownMode=0\relax
\def\markdownExecuteShellEscape{1}%
\else
- \let\markdownExecuteShellEscape\shellescape
+ \def\markdownExecuteShellEscape{%
+ \directlua{tex.sprint(status.shell_escape or "1")}}%
\fi
\else
- \let\markdownExecuteShellEscape\pdfshellescape
+ \let\markdownExecuteShellEscape\shellescape
\fi
-% \end{macrocode}
-% If Lua is available, inherit the value of the \t`status.shell_escape`
-% configuration item.
-% \begin{macrocode}
\else
- \def\markdownExecuteShellEscape{%
- \directlua{tex.sprint(status.shell_escape)}}%
+ \let\markdownExecuteShellEscape\pdfshellescape
\fi
% \end{macrocode}
%
@@ -3304,7 +3744,6 @@ local convert = md.new(\markdownLuaOptions)
% \begin{macrocode}
|def^^M{%
|markdownInfo{The ending token sequence was found}%
- |immediate|write|markdownLuaExecuteFileStream{}%
|immediate|closeout|markdownLuaExecuteFileStream%
|endgroup%
|markdownInput|markdownOptionInputTempFileName%
@@ -3421,8 +3860,8 @@ local convert = md.new(\markdownLuaOptions)
% the result into the input line buffer of \TeX{}.
% \begin{macrocode}
if line:match(ending_sequence) then
- |markdownLuaUnregisterIBCallback
- local input = table.concat(buffer, "\n") .. "\n\n"
+ |markdownLuaUnregisterIBCallback;
+ local input = table.concat(buffer, "\n") .. "\n"
local output = convert(input)
return [[\markdownInfo{The ending token sequence was found}]] ..
output .. [[\markdownReadAndConvertAfter]]
@@ -3465,7 +3904,7 @@ local convert = md.new(\markdownLuaOptions)
|markdownInfo{Including markdown document "#1"}%
|markdownLuaExecute{%
|markdownPrepare
- local input = assert(io.open("#1","r")):read("*a") .. "\n\n"
+ local input = assert(io.open("#1","r")):read("*a")
% \end{macrocode}
% Since the Lua converter expects \acro{unix} line endings, normalize the
% input.
@@ -3544,7 +3983,18 @@ local convert = md.new(\markdownLuaOptions)
\expandafter\markdownSetup\expandafter{\CurrentOption}}%
\ProcessOptions\relax
% \end{macrocode}
+% After processing the options, activate the \t`renderers` and
+% \t`rendererPrototypes` keys.
+% \begin{macrocode}
+\define@key{markdownOptions}{renderers}{%
+ \setkeys{markdownRenderers}{#1}%
+ \def\KV@prefix{KV@markdownOptions@}}%
+\define@key{markdownOptions}{rendererPrototypes}{%
+ \setkeys{markdownRendererPrototypes}{#1}%
+ \def\KV@prefix{KV@markdownOptions@}}%
+% \end{macrocode}
%
+% \subsubsection{Token Renderer Prototypes}
% The following configuration should be considered placeholder.
% \begin{macrocode}
\RequirePackage{url}
@@ -3610,27 +4060,103 @@ local convert = md.new(\markdownLuaOptions)
blockQuoteBegin = {\begin{quotation}},
blockQuoteEnd = {\end{quotation}},
inputVerbatim = {\VerbatimInput{#1}},
+ inputFencedCode = {%
+ \ifx\relax#2\relax
+ \VerbatimInput{#1}%
+ \else
+ \ifx\minted@jobname\undefined
+ \ifx\lst@version\undefined
+ \markdownRendererInputFencedCode{#1}{}%
+% \end{macrocode}
+% When the \pkg{listings} package is loaded, use it for syntax highlighting.
+% \begin{macrocode}
+ \else
+ \lstinputlisting[language=#2]{#1}%
+ \fi
+% \end{macrocode}
+% When the \pkg{minted} package is loaded, use it for syntax highlighting.
+% The \pkg{minted} package is preferred over \pkg{listings}.
+% \begin{macrocode}
+ \else
+ \inputminted{#2}{#1}%
+ \fi
+ \fi},
horizontalRule = {\noindent\rule[0.5ex]{\linewidth}{1pt}},
- footnote = {\footnote{#1}}}}%
+ footnote = {\footnote{#1}}}}
\ifx\chapter\undefined
- \markdownSetup{rendererPrototypes={
+ \markdownSetup{rendererPrototypes = {
headingOne = {\section{#1}},
headingTwo = {\subsection{#1}},
headingThree = {\subsubsection{#1}},
headingFour = {\paragraph{#1}},
- headingFive = {\subparagraph{#1}}}}%
+ headingFive = {\subparagraph{#1}}}}
\else
- \markdownSetup{rendererPrototypes={
+ \markdownSetup{rendererPrototypes = {
headingOne = {\chapter{#1}},
headingTwo = {\section{#1}},
headingThree = {\subsection{#1}},
headingFour = {\subsubsection{#1}},
headingFive = {\paragraph{#1}},
- headingSix = {\subparagraph{#1}}}}%
+ headingSix = {\subparagraph{#1}}}}
\fi
% \end{macrocode}
%
+% There is a basic implementation for citations that uses the \LaTeX{} \m{cite}
+% macro. There is also a more advanced implementation that uses the Bib\LaTeX{}
+% \m{autocites} and \m{textcites} macros. This implementation will be used, when
+% Bib\LaTeX{} is loaded.
+% \begin{macrocode}
+\newcount\markdownLaTeXCitationsCounter
+
+% Basic implementation
+\def\markdownLaTeXBasicCitations#1#2#3#4{%
+ \advance\markdownLaTeXCitationsCounter by 1\relax
+ \ifx\relax#2\relax\else#2~\fi\cite[#3]{#4}%
+ \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax
+ \expandafter\@gobble
+ \fi\markdownLaTeXBasicCitations}
+\let\markdownLaTeXBasicTextCitations\markdownLaTeXBasicCitations
+
+% BibLaTeX implementation
+\def\markdownLaTeXBibLaTeXCitations#1#2#3#4#5{%
+ \advance\markdownLaTeXCitationsCounter by 1\relax
+ \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax
+ \autocites#1[#3][#4]{#5}%
+ \expandafter\@gobbletwo
+ \fi\markdownLaTeXBibLaTeXCitations{#1[#3][#4]{#5}}}
+\def\markdownLaTeXBibLaTeXTextCitations#1#2#3#4#5{%
+ \advance\markdownLaTeXCitationsCounter by 1\relax
+ \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax
+ \textcites#1[#3][#4]{#5}%
+ \expandafter\@gobbletwo
+ \fi\markdownLaTeXBibLaTeXTextCitations{#1[#3][#4]{#5}}}
+
+\markdownSetup{rendererPrototypes = {
+ cite = {%
+ \markdownLaTeXCitationsCounter=1%
+ \def\markdownLaTeXCitationsTotal{#1}%
+ \ifx\autocites\undefined
+ \expandafter
+ \markdownLaTeXBasicCitations
+ \else
+ \expandafter\expandafter\expandafter
+ \markdownLaTeXBibLaTeXCitations
+ \expandafter{\expandafter}%
+ \fi},
+ textCite = {%
+ \markdownLaTeXCitationsCounter=1%
+ \def\markdownLaTeXCitationsTotal{#1}%
+ \ifx\textcites\undefined
+ \expandafter
+ \markdownLaTeXBasicTextCitations
+ \else
+ \expandafter\expandafter\expandafter
+ \markdownLaTeXBibLaTeXTextCitations
+ \expandafter{\expandafter}%
+ \fi}}}
+% \end{macrocode}
+%
% \subsubsection{Miscellanea}
% Unlike base Lua\TeX{}, which only allows for a single registered function per
% a callback (see \cite[Section~8.1]{luatex16}), the \Hologo{LaTeX2e} format
@@ -3643,12 +4169,24 @@ local convert = md.new(\markdownLuaOptions)
% redefine the \m{markdownLuaRegisterIBCallback} and
% \m{markdownLuaUnregisterIBCallback} macros accordingly.
% \begin{macrocode}
+\let\markdownLuaRegisterIBCallbackPrevious
+ \markdownLuaRegisterIBCallback
+\let\markdownLuaUnregisterIBCallbackPrevious
+ \markdownLuaUnregisterIBCallback
\renewcommand\markdownLuaRegisterIBCallback[1]{%
- luatexbase.add_to_callback("process_input_buffer", #1, %
- "The markdown input processor")}
+ if luatexbase and luatexbase.add_to_callback then
+ luatexbase.add_to_callback("process_input_buffer", #1, %
+ "The markdown input processor")
+ else
+ \markdownLuaRegisterIBCallbackPrevious{#1}
+ end}
\renewcommand\markdownLuaUnregisterIBCallback{%
- luatexbase.remove_from_callback("process_input_buffer",%
- "The markdown input processor")}
+ if luatexbase and luatexbase.add_to_callback then
+ luatexbase.remove_from_callback("process_input_buffer",%
+ "The markdown input processor")
+ else
+ \markdownLuaUnregisterIBCallbackPrevious;
+ end}
% \end{macrocode}
%
% When buffering user input, we should disable the bytes with the high bit set,
@@ -3722,7 +4260,7 @@ local convert = md.new(\markdownLuaOptions)
% macro, so that the pipe character (\t`|`) is inactive during the scanning.
% This is necessary, since the character is active in \Hologo{ConTeXt}.
% \begin{macrocode}
-\ifnum\markdownMode<2
+\ifnum\markdownMode<2\relax
\def\markdownMakeOther{%
\catcode`|=12}%
\fi
@@ -3756,7 +4294,7 @@ local convert = md.new(\markdownLuaOptions)
|endgroup
% \end{macrocode}
%
-% \subsubsection{Options}
+% \subsubsection{Token Renderer Prototypes}
% The following configuration should be considered placeholder.
% \begin{macrocode}
\def\markdownRendererLineBreakPrototype{\blank}%
@@ -3769,10 +4307,10 @@ local convert = md.new(\markdownLuaOptions)
\def\markdownRendererBackslashPrototype{\textbackslash}%
\def\markdownRendererTildePrototype{\textasciitilde}%
\def\markdownRendererPipePrototype{\char`|}%
-\long\def\markdownRendererLinkPrototype#1#2#3#4{%
+\def\markdownRendererLinkPrototype#1#2#3#4{%
\useURL[#1][#3][][#4]#1\footnote[#1]{\ifx\empty#4\empty\else#4:
\fi\tt<\hyphenatedurl{#3}>}}%
-\long\def\markdownRendererImagePrototype#1#2#3#4{%
+\def\markdownRendererImagePrototype#1#2#3#4{%
\placefigure[][fig:#1]{#4}{\externalfigure[#3]}}%
\def\markdownRendererUlBeginPrototype{\startitemize}%
\def\markdownRendererUlBeginTightPrototype{\startitemize[packed]}%
@@ -3782,11 +4320,11 @@ local convert = md.new(\markdownLuaOptions)
\def\markdownRendererOlBeginPrototype{\startitemize[n]}%
\def\markdownRendererOlBeginTightPrototype{\startitemize[packed,n]}%
\def\markdownRendererOlItemPrototype{\item}%
-\long\def\markdownRendererOlItemWithNumberPrototype#1{\sym{#1.}}%
+\def\markdownRendererOlItemWithNumberPrototype#1{\sym{#1.}}%
\def\markdownRendererOlEndPrototype{\stopitemize}%
\def\markdownRendererOlEndTightPrototype{\stopitemize}%
\definedescription
- [markdownConTeXtDlItemPrototype]
+ [MarkdownConTeXtDlItemPrototype]
[location=hanging,
margin=standard,
headstyle=bold]%
@@ -3802,26 +4340,55 @@ local convert = md.new(\markdownLuaOptions)
\startMarkdownConTeXtDlPrototype}%
\def\markdownRendererDlBeginTightPrototype{%
\startMarkdownConTeXtDlTightPrototype}%
-\long\def\markdownRendererDlItemPrototype#1{%
- \markdownConTeXtDlItemPrototype{#1}}%
+\def\markdownRendererDlItemPrototype#1{%
+ \startMarkdownConTeXtDlItemPrototype{#1}}%
+\def\markdownRendererDlItemEndPrototype{%
+ \stopMarkdownConTeXtDlItemPrototype}%
\def\markdownRendererDlEndPrototype{%
\stopMarkdownConTeXtDlPrototype}%
\def\markdownRendererDlEndTightPrototype{%
\stopMarkdownConTeXtDlTightPrototype}%
-\long\def\markdownRendererEmphasisPrototype#1{{\em#1}}%
-\long\def\markdownRendererStrongEmphasisPrototype#1{{\bf\em#1}}%
+\def\markdownRendererEmphasisPrototype#1{{\em#1}}%
+\def\markdownRendererStrongEmphasisPrototype#1{{\bf\em#1}}%
\def\markdownRendererBlockQuoteBeginPrototype{\startquotation}%
\def\markdownRendererBlockQuoteEndPrototype{\stopquotation}%
-\long\def\markdownRendererInputVerbatimPrototype#1{\typefile{#1}}%
-\long\def\markdownRendererHeadingOnePrototype#1{\chapter{#1}}%
-\long\def\markdownRendererHeadingTwoPrototype#1{\section{#1}}%
-\long\def\markdownRendererHeadingThreePrototype#1{\subsection{#1}}%
-\long\def\markdownRendererHeadingFourPrototype#1{\subsubsection{#1}}%
-\long\def\markdownRendererHeadingFivePrototype#1{\subsubsubsection{#1}}%
-\long\def\markdownRendererHeadingSixPrototype#1{\subsubsubsubsection{#1}}%
+\def\markdownRendererInputVerbatimPrototype#1{\typefile{#1}}%
+\def\markdownRendererInputFencedCodePrototype#1#2{%
+ \ifx\relax#2\relax
+ \typefile{#1}%
+ \else
+% \end{macrocode}
+% The code fence infostring is used as a name from the \Hologo{ConTeXt}
+% \m{definetyping} command. This allows the user to set up code highlighting
+% mapping as follows:
+% \begin{Verbatim}
+% % Map the `TEX` syntax highlighter to the `latex` infostring.
+% \definetyping [latex]
+% \setuptyping [latex] [option=TEX]
+%
+% \starttext
+% \startmarkdown
+% ~~~ latex
+% \documentclass{article}
+% \begin{document}
+% Hello world!
+% \end{document}
+% ~~~
+% \stopmarkdown
+% \stoptext
+% \end{Verbatim}
+% \begin{macrocode}
+ \typefile[#2][]{#1}%
+ \fi}%
+\def\markdownRendererHeadingOnePrototype#1{\chapter{#1}}%
+\def\markdownRendererHeadingTwoPrototype#1{\section{#1}}%
+\def\markdownRendererHeadingThreePrototype#1{\subsection{#1}}%
+\def\markdownRendererHeadingFourPrototype#1{\subsubsection{#1}}%
+\def\markdownRendererHeadingFivePrototype#1{\subsubsubsection{#1}}%
+\def\markdownRendererHeadingSixPrototype#1{\subsubsubsubsection{#1}}%
\def\markdownRendererHorizontalRulePrototype{%
\blackrule[height=1pt, width=\hsize]}%
-\long\def\markdownRendererFootnotePrototype#1{\footnote{#1}}%
+\def\markdownRendererFootnotePrototype#1{\footnote{#1}}%
\stopmodule\protect
% \end{macrocode}
%
diff --git a/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex b/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex
index bad0124577b..4f90f3b8f8f 100644
--- a/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex
+++ b/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex
@@ -67,7 +67,7 @@
tex.print(unescape("|input markdown"))
end}%
\fi
-\ifnum\markdownMode<2
+\ifnum\markdownMode<2\relax
\def\markdownMakeOther{%
\catcode`|=12}%
\fi
@@ -90,10 +90,10 @@
\def\markdownRendererBackslashPrototype{\textbackslash}%
\def\markdownRendererTildePrototype{\textasciitilde}%
\def\markdownRendererPipePrototype{\char`|}%
-\long\def\markdownRendererLinkPrototype#1#2#3#4{%
+\def\markdownRendererLinkPrototype#1#2#3#4{%
\useURL[#1][#3][][#4]#1\footnote[#1]{\ifx\empty#4\empty\else#4:
\fi\tt<\hyphenatedurl{#3}>}}%
-\long\def\markdownRendererImagePrototype#1#2#3#4{%
+\def\markdownRendererImagePrototype#1#2#3#4{%
\placefigure[][fig:#1]{#4}{\externalfigure[#3]}}%
\def\markdownRendererUlBeginPrototype{\startitemize}%
\def\markdownRendererUlBeginTightPrototype{\startitemize[packed]}%
@@ -103,11 +103,11 @@
\def\markdownRendererOlBeginPrototype{\startitemize[n]}%
\def\markdownRendererOlBeginTightPrototype{\startitemize[packed,n]}%
\def\markdownRendererOlItemPrototype{\item}%
-\long\def\markdownRendererOlItemWithNumberPrototype#1{\sym{#1.}}%
+\def\markdownRendererOlItemWithNumberPrototype#1{\sym{#1.}}%
\def\markdownRendererOlEndPrototype{\stopitemize}%
\def\markdownRendererOlEndTightPrototype{\stopitemize}%
\definedescription
- [markdownConTeXtDlItemPrototype]
+ [MarkdownConTeXtDlItemPrototype]
[location=hanging,
margin=standard,
headstyle=bold]%
@@ -123,26 +123,34 @@
\startMarkdownConTeXtDlPrototype}%
\def\markdownRendererDlBeginTightPrototype{%
\startMarkdownConTeXtDlTightPrototype}%
-\long\def\markdownRendererDlItemPrototype#1{%
- \markdownConTeXtDlItemPrototype{#1}}%
+\def\markdownRendererDlItemPrototype#1{%
+ \startMarkdownConTeXtDlItemPrototype{#1}}%
+\def\markdownRendererDlItemEndPrototype{%
+ \stopMarkdownConTeXtDlItemPrototype}%
\def\markdownRendererDlEndPrototype{%
\stopMarkdownConTeXtDlPrototype}%
\def\markdownRendererDlEndTightPrototype{%
\stopMarkdownConTeXtDlTightPrototype}%
-\long\def\markdownRendererEmphasisPrototype#1{{\em#1}}%
-\long\def\markdownRendererStrongEmphasisPrototype#1{{\bf\em#1}}%
+\def\markdownRendererEmphasisPrototype#1{{\em#1}}%
+\def\markdownRendererStrongEmphasisPrototype#1{{\bf\em#1}}%
\def\markdownRendererBlockQuoteBeginPrototype{\startquotation}%
\def\markdownRendererBlockQuoteEndPrototype{\stopquotation}%
-\long\def\markdownRendererInputVerbatimPrototype#1{\typefile{#1}}%
-\long\def\markdownRendererHeadingOnePrototype#1{\chapter{#1}}%
-\long\def\markdownRendererHeadingTwoPrototype#1{\section{#1}}%
-\long\def\markdownRendererHeadingThreePrototype#1{\subsection{#1}}%
-\long\def\markdownRendererHeadingFourPrototype#1{\subsubsection{#1}}%
-\long\def\markdownRendererHeadingFivePrototype#1{\subsubsubsection{#1}}%
-\long\def\markdownRendererHeadingSixPrototype#1{\subsubsubsubsection{#1}}%
+\def\markdownRendererInputVerbatimPrototype#1{\typefile{#1}}%
+\def\markdownRendererInputFencedCodePrototype#1#2{%
+ \ifx\relax#2\relax
+ \typefile{#1}%
+ \else
+ \typefile[#2][]{#1}%
+ \fi}%
+\def\markdownRendererHeadingOnePrototype#1{\chapter{#1}}%
+\def\markdownRendererHeadingTwoPrototype#1{\section{#1}}%
+\def\markdownRendererHeadingThreePrototype#1{\subsection{#1}}%
+\def\markdownRendererHeadingFourPrototype#1{\subsubsection{#1}}%
+\def\markdownRendererHeadingFivePrototype#1{\subsubsubsection{#1}}%
+\def\markdownRendererHeadingSixPrototype#1{\subsubsubsubsection{#1}}%
\def\markdownRendererHorizontalRulePrototype{%
\blackrule[height=1pt, width=\hsize]}%
-\long\def\markdownRendererFootnotePrototype#1{\footnote{#1}}%
+\def\markdownRendererFootnotePrototype#1{\footnote{#1}}%
\stopmodule\protect
\endinput
%%
diff --git a/Master/texmf-dist/tex/generic/markdown/markdown.tex b/Master/texmf-dist/tex/generic/markdown/markdown.tex
index 247290d0b3b..12fcc8df129 100644
--- a/Master/texmf-dist/tex/generic/markdown/markdown.tex
+++ b/Master/texmf-dist/tex/generic/markdown/markdown.tex
@@ -45,29 +45,37 @@
%%
%% The names of the source files used are shown above.
%%
-\def\markdownLastModified{2016/08/14}%
-\def\markdownVersion{1.0.2}%
+\def\markdownLastModified{2016/08/20}%
+\def\markdownVersion{2.1.0}%
\let\markdownBegin\relax
\let\markdownEnd\relax
\let\markdownInput\relax
\def\markdownOptionHelperScriptFileName{\jobname.markdown.lua}%
\def\markdownOptionInputTempFileName{\jobname.markdown.in}%
\def\markdownOptionOutputTempFileName{\jobname.markdown.out}%
-\def\markdownOptionCacheDir{_markdown-\jobname}%
+\def\markdownOptionCacheDir{_markdown_\jobname}%
\let\markdownOptionBlankBeforeBlockquote\undefined
+\let\markdownOptionBlankBeforeCodeFence\undefined
\let\markdownOptionBlankBeforeHeading\undefined
+\let\markdownOptionCitations\undefined
+\let\markdownOptionCitationNbsps\undefined
\let\markdownOptionDefinitionLists\undefined
+\let\markdownOptionFootnotes\undefined
+\let\markdownOptionFencedCode\undefined
\let\markdownOptionHashEnumerators\undefined
\let\markdownOptionHybrid\undefined
-\let\markdownOptionFootnotes\undefined
\let\markdownOptionPreserveTabs\undefined
\let\markdownOptionSmartEllipses\undefined
\let\markdownOptionStartNumber\undefined
\let\markdownOptionTightLists\undefined
+\def\markdownRendererInterblockSeparator{%
+ \markdownRendererInterblockSeparatorPrototype}%
\def\markdownRendererLineBreak{%
\markdownRendererLineBreakPrototype}%
\def\markdownRendererEllipsis{%
\markdownRendererEllipsisPrototype}%
+\def\markdownRendererNbsp{%
+ \markdownRendererNbspPrototype}%
\def\markdownRendererLeftBrace{%
\markdownRendererLeftBracePrototype}%
\def\markdownRendererRightBrace{%
@@ -102,6 +110,8 @@
\markdownRendererUlBeginTightPrototype}%
\def\markdownRendererUlItem{%
\markdownRendererUlItemPrototype}%
+\def\markdownRendererUlItemEnd{%
+ \markdownRendererUlItemEndPrototype}%
\def\markdownRendererUlEnd{%
\markdownRendererUlEndPrototype}%
\def\markdownRendererUlEndTight{%
@@ -112,6 +122,8 @@
\markdownRendererOlBeginTightPrototype}%
\def\markdownRendererOlItem{%
\markdownRendererOlItemPrototype}%
+\def\markdownRendererOlItemEnd{%
+ \markdownRendererOlItemEndPrototype}%
\def\markdownRendererOlItemWithNumber{%
\markdownRendererOlItemWithNumberPrototype}%
\def\markdownRendererOlEnd{%
@@ -124,6 +136,8 @@
\markdownRendererDlBeginTightPrototype}%
\def\markdownRendererDlItem{%
\markdownRendererDlItemPrototype}%
+\def\markdownRendererDlItemEnd{%
+ \markdownRendererDlItemEndPrototype}%
\def\markdownRendererDlDefinitionBegin{%
\markdownRendererDlDefinitionBeginPrototype}%
\def\markdownRendererDlDefinitionEnd{%
@@ -142,6 +156,8 @@
\markdownRendererBlockQuoteEndPrototype}%
\def\markdownRendererInputVerbatim{%
\markdownRendererInputVerbatimPrototype}%
+\def\markdownRendererInputFencedCode{%
+ \markdownRendererInputFencedCodePrototype}%
\def\markdownRendererHeadingOne{%
\markdownRendererHeadingOnePrototype}%
\def\markdownRendererHeadingTwo{%
@@ -158,8 +174,14 @@
\markdownRendererHorizontalRulePrototype}%
\def\markdownRendererFootnote{%
\markdownRendererFootnotePrototype}%
+\def\markdownRendererCite{%
+ \markdownRendererCitePrototype}%
+\def\markdownRendererTextCite{%
+ \markdownRendererTextCitePrototype}%
+\def\markdownRendererInterblockSeparatorPrototype{}%
\def\markdownRendererLineBreakPrototype{}%
\def\markdownRendererEllipsisPrototype{}%
+\def\markdownRendererNbspPrototype{}%
\def\markdownRendererLeftBracePrototype{}%
\def\markdownRendererRightBracePrototype{}%
\def\markdownRendererDollarSignPrototype{}%
@@ -171,40 +193,46 @@
\def\markdownRendererBackslashPrototype{}%
\def\markdownRendererTildePrototype{}%
\def\markdownRendererPipePrototype{}%
-\long\def\markdownRendererCodeSpanPrototype#1{}%
-\long\def\markdownRendererLinkPrototype#1#2#3#4{}%
-\long\def\markdownRendererImagePrototype#1#2#3#4{}%
+\def\markdownRendererCodeSpanPrototype#1{}%
+\def\markdownRendererLinkPrototype#1#2#3#4{}%
+\def\markdownRendererImagePrototype#1#2#3#4{}%
\def\markdownRendererUlBeginPrototype{}%
\def\markdownRendererUlBeginTightPrototype{}%
\def\markdownRendererUlItemPrototype{}%
+\def\markdownRendererUlItemEndPrototype{}%
\def\markdownRendererUlEndPrototype{}%
\def\markdownRendererUlEndTightPrototype{}%
\def\markdownRendererOlBeginPrototype{}%
\def\markdownRendererOlBeginTightPrototype{}%
\def\markdownRendererOlItemPrototype{}%
-\long\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemEndPrototype{}%
\def\markdownRendererOlEndPrototype{}%
\def\markdownRendererOlEndTightPrototype{}%
\def\markdownRendererDlBeginPrototype{}%
\def\markdownRendererDlBeginTightPrototype{}%
-\long\def\markdownRendererDlItemPrototype#1{}%
+\def\markdownRendererDlItemPrototype#1{}%
+\def\markdownRendererDlItemEndPrototype{}%
\def\markdownRendererDlDefinitionBeginPrototype{}%
\def\markdownRendererDlDefinitionEndPrototype{}%
\def\markdownRendererDlEndPrototype{}%
\def\markdownRendererDlEndTightPrototype{}%
-\long\def\markdownRendererEmphasisPrototype#1{}%
-\long\def\markdownRendererStrongEmphasisPrototype#1{}%
+\def\markdownRendererEmphasisPrototype#1{}%
+\def\markdownRendererStrongEmphasisPrototype#1{}%
\def\markdownRendererBlockQuoteBeginPrototype{}%
\def\markdownRendererBlockQuoteEndPrototype{}%
-\long\def\markdownRendererInputVerbatimPrototype#1{}%
-\long\def\markdownRendererHeadingOnePrototype#1{}%
-\long\def\markdownRendererHeadingTwoPrototype#1{}%
-\long\def\markdownRendererHeadingThreePrototype#1{}%
-\long\def\markdownRendererHeadingFourPrototype#1{}%
-\long\def\markdownRendererHeadingFivePrototype#1{}%
-\long\def\markdownRendererHeadingSixPrototype#1{}%
+\def\markdownRendererInputVerbatimPrototype#1{}%
+\def\markdownRendererInputFencedCodePrototype#1#2{}%
+\def\markdownRendererHeadingOnePrototype#1{}%
+\def\markdownRendererHeadingTwoPrototype#1{}%
+\def\markdownRendererHeadingThreePrototype#1{}%
+\def\markdownRendererHeadingFourPrototype#1{}%
+\def\markdownRendererHeadingFivePrototype#1{}%
+\def\markdownRendererHeadingSixPrototype#1{}%
\def\markdownRendererHorizontalRulePrototype{}%
-\long\def\markdownRendererFootnotePrototype#1{}%
+\def\markdownRendererFootnotePrototype#1{}%
+\def\markdownRendererCitePrototype#1{}%
+\def\markdownRendererTextCitePrototype#1{}%
\def\markdownInfo#1{}%
\def\markdownWarning#1{}%
\def\markdownError#1{}%
@@ -235,8 +263,10 @@
\def\markdownError#1#2{%
\errhelp{#2.}%
\errmessage{(l.\the\inputlineno) markdown.tex error: #1}}%
+\def\markdownRendererInterblockSeparatorPrototype{\par}%
\def\markdownRendererLineBreakPrototype{\hfil\break}%
\let\markdownRendererEllipsisPrototype\dots
+\def\markdownRendererNbspPrototype{~}%
\def\markdownRendererLeftBracePrototype{\char`{}%
\def\markdownRendererRightBracePrototype{\char`}}%
\def\markdownRendererDollarSignPrototype{\char`$}%
@@ -248,63 +278,82 @@
\def\markdownRendererBackslashPrototype{\char`\\}%
\def\markdownRendererTildePrototype{\char`~}%
\def\markdownRendererPipePrototype{|}%
-\long\def\markdownRendererCodeSpanPrototype#1{{\tt#1}}%
-\long\def\markdownRendererLinkPrototype#1#2#3#4{#2}%
-\long\def\markdownRendererImagePrototype#1#2#3#4{#2}%
+\def\markdownRendererCodeSpanPrototype#1{{\tt#1}}%
+\def\markdownRendererLinkPrototype#1#2#3#4{#2}%
+\def\markdownRendererImagePrototype#1#2#3#4{#2}%
\def\markdownRendererUlBeginPrototype{}%
\def\markdownRendererUlBeginTightPrototype{}%
\def\markdownRendererUlItemPrototype{}%
+\def\markdownRendererUlItemEndPrototype{}%
\def\markdownRendererUlEndPrototype{}%
\def\markdownRendererUlEndTightPrototype{}%
\def\markdownRendererOlBeginPrototype{}%
\def\markdownRendererOlBeginTightPrototype{}%
\def\markdownRendererOlItemPrototype{}%
-\long\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemWithNumberPrototype#1{}%
+\def\markdownRendererOlItemEndPrototype{}%
\def\markdownRendererOlEndPrototype{}%
\def\markdownRendererOlEndTightPrototype{}%
\def\markdownRendererDlBeginPrototype{}%
\def\markdownRendererDlBeginTightPrototype{}%
-\long\def\markdownRendererDlItemPrototype#1{#1}%
+\def\markdownRendererDlItemPrototype#1{#1}%
+\def\markdownRendererDlItemEndPrototype{}%
\def\markdownRendererDlDefinitionBeginPrototype{}%
\def\markdownRendererDlDefinitionEndPrototype{\par}%
\def\markdownRendererDlEndPrototype{}%
\def\markdownRendererDlEndTightPrototype{}%
-\long\def\markdownRendererEmphasisPrototype#1{{\it#1}}%
-\long\def\markdownRendererStrongEmphasisPrototype#1{{\it#1}}%
+\def\markdownRendererEmphasisPrototype#1{{\it#1}}%
+\def\markdownRendererStrongEmphasisPrototype#1{{\it#1}}%
\def\markdownRendererBlockQuoteBeginPrototype{\par\begingroup\it}%
\def\markdownRendererBlockQuoteEndPrototype{\endgroup\par}%
-\long\def\markdownRendererInputVerbatimPrototype#1{%
-\par{\tt\input"#1"\relax}\par}%
-\long\def\markdownRendererHeadingOnePrototype#1{#1}%
-\long\def\markdownRendererHeadingTwoPrototype#1{#1}%
-\long\def\markdownRendererHeadingThreePrototype#1{#1}%
-\long\def\markdownRendererHeadingFourPrototype#1{#1}%
-\long\def\markdownRendererHeadingFivePrototype#1{#1}%
-\long\def\markdownRendererHeadingSixPrototype#1{#1}%
+\def\markdownRendererInputVerbatimPrototype#1{%
+ \par{\tt\input"#1"\relax}\par}%
+\def\markdownRendererInputFencedCodePrototype#1#2{%
+ \markdownRendererInputVerbatimPrototype{#1}}%
+\def\markdownRendererHeadingOnePrototype#1{#1}%
+\def\markdownRendererHeadingTwoPrototype#1{#1}%
+\def\markdownRendererHeadingThreePrototype#1{#1}%
+\def\markdownRendererHeadingFourPrototype#1{#1}%
+\def\markdownRendererHeadingFivePrototype#1{#1}%
+\def\markdownRendererHeadingSixPrototype#1{#1}%
\def\markdownRendererHorizontalRulePrototype{}%
-\long\def\markdownRendererFootnotePrototype#1{#1}%
+\def\markdownRendererFootnotePrototype#1{#1}%
+\def\markdownRendererCitePrototype#1{}%
+\def\markdownRendererTextCitePrototype#1{}%
\def\markdownLuaOptions{{%
\ifx\markdownOptionBlankBeforeBlockquote\undefined\else
blankBeforeBlockquote = \markdownOptionBlankBeforeBlockquote,
\fi
+\ifx\markdownOptionBlankBeforeCodeFence\undefined\else
+ blankBeforeCodeFence = \markdownOptionBlankBeforeCodeFence,
+\fi
\ifx\markdownOptionBlankBeforeHeading\undefined\else
blankBeforeHeading = \markdownOptionBlankBeforeHeading,
\fi
\ifx\markdownOptionCacheDir\undefined\else
cacheDir = "\markdownOptionCacheDir",
\fi
+\ifx\markdownOptionCitations\undefined\else
+ citations = \markdownOptionCitations,
+\fi
+\ifx\markdownOptionCitationNbsps\undefined\else
+ citationNbsps = \markdownOptionCitationNbsps,
+\fi
\ifx\markdownOptionDefinitionLists\undefined\else
definitionLists = \markdownOptionDefinitionLists,
\fi
+\ifx\markdownOptionFootnotes\undefined\else
+ footnotes = \markdownOptionFootnotes,
+\fi
+\ifx\markdownOptionFencedCode\undefined\else
+ fencedCode = \markdownOptionFencedCode,
+\fi
\ifx\markdownOptionHashEnumerators\undefined\else
hashEnumerators = \markdownOptionHashEnumerators,
\fi
\ifx\markdownOptionHybrid\undefined\else
hybrid = \markdownOptionHybrid,
\fi
-\ifx\markdownOptionFootnotes\undefined\else
- footnotes = \markdownOptionFootnotes,
-\fi
\ifx\markdownOptionPreserveTabs\undefined\else
preserveTabs = \markdownOptionPreserveTabs,
\fi
@@ -335,19 +384,19 @@ local convert = md.new(\markdownLuaOptions)
\markdownInfo{Using mode 1: Shell escape via os.execute}%
\fi
\csname newwrite\endcsname\markdownLuaExecuteFileStream
-\ifnum\markdownMode=0\relax
- \ifx\pdfshellescape\undefined
- \ifx\shellescape\undefined
+\ifx\pdfshellescape\undefined
+ \ifx\shellescape\undefined
+ \ifnum\markdownMode=0\relax
\def\markdownExecuteShellEscape{1}%
\else
- \let\markdownExecuteShellEscape\shellescape
+ \def\markdownExecuteShellEscape{%
+ \directlua{tex.sprint(status.shell_escape or "1")}}%
\fi
\else
- \let\markdownExecuteShellEscape\pdfshellescape
+ \let\markdownExecuteShellEscape\shellescape
\fi
\else
- \def\markdownExecuteShellEscape{%
- \directlua{tex.sprint(status.shell_escape)}}%
+ \let\markdownExecuteShellEscape\pdfshellescape
\fi
\ifnum\markdownMode=0\relax
\def\markdownExecuteDirect#1{\immediate\write18{#1}}%
@@ -403,7 +452,6 @@ local convert = md.new(\markdownLuaOptions)
|else%
|def^^M{%
|markdownInfo{The ending token sequence was found}%
- |immediate|write|markdownLuaExecuteFileStream{}%
|immediate|closeout|markdownLuaExecuteFileStream%
|endgroup%
|markdownInput|markdownOptionInputTempFileName%
@@ -443,8 +491,8 @@ local convert = md.new(\markdownLuaOptions)
"([%(%)%.%%%+%-%*%?%[%]%^%$])", "%%%1")
|markdownLuaRegisterIBCallback{function(line)
if line:match(ending_sequence) then
- |markdownLuaUnregisterIBCallback
- local input = table.concat(buffer, "\n") .. "\n\n"
+ |markdownLuaUnregisterIBCallback;
+ local input = table.concat(buffer, "\n") .. "\n"
local output = convert(input)
return [[\markdownInfo{The ending token sequence was found}]] ..
output .. [[\markdownReadAndConvertAfter]]
@@ -463,7 +511,7 @@ local convert = md.new(\markdownLuaOptions)
|markdownInfo{Including markdown document "#1"}%
|markdownLuaExecute{%
|markdownPrepare
- local input = assert(io.open("#1","r")):read("*a") .. "\n\n"
+ local input = assert(io.open("#1","r")):read("*a")
print(convert(input:gsub("\r\n?", "\n")))}}%
|endgroup
\endinput
diff --git a/Master/texmf-dist/tex/latex/markdown/markdown.sty b/Master/texmf-dist/tex/latex/markdown/markdown.sty
index 08dc59ef1e8..34f443fef1b 100644
--- a/Master/texmf-dist/tex/latex/markdown/markdown.sty
+++ b/Master/texmf-dist/tex/latex/markdown/markdown.sty
@@ -59,18 +59,26 @@
\def\markdownOptionOutputTempFileName{#1}}%
\define@key{markdownOptions}{blankBeforeBlockquote}[true]{%
\def\markdownOptionBlankBeforeBlockquote{#1}}%
+\define@key{markdownOptions}{blankBeforeCodeFence}[true]{%
+ \def\markdownOptionBlankBeforeCodeFence{#1}}%
\define@key{markdownOptions}{blankBeforeHeading}[true]{%
\def\markdownOptionBlankBeforeHeading{#1}}%
+\define@key{markdownOptions}{citations}[true]{%
+ \def\markdownOptionCitations{#1}}%
+\define@key{markdownOptions}{citationNbsps}[true]{%
+ \def\markdownOptionCitationNbsps{#1}}%
\define@key{markdownOptions}{cacheDir}{%
\def\markdownOptionCacheDir{#1}}%
\define@key{markdownOptions}{definitionLists}[true]{%
\def\markdownOptionDefinitionLists{#1}}%
+\define@key{markdownOptions}{footnotes}[true]{%
+ \def\markdownOptionFootnotes{#1}}%
+\define@key{markdownOptions}{fencedCode}[true]{%
+ \def\markdownOptionFencedCode{#1}}%
\define@key{markdownOptions}{hashEnumerators}[true]{%
\def\markdownOptionHashEnumerators{#1}}%
\define@key{markdownOptions}{hybrid}[true]{%
\def\markdownOptionHybrid{#1}}%
-\define@key{markdownOptions}{footnotes}[true]{%
- \def\markdownOptionFootnotes{#1}}%
\define@key{markdownOptions}{preserveTabs}[true]{%
\def\markdownOptionPreserveTabs{#1}}%
\define@key{markdownOptions}{smartEllipses}[true]{%
@@ -79,12 +87,14 @@
\def\markdownOptionStartNumber{#1}}%
\define@key{markdownOptions}{tightLists}[true]{%
\def\markdownOptionTightLists{#1}}%
-\define@key{markdownOptions}{renderers}{%
- \setkeys{markdownRenderers}{#1}}%
+\define@key{markdownRenderers}{interblockSeparator}{%
+ \renewcommand\markdownRendererInterblockSeparator{#1}}%
\define@key{markdownRenderers}{lineBreak}{%
\renewcommand\markdownRendererLineBreak{#1}}%
\define@key{markdownRenderers}{ellipsis}{%
\renewcommand\markdownRendererEllipsis{#1}}%
+\define@key{markdownRenderers}{nbsp}{%
+ \renewcommand\markdownRendererNbsp{#1}}%
\define@key{markdownRenderers}{leftBrace}{%
\renewcommand\markdownRendererLeftBrace{#1}}%
\define@key{markdownRenderers}{rightBrace}{%
@@ -119,6 +129,8 @@
\renewcommand\markdownRendererUlBeginTight{#1}}%
\define@key{markdownRenderers}{ulItem}{%
\renewcommand\markdownRendererUlItem{#1}}%
+\define@key{markdownRenderers}{ulItemEnd}{%
+ \renewcommand\markdownRendererUlItemEnd{#1}}%
\define@key{markdownRenderers}{ulEnd}{%
\renewcommand\markdownRendererUlEnd{#1}}%
\define@key{markdownRenderers}{ulEndTight}{%
@@ -131,6 +143,8 @@
\renewcommand\markdownRendererOlItem{#1}}%
\define@key{markdownRenderers}{olItemWithNumber}{%
\renewcommand\markdownRendererOlItemWithNumber[1]{#1}}%
+\define@key{markdownRenderers}{olItemEnd}{%
+ \renewcommand\markdownRendererOlItemEnd{#1}}%
\define@key{markdownRenderers}{olEnd}{%
\renewcommand\markdownRendererOlEnd{#1}}%
\define@key{markdownRenderers}{olEndTight}{%
@@ -141,6 +155,8 @@
\renewcommand\markdownRendererDlBeginTight{#1}}%
\define@key{markdownRenderers}{dlItem}{%
\renewcommand\markdownRendererDlItem[1]{#1}}%
+\define@key{markdownRenderers}{dlItemEnd}{%
+ \renewcommand\markdownRendererDlItemEnd{#1}}%
\define@key{markdownRenderers}{dlDefinitionBegin}{%
\renewcommand\markdownRendererDlDefinitionBegin{#1}}%
\define@key{markdownRenderers}{dlDefinitionEnd}{%
@@ -159,6 +175,8 @@
\renewcommand\markdownRendererBlockQuoteEnd{#1}}%
\define@key{markdownRenderers}{inputVerbatim}{%
\renewcommand\markdownRendererInputVerbatim[1]{#1}}%
+\define@key{markdownRenderers}{inputFencedCode}{%
+ \renewcommand\markdownRendererInputFencedCode[2]{#1}}%
\define@key{markdownRenderers}{headingOne}{%
\renewcommand\markdownRendererHeadingOne[1]{#1}}%
\define@key{markdownRenderers}{headingTwo}{%
@@ -175,12 +193,18 @@
\renewcommand\markdownRendererHorizontalRule{#1}}%
\define@key{markdownRenderers}{footnote}{%
\renewcommand\markdownRendererFootnote[1]{#1}}%
-\define@key{markdownOptions}{rendererPrototypes}{%
- \setkeys{markdownRendererPrototypes}{#1}}%
+\define@key{markdownRenderers}{cite}{%
+ \renewcommand\markdownRendererCite[1]{#1}}%
+\define@key{markdownRenderers}{textCite}{%
+ \renewcommand\markdownRendererTextCite[1]{#1}}%
+\define@key{markdownRendererPrototypes}{interblockSeparator}{%
+ \renewcommand\markdownRendererInterblockSeparatorPrototype{#1}}%
\define@key{markdownRendererPrototypes}{lineBreak}{%
\renewcommand\markdownRendererLineBreakPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ellipsis}{%
\renewcommand\markdownRendererEllipsisPrototype{#1}}%
+\define@key{markdownRendererPrototypes}{nbsp}{%
+ \renewcommand\markdownRendererNbspPrototype{#1}}%
\define@key{markdownRendererPrototypes}{leftBrace}{%
\renewcommand\markdownRendererLeftBracePrototype{#1}}%
\define@key{markdownRendererPrototypes}{rightBrace}{%
@@ -202,19 +226,21 @@
\define@key{markdownRendererPrototypes}{tilde}{%
\renewcommand\markdownRendererTildePrototype{#1}}%
\define@key{markdownRendererPrototypes}{pipe}{%
- \renewcommand\markdownRendererPipe{#1}}%
+ \renewcommand\markdownRendererPipePrototype{#1}}%
\define@key{markdownRendererPrototypes}{codeSpan}{%
\renewcommand\markdownRendererCodeSpanPrototype[1]{#1}}%
\define@key{markdownRendererPrototypes}{link}{%
- \renewcommand\markdownRendererLink[4]{#1}}%
+ \renewcommand\markdownRendererLinkPrototype[4]{#1}}%
\define@key{markdownRendererPrototypes}{image}{%
- \renewcommand\markdownRendererImage[4]{#1}}%
+ \renewcommand\markdownRendererImagePrototype[4]{#1}}%
\define@key{markdownRendererPrototypes}{ulBegin}{%
\renewcommand\markdownRendererUlBeginPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulBeginTight}{%
\renewcommand\markdownRendererUlBeginTightPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulItem}{%
\renewcommand\markdownRendererUlItemPrototype{#1}}%
+\define@key{markdownRendererPrototypes}{ulItemEnd}{%
+ \renewcommand\markdownRendererUlItemEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulEnd}{%
\renewcommand\markdownRendererUlEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{ulEndTight}{%
@@ -227,6 +253,8 @@
\renewcommand\markdownRendererOlItemPrototype{#1}}%
\define@key{markdownRendererPrototypes}{olItemWithNumber}{%
\renewcommand\markdownRendererOlItemWithNumberPrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{olItemEnd}{%
+ \renewcommand\markdownRendererOlItemEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{olEnd}{%
\renewcommand\markdownRendererOlEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{olEndTight}{%
@@ -237,6 +265,8 @@
\renewcommand\markdownRendererDlBeginTightPrototype{#1}}%
\define@key{markdownRendererPrototypes}{dlItem}{%
\renewcommand\markdownRendererDlItemPrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{dlItemEnd}{%
+ \renewcommand\markdownRendererDlItemEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{dlDefinitionBegin}{%
\renewcommand\markdownRendererDlDefinitionBeginPrototype{#1}}%
\define@key{markdownRendererPrototypes}{dlDefinitionEnd}{%
@@ -255,6 +285,8 @@
\renewcommand\markdownRendererBlockQuoteEndPrototype{#1}}%
\define@key{markdownRendererPrototypes}{inputVerbatim}{%
\renewcommand\markdownRendererInputVerbatimPrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{inputFencedCode}{%
+ \renewcommand\markdownRendererInputFencedCodePrototype[2]{#1}}%
\define@key{markdownRendererPrototypes}{headingOne}{%
\renewcommand\markdownRendererHeadingOnePrototype[1]{#1}}%
\define@key{markdownRendererPrototypes}{headingTwo}{%
@@ -271,6 +303,10 @@
\renewcommand\markdownRendererHorizontalRulePrototype{#1}}%
\define@key{markdownRendererPrototypes}{footnote}{%
\renewcommand\markdownRendererFootnotePrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{cite}{%
+ \renewcommand\markdownRendererCitePrototype[1]{#1}}%
+\define@key{markdownRendererPrototypes}{textCite}{%
+ \renewcommand\markdownRendererTextCitePrototype[1]{#1}}%
\input markdown
\def\markdownVersionSpace{ }%
\ProvidesPackage{markdown}[\markdownLastModified\markdownVersionSpace v%
@@ -299,6 +335,12 @@
\DeclareOption*{%
\expandafter\markdownSetup\expandafter{\CurrentOption}}%
\ProcessOptions\relax
+\define@key{markdownOptions}{renderers}{%
+ \setkeys{markdownRenderers}{#1}%
+ \def\KV@prefix{KV@markdownOptions@}}%
+\define@key{markdownOptions}{rendererPrototypes}{%
+ \setkeys{markdownRendererPrototypes}{#1}%
+ \def\KV@prefix{KV@markdownOptions@}}%
\RequirePackage{url}
\RequirePackage{graphicx}
\RequirePackage{ifthen}
@@ -357,31 +399,103 @@
blockQuoteBegin = {\begin{quotation}},
blockQuoteEnd = {\end{quotation}},
inputVerbatim = {\VerbatimInput{#1}},
+ inputFencedCode = {%
+ \ifx\relax#2\relax
+ \VerbatimInput{#1}%
+ \else
+ \ifx\minted@jobname\undefined
+ \ifx\lst@version\undefined
+ \markdownRendererInputFencedCode{#1}{}%
+ \else
+ \lstinputlisting[language=#2]{#1}%
+ \fi
+ \else
+ \inputminted{#2}{#1}%
+ \fi
+ \fi},
horizontalRule = {\noindent\rule[0.5ex]{\linewidth}{1pt}},
- footnote = {\footnote{#1}}}}%
+ footnote = {\footnote{#1}}}}
\ifx\chapter\undefined
- \markdownSetup{rendererPrototypes={
+ \markdownSetup{rendererPrototypes = {
headingOne = {\section{#1}},
headingTwo = {\subsection{#1}},
headingThree = {\subsubsection{#1}},
headingFour = {\paragraph{#1}},
- headingFive = {\subparagraph{#1}}}}%
+ headingFive = {\subparagraph{#1}}}}
\else
- \markdownSetup{rendererPrototypes={
+ \markdownSetup{rendererPrototypes = {
headingOne = {\chapter{#1}},
headingTwo = {\section{#1}},
headingThree = {\subsection{#1}},
headingFour = {\subsubsection{#1}},
headingFive = {\paragraph{#1}},
- headingSix = {\subparagraph{#1}}}}%
+ headingSix = {\subparagraph{#1}}}}
\fi
+\newcount\markdownLaTeXCitationsCounter
+
+\def\markdownLaTeXBasicCitations#1#2#3#4{%
+ \advance\markdownLaTeXCitationsCounter by 1\relax
+ \ifx\relax#2\relax\else#2~\fi\cite[#3]{#4}%
+ \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax
+ \expandafter\@gobble
+ \fi\markdownLaTeXBasicCitations}
+\let\markdownLaTeXBasicTextCitations\markdownLaTeXBasicCitations
+
+\def\markdownLaTeXBibLaTeXCitations#1#2#3#4#5{%
+ \advance\markdownLaTeXCitationsCounter by 1\relax
+ \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax
+ \autocites#1[#3][#4]{#5}%
+ \expandafter\@gobbletwo
+ \fi\markdownLaTeXBibLaTeXCitations{#1[#3][#4]{#5}}}
+\def\markdownLaTeXBibLaTeXTextCitations#1#2#3#4#5{%
+ \advance\markdownLaTeXCitationsCounter by 1\relax
+ \ifnum\markdownLaTeXCitationsCounter>\markdownLaTeXCitationsTotal\relax
+ \textcites#1[#3][#4]{#5}%
+ \expandafter\@gobbletwo
+ \fi\markdownLaTeXBibLaTeXTextCitations{#1[#3][#4]{#5}}}
+
+\markdownSetup{rendererPrototypes = {
+ cite = {%
+ \markdownLaTeXCitationsCounter=1%
+ \def\markdownLaTeXCitationsTotal{#1}%
+ \ifx\autocites\undefined
+ \expandafter
+ \markdownLaTeXBasicCitations
+ \else
+ \expandafter\expandafter\expandafter
+ \markdownLaTeXBibLaTeXCitations
+ \expandafter{\expandafter}%
+ \fi},
+ textCite = {%
+ \markdownLaTeXCitationsCounter=1%
+ \def\markdownLaTeXCitationsTotal{#1}%
+ \ifx\textcites\undefined
+ \expandafter
+ \markdownLaTeXBasicTextCitations
+ \else
+ \expandafter\expandafter\expandafter
+ \markdownLaTeXBibLaTeXTextCitations
+ \expandafter{\expandafter}%
+ \fi}}}
+\let\markdownLuaRegisterIBCallbackPrevious
+ \markdownLuaRegisterIBCallback
+\let\markdownLuaUnregisterIBCallbackPrevious
+ \markdownLuaUnregisterIBCallback
\renewcommand\markdownLuaRegisterIBCallback[1]{%
- luatexbase.add_to_callback("process_input_buffer", #1, %
- "The markdown input processor")}
+ if luatexbase and luatexbase.add_to_callback then
+ luatexbase.add_to_callback("process_input_buffer", #1, %
+ "The markdown input processor")
+ else
+ \markdownLuaRegisterIBCallbackPrevious{#1}
+ end}
\renewcommand\markdownLuaUnregisterIBCallback{%
- luatexbase.remove_from_callback("process_input_buffer",%
- "The markdown input processor")}
+ if luatexbase and luatexbase.add_to_callback then
+ luatexbase.remove_from_callback("process_input_buffer",%
+ "The markdown input processor")
+ else
+ \markdownLuaUnregisterIBCallbackPrevious;
+ end}
\newcommand\markdownMakeOther{%
\count0=128\relax
\loop
diff --git a/Master/texmf-dist/tex/luatex/markdown/markdown.lua b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
index 8a0f237c1d7..6a194bbf7ea 100644
--- a/Master/texmf-dist/tex/luatex/markdown/markdown.lua
+++ b/Master/texmf-dist/tex/luatex/markdown/markdown.lua
@@ -57,24 +57,30 @@
-- should contain your own preambles for the files it generates, not
-- those in the standard .ins files.
--
-if not modules then modules = { } end modules ['markdown'] = {
- version = "1.0.2",
+local metadata = {
+ version = "2.1.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 Vít Novotný",
license = "LPPL 1.3"
}
+if not modules then modules = { } end
+modules['markdown'] = metadata
local lpeg = require("lpeg")
local unicode = require("unicode")
local md5 = require("md5")
local M = {}
local defaultOptions = {}
defaultOptions.blankBeforeBlockquote = false
+defaultOptions.blankBeforeCodeFence = false
defaultOptions.blankBeforeHeading = false
defaultOptions.cacheDir = "."
+defaultOptions.citationNbsps = true
+defaultOptions.citations = false
defaultOptions.definitionLists = false
defaultOptions.hashEnumerators = false
defaultOptions.hybrid = false
+defaultOptions.fencedCode = false
defaultOptions.footnotes = false
defaultOptions.preserveTabs = false
defaultOptions.smartEllipses = false
@@ -222,6 +228,7 @@ function M.writer.new(options)
return defaultOptions[key] end })
self.suffix = ".tex"
self.space = " "
+ self.nbsp = "\\markdownRendererNbsp{}"
function self.plain(s)
return s
end
@@ -231,12 +238,11 @@ function M.writer.new(options)
function self.pack(name)
return [[\input"]] .. name .. [["\relax]]
end
- self.interblocksep = "\n\n"
- self.containersep = "\n\n"
+ self.interblocksep = "\\markdownRendererInterblockSeparator\n{}"
self.eof = [[\relax]]
- self.linebreak = "\\markdownRendererLineBreak "
+ self.linebreak = "\\markdownRendererLineBreak\n{}"
self.ellipsis = "\\markdownRendererEllipsis{}"
- self.hrule = "\\markdownRendererHorizontalRule "
+ self.hrule = "\\markdownRendererHorizontalRule{}"
local escaped_chars = {
["{"] = "\\markdownRendererLeftBrace{}",
["}"] = "\\markdownRendererRightBrace{}",
@@ -282,7 +288,8 @@ function M.writer.new(options)
"{",self.string(tit or ""),"}"}
end
local function ulitem(s)
- return {"\\markdownRendererUlItem ",s}
+ return {"\\markdownRendererUlItem ",s,
+ "\\markdownRendererUlItemEnd "}
end
function self.bulletlist(items,tight)
@@ -301,9 +308,11 @@ function M.writer.new(options)
end
local function olitem(s,num)
if num ~= nil then
- return {"\\markdownRendererOlItemWithNumber{",num,"}",s}
+ return {"\\markdownRendererOlItemWithNumber{",num,"}",s,
+ "\\markdownRendererOlItemEnd "}
else
- return {"\\markdownRendererOlItem ",s}
+ return {"\\markdownRendererOlItem ",s,
+ "\\markdownRendererOlItemEnd "}
end
end
@@ -331,6 +340,7 @@ function M.writer.new(options)
retVal[#retVal+1] = {"\\markdownRendererDlDefinitionBegin ",def,
"\\markdownRendererDlDefinitionEnd "}
end
+ retVal[#retVal+1] = "\\markdownRendererDlItemEnd "
return retVal
end
@@ -339,13 +349,12 @@ function M.writer.new(options)
for _,item in ipairs(items) do
buffer[#buffer + 1] = dlitem(item.term, item.definitions)
end
- local contents = util.intersperse(buffer, self.containersep)
if tight and options.tightLists then
- return {"\\markdownRendererDlBeginTight\n\n", contents,
- "\n\n\\markdownRendererDlEndTight\n"}
+ return {"\\markdownRendererDlBeginTight\n", buffer,
+ "\n\\markdownRendererDlEndTight"}
else
- return {"\\markdownRendererDlBegin\n\n", contents,
- "\n\n\\markdownRendererDlEnd\n"}
+ return {"\\markdownRendererDlBegin\n", buffer,
+ "\n\\markdownRendererDlEnd"}
end
end
function self.emphasis(s)
@@ -362,6 +371,10 @@ function M.writer.new(options)
local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
return {"\\markdownRendererInputVerbatim{",name,"}"}
end
+ function self.fencedCode(i, s)
+ local name = util.cache(options.cacheDir, s, nil, nil, ".verbatim")
+ return {"\\markdownRendererInputFencedCode{",name,"}{",i,"}"}
+ end
function self.heading(s,level)
local cmd
if level == 1 then
@@ -384,6 +397,15 @@ function M.writer.new(options)
function self.note(s)
return {"\\markdownRendererFootnote{",s,"}"}
end
+ 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
return self
end
@@ -410,41 +432,33 @@ function M.reader.new(writer, options)
end
end
local syntax
+ local blocks_toplevel
local blocks
- local inlines
+ local inlines, inlines_no_link, inlines_nbsp
- local parse_blocks =
- function(str)
- local res = lpeg.match(blocks, str)
+ local function create_parser(name, grammar)
+ return function(str)
+ local res = lpeg.match(grammar(), str)
if res == nil then
- error(format("parse_blocks failed on:\n%s", str:sub(1,20)))
- else
- return res
- end
- end
-
- local parse_inlines =
- function(str)
- local res = lpeg.match(inlines, str)
- if res == nil then
- error(format("parse_inlines failed on:\n%s",
- str:sub(1,20)))
+ error(format("%s failed on:\n%s", name, str:sub(1,20)))
else
return res
end
end
+ end
- local parse_inlines_no_link =
- function(str)
- local res = lpeg.match(inlines_no_link, str)
- if res == nil then
- error(format("parse_inlines_no_link failed on:\n%s",
- str:sub(1,20)))
- else
- return res
- end
- end
+ local parse_blocks = create_parser("parse_blocks",
+ function() return blocks end)
+ local parse_blocks_toplevel = create_parser("parse_blocks_toplevel",
+ function() return blocks_toplevel end)
+ local parse_inlines = create_parser("parse_inlines",
+ function() return inlines end)
+ local parse_inlines_no_link = create_parser("parse_inlines_no_link",
+ function() return inlines_no_link end)
+ local parse_inlines_nbsp = create_parser("parse_inlines_nbsp",
+ function() return inlines_nbsp end)
local percent = P("%")
+ local at = P("@")
local asterisk = P("*")
local dash = P("-")
local plus = P("+")
@@ -468,12 +482,14 @@ function M.reader.new(writer, options)
local colon = P(":")
local semicolon = P(";")
local exclamation = P("!")
+ local tilde = P("~")
local digit = R("09")
local hexdigit = R("09","af","AF")
local letter = R("AZ","az")
local alphanumeric = R("AZ","az","09")
local keyword = letter * alphanumeric^0
+ local punctuation = S("!?,.:;")
local doubleasterisks = P("**")
local doubleunderscores = P("__")
@@ -483,7 +499,8 @@ function M.reader.new(writer, options)
local fail = any - 1
local always = P("")
- local escapable = S("\\`*_{}[]()+_.!<>#-~:^")
+ local escapable = S("\\`*_{}[]()+_.!<>#-~:^@;")
+
local anyescaped = P("\\") / "" * escapable
+ any
@@ -494,17 +511,14 @@ function M.reader.new(writer, options)
local nonspacechar = any - spacing
local tightblocksep = P("\001")
- local specialchar
- if options.smartEllipses then
- specialchar = S("*_`&[]<!\\.")
- else
- specialchar = S("*_`&[]<!\\")
- end
+ local specialchar = S("*_`&[]<!\\.@-")
local normalchar = any -
(specialchar + spacing + tightblocksep)
local optionalspace = spacechar^0
- local spaces = spacechar^1
+ local optionalspaceor = function(pattern)
+ return (spacechar + pattern)^0
+ end
local eof = - any
local nonindentspace = space^-3 * - spacechar
local indent = space^-3 * tab
@@ -518,6 +532,10 @@ function M.reader.new(writer, options)
local optionallyindentedline = indent^-1 /"" * C(linechar^1 * newline^-1)
local sp = spacing^0
local spnl = optionalspace * (newline * optionalspace)^-1
+ local spnlor = function(pattern)
+ local optional = optionalspaceor(pattern)
+ return optional * (newline * optional)^-1
+ end
local line = linechar^0 * newline
+ linechar^1 * eof
local nonemptyline = line - blankline
@@ -529,7 +547,7 @@ function M.reader.new(writer, options)
local function indented_blocks(bl)
return Cs( bl
* (blankline^1 * indent * -blankline * bl)^0
- * blankline^1 )
+ * (blankline^1 + eof) )
end
local bulletchar = C(plus + asterisk + dash)
@@ -565,7 +583,36 @@ function M.reader.new(writer, options)
+ (space - closeticks)
+ (backtick^1 - closeticks)
- local inticks = openticks * space^-1 * C(intickschar^1) * closeticks
+ local inticks = openticks * space^-1 * C(intickschar^0) * closeticks
+ local function captures_geq_length(s,i,a,b)
+ return #a >= #b and i
+ end
+
+ local infostring = (linechar - (backtick + space^1 * (newline + eof)))^0
+
+ local fenceindent
+ local function fencehead(char)
+ return C(nonindentspace) / function(s) fenceindent = #s end
+ * Cg(char^3, "fencelength")
+ * optionalspace * C(infostring) * optionalspace
+ * (newline + eof)
+ end
+
+ local function fencetail(char)
+ return nonindentspace
+ * Cmt(C(char^3) * Cb("fencelength"),
+ captures_geq_length)
+ * optionalspace * (newline + eof)
+ + eof
+ end
+
+ local function fencedline(char)
+ return C(line - fencetail(char))
+ / function(s)
+ return s:gsub("^" .. string.rep(" ?",
+ fenceindent), "")
+ end
+ end
local leader = space^-3
-- in balanced brackets, parentheses, quotes:
@@ -616,6 +663,38 @@ function M.reader.new(writer, options)
local optionaltitle = spnl * title * spacechar^0
+ Cc("")
+ local citation_name = (Cs(dash^-1)
+ * at * Cs((anyescaped
+ - (rbracket + spacing + punctuation + semicolon))^1))
+
+ local citation_body_prenote
+ = Cs((alphanumeric^1
+ + bracketed
+ + inticks
+ + (anyescaped
+ - (rbracket + semicolon + blankline^2))
+ - (spnl * dash^-1 * at))^0)
+
+ local citation_body_postnote
+ = Cs((alphanumeric^1
+ + bracketed
+ + inticks
+ + (anyescaped
+ - (rbracket + semicolon + blankline^2))
+ - (spnl * rbracket))^0)
+
+ local citation_body_chunk
+ = citation_body_prenote
+ * spnl * citation_name
+ * spnlor(punctuation - (semicolon + rbracket))
+ * citation_body_postnote
+
+ local citation_body = citation_body_chunk
+ * (semicolon * spnl * citation_body_chunk)^0
+
+ local citation_headless_body
+ = citation_body_postnote
+ * (sp * semicolon * spnl * citation_body_chunk)^0
local rawnotes = {}
local function strip_first_char(s)
@@ -627,7 +706,7 @@ function M.reader.new(writer, options)
return function()
local found = rawnotes[normalize_tag(ref)]
if found then
- return writer.note(parse_blocks(found))
+ return writer.note(parse_blocks_toplevel(found))
else
return {"[", parse_inlines("^" .. ref), "]"}
end
@@ -713,21 +792,10 @@ function M.reader.new(writer, options)
end
end
end
- local Inline = V("Inline")
-
- local Str = normalchar^1 / writer.string
-
- local Ellipsis = P("...") / writer.ellipsis
-
- local Smart = Ellipsis
-
- local Symbol = (specialchar - tightblocksep) / writer.string
-
- local Code = inticks / writer.code
-
local bqstart = more
local headerstart = hash
+ (line * (equal^1 + dash^1) * optionalspace * newline)
+ local fencestart = fencehead(backtick) + fencehead(tilde)
if options.blankBeforeBlockquote then
bqstart = fail
@@ -737,24 +805,41 @@ function M.reader.new(writer, options)
headerstart = fail
end
+ if not options.fencedCode or options.blankBeforeCodeFence then
+ fencestart = fail
+ end
+ local Inline = V("Inline")
+
+ local Str = normalchar^1 / writer.string
+
+ local Symbol = (specialchar - tightblocksep) / writer.string
+ local Ellipsis = P("...") / writer.ellipsis
+
+ local Smart = Ellipsis
+ local Code = inticks / writer.code
local Endline = newline * -( -- newline, but not before...
blankline -- paragraph break
+ tightblocksep -- nested list
+ eof -- end of document
+ bqstart
+ headerstart
+ + fencestart
) * spacechar^0 / writer.space
local Space = spacechar^2 * Endline / writer.linebreak
+ spacechar^1 * Endline^-1 * eof / ""
+ spacechar^1 * Endline^-1 * optionalspace / writer.space
+ local NonbreakingSpace
+ = spacechar^2 * Endline / writer.linebreak
+ + spacechar^1 * Endline^-1 * eof / ""
+ + spacechar^1 * Endline^-1 * optionalspace / writer.nbsp
+
-- parse many p between starter and ender
local function between(p, starter, ender)
local ender2 = B(nonspacechar) * ender
return (starter * #nonspacechar * Ct(p * (p - ender2)^0) * ender2)
end
-
local Strong = ( between(Inline, doubleasterisks, doubleasterisks)
+ between(Inline, doubleunderscores, doubleunderscores)
) / writer.strong
@@ -762,7 +847,6 @@ function M.reader.new(writer, options)
local Emph = ( between(Inline, asterisk, asterisk)
+ between(Inline, underscore, underscore)
) / writer.emphasis
-
local urlchar = anyescaped - newline - more
local AutoLinkUrl = less
@@ -792,7 +876,6 @@ function M.reader.new(writer, options)
-- parse a link or image (direct or indirect)
local Link = DirectLink + IndirectLink
-
local DirectImage = exclamation
* (tag / parse_inlines)
* spnl
@@ -806,43 +889,89 @@ function M.reader.new(writer, options)
indirect_image
local Image = DirectImage + IndirectImage
-
-- avoid parsing long strings of * or _ as emph/strong
local UlOrStarLine = asterisk^4 + underscore^4 / writer.string
local EscapedChar = S("\\") * C(escapable) / writer.string
+ local function citations(text_cites, raw_cites)
+ local function normalize(str)
+ if str == "" then
+ str = nil
+ else
+ str = (options.citationNbsps and parse_inlines_nbsp or
+ parse_inlines)(str)
+ end
+ return str
+ end
+
+ local cites = {}
+ for i = 1,#raw_cites,4 do
+ cites[#cites+1] = {
+ prenote = normalize(raw_cites[i]),
+ suppress_author = raw_cites[i+1] == "-",
+ name = writer.string(raw_cites[i+2]),
+ postnote = normalize(raw_cites[i+3]),
+ }
+ end
+ return writer.citations(text_cites, cites)
+ end
+
+ local TextCitations = Ct(Cc("")
+ * citation_name
+ * ((spnl
+ * lbracket
+ * citation_headless_body
+ * rbracket) + Cc(""))) /
+ function(raw_cites)
+ return citations(true, raw_cites)
+ end
+
+ local ParenthesizedCitations
+ = Ct(lbracket
+ * citation_body
+ * rbracket) /
+ function(raw_cites)
+ return citations(false, raw_cites)
+ end
+
+ local Citations = TextCitations + ParenthesizedCitations
local Block = V("Block")
local Verbatim = Cs( (blanklines
* ((indentedline - blankline))^1)^1
) / expandtabs / writer.verbatim
+ local TildeFencedCode
+ = fencehead(tilde)
+ * Cs(fencedline(tilde)^0)
+ * fencetail(tilde)
+
+ local BacktickFencedCode
+ = fencehead(backtick)
+ * Cs(fencedline(backtick)^0)
+ * fencetail(backtick)
+
+ local FencedCode = (TildeFencedCode + BacktickFencedCode)
+ / function(infostring, code)
+ return writer.fencedCode(
+ writer.string(infostring),
+ expandtabs(code))
+ end
-- strip off leading > and indents, and run through blocks
local Blockquote = Cs((
((leader * more * space^-1)/"" * linechar^0 * newline)^1
* (-blankline * linechar^1 * newline)^0
- * blankline^0
- )^1) / parse_blocks / writer.blockquote
+ * (blankline^0 / "")
+ )^1) / parse_blocks_toplevel / writer.blockquote
local function lineof(c)
- return (leader * (P(c) * optionalspace)^3 * newline * blankline^1)
+ return (leader * (P(c) * optionalspace)^3 * (newline * blankline^1
+ + newline^-1 * eof))
end
-
local HorizontalRule = ( lineof(asterisk)
+ lineof(dash)
+ lineof(underscore)
) / writer.hrule
-
- local Reference = define_reference_parser / register_link
-
- local Paragraph = nonindentspace * Ct(Inline^1) * newline
- * ( blankline^1
- + #hash
- + #(leader * more * space^-1)
- )
- / writer.paragraph
-
- local Plain = nonindentspace * Ct(Inline^1) / writer.plain
local starter = bullet + enumerator
-- we use \001 as a separator between a tight list item and a
@@ -913,7 +1042,7 @@ function M.reader.new(writer, options)
local DefinitionListItemLoose = C(line) * skipblanklines
* Ct((defstart *
indented_blocks(dlchunk) /
- parse_blocks)^1)
+ parse_blocks_toplevel)^1)
* Cc(false)
/ definition_list_item
@@ -928,10 +1057,29 @@ function M.reader.new(writer, options)
* (skipblanklines *
-DefinitionListItemLoose * Cc(true))
) / writer.definitionlist
+ local Reference = define_reference_parser / register_link
local Blank = blankline / ""
+ NoteBlock
+ Reference
+ (tightblocksep / "\n")
+ local Paragraph = nonindentspace * Ct(Inline^1) * newline
+ * ( blankline^1
+ + #hash
+ + #(leader * more * space^-1)
+ )
+ / writer.paragraph
+
+ local ToplevelParagraph
+ = nonindentspace * Ct(Inline^1) * (newline
+ * ( blankline^1
+ + #hash
+ + #(leader * more * space^-1)
+ + eof
+ )
+ + eof )
+ / writer.paragraph
+
+ local Plain = nonindentspace * Ct(Inline^1) / writer.plain
-- parse Atx heading start and return level
local HeadingStart = #hash * C(hash^-6) * -hash / length
@@ -955,6 +1103,8 @@ function M.reader.new(writer, options)
* HeadingLevel
* optionalspace * newline
/ writer.heading
+
+ local Heading = AtxHeading + SetextHeading
syntax =
{ "Blocks",
@@ -970,6 +1120,7 @@ function M.reader.new(writer, options)
Block = V("Blockquote")
+ V("Verbatim")
+ + V("FencedCode")
+ V("HorizontalRule")
+ V("BulletList")
+ V("OrderedList")
@@ -980,10 +1131,11 @@ function M.reader.new(writer, options)
Blockquote = Blockquote,
Verbatim = Verbatim,
+ FencedCode = FencedCode,
HorizontalRule = HorizontalRule,
BulletList = BulletList,
OrderedList = OrderedList,
- Heading = AtxHeading + SetextHeading,
+ Heading = Heading,
DefinitionList = DefinitionList,
DisplayHtml = DisplayHtml,
Paragraph = Paragraph,
@@ -996,6 +1148,7 @@ function M.reader.new(writer, options)
+ V("Strong")
+ V("Emph")
+ V("NoteRef")
+ + V("Citations")
+ V("Link")
+ V("Image")
+ V("Code")
@@ -1012,6 +1165,7 @@ function M.reader.new(writer, options)
Strong = Strong,
Emph = Emph,
NoteRef = NoteRef,
+ Citations = Citations,
Link = Link,
Image = Image,
Code = Code,
@@ -1028,6 +1182,14 @@ function M.reader.new(writer, options)
syntax.DefinitionList = fail
end
+ if not options.fencedCode then
+ syntax.FencedCode = fail
+ end
+
+ if not options.citations then
+ syntax.Citations = fail
+ end
+
if not options.footnotes then
syntax.NoteRef = fail
end
@@ -1036,6 +1198,10 @@ function M.reader.new(writer, options)
syntax.Smart = fail
end
+ local blocks_toplevel_t = util.table_copy(syntax)
+ blocks_toplevel_t.Paragraph = ToplevelParagraph
+ blocks_toplevel = Ct(blocks_toplevel_t)
+
blocks = Ct(syntax)
local inlines_t = util.table_copy(syntax)
@@ -1043,9 +1209,13 @@ function M.reader.new(writer, options)
inlines_t.Inlines = Inline^0 * (spacing^0 * eof / "")
inlines = Ct(inlines_t)
- inlines_no_link_t = util.table_copy(inlines_t)
+ local inlines_no_link_t = util.table_copy(inlines_t)
inlines_no_link_t.Link = fail
inlines_no_link = Ct(inlines_no_link_t)
+
+ local inlines_nbsp_t = util.table_copy(inlines_t)
+ inlines_nbsp_t.Space = NonbreakingSpace
+ inlines_nbsp = Ct(inlines_nbsp_t)
function self.convert(input)
references = {}
local opt_string = {}
@@ -1056,9 +1226,9 @@ function M.reader.new(writer, options)
end
end
table.sort(opt_string)
- local salt = table.concat(opt_string, ",")
+ local salt = table.concat(opt_string, ",") .. "," .. metadata.version
local name = util.cache(options.cacheDir, input, salt, function(input)
- return util.rope_to_string(parse_blocks(input)) .. writer.eof
+ return util.rope_to_string(parse_blocks_toplevel(input)) .. writer.eof
end, ".md" .. writer.suffix)
return writer.pack(name)
end