我想使用 markdown 分隔的 div 呈现一个两列的 pdf 文档。最简单的例子如下:
:::::::::::::: {.columns data-latex=""}
::: {.column width="40%" data-latex="[t]{0.4\textwidth}"}
contents...
:::
::: {.column width="60%" data-latex="[t]{0.6\textwidth}"}
contents...
:::
::::::::::::::
在 html 中渲染没问题,但显然有人认为 latex 中的多列渲染仅适用于 beamer,因此它不适用于纯 latex,也不适用于 pdf。我无法切换到 pandoc 的 html pdf 引擎,因为我的最终文档需要 latex 模板。
minipage latex 环境似乎非常方便实现我想要的功能。经过大量调查,我找到了这个 lua 过滤器:
local pandocList = require 'pandoc.List'
Div = function (div)
local options = div.attributes['data-latex']
if options == nil then return nil end
-- if the output format is not latex, the object is left unchanged
if FORMAT ~= 'latex' and FORMAT ~= 'beamer' then
div.attributes['data-latex'] = nil
return div
end
local env = div.classes[1]
-- if the div has no class, the object is left unchanged
if not env then return nil end
local returnedList
-- build the returned list of blocks
if env == 'column' then
local beginEnv = pandocList:new{pandoc.RawBlock('tex', '\\begin' .. '{' .. 'minipage' .. '}' .. options)}
local endEnv = pandocList:new{pandoc.RawBlock('tex', '\\end{' .. 'minipage' .. '}')}
returnedList = beginEnv .. div.content .. endEnv
end
return returnedList
end
不幸的是,生成的乳胶文档(pandoc --lua-filter ./latex-div.lua -o test.latex test.md
)如下,由于第一个小页面的结尾和第二个小页面的开头之间有空行,因此无法按预期呈现:
\begin{document}
\begin{minipage}[t]{0.4\textwidth}
contents\ldots{}
\end{minipage}
\begin{minipage}[t]{0.6\textwidth}
contents\ldots{}
\end{minipage}
\end{document}
我快到了。如何在不重新处理 latex 文件的情况下删除这个不需要的空白行?
答案1
经过进一步的调查和尝试,我终于能够回答我自己的问题了(希望它对某些人有用)。
由于嵌套的 div 在父 div 之前进行处理,因此可以重新处理它们以关闭小页面环境并在同一个 pandoc.RawBlock 中打开下一个环境(显然可以摆脱不需要的空白行)。
这是新的 lua 过滤器代码:
local pandocList = require 'pandoc.List'
Div = function (div)
local options = div.attributes['data-latex']
if options == nil then return nil end
-- if the output format is not latex, the object is left unchanged
if FORMAT ~= 'latex' and FORMAT ~= 'beamer' then
div.attributes['data-latex'] = nil
return div
end
local env = div.classes[1]
-- if the div has no class, the object is left unchanged
if not env then return nil end
local returnedList
-- build the returned list of blocks
if env == 'column' then
local beginEnv = pandocList:new{pandoc.RawBlock('tex', '\\begin' .. '{' .. 'minipage' .. '}' .. options)}
local endEnv = pandocList:new{pandoc.RawBlock('tex', '\\end{' .. 'minipage' .. '}')}
returnedList = beginEnv .. div.content .. endEnv
elseif env == 'columns' then
-- merge two consecutives RawBlocks (\end... and \begin...)
-- to get rid of the extra blank line
local blocks = div.content
local rbtxt = ''
for i = #blocks-1, 1, -1 do
if i > 1 and blocks[i].tag == 'RawBlock' and blocks[i].text:match 'end'
and blocks[i+1].tag == 'RawBlock' and blocks[i+1].text:match 'begin' then
rbtxt = blocks[i].text .. blocks[i+1].text
blocks:remove(i+1)
blocks[i].text = rbtxt
end
end
returnedList=blocks
end
return returnedList
end
生成的乳胶文档现在是正确的:
\begin{document}
\begin{minipage}[t]{0.4\textwidth}
contents\ldots{}
\end{minipage}\begin{minipage}[t]{0.6\textwidth}
contents\ldots{}
\end{minipage}
\end{document}
答案2
事实证明,有一个更简单的解决方案,即使用 Tex 来\mbox
使两个小页面粘在一起,尽管有空白行。
local pandocList = require 'pandoc.List'
Div = function (div)
local options = div.attributes['data-latex']
if options == nil then return nil end
-- if the output format is not latex, the object is left unchanged
if FORMAT ~= 'latex' and FORMAT ~= 'beamer' then
div.attributes['data-latex'] = nil
return div
end
local env = div.classes[1]
-- if the div has no class, the object is left unchanged
if not env then return nil end
local returnedList
-- build the returned list of blocks
if env == 'column' then
local beginEnv = pandocList:new{pandoc.RawBlock('tex', '\\begin' .. '{' .. 'minipage' .. '}' .. options)}
local endEnv = pandocList:new{pandoc.RawBlock('tex', '\\end{' .. 'minipage' .. '}')}
returnedList = beginEnv .. div.content .. endEnv
elseif env == 'columns' then
-- it turns-out that a simple Tex \mbox do the job
begin_env = List:new{pandoc.RawBlock('tex', '\\mbox{')}
end_env = List:new{pandoc.RawBlock('tex', '}')}
returned_list = begin_env .. div.content .. end_env
end
return returnedList
end
得到的乳胶代码是:
\begin{document}
\mbox{
\begin{minipage}[t]{0.4\textwidth}
contents\ldots{}
\end{minipage}\begin{minipage}[t]{0.6\textwidth}
contents\ldots{}
\end{minipage}
}
\end{document}
从那时起,我发布了一个更全面的过滤器git 存储库以及其他可能有用的过滤器。
答案3
介绍
根据我的评论,经过一番努力,我相信我成功地增加了一些整洁克里斯·阿加对他自己的问题的解决方案。
笔记:这个解决方案没有什么价值。它只是对作者最初努力的一次编辑,我仍然认为这是 ChrisAga 的杰作。
Lua 脚本
local pandocList = require 'pandoc.List'
Div = function (div)
local width = div.attributes['width']
local options = ""
if width ~= nil then
w = tonumber(width)
if w == nil then
width = string.gsub(width, '%%', '')
w = tonumber(width)
end
if w ~= nil then
if w >= 1 then w = w / 100 end
options = "[t]{" .. w .. "\\textwidth}"
end
end
if options == nil then return nil end
-- if the output format is not latex, the object is left unchanged
if FORMAT ~= 'latex' and FORMAT ~= 'beamer' then
div.attributes['data-latex'] = nil
return div
end
local env = div.classes[1]
-- if the div has no class, the object is left unchanged
if not env then return nil end
local returnedList
-- build the returned list of blocks
if env == 'column' then
local beginEnv = pandocList:new{pandoc.RawBlock('tex', '\\begin' .. '{' .. 'minipage' .. '}' .. options)}
local endEnv = pandocList:new{pandoc.RawBlock('tex', '\\end{' .. 'minipage' .. '}')}
returnedList = beginEnv .. div.content .. endEnv
elseif env == 'columns' then
-- merge two consecutives RawBlocks (\end... and \begin...)
-- to get rid of the extra blank line
local blocks = div.content
local rbtxt = ''
for i = #blocks-1, 1, -1 do
if i > 1 and blocks[i].tag == 'RawBlock' and blocks[i].text:match 'end'
and blocks[i+1].tag == 'RawBlock' and blocks[i+1].text:match 'begin' then
rbtxt = blocks[i].text .. blocks[i+1].text
blocks:remove(i+1)
blocks[i].text = rbtxt
end
end
returnedList=blocks
end
return returnedList
end
Markdown
有了这个脚本,Markdown现在可以简化成如下形式:
:::::::::::::: {.columns}
::: {.column width="40%"}
contents...
:::
::: {.column width="60%"}
contents...
:::
::::::::::::::
方法
我的目标是消除以下重复:
::: {.column width="40%" data-latex="[t]{0.4\textwidth}"}
其中我们说40%
和0.4
。这不仅复杂,而且还容易导致不一致。
options
我在这里所做的是从参数构建变量width
,而不是从参数中获取变量data-latex
。
该width
参数也可以用百分比、[1, 100] 比例或 [0, 1[ 比例来表示。该值1
毫无疑问地被视为[1, 100]
比例的一部分,因为否则它将相当于100%
宽度,这完全排除了对柱状环境的需求。