关于这个玩具项目 huntzhan/zhlint,之前在已经在 V2EX 发过两个帖子了,前情提要:
这个项目已经断断续续做了一个月了,从之前的 Demo ,到现在的粗糙成品,整个开发过程感触良多,发个贴分享一下。
之前看到 DaoCloud 的写作规范和格式规范,突然觉得来了灵感,类比之前用过的 cpplint/flake8
等工具,既然中文文档的书写也有风格的定义,那必定是可以通过搞一个自动化工具来检测、修复文档风格的错误嘛!
于是我撸起袖子简单计划了一下,觉得这个东西应该不算难,主要需要解决两个的问题就可以了:
解析 Markdown 语法似乎简单,但深入之后有会遇到问题:
经过一番调研,发现市面上的 Markdown Parser 都不能直接拿来用,无奈之下只能找一个看的顺眼的项目来 Hack 了。最终我选择的是 lepture/mistune,主要的原因是这个项目足够小,才一千行左右,改起来应该可以很快搞定。
然而,事实上搞起来是挺痛苦的。一方面的原因,是 mistune
的解析行为主要由其定义的 regex 决定, regex 读起来相当痛苦,通过一边猜一边用 Debuggex 解析 regex 的方式,用了大概一天才把整个逻辑搞懂;另一个方面的原因是 mistune
在设计的时候并不 care 解析出来的 Markdown Element 的位置信息,为了得到这些信息我必须做一些奇奇怪怪的 Hack ,主要的耗时也在这一步。最终使用继承 mistune
基类的方式自己搞了个 Markdown Parser 出来。
「 Parser 的部分搞定了,之后应该就是一帆风顺了吧,毕竟 Parser 的 Hack 应该是最脏的部分了。」这是我测完 Parser 的想法,现在看来还是太天真了。与检测、修复文档风格的逻辑相比, Parser 的部分「脏的程度」简直不值一提。
为了检测文档风格错误,需要考虑:
第一点还好,我仔细分析了 DaoCloud 的写作规范,提取了十余条可以自动化判断的规则,见支持的检查项目。然而,这些规则还是比较模糊的,当时没有仔细的思考每一条规则的边界条件,导致后续花费了很多时间在修 bug 上面。
对于第二点,我打算用 regex 来搞,每一条规则定义出一些错误的 case ,然后用一组 regex 来命中这些 case 。
"Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems." from Jamie Zawinski
不说了,都是泪,各种边界条件搞不清楚,每次遇到新的无法处理的 case 只能手动把这个 case 泛化之后加进规则里,然后祈祷这条规则不会与其他规则冲突。而且 regex 里各种奇奇怪怪的用法也把我虐得半死,什么 non-capturing 、 look-ahead 、 look-behind 、 catastrophic backtracking ,非常可怕!
就拿 E201 ,只有中文或中英文混排中,一律使用中文全角标点 这条规则为例。
触发 E201 的、有风格错误的样例有:
有中文, 错误.
中文'测试'
中文"测试"
LaTeX 公式 $$.
LaTeX 公式,$$
LaTeX 公式 \(\).
LaTeX 公式,\(\)
正常的样例有:
有中文,正确。
有中文,正确......
P.S. 这是一行中文。
LaTeX 公式 $$
LaTeX 公式 \(\)
邮箱: programmer.zhx@gmail.com
有中文, 1.0
有中文, www.google.com
链接地址 http://google.com
要用 regex 来表达出这种差异,还是挺蛋疼的。
万幸的是,这些坑我基本上都解决了。然而,通过这种类似「撞大运编程」搞出来的规则,我自己也不知道前面会有多少的坑,所以我在标题里讲 zhlint 是一个「粗糙的」中文 Markdown 文档风格检查器。反正 dog food 了一段时间之后感觉还是稳定的,已经能满足我自用的需求了,有什么问题以后慢慢再修。
之后就是自动修复的功能了,这个其实还是比较简单的,直接跑一个 LCS 得到原始文本与 parsed 后文本的映射关系,然后把在 parsed 后文本的修改操作映射回原始 Markdown 文本即可。虽然这部分涉及的算法应该是最多的,但并没有花多少时间。
总体的感想:
P.S. 本文已经过 zhlint 的风格检测。
P.S. 有没有工程师愿意帮我搞 online demo 呀?zhlint-web 这个 demo 太丑了,而我又没点多少前端技能。
P.S. 求靠谱内推。(其实这个项目是在面 DaoCloud 的过程中搞的,由于某些原因没有继续面下去)
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.