texlive[41950] Master/texmf-dist: markdown (29aug16)

commits+karl at tug.org commits+karl at tug.org
Mon Aug 29 23:19:56 CEST 2016


Revision: 41950
          http://tug.org/svn/texlive?view=revision&revision=41950
Author:   karl
Date:     2016-08-29 23:19:56 +0200 (Mon, 29 Aug 2016)
Log Message:
-----------
markdown (29aug16)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/generic/markdown/markdown.pdf
    trunk/Master/texmf-dist/source/generic/markdown/markdown.dtx
    trunk/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex
    trunk/Master/texmf-dist/tex/generic/markdown/markdown.tex
    trunk/Master/texmf-dist/tex/latex/markdown/markdown.sty
    trunk/Master/texmf-dist/tex/luatex/markdown/markdown.lua

Modified: trunk/Master/texmf-dist/doc/generic/markdown/markdown.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/generic/markdown/markdown.dtx
===================================================================
--- trunk/Master/texmf-dist/source/generic/markdown/markdown.dtx	2016-08-29 21:19:42 UTC (rev 41949)
+++ trunk/Master/texmf-dist/source/generic/markdown/markdown.dtx	2016-08-29 21:19:56 UTC (rev 41950)
@@ -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 @@
 %<*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 @@
 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.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 [- at 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 - at 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.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 @@
 % \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 @@
 %
 % 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 @@
 % 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 @@
 % 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 @@
   \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 @@
 %    \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 @@
   \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 @@
   \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 @@
   \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 @@
   \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 @@
 % 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 @@
 \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 @@
 % \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 @@
   \def\markdownOptionOutputTempFileName{#1}}%
 \define at key{markdownOptions}{blankBeforeBlockquote}[true]{%
   \def\markdownOptionBlankBeforeBlockquote{#1}}%
+\define at key{markdownOptions}{blankBeforeCodeFence}[true]{%
+  \def\markdownOptionBlankBeforeCodeFence{#1}}%
 \define at key{markdownOptions}{blankBeforeHeading}[true]{%
   \def\markdownOptionBlankBeforeHeading{#1}}%
+\define at key{markdownOptions}{citations}[true]{%
+  \def\markdownOptionCitations{#1}}%
+\define at key{markdownOptions}{citationNbsps}[true]{%
+  \def\markdownOptionCitationNbsps{#1}}%
 \define at key{markdownOptions}{cacheDir}{%
   \def\markdownOptionCacheDir{#1}}%
 \define at key{markdownOptions}{definitionLists}[true]{%
   \def\markdownOptionDefinitionLists{#1}}%
+\define at key{markdownOptions}{footnotes}[true]{%
+  \def\markdownOptionFootnotes{#1}}%
+\define at key{markdownOptions}{fencedCode}[true]{%
+  \def\markdownOptionFencedCode{#1}}%
 \define at key{markdownOptions}{hashEnumerators}[true]{%
   \def\markdownOptionHashEnumerators{#1}}%
 \define at key{markdownOptions}{hybrid}[true]{%
   \def\markdownOptionHybrid{#1}}%
-\define at key{markdownOptions}{footnotes}[true]{%
-  \def\markdownOptionFootnotes{#1}}%
 \define at key{markdownOptions}{preserveTabs}[true]{%
   \def\markdownOptionPreserveTabs{#1}}%
 \define at key{markdownOptions}{smartEllipses}[true]{%
@@ -1278,7 +1448,7 @@
 % 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 at key{markdownOptions}{tightLists}[true]{%
@@ -1296,18 +1466,20 @@
 % }
 % \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 at key{markdownOptions}{renderers}{%
-  \setkeys{markdownRenderers}{#1}}%
+\define at key{markdownRenderers}{interblockSeparator}{%
+  \renewcommand\markdownRendererInterblockSeparator{#1}}%
 \define at key{markdownRenderers}{lineBreak}{%
   \renewcommand\markdownRendererLineBreak{#1}}%
 \define at key{markdownRenderers}{ellipsis}{%
   \renewcommand\markdownRendererEllipsis{#1}}%
+\define at key{markdownRenderers}{nbsp}{%
+  \renewcommand\markdownRendererNbsp{#1}}%
 \define at key{markdownRenderers}{leftBrace}{%
   \renewcommand\markdownRendererLeftBrace{#1}}%
 \define at key{markdownRenderers}{rightBrace}{%
@@ -1342,6 +1514,8 @@
   \renewcommand\markdownRendererUlBeginTight{#1}}%
 \define at key{markdownRenderers}{ulItem}{%
   \renewcommand\markdownRendererUlItem{#1}}%
+\define at key{markdownRenderers}{ulItemEnd}{%
+  \renewcommand\markdownRendererUlItemEnd{#1}}%
 \define at key{markdownRenderers}{ulEnd}{%
   \renewcommand\markdownRendererUlEnd{#1}}%
 \define at key{markdownRenderers}{ulEndTight}{%
@@ -1354,6 +1528,8 @@
   \renewcommand\markdownRendererOlItem{#1}}%
 \define at key{markdownRenderers}{olItemWithNumber}{%
   \renewcommand\markdownRendererOlItemWithNumber[1]{#1}}%
+\define at key{markdownRenderers}{olItemEnd}{%
+  \renewcommand\markdownRendererOlItemEnd{#1}}%
 \define at key{markdownRenderers}{olEnd}{%
   \renewcommand\markdownRendererOlEnd{#1}}%
 \define at key{markdownRenderers}{olEndTight}{%
@@ -1364,6 +1540,8 @@
   \renewcommand\markdownRendererDlBeginTight{#1}}%
 \define at key{markdownRenderers}{dlItem}{%
   \renewcommand\markdownRendererDlItem[1]{#1}}%
+\define at key{markdownRenderers}{dlItemEnd}{%
+  \renewcommand\markdownRendererDlItemEnd{#1}}%
 \define at key{markdownRenderers}{dlDefinitionBegin}{%
   \renewcommand\markdownRendererDlDefinitionBegin{#1}}%
 \define at key{markdownRenderers}{dlDefinitionEnd}{%
@@ -1382,6 +1560,8 @@
   \renewcommand\markdownRendererBlockQuoteEnd{#1}}%
 \define at key{markdownRenderers}{inputVerbatim}{%
   \renewcommand\markdownRendererInputVerbatim[1]{#1}}%
+\define at key{markdownRenderers}{inputFencedCode}{%
+  \renewcommand\markdownRendererInputFencedCode[2]{#1}}%
 \define at key{markdownRenderers}{headingOne}{%
   \renewcommand\markdownRendererHeadingOne[1]{#1}}%
 \define at key{markdownRenderers}{headingTwo}{%
@@ -1398,6 +1578,10 @@
   \renewcommand\markdownRendererHorizontalRule{#1}}%
 \define at key{markdownRenderers}{footnote}{%
   \renewcommand\markdownRendererFootnote[1]{#1}}%
+\define at key{markdownRenderers}{cite}{%
+  \renewcommand\markdownRendererCite[1]{#1}}%
+\define at key{markdownRenderers}{textCite}{%
+  \renewcommand\markdownRendererTextCite[1]{#1}}%
 %    \end{macrocode}
 %
 % The following example \LaTeX{} code showcases a possible configuration of the
@@ -1413,17 +1597,20 @@
 % \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 at key{markdownOptions}{rendererPrototypes}{%
-  \setkeys{markdownRendererPrototypes}{#1}}%
+\define at key{markdownRendererPrototypes}{interblockSeparator}{%
+  \renewcommand\markdownRendererInterblockSeparatorPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{lineBreak}{%
   \renewcommand\markdownRendererLineBreakPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ellipsis}{%
   \renewcommand\markdownRendererEllipsisPrototype{#1}}%
+\define at key{markdownRendererPrototypes}{nbsp}{%
+  \renewcommand\markdownRendererNbspPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{leftBrace}{%
   \renewcommand\markdownRendererLeftBracePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{rightBrace}{%
@@ -1445,13 +1632,13 @@
 \define at key{markdownRendererPrototypes}{tilde}{%
   \renewcommand\markdownRendererTildePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{pipe}{%
-  \renewcommand\markdownRendererPipe{#1}}%
+  \renewcommand\markdownRendererPipePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{codeSpan}{%
   \renewcommand\markdownRendererCodeSpanPrototype[1]{#1}}%
 \define at key{markdownRendererPrototypes}{link}{%
-  \renewcommand\markdownRendererLink[4]{#1}}%
+  \renewcommand\markdownRendererLinkPrototype[4]{#1}}%
 \define at key{markdownRendererPrototypes}{image}{%
-  \renewcommand\markdownRendererImage[4]{#1}}%
+  \renewcommand\markdownRendererImagePrototype[4]{#1}}%
 \define at key{markdownRendererPrototypes}{ulBegin}{%
   \renewcommand\markdownRendererUlBeginPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulBeginTight}{%
@@ -1458,6 +1645,8 @@
   \renewcommand\markdownRendererUlBeginTightPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulItem}{%
   \renewcommand\markdownRendererUlItemPrototype{#1}}%
+\define at key{markdownRendererPrototypes}{ulItemEnd}{%
+  \renewcommand\markdownRendererUlItemEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulEnd}{%
   \renewcommand\markdownRendererUlEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulEndTight}{%
@@ -1470,6 +1659,8 @@
   \renewcommand\markdownRendererOlItemPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{olItemWithNumber}{%
   \renewcommand\markdownRendererOlItemWithNumberPrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{olItemEnd}{%
+  \renewcommand\markdownRendererOlItemEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{olEnd}{%
   \renewcommand\markdownRendererOlEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{olEndTight}{%
@@ -1480,6 +1671,8 @@
   \renewcommand\markdownRendererDlBeginTightPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{dlItem}{%
   \renewcommand\markdownRendererDlItemPrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{dlItemEnd}{%
+  \renewcommand\markdownRendererDlItemEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{dlDefinitionBegin}{%
   \renewcommand\markdownRendererDlDefinitionBeginPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{dlDefinitionEnd}{%
@@ -1498,6 +1691,8 @@
   \renewcommand\markdownRendererBlockQuoteEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{inputVerbatim}{%
   \renewcommand\markdownRendererInputVerbatimPrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{inputFencedCode}{%
+  \renewcommand\markdownRendererInputFencedCodePrototype[2]{#1}}%
 \define at key{markdownRendererPrototypes}{headingOne}{%
   \renewcommand\markdownRendererHeadingOnePrototype[1]{#1}}%
 \define at key{markdownRendererPrototypes}{headingTwo}{%
@@ -1514,6 +1709,10 @@
   \renewcommand\markdownRendererHorizontalRulePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{footnote}{%
   \renewcommand\markdownRendererFootnotePrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{cite}{%
+  \renewcommand\markdownRendererCitePrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{textCite}{%
+  \renewcommand\markdownRendererTextCitePrototype[1]{#1}}%
 %    \end{macrocode}
 %
 % The following example \LaTeX{} code showcases a possible configuration of the
@@ -1521,7 +1720,7 @@
 % markdown token renderer prototypes.
 % \begin{Verbatim}
 % \markdownSetup{
-%   renderers = {
+%   rendererPrototypes = {
 %     image = {\includegraphics{#2}},
 %     codeSpan = {\texttt{#1}},    % Render inline code via `\texttt`.
 %   }
@@ -1885,6 +2084,12 @@
   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,15 +2118,9 @@
 % Define \luamdef{writer->interblocksep} as the output format of a block
 % element separator.
 %  \begin{macrocode}
-  self.interblocksep = "\n\n"
+  self.interblocksep = "\\markdownRendererInterblockSeparator\n{}"
 %    \end{macrocode}
 %
-% Define \luamdef{writer->containersep} as the output format of a container
-% separator.
-%  \begin{macrocode}
-  self.containersep = "\n\n"
-%    \end{macrocode}
-%
 % Define \luamdef{writer->eof} as the end of file marker in the output format.
 %  \begin{macrocode}
   self.eof = [[\relax]]
@@ -1929,7 +2128,7 @@
 %
 % 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 @@
 %
 % 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 @@
 % 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 @@
 %  \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 @@
       retVal[#retVal+1] = {"\\markdownRendererDlDefinitionBegin ",def,
                            "\\markdownRendererDlDefinitionEnd "}
     end
+    retVal[#retVal+1] = "\\markdownRendererDlItemEnd "
     return retVal
   end
 
@@ -2104,13 +2307,12 @@
     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 @@
   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 @@
   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 @@
 % \paragraph{Top Level Parsing Functions}
 %  \begin{macrocode}
   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)))
+        error(format("%s failed on:\n%s", name, 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)))
-      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)))
-      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,6 +2539,7 @@
   local colon                  = P(":")
   local semicolon              = P(";")
   local exclamation            = P("!")
+  local tilde                  = P("~")
 
   local digit                  = R("09")
   local hexdigit               = R("09","af","AF")
@@ -2316,6 +2546,7 @@
   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 @@
   local fail                   = any - 1
   local always                 = P("")
 
-  local escapable              = S("\\`*_{}[]()+_.!<>#-~:^")
+  local escapable              = S("\\`*_{}[]()+_.!<>#-~:^@;")
+
   local anyescaped             = P("\\") / "" * escapable
                                + any
 
@@ -2336,17 +2568,14 @@
   local nonspacechar           = any - spacing
   local tightblocksep          = P("\001")
 
-  local specialchar
-  if options.smartEllipses then
-    specialchar                = S("*_`&[]<!\\.")
-  else
-    specialchar                = S("*_`&[]<!\\")
-  end
+  local specialchar            = S("*_`&[]<!\\. at -")
 
   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 @@
   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 @@
   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 @@
                     + (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 @@
   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 @@
     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 @@
     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,6 +2885,30 @@
     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
@@ -2603,24 +2915,26 @@
                       + 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 @@
   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 @@
 
   -- 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 @@
                          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 @@
   local DefinitionListItemLoose = C(line) * skipblanklines
                            * Ct((defstart *
                                  indented_blocks(dlchunk) /
-                                 parse_blocks)^1)
+                                 parse_blocks_toplevel)^1)
                            * Cc(false)
                            / definition_list_item
 
@@ -2801,15 +3177,37 @@
                                 -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 @@
                      * HeadingLevel
                      * optionalspace * newline
                      / writer.heading
+
+  local Heading = AtxHeading + SetextHeading
 %    \end{macrocode}
 % \paragraph{Top Level \acro{peg} Specification}
 %  \begin{macrocode}
@@ -2851,6 +3251,7 @@
 
       Block                 = V("Blockquote")
                             + V("Verbatim")
+                            + V("FencedCode")
                             + V("HorizontalRule")
                             + V("BulletList")
                             + V("OrderedList")
@@ -2861,10 +3262,11 @@
 
       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 @@
                             + V("Strong")
                             + V("Emph")
                             + V("NoteRef")
+                            + V("Citations")
                             + V("Link")
                             + V("Image")
                             + V("Code")
@@ -2893,6 +3296,7 @@
       Strong                = Strong,
       Emph                  = Emph,
       NoteRef               = NoteRef,
+      Citations             = Citations,
       Link                  = Link,
       Image                 = Image,
       Code                  = Code,
@@ -2909,6 +3313,14 @@
     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 @@
     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 @@
   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 @@
     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 @@
       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 @@
   \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 @@
 \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,6 +3491,9 @@
 \ifx\markdownOptionBlankBeforeBlockquote\undefined\else
   blankBeforeBlockquote = \markdownOptionBlankBeforeBlockquote,
 \fi
+\ifx\markdownOptionBlankBeforeCodeFence\undefined\else
+  blankBeforeCodeFence = \markdownOptionBlankBeforeCodeFence,
+\fi
 \ifx\markdownOptionBlankBeforeHeading\undefined\else
   blankBeforeHeading = \markdownOptionBlankBeforeHeading,
 \fi
@@ -3067,9 +3500,21 @@
 \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
@@ -3076,9 +3521,6 @@
 \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 @@
 % 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 @@
 %  \begin{macrocode}
         |def^^M{%
           |markdownInfo{The ending token sequence was found}%
-          |immediate|write|markdownLuaExecuteFileStream{}%
           |immediate|closeout|markdownLuaExecuteFileStream%
           |endgroup%
           |markdownInput|markdownOptionInputTempFileName%
@@ -3421,8 +3860,8 @@
 % 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 @@
     |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 @@
   \expandafter\markdownSetup\expandafter{\CurrentOption}}%
 \ProcessOptions\relax
 %    \end{macrocode}
+% After processing the options, activate the \t`renderers` and
+% \t`rendererPrototypes` keys.
+%  \begin{macrocode}
+\define at key{markdownOptions}{renderers}{%
+  \setkeys{markdownRenderers}{#1}%
+  \def\KV at prefix{KV at markdownOptions@}}%
+\define at key{markdownOptions}{rendererPrototypes}{%
+  \setkeys{markdownRendererPrototypes}{#1}%
+  \def\KV at prefix{KV at markdownOptions@}}%
+%    \end{macrocode}
 %
+% \subsubsection{Token Renderer Prototypes}
 % The following configuration should be considered placeholder.
 %  \begin{macrocode}
 \RequirePackage{url}
@@ -3610,27 +4060,103 @@
   blockQuoteBegin = {\begin{quotation}},
   blockQuoteEnd = {\end{quotation}},
   inputVerbatim = {\VerbatimInput{#1}},
+  inputFencedCode = {%
+    \ifx\relax#2\relax
+      \VerbatimInput{#1}%
+    \else
+      \ifx\minted at jobname\undefined
+        \ifx\lst at 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 @@
 % 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 @@
 % 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 @@
 |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 @@
 \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 @@
 \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 @@
   \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}
 %

Modified: trunk/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex
===================================================================
--- trunk/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex	2016-08-29 21:19:42 UTC (rev 41949)
+++ trunk/Master/texmf-dist/tex/context/third/markdown/t-markdown.tex	2016-08-29 21:19:56 UTC (rev 41950)
@@ -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
 %%

Modified: trunk/Master/texmf-dist/tex/generic/markdown/markdown.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/markdown/markdown.tex	2016-08-29 21:19:42 UTC (rev 41949)
+++ trunk/Master/texmf-dist/tex/generic/markdown/markdown.tex	2016-08-29 21:19:56 UTC (rev 41950)
@@ -45,8 +45,8 @@
 %% 
 %% 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
@@ -53,21 +53,29 @@
 \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,45 +278,55 @@
 \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
@@ -293,9 +333,21 @@
 \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
@@ -302,9 +354,6 @@
 \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 @@
   \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 @@
       |else%
         |def^^M{%
           |markdownInfo{The ending token sequence was found}%
-          |immediate|write|markdownLuaExecuteFileStream{}%
           |immediate|closeout|markdownLuaExecuteFileStream%
           |endgroup%
           |markdownInput|markdownOptionInputTempFileName%
@@ -443,8 +491,8 @@
           "([%(%)%.%%%+%-%*%?%[%]%^%$])", "%%%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 @@
     |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

Modified: trunk/Master/texmf-dist/tex/latex/markdown/markdown.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/markdown/markdown.sty	2016-08-29 21:19:42 UTC (rev 41949)
+++ trunk/Master/texmf-dist/tex/latex/markdown/markdown.sty	2016-08-29 21:19:56 UTC (rev 41950)
@@ -59,18 +59,26 @@
   \def\markdownOptionOutputTempFileName{#1}}%
 \define at key{markdownOptions}{blankBeforeBlockquote}[true]{%
   \def\markdownOptionBlankBeforeBlockquote{#1}}%
+\define at key{markdownOptions}{blankBeforeCodeFence}[true]{%
+  \def\markdownOptionBlankBeforeCodeFence{#1}}%
 \define at key{markdownOptions}{blankBeforeHeading}[true]{%
   \def\markdownOptionBlankBeforeHeading{#1}}%
+\define at key{markdownOptions}{citations}[true]{%
+  \def\markdownOptionCitations{#1}}%
+\define at key{markdownOptions}{citationNbsps}[true]{%
+  \def\markdownOptionCitationNbsps{#1}}%
 \define at key{markdownOptions}{cacheDir}{%
   \def\markdownOptionCacheDir{#1}}%
 \define at key{markdownOptions}{definitionLists}[true]{%
   \def\markdownOptionDefinitionLists{#1}}%
+\define at key{markdownOptions}{footnotes}[true]{%
+  \def\markdownOptionFootnotes{#1}}%
+\define at key{markdownOptions}{fencedCode}[true]{%
+  \def\markdownOptionFencedCode{#1}}%
 \define at key{markdownOptions}{hashEnumerators}[true]{%
   \def\markdownOptionHashEnumerators{#1}}%
 \define at key{markdownOptions}{hybrid}[true]{%
   \def\markdownOptionHybrid{#1}}%
-\define at key{markdownOptions}{footnotes}[true]{%
-  \def\markdownOptionFootnotes{#1}}%
 \define at key{markdownOptions}{preserveTabs}[true]{%
   \def\markdownOptionPreserveTabs{#1}}%
 \define at key{markdownOptions}{smartEllipses}[true]{%
@@ -79,12 +87,14 @@
   \def\markdownOptionStartNumber{#1}}%
 \define at key{markdownOptions}{tightLists}[true]{%
   \def\markdownOptionTightLists{#1}}%
-\define at key{markdownOptions}{renderers}{%
-  \setkeys{markdownRenderers}{#1}}%
+\define at key{markdownRenderers}{interblockSeparator}{%
+  \renewcommand\markdownRendererInterblockSeparator{#1}}%
 \define at key{markdownRenderers}{lineBreak}{%
   \renewcommand\markdownRendererLineBreak{#1}}%
 \define at key{markdownRenderers}{ellipsis}{%
   \renewcommand\markdownRendererEllipsis{#1}}%
+\define at key{markdownRenderers}{nbsp}{%
+  \renewcommand\markdownRendererNbsp{#1}}%
 \define at key{markdownRenderers}{leftBrace}{%
   \renewcommand\markdownRendererLeftBrace{#1}}%
 \define at key{markdownRenderers}{rightBrace}{%
@@ -119,6 +129,8 @@
   \renewcommand\markdownRendererUlBeginTight{#1}}%
 \define at key{markdownRenderers}{ulItem}{%
   \renewcommand\markdownRendererUlItem{#1}}%
+\define at key{markdownRenderers}{ulItemEnd}{%
+  \renewcommand\markdownRendererUlItemEnd{#1}}%
 \define at key{markdownRenderers}{ulEnd}{%
   \renewcommand\markdownRendererUlEnd{#1}}%
 \define at key{markdownRenderers}{ulEndTight}{%
@@ -131,6 +143,8 @@
   \renewcommand\markdownRendererOlItem{#1}}%
 \define at key{markdownRenderers}{olItemWithNumber}{%
   \renewcommand\markdownRendererOlItemWithNumber[1]{#1}}%
+\define at key{markdownRenderers}{olItemEnd}{%
+  \renewcommand\markdownRendererOlItemEnd{#1}}%
 \define at key{markdownRenderers}{olEnd}{%
   \renewcommand\markdownRendererOlEnd{#1}}%
 \define at key{markdownRenderers}{olEndTight}{%
@@ -141,6 +155,8 @@
   \renewcommand\markdownRendererDlBeginTight{#1}}%
 \define at key{markdownRenderers}{dlItem}{%
   \renewcommand\markdownRendererDlItem[1]{#1}}%
+\define at key{markdownRenderers}{dlItemEnd}{%
+  \renewcommand\markdownRendererDlItemEnd{#1}}%
 \define at key{markdownRenderers}{dlDefinitionBegin}{%
   \renewcommand\markdownRendererDlDefinitionBegin{#1}}%
 \define at key{markdownRenderers}{dlDefinitionEnd}{%
@@ -159,6 +175,8 @@
   \renewcommand\markdownRendererBlockQuoteEnd{#1}}%
 \define at key{markdownRenderers}{inputVerbatim}{%
   \renewcommand\markdownRendererInputVerbatim[1]{#1}}%
+\define at key{markdownRenderers}{inputFencedCode}{%
+  \renewcommand\markdownRendererInputFencedCode[2]{#1}}%
 \define at key{markdownRenderers}{headingOne}{%
   \renewcommand\markdownRendererHeadingOne[1]{#1}}%
 \define at key{markdownRenderers}{headingTwo}{%
@@ -175,12 +193,18 @@
   \renewcommand\markdownRendererHorizontalRule{#1}}%
 \define at key{markdownRenderers}{footnote}{%
   \renewcommand\markdownRendererFootnote[1]{#1}}%
-\define at key{markdownOptions}{rendererPrototypes}{%
-  \setkeys{markdownRendererPrototypes}{#1}}%
+\define at key{markdownRenderers}{cite}{%
+  \renewcommand\markdownRendererCite[1]{#1}}%
+\define at key{markdownRenderers}{textCite}{%
+  \renewcommand\markdownRendererTextCite[1]{#1}}%
+\define at key{markdownRendererPrototypes}{interblockSeparator}{%
+  \renewcommand\markdownRendererInterblockSeparatorPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{lineBreak}{%
   \renewcommand\markdownRendererLineBreakPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ellipsis}{%
   \renewcommand\markdownRendererEllipsisPrototype{#1}}%
+\define at key{markdownRendererPrototypes}{nbsp}{%
+  \renewcommand\markdownRendererNbspPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{leftBrace}{%
   \renewcommand\markdownRendererLeftBracePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{rightBrace}{%
@@ -202,13 +226,13 @@
 \define at key{markdownRendererPrototypes}{tilde}{%
   \renewcommand\markdownRendererTildePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{pipe}{%
-  \renewcommand\markdownRendererPipe{#1}}%
+  \renewcommand\markdownRendererPipePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{codeSpan}{%
   \renewcommand\markdownRendererCodeSpanPrototype[1]{#1}}%
 \define at key{markdownRendererPrototypes}{link}{%
-  \renewcommand\markdownRendererLink[4]{#1}}%
+  \renewcommand\markdownRendererLinkPrototype[4]{#1}}%
 \define at key{markdownRendererPrototypes}{image}{%
-  \renewcommand\markdownRendererImage[4]{#1}}%
+  \renewcommand\markdownRendererImagePrototype[4]{#1}}%
 \define at key{markdownRendererPrototypes}{ulBegin}{%
   \renewcommand\markdownRendererUlBeginPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulBeginTight}{%
@@ -215,6 +239,8 @@
   \renewcommand\markdownRendererUlBeginTightPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulItem}{%
   \renewcommand\markdownRendererUlItemPrototype{#1}}%
+\define at key{markdownRendererPrototypes}{ulItemEnd}{%
+  \renewcommand\markdownRendererUlItemEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulEnd}{%
   \renewcommand\markdownRendererUlEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{ulEndTight}{%
@@ -227,6 +253,8 @@
   \renewcommand\markdownRendererOlItemPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{olItemWithNumber}{%
   \renewcommand\markdownRendererOlItemWithNumberPrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{olItemEnd}{%
+  \renewcommand\markdownRendererOlItemEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{olEnd}{%
   \renewcommand\markdownRendererOlEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{olEndTight}{%
@@ -237,6 +265,8 @@
   \renewcommand\markdownRendererDlBeginTightPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{dlItem}{%
   \renewcommand\markdownRendererDlItemPrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{dlItemEnd}{%
+  \renewcommand\markdownRendererDlItemEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{dlDefinitionBegin}{%
   \renewcommand\markdownRendererDlDefinitionBeginPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{dlDefinitionEnd}{%
@@ -255,6 +285,8 @@
   \renewcommand\markdownRendererBlockQuoteEndPrototype{#1}}%
 \define at key{markdownRendererPrototypes}{inputVerbatim}{%
   \renewcommand\markdownRendererInputVerbatimPrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{inputFencedCode}{%
+  \renewcommand\markdownRendererInputFencedCodePrototype[2]{#1}}%
 \define at key{markdownRendererPrototypes}{headingOne}{%
   \renewcommand\markdownRendererHeadingOnePrototype[1]{#1}}%
 \define at key{markdownRendererPrototypes}{headingTwo}{%
@@ -271,6 +303,10 @@
   \renewcommand\markdownRendererHorizontalRulePrototype{#1}}%
 \define at key{markdownRendererPrototypes}{footnote}{%
   \renewcommand\markdownRendererFootnotePrototype[1]{#1}}%
+\define at key{markdownRendererPrototypes}{cite}{%
+  \renewcommand\markdownRendererCitePrototype[1]{#1}}%
+\define at 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 at key{markdownOptions}{renderers}{%
+  \setkeys{markdownRenderers}{#1}%
+  \def\KV at prefix{KV at markdownOptions@}}%
+\define at key{markdownOptions}{rendererPrototypes}{%
+  \setkeys{markdownRendererPrototypes}{#1}%
+  \def\KV at prefix{KV at 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 at jobname\undefined
+        \ifx\lst at 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

Modified: trunk/Master/texmf-dist/tex/luatex/markdown/markdown.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/markdown/markdown.lua	2016-08-29 21:19:42 UTC (rev 41949)
+++ trunk/Master/texmf-dist/tex/luatex/markdown/markdown.lua	2016-08-29 21:19:56 UTC (rev 41950)
@@ -57,13 +57,15 @@
 -- 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")
@@ -70,11 +72,15 @@
 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 @@
     return defaultOptions[key] end })
   self.suffix = ".tex"
   self.space = " "
+  self.nbsp = "\\markdownRendererNbsp{}"
   function self.plain(s)
     return s
   end
@@ -231,12 +238,11 @@
   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 @@
                            "{",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 @@
   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 @@
       retVal[#retVal+1] = {"\\markdownRendererDlDefinitionBegin ",def,
                            "\\markdownRendererDlDefinitionEnd "}
     end
+    retVal[#retVal+1] = "\\markdownRendererDlItemEnd "
     return retVal
   end
 
@@ -339,13 +349,12 @@
     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 @@
     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 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 @@
                  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)))
+        error(format("%s failed on:\n%s", name, str:sub(1,20)))
       else
         return res
       end
     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)))
-      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)))
-      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,6 +482,7 @@
   local colon                  = P(":")
   local semicolon              = P(";")
   local exclamation            = P("!")
+  local tilde                  = P("~")
 
   local digit                  = R("09")
   local hexdigit               = R("09","af","AF")
@@ -474,6 +489,7 @@
   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 @@
   local fail                   = any - 1
   local always                 = P("")
 
-  local escapable              = S("\\`*_{}[]()+_.!<>#-~:^")
+  local escapable              = S("\\`*_{}[]()+_.!<>#-~:^@;")
+
   local anyescaped             = P("\\") / "" * escapable
                                + any
 
@@ -494,17 +511,14 @@
   local nonspacechar           = any - spacing
   local tightblocksep          = P("\001")
 
-  local specialchar
-  if options.smartEllipses then
-    specialchar                = S("*_`&[]<!\\.")
-  else
-    specialchar                = S("*_`&[]<!\\")
-  end
+  local specialchar            = S("*_`&[]<!\\. at -")
 
   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 @@
   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 @@
   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 @@
                     + (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 @@
 
   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 @@
     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 @@
       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,6 +805,18 @@
     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
@@ -743,6 +823,7 @@
                       + eof       -- end of document
                       + bqstart
                       + headerstart
+                      + fencestart
                     ) * spacechar^0 / writer.space
 
   local Space     = spacechar^2 * Endline / writer.linebreak
@@ -749,12 +830,16 @@
                   + 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 @@
   local Emph   = ( between(Inline, asterisk, asterisk)
                  + between(Inline, underscore, underscore)
                  ) / writer.emphasis
-
   local urlchar = anyescaped - newline - more
 
   local AutoLinkUrl   = less
@@ -792,7 +876,6 @@
 
   -- parse a link or image (direct or indirect)
   local Link          = DirectLink + IndirectLink
-
   local DirectImage   = exclamation
                       * (tag / parse_inlines)
                       * spnl
@@ -806,11 +889,52 @@
                          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
@@ -817,32 +941,37 @@
                            * ((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 @@
   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 @@
                              * (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 @@
                      * HeadingLevel
                      * optionalspace * newline
                      / writer.heading
+
+  local Heading = AtxHeading + SetextHeading
   syntax =
     { "Blocks",
 
@@ -970,6 +1120,7 @@
 
       Block                 = V("Blockquote")
                             + V("Verbatim")
+                            + V("FencedCode")
                             + V("HorizontalRule")
                             + V("BulletList")
                             + V("OrderedList")
@@ -980,10 +1131,11 @@
 
       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 @@
                             + V("Strong")
                             + V("Emph")
                             + V("NoteRef")
+                            + V("Citations")
                             + V("Link")
                             + V("Image")
                             + V("Code")
@@ -1012,6 +1165,7 @@
       Strong                = Strong,
       Emph                  = Emph,
       NoteRef               = NoteRef,
+      Citations             = Citations,
       Link                  = Link,
       Image                 = Image,
       Code                  = Code,
@@ -1028,6 +1182,14 @@
     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 @@
     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 @@
   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 @@
       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



More information about the tex-live-commits mailing list