You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constreporter=(context,options={})=>{const{Syntax, RuleError, fixer, report, getSource}=context;return{[Syntax.Header](node){lettext=getSource(node);// Get textletmatch=/^.+(\s*\{#([a-z0-9\-_]+?)\}\s*)$/.exec(text);if(!match){constindex=text.lengthtext=text.replace(/#/g,'').trim().replace(specials,'').replace(emoji(),'').replace(whitespace,'-')text=hyphenate(text)text=` {#${text}}`constfix=fixer.insertTextAfter(node,text)construleError=newRuleError("Found bugs.",{
index,// padding of index
fix
});report(node,ruleError);}}}};
最近,有位细心的小伙伴在浏览文档时发现了锚点跳转异常的问题,这段时间我针对此问题着手进行了调研和解决。
先来描述下遇到的问题。
遇到的问题
打开 webpack 中文文档,随便找一篇文档介绍。比如直接访问概念 -> 入口,会发现页面空白。
具体异常如下:
从错误中可以很直观的看出,我们向
querySelector
中传入了一个 id 选择器,其值为#%E5%85%A5%E5%8F%A3entry
。由于 id 中不能使用
%
,所以报错,而出现%
的原因是浏览器针对链接进行了encode
操作,把「入口」转义成了%E5%85%A5%E5%8F%A3
。初步解决方案
既然知道了是浏览器对链接进行转义造成的,那么我们针对使用到
querySelector
的地方在传参前转义即可。在
webpack
文档的源码中查找querySelector
,最终在src/components/Page/Page.jsx
中找到了元凶。我们来优化下,防止浏览器转义中文字符:
如此修改后,发现浏览器能够跳转正常,问题得到了基本解决。
但是点击页面中的列表,又出现了新的问题。
新的问题
文中有大量引用链接,而锚点被改为了中文,链接无法识别也无法跳转。
有了新的问题,就要想新的解决方案。
和社区的小伙伴讨论了几种解决方案:
分别说下几种思路:
方案 1 的话,实现难度较高,并且对中英文文档要求较高,务必做到一一对应
方案 2 大量引用链接,逐个修改也会费时费力,并且无法做到傻瓜式修改。
最终,采用了方案 3 的方式,可以做到与原文档无任何差别,并且保证了跳转。最重要的是,方便修改。
具体方案就是如下,在标题后加入
{#锚点标题}
:以上为实际的输出效果。
如此修改又遇到了难题:
{#}
这种形式我们开始针对文档站点的部署以及构建进行查看,然后思考如何对解决这两个问题。
魔改源码
先解决 webpack 构建不能识别
{#}
的问题。翻看 webpack 文档的源码,你会发现 webpack 文档采用的是
remark
对 md 文件进行编译的,中间使用了大量的remark
相关的插件。在 webpack 文档站的
webpack.common.js
文件中有一个 mdPlugin 的属性:通过断点调试的方式,可以发现在经过
remark-slug
插件后,文档的标题,就被处理成 html 中对应的 title 和 id 了。因此,解决第一个问题的方式,就是将
remark-slug
魔改成,可以处理{#}
的插件。因此,我编写了
docschina-remark-slugger
插件,以解决{#}
无法处理的问题。除了 markdown 需要的编译需要修改之外,还需要针对文档站的左侧导航进行修改。
翻看源码,在
Page.jsx
中找到解析 title 和 id 的部分,进行了解析处理。上述过程的处理方式,其实很简单,正则匹配到
{#}
中 # 后面的部分,将后面的部分设置为 id,然后将 {} 前的内容,设置为 title 即可。奇技淫巧
解决了编译问题,接下来就是体力活了。
如何把这么多的文档都加上后缀?
最好省时省力,因为程序员都比较懒(比如我)。
修改文件最好的方式是通过 AST 修改,而修改 markdown 的 AST 网上已经存在需要现成的库。
刚刚上面提到的
remark
就属于这类库。通过调研,我想到了一个非常取巧的方式。
采用 lint 的方式对源文档进行修改,再结合 git 可以实现对已翻译的文档进行后缀添加。
最后,经过一番调研,最后采用了
textlint
对 md 进行处理。敲定了方案,开始翻阅文档思考如何解决。
我编写了测试文件
test.md
:这里将所有需要考虑的情况,都编写了进去。
如果想用 textlint 处理 md 文件,编写其对应的规则即可。
而我主要使用的是 lint 的 fix 功能。
因此,在编写规则时,还需编写其 fix 的处理方式。
textlint 的 rule 的实现如下:
这里考虑了很多特殊情况,如标题中出现 emoji 表情,有特殊符号,空格等。
试用一下:
感觉还不错,基本上解决了问题。
lint 有一个最大的好处就是,可以批量修改文件。
具体所有操作,详见 docschina/webpack.js.org。
总结
难题总会有的,想办法解决就好了。
lint 可以不止于 lint。
The text was updated successfully, but these errors were encountered: