Initial commit

This commit is contained in:
admin
2025-12-08 14:39:07 +08:00
commit 9d4f78656b
782 changed files with 66418 additions and 0 deletions

View File

View File

@@ -0,0 +1,56 @@
# mp-html
> 一个强大的小程序富文本组件
![star](https://img.shields.io/github/stars/jin-yufeng/mp-html)
![forks](https://img.shields.io/github/forks/jin-yufeng/mp-html)
[![npm](https://img.shields.io/npm/v/mp-html)](https://www.npmjs.com/package/mp-html)
![downloads](https://img.shields.io/npm/dt/mp-html)
[![Coverage Status](https://coveralls.io/repos/github/jin-yufeng/mp-html/badge.svg?branch=master)](https://coveralls.io/github/jin-yufeng/mp-html?branch=master)
![license](https://img.shields.io/github/license/jin-yufeng/mp-html)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
## 📢 概况 :id=overview
显示动态 *html* 富文本是很多应用必要的需求,小程序平台不支持 *dom* 操作使得这成为一个难题,其自带的 *rich-text* 组件支持的标签少且屏蔽所有事件,难以实际应用。因此就有了这样一个能够便捷的在小程序平台上处理富文本的组件,还支持丰富的扩展功能。
## 📋 特性 :id=feature
- 支持在多个主流的小程序平台和 *uni-app* 中使用
- 支持丰富的标签(包括 *table*、*video*、*svg* 等)
- 支持丰富的事件效果(自动预览图片、链接处理等)
- 支持设置占位图(加载中、出错时、预览时)
- 支持锚点跳转、长按复制等丰富功能
- 支持大部分 *html* 实体
- 丰富的插件(关键词搜索、内容编辑、*latex* 公式 等)
- 效率高、容错性强且轻量化(*≈25KB**9KB gzipped*
查看 [功能介绍](overview/feature) 了解更多
## 🎉 使用案例 :id=case
| [官方示例](https://github.com/jin-yufeng/mp-html-demo) | 欢喜商城 | 多么生活 | 食法查 | 微慕 | 古典文学名著阅读 |
|:---:|:---:|:---:|:---:|:---:|:---:|
| ![富文本插件](assets/case/富文本插件.jpg) | ![欢喜商城](assets/case/欢喜商城.png) | ![多么生活](assets/case/多么生活.jpg) | ![食法查](assets/case/食法查.png) | ![微慕](assets/case/微慕.jpg) | ![古典文学名著阅读](assets/case/古典文学名著阅读.jpg) |
| 科学复习 | [程序员技术之旅](https://github.com/fendoudebb/z-blog-wx) | 典典博客 | 优秀笔记 | 365 刷题 | 同城共享书 |
|:---:|:---:|:---:|:---:|:---:|:---:|
| ![科学复习](assets/case/科学复习.png) | ![程序员技术之旅](assets/case/程序员技术之旅.jpg) | ![典典博客](assets/case/典典博客.jpg) | ![优秀笔记](assets/case/优秀笔记.jpg) | ![365刷题](assets/case/365刷题.jpg) | ![同城共享书](assets/case/同城共享书.jpg) |
| [技术源 share](https://github.com/wangsrGit119/mini-blog-halo) | 你的代码写的真棒 | 谛否 | 小莫唐尼 | [模版演示](https://github.com/zhihuifanqiechaodan/miniprogram-template) | AI瓦力 |
|:---:|:---:|:---:|:---:|:---:|:---:|
| ![技术源share](assets/case/技术源share.jpg) | ![你的代码写的真棒](assets/case/你的代码写的真棒.jpg) | ![谛否](assets/case/谛否.jpg) | ![小莫唐尼](assets/case/小莫唐尼.png) | ![MiniProgram模版演示](assets/case/MiniProgram模版演示.jpg) | ![AI瓦力](assets/case/AI瓦力.jpg) |
以上排名不分先后,更多可见 [使用案例收集](https://github.com/jin-yufeng/mp-html/issues/27)(欢迎添加)
## 🎈 联系与支持 :id=sponsor
![group](assets/group.jpg)
![支持](assets/sponsor.png)
## 📃 许可 :id=license
[MIT License](https://github.com/jin-yufeng/mp-html/blob/master/LICENSE)
?> 您可以免费的使用(包括商用)、复制或修改本组件
!> 在用于生产环境前,务必进行仔细测试,由本组件 *bug* 带来的损失概不负责
---
Powered by docsify

View File

@@ -0,0 +1,12 @@
![logo](assets/logo/logo.png)
# mp-html <small>2.5.1</small>
> 一个强大的小程序富文本组件
- 全面的标签支持
- 多平台使用支持
- 丰富的附加功能
[GitHub](https://github.com/jin-yufeng/mp-html)
[快速开始](/overview/quickstart)

View File

@@ -0,0 +1,20 @@
- 概览
- [🚀 快速开始](overview/quickstart)
- [🎉 功能介绍](overview/feature)
- 基本使用
- [🔨 属性](basic/prop)
- [📫 事件](basic/event)
- 进阶使用
- [🔎 api](advanced/api)
- [📌 插件](advanced/plugin)
- [🔧 二次开发](advanced/develop)
- 疑问解答
- [📘 常见问题](question/faq)
- [📩 反馈](question/feedback)
- [📝 贡献指南](question/contribution)
- 更新日志
- [📖 更新日志](changelog/changelog)

View File

@@ -0,0 +1,230 @@
# 🔎 api
组件的实例上挂载了一些实用的 *api* 方法可供调用
## 获取组件实例 :id=getCompent
- *uni-app*
```vue
<template>
<view>
<mp-html ref="article" />
</view>
</template>
<script>
export default {
onLoad () {
var ctx = this.$refs.article
}
}
</script>
```
- 支付宝小程序
需开启 [component2](https://opendocs.alipay.com/mini/framework/component-ref) 模式
```axml
<mp-html ref="article">
```
```javascript
Page({
article (ctx) {
// 获得组件实例
}
})
```
- 其他小程序平台
```wxml
<mp-html id="article" />
```
```javascript
Page({
onLoad () {
// 微信、QQ、百度
var ctx = this.selectComponent('#article')
// 头条
this.selectComponent('#article', ctx => {
})
}
})
```
## in
功能:将锚点跳转的范围限定在一个 *scroll-view*(需要开启纵向滚动)内
输入值:
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|:---:|:---:|:---:|:---:|---|
| page | object | 是 | - | scroll-view 标签所在页面实例 |
| selector | string | 是 | - | scroll-view 标签 的选择器 |
| scrollTop | string | 是 | - | scroll-view 标签 scrollTop 属性绑定的变量名 |
返回值:无
示例:
```wxml
<scroll-view id="scroll" style="height:300px" scroll-top="{{top}}" scroll-y scroll-with-animation>
<mp-html id="article" content="{{html}}" />
</scroll-view>
```
```javascript
Page({
onLoad () {
// ctx 为组件实例
ctx.in(this, '#scroll', 'top')
}
})
```
!> 在 *scroll-view* 中使用时需要注意如果使用了视频,需要保证该平台的 *video* 标签支持同层渲染
## navigateTo
功能:锚点跳转
前提是 [use-anchor](basic/prop#use-anchor) 属性的值为 *true*
必须在 [load](basic/event#load) 事件触发后使用,建议在 [ready](basic/event#ready) 事件触发后使用以保证跳转位置准确
输入值:
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|:---:|:---:|:---:|:---:|---|
| id | string | 否 | - | 要跳转的锚点 id为空则跳转到开头 |
| offset | number | 否 | 0 | 跳转位置的偏移量 |
返回值:**Promise**
该方法中传入的 *offset* 优先级高于 [use-anchor](basic/prop#use-anchor) 属性
示例:
```javascript
Page({
ready () {
// ctx 为组件实例
ctx.navigateTo('anchor').then(() => {
console.log('跳转成功')
}).catch(err => {
console.log('跳转失败:', err)
})
}
})
```
## getText
功能:获取文本内容
必须在 [load](basic/event#load) 事件触发后使用
输入值:无
返回值:**String**
## getRect
功能:获取富文本内容的位置和大小
如果开启了 [lazy-load](basic/prop#lazy-load)[ready](basic/event#ready) 事件返回的不是最终大小,可通过此方法获得实时的大小和位置信息
输入值:无
返回值:**Promise**
示例:
```javascript
Page({
getRect () {
// ctx 为组件实例
ctx.getRect().then(rect => {
console.log(rect) // boundingClientRect 信息
}).catch(err => {
console.log('获取失败', err)
})
}
})
```
!> 该方法有小概率可能获取失败,需要做好错误处理
## setContent
功能:设置富文本内容
此方法的功能与 [content](basic/prop#content) 属性基本一致,但此方法的设置不需要经过视图层且可以从尾部追加
输入值:
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|:---:|:---:|:---:|:---:|---|
| content | string | 是 | - | 要渲染的 html 字符串 |
| append | boolean | 否 | false | 是否从尾部追加 |
返回值:无
!> 调用此方法会触发 [load](basic/event#load) 和 [ready](basic/event#ready) 事件,请勿在事件处理函数中调用,否则可能陷入死循环
## imgList
功能:获取所有图片的数组
该数组用于图片预览,对其进行修改可以在自动预览时生效(如修改为高清图链接或转存 *base64*
!> 这是一个属性,不是一个函数
请不要增删此数组(可以修改),否则在自动预览时可能出现问题
```javascript
Page({
load () {
// ctx 为组件实例
var cover = ctx.imgList[0] // 首张图可以作为转发封面图
ctx.imgList.forEach((src, i, array) => {
console.log(src)
// 替换为高清图链接
array[i] = src.replace('thumb', '')
// 转存 base64 便于预览
var fs = wx.getFileSystemManager && wx.getFileSystemManager()
var info = src.match(/data:image\/(\S+?);(\S+?),(.+)/)
if (!info) return
var filePath = `${wx.env.USER_DATA_PATH}/${Date.now()}.${info[1]}`
fs && fs.writeFile({
filePath,
data: info[3],
encoding: info[2],
success: () => array[i] = filePath
})
})
}
})
```
## pauseMedia
?> [2.2.2](changelog/changelog#v222) 版本起支持
功能:暂停正在播放的视频或音频
?> 和 [play](basic/event#play) 事件配合可以实现与页面中其他音视频进行互斥播放
输入值:无
返回值:无
示例:
```javascript
Page({
onHide () {
// ctx 为组件实例
ctx.pauseMedia() // 页面跳转或隐藏时暂停播放
}
})
```
## setPlaybackRate
?> [2.4.0](changelog/changelog#v240) 版本起支持
功能:设置音视频的播放速率
输入值:
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|:---:|:---:|:---:|:---:|---|
| rate | number | 是 | - | 播放速率,一般支持 0.5~2.0 |
返回值:无
示例:
```javascript
Page({
// 点击设置速率按钮
setPlaybackRate () {
wx.showActionSheet({
itemList: ['0.5', '1.0', '1.25', '1.5', '2.0'],
success: res => {
const rate = [0.5, 1.0, 1.25, 1.5, 2.0][res.tapIndex]
// ctx 为组件实例
ctx.setPlaybackRate(rate)
}
})
}
})
```

View File

@@ -0,0 +1,114 @@
# 二次开发 :id=develop
## 📣 说明 :id=notice
二次开发请在 *src* 目录下进行修改,修改完成后可通过下述方法自动生成各平台的代码包
为方便维护,本项目原生包多个平台共用一套源代码,在编写时直接按照微信端的写法进行编写即可,[生成代码包](#pack) 时会自动进行转换
自动转换已经抹平了大部分平台之间的差异(文件后缀名、*api* 格式等),需要注意的是 **访问组件的属性** 时,请通过 *this.properties* 访问而不是 *this.data*,因为在支付宝平台中两者不互通
个别问题可以自行修改 *tools/converter.js* 进行处理
附项目结构:
```
├─dev生成的各平台示例项目
├─dist生成的各平台代码包
│ ├─mp-alipay
│ ├─mp-baidu
│ ├─mp-qq
│ ├─mp-toutiao
│ ├─mp-weixin
│ └─uni-app
├─docs文档由 docsify 生成)
├─plugins插件源代码
├─src组件源代码
│ ├─miniprogram原生包源代码
│ └─uni-appuni-app 包源代码)
├─test测试代码
├─tools构建工具
│ ├─demo示例项目源代码
│ │ ├─miniprogram原生平台示例项目
│ │ └─uni-appuni-app 平台示例项目)
| ├─config.js构建工具的配置项
| ├─converter.js将微信端的代码转换到各个平台
| ├─ifdef.js处理条件编译
| ├─minifier.js处理 json 和 wxs 的压缩)
| └─plugin.js处理插件构建
├─.eslintrc.jsoneslint 配置)
├─.stylelintrc.jsonstylelint 配置)
├─gulpfile.jsgulp 生成文件)
├─LICENSE许可证 MIT
└─package.json项目配置
```
?> 对于较复杂的修改,如果能通过 [编写插件](advanced/plugin#develop) 方式实现更推荐插件方式,这样在组件包升级的时候便于维护和管理
## 🎈 条件编译 :id=ifdef
不同平台之间一些差异的地方可能无法简单的通过替换解决,因此本项目中引入了一种条件编译机制解决平台差异,可在修改时加以利用(条件编译是指在生成包的过程中就仅保留本平台需要的代码,与运行过程中的 *if* 判断不同)
方式 *1*(适用于 *js*、*wxml*、*wxss* 文件)
仅在某平台下需要使用的代码放在两个注释(各种注释格式皆可)之间即可,示例:
```javascript
// #ifdef MP-WEIXIN
console.log('这是微信平台')
// #endif
// #ifndef MP-WEIXIN
console.log('这不是微信平台')
// #endif
```
方式 *2*(适用于 *wxml* 文件)
对于仅在某一平台使用的属性,可在属性名前加 *平台名:* ,示例:
```wxml
<!-- show-menu-by-longpress 属性将仅被生成到微信包中 -->
<image mp-weixin:show-menu-by-longpress="xxx" />
```
说明:
1. 可用的平台名称:*mp-weixin*, *mp-qq*, *mp-baidu*, *mp-alipay*, *mp-toutiao*(不区分大小写)
2. *#if(n)def**#endif* 必须成对出现,否则会报错(可以多层嵌套)
3. 如果编译过程中发现问题可以自行修改 *tools/ifdef.js* 进行处理
## 📦 生成组件包 :id=pack
修改完成后,可按以下步骤生成新的组件包
*mp-html* 文件夹下执行:
?> 以下命令需要在组件包根目录下执行,即包含 [package.json](https://github.com/jin-yufeng/mp-html/blob/master/package.json) 的目录(如果通过 *npm* 获取就是 *node_modules/mp-html*
1. 安装依赖
```bash
# 通过 npm 安装
npm install
# 或通过 yarn 安装
yarn
```
2. 生成代码包到 *dist* 文件夹
```bash
# 生成微信包到 dist/mp-weixin
npm run build:weixin
# 生成 qq 包到 dist/mp-qq
npm run build:qq
# 生成百度包到 dist/mp-baidu
npm run build:baidu
# 生成支付宝包到 dist/mp-alipay
npm run build:alipay
# 生成头条包到 dist/mp-toutiao
npm run build:toutiao
# 生成 uni-app 包到 dist/uni-app
npm run build:uni-app
# 生成所有包
npm run build
```
?> 如需修改打包过程中的配置(*babel*, *uglifyJs* 等),可以对 *tools/config.js* 进行修改
## 🔦 检查和测试 :id=test
假设已安装好依赖
```bash
npm run lint # eslint 检查
npm run lintcss # stylelint 检查
npm run lintcss --fix # 检查并修复
npm run test # 执行 jest 测试
npm run coverage # 测试代码覆盖率
```
可以向 *test* 目录下添加新的测试用例进行测试

View File

@@ -0,0 +1,488 @@
# 📌 插件 :id=plugin
> 可以在这里选择需要的插件以实现更加丰富的功能
## 使用插件 :id=use
!> 直接将插件文件夹拷贝到组件包中无法生效,请通过以下方式生成包含扩展的组件包
#### 小程序方式
!> 该方式暂不可用
?> 该方式适合不熟悉 *npm* 的用户
1. 通过 [小程序方式](overview/quickstart#mp) 获取包含扩展插件的组件包
2. 将下载的组件包解压,原生小程序复制到 *components* 目录下,*uni-app* 复制到项目根目录下,按照源码方式引入即可,详见 [引入方式](overview/quickstart#use)
#### npm 方式
1. 获取完整的组件包
通过 [npm](overview/quickstart#npm) 或 [git](overview/quickstart#git) 等方式获取 **包含完整项目** 的组件包(注意从 *uni-app* 的插件市场中导入的包中仅包含构建后的组件,**不包含** 构建工具和插件)
![step1](../assets/tutorials/01.png)
2. 选择需要的插件
参考下方插件使用说明,确定要使用的插件,将其名称填入 [tools/config.js](https://github.com/jin-yufeng/mp-html/blob/master/tools/config.js#L8) 中的 *plugins*
如果想仅在部分平台使用该插件,可以在该插件目录下的 *build.js**platform* 字段中填入需要的平台名称
![step2](../assets/tutorials/02.png)
3. 生成组件包
设置完成后,可通过项目提供的命令行工具生成新的组件包,具体见 [生成组件包](advanced/develop#pack)
![step3_1](../assets/tutorials/03.png)
![step3_2](../assets/tutorials/04.png)
4. 按照源码或 *npm* 方式引入构建后的组件包进行使用即可,详见 [引入方式](overview/quickstart#use)
## audio
功能:音乐播放器
大小:*≈4KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √(nvue 不支持) |
!> 百度小程序原生包在此 [问题](https://smartprogram.baidu.com/forum/topic/show/125787) 未解决前无法使用
说明:
在大多数小程序平台,*audio* 标签已被废弃或无法使用,本插件可以代替 *audio* 标签播放音乐,并实现以下优化:
1. [pause-video](basic/prop#pause-video) 属性也可以应用于音频,即播放一个音视频时可以自动暂停其他正在播放的音视频
2. 增加了一个可以拖动的进度条
3. 组件大小可以根据页面宽度自动调整
4. 支持 *autoplay* 属性
5. 播放被后台打断时,页面显示后自动继续播放
基础库要求:
支付宝 *1.23.4+* ,其余平台满足 [最低要求](question/faq#lib) 即可
*5* 条仅微信 *2.2.3+* 、*QQ*、百度支持
?> 如果希望页面上使用本组件,组件的路径为 *path/to/mp-html/audio/audio*
属性和事件基本同 *audio* 组件,组件实例上提供了 *setSrc*、*play*、*seek*、*pause*、*stop* 方法可供控制播放状态
## editable
功能:富文本编辑
下表列出了本插件与原生 *editor* 组件的功能差异,可按需选用
| 组件 | 优点 | 缺点 |
|:---:|:---:|:---:|
| 原生 *editor* | 底层通过 *contenteditable* 实现,编辑流畅 | 支持标签少(不支持音视频、表格以及 *section* 等常用标签)、部分小程序平台不支持或低版本不兼容 |
| 本插件 | 支持标签全面、支持平台全面 | 编辑灵活性不够强 |
大小:*≈17.5KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √(nvue 不支持) |
##### 示例项目 :id=editable_demo
微信小程序点击 [代码片段](https://developers.weixin.qq.com/s/S2ZpZDm87fQP) 即可在微信开发者工具中导入;*uni-app* 下载 [示例项目](https://mp-html.oss-cn-hangzhou.aliyuncs.com/editable.zip) 在 *HBuilder X* 中打开即可体验;注意示例项目中不一定包含最新版本,仅供参考使用方法
?> 也可以参考示例小程序 [源代码](https://github.com/jin-yufeng/mp-html-demo)
说明:
引入本插件后,会给组件添加以下属性:
| 属性名 | 类型 | 默认值 | 说明 |
|:---:|:---:|:---:|:---:|
| editable | Boolean | false | 是否开启内容编辑 |
| placeholder | String | 请输入 | 输入框为空时占位符([2.1.0+](changelog/changelog#v210) |
?> [2.5.0](changelog/changelog#v250) 版本起支持将 *editable* 属性设置为 *"simple"* 来开启简易模式,简易模式下,点击文字内容直接进入编辑,不再弹出操作菜单栏和方框
添加以下事件:
| 事件名 | 触发时机 | 用途 |
|:---:|:---:|:---:|
| remove[2.2.0+](changelog/changelog#v220) | 删除图片/视频/音频标签时 | 删除已上传的线上文件 |
支持以下操作:
| 类型 | 操作 |
|:---:|:---:|
| 文本 | 修改 |
| 图片 | 更换链接、调整宽度、设置成超链接([2.0.4+](changelog/changelog#v204))、设置预览图链接、禁用预览、删除 |
| 链接 | 更换链接、删除 |
| 音视频 | 设置封面、设置循环播放、设置自动播放([2.2.0+](changelog/changelog#v220))、删除 |
| 普通标签 | 设置字体大小、颜色([2.4.2+](changelog/changelog#v242))、斜体、粗体、下划线([2.0.4+](changelog/changelog#v204))、居中、缩进、删除 |
?> [2.2.1](changelog/changelog#v221) 版本起所有标签支持上下移动操作,但仅限同级标签间移动,即在有同级标签且非第一个(或最后一个)时可以上移(或下移)
?> 在支付宝小程序中使用时需要在页面样式中添加 *page { position: relative; }* 避免 *tooltip* 错位
?> 菜单项可以通过编辑 *plugins/editable/config.js* 进行修改,仅可以删减或调整顺序,添加或更名无效(颜色设置除外)
[组件实例](advanced/api#getCompent) 上提供了以下方法(*editable* 属性为 *true* 时才可以调用):
| 名称 | 功能 |
|:---:|:---:|
| undo | 撤销一个操作 |
| redo | 重做一个操作 |
| insertHtml | 在光标处插入指定 html 内容([2.1.0+](changelog/changelog#v210) |
| insertImg | 在光标处插入一张图片 |
| insertTable(rows, cols) | 在光标处插入一个 rows 行 cols 列的表格([2.1.3+](changelog/changelog#v213) |
| insertVideo | 在光标处插入一个视频 |
| insertAudio | 在光标处插入一个音频 |
| insertLink | 在光标处插入一个链接 |
| insertText | 在光标处插入一段文本 |
| clear | 清空内容 |
| getContent | 获取编辑后的 html 内容 |
?> 考虑到不同场景下希望获取链接的方法不同,需要在初始时给组件设置一个 *getSrc* 方法(否则插入图片、音视频、链接或修改链接等操作无法使用),每次组件内需要链接时会调用此方法,开发者可在此方法中自行决定如何获取链接,返回 **线上地址** 即可(具体用法见下方示例)
[2.2.0](changelog/changelog#v220) 版本起设置了 [domain](basic/prop#domain) 属性时,返回的地址可以缺省主域名
编辑完成后,通过 *getContent* 方法获取编辑后的 *html*,最后将 *editable* 属性设置为 *false* 即可正常渲染
!> 点击保存按钮时,部分平台 *tap* 事件早于 *blur* 事件触发,直接获取内容可能导致无法获取当前编辑的文本内容,因此建议设置一个小的延时后获取(可参考下方示例,[详细](https://github.com/jin-yufeng/mp-html/issues/368)
示例:
```javascript
Page({
onLoad () {
// ctx 为组件实例,获取方法见上
/**
* @description 设置获取链接的方法
* @param {String} type 链接的类型img/video/audio/link
* @param {String} value 修改链接时,这里会传入旧值
* @returns {Promise} 返回线上地址2.2.0 版本起设置了 domain 属性时,可以缺省主域名)
* type 为 audio/video 时,可以返回一个源地址数组
* 2.1.3 版本起 type 为 audio 时,可以返回一个 object包含 src、name、author、poster 等字段
* 2.2.0 版本起 type 为 img 时,可以返回一个源地址数组,表示插入多张图片(修改链接时仅限一张)
*/
this.ctx.getSrc = (type, value) => {
return new Promise((resolve, reject) => {
// 以图片为例
if (type == 'img') {
wx.chooseImage({
count: value === undefined ? 9 : 1, // 2.2.0 版本起插入图片时支持多张(修改图片链接时仅限一张)
success: res => {
wx.showLoading({
title: '上传中'
});
(async ()=>{
const arr = []
for (let item of res.tempFilePaths) {
// 依次上传
const src = await upload(item)
arr.push(src)
}
return arr
})().then(res => {
wx.hideLoading()
resolve(res)
})
},
fail: reject
})
}
})
}
},
finishEdit () {
setTimeout(() => {
var html = ctx.getContent() // 获取编辑好的 html
// 上传 html
wx.request({
url: 'xxx',
data: {
html
},
success: () => {
this.setData({
editable: false // 结束编辑
})
}
})
}, 50)
}
})
```
注意事项:
不要在 *editable* 属性被设置为 *true* 前通过 [setContent](advanced/api#setContent) 方法(用 [content](basic/prop#content) 属性)设置内容,否则在切换为 *true* 后会变成空白
## emoji
功能:解析 *emoji*
大小:*≈3KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √ |
说明:
将形如 *[笑脸]* 的文本替换为 *emoji* 字符 😄
匹配模式可以通过修改 *reg* 变量实现
默认配置了 *177* 个常用的 *emoji* 小表情,可以自行按照需要修改 *data* 变量
?> 与 [editable](#editable) 插件共用时,导出编辑好的 *html* 内容,会将 *emoji* 字符编码为文本形式,便于存储
## highlight
功能:代码块高亮显示
大小:*≈16KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √ |
说明:
编辑 *plugins/highlight/config.js* ,可以选择是否需要以下功能:
- *copyByLongPress* 是否需要长按代码块时显示复制代码内容菜单(*uni-app nvue* 暂不支持)
- *showLanguageName* 是否在代码块右上角显示语言的名称
- *showLineNumber* 是否在左侧显示行号
!> 修改该配置后需要重新 [生成组件包](advanced/develop#pack),在构建后的组件包中修改配置无法生效
引入本插件后,*html* 中符合以下格式的 *pre* 将被高亮处理:
```html
<!-- pre 中内含一个 code并在 pre 或 code 的 class 中设置 language- -->
<pre><code class="language-css">p { color: red }</code></pre>
```
?> 与 [editable](#editable) 插件共用时,编辑状态下,不会进行高亮,可以直接修改代码文本
?> 本插件的高亮功能依赖于 [prismjs](https://prismjs.com/),默认配置中仅支持 *html*、*css*、*c-like*、*javascript* 语言和 *Tomorrow Night* 主题,如果需要更多语言或更换主题请前往 [官网](https://prismjs.com/download.html) 下载对应的 *prism.min.js**prism.css* 并替换 *plugins/highlight/* 目录下的文件(*prismjs* 的插件大多涉及 *dom* 操作,基本不可用,请勿选择)
## markdown
功能:渲染 *markdown*
大小:*≈37KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √ |
说明:
引入本插件后,会给组件添加一个 *markdown* 属性,将该属性设置为 *true* 后,即可通过 [content](basic/prop#content) 属性或 [setContent](advanced/api#setContent) 方法设置 *markdown* 内容即可
?> 若开启 [use-anchor](basic/prop#use-anchor) 属性,所有标题 `# xxx` 都会被设置为锚点,通过链接 `[xxx](#xxx)` 可以直接跳转
?> 本插件通过 [marked](https://github.com/markedjs/marked) 解析 *markdown* 文本,部分 *css* 摘选自 [github-markdown-css](https://github.com/sindresorhus/github-markdown-css)
?> 本插件可以和 [highlight](#highlight) 插件共用,实现 *markdown* 中代码块的高亮效果
## search
功能:关键词搜索
大小:*≈1.5KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √(nvue 不支持) |
说明:
引入后会在 [组件实例](advanced/api#getCompent) 上挂载一个 *search* 方法,用于关键词搜索
输入值
| 参数名 | 类型 | 默认值 | 说明 |
|:---:|:---:|:---:|---|
| key | String 或 RegExp | - | 要搜索的关键词,支持字符串和正则 |
| anchor | Boolean | false | 是否将搜索结果设置为锚点 |
| style | String | background-color:yellow | 标记搜索结果的样式 |
返回值:*Promise*
| 属性 | 类型 | 说明 |
|:---:|:---:|---|
| num | Number | 搜索结果数量 |
| highlight | Function(i, style='background-color:#FF9632') | 高亮第 i1 ~ num个结果将其样式设置为 style |
| jump | Function(i, offset) | 跳转到第 i1 ~ num个结果偏移量为 offsetanchor 为 true 才可用 |
示例:
```javascript
function search (key) {
// ctx 为组件实例
ctx.search(key, true).then(res => {
res.highlight(1)
res.jump(1, -50) // 高亮第 1 个结果并跳转到该位置,偏移量 -50
})
}
```
?> 具体用法可以参考示例小程序 [源代码](https://github.com/jin-yufeng/mp-html-demo)
附加说明:
1. 不传入 *key*(或为空)时即可取消搜索,取消所有的高亮,还原到原来的效果
2. 进行新的搜索时旧的搜索结果将被还原,旧的结果中的 *highlight* 等方法不再可用
3. 调用 *highlight* 方法高亮一个结果时,之前被高亮的结果会被还原,即始终只有一个结果被高亮
4. *key* 传入字符串时大小写敏感,如果要忽略大小写可以用正则的 *i*(字符串搜索效率高于正则)
5. 设置 *anchor**true* 会一定程度上降低效率,非必要不要开启
6. 暂不支持跨标签搜索,即只有一个文本节点内包含整个关键词才能被搜索到
## style
功能:解析和匹配 *style* 标签中的样式
?> 这里的 *style* 标签指的是传入 [content](basic/prop#content) 属性中的 *html* 里包含的 *style* 标签,且 *style* 标签要放在其他标签前面才能生效
大小:*≈3.5KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √ (nvue 直接支持) |
说明:
支持以下选择器:
| 名称 | 示例 |
|:---:|---|
| 标签名选择器 | p {} |
| class 选择器 | .class {} |
| id 选择器 | #id {} |
| 多选择器交集 | p.class {} |
| 多选择器并集 | p, .class {} |
| 后代选择器 | .class1 .class2 {} |
| 子选择器 | .class1 > .class2 {} |
| 伪类 | .class::before {} |
伪类仅支持 *before**after*,支持 *attr* 方法
不支持的选择器(属性选择器等)将被忽略
!> 由于小程序中无法动态写入 *css*,本插件的实现原理是通过解析,将匹配的样式添加到各标签的行内 *style* 中去,请慎用宽泛的选择器,以免大大增加解析结果大小,减慢渲染速度
## txv-video
功能:使用腾讯视频
大小:*≈1KB*
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | | | | √ (h5 和 app 直接支持) |
说明:
引入本插件后,*html* 中符合下方格式的 *iframe* 标签(*src* 中含有 *vid*)将被转为通过腾讯视频播放:
```html
<iframe src="https://v.qq.com/txp/iframe/player.html?vid=xxxxxx" allowFullScreen="true"></iframe>
```
同时,其可以被 [pause-video](basic/prop#pause-video) 属性控制
!> 本插件仅用于将官方 [腾讯视频插件](https://github.com/tvfe/txv-miniprogram-plugin) 应用于本组件,使用前请确认已经成功申请使用该插件并按要求在小程序 *app.json* 中配置完成(*uni-app* 中的配置方法可以参考 [#103](https://github.com/jin-yufeng/mp-html/issues/103#issuecomment-654586246)),否则可能报错 **This application has not registered any plugins yet** 且无法生效
?> 腾讯视频插件 [v2](https://github.com/tvfe/txv-miniprogram-plugin) 默认自动播放,[v1](https://github.com/tvfe/txv-miniprogram-plugin/blob/master/archieve/readme.md) 不会,可按需选择
## img-cache
功能:图片本地缓存
大小:*≈4KB*
作者:[@PentaTea](https://github.com/PentaTea)
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| | | | | | √(仅支持 app 的 vue 页面) |
说明:
引入本插件后,会给组件添加一个 *img-cache* 属性,将该属性设置为 *true* 后,将自动下载引用的图片并将 *src* 属性更换为本地地址
同时在 [组件实例](advanced/api#getCompent) 上挂载了 *imgCache* 对象,扩充缓存控制能力
*imgCache* 对象属性和方法:
| 属性 | 功能 |
|:---:|:---:|
| list | 当前缓存的 url 列表 |
| get(url) | 传入 url 获得本地地址 |
| delete(url) | 传入 url 删除缓存记录 |
| add(url) | 传入 url 并下载目标为缓存 |
| clear() | 清空所有缓存 |
!> 请尽量确保 *src* 中含有文件后缀名,不以后缀结尾也没关系,插件会从路径中推测合理的图片后缀,如果完全不包含后缀信息可能会无法保存到相册
## latex
功能:渲染 *latex* 公式
大小:**≈300KB**
作者:[@Zeng-J](https://github.com/Zeng-J)
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √ |
说明:
引入本插件后,会将 *$xxx$* 的文本内容按照 *latex* 规则进行解析和渲染
?> [2.5.0](changelog/changelog#v250) 版本起支持 *$$xxx$$* 形式的块级公式
?> 与 [editable](#editable) 插件共用时,编辑状态下,公式不会渲染,可以直接修改公式文本
?> 在 *js* 的字符串中写 *latex* 公式时需注意 *\\* 会变成转义符,要使用 *\\\\**String.raw``* 的方式
?> 本插件通过 [katex-mini](https://github.com/rojer95/katex-mini) 解析 *latex* 文本,[字体文件](https://github.com/KaTeX/KaTeX/tree/main/fonts) 建议自行转存
## card
功能:商品(联络人)信息卡
大小:*≈7KB*
作者:[@whoooami](https://github.com/whoooami)
支持平台:
| 微信小程序 | QQ 小程序 | 百度小程序 | 支付宝小程序 | 头条小程序 | uni-app |
|:---:|:---:|:---:|:---:|:---:|:---:|
| √ | √ | √ | √ | √ | √(nvue 不支持) |
效果图:
![效果图](../assets/plugin/card.png)
参数列表:
|参数名|是否必须|类型|说明|
|:---- |:---|:----- |----- |
|src|是|String|图片Url|
|title|是|String|标题|
|desc|是|String|描述|
|url|是|String|跳转url|
|color|是|String|文字颜色|
|bgcolor|是|String|卡片背景颜色|
|border|是|String|卡片边框颜色|
说明:
1. 可以显示商品信息卡片/联络人信息卡片
基础库要求:
满足最低要求即可
?> 如果希望页面上使用本组件,组件的路径为 *path/to/mp-html/card/card*
## 开发插件 :id=develop
一个插件大致需要以下文件(*plugin/template* 中提供了一个模板)
- *build.js*
构建文件,需要导出一个 *object*,可以内含以下项:
| 名称 | 类型 | 默认值 | 功能 |
|:---:|:---:|:---:|---|
| main | string | index.js | 入口文件路径 |
| platform | string[] | ['mp-weixin', 'mp-qq', 'mp-baidu', 'mp-alipay', 'mp-toutiao', 'uni-app'] | 支持使用的平台 |
| template | string | - | 要被添加到模板文件中的标签 (nvue 不可用) |
| methods | object | {} | 用于处理模板中事件的方法 (nvue 不可用) |
| style | string | - | 用于模板文件的 css 样式 |
| import | string&#124;string[] | - | 用于模板文件的 css 文件路径 |
| usingComponents | object | {} | 用于模板的组件或插件列表 (nvue 不可用) |
| handler | function | - | 自定义文件处理方法 |
- *index.js*
入口文件,导出一个 *function*,每个组件在被创建时,会依次实例化各个插件,并传入组件实例可供调用
插件实例上可以挂载以下钩子方法,将在对应时机被调用
| 名称 | 触发时机 | 参数 | 返回值 |
|:---:|:---:|:---:|:---:|
| onUpdate | 更新 html 内容时触发 | 更新的 html 内容和解析配置 | 如果对输入值进行了修改,则返回修改后的内容 |
| onParse | 解析到一个标签时触发 | 标签和解析器实例 | 返回 false 将移除该标签 |
| onLoad | dom 树加载完成时触发 | - | - |
| onDetached | 组件被移除时触发 | - | - |
- *README.md*
使用说明
- *其他依赖文件*
插件目录下,除了 *.md* 的文件、*build.js* 和 *import* 字段中的 *css* 文件,其他的都会被拷贝到生成的组件包中,因此请不要放置无关文件
对于仅在原生平台中使用的内容可放在 *miniprogram* 目录下,仅在 *uni-app* 中使用的内容可放在 *uni-app* 目录下,两个目录下可以分别放置 *build.js*
如果在插件中需要用到解析器(将 *html* 字符串解析为 *nodes* 数组),可以引入 *src/parser.js* 使用,方法如下:
```javascript
const Parser = require('../parser.js')
var instance = new Parser(vm) // 实例化解析器,传入组件实例将自动获取相关配置
var nodes = instance.parse(content) // 解析完成
```
!> 如果编写了插件,在升级组件包时请注意备份,避免丢失
?> 欢迎提交实用的插件 [pull requests](https://github.com/jin-yufeng/mp-html/pulls) 到 *plugins* 文件夹

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -0,0 +1,173 @@
# 📫 事件 :id=event
## 获取方式 :id=method
- *uni-app*
*@* + 事件名 或 *v-on:* + 事件名
事件信息从 *event* 中获取
```vue
<template>
<view>
<mp-html @ready="ready" />
</view>
</template>
<script>
export default {
methods: {
ready (e) {
console.log(e)
}
}
}
</script>
```
- 支付宝小程序
*on* + 事件名(首字母大写)
事件信息从 *event* 中获取
```axml
<mp-html onReady="ready">
```
```javascript
Page({
ready (e) {
console.log(e)
}
})
```
- 其他小程序平台
*bind* + 事件名
事件信息从 *event.detail* 中获取
```wxml
<mp-html bindready="ready" />
```
```javascript
Page({
ready (e) {
console.log(e.detail)
}
})
```
## load
触发时机:*dom* 树加载完毕时
返回值:无
用途:可以调用 [api](advanced/api) 函数
## ready
触发时机:图片加载完毕时(不包含懒加载的图片)
?> 判断方式是 *350ms* 总高度无变化就认为加载完毕,部分情况下可能不准确;[2.4.0](changelog/changelog#v240) 版本起 [lazy-load](basic/prop#lazy-load) 属性为 *false* 时根据图片的 *load* 事件判断,可以基本准确触发
返回值:富文本区域的 *boundingClientRect* 结构体,包含大小位置信息
用途:此时进行 [锚点跳转](advanced/api#navigateTo) 可以基本保证跳转位置正确
?> 如果设置了 [懒加载](basic/prop#lazy-load),此时返回的大小不一定是最终大小,如果需要实时的大小,可以调用 [getRect](advanced/api#getRect) 方法
## error
触发时机:发生渲染错误时
返回值:一个 *object*,其中 *source* 为错误来源(包括 *img*、*video*、*audio**attrs* 为该标签的属性列表(包含 *src* 等信息),*errMsg* 是错误信息
用途:收集错误信息,减少使用出错率高的链接
## imgtap
触发时机:图片被点击时
返回值:该 *img* 标签的属性列表
用途:
默认情况下图片被点击时将自动预览(具体处理可见 [图片效果](overview/feature#img)),如果不希望如此,可将 [preview-img](basic/prop#preview-img) 属性设置为 *false* 并在这里自定义处理
如果需要用到富文本中所有图片的数组,可以通过 [imgList](advanced/api#imgList) 的 *api* 获取
示例:
```javascript
Page({
imgtap (e) {
// 对做了某种标记的图片进行预览
if (e.detail['data-flag']) {
wx.previewImage({
urls: [e.detail.src] // 仅预览单张图片
})
}
}
})
```
## linktap
触发时机:链接被点击时
返回值:该 *a* 标签的属性列表
?> [2.0.5](changelog/changelog#v205) 版本起增加返回该标签内部文本 *innerText*
用途:
默认情况下链接被点击时,对于外部链接,将被拷贝到剪贴板,如果不希望如此,可以将 [copy-link](basic/prop#copy-link) 属性的值设置为 *false* 后在这里自定义处理,可参考以下方案:
1. 跳转 *web-view*
跳转到一个新的页面,该页面放置一个 [web-view](https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html) 用于显示外部网页(需要注意 *web-view* 的使用限制)
2. 跳转其他小程序
对于其他小程序的链接(可通过自行设置的 *data-* 属性判断),通过 [navigateToMiniProgram](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/miniprogram-navigate/wx.navigateToMiniProgram.html) 接口跳转(需要注意跳转限制)
3. 下载文档
对于文档类的链接(可通过后缀名或自行设置的 *data-* 属性判断),可以通过 [downloadFile](https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html) 接口下载文件后通过 [openDocument](https://developers.weixin.qq.com/miniprogram/dev/api/file/wx.openDocument.html) 接口打开文档(需要注意下载域名限制)
4. 下载压缩包
对于压缩包类的链接(可通过后缀名或自行设置的 *data-* 属性判断),可以通过 [downloadFile](https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html) 接口下载文件后通过 [FileSystemManager.unzip](https://developers.weixin.qq.com/miniprogram/dev/api/file/FileSystemManager.unzip.html) 接口解压,然后进行打开文档等操作(需要注意下载域名限制)
对于大文件(可通过 *data-* 属性标注),还可以在下载前进行询问,下载过程中通过 [DownloadTask](https://developers.weixin.qq.com/miniprogram/dev/api/network/download/DownloadTask.html) 提示下载进度等
示例:
```javascript
Page({
linktap (e) {
if (e.detail.href.includes('.doc')) {
// 下载 doc 文件
wx.downloadFile({
url: e.detail.href,
success (res) {
wx.hideLoading()
wx.openDocument({
filePath: res.tempFilePath
})
},
fail (err) {
wx.hideLoading()
wx.showModal({
title: '失败',
content: err.errMsg,
showCancel: false
})
}
})
} else if (e.detail.href.includes('xxx.com')) {
// 跳转到 webview
wx.navigateTo({
url: 'pages/webview/webview?url=' + e.detail.href,
})
} else if (e.detail['data-appid']) {
// 跳转其他小程序
wx.navigateToMiniProgram({
appId: e.detail['data-appid']
})
}
}
})
```
## play
?> [2.3.0](changelog/changelog#v230) 版本起支持
触发时机:音视频播放时
返回值:无
?> [2.5.0](changelog/changelog#v250) 版本起返回值变更为一个 *object*,其中 *source* 为播放来源(包括 *video*、*audio**attrs* 为该标签的属性列表(包含 *src* 等信息),可以统计播放量等信息
用途:和 [pauseMedia](advanced/api#pauseMedia) 的 `api` 配合可以实现与页面中其他音视频进行互斥播放
示例:
```javascript
Page({
// 页面中的音视频播放事件
pagePlay() {
// ctx 为组件实例
ctx.pauseMedia() // 暂停组件内的音视频播放
},
// 组件的 play 事件
componentPlay() {
// media 为页面中的音视频实例
media.pause() // 暂停页面中的音视频播放
}
})
```

View File

@@ -0,0 +1,141 @@
# 🔨 属性 :id=prop
!> 需要将某个属性设置为 *false* 时,应写作 *attr="{{false}}"*
## container-style
?> [2.1.0](changelog/changelog#v210) 版本起支持
功能:设置容器的样式
类型:*String*
示例:
```css
padding: 5px; /* 设置内边距 */
font-size: 18px; /* 设置默认的字体大小 */
overflow: hidden; /* 禁用横向滚动 */
display: inline; /* 行内显示 */
white-space: pre-wrap; /* 保留空格和换行符 */
white-space: pre-line; /* 保留换行符 */
```
## content
功能:用于渲染的 *html* 字符串
类型:*String*
## copy-link
功能:是否允许外部链接被点击时自动复制
类型:*Boolean*
默认值:*true*
?> 对于 *uni-app**h5**app* 平台,外链是能够直接跳转的,这种情况下如果该属性为 *true* 则直接跳转外链(而不是复制链接),为 *false* 则不跳转
## domain
功能:主域名(用于链接拼接)
类型:*String*
示例:
```html
<!-- 假设 domain 属性被设置为 https://example.com
以下链接均会被拼接为 https://example.com/path -->
<img src="//example.com/path" />
<img src="/path" />
<div style="background-image:url('path')"></div>
```
?> 通过 *base* 标签也可以设置主域名,但优先级低于此属性
!> 该属性必须填写 协议名://域名 的完整链接
暂不支持拼接含有 *../* 的相对路径链接
*a* 标签的 *href* 属性可能需要跳转到小程序内路径,因此不进行 *domain* 拼接
设置该属性后将无法使用本地图片
## error-img
功能:图片出错时的占位图链接
类型:*String*
!> 该属性不会进行拼接 [domain](#domain),需传入完整路径(可以使用本地路径)
## lazy-load
功能:是否开启图片懒加载
类型:*Boolean*
默认值:*false*
?> 不同平台懒加载的时机不同,具体参考各平台 *image* 组件懒加载的时机
## loading-img
功能:图片加载过程中的占位图链接
类型:*String*
!> 该属性不会进行拼接 [domain](#domain),需传入完整路径(可以使用本地路径)
## pause-video
功能:是否在播放一个视频时自动暂停其他视频
类型:*Boolean*
默认值:*true*
?> 如果需要多个视频同时播放的,请将此属性设置为 *false*
## preview-img
功能:是否允许图片被点击时自动预览
类型:*Boolean*
默认值:*true*
?> 自动预览允许左右滑动查看所有图片,如果不希望如此可以禁用自动预览并在 [imgtap](basic/event#imgtap) 事件中自行处理
!> 默认情况下 *base64* 图片无法点击预览,[2.5.0](changelog/changelog#v250) 版本起支持将本属性设置为 *"all"* 开启 *base64* 图片的预览,但需要注意各平台 *previewImage**api**base64* 图片支持度不高,需充分测试后使用,如果无法预览,可参考 [imgList](advanced/api#imgList) 中的方法进行转存
## scroll-table
功能:是否给每个表格添加一个滚动层使其能单独横向滚动
类型:*Boolean*
默认值:*false*
!> 如果表格设置了 *inline* 布局,该属性将不会生效以免破坏行内布局
## selectable
功能:是否开启文本长按复制
类型:*Boolean* / *String*
默认值:*false*
!> 将本属性的值设置为 *true* 在微信 *iOS* 端可能失效,[2.0.5](changelog/changelog#v205) 版本起支持将本属性设置为 "*force*" 来支持,但会带来以下影响:
1、所有文本块会显示为 *inline-block*(通过 [text](https://developers.weixin.qq.com/miniprogram/dev/component/text.html) 标签的 *user-select* 属性实现),需要自行适配
2、文字下划线、删除线等效果将失效[详细](https://github.com/jin-yufeng/mp-html/issues/382)
3、所有文本块都无法被 *rich-text* 包含,一定程度上增加标签数,减慢渲染速度
从 [2.3.1](changelog/changelog#v231) 版本起对此问题进行优化(通过 [rich-text](https://developers.weixin.qq.com/miniprogram/dev/component/rich-text.html) 标签的 *user-select* 属性实现,基础库 *2.24.0* 及以上生效),第 *3* 个问题已解决,第 *1*、*2* 个问题部分情况下还会存在
## set-title
功能:是否将 *title* 标签的内容设置到页面标题
类型:*Boolean*
默认值:*true*
## show-img-menu
?> [2.3.0](changelog/changelog#v230) 版本起支持控制预览时是否长按显示菜单(仅微信、百度小程序有效)
功能:是否允许图片被长按时显示菜单
类型:*Boolean*
默认值:*true*
!> 该属性目前仅微信、百度和 *uni-app**app* 平台有效
## tag-style
功能:设置标签的默认样式
类型:*Object*
示例:
```javascript
// 格式为 标签名: 样式
{
a: 'color:red' // a 标签默认为红色
}
```
?> 该属性非响应式,需要在设置 [content](#content) 属性前设置才能生效,动态修改不能实时生效
!> 该属性的原理是解析到各标签的内联 *style* 属性中去,如果对特别常用的标签设置默认样式,将大大加大解析结果大小,减慢渲染速度,这种情况下建议通过 [外部样式](overview/quickstart#setting) 引入
## use-anchor
功能:是否使用锚点链接
类型:*Boolean* / *Number*
默认值:*false*
?> 传入一个数字时表示跳转锚点的偏移量(单位 *px*
?> 开启该属性会将所有设置了 *id* 属性的标签都暴露出来,一定程度上减慢渲染速度,非必要不要开启

View File

@@ -0,0 +1,322 @@
# 📖 更新日志 :id=changelog
## v2.5.1
发布时间:*2025-04-20*
主要更新:
1. `U` `uni-app` 包适配鸿蒙 `APP` [详细](https://github.com/jin-yufeng/mp-html/issues/615)
2. `U` 微信小程序替换废弃 `api` `getSystemInfoSync` [详细](https://github.com/jin-yufeng/mp-html/issues/613)
3. `F` 修复了微信小程序 `glass-easel` 框架下真机换行异常的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/607) by [@PaperStrike](https://github.com/PaperStrike)
4. `F` 修复了 `uni-app``app` 端播放视频可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/617)
5. `F` 修复了 [latex](advanced/plugin#latex) 插件可能出现 `xxx can be used only in display mode` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/632)
6. `F` 修复了 `uni-app` 包 [latex](advanced/plugin#latex) 公式可能不显示的问题 [#599](https://github.com/jin-yufeng/mp-html/issues/599)、[#627](https://github.com/jin-yufeng/mp-html/issues/627)
## v2.5.0
发布时间:*2024-04-22*
主要更新:
1. `U` [play](basic/event#play) 事件增加返回 `src` 等信息 [详细](https://github.com/jin-yufeng/mp-html/issues/526)
2. `U` [preview-img](basic/prop#preview-img) 属性支持设置为 `all` 开启 `base64` 图片预览 [详细](https://github.com/jin-yufeng/mp-html/issues/536)
3. `U` [editable](advanced/plugin#editable) 插件增加简易模式(点击文字直接编辑)
4. `U` [latex](advanced/plugin#latex) 插件支持块级公式 [详细](https://github.com/jin-yufeng/mp-html/issues/582)
5. `F` 修复了表格部分情况下背景丢失的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/587)
6. `F` 修复了部分 `svg` 无法显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/591)
7. `F` 修复了 `uni-app``h5``app` 端部分情况下样式无法识别的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/518)
8. `F` 修复了 [latex](advanced/plugin#latex) 插件部分情况下显示不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/580)
9. `F` 修复了 [editable](advanced/plugin#editable) 插件表格无法删除的问题
10. `F` 修复了 [editable](advanced/plugin#editable) 插件 `uni-app``vue3` `h5` 端点击图片报错的问题
11. `F` 修复了 [editable](advanced/plugin#editable) 插件 `uni-app` 包点击表格没有菜单栏的问题
## v2.4.3
发布时间:*2024-01-21*
主要更新:
1. `A` 增加 [card](advanced/plugin#card) 插件 [详细](https://github.com/jin-yufeng/mp-html/pull/533) by [@whoooami](https://github.com/whoooami)
2. `F` 修复了 `svg` 中包含 `foreignobject` 可能不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/523)
3. `F` 修复了合并单元格的表格部分情况下显示不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/561)
4. `F` 修复了 `img` 标签设置 `object-fit` 无效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/567)
5. `F` 修复了 [latex](advanced/plugin#latex) 插件公式会换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/540)
6. `F` 修复了 `uni-app` 包 [editable](advanced/plugin#editable) 和 [audio](advanced/plugin#audio) 插件共用时点击 `audio` 无法编辑的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/529) by [@whoooami](https://github.com/whoooami)
7. `F` 修复了支付宝小程序设置了宽高的图片可能显示不正常的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/544)
8. `F` 修复了 `uni-app` 包微信小程序部分情况下图片会报错 `replace of undefined` 的问题
9. `F` 修复了 `uni-app` 包快手小程序图片不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/571)
## v2.4.2
发布时间:*2023-05-14*
主要更新:
1. `A` [editable](advanced/plugin#editable) 插件支持修改文字颜色 [详细](https://github.com/jin-yufeng/mp-html/issues/254)
2. `F` 修复了 `svg` 中有 `style` 不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/505)
3. `F` 修复了 `uni-app` 包使用旧版编译器可能报错 `Bad attr nodes` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/472)
4. `F` 修复了 `uni-app``app` 端可能出现无法读取 `lazyLoad` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/513)
5. `F` 修复了 [editable](advanced/plugin#editable) 插件在点击换图时未拼接 [domain](basic/prop#domain) 的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/497) by [@TwoKe945](https://github.com/TwoKe945)
6. `F` 修复了 [latex](advanced/plugin#latex) 插件部分情况下不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/515)
7. `F` 修复了 [editable](advanced/plugin#editable) 插件点击音视频时其他标签框不消失的问题
## v2.4.1
发布时间:*2022-12-25*
主要更新:
1. `F` 修复了没有图片时 [ready](basic/event#ready) 事件可能不触发的问题
2. `F` 修复了加载过程中可能出现 `Root label not found` 错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/470)
3. `F` 修复了 [audio](advanced/plugin#audio) 插件退出页面可能会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/457)
4. `F` 修复了 `uni-app``vue3` 运行到 `app``HBuilder X 3.6.10` 以上报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/480)
5. `F` 修复了原生包链接内有图片时可能错误换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/464)
6. `F` 修复了 `uni-app``nvue` 端链接中包含 `%22` 时可能无法显示的问题
7. `F` 修复了 `uni-app``vue3` 使用 [highlight](advanced/plugin#highlight) 插件可能报错的问题
8. `F` 修复了头条小程序使用 [editable](advanced/plugin#editable) 插件内容为空时点击会报错的问题
## v2.4.0
发布时间:*2022-08-27*
主要更新:
1. `A` 增加了 [setPlaybackRate](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](basic/event#ready) 事件触发时机,未设置懒加载的情况下基本可以准确触发 [详细](https://github.com/jin-yufeng/mp-html/issues/195)
4. `U` [highlight](advanced/plugin#highlight) 插件在编辑状态下不进行高亮处理,便于编辑
5. `F` 修复了 `flex` 布局下图片大小可能不正确的问题
6. `F` 修复了 [selectable](basic/prop#selectable) 属性没有设置 `force` 也可能出现渲染异常的问题
7. `F` 修复了表格中的图片大小可能不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/448)
8. `F` 修复了含有合并单元格的表格可能无法设置竖直对齐的问题
9. `F` 修复了 [editable](advanced/plugin#editable) 插件在 `scroll-view` 中使用时工具条位置可能不正确的问题
10. `F` 修复了 `uni-app``vue3` 使用 [search](advanced/plugin#search) 插件可能导致错误换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/449)
## v2.3.2
发布时间:*2022-08-13*
主要更新:
1. `A` 增加 [latex](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](advanced/plugin#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](advanced/plugin#editable) 插件输入连续空格无效的问题
6. `F` 修复了 `uni-app``vue3` 图片设置 `inline` 会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/438)
7. `F` 修复了 `uni-app``vue3` 使用 `table` 可能报错的问题
## v2.3.1
发布时间:*2022-05-20*
主要更新:
1. `U` `uni-app``app` 端支持使用本地图片
2. `U` 优化了微信小程序 [selectable](basic/prop#selectable) 属性在 `ios` 端的处理 [详细](basic/prop#selectable)
3. `U` 原生包取消样式隔离,部分平台可以直接引入页面样式 [#376](https://github.com/jin-yufeng/mp-html/issues/376)、[详细](overview/quickstart#externStyle)
4. `F` 修复了 [editable](advanced/plugin#editable) 插件不在顶部时 `tooltip` 位置可能错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/430)
5. `F` 修复了 `uni-app``vue3` 运行到微信小程序可能报错丢失内容的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/414)
6. `F` 修复了 `uni-app``vue3` 部分标签可能被错误换行的问题
7. `F` 修复了原生包个别情况下可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/428)
8. `F` 修复了 [editable](advanced/plugin#editable) 插件 `uni-app` 包的 `app` 端插入视频无法预览的问题
## v2.3.0
发布时间:*2022-04-01*
主要更新:
1. `A` 增加了 `play` 事件,音视频播放时触发,可用于与页面其他音视频进行互斥播放 [详细](basic/event#play)
2. `U` [show-img-menu](basic/prop#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` 修复了百度小程序使用 `br` 标签可能部分不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/409)
11. `F` 修复了 [editable](advanced/plugin#editable) 插件连续插入内容时顺序不正确的问题
12. `F` 修复了 `uni-app``vue3` 使用 [audio](advanced/plugin#audio) 插件报错的问题
13. `F` 修复了 `uni-app` 包 [highlight](advanced/plugin#highlight) 插件使用自定义的 `prism.min.js` 报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/416)
## v2.2.2
发布时间:*2022-02-26*
主要更新:
1. `A` 增加了 [pauseMedia](advanced/api#pauseMedia) 的 `api`,可用于暂停播放音视频 [详细](https://github.com/jin-yufeng/mp-html/issues/317)
2. `U` 优化了长内容的加载速度
3. `U` `uni-app` 包适配 `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](advanced/plugin#highlight) 插件部分情况下可能显示不完整的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/403)
## v2.2.1
发布时间:*2021-12-24*
主要更新:
1. `A` [editable](advanced/plugin#editable) 插件增加上下移动标签功能
2. `U` [editable](advanced/plugin#editable) 插件支持在文本中间光标处插入内容
3. `F` 修复了 `uni-app``nvue` 端设置 `margin` 后可能导致高度不正确的问题
4. `F` 修复了 [highlight](advanced/plugin#highlight) 插件使用压缩版的 `prism.css` 可能导致背景失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/367)
5. `F` 修复了 `uni-app` 包编辑状态下使用 [emoji](advanced/plugin#emoji) 插件内容为空时可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/371)
6. `F` 修复了使用 [editable](advanced/plugin#editable) 插件后将 [selectable](basic/prop#selectable) 属性设置为 `force` 不生效的问题
## v2.2.0
发布时间:*2021-10-11*
主要更新:
1. `A` 增加 [customElements](overview/quickstart#customelements) 配置项,便于添加自定义功能性标签 [详细](https://github.com/jin-yufeng/mp-html/issues/350)
2. `A` [editable](advanced/plugin#editable) 插件增加切换音视频自动播放状态的功能 [详细](https://github.com/jin-yufeng/mp-html/pull/341) by [@leeseett](https://github.com/leeseett)
3. `A` [editable](advanced/plugin#editable) 插件删除媒体标签时触发 `remove` 事件,便于删除已上传的文件
4. `U` [editable](advanced/plugin#editable) 插件 `insertImg` 方法支持同时插入多张图片 [详细](https://github.com/jin-yufeng/mp-html/issues/342)
5. `U` [editable](advanced/plugin#editable) 插入图片和音视频时支持拼接 [domian](basic/prop#domain) 主域名
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` 修复了 `uni-app``nvue` 页面运行到非 `app` 平台时可能样式错误的问题
9. `D` 移除了 `ad` 配置项(由 [customElements](overview/quickstart#customelements) 代替)
## 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](overview/quickstart#setting) 中的 `class` 名包含下划线或数字时可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
5. `F` 修复了 `uni-app``h5` 端引入 [externStyle](overview/quickstart#setting) 可能不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
6. `F` 修复了微信原生包 `a` 标签的 `style` 中包含 `inline` 时不响应事件的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/332)
## v2.1.4
发布时间:*2021-07-14*
主要更新:
1. `F` 修复了 `rt` 标签无法设置样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/318)
2. `F` 修复了表格中有单元格同时合并行和列时可能显示不正确的问题
3. `F` 修复了 `uni-app` 包的 `app` 端无法关闭图片长按菜单的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/322)
4. `F` 修复了 [editable](advanced/plugin#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](advanced/plugin#editable) 插件增加 `insertTable` 方法
2. `U` [editable](advanced/plugin#editable) 插件支持编辑表格中的空白单元格 [详细](https://github.com/jin-yufeng/mp-html/issues/310)
3. `F` 修复了 [externStyle](overview/quickstart#setting) 中使用伪类可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/298)
4. `F` 修复了多个组件同时使用时 [tag-style](basic/prop#tag-style) 属性时可能互相影响的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/305) by [@woodguoyu](https://github.com/woodguoyu)
5. `F` 修复了包含 `linearGradient``svg` 可能无法显示的问题
6. `F` 修复了 `uni-app` 包编译到头条小程序时可能报错的问题
7. `F` 修复了 `uni-app``nvue` 端不触发 `click` 事件的问题
8. `F` 修复了 [editable](advanced/plugin#editable) 插件尾部插入时无法撤销的问题
9. `F` 修复了 [editable](advanced/plugin#editable) 插件的 `insertHtml` 方法只能在末尾插入的问题
10. `F` 修复了 [editable](advanced/plugin#editable) 插件插入音频不显示的问题
## v2.1.2
发布时间:*2021-04-24*
主要更新:
1. `A` 增加了 [img-cache](advanced/plugin#img-cache) 插件,可以在 `uni-app``app` 端缓存图片 [详细](https://github.com/jin-yufeng/mp-html/issues/292) by [@PentaTea](https://github.com/PentaTea)
2. `U` 支持通过 [container-style](basic/prop#container-style) 属性设置 `white-space` 来保留连续空格和换行符 [详细](question/faq#space)
3. `U` 代码风格符合 [standard](https://standardjs.com) 标准
4. `U` `uni-app` 包使用 [editable](advanced/plugin#editable) 插件编辑状态下支持预览视频 [详细](https://github.com/jin-yufeng/mp-html/issues/286)
5. `F` 修复了 `svg` 标签内嵌 `svg` 时无法显示的问题
6. `F` 修复了微信原生包 `img` 标签的 `style` 中包含 `inline` 时不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/287)
7. `F` 修复了支付宝和头条小程序部分区域不可复制的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/291)
## v2.1.1
发布时间:*2021-04-09*
主要更新:
1. `F` 修复了对 `p` 标签设置 [tag-style](basic/prop#tag-style) 可能不生效的问题
2. `F` 修复了 `svg` 标签中的文本无法显示的问题
3. `F` 修复了 `uni-app` 包的 `nvue` 端不设置 [container-style](basic/prop#container-style) 可能报错的问题
4. `F` 修复了 `uni-app` 包使用 [editable](advanced/plugin#editable) 插件编辑表格时可能报错的问题
5. `F` 修复了 `uni-app` 包使用 [highlight](advanced/plugin#highlight) 插件运行到头条小程序时可能没有样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/280)
6. `F` 修复了 `uni-app` 包使用 [editable](advanced/plugin#editable) 插件 `editable` 属性为 `false` 时会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/284)
7. `F` 修复了 [style](advanced/plugin#style) 插件连续子选择器失效的问题
8. `F` 修复了 [editable](advanced/plugin#editable) 插件无法修改图片和字体大小的问题
## v2.1.0
发布时间:*2021-03-20*
主要更新:
1. `A` 增加了 [container-style](basic/prop#container-style) 属性 [详细](https://gitee.com/jin-yufeng/mp-html/pulls/1)
2. `A` 增加支持 `strike` 标签
3. `A` `editable` 插件增加 `placeholder` 属性 [详细](advanced/plugin#editable)
4. `A` `editable` 插件增加 `insertHtml` 方法 [详细](advanced/plugin#editable)
5. `U` 外部样式支持标签名选择器 [详细](overview/quickstart#setting)
6. `F` 修复了 `uni-app``nvue` 端部分情况下可能不显示的问题
## v2.0.5
发布时间:*2021-03-12*
主要更新:
1. `U` [linktap](basic/event#linktap) 事件增加返回内部文本内容 `innerText` [详细](https://github.com/jin-yufeng/mp-html/issues/271)
2. `U` [selectable](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` 修复了 `uni-app` 包多次修改富文本数据时部分内容可能不显示的问题
5. `F` 修复了百度小程序真机部分内容不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/272)
6. `F` 修复了 [腾讯视频](advanced/plugin#txv-video) 插件可能无法播放的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/265)
7. `F` 修复了 [highlight](advanced/plugin#highlight) 插件没有设置高亮语言时没有应用默认样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/276) by [@fuzui](https://github.com/fuzui)
## v2.0.4
发布时间:*2021-01-31*
主要更新:
1. `A` [editable](advanced/plugin#editable) 插件增加下划线和图片超链接的功能 [详细](https://github.com/jin-yufeng/mp-html/issues/254)
2. `U` 支付宝和头条小程序原生包直接通过 `template` 递归实现渲染
3. `F` 修复了 `img` 标签设置 `data-src` 可能导致图片不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/257)
4. `F` 修复了 `script` 标签中的 `<` 会被解析为标签的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/259)
5. `F` 修复了 `uni-app` 包的 `app` 端播放视频时可能高度突然变小的问题
6. `F` 修复了 `uni-app` 包的 `app` 端长按图片会报错的问题
7. `F` 修复了 `uni-app` 包的 `nvue` 端使用 [editable](advanced/plugin#editable) 插件后无法显示的问题
8. `F` 修复了 [editable](advanced/plugin#editable) 插件删除图片和切换内容时可能出现错误选择框的问题
9. `F` 修复了 [editable](advanced/plugin#editable) 插件无法编辑链接文本内容的问题
## v2.0.3
发布时间:*2021-01-15*
主要更新:
1. `U` 图片被点击时不冒泡(可以与整体的点击区分开,不影响链接中的图片)
2. `F` 修复了图片链接缺省协议名时可能无法预览的问题
3. `F` 修复了原生包 `video``audio` 标签内放置文本会报错的问题
4. `F` 修复了 [editable](advanced/plugin#editable) 插件清空内容时弹窗可能不消失的问题
5. `F` 修复了 [highlight](advanced/plugin#highlight) 插件部分情况下样式不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/231)
6. `F` 修复了文档首页跳转到快速开始页时 `404` 的问题 by [@AnsonZnl](https://github.com/AnsonZnl)
## v2.0.2
发布时间:*2021-01-08*
主要更新:
1. `U` `uni-app` 包微信端利用 `virtualHost` 去除夹层,加快渲染
2. `F` 修复了部分情况下 `flex` 布局显示不正确的问题
3. `F` 修复了设置 [loading-img](basic/prop#loading-img) 会导致懒加载失效的问题
4. `F` 修复了头条原生包部分情况下表格显示不正确的问题
5. `F` 修复了 `uni-app``h5``app` 端部分插件样式无法应用的问题
6. `F` 修复了 `uni-app` 包没有自动将 `data-src` 设置为 `src` 的问题
7. `F` 修复了 `uni-app` 包的 `nvue` 端 [getRect](advanced/api#getRect) 方法无法使用的问题
8. `F` 修复了 `uni-app` 包运行到华为快应用可能报错的问题
9. `F` 修复了在低版本 taro 中使用可能无法正确解析的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/248)
10. `F` 修复了 [highlight](advanced/plugin#highlight) 插件 `pre``code` 之间有空白符时无法高亮的问题
11. `F` 修复了 [editable](advanced/plugin#editable) 插件清空内容后插入可能报错的问题
## v2.0.1
发布时间:*2021-01-01*
主要更新:
1. `F` 修复了 `a` 标签自动跳转到不存在页面时可能报错的问题
2. `F` 修复了含合并单元格的表格设置列宽可能导致显示不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/239)
3. `F` 修复了表格中的图片可能错位的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/194)
4. `F` 修复了原生包使用 [editable](advanced/plugin#editable) 插件点击标签时可能报错的问题
5. `F` 修复了 `uni-app``h5``app` 端可能无法使用 `iframe``embed` 标签的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/245)
6. `F` 修复了 `uni-app` 使用部分插件会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/246)
## v2.0.0
发布时间:*2020-12-26*
主要更新:
1. `U` 通过 `gulp` 进行构建,自动生成各平台压缩版代码,减小引入包大小 [详细](advanced/develop#pack)
2. `U` 没有设置 `href` 属性的 `a` 标签不应用链接的样式,可以用作一般标签的点击处理 [详细](question/faq#tap)
3. `U` 提供了统一的插件接口,扩展更加方便(代码高亮、`markdown` 等都可以直接通过引入插件实现)[详细](advanced/plugin)
4. `U` 实现了简单的编辑功能 [详细](advanced/plugin#editable)
5. `U` 支持生成各平台的示例项目,便于调试 [详细](overview/quickstart#demo)
6. `U` 原生包共用一份源代码(构建时进行自动转换),注释更加详细,便于了解和维护
7. `U` 通过 `jest` 进行单元测试,进一步保证代码质量 [详细](advanced/develop#test)
8. `U` 去除了一些冗余功能,进一步减小包大小(约 `24.5KB`
9. `U` 减少了递归节点树,加快渲染速度
10. `U` `uni-app``app` 端使用非原生的 `video` 显示视频以解决无法同层带来的系列问题
11. `U` `uni-app``nvue` 端支持通过 `bgColor` 属性设置背景色(默认白色,不可设置为透明)
12. `F` 修复了 `uni-app``nvue` 端从不可见区域到可见时可能显示不正确的问题
*v1.x* 更新指南:
- 组件路径和名称
*parser* -> *mp-html*
- *npm* 包名
*parser-wx* -> *mp-html*
- 组件属性
更名:
*html* -> [content](basic/prop#content)
*autopause* -> [pause-video](basic/prop#pause-video)
*autoscroll* -> [scroll-table](basic/prop#scroll-table)
*autosetTitle* -> [set-title](basic/prop#set-title)
移除:
*compress*, *show-with-animation*, *use-cache*
新增:
[copy-link](basic/prop#copy-link), [error-img](basic/prop#error-img), [preview-img](basic/prop#preview-img), [show-img-menu](basic/prop#show-img-menu)
修改:
[use-anchor](basic/prop#use-anchor) 支持传入数字表示跳转偏移量
- 组件事件
更名 *linkpress* -> [linktap](basic/event#linktap)
移除 *parse* 事件
*imgtap**linktap* 事件中不再返回 *ignore* 方法,可以使用 [preview-img](basic/prop#preview-img) 和 [copy-link](basic/prop#copy-link) 属性禁用自动预览/拷贝
链接被点击时,不再支持自动跳转其他小程序,可以自行在 [linktap](basic/event#linktap) 事件中进行跳转
- api
[navigateTo](advanced/api#navigateTo) 返回 *Promise*,不再采用 *success**fail* 回调
*rect* 变更为 [getRect](advanced/api#getRect) 方法
移除 *getVideoContext* 方法
[imgList](advanced/api#imgList) 不再包含 *setItem**each* 方法
- 其他
默认不再支持匹配 *style* 标签中的样式,如有需要请使用 [style](advanced/plugin#style) 插件
不再支持 *base64* 图片预览(默认为不可预览的小图片)
取消了配置项(相关解析配置在 *parser.js* 中,*filter* 等方法用 [插件](advanced/plugin) 的方式替代)
取消了视频的懒加载(应避免在一个页面中使用过多视频,以免卡顿)
*ad* 标签默认不添加到模板(详见 [个性化](overview/quickstart#setting)

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>小程序富文本组件</title>
<link rel="icon" href="assets/logo/logo.ico" type="image/x-icon">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="小程序富文本组件">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="lib/vue.css">
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script")
hm.src = "https://hm.baidu.com/hm.js?69554d980eb5eb786919e3c3ad37b2ce"
var s = document.getElementsByTagName("script")[0]
s.parentNode.insertBefore(hm, s)
})()
</script>
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: 'mp-html',
repo: 'https://github.com/jin-yufeng/mp-html',
coverpage: true,
loadSidebar: true,
subMaxLevel: 3,
auto2top: true,
search: {
placeholder: '搜索',
noData: '找不到结果'
}
}
// 渲染测试内容
function render () {
document.getElementById("show").srcdoc='<meta name="viewport" content="width=device-width"><style>img{max-width:100%}</style>'+document.getElementById("input").value.replace(/<script[\s\S]+?<\/script>/g, '')
}
// 清空测试内容
function reset () {
document.getElementById("input").value = ''
document.getElementById("show").srcdoc = ''
}
</script>
<script src="lib/docsify.min.js"></script>
<script src="lib/search.min.js"></script>
<script src="lib/prism-bash.min.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,858 @@
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600");
* {
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
box-sizing: border-box;
}
body:not(.ready) {
overflow: hidden;
}
body:not(.ready) [data-cloak],
body:not(.ready) .app-nav,
body:not(.ready) > nav {
display: none;
}
div#app {
font-size: 30px;
font-weight: lighter;
margin: 40vh auto;
text-align: center;
}
div#app:empty::before {
content: 'Loading...';
}
.emoji {
height: 1.2rem;
vertical-align: middle;
}
.progress {
background-color: var(--theme-color, #42b983);
height: 2px;
left: 0px;
position: fixed;
right: 0px;
top: 0px;
transition: width 0.2s, opacity 0.4s;
width: 0%;
z-index: 999999;
}
.search a:hover {
color: var(--theme-color, #42b983);
}
.search .search-keyword {
color: var(--theme-color, #42b983);
font-style: normal;
font-weight: bold;
}
html,
body {
height: 100%;
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: #34495e;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
}
img {
max-width: 100%;
}
a[disabled] {
cursor: not-allowed;
opacity: 0.6;
}
kbd {
border: solid 1px #ccc;
border-radius: 3px;
display: inline-block;
font-size: 12px !important;
line-height: 12px;
margin-bottom: 3px;
padding: 3px 5px;
vertical-align: middle;
}
li input[type='checkbox'] {
margin: 0 0.2em 0.25em 0;
vertical-align: middle;
}
.app-nav {
margin: 25px 60px 0 0;
position: absolute;
right: 0;
text-align: right;
z-index: 10;
/* navbar dropdown */
}
.app-nav.no-badge {
margin-right: 25px;
}
.app-nav p {
margin: 0;
}
.app-nav > a {
margin: 0 1rem;
padding: 5px 0;
}
.app-nav ul,
.app-nav li {
display: inline-block;
list-style: none;
margin: 0;
}
.app-nav a {
color: inherit;
font-size: 16px;
text-decoration: none;
transition: color 0.3s;
}
.app-nav a:hover {
color: var(--theme-color, #42b983);
}
.app-nav a.active {
border-bottom: 2px solid var(--theme-color, #42b983);
color: var(--theme-color, #42b983);
}
.app-nav li {
display: inline-block;
margin: 0 1rem;
padding: 5px 0;
position: relative;
cursor: pointer;
}
.app-nav li ul {
background-color: #fff;
border: 1px solid #ddd;
border-bottom-color: #ccc;
border-radius: 4px;
box-sizing: border-box;
display: none;
max-height: calc(100vh - 61px);
overflow-y: auto;
padding: 10px 0;
position: absolute;
right: -15px;
text-align: left;
top: 100%;
white-space: nowrap;
}
.app-nav li ul li {
display: block;
font-size: 14px;
line-height: 1rem;
margin: 0;
margin: 8px 14px;
white-space: nowrap;
}
.app-nav li ul a {
display: block;
font-size: inherit;
margin: 0;
padding: 0;
}
.app-nav li ul a.active {
border-bottom: 0;
}
.app-nav li:hover ul {
display: block;
}
.github-corner {
border-bottom: 0;
position: fixed;
right: 0;
text-decoration: none;
top: 0;
z-index: 1;
}
.github-corner:hover .octo-arm {
-webkit-animation: octocat-wave 560ms ease-in-out;
animation: octocat-wave 560ms ease-in-out;
}
.github-corner svg {
color: #fff;
fill: var(--theme-color, #42b983);
height: 80px;
width: 80px;
}
main {
display: block;
position: relative;
width: 100vw;
height: 100%;
z-index: 0;
}
main.hidden {
display: none;
}
.anchor {
display: inline-block;
text-decoration: none;
transition: all 0.3s;
}
.anchor span {
color: #34495e;
}
.anchor:hover {
text-decoration: underline;
}
.sidebar {
border-right: 1px solid rgba(0,0,0,0.07);
overflow-y: auto;
padding: 40px 0 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
transition: transform 250ms ease-out;
width: 300px;
z-index: 20;
}
.sidebar > h1 {
margin: 0 auto 1rem;
font-size: 1.5rem;
font-weight: 300;
text-align: center;
}
.sidebar > h1 a {
color: inherit;
text-decoration: none;
}
.sidebar > h1 .app-nav {
display: block;
position: static;
}
.sidebar .sidebar-nav {
line-height: 2em;
padding-bottom: 40px;
}
.sidebar li.collapse .app-sub-sidebar {
display: none;
}
.sidebar ul {
margin: 0 0 0 15px;
padding: 0;
}
.sidebar li > p {
font-weight: 700;
margin: 0;
}
.sidebar ul,
.sidebar ul li {
list-style: none;
}
.sidebar ul li a {
border-bottom: none;
display: block;
}
.sidebar ul li ul {
padding-left: 20px;
}
.sidebar::-webkit-scrollbar {
width: 4px;
}
.sidebar::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 4px;
}
.sidebar:hover::-webkit-scrollbar-thumb {
background: rgba(136,136,136,0.4);
}
.sidebar:hover::-webkit-scrollbar-track {
background: rgba(136,136,136,0.1);
}
.sidebar-toggle {
background-color: transparent;
background-color: rgba(255,255,255,0.8);
border: 0;
outline: none;
padding: 10px;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
transition: opacity 0.3s;
width: 284px;
z-index: 30;
cursor: pointer;
}
.sidebar-toggle:hover .sidebar-toggle-button {
opacity: 0.4;
}
.sidebar-toggle span {
background-color: var(--theme-color, #42b983);
display: block;
margin-bottom: 4px;
width: 16px;
height: 2px;
}
body.sticky .sidebar,
body.sticky .sidebar-toggle {
position: fixed;
}
.content {
padding-top: 60px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 300px;
transition: left 250ms ease;
}
.markdown-section {
margin: 0 auto;
max-width: 80%;
padding: 30px 15px 40px 15px;
position: relative;
}
.markdown-section > * {
box-sizing: border-box;
font-size: inherit;
}
.markdown-section > :first-child {
margin-top: 0 !important;
}
.markdown-section hr {
border: none;
border-bottom: 1px solid #eee;
margin: 2em 0;
}
.markdown-section iframe {
border: 1px solid #eee;
/* fix horizontal overflow on iOS Safari */
width: 1px;
min-width: 100%;
}
.markdown-section table {
border-collapse: collapse;
border-spacing: 0;
display: block;
margin-bottom: 1rem;
overflow: auto;
width: 100%;
}
.markdown-section th {
border: 1px solid #ddd;
font-weight: bold;
padding: 6px 13px;
}
.markdown-section td {
border: 1px solid #ddd;
padding: 6px 13px;
}
.markdown-section tr {
border-top: 1px solid #ccc;
}
.markdown-section tr:nth-child(2n) {
background-color: #f8f8f8;
}
.markdown-section p.tip {
background-color: #f8f8f8;
border-bottom-right-radius: 2px;
border-left: 4px solid #f66;
border-top-right-radius: 2px;
margin: 2em 0;
padding: 12px 24px 12px 30px;
position: relative;
}
.markdown-section p.tip:before {
background-color: #f66;
border-radius: 100%;
color: #fff;
content: '!';
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
font-weight: bold;
left: -12px;
line-height: 20px;
position: absolute;
height: 20px;
width: 20px;
text-align: center;
top: 14px;
}
.markdown-section p.tip code {
background-color: #efefef;
}
.markdown-section p.tip em {
color: #34495e;
}
.markdown-section p.warn {
background: rgba(66,185,131,0.1);
border-radius: 2px;
padding: 1rem;
}
.markdown-section ul.task-list > li {
list-style-type: none;
}
body.close .sidebar {
transform: translateX(-300px);
}
body.close .sidebar-toggle {
width: auto;
}
body.close .content {
left: 0;
}
@media print {
.github-corner,
.sidebar-toggle,
.sidebar,
.app-nav {
display: none;
}
}
@media screen and (max-width: 768px) {
.github-corner,
.sidebar-toggle,
.sidebar {
position: fixed;
}
.app-nav {
margin-top: 16px;
}
.app-nav li ul {
top: 30px;
}
main {
height: auto;
min-height: 100vh;
overflow-x: hidden;
}
.sidebar {
left: -300px;
transition: transform 250ms ease-out;
}
.content {
left: 0;
max-width: 100vw;
position: static;
padding-top: 20px;
transition: transform 250ms ease;
}
.app-nav,
.github-corner {
transition: transform 250ms ease-out;
}
.sidebar-toggle {
background-color: transparent;
width: auto;
padding: 30px 30px 10px 10px;
}
body.close .sidebar {
transform: translateX(300px);
}
body.close .sidebar-toggle {
background-color: rgba(255,255,255,0.8);
transition: 1s background-color;
width: 284px;
padding: 10px;
}
body.close .content {
transform: translateX(300px);
}
body.close .app-nav,
body.close .github-corner {
display: none;
}
.github-corner:hover .octo-arm {
-webkit-animation: none;
animation: none;
}
.github-corner .octo-arm {
-webkit-animation: octocat-wave 560ms ease-in-out;
animation: octocat-wave 560ms ease-in-out;
}
}
@-webkit-keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
}
@keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
}
section.cover {
align-items: center;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
width: 100vw;
display: none;
}
section.cover.show {
display: flex;
}
section.cover.has-mask .mask {
background-color: #fff;
opacity: 0.8;
position: absolute;
top: 0;
height: 100%;
width: 100%;
}
section.cover .cover-main {
flex: 1;
margin: -20px 16px 0;
text-align: center;
position: relative;
}
section.cover a {
color: inherit;
text-decoration: none;
}
section.cover a:hover {
text-decoration: none;
}
section.cover p {
line-height: 1.5rem;
margin: 1em 0;
}
section.cover h1 {
color: inherit;
font-size: 2.5rem;
font-weight: 300;
margin: 0.625rem 0 2.5rem;
position: relative;
text-align: center;
}
section.cover h1 a {
display: block;
}
section.cover h1 small {
bottom: -0.4375rem;
font-size: 1rem;
position: absolute;
}
section.cover blockquote {
font-size: 1.5rem;
text-align: center;
}
section.cover ul {
line-height: 1.8;
list-style-type: none;
margin: 1em auto;
max-width: 500px;
padding: 0;
}
section.cover .cover-main > p:last-child a {
border-color: var(--theme-color, #42b983);
border-radius: 2rem;
border-style: solid;
border-width: 1px;
box-sizing: border-box;
color: var(--theme-color, #42b983);
display: inline-block;
font-size: 1.05rem;
letter-spacing: 0.1rem;
margin: 0.5rem 1rem;
padding: 0.75em 2rem;
text-decoration: none;
transition: all 0.15s ease;
}
section.cover .cover-main > p:last-child a:last-child {
background-color: var(--theme-color, #42b983);
color: #fff;
}
section.cover .cover-main > p:last-child a:last-child:hover {
color: inherit;
opacity: 0.8;
}
section.cover .cover-main > p:last-child a:hover {
color: inherit;
}
section.cover blockquote > p > a {
border-bottom: 2px solid var(--theme-color, #42b983);
transition: color 0.3s;
}
section.cover blockquote > p > a:hover {
color: var(--theme-color, #42b983);
}
body {
background-color: #fff;
}
/* sidebar */
.sidebar {
background-color: #fff;
color: #364149;
}
.sidebar li {
margin: 6px 0 6px 0;
}
.sidebar ul li a {
color: #505d6b;
font-size: 14px;
font-weight: normal;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.sidebar ul li a:hover {
text-decoration: underline;
}
.sidebar ul li ul {
padding: 0;
}
.sidebar ul li.active > a {
border-right: 2px solid;
color: var(--theme-color, #42b983);
font-weight: 600;
}
.app-sub-sidebar li::before {
content: '-';
padding-right: 4px;
float: left;
}
/* markdown content found on pages */
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
color: #2c3e50;
font-weight: 600;
}
.markdown-section a {
color: var(--theme-color, #42b983);
font-weight: 600;
}
.markdown-section h1 {
font-size: 2rem;
margin: 0 0 1rem;
}
.markdown-section h2 {
font-size: 1.75rem;
margin: 45px 0 0.8rem;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 40px 0 0.6rem;
}
.markdown-section h4 {
font-size: 1.25rem;
}
.markdown-section h5 {
font-size: 1rem;
}
.markdown-section h6 {
color: #777;
font-size: 1rem;
}
.markdown-section figure,
.markdown-section p {
margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
line-height: 1.6rem;
word-spacing: 0.05rem;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5rem;
}
.markdown-section blockquote {
border-left: 4px solid var(--theme-color, #42b983);
color: #858585;
margin: 2em 0;
padding-left: 20px;
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
}
.markdown-section iframe {
margin: 1em 0;
}
.markdown-section em {
color: #7f8c8d;
}
.markdown-section code,
.markdown-section pre,
.markdown-section output::after {
font-family: 'Roboto Mono', Monaco, courier, monospace;
}
.markdown-section code,
.markdown-section pre {
background-color: #f8f8f8;
}
.markdown-section pre,
.markdown-section output {
margin: 1.2em 0;
position: relative;
}
.markdown-section pre > code,
.markdown-section output {
border-radius: 2px;
display: block;
}
.markdown-section pre > code,
.markdown-section output::after {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
}
.markdown-section code {
border-radius: 2px;
color: #e96900;
margin: 0 2px;
padding: 3px 5px;
white-space: pre-wrap;
}
.markdown-section > :not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) code {
font-size: 0.8rem;
}
.markdown-section pre {
padding: 0 1.4rem;
line-height: 1.5rem;
overflow: auto;
word-wrap: normal;
}
.markdown-section pre > code {
color: #525252;
font-size: 0.8rem;
padding: 2.2em 5px;
line-height: inherit;
margin: 0 2px;
max-width: inherit;
overflow: inherit;
white-space: inherit;
}
.markdown-section output {
padding: 1.7rem 1.4rem;
border: 1px dotted #ccc;
}
.markdown-section output > :first-child {
margin-top: 0;
}
.markdown-section output > :last-child {
margin-bottom: 0;
}
.markdown-section code::after,
.markdown-section code::before,
.markdown-section output::after,
.markdown-section output::before {
letter-spacing: 0.05rem;
}
.markdown-section pre::after,
.markdown-section output::after {
color: #ccc;
font-size: 0.6rem;
font-weight: 600;
height: 15px;
line-height: 15px;
padding: 5px 10px 0;
position: absolute;
right: 0;
text-align: right;
top: 0;
}
.markdown-section pre::after,
.markdown-section output::after {
content: attr(data-lang);
}
/* code highlight */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8e908c;
}
.token.namespace {
opacity: 0.7;
}
.token.boolean,
.token.number {
color: #c76b29;
}
.token.punctuation {
color: #525252;
}
.token.property {
color: #c08b30;
}
.token.tag {
color: #2973b7;
}
.token.string {
color: var(--theme-color, #42b983);
}
.token.selector {
color: #6679cc;
}
.token.attr-name {
color: #2973b7;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #22a2c9;
}
.token.attr-value,
.token.control,
.token.directive,
.token.unit {
color: var(--theme-color, #42b983);
}
.token.keyword,
.token.function {
color: #e96900;
}
.token.statement,
.token.regex,
.token.atrule {
color: #22a2c9;
}
.token.placeholder,
.token.variable {
color: #3d8fd1;
}
.token.deleted {
text-decoration: line-through;
}
.token.inserted {
border-bottom: 1px dotted #202746;
text-decoration: none;
}
.token.italic {
font-style: italic;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.important {
color: #c94922;
}
.token.entity {
cursor: help;
}
code .token {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
min-height: 1.5rem;
position: relative;
left: auto;
}

View File

@@ -0,0 +1,228 @@
# 功能介绍
## ⏳ 渲染效果 :id=show
1. *加载提示*
支持在 *mp-html* 标签内部放上自定义的加载提示,内容未加载完成(或为空)时将显示,加载完成后自动隐藏
```wxml
<mp-html>加载中...</mp-html>
```
2. *自动设置标题*
支持自动把 *title* 标签的内容设置到页面标题上,如不需要,可通过 [set-title](basic/prop#set-title) 属性关闭
3. *长按复制*
支持长按复制文本内容,可通过 [selectable](basic/prop#selectable) 属性开启
4. *支持 rpx*
支持 *rpx* 作为单位,自动根据屏幕宽度调整
5. *支持 html 实体*
支持所有形如 *&amp;#123;* 的 *html* 实体和大部分常用的形如 *&amp;nbsp;* 的实体
## 📰 图片效果 :id=img
1. *占位图*
支持设置图片未加载完成时的占位图 [loading-img](basic/prop#loading-img) 和加载出错时的占位图 [error-img](basic/prop#error-img)
2. *懒加载*
内容较长、图片较多时,开启懒加载有助于改善性能,需要时可通过 [lazy-load](basic/prop#lazy-load) 属性开启
3. *自动预览*
图片被点击时,将自动放大预览,如不需要,可通过 [preview-img](basic/prop#preview-img) 属性关闭。还可以在 [imgtap](basic/event#imgtap) 事件中进行自定义处理
自动预览通过特定的处理,可以实现左右滑动查看所有图片、预览重复链接不错位等效果
4. *预览高清图*
同一张图片,可以给显示时和预览时设置不同的链接地址以达到最佳效果
设置方式 1给 *img* 标签增加一个 *original-src* 即可
```html
<!-- 显示时使用 xxx预览时使用 yyy -->
<img src="xxx" original-src="yyy" />
```
设置方式 2通过 [imgList](advanced/api#imgList) 的 *api* 进行设置
5. *长按弹出菜单*
微信和百度平台支持图片长按时弹出菜单,可以进行保存、分享等操作,如不需要,可通过 [show-img-menu](basic/prop#show-img-menu) 属性关闭
6. *装饰图片处理*
有时对于一些小的装饰性图片,可能不希望产生上述效果,此时可以给 *img* 标签设置 *ignore* 属性,将屏蔽预览、弹出菜单等操作,提升体验
```html
<!-- 设置 ignore 属性后这张图片不可预览、不会弹出菜单 -->
<img src="xxx" ignore />
```
在链接内的、*src* 为 *data url* 且没有设置 *original-src* 的图片,默认为不可预览的小图片
7. *支持原大小显示*
本组件通过合理转换,基本实现了和 *html* 中 *img* 的相同效果:没有设置宽度时按原大小显示;设置了宽度时按比例缩放;同时设置宽高时按设置的值显示。不必去考虑小程序中的 *mode* 等问题
8. *支持 svg*
虽然小程序中不支持 *svg* 系列标签,本组件通过在解析过程中转为 *data url* 图片的方式实现了 *svg* 的显示
## 🔗 链接效果 :id=link
1. *支持设置多种状态下的样式*
包括默认状态、点击态的样式,可以在 *src/node/node.wxss* 中进行修改
2. *锚点跳转*
支持跳转内部锚点,使用锚点需要开启 [use-anchor](basic/prop#use-anchor) 属性
跳转方式 1给 *a* 标签的 *href* 属性设置为 *#id*,点击时即可跳转到对应 *id* 的位置(设置为 *#* 则跳转到开头)
跳转方式 2通过 [navigateTo](advanced/api#navigateTo) 的 *api* 进行跳转
默认情况下锚点跳转通过控制页面滚动的方式进行,如果要在 *scroll-view* 内使用,可以通过 [in](advanced/api#in) 的 *api* 进行配置
3. *跳转内部路径*
如果需要点击 *a* 标签跳转到小程序内的一个页面,直接将其 *href* 属性设置为页面路径即可(包括 *tab* 页面,需要使用绝对路径)
```html
<!-- 该链接被点击后将跳转到 /pages/test/test 页面 -->
<a href="/pages/test/test">链接</a>
```
4. *复制外部链接*
对于外部链接,由于小程序无法直接打开,将自动复制到剪贴板,如不需要,可通过 [copy-link](basic/prop#copy-link) 属性关闭
?> 设置 *a* 标签的 *href* 属性时,如果是外部链接需将协议名 *http://* 写完整,否则会被认为是内部路径并尝试跳转
除这些默认的处理外,还可以在 [linktap](basic/event#linktap) 事件中进行自定义处理
## 📈 表格效果 :id=table
1. *支持独立横向滚动*
表格宽度通常较大,容易超出屏幕宽度,导致整体内容一起滚动,影响体验,可以通过设置 [scroll-table](basic/prop#scroll-table) 属性给所有表格添加一个滚动层使其能单独横向滚动
2. *支持常用表格属性*
支持 *border*, *cellspacing*, *cellpadding*, *align* 等常用表格属性
3. *支持含有合并单元格的表格*
附渲染原理:
小程序中没有 *table* 标签,使得显示表格一直是一个难题,本组件主要通过以下三种方式显示表格
| 显示方式 | 适用情况 | 说明 |
|:---:|:---:|:---:|
| *rich-text* 标签 | 表格内部没有链接、图片等特殊标签 | 效果最佳,几乎不需要进行转换 |
| *table* 布局 | 表格内有特殊标签但没有使用合并单元格 | 需要进行一定转换,将 *table*, *tr*, *td* 等标签转为对应的布局 |
| *grid* 布局 | 表格内有特殊标签且使用了合并单元格 | 需要进行复杂的转换将合并单元格用 *grid* 布局表现出来 |
## 📊 列表效果 :id=list
1. *支持多层嵌套*
支持嵌套多层列表,对于无序列表,不同的层级会显示不同的黑点格式
2. *支持多种有序列表格式*
通过设置 *ol* 标签的 *type* 属性,可以显示数字、字母、罗马数字等多种形式的标号
3. *支持不显示标号*
支持通过设置 *list-style:none* 的方式不显示 *li* 标签开头的标号
## 🎬 音视频效果 :id=video
1. *自动暂停*
在存在多个视频的情况下,同时播放可能会影响体验,本组件支持在播放一个视频的时候自动暂停其他所有视频,如不需要,可通过 [pause-video](basic/prop#pause-video) 属性关闭
音频在引入 [audio](advanced/plugin#audio) 插件后也可以实现此效果
2. *多源加载*
不同平台支持播放的格式不同,只设置一个 *src* 可能会出现兼容性问题导致无法播放,因此本组件支持像 *html* 中一样给 *video* 和 *audio* 设置多个 *source*,将按照顺序进行加载,直到可以播放,最大程度上避免无法播放
```html
<!-- 组件将依次加载 xxx 和 yyy -->
<video controls>
<source src="xxx">
<source src="yyy">
</video>
```
3. *自动添加控件*
对于既没有设置 *controls* 也没有设置 *autoplay* 的标签将自动把 *controls* 属性设置为 *true*,避免无法播放,影响体验
## 📡 样式设置 :id=style
样式(*css*)是富文本中最重要的内容之一,本组件提供多种样式设置的方法,可以进行灵活的设置
1. *行内样式*
这是最常用的样式设置方法,直接将需要的样式放在对应标签的 *style* 属性中即可,这种方式仅作用于单个标签,优先级最高
2. *tag-style*
这是本组件独有的一种样式设置方式,可以给某一种标签名设置默认的样式
可以通过 [tag-style](basic/prop#tag-style) 属性设置,具体用法见对应说明
3. *外部样式*
如果希望将某些样式固定的用于渲染,可以添加到 *tools/config.js* 的 *externStyle* 字段中,该方法仅支持 *class* 选择器([2.1.0](changelog/changlog#v210) 版本起支持标签名选择器),优先级最低,具体见 [个性化](overview/quickstart#setting)
需要调整优先级时,可以通过设置 *!important* 实现
另外,通过引入 [style](advanced/plugin#style) 插件,还可以实现匹配 *style* 标签中样式的功能
## 🍭 全面的标签支持 :id=tag
本组件支持以下标签和属性:
| 标签 | 属性 |
|:---:|:---:|
| a | href |
| abbr | |
| address | |
| article | |
| aside | |
| audio | author, controls, loop, name, poster, src |
| b | |
| base | href |
| big | |
| blockquote | |
| body | |
| br | |
| caption | |
| center | |
| cite | |
| code | |
| col | span |
| colgroup | span |
| dd | |
| del | |
| div | |
| dl | |
| dt | |
| em | |
| embed | autostart, loop, src, type |
| fieldset | |
| font | color, face, size |
| footer | |
| h1 | |
| h2 | |
| h3 | |
| h4 | |
| h5 | |
| h6 | |
| head | |
| header | |
| hr | |
| html | |
| i | |
| img | ignore, original-src, src |
| ins | |
| label | |
| legend | |
| li | |
| mark | |
| nav | |
| ol | start, type |
| p | |
| pre | |
| q | |
| rt | |
| ruby | |
| s | |
| section | |
| small | |
| source | src |
| span | |
| strike | |
| strong | |
| style | |
| sub | |
| sup | |
| table | border, cellpadding, cellspacing |
| tbody | |
| td | colspan, rowspan |
| tfoot | |
| th | colspan, rowspan |
| thead | |
| tr | |
| tt | |
| u | |
| ul | |
| video | autoplay, controls, loop, muted, object-fit, poster, src |
说明:
1. 除上面列举的外,还支持 *svg* 系列的标签和 *id*、*style*、*class*、*align*、*height*、*width*、*dir* 属性
2. 对于不信任的标签,除个别将被直接移除,都会被转为一个行内标签,因此可以使用更多语义化标签
## 🌟 稳定性 :id=stable
本组件的解析脚本能够支持多种 *html* 格式,具有强大的稳定性:
1. 标签名中可以含有 *:* 等特殊字符(如 *o:p*
2. 标签名和属性名大小写不敏感
3. 属性值可以不加引号、加单引号、加双引号,也可以缺省(默认 *true*
4. 属性之间可以没有空格(通过引号划分)、有空格(可以多个)、有换行符
5. 支持正常格式、*CDATA* 等多种形式的注释
同时,对于一些错误情况,程序也能够自动处理:
1. 标签首尾不匹配
2. 属性值中冒号不匹配
3. 标签未闭合
以下情况均能正确解析:
```html
<!-- 不同的属性格式 -->
<font face="宋体" color='green' size=7>Hello</font>
<!-- 标签首尾不匹配或未闭合 -->
<div> World</section>
<!-- 大小写搭配 -->
<dIv StYle="color:green">!</DIv>
```

View File

@@ -0,0 +1,287 @@
# 快速开始 :id=quickstart
## 📦 源码获取 :id=source
#### 小程序方式 :id=mp
!> 该方式暂不可用
打开微信小程序 *富文本插件*,点击 *获取组件包* 按钮,选择使用平台、[扩展插件](advanced/plugin) 以及 [个性化设置](#setting) 后即可生成组件包
![富文本插件](../assets/case/富文本插件.jpg)
#### npm 方式 :id=npm
```bash
# 通过 npm 获取
npm install mp-html
# 或通过 yarn 获取
yarn add mp-html
```
需要升级时:
```bash
# 通过 npm 升级
npm update mp-html
# 或通过 yarn 升级
yarn upgrade mp-html
```
#### git 方式 :id=git
```bash
# 通过 github 获取
git clone https://github.com/jin-yufeng/mp-html.git
# 或通过 gitee 获取
git clone https://gitee.com/jin-yufeng/mp-html.git
```
#### 下载 zip :id=zip
*github releases*[https://github.com/jin-yufeng/mp-html/releases](https://github.com/jin-yufeng/mp-html/releases)
*gitee releases*[https://gitee.com/jin-yufeng/mp-html/releases](https://gitee.com/jin-yufeng/mp-html/releases)
#### QQ 群 :id=qqgroup
*QQ* 交流群的群文件中也可以获取组件包
交流群1: `699734691`
交流群2: `778239129`
交流群3: `960265313`
## 📚 引入和使用 :id=use
### 📗 原生框架 :id=miniprogram
#### 引入 :id=mp-import
- npm 方式
?> 本方法仅适用于微信、*QQ* 小程序
1. 在小程序项目根目录下通过 [npm](#npm) 安装组件包
2. 开发者工具中勾选 *使用 npm 模块*(若没有此选项则不需要)并点击 *工具* - *构建 npm*
3. 在需要使用页面的 *json* 文件中添加
```json
{
"usingComponents": {
"mp-html": "mp-html"
}
}
```
- 源码引入
?> 本方法适用于所有平台
1. 将 [源码](#source) 中对应平台的代码包(*dist/platform*)拷贝到 *components* 目录下,更名为 *mp-html*
2. 在需要使用页面的 *json* 文件中添加
```json
{
"usingComponents": {
"mp-html": "/components/mp-html/index"
}
}
```
#### 使用 :id=mp-use
1. 在需要使用页面的 *wxml* 文件中添加
```wxml
<mp-html content="{{html}}" />
```
2. 在需要使用页面的 *js* 文件中添加
```javascript
Page({
onLoad () {
this.setData({
html: '<div>Hello World!</div>'
})
}
})
```
支持的 [属性](basic/prop) 和 [事件](basic/event) 见对应文档
### 📘 uni-app 框架 :id=uni-app
#### uni-modules 方式 :id=uni-modules
?> 本方法需要使用 *3.1.0+* 版本的 *HBuilder X* 开发
1. 进入 [插件市场](https://ext.dcloud.net.cn/plugin?id=805),点击右上角的 *使用 HBuilder X 导入插件* 按钮导入项目或点击 *下载插件ZIP* 按钮下载插件包并解压到项目的 *uni_modules/mp-html* 目录下
2. 在需要使用页面的 *(n)vue* 文件中添加
```vue
<template>
<view>
<!-- 不需要引入,可直接使用 -->
<mp-html :content="html" />
</view>
</template>
<script>
export default {
data () {
return {
html: '<div>Hello World!</div>'
}
}
}
</script>
```
3. 需要更新版本时在 *HBuilder X* 中右键 *uni_modules/mp-html* 目录选择 *从插件市场更新* 即可
#### 源码方式 :id=uni-app-source
1. 将 [源码](#source) 中 *dist/uni-app* 内的内容拷贝到 **项目根目录** 下
!> [插件市场](https://ext.dcloud.net.cn/plugin?id=805) 的 *非 uni_modules* 版本无法更新,请从其他方式获取 [源码](#source)
2. 在需要使用页面的 *(n)vue* 文件中添加
```vue
<template>
<view>
<mp-html :content="html" />
</view>
</template>
<script>
import mpHtml from '@/components/mp-html/mp-html'
export default {
// HBuilderX 2.5.5+ 可以通过 easycom 自动引入
components: {
mpHtml
},
data () {
return {
html: '<div>Hello World!</div>'
}
}
}
</script>
```
#### npm 方式 :id=uni-app-npm
1. 在项目根目录下通过 [npm](#npm) 安装组件包
2. 在需要使用页面的 *(n)vue* 文件中添加
```vue
<template>
<view>
<mp-html :content="html" />
</view>
</template>
<script>
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
export default {
// 不可省略
components: {
mpHtml
},
data () {
return {
html: '<div>Hello World!</div>'
}
}
}
</script>
```
!> 使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
!> 如果在 *nvue* 中使用还要将 *dist/uni-app/static* 目录下的内容拷贝到项目的 *static* 目录下,否则无法运行
支持的 [属性](basic/prop) 和 [事件](basic/event) 见对应文档
由于 *uni-app* 编译过程中会进行压缩,构建 *uni-app* 包时基本不进行压缩,包的体积与原生包相比较大
#### 关于 nvue :id=nvue
*nvue* 使用原生渲染,不支持部分 *css* 样式,为实现和 *html* 相同的效果,组件内部通过 *web-view* 进行渲染,性能上差于原生,根据 *weex* 官方建议,*web* 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 *richtext*)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 *vue* 页面
由于渲染方式与其他端不同,有以下限制:
1. 不支持 [lazy-load](basic/prop#lazy-load) 属性
2. 视频不支持全屏播放
3. 如果在 *flex-direction: row* 的容器中使用,需要给组件设置宽度或设置 *flex: 1* 占满剩余宽度
### 📙 其他框架 :id=other
其他框架没有专用包,但也可以引入对应平台的原生包使用,具体方法参考各框架官方文档
- taro
[https://taro-docs.jd.com/docs/hybrid#使用原生组件](https://taro-docs.jd.com/docs/hybrid#%E4%BD%BF%E7%94%A8%E5%8E%9F%E7%94%9F%E7%BB%84%E4%BB%B6)
!> 在 *taro2* 中使用请使用 [示例项目](#demo) 中的非压缩组件包,否则可能出现异常,详见 [#301](https://github.com/jin-yufeng/mp-html/issues/301)
!> 在 *taro3* 的 *vue3* 中使用时需要修改 *content* 属性的属性名或使用 [setContent](advanced/api#setContent) 方法设置内容,详见 [taro#13146](https://github.com/NervJS/taro/issues/13146)
?> 在 *taro* 中使用时属性名需用驼峰写法,如 *copy-link* 属性应写作 *copyLink*
?> 需要 *taro* 专用包的开发者欢迎参与 [需求调研](https://github.com/jin-yufeng/mp-html/issues/374)
- kbone
[https://wechat-miniprogram.github.io/kbone/docs/guide/advanced.html#使用小程序自定义组件](https://wechat-miniprogram.github.io/kbone/docs/guide/advanced.html#%E4%BD%BF%E7%94%A8%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6)
- chameleon
[https://cml.js.org/docs/io.html#怎么引入微信小程序组件](https://cml.js.org/docs/io.html#%E6%80%8E%E4%B9%88%E5%BC%95%E5%85%A5%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%BB%84%E4%BB%B6)
- remax
[https://remaxjs.org/guide/basic/custom-component](https://remaxjs.org/guide/basic/custom-component)
## 💡 运行示例 :id=demo
1. 安装依赖
```bash
# 通过 npm 安装
npm install
# 或通过 yarn 安装
yarn
```
2. 生成 *demo* 项目
```bash
# 生成微信示例项目到 dev/mp-weixin
npm run dev:weixin
# 生成 qq 示例项目到 dev/mp-qq
npm run dev:qq
# 生成百度示例项目到 dev/mp-baidu
npm run dev:baidu
# 生成支付宝示例项目到 dev/mp-alipay
npm run dev:alipay
# 生成头条示例项目到 dev/mp-toutiao
npm run dev:toutiao
# 生成 uni-app 示例项目到 dev/uni-app
npm run dev:uni-app
```
3. 运行
用各平台的开发者工具打开 *dev/platform* 文件夹即可
4. 监听修改
如果要对 *demo* 项目进行修改(如放入自己的测试内容)可在 *tools/demo* 目录中进行修改
如果要对组件包进行修改可在 *src* 目录中进行修改(参考 [二次开发](advanced/develop)
可以通过 *watch* 命令监听修改并实时编译到 *dev* 目录下
```bash
# 监听并实时生成微信示例项目到 dev/mp-weixin
npm run watch:weixin
# 监听并实时生成 qq 示例项目到 dev/mp-qq
npm run watch:qq
# 监听并实时生成百度示例项目到 dev/mp-baidu
npm run watch:baidu
# 监听并实时生成支付宝示例项目到 dev/mp-alipay
npm run watch:alipay
# 监听并实时生成头条示例项目到 dev/mp-toutiao
npm run watch:toutiao
```
## 🎈 个性化 :id=setting
?> 本组件提供了以下配置项可以生成个性化的组件包,配置项可以通过 [示例小程序](#mp) 进行设置,或参考 [使用插件包](advanced/plugin#use) 中的 *npm* 方式自行设置配置文件并进行打包
#### plugins
需要使用的插件名称列表,关于插件的详细信息见 [插件](advanced/plugin)
#### externStyle
!> 暂不支持对图片设置宽高,详见 [#426](https://github.com/jin-yufeng/mp-html/issues/426)
外部样式,一个 *css* 字符串,将被用于 *html* 的渲染,但仅支持 *class* 选择器
?> [2.1.0](changelog/changelog#v210) 版本起增加支持 **标签名选择器**,通过这种方式给标签设置的样式全局有效,在样式较长或作用标签数量较大时这种方法的性能要高于 [tag-style](basic/prop#tag-style) 属性,且写法更加灵活(可以与伪类、*class* 配合等)
需要注意的是,由于 [组件](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F) 内仅支持 *class* 选择器,直接将标签名选择器 **写在 wxss 中是无效的**,必须写在本字段中,构建过程中会自动转换为 *class* 选择器
?> [2.3.1](changelog/changelog#v231) 版本起,组件取消样式隔离,部分平台(微信小程序 *2.11.0+* 基础库完全支持;*QQ*、百度小程序部分情况下支持)支持直接引入页面样式中的 *class* 选择器,无需使用本方法引入;若遇到样式无法生效或需要使用标签名选择器,则仍需要使用本方法
#### customElements
自定义标签列表([2.2.0](changelog/changelog#v220) 版本起支持),可以在这里注册需要使用的小程序功能标签(如 *ad*、*ad-custom*、*official-account*、*map* 等)
每个标签为一个 *object*,需要包含以下字段,注册完成后即可在传入的 `html` 中使用该组件
| 字段名 | 功能 | 类型 | 必填 | 备注 |
|:---:|:---:|:---:|:---:|:---:|
| name | 标签名 | String | 是 | |
| attrs | 需要使用的属性列表 | String[] | 否 | class 和 style 默认添加,无需填写 |
| platforms | 需要使用的平台 | String[] | 否 | 默认添加到所有平台,可以从 h5、mp-weixin、mp-qq、mp-baidu、mp-alipay、mp-toutiao、app-plus 中选择,不区分大小写 |
?> 仅能添加没有子节点的标签,且不响应任何事件,如果需要更加复杂的功能,可以通过 [插件](advanced/plugin#develop) 实现
示例:
```javascript
// 设置完成后 html 中添加 <ad unit-id="xxx" /> 即可使用该标签
customElements: [{
name: 'ad',
attrs: ['unit-id']
}]
```
剩余的是一些编译过程中压缩工具的配置,可以按需要设置

View File

@@ -0,0 +1,16 @@
# 📝 贡献指南 :id=contribution
本组件欢迎所有开发者对以下方面提交 [pr](https://github.com/jin-yufeng/mp-html/pulls),一起完善本组件
1. 针对 [issue](https://github.com/jin-yufeng/mp-html/issues) 中 *bug* 的修复
2. 实现新功能
- 在主包中添加(需确保该功能适用面广且体积不大)
- 新增扩展插件(参考 [开发插件](advanced/plugin#develop)
3. 文档错误修复
开发过程中请注意:
1. 不要修改 [dist](https://github.com/jin-yufeng/mp-html/tree/master/dist) 目录下的文件(该文件夹在版本更新时会进行构建)和配置文件
2. 代码风格参考 [standard](https://standardjs.com)
3. 可参考 [二次开发](advanced/develop) 中的说明
感谢所有 [贡献者](https://github.com/jin-yufeng/mp-html/graphs/contributors) 对本组件的贡献

View File

@@ -0,0 +1,152 @@
# 📘 常见问题 :id=question
## 无法使用扩展功能 :id=plugin
由于小程序空间有限,默认组件包中仅包含基本功能,其他 [扩展](advanced/plugin) 按需添加。
!> 编辑器、*markdown*、代码高亮、关键词搜索、*latex* 公式等属于 [扩展](advanced/plugin) 功能,直接获取的组件包中 **不包含** 这些功能
需要使用扩展功能的,参考 [使用插件](advanced/plugin#use) 的说明,通过示例小程序或 *npm* 打包的方式获取包含扩展功能的组件包替换原组件包,然后按照各个 [扩展](advanced/plugin) 插件的说明和示例进行使用
## 图片底部缝隙 :id=img
由于图片的默认 *display**inline-block*,多个图片连接时底部会有一条缝隙,可以通过设置 *vertical-align: bottom*, *display:block**float:left* 等方法去除
设置以上样式后仍有一个小缝隙的,可以进一步添加 *margin-top:-1px*
设置方法参考 [样式设置](overview/feature#style)
## 标签原样显示 :id=entity
如果出现渲染后 *html* 标签还是原样显示,请检查传入的 *html* 是否被转义:
1. *&lt;**&gt;* 被转义为 *&amp;lt;**&amp;gt;*
2. *&lt;img* 被转义为 *< img*
如果是则需要进行替换
```javascript
// 第一种
html = html.replace(/&lt;/g, '<').replace(/&gt;/g, '>') // 如果还转义了其他字符如 &amp; 等也要进行替换
// 第二种
html = html.replace(/< img/g, '<img')
```
## 空白符失效 :id=space
*html* 中,默认会将多个空白符(包括换行)合并为一个空格,若不希望如此,可参考以下方法:
1. 替换为指定标签或实体编码
换行可以使用 *br* 标签
连续空格可以使用 *&amp;nbsp;* *&amp;ensp;* *&amp;emsp;* 等实体编码
```javascript
html = html.replace(/\n/g, '<br>') // 替换换行符
```
2. 通过 *css* 设置 *white-space*
将 *css* 中的 *white-space* 设置为 *pre-line* 可以保留换行符,设置为 *pre-wrap* 可以保留空格和换行符
给特定标签设置的方法见 [样式设置](overview/feature#style),需要注意的是如果通过外部样式设置 *white-space* 将不会生效,因为在解析过程中为减小解析结果大小提前进行了空白符合并(解析过程中无法获取外部样式)
[2.1.2](changelog/changelog#v212) 版本起可以通过 [container-style](basic/prop#container-style) 属性全局设置 *white-space*
```html
<mp-html container-style="white-space:pre-wrap" />
```
## 表格没有边框 :id=table
*html* 中的 *table* 标签默认没有边框,一些编辑器有自带的表格样式,没有引入就会导致表格边框缺失,可通过以下方式解决:
1. 给 `table` 标签设置 `border` 属性
```javascript
html = html.replace(/<table/g, '<table border="1"')
```
2. 通过 [tag-style](basic/prop#tag-style) 属性或 [外部样式](overview/quickstart#externStyle) 给表格标签设置默认样式
```javascript
tagStyle: {
table: 'border-top: 1px solid gray; border-left: 1px solid gray; border-collapse:collapse',
th: 'border-right: 1px solid gray; border-bottom: 1px solid gray;',
td: 'border-right: 1px solid gray; border-bottom: 1px solid gray;'
}
```
## 多媒体内容不显示 :id=media
若出现 图片不显示/无法预览、音频/视频无法播放 等问题,可通过以下方式检查:
- 若视频不显示,请检查 *html* 中的视频是否为 *video* 标签(*iframe* 标签在小程序端仅微信小程序可以通过 [腾讯视频插件](advanced/plugin#txv-video) 播放,其他不支持)
- 若图片无法预览,请检查该图片是否为 *base64* 格式,目前不支持 *base64* 图片预览(原因参考 [#249](https://github.com/jin-yufeng/mp-html/issues/249#issuecomment-755290540);如果确需使用,可将 [parser.js#L425](https://github.com/jin-yufeng/mp-html/blob/master/src/miniprogram/parser.js#L425) 去掉,在部分平台可能可以使用)
- 若是 *svg* 无法显示,请检查是否包含响应式 *animate* 等标签,目前不支持(原因参考 [#569](https://github.com/jin-yufeng/mp-html/issues/569)),除此之外可能是 *svg* 标签名和属性名大小写问题,可以在 [svgDict](https://github.com/jin-yufeng/mp-html/blob/master/src/miniprogram/parser.js#L61) 中补充
- 若非以上原因依然无法显示,将该 图片/音频/视频 的链接放在原生标签 [image](https://developers.weixin.qq.com/miniprogram/dev/component/image.html)、[audio](https://developers.weixin.qq.com/miniprogram/dev/component/audio.html)、[video](https://developers.weixin.qq.com/miniprogram/dev/component/video.html) 或 api [wx.previewImage](https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.previewImage.html) 中进行测试,如果也不能显示,则链接存在问题
若出现这种情况,可按照以下方法进行检查
1. 检查链接是否完整(缺少域名可以设置 [domain](basic/prop#domain) 属性)、有效(可以放在浏览器中测试)
2. 检查链接是否存在防盗链(可以参考 [#387](https://github.com/jin-yufeng/mp-html/issues/387)
3. 检查编码和格式是否支持(参考 [音频格式](https://developers.weixin.qq.com/miniprogram/dev/api/media/audio/InnerAudioContext.html#%E6%94%AF%E6%8C%81%E6%A0%BC%E5%BC%8F)、[视频格式和编码](https://developers.weixin.qq.com/miniprogram/dev/component/video.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F)
4. 查看 *error* 事件中的错误信息
## 长内容处理 :id=long
如果富文本内容特别长,可以考虑以下方案:
1. 分次渲染
小程序中单次 *setData* 大小不能超过 *1MB*,如果内容过长,可以先将内容拆分成几段,首先渲染第一段,后续内容在适当的时机(触底等)通过 [setContent](/advanced/api#setContent) 方法追加到末尾
2. 分页渲染
以上方案虽然能解决一次性设置数据过大问题,但过长的内容仍会导致总标签数量过大,页面性能下降的问题,因此,对于过长的内容,应该分页进行显示,每页仅显示一部分
## 懒加载失效 :id=lazy-load
如果富文本内容全部(或大部分)是图片,由于其图片未加载时大小为零,即使数量很多也会全部进入视图范围,导致懒加载失效,若出现这种情况,可通过以下方案解决
1. 通过 [tag-style](basic/prop#tag-style) 属性等方法给 *img* 父级标签的样式里设置 *min-height*(如果直接给图片本身设置 *min-height*,可能在加载过程中出现变形的情况)
2. 通过 [loading-img](basic/prop#loading-img) 属性设置加载过程中的占位图
## 一般标签的点击事件 :id=tap
默认情况下,组件仅支持 *a* 和 *img* 标签的点击事件,如果希望给标签添加点击事件,又不希望应用 *a* 标签的默认样式,可以使用没有 *href* 属性的 *a* 标签,该标签不会应用链接的默认样式,但被点击时会触发 *linktap* 事件,可以在 *data-* 属性中记录需要的信息
## 基础库要求 :id=lib
本组件尽最大可能兼容低版本基础库,各平台只要满足 **最低要求** 即可正常使用(不报错,但高基础库支持的功能不可用),可按照实际需要设置最低基础库要求
微信:
| 版本 | 功能 | 占比 |
|:---:|:---:|:---:|
| 2.9.0+ | ios 支持 webp 图片 | >99.74% |
| 2.7.0+ | 支持图片长按弹出菜单 | >99.87% |
| 2.4.0+ | 支持 video 同层渲染 | >99.90% |
| 2.3.0+ | 支持使用云文件 ID | >99.98% |
| 2.2.1+ | 支持 npm 引入 | >99.99% |
| 1.9.94+ | 支持使用 ad | >99.99% |
| 1.6.6+ | 可以使用 | >99.99% |
QQ
| 版本 | 功能 |
|:---:|:---:|
| 安卓 1.10.2+ios 1.4.7+ | 支持 video 同层渲染 |
| 1.1.7+ | 可以使用 |
百度:
| 版本 | 功能 | 占比 |
|:---:|:---:|:---:|
| 3.180.1+ | ios 支持 webp 图片 | >99.04% |
| 3.170.1+ | 支持图片长按弹出菜单 | >99.19% |
| 3.90.25+ | 可以使用 | >99.99% |
*3.240.10* - *3.260.25* 基础库由于 [此问题](https://smartprogram.baidu.com/forum/topic/show/125787),需要将以下样式拷贝到 *app.css* 以保证正确显示
```css
/* a 标签默认效果 */
._a {
padding: 1.5px 0 1.5px 0;
color: #366092;
word-break: break-all;
}
/* a 标签点击态效果 */
._hover {
text-decoration: underline;
opacity: 0.7;
}
/* 图片默认效果 */
._img {
max-width: 100%;
-webkit-touch-callout: none;
}
```
支付宝:
| 版本 | 功能 | 占比 |
|:---:|:---:|:---:|
| 1.11.0+ | 可以使用 | >97.95% |
头条:
| 版本 | 功能 |
|:---:|:---:|
| 1.59.0+ | 支持 video 同层渲染 |
| 1.19.0+ | 支持使用 ad |
| 1.7.0+ | 可以使用 |
!> 不支持 *video* 同层渲染时,需要注意原生组件的限制,视频的层级最高,且不能在 *scroll-view* 中使用

View File

@@ -0,0 +1,30 @@
# 📩 反馈 :id=feedback
## 注意事项 :id=notice
反馈问题前,请先确认以下方式无法解决:
1. 在 [常见问题](question/faq) 中查看是否已有解决方案
2. 在 [issue](https://github.com/jin-yufeng/mp-html/issues) 中查找是否已有相同或类似的问题
3. 如果是对于渲染效果的问题,请先在下方的模拟器中尝试,如果在浏览器中渲染也不正常,请检查样式
<div style="display: flex;">
<div style="flex: 1; margin: 0 40px; display: flex; flex-direction: column;">
<textarea id="input" style="flex: 1; width: 100%; padding: 5px; resize: none;" placeholder="请输入 html 内容"></textarea>
<div style="text-align: center; margin-top: 10px;">
<button onclick="reset()">清空</button>
<button onclick="render()" style="margin-left: 20px;">渲染</button>
</div>
</div>
<div style="flex: 0 0 320px; height: 568px; box-shadow: 0px 0px 10px #c0c0c0;">
<iframe id="show" style="width: 100%; height: 100%; margin: 0;"></iframe>
</div>
</div>
## 反馈方式 :id=method
1. *issue* 方式
*github* 中提出 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose)(推荐,解决方案可以给其他人参考)
2. *QQ* 群方式
加入 *QQ* 交流群 *699734691**778239129*,并发送和交流相关问题
3. 邮箱方式
如果不希望公开问题,可以通过邮箱方式联系,发送邮件到 *mp_html@126.com*,邮件格式可参考 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose)
!> 注意务必按照模板要求填写,未描述清楚或无法复现的问题将不予处理