diff --git a/test_client/src/views/crm/consumer.vue b/test_client/src/views/crm/consumer.vue
index 33ca475..d3d0749 100644
--- a/test_client/src/views/crm/consumer.vue
+++ b/test_client/src/views/crm/consumer.vue
@@ -45,6 +45,9 @@
icon="el-icon-refresh-left"
@click="resetFilter"
>刷新重置
+
+ 创建时间
+
新增
@@ -115,7 +118,7 @@
{{ scope.row.workscope_name }}
-
+
{{ scope.row.create_time }}
@@ -246,6 +249,8 @@ export default {
},
data() {
return {
+ tableKey: 0,
+ showCreate: false,
uploadUrl: uploadUrl(),
popovervisible: false,
consumer: defaultConsumer,
diff --git a/test_client/src/views/news/newsupdate.vue b/test_client/src/views/news/newsupdate.vue
index 29620da..8347395 100644
--- a/test_client/src/views/news/newsupdate.vue
+++ b/test_client/src/views/news/newsupdate.vue
@@ -54,7 +54,7 @@ export default {
{ required: true, message: "请输入", trigger: "blur" }
],
},
- is_show: false
+ is_show: true
}
},
created() {
diff --git a/test_mini/components/parser/audio/audio.js b/test_mini/components/parser/audio/audio.js
new file mode 100644
index 0000000..e50640d
--- /dev/null
+++ b/test_mini/components/parser/audio/audio.js
@@ -0,0 +1,100 @@
+/*
+ audio 扩展包
+ github:https://github.com/jin-yufeng/Parser
+ docs:https://jin-yufeng.github.io/Parser
+ author:JinYufeng
+*/
+Component({
+ data: {
+ time: '00:00'
+ },
+ properties: {
+ author: String,
+ autoplay: Boolean,
+ controls: Boolean,
+ loop: Boolean,
+ name: String,
+ poster: String,
+ src: {
+ type: String,
+ observer(src) {
+ this.setSrc(src);
+ }
+ }
+ },
+ created() {
+ this._ctx = wx.createInnerAudioContext();
+ this._ctx.onError((err) => {
+ this.setData({
+ error: true
+ })
+ this.triggerEvent('error', err);
+ })
+ this._ctx.onTimeUpdate(() => {
+ var time = this._ctx.currentTime,
+ min = parseInt(time / 60),
+ sec = Math.ceil(time % 60),
+ data = {};
+ data.time = (min > 9 ? min : '0' + min) + ':' + (sec > 9 ? sec : '0' + sec);
+ if (!this.lastTime) data.value = time / this._ctx.duration * 100; // 不在拖动状态下
+ this.setData(data);
+ })
+ this._ctx.onEnded(() => {
+ this.setData({
+ playing: false
+ })
+ })
+ },
+ detached() {
+ this._ctx.destroy();
+ },
+ pageLifetimes: {
+ show() {
+ if (this.data.playing && this._ctx.paused)
+ this._ctx.play();
+ }
+ },
+ methods: {
+ // 设置源
+ setSrc(src) {
+ this._ctx.autoplay = this.data.autoplay;
+ this._ctx.loop = this.data.loop;
+ this._ctx.src = src;
+ },
+ // 播放
+ play() {
+ this._ctx.play();
+ this.setData({
+ playing: true
+ })
+ this.triggerEvent('play');
+ },
+ // 暂停
+ pause() {
+ this._ctx.pause();
+ this.setData({
+ playing: false
+ })
+ this.triggerEvent('pause');
+ },
+ // 移动进度条
+ seek(sec) {
+ this._ctx.seek(sec);
+ },
+ // 内部方法
+ _seeking(e) {
+ if (e.timeStamp - this.lastTime < 200) return;
+ var time = Math.round(e.detail.value / 100 * this._ctx.duration),
+ min = parseInt(time / 60),
+ sec = time % 60;
+ this.setData({
+ time: (min > 9 ? min : '0' + min) + ':' + (sec > 9 ? sec : '0' + sec)
+ })
+ this.lastTime = e.timeStamp;
+ },
+ _seeked(e) {
+ this.seek(e.detail.value / 100 * this._ctx.duration);
+ this.lastTime = void 0;
+ }
+ }
+})
\ No newline at end of file
diff --git a/test_mini/components/parser/audio/audio.json b/test_mini/components/parser/audio/audio.json
new file mode 100644
index 0000000..32640e0
--- /dev/null
+++ b/test_mini/components/parser/audio/audio.json
@@ -0,0 +1,3 @@
+{
+ "component": true
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/audio/audio.wxml b/test_mini/components/parser/audio/audio.wxml
new file mode 100644
index 0000000..bd30fbd
--- /dev/null
+++ b/test_mini/components/parser/audio/audio.wxml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+ {{name||'未知音频'}}
+ {{author||'未知作者'}}
+
+ {{time}}
+
\ No newline at end of file
diff --git a/test_mini/components/parser/audio/audio.wxss b/test_mini/components/parser/audio/audio.wxss
new file mode 100644
index 0000000..d193004
--- /dev/null
+++ b/test_mini/components/parser/audio/audio.wxss
@@ -0,0 +1,75 @@
+:host {
+ display: inline-block;
+}
+.author {
+ color: #888;
+ font-size: 28rpx;
+ width: 140rpx;
+}
+.author, .name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.button {
+ align-items: center;
+ background-color: rgb(0, 0, 0, 0.2);
+ border: 3.5rpx solid white;
+ border-radius: 50%;
+ display: flex;
+ height: 47rpx;
+ justify-content: center;
+ opacity: 0.9;
+ overflow: hidden;
+ width: 47rpx;
+}
+.contain {
+ background-color: #fcfcfc;
+ border: 1px solid #e0e0e0;
+ border-radius: 2px;
+ display: flex;
+ position: relative;
+ width: 650rpx;
+}
+.name {
+ font-size: 33rpx;
+ line-height: 80rpx;
+ width: 320rpx;
+}
+.pause {
+ width: 16.5rpx;
+ height: 16.5rpx;
+ background-color: white;
+}
+.play {
+ border-bottom: 10rpx solid transparent;
+ border-left: 18rpx solid white;
+ border-top: 10rpx solid transparent;
+ margin-left: 5rpx;
+}
+.poster {
+ align-items: center;
+ background-color: #e6e6e6;
+ background-size: contain;
+ display: flex;
+ height: 152.35rpx;
+ justify-content: center;
+ width: 152.35rpx;
+}
+.slider {
+ position: absolute;
+ bottom: 18.75rpx;
+ margin: 0;
+ right: 35.15rpx;
+ width: 316.4rpx;
+}
+.title {
+ flex: 1;
+ margin: 10rpx 0 0 35.15rpx;
+ text-align: left;
+}
+.time {
+ color: #888;
+ font-size: 28rpx;
+ margin: 16.4rpx 35.15rpx 0 0;
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/libs/CssHandler.js b/test_mini/components/parser/libs/CssHandler.js
new file mode 100644
index 0000000..fd9c486
--- /dev/null
+++ b/test_mini/components/parser/libs/CssHandler.js
@@ -0,0 +1,102 @@
+/*
+ 解析和匹配 Css 的选择器
+ github:https://github.com/jin-yufeng/Parser
+ docs:https://jin-yufeng.github.io/Parser
+ author:JinYufeng
+ update:2020/03/15
+*/
+var cfg = require('./config.js');
+class CssHandler {
+ constructor(tagStyle) {
+ var styles = Object.assign({}, cfg.userAgentStyles);
+ for (var item in tagStyle)
+ styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
+ this.styles = styles;
+ }
+ getStyle = data => this.styles = new CssParser(data, this.styles).parse();
+ match(name, attrs) {
+ var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
+ if (attrs.class) {
+ var items = attrs.class.split(' ');
+ for (var i = 0, item; item = items[i]; i++)
+ if (tmp = this.styles['.' + item])
+ matched += tmp + ';';
+ }
+ if (tmp = this.styles['#' + attrs.id])
+ matched += tmp + ';';
+ return matched;
+ }
+}
+module.exports = CssHandler;
+class CssParser {
+ constructor(data, init) {
+ this.data = data;
+ this.floor = 0;
+ this.i = 0;
+ this.list = [];
+ this.res = init;
+ this.state = this.Space;
+ }
+ parse() {
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ return this.res;
+ }
+ section = () => this.data.substring(this.start, this.i);
+ isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ // 状态机
+ Space(c) {
+ if (c == '.' || c == '#' || this.isLetter(c)) {
+ this.start = this.i;
+ this.state = this.Name;
+ } else if (c == '/' && this.data[this.i + 1] == '*')
+ this.Comment();
+ else if (!cfg.blankChar[c] && c != ';')
+ this.state = this.Ignore;
+ }
+ Comment() {
+ this.i = this.data.indexOf('*/', this.i) + 1;
+ if (!this.i) this.i = this.data.length;
+ this.state = this.Space;
+ }
+ Ignore(c) {
+ if (c == '{') this.floor++;
+ else if (c == '}' && !--this.floor) this.state = this.Space;
+ }
+ Name(c) {
+ if (cfg.blankChar[c]) {
+ this.list.push(this.section());
+ this.state = this.NameSpace;
+ } else if (c == '{') {
+ this.list.push(this.section());
+ this.Content();
+ } else if (c == ',') {
+ this.list.push(this.section());
+ this.Comma();
+ } else if (!this.isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
+ this.state = this.Ignore;
+ }
+ NameSpace(c) {
+ if (c == '{') this.Content();
+ else if (c == ',') this.Comma();
+ else if (!cfg.blankChar[c]) this.state = this.Ignore;
+ }
+ Comma() {
+ while (cfg.blankChar[this.data[++this.i]]);
+ if (this.data[this.i] == '{') this.Content();
+ else {
+ this.start = this.i--;
+ this.state = this.Name;
+ }
+ }
+ Content() {
+ this.start = ++this.i;
+ if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
+ var content = this.section();
+ for (var i = 0, item; item = this.list[i++];)
+ if (this.res[item]) this.res[item] += ';' + content;
+ else this.res[item] = content;
+ this.list = [];
+ this.state = this.Space;
+ }
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/libs/MpHtmlParser.js b/test_mini/components/parser/libs/MpHtmlParser.js
new file mode 100644
index 0000000..6368a4f
--- /dev/null
+++ b/test_mini/components/parser/libs/MpHtmlParser.js
@@ -0,0 +1,528 @@
+/*
+ 将 html 解析为适用于小程序 rich-text 的 DOM 结构
+ github:https://github.com/jin-yufeng/Parser
+ docs:https://jin-yufeng.github.io/Parser
+ author:JinYufeng
+ update:2020/04/26
+*/
+var cfg = require('./config.js'),
+ blankChar = cfg.blankChar,
+ CssHandler = require('./CssHandler.js'),
+ screenWidth = wx.getSystemInfoSync().screenWidth;
+try {
+ var emoji = require('./emoji.js');
+} catch (e) {}
+class MpHtmlParser {
+ constructor(data, options = {}) {
+ this.attrs = {};
+ this.compress = options.compress;
+ this.CssHandler = new CssHandler(options.tagStyle, screenWidth);
+ this.data = data;
+ this.domain = options.domain;
+ this.DOM = [];
+ this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
+ this.protocol = this.domain && this.domain.includes('://') ? this.domain.split('://')[0] : 'http';
+ this.state = this.Text;
+ this.STACK = [];
+ this.useAnchor = options.useAnchor;
+ this.xml = options.xml;
+ }
+ parse() {
+ if (emoji) this.data = emoji.parseEmoji(this.data);
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ if (this.state == this.Text) this.setText();
+ while (this.STACK.length) this.popNode(this.STACK.pop());
+ if (this.DOM.length) {
+ this.DOM[0].PoweredBy = 'Parser';
+ if (this.title) this.DOM[0].title = this.title;
+ }
+ return this.DOM;
+ }
+ // 设置属性
+ setAttr() {
+ var name = this.getName(this.attrName);
+ if (cfg.trustAttrs[name]) {
+ var val = this.attrVal;
+ if (val) {
+ if (name == 'src') this.attrs[name] = this.getUrl(this.decode(val, 'amp'));
+ else if (name == 'href' || name == 'style') this.attrs[name] = this.decode(val, 'amp');
+ else this.attrs[name] = val;
+ } else if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
+ }
+ this.attrVal = '';
+ while (blankChar[this.data[this.i]]) this.i++;
+ if (this.isClose()) this.setNode();
+ else {
+ this.start = this.i;
+ this.state = this.AttrName;
+ }
+ }
+ // 设置文本节点
+ setText() {
+ var back, text = this.section();
+ if (!text) return;
+ text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
+ if (back) {
+ this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
+ let j = this.start + text.length;
+ for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
+ return;
+ }
+ if (!this.pre) {
+ // 合并空白符
+ var tmp = [];
+ for (let i = text.length, c; c = text[--i];)
+ if (!blankChar[c] || (!blankChar[tmp[0]] && (c = ' '))) tmp.unshift(c);
+ text = tmp.join('');
+ if (text == ' ') return;
+ }
+ this.siblings().push({
+ type: 'text',
+ text: this.decode(text)
+ });
+ }
+ // 设置元素节点
+ setNode() {
+ var node = {
+ name: this.getName(this.tagName),
+ attrs: this.attrs
+ },
+ close = cfg.selfClosingTags[node.name] || (this.xml && this.data[this.i] == '/');
+ this.attrs = {};
+ if (!cfg.ignoreTags[node.name]) {
+ this.matchAttr(node);
+ if (!close) {
+ node.children = [];
+ if (node.name == 'pre' && cfg.highlight) {
+ this.remove(node);
+ this.pre = node.pre = true;
+ }
+ this.siblings().push(node);
+ this.STACK.push(node);
+ } else if (!cfg.filter || cfg.filter(node, this) != false)
+ this.siblings().push(node);
+ } else {
+ if (!close) this.remove(node);
+ else if (node.name == 'source') {
+ var parent = this.parent(),
+ attrs = node.attrs;
+ if (parent && attrs.src)
+ if (parent.name == 'video' || parent.name == 'audio')
+ parent.attrs.source.push(attrs.src);
+ else {
+ var i, media = attrs.media;
+ if (parent.name == 'picture' && !parent.attrs.src && (!media || (media.includes('px') &&
+ (((i = media.indexOf('min-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth > parseInt(media.substr(i + 1))) ||
+ ((i = media.indexOf('max-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth < parseInt(media.substr(i + 1)))))))
+ parent.attrs.src = attrs.src;
+ }
+ } else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
+ }
+ if (this.data[this.i] == '/') this.i++;
+ this.start = this.i + 1;
+ this.state = this.Text;
+ }
+ // 移除标签
+ remove(node) {
+ var name = node.name,
+ j = this.i;
+ while (1) {
+ if ((this.i = this.data.indexOf('', this.i + 1)) == -1) {
+ if (name == 'pre' || name == 'svg') this.i = j;
+ else this.i = this.data.length;
+ return;
+ }
+ this.start = (this.i += 2);
+ while (!blankChar[this.data[this.i]] && !this.isClose()) this.i++;
+ if (this.getName(this.section()) == name) {
+ // 代码块高亮
+ if (name == 'pre') {
+ this.data = this.data.substr(0, j + 1) + cfg.highlight(this.data.substring(j + 1, this.i - 5), node.attrs) + this.data.substr(this.i - 5);
+ return this.i = j;
+ } else if (name == 'style')
+ this.CssHandler.getStyle(this.data.substring(j + 1, this.i - 7));
+ else if (name == 'title')
+ this.title = this.data.substring(j + 1, this.i - 7);
+ if ((this.i = this.data.indexOf('>', this.i)) == -1) this.i = this.data.length;
+ // 处理 svg
+ if (name == 'svg') {
+ var src = this.data.substring(j, this.i + 1);
+ if (!node.attrs.xmlns) src = ' xmlns="http://www.w3.org/2000/svg"' + src;
+ var i = j;
+ while (this.data[j] != '<') j--;
+ src = this.data.substring(j, i) + src;
+ var parent = this.parent();
+ if (node.attrs.width == '100%' && parent && (parent.attrs.style || '').includes('inline'))
+ parent.attrs.style = 'width:300px;max-width:100%;' + parent.attrs.style;
+ this.siblings().push({
+ name: 'img',
+ attrs: {
+ src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
+ ignore: 'T'
+ }
+ })
+ }
+ return;
+ }
+ }
+ }
+ // 处理属性
+ matchAttr(node) {
+ var attrs = node.attrs,
+ style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
+ styleObj = {};
+ if (attrs.id) {
+ if (this.compress & 1) attrs.id = void 0;
+ else if (this.useAnchor) this.bubble();
+ }
+ if ((this.compress & 2) && attrs.class) attrs.class = void 0;
+ switch (node.name) {
+ case 'a':
+ case 'ad':
+ this.bubble();
+ break;
+ case 'font':
+ if (attrs.color) {
+ styleObj['color'] = attrs.color;
+ attrs.color = void 0;
+ }
+ if (attrs.face) {
+ styleObj['font-family'] = attrs.face;
+ attrs.face = void 0;
+ }
+ if (attrs.size) {
+ var size = parseInt(attrs.size);
+ if (size < 1) size = 1;
+ else if (size > 7) size = 7;
+ var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
+ styleObj['font-size'] = map[size - 1];
+ attrs.size = void 0;
+ }
+ break;
+ case 'video':
+ case 'audio':
+ if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
+ else this[`${node.name}Num`]++;
+ if (node.name == 'video') {
+ if (this.videoNum > 3)
+ node.lazyLoad = 1;
+ if (attrs.width) {
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px');
+ attrs.width = void 0;
+ }
+ if (attrs.height) {
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px');
+ attrs.height = void 0;
+ }
+ }
+ attrs.source = [];
+ if (attrs.src) attrs.source.push(attrs.src);
+ if (!attrs.controls && !attrs.autoplay)
+ console.warn(`存在没有 controls 属性的 ${node.name} 标签,可能导致无法播放`, node);
+ this.bubble();
+ break;
+ case 'td':
+ case 'th':
+ if (attrs.colspan || attrs.rowspan)
+ for (var k = this.STACK.length, item; item = this.STACK[--k];)
+ if (item.name == 'table') {
+ item.c = void 0;
+ break;
+ }
+ }
+ if (attrs.align) {
+ styleObj['text-align'] = attrs.align;
+ attrs.align = void 0;
+ }
+ // 压缩 style
+ var styles = style.split(';');
+ style = '';
+ for (var i = 0, len = styles.length; i < len; i++) {
+ var info = styles[i].split(':');
+ if (info.length < 2) continue;
+ let key = info[0].trim().toLowerCase(),
+ value = info.slice(1).join(':').trim();
+ if (value.includes('-webkit') || value.includes('-moz') || value.includes('-ms') || value.includes('-o') || value.includes('safe'))
+ style += `;${key}:${value}`;
+ else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
+ styleObj[key] = value;
+ }
+ if (node.name == 'img' || node.name == 'picture') {
+ if (attrs['data-src']) {
+ attrs.src = attrs.src || attrs['data-src'];
+ attrs['data-src'] = void 0;
+ }
+ if ((attrs.src || node.name == 'picture') && !attrs.ignore) {
+ if (this.bubble())
+ attrs.i = (this.imgNum++).toString();
+ else attrs.ignore = 'T';
+ }
+ if (attrs.ignore) styleObj['max-width'] = '100%';
+ var width;
+ if(styleObj.width) width = styleObj.width;
+ else if(attrs.width) width = attrs.width.includes('%') ? attrs.width : attrs.width + 'px';
+ if (width) {
+ styleObj.width = width;
+ attrs.width = '100%';
+ if (parseInt(width) > screenWidth) {
+ styleObj.height = '';
+ if (attrs.height) attrs.height = void 0;
+ }
+ }
+ if (styleObj.height) {
+ attrs.height = styleObj.height;
+ styleObj.height = '';
+ } else if (attrs.height && !attrs.height.includes('%'))
+ attrs.height += 'px';
+ }
+ for (var key in styleObj) {
+ var value = styleObj[key];
+ if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
+ // 填充链接
+ if (value.includes('url')) {
+ var j = value.indexOf('(');
+ if (j++ != -1) {
+ while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
+ value = value.substr(0, j) + this.getUrl(value.substr(j));
+ }
+ }
+ // 转换 rpx
+ else if (value.includes('rpx'))
+ value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * screenWidth / 750 + 'px');
+ else if (key == 'white-space' && value.includes('pre'))
+ this.pre = node.pre = true;
+ style += `;${key}:${value}`;
+ }
+ style = style.substr(1);
+ if (style) attrs.style = style;
+ }
+ // 节点出栈处理
+ popNode(node) {
+ // 空白符处理
+ if (node.pre) {
+ node.pre = this.pre = void 0;
+ for (let i = this.STACK.length; i--;)
+ if (this.STACK[i].pre)
+ this.pre = true;
+ }
+ if (node.name == 'head' || (cfg.filter && cfg.filter(node, this) == false))
+ return this.siblings().pop();
+ var attrs = node.attrs;
+ // 替换一些标签名
+ if (node.name == 'picture') {
+ node.name = 'img';
+ if (!attrs.src && (node.children[0] || '').name == 'img')
+ attrs.src = node.children[0].attrs.src;
+ return node.children = void 0;
+ }
+ if (cfg.blockTags[node.name]) node.name = 'div';
+ else if (!cfg.trustTags[node.name]) node.name = 'span';
+ // 处理列表
+ if (node.c && (node.name == 'ul' || node.name == 'ol')) {
+ if ((node.attrs.style || '').includes('list-style:none')) {
+ for (let i = 0, child; child = node.children[i++];)
+ if (child.name == 'li')
+ child.name = 'div';
+ } else if (node.name == 'ul') {
+ var floor = 1;
+ for (let i = this.STACK.length; i--;)
+ if (this.STACK[i].name == 'ul') floor++;
+ if (floor != 1)
+ for (let i = node.children.length; i--;)
+ node.children[i].floor = floor;
+ } else {
+ for (let i = 0, num = 1, child; child = node.children[i++];)
+ if (child.name == 'li') {
+ child.type = 'ol';
+ child.num = ((num, type) => {
+ if (type == 'a') return String.fromCharCode(97 + (num - 1) % 26);
+ if (type == 'A') return String.fromCharCode(65 + (num - 1) % 26);
+ if (type == 'i' || type == 'I') {
+ num = (num - 1) % 99 + 1;
+ var one = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
+ ten = ['X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
+ res = (ten[Math.floor(num / 10) - 1] || '') + (one[num % 10 - 1] || '');
+ if (type == 'i') return res.toLowerCase();
+ return res;
+ }
+ return num;
+ })(num++, attrs.type) + '.';
+ }
+ }
+ }
+ // 处理表格的边框
+ if (node.name == 'table') {
+ var padding = attrs.cellpadding,
+ spacing = attrs.cellspacing,
+ border = attrs.border;
+ if (node.c) {
+ this.bubble();
+ attrs.style = (attrs.style || '') + ';display:table';
+ if (!padding) padding = 2;
+ if (!spacing) spacing = 2;
+ }
+ if (border) attrs.style = `border:${border}px solid gray;${attrs.style || ''}`;
+ if (spacing) attrs.style = `border-spacing:${spacing}px;${attrs.style || ''}`;
+ if (border || padding || node.c)
+ (function f(ns) {
+ for (var i = 0, n; n = ns[i]; i++) {
+ if(n.type == 'text') continue;
+ var style = n.attrs.style || '';
+ if (node.c && n.name[0] == 't') {
+ n.c = 1;
+ style += ';display:table-' + (n.name == 'th' || n.name == 'td' ? 'cell' : (n.name == 'tr' ? 'row' : 'row-group'));
+ }
+ if (n.name == 'th' || n.name == 'td') {
+ if (border) style = `border:${border}px solid gray;${style}`;
+ if (padding) style = `padding:${padding}px;${style}`;
+ } else f(n.children || []);
+ if (style) n.attrs.style = style;
+ }
+ })(node.children)
+ }
+ this.CssHandler.pop && this.CssHandler.pop(node);
+ // 自动压缩
+ if (node.name == 'div' && !Object.keys(attrs).length) {
+ var siblings = this.siblings();
+ if (node.children.length == 1 && node.children[0].name == 'div')
+ siblings[siblings.length - 1] = node.children[0];
+ }
+ }
+ // 工具函数
+ bubble() {
+ for (var i = this.STACK.length, item; item = this.STACK[--i];) {
+ if (cfg.richOnlyTags[item.name]) {
+ if (item.name == 'table' && !Object.hasOwnProperty.call(item, 'c')) item.c = 1;
+ return false;
+ }
+ item.c = 1;
+ }
+ return true;
+ }
+ decode(val, amp) {
+ var i = -1,
+ j, en;
+ while (1) {
+ if ((i = val.indexOf('&', i + 1)) == -1) break;
+ if ((j = val.indexOf(';', i + 2)) == -1) break;
+ if (val[i + 1] == '#') {
+ en = parseInt((val[i + 2] == 'x' ? '0' : '') + val.substring(i + 2, j));
+ if (!isNaN(en)) val = val.substr(0, i) + String.fromCharCode(en) + val.substr(j + 1);
+ } else {
+ en = val.substring(i + 1, j);
+ if (cfg.entities[en] || en == amp)
+ val = val.substr(0, i) + (cfg.entities[en] || '&') + val.substr(j + 1);
+ }
+ }
+ return val;
+ }
+ getUrl(url) {
+ if (url[0] == '/') {
+ if (url[1] == '/') url = this.protocol + ':' + url;
+ else if (this.domain) url = this.domain + url;
+ } else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
+ url = this.domain + '/' + url;
+ return url;
+ }
+ getName = val => this.xml ? val : val.toLowerCase();
+ isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
+ section = () => this.data.substring(this.start, this.i);
+ parent = () => this.STACK[this.STACK.length - 1];
+ siblings = () => this.STACK.length ? this.parent().children : this.DOM;
+ // 状态机
+ Text(c) {
+ if (c == '<') {
+ var next = this.data[this.i + 1],
+ isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ if (isLetter(next)) {
+ this.setText();
+ this.start = this.i + 1;
+ this.state = this.TagName;
+ } else if (next == '/') {
+ this.setText();
+ if (isLetter(this.data[++this.i + 1])) {
+ this.start = this.i + 1;
+ this.state = this.EndTag;
+ } else this.Comment();
+ } else if (next == '!') {
+ this.setText();
+ this.Comment();
+ }
+ }
+ }
+ Comment() {
+ var key;
+ if (this.data.substring(this.i + 2, this.i + 4) == '--') key = '-->';
+ else if (this.data.substring(this.i + 2, this.i + 9) == '[CDATA[') key = ']]>';
+ else key = '>';
+ if ((this.i = this.data.indexOf(key, this.i + 2)) == -1) this.i = this.data.length;
+ else this.i += key.length - 1;
+ this.start = this.i + 1;
+ this.state = this.Text;
+ }
+ TagName(c) {
+ if (blankChar[c]) {
+ this.tagName = this.section();
+ while (blankChar[this.data[this.i]]) this.i++;
+ if (this.isClose()) this.setNode();
+ else {
+ this.start = this.i;
+ this.state = this.AttrName;
+ }
+ } else if (this.isClose()) {
+ this.tagName = this.section();
+ this.setNode();
+ }
+ }
+ AttrName(c) {
+ var blank = blankChar[c];
+ if (blank) {
+ this.attrName = this.section();
+ c = this.data[this.i];
+ }
+ if (c == '=') {
+ if (!blank) this.attrName = this.section();
+ while (blankChar[this.data[++this.i]]);
+ this.start = this.i--;
+ this.state = this.AttrValue;
+ } else if (blank) this.setAttr();
+ else if (this.isClose()) {
+ this.attrName = this.section();
+ this.setAttr();
+ }
+ }
+ AttrValue(c) {
+ if (c == '"' || c == "'") {
+ this.start++;
+ if ((this.i = this.data.indexOf(c, this.i + 1)) == -1) return this.i = this.data.length;
+ this.attrVal = this.section();
+ this.i++;
+ } else {
+ for (; !blankChar[this.data[this.i]] && !this.isClose(); this.i++);
+ this.attrVal = this.section();
+ }
+ this.setAttr();
+ }
+ EndTag(c) {
+ if (blankChar[c] || c == '>' || c == '/') {
+ var name = this.getName(this.section());
+ for (var i = this.STACK.length; i--;)
+ if (this.STACK[i].name == name) break;
+ if (i != -1) {
+ var node;
+ while ((node = this.STACK.pop()).name != name);
+ this.popNode(node);
+ } else if (name == 'p' || name == 'br')
+ this.siblings().push({
+ name,
+ attrs: {}
+ });
+ this.i = this.data.indexOf('>', this.i);
+ this.start = this.i + 1;
+ if (this.i == -1) this.i = this.data.length;
+ else this.state = this.Text;
+ }
+ }
+}
+module.exports = MpHtmlParser;
\ No newline at end of file
diff --git a/test_mini/components/parser/libs/config.js b/test_mini/components/parser/libs/config.js
new file mode 100644
index 0000000..795f439
--- /dev/null
+++ b/test_mini/components/parser/libs/config.js
@@ -0,0 +1,102 @@
+/* 配置文件 */
+const canIUse = wx.canIUse('editor'); // 高基础库标识,用于兼容
+const Prism = require('./prism.js');
+module.exports = {
+ // 过滤器函数
+ filter(node, cxt) {
+ if (node.name == 'pre')
+ cxt.bubble(); // 使得 pre 不被 rich-text 包含(为实现长按复制)
+ },
+ // 代码高亮函数
+ highlight(content, attrs) {
+ var info = content.match(/([\s\S]+)<\/code.*?>/m);
+ if (!info) return content;
+ var lan = info[1];
+ content = info[2].replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
+ attrs['data-content'] = content; // 记录原始内容,长按复制时使用
+ switch (lan) {
+ case 'js':
+ case 'javascript':
+ content = Prism.highlight(content, Prism.languages.javascript, 'javascript');
+ break;
+ case 'html':
+ case 'html-editor':
+ case 'wxml':
+ case 'vue':
+ content = Prism.highlight(content, Prism.languages.html, 'html');
+ break;
+ case 'json':
+ content = Prism.highlight(content, Prism.languages.json, 'json');
+ break;
+ case 'md':
+ case 'md-editor':
+ case 'markdown':
+ content = Prism.highlight(content, Prism.languages.markdown, 'markdown');
+ break;
+ case 'c':
+ case 'cpp':
+ content = Prism.highlight(content, Prism.languages.clike, 'clike');
+ }
+ // 增加语言显示
+ if (!lan.includes('editor'))
+ content = `${lan}${content}
`;
+ return content;
+ },
+ // 文本处理函数
+ onText: null,
+ // 实体编码列表
+ entities: {
+ quot: '"',
+ apos: "'",
+ semi: ';',
+ nbsp: '\xA0',
+ ndash: '–',
+ mdash: '—',
+ middot: '·',
+ lsquo: '‘',
+ rsquo: '’',
+ ldquo: '“',
+ rdquo: '”',
+ bull: '•',
+ hellip: '…'
+ },
+ blankChar: makeMap(' ,\xA0,\t,\r,\n,\f'),
+ inlineTags: makeMap('abbr,b,big,code,del,em,i,ins,label,q,small,span,strong'),
+ // 块级标签,将被转为 div
+ blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,section' + (canIUse ? '' : ',pre')),
+ // 将被移除的标签
+ ignoreTags: makeMap('area,base,basefont,canvas,command,embed,frame,iframe,input,isindex,keygen,link,map,meta,param,script,source,style,svg,textarea,title,track,use,wbr' + (canIUse ? ',rp' : '')),
+ // 只能被 rich-text 显示的标签
+ richOnlyTags: makeMap('a,colgroup,fieldset,legend,picture,table' + (canIUse ? ',bdi,bdo,rt,ruby' : '')),
+ // 自闭合的标签
+ selfClosingTags: makeMap('area,base,basefont,br,col,circle,ellipse,embed,frame,hr,img,input,isindex,keygen,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
+ // 信任的属性
+ trustAttrs: makeMap('align,alt,app-id,author,autoplay,border,cellpadding,cellspacing,class,color,colspan,controls,data-src,dir,face,height,href,id,ignore,loop,media,muted,name,path,poster,rowspan,size,span,src,start,style,type,unit-id,width,xmlns'),
+ // bool 型的属性
+ boolAttrs: makeMap('autoplay,controls,ignore,loop,muted'),
+ // 信任的标签
+ 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,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video' + (canIUse ? ',bdi,bdo,caption,pre,rt,ruby' : '')),
+ // 默认的标签样式
+ userAgentStyles: {
+ address: 'font-style:italic',
+ big: 'display:inline;font-size:1.2em',
+ blockquote: 'background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px',
+ 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;overflow:scroll',
+ s: 'text-decoration:line-through',
+ small: 'display:inline;font-size:0.8em',
+ u: 'text-decoration:underline'
+ }
+}
+
+function makeMap(str) {
+ var map = {},
+ list = str.split(',');
+ for (var i = list.length; i--;)
+ map[list[i]] = true;
+ return map;
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/libs/emoji.js b/test_mini/components/parser/libs/emoji.js
new file mode 100644
index 0000000..d6dadee
--- /dev/null
+++ b/test_mini/components/parser/libs/emoji.js
@@ -0,0 +1,198 @@
+/*
+ emoji 扩展包
+ github:https://github.com/jin-yufeng/Parser
+ docs:https://jin-yufeng.github.io/Parser
+ author:JinYufeng
+*/
+const reg = /\[(\S+?)\]/g;
+const data = {
+ '笑脸': '😄',
+ '生病': '😷',
+ '破涕为笑': '😂',
+ '吐舌': '😝',
+ '脸红': '😳',
+ '恐惧': '😱',
+ '失望': '😔',
+ '无语': '😒',
+ '眨眼': '😉',
+ '酷': '😎',
+ '哭': '😭',
+ '痴迷': '😍',
+ '吻': '😘',
+ '思考': '🤔',
+ '困惑': '😕',
+ '颠倒': '🙃',
+ '钱': '🤑',
+ '惊讶': '😲',
+ '白眼': '🙄',
+ '叹气': '😤',
+ '睡觉': '😴',
+ '书呆子': '🤓',
+ '愤怒': '😡',
+ '面无表情': '😑',
+ '张嘴': '😮',
+ '量体温': '🤒',
+ '呕吐': '🤮',
+ '光环': '😇',
+ '幽灵': '👻',
+ '外星人': '👽',
+ '机器人': '🤖',
+ '捂眼镜': '🙈',
+ '捂耳朵': '🙉',
+ '捂嘴': '🙊',
+ '婴儿': '👶',
+ '男孩': '👦',
+ '女孩': '👧',
+ '男人': '👨',
+ '女人': '👩',
+ '老人': '👴',
+ '老妇人': '👵',
+ '警察': '👮',
+ '王子': '🤴',
+ '公主': '🤴',
+ '举手': '🙋',
+ '跑步': '🏃',
+ '家庭': '👪',
+ '眼睛': '👀',
+ '鼻子': '👃',
+ '耳朵': '👂',
+ '舌头': '👅',
+ '嘴': '👄',
+ '心': '❤️',
+ '心碎': '💔',
+ '雪人': '☃️',
+ '情书': '💌',
+ '大便': '💩',
+ '闹钟': '⏰',
+ '眼镜': '👓',
+ '雨伞': '☂️',
+ '音乐': '🎵',
+ '话筒': '🎤',
+ '游戏机': '🎮',
+ '喇叭': '📢',
+ '耳机': '🎧',
+ '礼物': '🎁',
+ '电话': '📞',
+ '电脑': '💻',
+ '打印机': '🖨️',
+ '手电筒': '🔦',
+ '灯泡': '💡',
+ '书本': '📖',
+ '信封': '✉️',
+ '药丸': '💊',
+ '口红': '💄',
+ '手机': '📱',
+ '相机': '📷',
+ '电视': '📺',
+ '中': '🀄',
+ '垃圾桶': '🚮',
+ '厕所': '🚾',
+ '感叹号': '❗',
+ '禁': '🈲',
+ '可': '🉑',
+ '彩虹': '🌈',
+ '旋风': '🌀',
+ '雷电': '⚡',
+ '雪花': '❄️',
+ '星星': '⭐',
+ '水滴': '💧',
+ '玫瑰': '🌹',
+ '加油': '💪',
+ '左': '👈',
+ '右': '👉',
+ '上': '👆',
+ '下': '👇',
+ '手掌': '🖐️',
+ '好的': '👌',
+ '好': '👍',
+ '差': '👎',
+ '胜利': '✌',
+ '拳头': '👊',
+ '挥手': '👋',
+ '鼓掌': '👏',
+ '猴子': '🐒',
+ '狗': '🐶',
+ '狼': '🐺',
+ '猫': '🐱',
+ '老虎': '🐯',
+ '马': '🐎',
+ '独角兽': '🦄',
+ '斑马': '🦓',
+ '鹿': '🦌',
+ '牛': '🐮',
+ '猪': '🐷',
+ '羊': '🐏',
+ '长颈鹿': '🦒',
+ '大象': '🐘',
+ '老鼠': '🐭',
+ '蝙蝠': '🦇',
+ '刺猬': '🦔',
+ '熊猫': '🐼',
+ '鸽子': '🕊️',
+ '鸭子': '🦆',
+ '兔子': '🐇',
+ '老鹰': '🦅',
+ '青蛙': '🐸',
+ '蛇': '🐍',
+ '龙': '🐉',
+ '鲸鱼': '🐳',
+ '海豚': '🐬',
+ '足球': '⚽',
+ '棒球': '⚾',
+ '篮球': '🏀',
+ '排球': '🏐',
+ '橄榄球': '🏉',
+ '网球': '🎾',
+ '骰子': '🎲',
+ '鸡腿': '🍗',
+ '蛋糕': '🎂',
+ '啤酒': '🍺',
+ '饺子': '🥟',
+ '汉堡': '🍔',
+ '薯条': '🍟',
+ '意大利面': '🍝',
+ '干杯': '🥂',
+ '筷子': '🥢',
+ '糖果': '🍬',
+ '奶瓶': '🍼',
+ '爆米花': '🍿',
+ '邮局': '🏤',
+ '医院': '🏥',
+ '银行': '🏦',
+ '酒店': '🏨',
+ '学校': '🏫',
+ '城堡': '🏰',
+ '火车': '🚂',
+ '高铁': '🚄',
+ '地铁': '🚇',
+ '公交': '🚌',
+ '救护车': '🚑',
+ '消防车': '🚒',
+ '警车': '🚓',
+ '出租车': '🚕',
+ '汽车': '🚗',
+ '货车': '🚛',
+ '自行车': '🚲',
+ '摩托': '🛵',
+ '红绿灯': '🚥',
+ '帆船': '⛵',
+ '游轮': '🛳️',
+ '轮船': '⛴️',
+ '飞机': '✈️',
+ '直升机': '🚁',
+ '缆车': '🚠',
+ '警告': '⚠️',
+ '禁止': '⛔'
+}
+module.exports = {
+ parseEmoji: (text) => text.replace(reg, ($, $1) => {
+ if (data[$1]) {
+ if (data[$1].includes('http'))
+ return `
`;
+ else return data[$1];
+ } else return $;
+ }),
+ getEmoji: (key) => data[key],
+ setEmoji: (key, emoji) => data[key] = emoji,
+ removeEmoji: (key) => data[key] = void 0
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/libs/prism.js b/test_mini/components/parser/libs/prism.js
new file mode 100644
index 0000000..9a95229
--- /dev/null
+++ b/test_mini/components/parser/libs/prism.js
@@ -0,0 +1,9 @@
+/* PrismJS 1.19.0
+https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+json+markdown */
+var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,r=0,C={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(r){return r instanceof _?new _(r.type,e(r.content),r.alias):Array.isArray(r)?r.map(e):r.replace(/&/g,"&").replace(/e.length)return;if(!(k instanceof _)){if(h&&y!=r.length-1){if(c.lastIndex=v,!(S=c.exec(e)))break;for(var b=S.index+(f&&S[1]?S[1].length:0),w=S.index+S[0].length,A=y,P=v,x=r.length;A"+a.content+""+a.tag+">"},!u.document)return u.addEventListener&&(C.disableWorkerMessageHandler||u.addEventListener("message",function(e){var r=JSON.parse(e.data),n=r.language,t=r.code,a=r.immediateClose;u.postMessage(C.highlight(t,C.languages[n],n)),a&&u.close()},!1)),C;var e=C.util.currentScript();function n(){C.manual||C.highlightAll()}if(e&&(C.filename=e.src,e.hasAttribute("data-manual")&&(C.manual=!0)),!C.manual){var t=document.readyState;"loading"===t||"interactive"===t&&e&&e.defer?document.addEventListener("DOMContentLoaded",n):window.requestAnimationFrame?window.requestAnimationFrame(n):window.setTimeout(n,16)}return C}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
+Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:(?!)*\]\s*)?>/i,greedy:!0},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[\\s\\S]*?>)(?:\\s*|[\\s\\S])*?(?=<\\/__>)".replace(/__/g,a),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup;
+!function(s){var e=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"}}},url:{pattern:RegExp("url\\((?:"+e.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+e.source+")*?(?=\\s*\\{)"),string:{pattern:e,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:t.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:s.languages.css}},alias:"language-css"}},t.tag))}(Prism);
+Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
+Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&|\|\||[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?[.?]?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*[\s\S]*?\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript;
+Prism.languages.json={property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,number:/-?\d+\.?\d*(?:e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}};
+!function(d){function n(n,e){return n=n.replace(//g,"(?:\\\\.|[^\\\\\\n\r]|(?:\r?\n|\r)(?!\r?\n|\r))"),e&&(n=n+"|"+n.replace(/_/g,"\\*")),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var e="(?:\\\\.|``.+?``|`[^`\r\\n]+`|[^\\\\|\r\\n`])+",t="\\|?__(?:\\|__)+\\|?(?:(?:\r?\n|\r)|$)".replace(/__/g,e),a="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\r?\n|\r)";d.languages.markdown=d.languages.extend("markup",{}),d.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+t+a+"(?:"+t+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+t+a+")(?:"+t+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(e),inside:d.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+t+")"+a+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+t+"$"),inside:{"table-header":{pattern:RegExp(e),alias:"important",inside:d.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/(^[ \t]*(?:\r?\n|\r))(?: {4}|\t).+(?:(?:\r?\n|\r)(?: {4}|\t).+)*/m,lookbehind:!0,alias:"keyword"},{pattern:/``.+?``|`[^`\r\n]+`/,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\r?\n|\r))[\s\S]+?(?=(?:\r?\n|\r)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\r?\n|\r)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n("__(?:(?!_)|_(?:(?!_))+_)+__",!0),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n("_(?:(?!_)|__(?:(?!_))+__)+_",!0),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n("(~~?)(?:(?!~))+?\\2",!1),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},url:{pattern:n('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)| ?\\[(?:(?!\\]))+\\])',!1),lookbehind:!0,greedy:!0,inside:{variable:{pattern:/(\[)[^\]]+(?=\]$)/,lookbehind:!0},content:{pattern:/(^!?\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),["url","bold","italic","strike"].forEach(function(e){["url","bold","italic","strike"].forEach(function(n){e!==n&&(d.languages.markdown[e].inside.content.inside[n]=d.languages.markdown[n])})}),d.hooks.add("after-tokenize",function(n){"markdown"!==n.language&&"md"!==n.language||!function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t 0.5 ? c.toUpperCase() : c;
+ }
+ newSrc += src.substr(j);
+ return this[i] = newSrc;
+ }
+ this[i] = src;
+ // 暂存 data src
+ if (src.includes('data:image')) {
+ 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: () => this[i] = filePath
+ })
+ }
+ }
+ this.imgList.each = function (f) {
+ for (var i = 0, len = this.length; i < len; i++)
+ this.setItem(i, f(this[i], i, this));
+ }
+ if (dom) this.document = new dom(this);
+ },
+ detached() {
+ // 删除暂存
+ this.imgList.each(src => {
+ if (src && src.includes(wx.env.USER_DATA_PATH) && fs)
+ fs.unlink({
+ filePath: src
+ })
+ })
+ clearInterval(this._timer);
+ },
+ methods: {
+ // 锚点跳转
+ navigateTo(obj) {
+ if (!this.data.useAnchor)
+ return obj.fail && obj.fail({
+ errMsg: 'Anchor is disabled'
+ })
+ this.createSelectorQuery()
+ .select('.top' + (obj.id ? '>>>#' + obj.id : '')).boundingClientRect()
+ .selectViewport().scrollOffset().exec(res => {
+ if (!res[0])
+ return this.group ? this.group.navigateTo(this.i, obj) :
+ obj.fail && obj.fail({
+ errMsg: 'Label not found'
+ });
+ obj.scrollTop = res[1].scrollTop + res[0].top + (obj.offset || 0);
+ wx.pageScrollTo(obj);
+ })
+ },
+ // 获取文本
+ getText(ns = this.data.html) {
+ var txt = '';
+ for (var i = 0, n; n = ns[i++];) {
+ if (n.type == 'text') txt += n.text.replace(/ /g, '\u00A0').replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
+ else if (n.type == 'br') txt += '\n';
+ else {
+ // 块级标签前后加换行
+ var br = n.name == 'p' || n.name == 'div' || n.name == 'tr' || n.name == 'li' || (n.name[0] == 'h' && n.name[1] > '0' && n.name[1] < '7');
+ if (br && txt && txt[txt.length - 1] != '\n') txt += '\n';
+ if (n.children) txt += this.getText(n.children);
+ if (br && txt[txt.length - 1] != '\n') txt += '\n';
+ else if (n.name == 'td' || n.name == 'th') txt += '\t';
+ }
+ }
+ return txt;
+ },
+ // 获取视频 context
+ getVideoContext(id) {
+ if (!id) return this.videoContexts;
+ for (var i = this.videoContexts.length; i--;)
+ if (this.videoContexts[i].id == id) return this.videoContexts[i];
+ },
+ // 渲染富文本
+ setContent(html, append, _watch) {
+ var data = {};
+ if (!html) {
+ if (_watch || append) return;
+ data.html = '';
+ } else if (typeof html == 'string') {
+ let parser = new Parser(html, this.data);
+ // 缓存读取
+ if (this.data.useCache) {
+ var hashVal = hash(html);
+ if (cache[hashVal]) data.html = cache[hashVal];
+ else {
+ data.html = parser.parse();
+ cache[hashVal] = data.html;
+ }
+ } else data.html = parser.parse();
+ this._refresh = true;
+ this.triggerEvent('parse', data.html);
+ } else if (html.constructor == Array) {
+ // 转换不符合格式的 array
+ if (html.length && html[0].PoweredBy != 'Parser') {
+ let parser = new Parser('', this.data);
+ (function f(ns) {
+ for (var i = 0, n; n = ns[i]; i++) {
+ if (n.type == 'text') continue;
+ n.attrs = n.attrs || {};
+ for (var key in n.attrs)
+ if (typeof n.attrs[key] != 'string') n.attrs[key] = n.attrs[key].toString();
+ parser.matchAttr(n);
+ if (n.children) {
+ parser.STACK.push(n);
+ f(n.children);
+ parser.popNode(parser.STACK.pop());
+ }
+ }
+ })(html);
+ data.html = html;
+ }
+ if (!_watch) data.html = html;
+ } else if (typeof html == 'object' && html.nodes) {
+ data.html = html.nodes;
+ console.warn('错误的 html 类型:object 类型已废弃');
+ } else
+ return console.warn('错误的 html 类型:' + typeof html);
+ if (append) {
+ this._refresh = true;
+ data.html = (this.data.html || []).concat(data.html);
+ } else if (this.data.showWithAnimation) data.showAm = 'animation: show .5s';
+ if (data.html || data.showAm) this.setData(data);
+ // 设置标题
+ if (this.data.html.length && this.data.html[0].title && this.data.autosetTitle)
+ wx.setNavigationBarTitle({
+ title: this.data.html[0].title
+ })
+ this.imgList.length = 0;
+ this.videoContexts = [];
+ var ns = this.selectAllComponents('.top,.top>>>._node');
+ for (let i = 0, n; n = ns[i++];) {
+ n.top = this;
+ for (var j = 0, item; item = n.data.nodes[j++];) {
+ if (item.c) continue;
+ // 获取图片列表
+ if (item.name == 'img')
+ this.imgList.setItem(item.attrs.i, item.attrs.src);
+ // 音视频控制
+ else if (item.name == 'video' || item.name == 'audio') {
+ var ctx;
+ if (item.name == 'video') ctx = wx.createVideoContext(item.attrs.id, n);
+ else ctx = n.selectComponent('#' + item.attrs.id);
+ if (ctx) {
+ ctx.id = item.attrs.id;
+ this.videoContexts.push(ctx);
+ }
+ }
+ }
+ }
+ (wx.nextTick || setTimeout)(() => this.triggerEvent('load'), 50);
+ var height;
+ clearInterval(this._timer);
+ this._timer = setInterval(() => {
+ this.createSelectorQuery().select('.top').boundingClientRect(res => {
+ this.rect = res;
+ if (res.height == height) {
+ this.triggerEvent('ready', res)
+ clearInterval(this._timer);
+ }
+ height = res.height;
+ }).exec();
+ }, 350)
+ },
+ // 预加载
+ preLoad(html, num) {
+ if (typeof html == 'string') {
+ var id = hash(html);
+ html = new Parser(html, this.data).parse();
+ cache[id] = html;
+ }
+ var imgs, wait = [];
+ (function f(ns) {
+ for (var i = 0, n; n = ns[i++];) {
+ if (n.name == 'img' && n.attrs.src && !wait.includes(n.attrs.src))
+ wait.push(n.attrs.src);
+ f(n.children || []);
+ }
+ })(html);
+ if (num) wait = wait.slice(0, num);
+ this._wait = (this._wait || []).concat(wait);
+ if (!this.data.imgs) imgs = this._wait.splice(0, 15);
+ else if (this.data.imgs.length < 15)
+ imgs = this.data.imgs.concat(this._wait.splice(0, 15 - this.data.imgs.length));
+ imgs && this.setData({
+ imgs
+ });
+ },
+ _load(e) {
+ if (this._wait.length)
+ this.setData({
+ [`imgs[${e.target.id}]`]: this._wait.shift()
+ })
+ },
+ // 事件处理
+ _tap(e) {
+ if (this.data.gestureZoom && e.timeStamp - this._lastT < 300) {
+ var initY = e.detail.y - e.currentTarget.offsetTop;
+ if (this._zoom) {
+ this._scaleAm.translateX(0).scale(1).step();
+ wx.pageScrollTo({
+ scrollTop: (initY + this._initY) / 2 - e.touches[0].clientY,
+ duration: 400
+ })
+ } else {
+ var initX = e.detail.x - e.currentTarget.offsetLeft;
+ this._initY = initY;
+ this._scaleAm = wx.createAnimation({
+ transformOrigin: `${initX}px ${this._initY}px 0`,
+ timingFunction: 'ease-in-out'
+ });
+ this._scaleAm.scale(2).step();
+ this._tMax = initX / 2;
+ this._tMin = (initX - this.rect.width) / 2;
+ this._tX = 0;
+ }
+ this._zoom = !this._zoom;
+ this.setData({
+ scaleAm: this._scaleAm.export()
+ })
+ }
+ this._lastT = e.timeStamp;
+ },
+ _touchstart(e) {
+ if (e.touches.length == 1)
+ this._initX = this._lastX = e.touches[0].pageX;
+ },
+ _touchmove(e) {
+ var diff = e.touches[0].pageX - this._lastX;
+ if (this._zoom && e.touches.length == 1 && Math.abs(diff) > 20) {
+ this._lastX = e.touches[0].pageX;
+ if ((this._tX <= this._tMin && diff < 0) || (this._tX >= this._tMax && diff > 0)) return;
+ this._tX += diff * Math.abs(this._lastX - this._initX) * 0.05;
+ if (this._tX < this._tMin) this._tX = this._tMin;
+ if (this._tX > this._tMax) this._tX = this._tMax;
+ this._scaleAm.translateX(this._tX).step();
+ this.setData({
+ scaleAm: this._scaleAm.export()
+ })
+ }
+ }
+ }
+})
\ No newline at end of file
diff --git a/test_mini/components/parser/parser.json b/test_mini/components/parser/parser.json
new file mode 100644
index 0000000..85e49c9
--- /dev/null
+++ b/test_mini/components/parser/parser.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "trees": "./trees/trees"
+ }
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/parser.wxml b/test_mini/components/parser/parser.wxml
new file mode 100644
index 0000000..d905cce
--- /dev/null
+++ b/test_mini/components/parser/parser.wxml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/test_mini/components/parser/parser.wxss b/test_mini/components/parser/parser.wxss
new file mode 100644
index 0000000..7801832
--- /dev/null
+++ b/test_mini/components/parser/parser.wxss
@@ -0,0 +1,16 @@
+:host {
+ display: block;
+ overflow: scroll;
+ -webkit-overflow-scrolling: touch;
+}
+.top {
+ display: inherit;
+}
+@keyframes show {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/trees/trees.js b/test_mini/components/parser/trees/trees.js
new file mode 100644
index 0000000..24bf445
--- /dev/null
+++ b/test_mini/components/parser/trees/trees.js
@@ -0,0 +1,134 @@
+/*
+ trees 递归子组件
+ github:https://github.com/jin-yufeng/Parser
+ docs:https://jin-yufeng.github.io/Parser
+ author:JinYufeng
+ update:2020/04/25
+*/
+Component({
+ data: {
+ canIUse: !!wx.chooseMessageFile,
+ placeholder: "data:image/svg+xml;utf8,",
+ inlineTags: require('../libs/config.js').inlineTags
+ },
+ properties: {
+ nodes: Array,
+ lazyLoad: Boolean
+ },
+ methods: {
+ // 自定义事件
+ copyCode(e) {
+ wx.showActionSheet({
+ itemList: ['复制代码'],
+ success: () =>
+ wx.setClipboardData({
+ data: e.target.dataset.content
+ })
+ })
+ },
+ // 视频播放事件
+ play(e) {
+ this.top.group && this.top.group.pause(this.top.i);
+ if (this.top.videoContexts.length > 1 && this.top.data.autopause)
+ for (var i = this.top.videoContexts.length; i--;)
+ if (this.top.videoContexts[i].id != e.currentTarget.id)
+ this.top.videoContexts[i].pause();
+ },
+ // 图片事件
+ imgtap(e) {
+ var attrs = e.currentTarget.dataset.attrs;
+ if (!attrs.ignore) {
+ var preview = true;
+ this.top.triggerEvent('imgtap', {
+ id: e.currentTarget.id,
+ src: attrs.src,
+ ignore: () => preview = false
+ })
+ if (preview) {
+ if (this.top.group) return this.top.group.preview(this.top.i, attrs.i);
+ var urls = this.top.imgList,
+ current = urls[attrs.i] ? urls[attrs.i] : (urls = [attrs.src], attrs.src);
+ wx.previewImage({
+ current,
+ urls
+ })
+ }
+ }
+ },
+ loadImg(e) {
+ var i = e.target.dataset.i;
+ if (this.data.lazyLoad && !this.data.nodes[i].load)
+ this.setData({
+ [`nodes[${i}].load`]: true
+ })
+ },
+ // 链接点击事件
+ linkpress(e) {
+ var jump = true,
+ attrs = e.currentTarget.dataset.attrs;
+ attrs.ignore = () => jump = false;
+ this.top.triggerEvent('linkpress', attrs);
+ if (jump) {
+ if (attrs['app-id'])
+ wx.navigateToMiniProgram({
+ appId: attrs['app-id'],
+ path: attrs.path
+ })
+ else if (attrs.href) {
+ if (attrs.href[0] == '#')
+ this.top.navigateTo({
+ id: attrs.href.substring(1)
+ })
+ else if (attrs.href.indexOf('http') == 0 || attrs.href.indexOf('//') == 0)
+ wx.setClipboardData({
+ data: attrs.href,
+ success: () =>
+ wx.showToast({
+ title: '链接已复制'
+ })
+ })
+ else
+ wx.navigateTo({
+ url: attrs.href,
+ })
+ }
+ }
+ },
+ // 错误事件
+ error(e) {
+ var context, source = e.target.dataset.source,
+ i = e.target.dataset.i,
+ node = this.data.nodes[i];
+ if (source == 'video' || source == 'audio') {
+ // 加载其他 source
+ var index = (node.i || 0) + 1;
+ if (index < node.attrs.source.length)
+ return this.setData({
+ [`nodes[${i}].i`]: index
+ })
+ if (this.top) context = this.top.getVideoContext(e.target.id);
+ } else if (source == 'img')
+ context = {
+ setSrc: src => {
+ this.setData({
+ [`nodes[${i}].attrs.src`]: src
+ })
+ }
+ }
+ this.top && this.top.triggerEvent('error', {
+ source,
+ target: e.target,
+ context,
+ ...e.detail
+ })
+ },
+ // 加载视频
+ loadVideo(e) {
+ var i = e.target.dataset.i;
+ this.setData({
+ [`nodes[${i}].lazyLoad`]: false,
+ [`nodes[${i}].attrs.autoplay`]: true
+ })
+ }
+ }
+})
\ No newline at end of file
diff --git a/test_mini/components/parser/trees/trees.json b/test_mini/components/parser/trees/trees.json
new file mode 100644
index 0000000..125a52b
--- /dev/null
+++ b/test_mini/components/parser/trees/trees.json
@@ -0,0 +1,7 @@
+{
+ "component": true,
+ "usingComponents": {
+ "trees": "./trees",
+ "myAudio": "../audio/audio"
+ }
+}
\ No newline at end of file
diff --git a/test_mini/components/parser/trees/trees.wxml b/test_mini/components/parser/trees/trees.wxml
new file mode 100644
index 0000000..61dea53
--- /dev/null
+++ b/test_mini/components/parser/trees/trees.wxml
@@ -0,0 +1,52 @@
+
+
+module.exports = {
+ visited: function (e, owner) {
+ if (!e.instance.hasClass('_visited'))
+ e.instance.addClass('_visited')
+ owner.callMethod('linkpress', e);
+ },
+ useRichText: function (item, inlineTags) {
+ return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1
+ }
+}
+
+
+
+
+
+
+
+
+ {{n.text}}
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{n.num}}
+
+ █
+
+ █
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test_mini/components/parser/trees/trees.wxss b/test_mini/components/parser/trees/trees.wxss
new file mode 100644
index 0000000..520b6df
--- /dev/null
+++ b/test_mini/components/parser/trees/trees.wxss
@@ -0,0 +1,136 @@
+/* 在这里引入自定义样式 */
+@import "../libs/prism.wxss";
+
+/* 链接和图片效果 */
+._a {
+ color: #366092;
+ display: inline;
+ padding: 1.5px 0 1.5px 0;
+ word-break: break-all;
+}
+._hover {
+ opacity: 0.7;
+ text-decoration: underline;
+}
+._visited {
+ color: #551a8b;
+}
+._img {
+ display: inline-block;
+ max-width: 100%;
+ position: relative;
+}
+/* 内部样式 */
+:host {
+ display: inline;
+}
+._blockquote, ._div, ._p, ._ul, ._ol, ._li {
+ display: block;
+}
+._b, ._strong {
+ font-weight: bold;
+}
+._code {
+ font-family: monospace;
+}
+._del {
+ text-decoration: line-through;
+}
+._em, ._i {
+ font-style: italic;
+}
+._h1 {
+ font-size: 2em;
+}
+._h2 {
+ font-size: 1.5em;
+}
+._h3 {
+ font-size: 1.17em;
+}
+._h5 {
+ font-size: 0.83em;
+}
+._h6 {
+ font-size: 0.67em;
+}
+._h1, ._h2, ._h3, ._h4, ._h5, ._h6 {
+ display: block;
+ font-weight: bold;
+}
+._image {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+}
+._ins {
+ text-decoration: underline;
+}
+._li {
+ flex: 1;
+ width: 0;
+}
+._ol-bef {
+ margin-right: 5px;
+ text-align: right;
+ width: 36px;
+}
+._ul-bef {
+ line-height: normal;
+ margin: 0 12px 0 23px;
+}
+._ol-bef, ._ul_bef {
+ flex: none;
+ user-select: none;
+}
+._ul-p1 {
+ display: inline-block;
+ height: 0.3em;
+ line-height: 0.3em;
+ overflow: hidden;
+ width: 0.3em;
+}
+._ul-p2 {
+ border: 0.05em solid black;
+ border-radius: 50%;
+ display: inline-block;
+ height: 0.23em;
+ width: 0.23em;
+}
+._q::before {
+ content: '"';
+}
+._q::after {
+ content: '"';
+}
+._sub {
+ font-size: smaller;
+ vertical-align: sub;
+}
+._sup {
+ font-size: smaller;
+ vertical-align: super;
+}
+.__bdi, .__bdo, .__ruby, .__rt {
+ display: inline-block;
+}
+._video {
+ background-color: black;
+ display: inline-block;
+ height: 225px;
+ position: relative;
+ width: 300px;
+}
+._video::after {
+ border-color: transparent transparent transparent white;
+ border-style: solid;
+ border-width: 15px 0 15px 30px;
+ content: '';
+ left: 50%;
+ margin: -15px 0 0 -15px;
+ position: absolute;
+ top: 50%;
+}
\ No newline at end of file
diff --git a/test_mini/pages/article/detail.js b/test_mini/pages/article/detail.js
index 737a648..70efbc9 100644
--- a/test_mini/pages/article/detail.js
+++ b/test_mini/pages/article/detail.js
@@ -6,7 +6,8 @@ Page({
* 页面的初始数据
*/
data: {
- elink_f:''
+ elink_f:'',
+ domain:getApp().globalData.mediahost
},
/**
@@ -68,6 +69,7 @@ Page({
getDetail: function (id) {
var that = this
api.request(`/cms/article/${id}/`,'GET').then(res => {
+ // res.data.content = res.data.content.replace(/"media/g, '"'+getApp().globalData.mediahost + '/media').replace(/\
+
+
{{title}}
{{ifrom}}
置顶
- 原创
+ 原创
-
+
diff --git a/test_mini/pages/lianxi/index.wxml b/test_mini/pages/lianxi/index.wxml
index c527cce..4877c07 100644
--- a/test_mini/pages/lianxi/index.wxml
+++ b/test_mini/pages/lianxi/index.wxml
@@ -11,10 +11,7 @@
- {{item.type}}
- --共
- {{item.tmtotal}}
- 道/已答
+ 已答
{{item.ydtmtotal}}
道
diff --git a/test_server/crm/models.py b/test_server/crm/models.py
index 4bb67fc..092dec5 100644
--- a/test_server/crm/models.py
+++ b/test_server/crm/models.py
@@ -32,7 +32,7 @@ class Consumer(SoftCommonModel):
subjects = models.ManyToManyField(Questioncat, verbose_name='付费学科', through='PaySubject')
workscope = models.ForeignKey(WorkScope, verbose_name='工作类别', on_delete=models.SET_NULL, null=True, blank=True)
collects = models.ManyToManyField(Question, verbose_name='收藏试题')
- remain_count = models.IntegerField('可考次数', default=1)
+ remain_count = models.IntegerField('体验次数', default=3)
class Meta: