如何编写Pandoc过滤器实现按元数据变量条件渲染内容?
解决Pandoc条件渲染解答区块的过滤器问题
问题场景
我需要编写包含课堂习题的Markdown文档,通过元数据里的render-solution变量(取值yes/no)控制是否显示.conditional-render区块中的解答内容,但自己写的Python过滤器完全不生效——不管变量设成什么,解答区块都无法正常渲染。
我的示例Markdown:
--- title: My Document render-solution: yes --- ## Task 1 A difficult problem ::: { .conditional-render } ## Solution 1 Here is the solution :::
尝试的过滤器代码:
#!/usr/bin/env python from pandocfilters import toJSONFilter, Str, Para, Div def conditional_render(key, value, format, meta): if key == 'Div': [[ident, classes, kvs], content] = value if 'conditional-render' in classes: if meta['render-solution']['c'] == "yes": return Div([ident, classes, kvs], content) else: return [] if __name__ == "__main__": toJSONFilter(conditional_render)
问题分析
原过滤器存在两个核心问题:
- 元数据读取逻辑不健壮:Pandoc的元数据中字符串类型字段的结构是
{"t": "MetaString", "c": "值"},直接访问meta['render-solution']['c']会在字段未定义或类型不符时抛出异常,导致过滤器逻辑直接中断。 - 返回值处理有误:当需要保留区块时,返回原Div对象的写法不符合Pandoc过滤器规范——正确做法是返回区块内容或调整后的Div结构;且原代码判断逻辑容易因元数据读取失败跳过处理,导致默认行为不符合预期。
修复后的过滤器代码
#!/usr/bin/env python from pandocfilters import toJSONFilter, Div def conditional_render(key, value, format, meta): # 仅处理Div类型元素 if key != 'Div': return None ident, classes, kvs = value[0] content = value[1] # 检查是否是目标条件渲染区块 if 'conditional-render' not in classes: return None # 安全读取元数据,默认设为不显示解答 render_solution = meta.get('render-solution', {}).get('c', 'no').lower() # 根据配置决定保留或删除区块 if render_solution == 'yes': return Div([ident, classes, kvs], content) else: return [] if __name__ == "__main__": toJSONFilter(conditional_render)
使用说明
- 将修复后的代码保存为
conditional-render.py,赋予执行权限:chmod +x conditional-render.py - 执行Pandoc转换时指定过滤器:
# 转换为PDF pandoc input.md -o output.pdf --filter ./conditional-render.py # 转换为HTML pandoc input.md -o output.html --filter ./conditional-render.py - 修改Markdown元数据中的
render-solution: yes或no,即可控制解答区块的显示/隐藏。
内容的提问来源于stack exchange,提问作者Rafael Mayoral
相关产品推荐
相关产品推荐

