一个改善 Markdown to Org 转换的 Pandoc Filter 脚本

使用 pandoc.markdown 转换为 .org 时,经常会遇到这种行内的 Code 两边的 = 因为缺少必要的空白的,导致格式错误的问题,如图中的 =FRUIT_COUNT==HashMap=

可以使用这个过滤脚本把行内 Code 的 = 的两边强制加上一个空格来解决这个问题,效果如下:

脚本:

#!/usr/bin/env python3

from pandocfilters import toJSONFilter, Plain, Para, BlockQuote, DefinitionList
import re

constructors_map = {
    'Plain': Plain,
    'Para': Para,
    'BlockQuote': BlockQuote,
    'DefinitionList': DefinitionList,
}


# 1. insert a white space before and after the `Code` element in a paragraph
# 2. insert zero-width space before and after quotes characters if they are at boundaries of a Code element
def code(key, value, format, meta):
    if key in constructors_map and isinstance(value, list):
        new_elemets = []
        elments = value
        for element in elments:
            if isinstance(element, dict) and element['t'] in ['Code', 'Strong', 'Emph']:
                new_elemets.append({'t': 'Space'})
                if len(element['c']) > 1:
                    element['c'][1] = re.sub(r'^"', r'​"', element['c'][1])
                    element['c'][1] = re.sub(r'"$', r'"​', element['c'][1])
                    element['c'][1] = re.sub(r"^'", r"​'", element['c'][1])
                    element['c'][1] = re.sub(r"'$", r"'​", element['c'][1])
                new_elemets.append(element)
                new_elemets.append({'t': 'Space'})
            else:
                new_elemets.append(element)
        return constructors_map[key](new_elemets)
    else:
        return None


if __name__ == "__main__":
    toJSONFilter(code)

需要安装 pandocfilter 这个包:

pip install [--user] [-U] [--break-system-packages] pandocfilters

使用方法:

pandoc --filter=pandoc-org-filter.py -t markdown -f input.md -t org -o output.org

另外,如果 = 边界处的字符是 ' / " 时,也会导致格式丢失,脚本对这种情况是在 ' / " 旁边加了个 ZERO WIDTH SPACE (0x200b) 字符,来解决这个问题

如果将转换后的 org 文本/文件用 Emacs 打开之后,用 org-fill-xxx 来重新整理行宽度的话,如果 = 处于一行的结尾或者开头,在 org-fill-xxx 之后仍然会出现丢失的问题,解决方法是:

  1. --wrap=none 让 pandoc 不要折行,然后自己在 Emacs 中通过 org-fill-xxx 来设置行宽: pandoc --filter=pandoc-org-filter.py -t markdown -f input.md -t org -o output.org --wrap=none

  2. --columns=NUM 让 pandoc 按指定的宽度折行: pandoc --filter=pandoc-org-filter.py -t markdown -f input.md -t org -o output.org --columns=120

5 个赞