
文章目录
-
- 引言
- [1. Pandoc 过滤器基础](#1. Pandoc 过滤器基础)
-
- [1.1 Pandoc 文档转换过程](#1.1 Pandoc 文档转换过程)
- [1.2 Lua 过滤器的工作原理](#1.2 Lua 过滤器的工作原理)
- [2. 编写针对图片的过滤器](#2. 编写针对图片的过滤器)
-
- [2.1 基本图片过滤器](#2.1 基本图片过滤器)
- [2.2 高级图片处理](#2.2 高级图片处理)
- [3. 编写针对表格的过滤器](#3. 编写针对表格的过滤器)
-
- [3.1 基本表格过滤器](#3.1 基本表格过滤器)
- [3.2 高级表格格式化](#3.2 高级表格格式化)
- [4. 综合过滤器示例](#4. 综合过滤器示例)
- [5. 使用过滤器的方法](#5. 使用过滤器的方法)
-
- [5.1 命令行使用](#5.1 命令行使用)
- [5.2 与Pandoc参考文档结合使用](#5.2 与Pandoc参考文档结合使用)
- [6. 实用技巧和注意事项](#6. 实用技巧和注意事项)
-
- [6.1 处理不同输出格式](#6.1 处理不同输出格式)
- [6.2 使用自定义属性](#6.2 使用自定义属性)
- [6.3 调试过滤器](#6.3 调试过滤器)
- [7. 总结](#7. 总结)
引言
在使用 Pandoc 将 Markdown 文档转换为 Word (.docx) 格式时,使用默认模板并不能将文档中的图片和表格转换为我们希望的格式。之前的文章《WPS宏使用:一键批量调整图片与表格格式》介绍了如何利用WPS中的宏功能,快速实现图片和表格格式的批量调整。在使用Pandoc将Markdown文档转换为word时,通过添加使用 Lua 过滤器,我们也可以相对精细地控制这些元素的样式。
本文将介绍如何使用Pandoc过滤器统一调整文档中的图片和表格样式。
1. Pandoc 过滤器基础
1.1 Pandoc 文档转换过程
理解 Pandoc 过滤器之前,需要了解 Pandoc 的文档转换过程:
- INPUT:源文件(如 Markdown)
- Reader:读取器将源文件解析为 Pandoc 的中间表示(AST,抽象语法树)
- AST:JSON 格式的抽象语法树,表示文档结构
- Filter:过滤器处理和修改 AST
- AST(2):经过过滤器处理后的抽象语法树
- Writer:写入器将 AST 转换为目标格式(如 DOCX)
- OUTPUT:目标文件
这个过程可以表示为:INPUT --reader--> AST --filter--> AST --writer--> OUTPUT
1.2 Lua 过滤器的工作原理
Lua 过滤器是通过 Pandoc 的 Lua 接口操作 AST 的脚本。当 Pandoc 处理文档时,它会遍历 AST,并在遇到特定类型的元素(如图片、表格)时调用相应的过滤器函数,根据函数的返回值修改 AST。
2. 编写针对图片的过滤器
2.1 基本图片过滤器
图片在 Pandoc 的 AST 中对应 Image 元素。一个简单的图片过滤器示例如下:
lua
function Image(img)
-- 设置图片宽度为页面宽度的80%
img.attributes.width = "80%"
-- 添加居中样式
img.attributes.style = "display: block; margin-left: auto; margin-right: auto;"
-- 确保图片有替代文本
if not img.caption or #img.caption == 0 then
img.caption = {pandoc.Str("图片")}
end
return img
end
2.2 高级图片处理
对于更复杂的需求,例如限制图片大小以防止恶意文档:
lua
local total_size_images = 0
local max_images_size = 10000000 -- 10MB,单位为字节
function Image(img)
-- 获取图片内容
local mimetype, contents = pandoc.mediabag.fetch(img.src)
-- 检查图片大小是否超出限制
total_size_images = total_size_images + #contents
if total_size_images > max_images_size then
error('图片总体积过大!')
end
-- 设置统一格式
img.attributes.width = "90%"
img.attributes.style = "display: block; margin: 1em auto; border: 1px solid #ddd; padding: 5px;"
return img
end
3. 编写针对表格的过滤器
3.1 基本表格过滤器
表格在 Pandoc AST 中对应 Table 元素。以下是一个表格格式调整的示例:
lua
function Table(table)
-- 添加表格边框和宽度
table.attributes.style = "width: 100%; border-collapse: collapse;"
-- 设置表格居中对齐
table.attributes.align = "center"
-- 为表格添加标题
if not table.caption or #table.caption == 0 then
table.caption = {pandoc.Str("表格")}
end
return table
end
3.2 高级表格格式化
对于更专业的表格格式要求:
lua
function Table(table)
-- 设置表格样式
table.attributes.style = "width: 95%; border: 1px solid black; border-collapse: collapse; margin: 1em auto;"
-- 处理表头
if table.head then
for i, row in ipairs(table.head.rows) do
for j, cell in ipairs(row.cells) do
cell.attributes.style = "background-color: #f2f2f2; font-weight: bold; padding: 8px; border: 1px solid black;"
end
end
end
-- 处理表格主体
if table.bodies then
for i, body in ipairs(table.bodies) do
for j, row in ipairs(body.body.rows) do
for k, cell in ipairs(row.cells) do
cell.attributes.style = "padding: 8px; border: 1px solid black;"
end
end
end
end
return table
end
4. 综合过滤器示例
以下是一个同时处理图片和表格的完整过滤器示例:
lua
-- 统一格式设置
local image_style = {
width = "85%",
style = "display: block; margin: 1.5em auto; border: 1px solid #ccc; box-shadow: 2px 2px 5px rgba(0,0,0,0.1);"
}
local table_style = {
width = "95%",
style = "border-collapse: collapse; margin: 1.5em auto; font-size: 0.9em;"
}
-- 图片处理
function Image(img)
for attr, value in pairs(image_style) do
img.attributes[attr] = value
end
-- 确保图片有ID,便于交叉引用
if not img.identifier or img.identifier == "" then
img.identifier = "img-" .. os.time()
end
return img
end
-- 表格处理
function Table(tbl)
for attr, value in pairs(table_style) do
if not tbl.attributes then tbl.attributes = {} end
tbl.attributes[attr] = value
end
-- 设置表头样式
if tbl.head and tbl.head.rows and #tbl.head.rows > 0 then
for _, row in ipairs(tbl.head.rows) do
for _, cell in ipairs(row.cells) do
cell.attributes = cell.attributes or {}
cell.attributes.style = "background-color: #4CAF50; color: white; font-weight: bold; padding: 12px; text-align: left; border: 1px solid #ddd;"
end
end
end
-- 设置表格主体样式
if tbl.bodies and #tbl.bodies > 0 then
local body = tbl.bodies[1]
if body and body.body and body.body.rows then
for i, row in ipairs(body.body.rows) do
for _, cell in ipairs(row.cells) do
cell.attributes = cell.attributes or {}
cell.attributes.style = "padding: 10px; border: 1px solid #ddd;"
-- 交替行颜色
if i % 2 == 0 then
cell.attributes.style = cell.attributes.style .. " background-color: #f9f9f9;"
end
end
end
end
end
return tbl
end
5. 使用过滤器的方法
5.1 命令行使用
将上述 Lua 代码保存为 formatting.lua,然后使用以下命令应用过滤器:
bash
pandoc input.md -o output.docx --lua-filter=formatting.lua
5.2 与Pandoc参考文档结合使用
我们可以将 Lua 过滤器与 Pandoc 的其他功能结合使用:
bash
# 同时使用参考文档和过滤器
pandoc input.md -o output.docx --reference-doc=custom-template.docx --lua-filter=formatting.lua
# 使用多个过滤器
pandoc input.md -o output.docx --lua-filter=image-filter.lua --lua-filter=table-filter.lua
6. 实用技巧和注意事项
6.1 处理不同输出格式
如果你的文档需要转换为多种格式,可以在过滤器中根据目标格式调整行为:
lua
function Image(img)
if FORMAT == "docx" then
-- Word 特定的格式
img.attributes.width = "80%"
elseif FORMAT:match "html" then
-- HTML 特定的格式
img.attributes.style = "max-width: 80%; height: auto; display: block; margin: 1em auto;"
elseif FORMAT:match "latex" then
-- LaTeX 特定的格式
-- 可能需要返回 RawBlock 包含 LaTeX 代码
end
return img
end
6.2 使用自定义属性
在 Markdown 中为图片和表格添加自定义属性,然后在过滤器中根据这些属性进行处理:
markdown
```{#my-table .custom-style}
| 列1 | 列2 |
|-----|-----|
| 数据 | 数据 |
```
在过滤器中:
lua
function Table(tbl)
if tbl.classes:find("custom-style") then
-- 应用自定义样式
tbl.attributes.style = "width: 100%; border: 2px solid blue;"
end
return tbl
end
6.3 调试过滤器
编写过滤器时可能会遇到问题,可以使用以下方法调试:
lua
function Image(img)
-- 打印图片信息
io.stderr:write("处理图片: " .. img.src .. "\n")
-- 使用 pandoc.utils 调试
local img_json = pandoc.write(pandoc.Pandoc({img}), "json")
io.stderr:write("图片 AST: " .. img_json .. "\n")
return img
end
7. 总结
通过使用 Lua 过滤器,我们可以更好的控制 Markdown 转换时生成word文档中的图片和表格的样式。关键要点包括:
- 理解 AST:掌握 Pandoc 的抽象语法树结构是编写有效过滤器的关键。
- 针对性处理:为不同类型的元素(Image、Table)编写专门的处理函数。
- 属性控制 :通过修改元素的
attributes字段控制格式。 - 灵活应用:根据输出格式和元素特性灵活调整处理逻辑。