From 667f91dd3fab899c039962d91aeeb740ad23206c Mon Sep 17 00:00:00 2001
From: wangchenguang <728837162@qq.com>
Date: Wed, 26 Apr 2023 10:36:53 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=9C=80=E6=B1=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
order/orderDetail/orderDetail.vue | 10 +-
team/article/article.vue | 6 +-
uni_modules/mp-html/README.md | 191 +++
uni_modules/mp-html/changelog.md | 121 ++
.../mp-html/components/mp-html/mp-html.vue | 498 ++++++
.../mp-html/components/mp-html/node/node.vue | 576 +++++++
.../mp-html/components/mp-html/parser.js | 1333 +++++++++++++++++
uni_modules/mp-html/package.json | 76 +
.../static/app-plus/mp-html/js/handler.js | 1 +
.../app-plus/mp-html/js/uni.webview.min.js | 1 +
.../static/app-plus/mp-html/local.html | 1 +
11 files changed, 2806 insertions(+), 8 deletions(-)
create mode 100644 uni_modules/mp-html/README.md
create mode 100644 uni_modules/mp-html/changelog.md
create mode 100644 uni_modules/mp-html/components/mp-html/mp-html.vue
create mode 100644 uni_modules/mp-html/components/mp-html/node/node.vue
create mode 100644 uni_modules/mp-html/components/mp-html/parser.js
create mode 100644 uni_modules/mp-html/package.json
create mode 100644 uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
create mode 100644 uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
create mode 100644 uni_modules/mp-html/static/app-plus/mp-html/local.html
diff --git a/order/orderDetail/orderDetail.vue b/order/orderDetail/orderDetail.vue
index b5cb1f5..0e5c4f7 100644
--- a/order/orderDetail/orderDetail.vue
+++ b/order/orderDetail/orderDetail.vue
@@ -12,23 +12,23 @@
{{ form.customerName }}
{{ form.customerName || '请选择客户' }}
-
+
省份
{{ form.provinceName }}
-
+
城市
{{ form.cityName }}
-
+
联系人
{{ form.orderContact }}
-
+
电话
{{ form.phone }}
-
+
邮箱
{{ form.email }}
diff --git a/team/article/article.vue b/team/article/article.vue
index f854fa6..781ab90 100644
--- a/team/article/article.vue
+++ b/team/article/article.vue
@@ -18,7 +18,7 @@
-
+
@@ -66,7 +66,6 @@
const regex = /(]*?\s+style=")([^"]*)("[^>]*?>)/g;
const newStr = str.replace(regex, `$1${newStyle}$3`);
const videoStr = this.replaceAllVideoTagStyles(str, "width: 95%; height: 450rpx;display: block;margin:0 auto")
- // const imgStr = videoStr.replace(regex, `$1${newStyle}$3`);
const imgStr = this.addImgStyle(videoStr)
message.mainBody = imgStr
this.form = message
@@ -107,7 +106,7 @@
return str.replace(/<(img).*?(\/>|<\/img>)/g, function (a) {
if (a.indexOf('style') < 0) {
// 字符串中没有style
- return a.replace(/<\s*img/, '< img style="width:100%"');
+ return a.replace(/<\s*img/, '
+
+ ```
+ ```javascript
+ export default {
+ data() {
+ return {
+ html: 'Hello World!
'
+ }
+ }
+ }
+ ```
+ 3. 需要更新版本时在 `HBuilder X` 中右键 `uni_modules/mp-html` 目录选择 `从插件市场更新` 即可
+
+- 源码方式
+ 1. 从 [github](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 或 [gitee](https://gitee.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 下载源码
+ 插件市场的 **非 uni_modules 版本** 无法更新,不建议从插件市场获取
+ 2. 在需要使用页面的 `(n)vue` 文件中添加
+ ```html
+
+ ```
+ ```javascript
+ import mpHtml from '@/components/mp-html/mp-html'
+ export default {
+ // HBuilderX 2.5.5+ 可以通过 easycom 自动引入
+ components: {
+ mpHtml
+ },
+ data() {
+ return {
+ html: 'Hello World!
'
+ }
+ }
+ }
+ ```
+
+- npm 方式
+ 1. 在项目根目录下执行
+ ```bash
+ npm install mp-html
+ ```
+ 2. 在需要使用页面的 `(n)vue` 文件中添加
+ ```html
+
+ ```
+ ```javascript
+ import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
+ export default {
+ // 不可省略
+ components: {
+ mpHtml
+ },
+ data() {
+ return {
+ html: 'Hello World!
'
+ }
+ }
+ }
+ ```
+ 3. 需要更新版本时执行以下命令即可
+ ```bash
+ npm update mp-html
+ ```
+
+ 使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
+ 如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
+
+查看 [快速开始](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart) 了解更多
+
+## 组件属性
+
+| 属性 | 类型 | 默认值 | 说明 |
+|:---:|:---:|:---:|---|
+| container-style | String | | 容器的样式([2.1.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v210)) |
+| content | String | | 用于渲染的 html 字符串 |
+| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
+| domain | String | | 主域名(用于链接拼接) |
+| error-img | String | | 图片出错时的占位图链接 |
+| lazy-load | Boolean | false | 是否开启图片懒加载 |
+| loading-img | String | | 图片加载过程中的占位图链接 |
+| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
+| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
+| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
+| selectable | Boolean | false | 是否开启文本长按复制 |
+| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
+| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
+| tag-style | Object | | 设置标签的默认样式 |
+| use-anchor | Boolean | false | 是否使用锚点链接 |
+
+查看 [属性](https://jin-yufeng.gitee.io/mp-html/#/basic/prop) 了解更多
+
+## 组件事件
+
+| 名称 | 触发时机 |
+|:---:|---|
+| load | dom 树加载完毕时 |
+| ready | 图片加载完毕时 |
+| error | 发生渲染错误时 |
+| imgtap | 图片被点击时 |
+| linktap | 链接被点击时 |
+| play | 音视频播放时 |
+
+查看 [事件](https://jin-yufeng.gitee.io/mp-html/#/basic/event) 了解更多
+
+## api
+组件实例上提供了一些 `api` 方法可供调用
+
+| 名称 | 作用 |
+|:---:|---|
+| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
+| navigateTo | 锚点跳转 |
+| getText | 获取文本内容 |
+| getRect | 获取富文本内容的位置和大小 |
+| setContent | 设置富文本内容 |
+| imgList | 获取所有图片的数组 |
+| pauseMedia | 暂停播放音视频([2.2.2+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v222)) |
+| setPlaybackRate | 设置音视频播放速率([2.4.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v240)) |
+
+查看 [api](https://jin-yufeng.gitee.io/mp-html/#/advanced/api) 了解更多
+
+## 插件扩展
+除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
+
+| 名称 | 作用 |
+|:---:|---|
+| audio | 音乐播放器 |
+| editable | 富文本 **编辑**([示例项目](https://mp-html.oss-cn-hangzhou.aliyuncs.com/editable.zip)) |
+| emoji | 解析 emoji |
+| highlight | 代码块高亮显示 |
+| markdown | 渲染 markdown |
+| search | 关键词搜索 |
+| style | 匹配 style 标签中的样式 |
+| txv-video | 使用腾讯视频 |
+| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
+| latex | 渲染 latex 公式 by [@Zeng-J](https://github.com/Zeng-J) |
+
+从插件市场导入的包中 **不含有** 扩展插件,使用插件需通过微信小程序 `富文本插件` 获取或参考以下方法进行打包:
+1. 获取完整组件包
+ ```bash
+ npm install mp-html
+ ```
+2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件
+3. 生成新的组件包
+ 在 `node_modules/mp-html` 目录下执行
+ ```bash
+ npm install
+ npm run build:uni-app
+ ```
+4. 拷贝 `dist/uni-app` 中的内容到项目根目录
+
+查看 [插件](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin) 了解更多
+
+## 关于 nvue
+`nvue` 使用原生渲染,不支持部分 `css` 样式,为实现和 `html` 相同的效果,组件内部通过 `web-view` 进行渲染,性能上差于原生,根据 `weex` 官方建议,`web` 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 `richtext`)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 `vue` 页面
+由于渲染方式与其他端不同,有以下限制:
+1. 不支持 `lazy-load` 属性
+2. 视频不支持全屏播放
+3. 如果在 `flex-direction: row` 的容器中使用,需要给组件设置宽度或设置 `flex: 1` 占满剩余宽度
+
+纯 `nvue` 模式下,[此问题](https://ask.dcloud.net.cn/question/119678) 修复前,不支持通过 `uni_modules` 引入,需要本地引入(将 [dist/uni-app](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 中的内容拷贝到项目根目录下)
+
+## 立即体验
+![富文本插件](https://mp-html.oss-cn-hangzhou.aliyuncs.com/qrcode.jpg)
+
+## 问题反馈
+遇到问题时,请先查阅 [常见问题](https://jin-yufeng.gitee.io/mp-html/#/question/faq) 和 [issue](https://github.com/jin-yufeng/mp-html/issues) 中是否已有相同的问题
+可通过 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose) 、插件问答或发送邮件到 [mp_html@126.com](mailto:mp_html@126.com) 提问,不建议在评论区提问(不方便回复)
+提问请严格按照 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose) ,描述清楚使用环境、`html` 内容或可复现的 `demo` 项目以及复现方式,对于 **描述不清**、**无法复现** 或重复的问题将不予回复
+
+欢迎加入 `QQ` 交流群:`699734691`
+
+查看 [问题反馈](https://jin-yufeng.gitee.io/mp-html/#/question/feedback) 了解更多
diff --git a/uni_modules/mp-html/changelog.md b/uni_modules/mp-html/changelog.md
new file mode 100644
index 0000000..51d049e
--- /dev/null
+++ b/uni_modules/mp-html/changelog.md
@@ -0,0 +1,121 @@
+## v2.4.1(2022-12-25)
+1. `F` 修复了没有图片时 `ready` 事件可能不触发的问题
+2. `F` 修复了加载过程中可能出现 `Root label not found` 错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/470)
+3. `F` 修复了 `audio` 插件退出页面可能会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/457)
+4. `F` 修复了 `vue3` 运行到 `app` 在 `HBuilder X 3.6.10` 以上报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/480)
+5. `F` 修复了 `nvue` 端链接中包含 `%22` 时可能无法显示的问题
+6. `F` 修复了 `vue3` 使用 `highlight` 插件可能报错的问题
+## v2.4.0(2022-08-27)
+1. `A` 增加了 [setPlaybackRate](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#setPlaybackRate) 的 `api`,可以设置音视频的播放速率 [详细](https://github.com/jin-yufeng/mp-html/issues/452)
+2. `A` 示例小程序代码开源 [详细](https://github.com/jin-yufeng/mp-html-demo)
+3. `U` 优化 `ready` 事件触发时机,未设置懒加载的情况下基本可以准确触发 [详细](https://github.com/jin-yufeng/mp-html/issues/195)
+4. `U` `highlight` 插件在编辑状态下不进行高亮处理,便于编辑
+5. `F` 修复了 `flex` 布局下图片大小可能不正确的问题
+6. `F` 修复了 `selectable` 属性没有设置 `force` 也可能出现渲染异常的问题
+7. `F` 修复了表格中的图片大小可能不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/448)
+8. `F` 修复了含有合并单元格的表格可能无法设置竖直对齐的问题
+9. `F` 修复了 `editable` 插件在 `scroll-view` 中使用时工具条位置可能不正确的问题
+10. `F` 修复了 `vue3` 使用 [search](advanced/plugin#search) 插件可能导致错误换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/449)
+## v2.3.2(2022-08-13)
+1. `A` 增加 [latex](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#latex) 插件,可以渲染数学公式 [详细](https://github.com/jin-yufeng/mp-html/pull/447) by [@Zeng-J](https://github.com/Zeng-J)
+2. `U` 优化根节点下有很多标签的长内容渲染速度
+3. `U` `highlight` 插件适配 `lang-xxx` 格式
+4. `F` 修复了 `table` 标签设置 `border` 属性后可能无法修改边框样式的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/439) by [@zouxingjie](https://github.com/zouxingjie)
+5. `F` 修复了 `editable` 插件输入连续空格无效的问题
+6. `F` 修复了 `vue3` 图片设置 `inline` 会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/438)
+7. `F` 修复了 `vue3` 使用 `table` 可能报错的问题
+## v2.3.1(2022-05-20)
+1. `U` `app` 端支持使用本地图片
+2. `U` 优化了微信小程序 `selectable` 属性在 `ios` 端的处理 [详细](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable)
+3. `F` 修复了 `editable` 插件不在顶部时 `tooltip` 位置可能错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/430)
+4. `F` 修复了 `vue3` 运行到微信小程序可能报错丢失内容的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/414)
+5. `F` 修复了 `vue3` 部分标签可能被错误换行的问题
+6. `F` 修复了 `editable` 插件 `app` 端插入视频无法预览的问题
+## v2.3.0(2022-04-01)
+1. `A` 增加了 `play` 事件,音视频播放时触发,可用于与页面其他音视频进行互斥播放 [详细](basic/event#play)
+2. `U` `show-img-menu` 属性支持控制预览时是否长按弹出菜单
+3. `U` 优化 `wxs` 处理,提高渲染性能 [详细](https://developers.weixin.qq.com/community/develop/article/doc/0006cc2b204740f601bd43fa25a413)
+4. `U` `video` 标签支持 `object-fit` 属性
+5. `U` 增加支持一些常用实体编码 [详细](https://github.com/jin-yufeng/mp-html/issues/418)
+6. `F` 修复了图片仅设置高度可能不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/410)
+7. `F` 修复了 `video` 标签高度设置为 `auto` 不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/411)
+8. `F` 修复了使用 `grid` 布局时可能样式错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/413)
+9. `F` 修复了含有合并单元格的表格部分情况下显示异常的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/417)
+10. `F` 修复了 `editable` 插件连续插入内容时顺序不正确的问题
+11. `F` 修复了 `uni-app` 包 `vue3` 使用 `audio` 插件报错的问题
+12. `F` 修复了 `uni-app` 包 `highlight` 插件使用自定义的 `prism.min.js` 报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/416)
+## v2.2.2(2022-02-26)
+1. `A` 增加了 [pauseMedia](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#pauseMedia) 的 `api`,可用于暂停播放音视频 [详细](https://github.com/jin-yufeng/mp-html/issues/317)
+2. `U` 优化了长内容的加载速度
+3. `U` 适配 `vue3` [#389](https://github.com/jin-yufeng/mp-html/issues/389)、[#398](https://github.com/jin-yufeng/mp-html/pull/398) by [@zhouhuafei](https://github.com/zhouhuafei)、[#400](https://github.com/jin-yufeng/mp-html/issues/400)
+4. `F` 修复了小程序端图片高度设置为百分比时可能不显示的问题
+5. `F` 修复了 `highlight` 插件部分情况下可能显示不完整的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/403)
+## v2.2.1(2021-12-24)
+1. `A` `editable` 插件增加上下移动标签功能
+2. `U` `editable` 插件支持在文本中间光标处插入内容
+3. `F` 修复了 `nvue` 端设置 `margin` 后可能导致高度不正确的问题
+4. `F` 修复了 `highlight` 插件使用压缩版的 `prism.css` 可能导致背景失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/367)
+5. `F` 修复了编辑状态下使用 `emoji` 插件内容为空时可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/371)
+6. `F` 修复了使用 `editable` 插件后将 `selectable` 属性设置为 `force` 不生效的问题
+## v2.2.0(2021-10-12)
+1. `A` 增加 `customElements` 配置项,便于添加自定义功能性标签 [详细](https://github.com/jin-yufeng/mp-html/issues/350)
+2. `A` `editable` 插件增加切换音视频自动播放状态的功能 [详细](https://github.com/jin-yufeng/mp-html/pull/341) by [@leeseett](https://github.com/leeseett)
+3. `A` `editable` 插件删除媒体标签时触发 `remove` 事件,便于删除已上传的文件
+4. `U` `editable` 插件 `insertImg` 方法支持同时插入多张图片 [详细](https://github.com/jin-yufeng/mp-html/issues/342)
+5. `U` `editable` 插入图片和音视频时支持拼接 `domian` 主域名
+6. `F` 修复了内部链接参数中包含 `://` 时被认为是外部链接的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/356)
+7. `F` 修复了部分 `svg` 标签名或属性名大小写不正确时不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/351)
+8. `F` 修复了 `nvue` 页面运行到非 `app` 平台时可能样式错误的问题
+## v2.1.5(2021-08-13)
+1. `A` 增加支持标签的 `dir` 属性
+2. `F` 修复了 `ruby` 标签文字与拼音没有居中对齐的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/325)
+3. `F` 修复了音视频标签内有 `a` 标签时可能无法播放的问题
+4. `F` 修复了 `externStyle` 中的 `class` 名包含下划线或数字时可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
+5. `F` 修复了 `h5` 端引入 `externStyle` 可能不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
+## v2.1.4(2021-07-14)
+1. `F` 修复了 `rt` 标签无法设置样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/318)
+2. `F` 修复了表格中有单元格同时合并行和列时可能显示不正确的问题
+3. `F` 修复了 `app` 端无法关闭图片长按菜单的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/322)
+4. `F` 修复了 `editable` 插件只能添加图片链接不能修改的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/312) by [@leeseett](https://github.com/leeseett)
+## v2.1.3(2021-06-12)
+1. `A` `editable` 插件增加 `insertTable` 方法
+2. `U` `editable` 插件支持编辑表格中的空白单元格 [详细](https://github.com/jin-yufeng/mp-html/issues/310)
+3. `F` 修复了 `externStyle` 中使用伪类可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/298)
+4. `F` 修复了多个组件同时使用时 `tag-style` 属性时可能互相影响的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/305) by [@woodguoyu](https://github.com/woodguoyu)
+5. `F` 修复了包含 `linearGradient` 的 `svg` 可能无法显示的问题
+6. `F` 修复了编译到头条小程序时可能报错的问题
+7. `F` 修复了 `nvue` 端不触发 `click` 事件的问题
+8. `F` 修复了 `editable` 插件尾部插入时无法撤销的问题
+9. `F` 修复了 `editable` 插件的 `insertHtml` 方法只能在末尾插入的问题
+10. `F` 修复了 `editable` 插件插入音频不显示的问题
+## v2.1.2(2021-04-24)
+1. `A` 增加了 [img-cache](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#img-cache) 插件,可以在 `app` 端缓存图片 [详细](https://github.com/jin-yufeng/mp-html/issues/292) by [@PentaTea](https://github.com/PentaTea)
+2. `U` 支持通过 `container-style` 属性设置 `white-space` 来保留连续空格和换行符 [详细](https://jin-yufeng.gitee.io/mp-html/#/question/faq#space)
+3. `U` 代码风格符合 [standard](https://standardjs.com) 标准
+4. `U` `editable` 插件编辑状态下支持预览视频 [详细](https://github.com/jin-yufeng/mp-html/issues/286)
+5. `F` 修复了 `svg` 标签内嵌 `svg` 时无法显示的问题
+6. `F` 修复了编译到支付宝和头条小程序时部分区域不可复制的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/291)
+## v2.1.1(2021-04-09)
+1. 修复了对 `p` 标签设置 `tag-style` 可能不生效的问题
+2. 修复了 `svg` 标签中的文本无法显示的问题
+3. 修复了使用 `editable` 插件编辑表格时可能报错的问题
+4. 修复了使用 `highlight` 插件运行到头条小程序时可能没有样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/280)
+5. 修复了使用 `editable` 插件 `editable` 属性为 `false` 时会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/284)
+6. 修复了 `style` 插件连续子选择器失效的问题
+7. 修复了 `editable` 插件无法修改图片和字体大小的问题
+## v2.1.0.2(2021-03-21)
+修复了 `nvue` 端使用可能报错的问题
+## v2.1.0(2021-03-20)
+1. `A` 增加了 [container-style](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#container-style) 属性 [详细](https://gitee.com/jin-yufeng/mp-html/pulls/1)
+2. `A` 增加支持 `strike` 标签
+3. `A` `editable` 插件增加 `placeholder` 属性 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
+4. `A` `editable` 插件增加 `insertHtml` 方法 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
+5. `U` 外部样式支持标签名选择器 [详细](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart#setting)
+6. `F` 修复了 `nvue` 端部分情况下可能不显示的问题
+## v2.0.5(2021-03-12)
+1. `U` [linktap](https://jin-yufeng.gitee.io/mp-html/#/basic/event#linktap) 事件增加返回内部文本内容 `innerText` [详细](https://github.com/jin-yufeng/mp-html/issues/271)
+2. `U` [selectable](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable) 属性设置为 `force` 时能够在微信 `iOS` 端生效(文本块会变成 `inline-block`) [详细](https://github.com/jin-yufeng/mp-html/issues/267)
+3. `F` 修复了部分情况下竖向无法滚动的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/182)
+4. `F` 修复了多次修改富文本数据时部分内容可能不显示的问题
+5. `F` 修复了 [腾讯视频](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#txv-video) 插件可能无法播放的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/265)
+6. `F` 修复了 [highlight](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#highlight) 插件没有设置高亮语言时没有应用默认样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/276) by [@fuzui](https://github.com/fuzui)
diff --git a/uni_modules/mp-html/components/mp-html/mp-html.vue b/uni_modules/mp-html/components/mp-html/mp-html.vue
new file mode 100644
index 0000000..a9b5dec
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/mp-html.vue
@@ -0,0 +1,498 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/mp-html/components/mp-html/node/node.vue b/uni_modules/mp-html/components/mp-html/node/node.vue
new file mode 100644
index 0000000..372bcd1
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/node/node.vue
@@ -0,0 +1,576 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{n.text}}
+
+
+ {{n.text}}
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/uni_modules/mp-html/components/mp-html/parser.js b/uni_modules/mp-html/components/mp-html/parser.js
new file mode 100644
index 0000000..cdbb135
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/parser.js
@@ -0,0 +1,1333 @@
+/**
+ * @fileoverview html 解析器
+ */
+
+// 配置
+const config = {
+ // 信任的标签(保持标签名不变)
+ trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
+
+ // 块级标签(转为 div,其他的非信任标签转为 span)
+ blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
+
+ // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
+ // 行内标签
+ inlineTags: makeMap('abbr,b,big,code,del,em,i,ins,label,q,small,span,strong,sub,sup'),
+ // #endif
+
+ // 要移除的标签
+ ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
+
+ // 自闭合的标签
+ voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
+
+ // html 实体
+ entities: {
+ lt: '<',
+ gt: '>',
+ quot: '"',
+ apos: "'",
+ ensp: '\u2002',
+ emsp: '\u2003',
+ nbsp: '\xA0',
+ semi: ';',
+ ndash: '–',
+ mdash: '—',
+ middot: '·',
+ lsquo: '‘',
+ rsquo: '’',
+ ldquo: '“',
+ rdquo: '”',
+ bull: '•',
+ hellip: '…',
+ larr: '←',
+ uarr: '↑',
+ rarr: '→',
+ darr: '↓'
+ },
+
+ // 默认的标签样式
+ tagStyle: {
+ // #ifndef APP-PLUS-NVUE
+ address: 'font-style:italic',
+ big: 'display:inline;font-size:1.2em',
+ caption: 'display:table-caption;text-align:center',
+ center: 'text-align:center',
+ cite: 'font-style:italic',
+ dd: 'margin-left:40px',
+ mark: 'background-color:yellow',
+ pre: 'font-family:monospace;white-space:pre',
+ s: 'text-decoration:line-through',
+ small: 'display:inline;font-size:0.8em',
+ strike: 'text-decoration:line-through',
+ u: 'text-decoration:underline'
+ // #endif
+ },
+
+ // svg 大小写对照表
+ svgDict: {
+ animatetransform: 'animateTransform',
+ lineargradient: 'linearGradient',
+ viewbox: 'viewBox',
+ attributename: 'attributeName',
+ repeatcount: 'repeatCount',
+ repeatdur: 'repeatDur'
+ }
+}
+const tagSelector={}
+const {
+ windowWidth,
+ // #ifdef MP-WEIXIN
+ system
+ // #endif
+} = uni.getSystemInfoSync()
+const blankChar = makeMap(' ,\r,\n,\t,\f')
+let idIndex = 0
+
+// #ifdef H5 || APP-PLUS
+config.ignoreTags.iframe = undefined
+config.trustTags.iframe = true
+config.ignoreTags.embed = undefined
+config.trustTags.embed = true
+// #endif
+// #ifdef APP-PLUS-NVUE
+config.ignoreTags.source = undefined
+config.ignoreTags.style = undefined
+// #endif
+
+/**
+ * @description 创建 map
+ * @param {String} str 逗号分隔
+ */
+function makeMap (str) {
+ const map = Object.create(null)
+ const list = str.split(',')
+ for (let i = list.length; i--;) {
+ map[list[i]] = true
+ }
+ return map
+}
+
+/**
+ * @description 解码 html 实体
+ * @param {String} str 要解码的字符串
+ * @param {Boolean} amp 要不要解码 &
+ * @returns {String} 解码后的字符串
+ */
+function decodeEntity (str, amp) {
+ let i = str.indexOf('&')
+ while (i !== -1) {
+ const j = str.indexOf(';', i + 3)
+ let code
+ if (j === -1) break
+ if (str[i + 1] === '#') {
+ // { 形式的实体
+ code = parseInt((str[i + 2] === 'x' ? '0' : '') + str.substring(i + 2, j))
+ if (!isNaN(code)) {
+ str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1)
+ }
+ } else {
+ // 形式的实体
+ code = str.substring(i + 1, j)
+ if (config.entities[code] || (code === 'amp' && amp)) {
+ str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1)
+ }
+ }
+ i = str.indexOf('&', i + 1)
+ }
+ return str
+}
+
+/**
+ * @description 合并多个块级标签,加快长内容渲染
+ * @param {Array} nodes 要合并的标签数组
+ */
+function mergeNodes (nodes) {
+ let i = nodes.length - 1
+ for (let j = i; j >= -1; j--) {
+ if (j === -1 || nodes[j].c || !nodes[j].name || (nodes[j].name !== 'div' && nodes[j].name !== 'p' && nodes[j].name[0] !== 'h') || (nodes[j].attrs.style || '').includes('inline')) {
+ if (i - j >= 5) {
+ nodes.splice(j + 1, i - j, {
+ name: 'div',
+ attrs: {},
+ children: nodes.slice(j + 1, i + 1)
+ })
+ }
+ i = j - 1
+ }
+ }
+}
+
+/**
+ * @description html 解析器
+ * @param {Object} vm 组件实例
+ */
+function Parser (vm) {
+ this.options = vm || {}
+ this.tagStyle = Object.assign({}, config.tagStyle, this.options.tagStyle)
+ this.imgList = vm.imgList || []
+ this.imgList._unloadimgs = 0
+ this.plugins = vm.plugins || []
+ this.attrs = Object.create(null)
+ this.stack = []
+ this.nodes = []
+ this.pre = (this.options.containerStyle || '').includes('white-space') && this.options.containerStyle.includes('pre') ? 2 : 0
+}
+
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+Parser.prototype.parse = function (content) {
+ // 插件处理
+ for (let i = this.plugins.length; i--;) {
+ if (this.plugins[i].onUpdate) {
+ content = this.plugins[i].onUpdate(content, config) || content
+ }
+ }
+
+ new Lexer(this).parse(content)
+ // 出栈未闭合的标签
+ while (this.stack.length) {
+ this.popNode()
+ }
+ if (this.nodes.length > 50) {
+ mergeNodes(this.nodes)
+ }
+ return this.nodes
+}
+
+/**
+ * @description 将标签暴露出来(不被 rich-text 包含)
+ */
+Parser.prototype.expose = function () {
+ // #ifndef APP-PLUS-NVUE
+ for (let i = this.stack.length; i--;) {
+ const item = this.stack[i]
+ if (item.c || item.name === 'a' || item.name === 'video' || item.name === 'audio') return
+ item.c = 1
+ }
+ // #endif
+}
+
+/**
+ * @description 处理插件
+ * @param {Object} node 要处理的标签
+ * @returns {Boolean} 是否要移除此标签
+ */
+Parser.prototype.hook = function (node) {
+ for (let i = this.plugins.length; i--;) {
+ if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) === false) {
+ return false
+ }
+ }
+ return true
+}
+
+/**
+ * @description 将链接拼接上主域名
+ * @param {String} url 需要拼接的链接
+ * @returns {String} 拼接后的链接
+ */
+Parser.prototype.getUrl = function (url) {
+ const domain = this.options.domain
+ if (url[0] === '/') {
+ if (url[1] === '/') {
+ // // 开头的补充协议名
+ url = (domain ? domain.split('://')[0] : 'http') + ':' + url
+ } else if (domain) {
+ // 否则补充整个域名
+ url = domain + url
+ } /* #ifdef APP-PLUS */ else {
+ url = plus.io.convertLocalFileSystemURL(url)
+ } /* #endif */
+ } else if (!url.includes('data:') && !url.includes('://')) {
+ if (domain) {
+ url = domain + '/' + url
+ } /* #ifdef APP-PLUS */ else {
+ url = plus.io.convertLocalFileSystemURL(url)
+ } /* #endif */
+ }
+ return url
+}
+
+/**
+ * @description 解析样式表
+ * @param {Object} node 标签
+ * @returns {Object}
+ */
+Parser.prototype.parseStyle = function (node) {
+ const attrs = node.attrs
+ const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';'))
+ const styleObj = {}
+ let tmp = ''
+
+ if (attrs.id && !this.xml) {
+ // 暴露锚点
+ if (this.options.useAnchor) {
+ this.expose()
+ } else if (node.name !== 'img' && node.name !== 'a' && node.name !== 'video' && node.name !== 'audio') {
+ attrs.id = undefined
+ }
+ }
+
+ // 转换 width 和 height 属性
+ if (attrs.width) {
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')
+ attrs.width = undefined
+ }
+ if (attrs.height) {
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')
+ attrs.height = undefined
+ }
+
+ for (let i = 0, len = list.length; i < len; i++) {
+ const info = list[i].split(':')
+ if (info.length < 2) continue
+ const key = info.shift().trim().toLowerCase()
+ let value = info.join(':').trim()
+ if ((value[0] === '-' && value.lastIndexOf('-') > 0) || value.includes('safe')) {
+ // 兼容性的 css 不压缩
+ tmp += `;${key}:${value}`
+ } else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
+ // 重复的样式进行覆盖
+ if (value.includes('url')) {
+ // 填充链接
+ let j = value.indexOf('(') + 1
+ if (j) {
+ while (value[j] === '"' || value[j] === "'" || blankChar[value[j]]) {
+ j++
+ }
+ value = value.substr(0, j) + this.getUrl(value.substr(j))
+ }
+ } else if (value.includes('rpx')) {
+ // 转换 rpx(rich-text 内部不支持 rpx)
+ value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px')
+ }
+ styleObj[key] = value
+ }
+ }
+
+ node.attrs.style = tmp
+ return styleObj
+}
+
+/**
+ * @description 解析到标签名
+ * @param {String} name 标签名
+ * @private
+ */
+Parser.prototype.onTagName = function (name) {
+ this.tagName = this.xml ? name : name.toLowerCase()
+ if (this.tagName === 'svg') {
+ this.xml = (this.xml || 0) + 1 // svg 标签内大小写敏感
+ }
+}
+
+/**
+ * @description 解析到属性名
+ * @param {String} name 属性名
+ * @private
+ */
+Parser.prototype.onAttrName = function (name) {
+ name = this.xml ? name : name.toLowerCase()
+ if (name.substr(0, 5) === 'data-') {
+ if (name === 'data-src' && !this.attrs.src) {
+ // data-src 自动转为 src
+ this.attrName = 'src'
+ } else if (this.tagName === 'img' || this.tagName === 'a') {
+ // a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
+ this.attrName = name
+ } else {
+ // 剩余的移除以减小大小
+ this.attrName = undefined
+ }
+ } else {
+ this.attrName = name
+ this.attrs[name] = 'T' // boolean 型属性缺省设置
+ }
+}
+
+/**
+ * @description 解析到属性值
+ * @param {String} val 属性值
+ * @private
+ */
+Parser.prototype.onAttrVal = function (val) {
+ const name = this.attrName || ''
+ if (name === 'style' || name === 'href') {
+ // 部分属性进行实体解码
+ this.attrs[name] = decodeEntity(val, true)
+ } else if (name.includes('src')) {
+ // 拼接主域名
+ this.attrs[name] = this.getUrl(decodeEntity(val, true))
+ } else if (name) {
+ this.attrs[name] = val
+ }
+}
+
+/**
+ * @description 解析到标签开始
+ * @param {Boolean} selfClose 是否有自闭合标识 />
+ * @private
+ */
+Parser.prototype.onOpenTag = function (selfClose) {
+ // 拼装 node
+ const node = Object.create(null)
+ node.name = this.tagName
+ node.attrs = this.attrs
+ // 避免因为自动 diff 使得 type 被设置为 null 导致部分内容不显示
+ if (this.options.nodes.length) {
+ node.type = 'node'
+ }
+ this.attrs = Object.create(null)
+
+ const attrs = node.attrs
+ const parent = this.stack[this.stack.length - 1]
+ const siblings = parent ? parent.children : this.nodes
+ const close = this.xml ? selfClose : config.voidTags[node.name]
+
+ // 替换标签名选择器
+ if (tagSelector[node.name]) {
+ attrs.class = tagSelector[node.name] + (attrs.class ? ' ' + attrs.class : '')
+ }
+
+ // 转换 embed 标签
+ if (node.name === 'embed') {
+ // #ifndef H5 || APP-PLUS
+ const src = attrs.src || ''
+ // 按照后缀名和 type 将 embed 转为 video 或 audio
+ if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) {
+ node.name = 'video'
+ } else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) {
+ node.name = 'audio'
+ }
+ if (attrs.autostart) {
+ attrs.autoplay = 'T'
+ }
+ attrs.controls = 'T'
+ // #endif
+ // #ifdef H5 || APP-PLUS
+ this.expose()
+ // #endif
+ }
+
+ // #ifndef APP-PLUS-NVUE
+ // 处理音视频
+ if (node.name === 'video' || node.name === 'audio') {
+ // 设置 id 以便获取 context
+ if (node.name === 'video' && !attrs.id) {
+ attrs.id = 'v' + idIndex++
+ }
+ // 没有设置 controls 也没有设置 autoplay 的自动设置 controls
+ if (!attrs.controls && !attrs.autoplay) {
+ attrs.controls = 'T'
+ }
+ // 用数组存储所有可用的 source
+ node.src = []
+ if (attrs.src) {
+ node.src.push(attrs.src)
+ attrs.src = undefined
+ }
+ this.expose()
+ }
+ // #endif
+
+ // 处理自闭合标签
+ if (close) {
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
+ // 通过 base 标签设置主域名
+ if (node.name === 'base' && !this.options.domain) {
+ this.options.domain = attrs.href
+ } /* #ifndef APP-PLUS-NVUE */ else if (node.name === 'source' && parent && (parent.name === 'video' || parent.name === 'audio') && attrs.src) {
+ // 设置 source 标签(仅父节点为 video 或 audio 时有效)
+ parent.src.push(attrs.src)
+ } /* #endif */
+ return
+ }
+
+ // 解析 style
+ const styleObj = this.parseStyle(node)
+
+ // 处理图片
+ if (node.name === 'img') {
+ if (attrs.src) {
+ // 标记 webp
+ if (attrs.src.includes('webp')) {
+ node.webp = 'T'
+ }
+ // data url 图片如果没有设置 original-src 默认为不可预览的小图片
+ if (attrs.src.includes('data:') && !attrs['original-src']) {
+ attrs.ignore = 'T'
+ }
+ if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
+ for (let i = this.stack.length; i--;) {
+ const item = this.stack[i]
+ if (item.name === 'a') {
+ node.a = item.attrs
+ }
+ if (item.name === 'table' && !node.webp && !attrs.src.includes('cloud://')) {
+ if (!styleObj.display || styleObj.display.includes('inline')) {
+ node.t = 'inline-block'
+ } else {
+ node.t = styleObj.display
+ }
+ styleObj.display = undefined
+ }
+ // #ifndef H5 || APP-PLUS
+ const style = item.attrs.style || ''
+ if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || parseInt(styleObj.width) > 100)) {
+ styleObj.width = '100% !important'
+ styleObj.height = ''
+ for (let j = i + 1; j < this.stack.length; j++) {
+ this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '')
+ }
+ } else if (style.includes('flex') && styleObj.width === '100%') {
+ for (let j = i + 1; j < this.stack.length; j++) {
+ const style = this.stack[j].attrs.style || ''
+ if (!style.includes(';width') && !style.includes(' width') && style.indexOf('width') !== 0) {
+ styleObj.width = ''
+ break
+ }
+ }
+ } else if (style.includes('inline-block')) {
+ if (styleObj.width && styleObj.width[styleObj.width.length - 1] === '%') {
+ item.attrs.style += ';max-width:' + styleObj.width
+ styleObj.width = ''
+ } else {
+ item.attrs.style += ';max-width:100%'
+ }
+ }
+ // #endif
+ item.c = 1
+ }
+ attrs.i = this.imgList.length.toString()
+ let src = attrs['original-src'] || attrs.src
+ // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
+ if (this.imgList.includes(src)) {
+ // 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
+ let i = src.indexOf('://')
+ if (i !== -1) {
+ i += 3
+ let newSrc = src.substr(0, i)
+ for (; i < src.length; i++) {
+ if (src[i] === '/') break
+ newSrc += Math.random() > 0.5 ? src[i].toUpperCase() : src[i]
+ }
+ newSrc += src.substr(i)
+ src = newSrc
+ }
+ }
+ // #endif
+ this.imgList.push(src)
+ if (!node.t) {
+ this.imgList._unloadimgs += 1
+ }
+ // #ifdef H5 || APP-PLUS
+ if (this.options.lazyLoad) {
+ attrs['data-src'] = attrs.src
+ attrs.src = undefined
+ }
+ // #endif
+ }
+ }
+ if (styleObj.display === 'inline') {
+ styleObj.display = ''
+ }
+ // #ifndef APP-PLUS-NVUE
+ if (attrs.ignore) {
+ styleObj['max-width'] = styleObj['max-width'] || '100%'
+ attrs.style += ';-webkit-touch-callout:none'
+ }
+ // #endif
+ // 设置的宽度超出屏幕,为避免变形,高度转为自动
+ if (parseInt(styleObj.width) > windowWidth) {
+ styleObj.height = undefined
+ }
+ // 记录是否设置了宽高
+ if (!isNaN(parseInt(styleObj.width))) {
+ node.w = 'T'
+ }
+ if (!isNaN(parseInt(styleObj.height)) && (!styleObj.height.includes('%') || (parent && (parent.attrs.style || '').includes('height')))) {
+ node.h = 'T'
+ }
+ } else if (node.name === 'svg') {
+ siblings.push(node)
+ this.stack.push(node)
+ this.popNode()
+ return
+ }
+ for (const key in styleObj) {
+ if (styleObj[key]) {
+ attrs.style += `;${key}:${styleObj[key].replace(' !important', '')}`
+ }
+ }
+ attrs.style = attrs.style.substr(1) || undefined
+ // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
+ if (!attrs.style) {
+ delete attrs.style
+ }
+ // #endif
+ } else {
+ if ((node.name === 'pre' || ((attrs.style || '').includes('white-space') && attrs.style.includes('pre'))) && this.pre !== 2) {
+ this.pre = node.pre = 1
+ }
+ node.children = []
+ this.stack.push(node)
+ }
+
+ // 加入节点树
+ siblings.push(node)
+}
+
+/**
+ * @description 解析到标签结束
+ * @param {String} name 标签名
+ * @private
+ */
+Parser.prototype.onCloseTag = function (name) {
+ // 依次出栈到匹配为止
+ name = this.xml ? name : name.toLowerCase()
+ let i
+ for (i = this.stack.length; i--;) {
+ if (this.stack[i].name === name) break
+ }
+ if (i !== -1) {
+ while (this.stack.length > i) {
+ this.popNode()
+ }
+ } else if (name === 'p' || name === 'br') {
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
+ siblings.push({
+ name,
+ attrs: {
+ class: tagSelector[name] || '',
+ style: this.tagStyle[name] || ''
+ }
+ })
+ }
+}
+
+/**
+ * @description 处理标签出栈
+ * @private
+ */
+Parser.prototype.popNode = function () {
+ const node = this.stack.pop()
+ let attrs = node.attrs
+ const children = node.children
+ const parent = this.stack[this.stack.length - 1]
+ const siblings = parent ? parent.children : this.nodes
+
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
+ // 获取标题
+ if (node.name === 'title' && children.length && children[0].type === 'text' && this.options.setTitle) {
+ uni.setNavigationBarTitle({
+ title: children[0].text
+ })
+ }
+ siblings.pop()
+ return
+ }
+
+ if (node.pre && this.pre !== 2) {
+ // 是否合并空白符标识
+ this.pre = node.pre = undefined
+ for (let i = this.stack.length; i--;) {
+ if (this.stack[i].pre) {
+ this.pre = 1
+ }
+ }
+ }
+
+ const styleObj = {}
+
+ // 转换 svg
+ if (node.name === 'svg') {
+ if (this.xml > 1) {
+ // 多层 svg 嵌套
+ this.xml--
+ return
+ }
+ // #ifdef APP-PLUS-NVUE
+ (function traversal (node) {
+ if (node.name) {
+ // 调整 svg 的大小写
+ node.name = config.svgDict[node.name] || node.name
+ for (const item in node.attrs) {
+ if (config.svgDict[item]) {
+ node.attrs[config.svgDict[item]] = node.attrs[item]
+ node.attrs[item] = undefined
+ }
+ }
+ for (let i = 0; i < (node.children || []).length; i++) {
+ traversal(node.children[i])
+ }
+ }
+ })(node)
+ // #endif
+ // #ifndef APP-PLUS-NVUE
+ let src = ''
+ const style = attrs.style
+ attrs.style = ''
+ attrs.xmlns = 'http://www.w3.org/2000/svg';
+ (function traversal (node) {
+ if (node.type === 'text') {
+ src += node.text
+ return
+ }
+ const name = config.svgDict[node.name] || node.name
+ src += '<' + name
+ for (const item in node.attrs) {
+ const val = node.attrs[item]
+ if (val) {
+ src += ` ${config.svgDict[item] || item}="${val}"`
+ }
+ }
+ if (!node.children) {
+ src += '/>'
+ } else {
+ src += '>'
+ for (let i = 0; i < node.children.length; i++) {
+ traversal(node.children[i])
+ }
+ src += '' + name + '>'
+ }
+ })(node)
+ node.name = 'img'
+ node.attrs = {
+ src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
+ style,
+ ignore: 'T'
+ }
+ node.children = undefined
+ // #endif
+ this.xml = false
+ return
+ }
+
+ // #ifndef APP-PLUS-NVUE
+ // 转换 align 属性
+ if (attrs.align) {
+ if (node.name === 'table') {
+ if (attrs.align === 'center') {
+ styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'
+ } else {
+ styleObj.float = attrs.align
+ }
+ } else {
+ styleObj['text-align'] = attrs.align
+ }
+ attrs.align = undefined
+ }
+
+ // 转换 dir 属性
+ if (attrs.dir) {
+ styleObj.direction = attrs.dir
+ attrs.dir = undefined
+ }
+
+ // 转换 font 标签的属性
+ if (node.name === 'font') {
+ if (attrs.color) {
+ styleObj.color = attrs.color
+ attrs.color = undefined
+ }
+ if (attrs.face) {
+ styleObj['font-family'] = attrs.face
+ attrs.face = undefined
+ }
+ if (attrs.size) {
+ let size = parseInt(attrs.size)
+ if (!isNaN(size)) {
+ if (size < 1) {
+ size = 1
+ } else if (size > 7) {
+ size = 7
+ }
+ styleObj['font-size'] = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'xxx-large'][size - 1]
+ }
+ attrs.size = undefined
+ }
+ }
+ // #endif
+
+ // 一些编辑器的自带 class
+ if ((attrs.class || '').includes('align-center')) {
+ styleObj['text-align'] = 'center'
+ }
+
+ Object.assign(styleObj, this.parseStyle(node))
+
+ if (node.name !== 'table' && parseInt(styleObj.width) > windowWidth) {
+ styleObj['max-width'] = '100%'
+ styleObj['box-sizing'] = 'border-box'
+ }
+
+ // #ifndef APP-PLUS-NVUE
+ if (config.blockTags[node.name]) {
+ node.name = 'div'
+ } else if (!config.trustTags[node.name] && !this.xml) {
+ // 未知标签转为 span,避免无法显示
+ node.name = 'span'
+ }
+
+ if (node.name === 'a' || node.name === 'ad'
+ // #ifdef H5 || APP-PLUS
+ || node.name === 'iframe' // eslint-disable-line
+ // #endif
+ ) {
+ this.expose()
+ } else if (node.name === 'video') {
+ if ((styleObj.height || '').includes('auto')) {
+ styleObj.height = undefined
+ }
+ /* #ifdef APP-PLUS */
+ let str = ''
+ node.html = str
+ /* #endif */
+ } else if ((node.name === 'ul' || node.name === 'ol') && node.c) {
+ // 列表处理
+ const types = {
+ a: 'lower-alpha',
+ A: 'upper-alpha',
+ i: 'lower-roman',
+ I: 'upper-roman'
+ }
+ if (types[attrs.type]) {
+ attrs.style += ';list-style-type:' + types[attrs.type]
+ attrs.type = undefined
+ }
+ for (let i = children.length; i--;) {
+ if (children[i].name === 'li') {
+ children[i].c = 1
+ }
+ }
+ } else if (node.name === 'table') {
+ // 表格处理
+ // cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
+ let padding = parseFloat(attrs.cellpadding)
+ let spacing = parseFloat(attrs.cellspacing)
+ const border = parseFloat(attrs.border)
+ const bordercolor = styleObj['border-color']
+ const borderstyle = styleObj['border-style']
+ if (node.c) {
+ // padding 和 spacing 默认 2
+ if (isNaN(padding)) {
+ padding = 2
+ }
+ if (isNaN(spacing)) {
+ spacing = 2
+ }
+ }
+ if (border) {
+ attrs.style += `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}`
+ }
+ if (node.flag && node.c) {
+ // 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
+ styleObj.display = 'grid'
+ if (spacing) {
+ styleObj['grid-gap'] = spacing + 'px'
+ styleObj.padding = spacing + 'px'
+ } else if (border) {
+ // 无间隔的情况下避免边框重叠
+ attrs.style += ';border-left:0;border-top:0'
+ }
+
+ const width = [] // 表格的列宽
+ const trList = [] // tr 列表
+ const cells = [] // 保存新的单元格
+ const map = {}; // 被合并单元格占用的格子
+
+ (function traversal (nodes) {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].name === 'tr') {
+ trList.push(nodes[i])
+ } else {
+ traversal(nodes[i].children || [])
+ }
+ }
+ })(children)
+
+ for (let row = 1; row <= trList.length; row++) {
+ let col = 1
+ for (let j = 0; j < trList[row - 1].children.length; j++) {
+ const td = trList[row - 1].children[j]
+ if (td.name === 'td' || td.name === 'th') {
+ // 这个格子被上面的单元格占用,则列号++
+ while (map[row + '.' + col]) {
+ col++
+ }
+ let style = td.attrs.style || ''
+ let start = style.indexOf('width') ? style.indexOf(';width') : 0
+ // 提取出 td 的宽度
+ if (start !== -1) {
+ let end = style.indexOf(';', start + 6)
+ if (end === -1) {
+ end = style.length
+ }
+ if (!td.attrs.colspan) {
+ width[col] = style.substring(start ? start + 7 : 6, end)
+ }
+ style = style.substr(0, start) + style.substr(end)
+ }
+ // 设置竖直对齐
+ style += ';display:flex'
+ start = style.indexOf('vertical-align')
+ if (start !== -1) {
+ const val = style.substr(start + 15, 10)
+ if (val.includes('middle')) {
+ style += ';align-items:center'
+ } else if (val.includes('bottom')) {
+ style += ';align-items:flex-end'
+ }
+ } else {
+ style += ';align-items:center'
+ }
+ // 设置水平对齐
+ start = style.indexOf('text-align')
+ if (start !== -1) {
+ const val = style.substr(start + 11, 10)
+ if (val.includes('center')) {
+ style += ';justify-content: center'
+ } else if (val.includes('right')) {
+ style += ';justify-content: right'
+ }
+ }
+ style = (border ? `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}` + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? `;padding:${padding}px` : '') + ';' + style
+ // 处理列合并
+ if (td.attrs.colspan) {
+ style += `;grid-column-start:${col};grid-column-end:${col + parseInt(td.attrs.colspan)}`
+ if (!td.attrs.rowspan) {
+ style += `;grid-row-start:${row};grid-row-end:${row + 1}`
+ }
+ col += parseInt(td.attrs.colspan) - 1
+ }
+ // 处理行合并
+ if (td.attrs.rowspan) {
+ style += `;grid-row-start:${row};grid-row-end:${row + parseInt(td.attrs.rowspan)}`
+ if (!td.attrs.colspan) {
+ style += `;grid-column-start:${col};grid-column-end:${col + 1}`
+ }
+ // 记录下方单元格被占用
+ for (let rowspan = 1; rowspan < td.attrs.rowspan; rowspan++) {
+ for (let colspan = 0; colspan < (td.attrs.colspan || 1); colspan++) {
+ map[(row + rowspan) + '.' + (col - colspan)] = 1
+ }
+ }
+ }
+ if (style) {
+ td.attrs.style = style
+ }
+ cells.push(td)
+ col++
+ }
+ }
+ if (row === 1) {
+ let temp = ''
+ for (let i = 1; i < col; i++) {
+ temp += (width[i] ? width[i] : 'auto') + ' '
+ }
+ styleObj['grid-template-columns'] = temp
+ }
+ }
+ node.children = cells
+ } else {
+ // 没有使用合并单元格的表格通过 table 布局实现
+ if (node.c) {
+ styleObj.display = 'table'
+ }
+ if (!isNaN(spacing)) {
+ styleObj['border-spacing'] = spacing + 'px'
+ }
+ if (border || padding) {
+ // 遍历
+ (function traversal (nodes) {
+ for (let i = 0; i < nodes.length; i++) {
+ const td = nodes[i]
+ if (td.name === 'th' || td.name === 'td') {
+ if (border) {
+ td.attrs.style = `border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'};${td.attrs.style || ''}`
+ }
+ if (padding) {
+ td.attrs.style = `padding:${padding}px;${td.attrs.style || ''}`
+ }
+ } else if (td.children) {
+ traversal(td.children)
+ }
+ }
+ })(children)
+ }
+ }
+ // 给表格添加一个单独的横向滚动层
+ if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
+ const table = Object.assign({}, node)
+ node.name = 'div'
+ node.attrs = {
+ style: 'overflow:auto'
+ }
+ node.children = [table]
+ attrs = table.attrs
+ }
+ } else if ((node.name === 'td' || node.name === 'th') && (attrs.colspan || attrs.rowspan)) {
+ for (let i = this.stack.length; i--;) {
+ if (this.stack[i].name === 'table') {
+ this.stack[i].flag = 1 // 指示含有合并单元格
+ break
+ }
+ }
+ } else if (node.name === 'ruby') {
+ // 转换 ruby
+ node.name = 'span'
+ for (let i = 0; i < children.length - 1; i++) {
+ if (children[i].type === 'text' && children[i + 1].name === 'rt') {
+ children[i] = {
+ name: 'div',
+ attrs: {
+ style: 'display:inline-block;text-align:center'
+ },
+ children: [{
+ name: 'div',
+ attrs: {
+ style: 'font-size:50%;' + (children[i + 1].attrs.style || '')
+ },
+ children: children[i + 1].children
+ }, children[i]]
+ }
+ children.splice(i + 1, 1)
+ }
+ }
+ } else if (node.c) {
+ (function traversal (node) {
+ node.c = 2
+ for (let i = node.children.length; i--;) {
+ const child = node.children[i]
+ // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
+ if (child.name && (config.inlineTags[child.name] || ((child.attrs.style || '').includes('inline') && child.children)) && !child.c) {
+ traversal(child)
+ }
+ // #endif
+ if (!child.c || child.name === 'table') {
+ node.c = 1
+ }
+ }
+ })(node)
+ }
+
+ if ((styleObj.display || '').includes('flex') && !node.c) {
+ for (let i = children.length; i--;) {
+ const item = children[i]
+ if (item.f) {
+ item.attrs.style = (item.attrs.style || '') + item.f
+ item.f = undefined
+ }
+ }
+ }
+ // flex 布局时部分样式需要提取到 rich-text 外层
+ const flex = parent && ((parent.attrs.style || '').includes('flex') || (parent.attrs.style || '').includes('grid'))
+ // #ifdef MP-WEIXIN
+ // 检查基础库版本 virtualHost 是否可用
+ && !(node.c && wx.getNFCAdapter) // eslint-disable-line
+ // #endif
+ // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
+ && !node.c // eslint-disable-line
+ // #endif
+ if (flex) {
+ node.f = ';max-width:100%'
+ }
+
+ if (children.length >= 50 && node.c && !(styleObj.display || '').includes('flex')) {
+ mergeNodes(children)
+ }
+ // #endif
+
+ for (const key in styleObj) {
+ if (styleObj[key]) {
+ const val = `;${key}:${styleObj[key].replace(' !important', '')}`
+ /* #ifndef APP-PLUS-NVUE */
+ if (flex && ((key.includes('flex') && key !== 'flex-direction') || key === 'align-self' || key.includes('grid') || styleObj[key][0] === '-' || (key.includes('width') && val.includes('%')))) {
+ node.f += val
+ if (key === 'width') {
+ attrs.style += ';width:100%'
+ }
+ } else /* #endif */ {
+ attrs.style += val
+ }
+ }
+ }
+ attrs.style = attrs.style.substr(1) || undefined
+ // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
+ for (const key in attrs) {
+ if (!attrs[key]) {
+ delete attrs[key]
+ }
+ }
+ // #endif
+}
+
+/**
+ * @description 解析到文本
+ * @param {String} text 文本内容
+ */
+Parser.prototype.onText = function (text) {
+ if (!this.pre) {
+ // 合并空白符
+ let trim = ''
+ let flag
+ for (let i = 0, len = text.length; i < len; i++) {
+ if (!blankChar[text[i]]) {
+ trim += text[i]
+ } else {
+ if (trim[trim.length - 1] !== ' ') {
+ trim += ' '
+ }
+ if (text[i] === '\n' && !flag) {
+ flag = true
+ }
+ }
+ }
+ // 去除含有换行符的空串
+ if (trim === ' ') {
+ if (flag) return
+ // #ifdef VUE3
+ else {
+ const parent = this.stack[this.stack.length - 1]
+ if (parent && parent.name[0] === 't') return
+ }
+ // #endif
+ }
+ text = trim
+ }
+ const node = Object.create(null)
+ node.type = 'text'
+ // #ifdef (MP-BAIDU || MP-ALIPAY || MP-TOUTIAO) && VUE3
+ node.attrs = {}
+ // #endif
+ node.text = decodeEntity(text)
+ if (this.hook(node)) {
+ // #ifdef MP-WEIXIN
+ if (this.options.selectable === 'force' && system.includes('iOS') && !uni.canIUse('rich-text.user-select')) {
+ this.expose()
+ }
+ // #endif
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
+ siblings.push(node)
+ }
+}
+
+/**
+ * @description html 词法分析器
+ * @param {Object} handler 高层处理器
+ */
+function Lexer (handler) {
+ this.handler = handler
+}
+
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+Lexer.prototype.parse = function (content) {
+ this.content = content || ''
+ this.i = 0 // 标记解析位置
+ this.start = 0 // 标记一个单词的开始位置
+ this.state = this.text // 当前状态
+ for (let len = this.content.length; this.i !== -1 && this.i < len;) {
+ this.state()
+ }
+}
+
+/**
+ * @description 检查标签是否闭合
+ * @param {String} method 如果闭合要进行的操作
+ * @returns {Boolean} 是否闭合
+ * @private
+ */
+Lexer.prototype.checkClose = function (method) {
+ const selfClose = this.content[this.i] === '/'
+ if (this.content[this.i] === '>' || (selfClose && this.content[this.i + 1] === '>')) {
+ if (method) {
+ this.handler[method](this.content.substring(this.start, this.i))
+ }
+ this.i += selfClose ? 2 : 1
+ this.start = this.i
+ this.handler.onOpenTag(selfClose)
+ if (this.handler.tagName === 'script') {
+ this.i = this.content.indexOf('', this.i)
+ if (this.i !== -1) {
+ this.i += 2
+ this.start = this.i
+ }
+ this.state = this.endTag
+ } else {
+ this.state = this.text
+ }
+ return true
+ }
+ return false
+}
+
+/**
+ * @description 文本状态
+ * @private
+ */
+Lexer.prototype.text = function () {
+ this.i = this.content.indexOf('<', this.i) // 查找最近的标签
+ if (this.i === -1) {
+ // 没有标签了
+ if (this.start < this.content.length) {
+ this.handler.onText(this.content.substring(this.start, this.content.length))
+ }
+ return
+ }
+ const c = this.content[this.i + 1]
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ // 标签开头
+ if (this.start !== this.i) {
+ this.handler.onText(this.content.substring(this.start, this.i))
+ }
+ this.start = ++this.i
+ this.state = this.tagName
+ } else if (c === '/' || c === '!' || c === '?') {
+ if (this.start !== this.i) {
+ this.handler.onText(this.content.substring(this.start, this.i))
+ }
+ const next = this.content[this.i + 2]
+ if (c === '/' && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
+ // 标签结尾
+ this.i += 2
+ this.start = this.i
+ this.state = this.endTag
+ return
+ }
+ // 处理注释
+ let end = '-->'
+ if (c !== '!' || this.content[this.i + 2] !== '-' || this.content[this.i + 3] !== '-') {
+ end = '>'
+ }
+ this.i = this.content.indexOf(end, this.i)
+ if (this.i !== -1) {
+ this.i += end.length
+ this.start = this.i
+ }
+ } else {
+ this.i++
+ }
+}
+
+/**
+ * @description 标签名状态
+ * @private
+ */
+Lexer.prototype.tagName = function () {
+ if (blankChar[this.content[this.i]]) {
+ // 解析到标签名
+ this.handler.onTagName(this.content.substring(this.start, this.i))
+ while (blankChar[this.content[++this.i]]);
+ if (this.i < this.content.length && !this.checkClose()) {
+ this.start = this.i
+ this.state = this.attrName
+ }
+ } else if (!this.checkClose('onTagName')) {
+ this.i++
+ }
+}
+
+/**
+ * @description 属性名状态
+ * @private
+ */
+Lexer.prototype.attrName = function () {
+ let c = this.content[this.i]
+ if (blankChar[c] || c === '=') {
+ // 解析到属性名
+ this.handler.onAttrName(this.content.substring(this.start, this.i))
+ let needVal = c === '='
+ const len = this.content.length
+ while (++this.i < len) {
+ c = this.content[this.i]
+ if (!blankChar[c]) {
+ if (this.checkClose()) return
+ if (needVal) {
+ // 等号后遇到第一个非空字符
+ this.start = this.i
+ this.state = this.attrVal
+ return
+ }
+ if (this.content[this.i] === '=') {
+ needVal = true
+ } else {
+ this.start = this.i
+ this.state = this.attrName
+ return
+ }
+ }
+ }
+ } else if (!this.checkClose('onAttrName')) {
+ this.i++
+ }
+}
+
+/**
+ * @description 属性值状态
+ * @private
+ */
+Lexer.prototype.attrVal = function () {
+ const c = this.content[this.i]
+ const len = this.content.length
+ if (c === '"' || c === "'") {
+ // 有冒号的属性
+ this.start = ++this.i
+ this.i = this.content.indexOf(c, this.i)
+ if (this.i === -1) return
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
+ } else {
+ // 没有冒号的属性
+ for (; this.i < len; this.i++) {
+ if (blankChar[this.content[this.i]]) {
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
+ break
+ } else if (this.checkClose('onAttrVal')) return
+ }
+ }
+ while (blankChar[this.content[++this.i]]);
+ if (this.i < len && !this.checkClose()) {
+ this.start = this.i
+ this.state = this.attrName
+ }
+}
+
+/**
+ * @description 结束标签状态
+ * @returns {String} 结束的标签名
+ * @private
+ */
+Lexer.prototype.endTag = function () {
+ const c = this.content[this.i]
+ if (blankChar[c] || c === '>' || c === '/') {
+ this.handler.onCloseTag(this.content.substring(this.start, this.i))
+ if (c !== '>') {
+ this.i = this.content.indexOf('>', this.i)
+ if (this.i === -1) return
+ }
+ this.start = ++this.i
+ this.state = this.text
+ } else {
+ this.i++
+ }
+}
+
+export default Parser
diff --git a/uni_modules/mp-html/package.json b/uni_modules/mp-html/package.json
new file mode 100644
index 0000000..982c9af
--- /dev/null
+++ b/uni_modules/mp-html/package.json
@@ -0,0 +1,76 @@
+{
+ "id": "mp-html",
+ "displayName": "mp-html 富文本组件【全端支持,支持编辑、latex等扩展】",
+ "version": "v2.4.1",
+ "description": "一个强大的富文本组件,高效轻量,功能丰富",
+ "keywords": [
+ "富文本",
+ "编辑器",
+ "html",
+ "rich-text",
+ "editor"
+ ],
+ "repository": "https://github.com/jin-yufeng/mp-html",
+ "dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/mp-html",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "u",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "y",
+ "联盟": "y"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js b/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
new file mode 100644
index 0000000..1d986bd
--- /dev/null
+++ b/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
@@ -0,0 +1 @@
+"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){a[1]&&(this.src=a[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(){window.unloadimgs-=1,0===window.unloadimgs&&uni.postMessage({data:{action:"onReady"}})}function o(r,s,c){for(var d=0;d0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m
\ No newline at end of file