看到 PostHTML,你应该自然就会想起 PostCSS,后者作为新一代的 CSS 处理器,一扫 SASS LESS 的威风,在社区中刮起了一阵旋风。虽然 PostHTML 后起,也不知道能否秀起来,先带着大家揭开 PostHTML 的神秘面纱。
PostHTML 能干什么呢?先给大家上个小例子。如下一个 HTML 文档:
在段落中包含了一些 emoji 表情的文本表示,比如 :speak_no_evil:等。如何将其换成可在网页上直接显示的表情呢?我们可以借助 PostHTML 的插件PostHTML-Retext 来实现:
运行上面的代码,即可把原来的 HTML 替换成如下的样子:
如果你看不到表情的话,我猜是你的系统不支持,可以点击看图。原来是知乎不支持 ——(>_
大家现在应该明白 PostHTML 的功能了吧——PostHTML 即为 HTML 的处理器,输入 HTML,经过一系列的修改,输出新的 HTML。
客官可能会问,这种替换的功能,我用正则表达式也能做呀,那 PostHTML 的优势是什么呀?
PostHTML 之于 HTML,就像 PostCSS 之于 CSS。
Uglify 之于 JavaScript,除了插件体系并不成熟以外。
PostHTML 好比一个汽车翻新工厂,而 PostHTML 插件就是一个个流水线车间:
PostHTML 将 HTML 文档按照 DOM 模型分解为一个个 node(JavaScript 对象),加上这些 node 的父子关系,形成 PostHTMLTree;PostHTML 插件获得用 JavaScript 表示的 PostHTMLTree 对象,修改、更新或者移除树上的节点,实现特定功能;最后 PostHTML 再把新的 PostHTMLTree 对象转换成 HTML 文档。
可见,PostHTML 并不提供具体的功能,仅仅实现了 HTML 和 PostHTMLTree 互相转化,且提供通用的 API 和 插件模型,让插件操作 PostHTMLTree。这与 PostCSS 如出一辙。具备如下的有点:
JavaScript only:使用 JavaScript 实现,是每一个前端的梦想;模块化:你可以按照需求,将插件(功能)组合起来使用;轻量:按需添加,避免引入大量并不使用的特性;快速扩展:在需求无法满足的时候,PostHTML 提供了便利的方式来扩展功能;鲁棒性:按照 DOM 语法,将 HTML 转换为 AST,比起正则匹配来说有更高的准确性、更细的粒度以及更强的控制力;
可编程:将 HTML 转换为用 JS 对象表示的 AST,可以很方面的使用 JS 来修改,易于编程。
posthtml([Array(plugin)]):
调用 posthtml 装载插件,获取 PostHTML 实例;
posthtml().use(Array(plugin)):
也可以通过 PostHTML 实例的 use 方法来装载插件;
posthtml().use(…).process(html[, options]):
插件装载好之后,就可以使用 process 来处理 HTML 文档了。
下面是来自官方的例子。
通过 use 方法装载了 posthtml-custom-elements 插件,就可以将自定义组件 myComponent 转换为
gulp 插件
posthtml 也可以在 gulp 中使用。安装 gulp 插件 gulp-posthtml:
使用:
PostHTML 的插件本质上就是一个函数,就接受一个参数,即 PostHTML 工厂处理好的 PostHTMLTree,插件要做的就是对这个 tree 进行修改。
PostHTML 提供了两个方法来遍历 tree:
.match(matcher, callback):matcher 可以是对象、字符串或者正则表达式,match 方法会遍历整个 tree,寻找与 matcher 匹配的 node,然后将 node 传递给 callback,我们可以在 callback 中修改 node 实现我们想要的功能;.walk(callback):比起 match,walk 是一个更加通用的方法,遍历 tree 中的每一个节点,传递给 callback。
下面是一个简单的插件:
这个插件会对影响 HTML 中的 img 标记产生影响,例如,有段 HTML 为:
使用了这个插件后:
很简单不是,是时候发挥你的聪明才智了,动手写一个插件来满足自己的需求吧!
提示:在使用 match 或者 walk 方法遍历 tree 时,如果 callback 没有返回值的话,当前的 node 就相当于被删除了。也就是说,如果你想移除某些节点,只需让 callback 不返回值或者返回 undefined 即可。暂时不能返回 null,报错,为此我提交了一个 PR。
PostHTML 作为 HTML 处理器,自然可以与 jade 或者 ejs 之类的模板引擎结合使用。jade 和 ejs 在处理业务逻辑,拼装业务数据方面有自己的优势,
而 PostHTML 可以更多地用来处理这些模板引擎产生的 HTML,比如压缩 HTML 代码等等。
下面这个例子来自 PostHTML 上的一个 PR:
PostHTML 初出茅庐,在 Github star 也才 214,但相信不久的将来PostHTML 也会像 PostCSS 一样横扫整个 HTML 处理器的世界。我也着手编写一个 PostHTML 插件posthtml-web-component,用来实现服务器端的动态化组件。欢迎关注。