在小程序中使用 towxml 解析富文本

, in 编程#微信小程序

towxml 是什么?

微信小程序内置了一个组件可以让我们渲染富文本,也就是 <rich-text /> 组件。但该组件能力较弱,并且主要是为了渲染由小程序端输入的富文本内容,面对复杂的富文本时,<rich-text /> 组件可能无法完全还原富文本内容。

为了解决这个问题,我们可以使用开源的 sbfkcel/towxml 库。

Towxml 是一个可将HTML、Markdown转为微信小程序WXML(WeiXin Markup Language)的渲染库。用于解决在微信小程序中Markdown、HTML不能直接渲染的问题。
—— towxml 的 Github README

towxml 的构建

towxml 的使用非常简单,我们按照官方文档一步步走就可以了。

首先,我们需要先克隆项目源码,并安装依赖:

# 克隆项目到本地 git clone https://github.com/sbfkcel/towxml.git # 进入项目并安装依赖 cd towxml npm install / yarn

接着我们编辑项目根目录中的 config.js,根据注释,仅保留自己需要的功能。这里给出一份我的配置:

module.exports = { // LaTex公式、yuml解析服务架设参见 https://github.com/sbfkcel/markdown-server // 数学公式解析API latex:{ api:'http://towxml.vvadd.com/?tex' }, // yuml图解析APPI yuml:{ api:'http://towxml.vvadd.com/?yuml' }, // markdown解析配置,保留需要的选项即可 markdown:[ 'sub', // 下标支持 'sup', // 上标支持 'ins', // 文本删除线支持 'mark', // 文本高亮支持 'emoji', // emoji表情支持 // 'todo' // todo支持 ], // 代码高亮配置,保留需要的选项即可(尽量越少越好,不要随意调整顺序。部分高亮有顺序依赖) highlight:[ ... ], // wxml原生标签,该系列标签将不会被转换 wxml:[ 'view', 'video', 'text', 'image', 'navigator', 'swiper', 'swiper-item', 'block', 'form', 'input', 'textarea', 'button', 'checkbox-group', 'checkbox', 'radio-group', 'radio', 'rich-text', // 可以解析的标签(html或markdown中会很少使用) // 'canvas', // 'map', // 'slider', // 'scroll-view', // 'movable-area', // 'movable-view', // 'progress', // 'label', // 'switch', // 'picker', // 'picker-view', // 'switch', // 'contact-button' ], // 自定义组件 components:[ 'audio-player', // 音频组件,建议保留,由于小程序原生audio存在诸多问题,towxml解决了原生音频播放器的相关问题 // 'echarts', // echarts图表支持 // 'latex', // 数学公式支持 'table', // 表格支持 'todogroup', // todo支持 // 'yuml', // yuml图表支持 'img' // 图片解析组件 ], // 保留原本的元素属性(建议不要变动) attrs:[ 'class', 'data', 'id', 'style' ], // 事件绑定方式(catch或bind),catch 会阻止事件向上冒泡。更多请参考:https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html bindType:'catch', // 需要激活的事件 events:[ // 'touchstart', // 'touchmove', // 'touchcancel', // 'touchend', 'tap', // 用于元素的点击事件 'change', // 用于todoList的change事件 ], // 图片倍数 dpr:1, // 代码块显示行号 showLineNumber:true }

进行构建:

npm run build / yarn build

执行完毕后,项目根目录就会多出构建好的 dist 文件夹了。

在小程序中使用

我们把上一节中构建好的 dist 目录复制到需要使用的小程序项目的根目录中,并重命名为 towxml接下来我们就需要在项目中引入 towxml 包。

引入 towxml 组件

首先,我们需要在页面的 json 配置文件中引入 towxml 组件:

{ "usingComponents": { "towxml": "/towxml/towxml" } }

在页面中插入组件

<view class="container"> <towxml nodes="{{article}}" /> </view>

引入并使用 towxml 解析方法

接下来我们需要引入 towxml 解析方法,这个方法负责解析富文本内容。

在 towxml 的官方文档 如何使用 这一节中,demo 代码需要在 app.js 中全局注册 towxml 解析方法:

// app.js App({ // 引入`towxml3.0`解析方法 towxml:require('/towxml/index') }) // page.js const app = getApp(); onLoad() { app.towxml(...); }

如果你的小程序中处处充斥着富文本解析的需求,那么这样做当然是更简便的。但大部分小程序中的富文本解析只占一小部分,因此我们可以考虑在某个页面中单独引入 towxml 解析方法。

// page.js import towxml from '../../vendor/towxml/index'; onLoad() { towxml(...); }

至于方法的使用和具体 API,请参考 官方文档中的 API 这一节。

onLoad() { const result = app.towxml(`# Markdown`, "markdown", { base: "https://xxx.com", // 相对资源的base路径 theme: "dark", // 主题,默认`light` events: { // 为元素绑定的事件方法 tap: (e) => { console.log("tap", e); }, }, }); // 更新解析数据 this.setData({ article: result, isLoading: false, }); }

注意取消 towxml 的格式化和代码检查

如果我们的小程序项目中使用了 Prettier 或者 ESLint,那么应当注意在 .prettierignore.eslintignore 文件中添加对 towxml 目录的忽略。

更改 towxml 包在项目中的位置

在官方文档中,towxml 要求放置在小程序的根目录才能运行,如果我们放置到小程序的某个子目录中,比如 /vendor/towxml,即使项目中的引用路径正确也会抛出异常。

好在我们可以通过修改 towxml/decode.json 中的文件路径解决这个问题。假如我们把 towxml 文件夹放在 /vendor/towxml 目录下,那么我们可以把文件内容修改为:

// towxml/decode.json { "component": true, "usingComponents": { "decode": "/vendor/towxml/decode", "audio-player": "/vendor/towxml/audio-player/audio-player", "table": "/vendor/towxml/table/table", "todogroup": "/vendor/towxml/todogroup/todogroup", "img": "/vendor/towxml/img/img" } }

重新编译小程序,就应该能够生效了。

在小程序分包中使用

towxml 虽然强大,但体积并不算小。笔者只打开了自己需要的功能,构建后的文件夹还是有 250KB。因此我们可以考虑把所有的富文本页面以及 towxml 拆成一个小程序分包。

新建分包

首先我们需要新建一个分包文件夹,比如 /subpackages/richTextRender

接着我们需要在 app.json 中注册这个分包:

{ "subpackages": [ { "root": "subpackages/rickTextRender", "pages": ["pages/articleDetail/articleDetail"] } ], }

把 towxml 移入分包中

移动 towxml 文件夹到 /subpackages/richTextRender/vendor/towxml

修改 decode.json

修改 /subpackages/richTextRender/vendor/towxml/decode.json 中的内容,保证文件路径和 towxml 所在的文件路径一致。

{ "component": true, "usingComponents": { "decode": "/subpackages/rickTextRender/vendor/towxml/decode", "audio-player": "/subpackages/rickTextRender/vendor/towxml/audio-player/audio-player", "table": "/subpackages/rickTextRender/vendor/towxml/table/table", "todogroup": "/subpackages/rickTextRender/vendor/towxml/todogroup/todogroup", "img": "/subpackages/rickTextRender/vendor/towxml/img/img" } }

在页面中使用 towxml

page.js:

// page.js import towxml from '../../vendor/towxml/index'; onLoad() { const result = towxml(...); this.setData({ article: result }) }

page.json:

// page.json { "usingComponents": { "towxml": "/subpackages/rickTextRender/vendor/towxml/towxml" } }

page.wxml:

<view class="container"> <towxml nodes="{{article}}" /> </view>
£ 赞赏