Proof of concept
The following code implements a "proof of concept" showing that the approach (1) I proposed in another answer is feasible.
This example defines a Markdown
environment which dumps its contents verbatim to an auxiliar file (called \jobname-aux.md
), and inmediatelly uses Lua to parse that file as markdown. For this parsing it uses the library markdown.lua
, which currently can only output HTML.
The result of the parsing is split into lines, and each line fed again to TeX via tex.print
function. Currently those contents are inserted in a verbatim
environment, because they are HTML.
MWE
\documentclass{article}
\usepackage[margin=2cm]{geometry}
\usepackage{fancyvrb}
\usepackage{fontspec}
\setmonofont{Consolas}\fontspec{Consolas}
\usepackage{markdown}
\title{Proof of concept}
\author{JL Diaz}
\begin{document}
\maketitle
\begin{Markdown}
# Idea
This is a _proof of concept_ about the posibility of using
a [markdown][1] parser
embedded in LuaTex.
## How it works
The contents of a `markdown` environment are written verbatim
in an auxiliar file, which is later processed by Lua (using
[`markdown.lua`][2] code,
and the result inserted back in TeX.
# Status
Currently `markdown.lua` only can generate HTML output, so
the result is inserted back in a `Verbatim` environment into
the TeX document. When proper LaTeX output would be available
the `Verbatim` will be removed.
[1]: http://daringfireball.net/projects/markdown/
[2]: http://luaforge.net/projects/markdown
\end{Markdown}
\end{document}
After compiling it with lualatex
the resulting pdf shows the HTML translation made by Lua in a verbatim environment:

Setup
In order to reproduce this result, you will need the following files:
compat_env.lua
Download it from its source
markdown.lua
Download it from its source, making some changes for Lua 5.2 compatibility:
- Add this line near the top of the file
local CE = require 'compat_env'
- modify all occurances of
setfenv
to CE.setfenv
- change all occurances of
unpack
to table.unpack
markdownify.lua
These are its contents:
function splitIntoLines(str)
local t = {}
local function helper(line) table.insert(t, line) return "" end
helper((str:gsub("(.-)\r?\n", helper)))
return t
end
function markdownify(f)
file=io.open(f)
s = file:read("*all")
file:close()
s = markdown(s)
t = splitIntoLines(s)
tex.print("\\par")
tex.print("\\begin{verbatim}")
tex.print(t)
tex.print("\\end{verbatim}")
end
markdown.sty
These are its contents:
\RequirePackage{luatexbase}
\directlua{dofile("markdown.lua")}
\directlua{dofile("markdownify.lua")}
\makeatletter
\def\Markdown{\FV@Environment{}{Markdown}}
\def\FVB@Markdown{%
\@bsphack
\begingroup
\FV@UseKeyValues
\FV@DefineWhiteSpace
\def\FV@Space{\space}%
\FV@DefineTabOut
\def\FV@ProcessLine{\immediate\write\FV@OutFile}%
\immediate\openout\FV@OutFile \jobname-aux.md\relax
\let\FV@FontScanPrep\relax
\let\@noligs\relax
\FV@Scan}
\def\FVE@Markdown{\immediate\closeout\FV@OutFile\endgroup\@esphack\markdownify}
\DefineVerbatimEnvironment{Markdown}{Markdown}{}
\makeatother
\def\markdownify{\directlua{markdownify("\jobname-aux.md")}}
Update
I coded a new version of the .lua
and .sty
files which does not create any auxiliar file, but instead process all "in memory". Thanks to mbork which pointed me to this answer which shows a technique to record the contents of an environment, and have those contents in a string when the environment ends.
I adapted that answer to this problem. The tricky part was avoiding that the environment contents were seen by tex. In the referred answer, in addition to record the contents they are still part of the document, but we want to avoid this in this case. However, if I delete those contents while I'm recording them (so that TeX cannot see them), then TeX won't be see the \end{Markdown}
either and all will fail. So I had to hardcode that particular line.
These are the new files which implement this solution:
markdownify.lua
local mybuf = ""
function readbuf( buf )
if buf:find("\\end{Markdown}") == nil then
mybuf = mybuf .. buf .. "\n"
return ""
else
return nil
end
end
function startrecording()
luatexbase.add_to_callback('process_input_buffer', readbuf, 'readbuf')
end
function stoprecording()
luatexbase.remove_from_callback('process_input_buffer', 'readbuf')
markdownify(mybuf)
end
function splitIntoLines(str)
local t = {}
local function helper(line) table.insert(t, line) return "" end
helper((str:gsub("(.-)\r?\n", helper)))
return t
end
function markdownify(s)
s = markdown(s)
t = splitIntoLines(s)
tex.print("\\par")
tex.print("\\begin{verbatim}")
tex.print(t)
tex.print("\\end{verbatim}")
end
markdown.sty
(Much simpler now!)
\directlua{dofile("markdown.lua")}
\directlua{dofile("markdownify.lua")}
\newenvironment{Markdown}{\directlua{startrecording()}}{\directlua{stoprecording()}}
The MWE can compile without changes, but fancyvrb
is not longer required (I used it to dump the contents of the environment to an auxiliar file).
markdown
, put the latex code inside and run the file throughpandoc
. As the last, finishing step, you may tweakpandoc
s latex-output and compile it withlatex
, if you are not able to get the preferred output directly frompandoc
. – Sveinung Mar 10 '13 at 9:40