diff --git a/markdown.dtx b/markdown.dtx index 47b3a482d..54423b63a 100644 --- a/markdown.dtx +++ b/markdown.dtx @@ -14388,7 +14388,9 @@ following text: % \end{macrocode} % \begin{markdown} % The macro is exposed in the interface, so that the user can create their own -% markdown environments. +% markdown environments. Due to the way the arguments are passed to Lua (see +% Section <#sec:directlua>), the first argument may not contain the +% string `]]` (regardless of the category code of the bracket symbol (`]`)). % % The \mdef{markdownMode} macro specifies how the plain \TeX{} implementation % interfaces with the Lua interface. The valid values and their meaning are @@ -21892,10 +21894,245 @@ end % \par % \begin{markdown} % +% The following two sections of the implementation have been deprecated and +% will be removed in Markdown 3.0.0. The code that corresponds to +% \mref{markdownMode} value of `4` will be the one and only implementation. +% +% \end{markdown} +% \begin{macrocode} +\ifnum\markdownMode=4\relax +\markdownInfo{Using mode 4: The lt3luabridge package}% +\input lt3luabridge\relax +\def\markdownLuaExecute{\luabridgeExecute}% +\else +% \end{macrocode} +% \begin{markdown} +% +%### Lua Shell Escape Bridge {#luabridge} +% +% The following \TeX{} code is intended for \TeX{} engines that do not provide +% direct access to Lua, but expose the shell of the operating system. This +% corresponds to the \mref{markdownMode} values of `0` and `1`. +% +% The \mref{markdownLuaExecute} macro defined here and in Section +% <#sec:directlua> are meant to be indistinguishable to the remaining code. +% +% The package assumes that although the user is not using the Lua\TeX{} engine, +% their \TeX{} distribution contains it, and uses shell access to produce and +% execute Lua scripts using the \TeX{}Lua interpreter~[@luatex17, Section +% 3.1.1]. +% +\ifnum\markdownMode<2\relax +\ifnum\markdownMode=0\relax + \markdownWarning{Using mode 0: Shell escape via write18 + (deprecated, to be removed in Markdown 3.0.0)}% +\else + \markdownWarning{Using mode 1: Shell escape via os.execute + (deprecated, to be removed in Markdown 3.0.0)}% +\fi +% \end{macrocode} +% \par +% \begin{markdown} +% +% The \mdef{markdownExecuteShellEscape} macro contains the numeric value indicating +% whether the shell access is enabled (`1`), disabled (`0`), or restricted +% (`2`). +% +% Inherit the value of the the \mref{pdfshellescape} (Lua\TeX{}, \Hologo{pdfTeX}) +% or the \mref{shellescape} (\Hologo{XeTeX}) commands. If neither of these +% commands is defined and Lua is available, attempt to access the +% \luamref{status.shell_escape} configuration item. +% +% If you cannot detect, whether the shell access is enabled, act as if it were. +% +% \end{markdown} +% \begin{macrocode} +\ifx\pdfshellescape\undefined + \ifx\shellescape\undefined + \ifnum\markdownMode=0\relax + \def\markdownExecuteShellEscape{1}% + \else + \def\markdownExecuteShellEscape{% + \directlua{tex.sprint(status.shell_escape or "1")}}% + \fi + \else + \let\markdownExecuteShellEscape\shellescape + \fi +\else + \let\markdownExecuteShellEscape\pdfshellescape +\fi +% \end{macrocode} +% \par +% \begin{markdown} +% +% The \mdef{markdownExecuteDirect} macro executes the code it has received as +% its first argument by writing it to the output file stream 18, if Lua is +% unavailable, or by using the Lua \luamref{os.execute} method otherwise. +% +% \end{markdown} +% \begin{macrocode} +\ifnum\markdownMode=0\relax + \def\markdownExecuteDirect#1{\immediate\write18{#1}}% +\else + \def\markdownExecuteDirect#1{% + \directlua{os.execute("\luaescapestring{#1}")}}% +\fi +% \end{macrocode} +% \par +% \begin{markdown} +% +% The \mdef{markdownExecute} macro is a wrapper on top of +% \mref{markdownExecuteDirect} that checks the value of +% \mref{markdownExecuteShellEscape} and prints an error message if the shell is +% inaccessible. +% +% \end{markdown} +% \begin{macrocode} +\def\markdownExecute#1{% + \ifnum\markdownExecuteShellEscape=1\relax + \markdownExecuteDirect{#1}% + \else + \markdownError{I can not access the shell}{Either run the TeX + compiler with the --shell-escape or the --enable-write18 flag, + or set shell_escape=t in the texmf.cnf file}% + \fi}% +% \end{macrocode} +% \par +% \begin{markdown} +% +% The \mdef{markdownLuaExecute} macro executes the Lua code it has received as +% its first argument. The Lua code may not directly interact with the \TeX{} +% engine, but it can use the \luamref{print} function in the same manner it +% would use the \luamref{tex.print} method. +% +% \end{markdown} +% \begin{macrocode} +\begingroup +% \end{macrocode} +% \begin{markdown} +% Swap the category code of the backslash symbol and the pipe symbol, so that +% we may use the backslash symbol freely inside the Lua code. +% \end{markdown} +% \begin{macrocode} + \catcode`|=0% + \catcode`\\=12% + |gdef|markdownLuaExecute#1{% +% \end{macrocode} +% \begin{markdown} +% Create the file \mref{markdownOptionHelperScriptFileName} and fill it with the +% input Lua code prepended with \pkg{kpathsea} initialization, so that Lua +% modules from the \TeX{} distribution are available. +% \end{markdown} +% \begin{macrocode} + |immediate|openout|markdownOutputFileStream=% + |markdownOptionHelperScriptFileName + |markdownInfo{Writing a helper Lua script to the file + "|markdownOptionHelperScriptFileName"}% + |immediate|write|markdownOutputFileStream{% + local ran_ok, error = pcall(function() + local ran_ok, kpse = pcall(require, "kpse") + if ran_ok then kpse.set_program_name("luatex") end + #1 + end) +% \end{macrocode} +% \begin{markdown} +% If there was an error, use the file \mref{markdownOptionErrorTempFileName} to +% store the error message. +% \end{markdown} +% \begin{macrocode} + if not ran_ok then + local file = io.open("% + |markdownOptionOutputDir + /|markdownOptionErrorTempFileName", "w") + if file then + file:write(error .. "\n") + file:close() + end + print('\\markdownError{An error was encountered while executing + Lua code}{For further clues, examine the file + "|markdownOptionOutputDir + /|markdownOptionErrorTempFileName"}') + end}% + |immediate|closeout|markdownOutputFileStream +% \end{macrocode} +% \begin{markdown} +% Execute the generated \mref{markdownOptionHelperScriptFileName} Lua script using +% the \TeX{}Lua binary and store the output in the +% \mref{markdownOptionOutputTempFileName} file. +% \end{markdown} +% \begin{macrocode} + |markdownInfo{Executing a helper Lua script from the file + "|markdownOptionHelperScriptFileName" and storing the result in the + file "|markdownOptionOutputTempFileName"}% + |markdownExecute{texlua "|markdownOptionOutputDir + /|markdownOptionHelperScriptFileName" > % + "|markdownOptionOutputDir + /|markdownOptionOutputTempFileName"}% +% \end{macrocode} +% \begin{markdown} +% \mref{input} the generated \mref{markdownOptionOutputTempFileName} file. +% \end{markdown} +% \begin{macrocode} + |input|markdownOptionOutputTempFileName|relax}% +|endgroup +% \end{macrocode} +% \par +% \begin{markdown} +% +%### Direct Lua Access {#directlua} +% +% The following \TeX{} code is intended for \TeX{} engines that provide +% direct access to Lua (Lua\TeX{}). The macro \mref{markdownLuaExecute} defined +% here and in Section <#sec:luabridge> are meant to be indistinguishable to +% the remaining code. This corresponds to the \mref{markdownMode} value of `2`. +% +% \end{markdown} +% \begin{macrocode} +\else + \markdownWarning{Using mode 2: Direct Lua access + (deprecated, to be removed in Markdown 3.0.0)}% +% \end{macrocode} +% \par +% \begin{markdown} +% +% The direct Lua access version of the \mref{markdownLuaExecute} macro is defined +% in terms of the \mref{directlua} primitive. The \luamref{print} function is set as +% an alias to the \luamref{tex.print} method in order to mimic the behaviour of the +% \mref{markdownLuaExecute} definition from Section <#sec:luabridge>, +% +% \end{markdown} +% \begin{macrocode} +\begingroup +% \end{macrocode} +% \begin{markdown} +% Swap the category code of the backslash symbol and the pipe symbol, so that +% we may use the backslash symbol freely inside the Lua code. +% \end{markdown} +% \begin{macrocode} + \catcode`|=0% + \catcode`\\=12% + |gdef|markdownLuaExecute#1{% + |directlua{% + local function print(input) + local output = {} + for line in input:gmatch("[^\r\n]+") do + table.insert(output, line) + end + tex.print(output) + end + #1 + }% + }% +|endgroup +\fi\fi +% \end{macrocode} +% \par +% \begin{markdown} +% %### Typesetting Markdown % -% The \mref{markdownInput} macro uses the \mref{luabridgeExecute} macro from -% the \pkg{l3luabridge} package to convert the contents of the file whose +% The \mref{markdownInput} macro uses an implementation of the +% \mref{markdownLuaExecute} macro to convert the contents of the file whose % filename it has received as its single argument from markdown to plain % \TeX{}. % @@ -21949,7 +22186,7 @@ end |openin|markdownInputFileStream#1 |closein|markdownInputFileStream |markdownPrepareLuaOptions - |luabridgeExecute{% + |markdownLuaExecute{% |markdownPrepare local file = assert(io.open("#1", "r"), [[could not open file "#1" for reading]])