├── README.md
├── package.json
└── rich-parse
├── helper
├── html2json.js
├── htmlparser.js
└── wx-discode.js
├── render-nodes
├── recursion.wxml
├── render-nodes.js
├── render-nodes.json
├── render-nodes.wxml
└── render-nodes.wxss
├── rich-parse.js
├── rich-parse.json
├── rich-parse.wxml
└── rich-parse.wxss
/README.md:
--------------------------------------------------------------------------------
1 | # 微信小程序富文本解析组件
2 |
3 | ## 代码从 https://github.com/icindy/wxParse fork。
4 |
5 | 于 wxParse 的差异:
6 |
7 | 1. 使用自定义组件重写逻辑
8 | 2. 解决 wxParse 中的 template 不能循环使用的问题
9 |
10 | ## 特性
11 |
12 | | 支持特性 |
13 | | ------------- |
14 | | - [x] HTML的大部分标签解析 |
15 | | - [x] 内联style |
16 | | - [x] 标签Class |
17 | | - [x] 图片自适应规则 |
18 | | - [x] 图片多图片预览 |
19 | | - [x] 模版层级可扩展性 |
20 | | - [x] 多数据循环方式 |
21 | | - [x] 内联style |
22 | | - [x] a标签跳转 |
23 |
24 | ## 基本使用方法
25 |
26 | 1. Copy文件夹 `rich-parse` 到放置自定义组件的地方
27 |
28 | 2. 引入必要文件
29 |
30 | ```
31 | // 在使用的View中引入 rich-parse
32 | {
33 | "usingComponents": {
34 | "rich-parse": "/自定义组件路径/rich-parse/rich-parse"
35 | }
36 | }
37 | ```
38 |
39 | 3. 使用
40 | ```
41 |
42 | // content 是字符串内容,type 默认 html,可选 md。
43 | // md 解析器需要手动配置,函数挂在 global.md2html 上才有效
44 | ```
45 |
46 | 4. a 标签使用
47 | ```
48 |
49 | ```
50 |
51 | 5. 图片预览
52 | ```
53 |
54 | ```
55 |
56 | ## 相关文章
57 |
58 | * [wxDiscode-微信小程序特殊字符转义符转化工具类](http://weappdev.com/t/wxdiscode/203)
59 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wx-rich-parse",
3 | "version": "1.0.0",
4 | "description": "微信小程序富文本解析组件",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/jamieYou/wx-rich-parse.git"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "bugs": {
12 | "url": "https://github.com/jamieYou/wx-rich-parse/issues"
13 | },
14 | "homepage": "https://github.com/jamieYou/wx-rich-parse#readme"
15 | }
16 |
--------------------------------------------------------------------------------
/rich-parse/helper/html2json.js:
--------------------------------------------------------------------------------
1 | /**
2 | * html2Json 改造来自: https://github.com/Jxck/html2json
3 | *
4 | *
5 | * author: Di (微信小程序开发工程师)
6 | * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
7 | * 垂直微信小程序开发交流社区
8 | *
9 | * github地址: https://github.com/icindy/wxParse
10 | *
11 | * for: 微信小程序富文本解析
12 | * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
13 | */
14 |
15 | /* eslint-disable */
16 |
17 | var __placeImgeUrlHttps = "https";
18 | var __emojisReg = '';
19 | var __emojisBaseSrc = '';
20 | var __emojis = {};
21 | var wxDiscode = require('./wx-discode.js');
22 | var HTMLParser = require('./htmlparser.js');
23 | // Empty Elements - HTML 5
24 | var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
25 | // Block Elements - HTML 5
26 | var block = makeMap("br,a,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
27 |
28 | // Inline Elements - HTML 5
29 | var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
30 |
31 | // Elements that you can, intentionally, leave open
32 | // (and which close themselves)
33 | var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
34 |
35 | // Attributes that have their values filled in disabled="disabled"
36 | var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
37 |
38 | // Special Elements (can contain anything)
39 | var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
40 | function makeMap(str) {
41 | var obj = {}, items = str.split(",");
42 | for (var i = 0; i < items.length; i++)
43 | obj[items[i]] = true;
44 | return obj;
45 | }
46 |
47 | function q(v) {
48 | return '"' + v + '"';
49 | }
50 |
51 | function removeDOCTYPE(html) {
52 | return html
53 | .replace(/<\?xml.*\?>\n/, '')
54 | .replace(/<.*!doctype.*\>\n/, '')
55 | .replace(/<.*!DOCTYPE.*\>\n/, '');
56 | }
57 |
58 | function trimHtml(html) {
59 | return html
60 | .replace(/\r?\n+/g, '')
61 | .replace(//ig, '')
62 | .replace(/\/\*.*?\*\//ig, '')
63 | .replace(/[ ]+
196 | // add to parents
197 | var parent = bufArray[0] || results;
198 | if (parent.nodes === undefined) {
199 | parent.nodes = [];
200 | }
201 | parent.nodes.push(node);
202 | } else {
203 | bufArray.unshift(node);
204 | }
205 | },
206 | end: function (tag) {
207 | //debug(tag);
208 | // merge into parent tag
209 | var node = bufArray.shift();
210 | if (node.tag !== tag) console.error('invalid state: mismatch end tag');
211 |
212 | //当有缓存source资源时于于video补上src资源
213 | if(node.tag === 'video' && results.source){
214 | node.attr.src = results.source;
215 | delete results.source;
216 | }
217 |
218 | if (bufArray.length === 0) {
219 | results.nodes.push(node);
220 | } else {
221 | var parent = bufArray[0];
222 | if (parent.nodes === undefined) {
223 | parent.nodes = [];
224 | }
225 | parent.nodes.push(node);
226 | }
227 | },
228 | chars: function (text) {
229 | //debug(text);
230 | var node = {
231 | node: 'text',
232 | text: text,
233 | textArray:transEmojiStr(text)
234 | };
235 |
236 | if (bufArray.length === 0) {
237 | node.index = index.toString()
238 | index += 1
239 | results.nodes.push(node);
240 | } else {
241 | var parent = bufArray[0];
242 | if (parent.nodes === undefined) {
243 | parent.nodes = [];
244 | }
245 | node.index = parent.index + '.' + parent.nodes.length
246 | parent.nodes.push(node);
247 | }
248 | },
249 | comment: function (text) {
250 | //debug(text);
251 | // var node = {
252 | // node: 'comment',
253 | // text: text,
254 | // };
255 | // var parent = bufArray[0];
256 | // if (parent.nodes === undefined) {
257 | // parent.nodes = [];
258 | // }
259 | // parent.nodes.push(node);
260 | },
261 | });
262 | return results;
263 | };
264 |
265 | function transEmojiStr(str){
266 | // var eReg = new RegExp("["+__reg+' '+"]");
267 | // str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
268 |
269 | var emojiObjs = [];
270 | //如果正则表达式为空
271 | if(__emojisReg.length == 0 || !__emojis){
272 | var emojiObj = {}
273 | emojiObj.node = "text";
274 | emojiObj.text = str;
275 | array = [emojiObj];
276 | return array;
277 | }
278 | //这个地方需要调整
279 | str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
280 | var eReg = new RegExp("[:]");
281 | var array = str.split(eReg);
282 | for(var i = 0; i < array.length; i++){
283 | var ele = array[i];
284 | var emojiObj = {};
285 | if(__emojis[ele]){
286 | emojiObj.node = "element";
287 | emojiObj.tag = "emoji";
288 | emojiObj.text = __emojis[ele];
289 | emojiObj.baseSrc= __emojisBaseSrc;
290 | }else{
291 | emojiObj.node = "text";
292 | emojiObj.text = ele;
293 | }
294 | emojiObjs.push(emojiObj);
295 | }
296 |
297 | return emojiObjs;
298 | }
299 |
300 | function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
301 | __emojisReg = reg;
302 | __emojisBaseSrc=baseSrc;
303 | __emojis=emojis;
304 | }
305 |
306 | module.exports = {
307 | html2json: html2json,
308 | emojisInit:emojisInit
309 | };
310 |
311 |
--------------------------------------------------------------------------------
/rich-parse/helper/htmlparser.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
4 | *
5 | * author: Di (微信小程序开发工程师)
6 | * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
7 | * 垂直微信小程序开发交流社区
8 | *
9 | * github地址: https://github.com/icindy/wxParse
10 | *
11 | * for: 微信小程序富文本解析
12 | * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
13 | */
14 | // Regular Expressions for parsing tags and attributes
15 | /* eslint-disable */
16 |
17 | var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
18 | endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/,
19 | attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
20 |
21 | // Empty Elements - HTML 5
22 | var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
23 |
24 | // Block Elements - HTML 5
25 | var block = makeMap("a,address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
26 |
27 | // Inline Elements - HTML 5
28 | var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
29 |
30 | // Elements that you can, intentionally, leave open
31 | // (and which close themselves)
32 | var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
33 |
34 | // Attributes that have their values filled in disabled="disabled"
35 | var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
36 |
37 | // Special Elements (can contain anything)
38 | var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
39 |
40 | function HTMLParser(html, handler) {
41 | var index, chars, match, stack = [], last = html;
42 | stack.last = function () {
43 | return this[this.length - 1];
44 | };
45 |
46 | while (html) {
47 | chars = true;
48 |
49 | // Make sure we're not in a script or style element
50 | if (!stack.last() || !special[stack.last()]) {
51 |
52 | // Comment
53 | if (html.indexOf("");
55 |
56 | if (index >= 0) {
57 | if (handler.comment)
58 | handler.comment(html.substring(4, index));
59 | html = html.substring(index + 3);
60 | chars = false;
61 | }
62 |
63 | // end tag
64 | } else if (html.indexOf("") == 0) {
65 | match = html.match(endTag);
66 |
67 | if (match) {
68 | html = html.substring(match[0].length);
69 | match[0].replace(endTag, parseEndTag);
70 | chars = false;
71 | }
72 |
73 | // start tag
74 | } else if (html.indexOf("<") == 0) {
75 | match = html.match(startTag);
76 |
77 | if (match) {
78 | html = html.substring(match[0].length);
79 | match[0].replace(startTag, parseStartTag);
80 | chars = false;
81 | }
82 | }
83 |
84 | if (chars) {
85 | index = html.indexOf("<");
86 | var text = ''
87 | while (index === 0) {
88 | text += "<";
89 | html = html.substring(1);
90 | index = html.indexOf("<");
91 | }
92 | text += index < 0 ? html : html.substring(0, index);
93 | html = index < 0 ? "" : html.substring(index);
94 |
95 | if (handler.chars)
96 | handler.chars(text);
97 | }
98 |
99 | } else {
100 |
101 | html = html.replace(new RegExp("([\\s\\S]*?)<\/" + stack.last() + "[^>]*>"), function (all, text) {
102 | text = text.replace(/|/g, "$1$2");
103 | if (handler.chars)
104 | handler.chars(text);
105 |
106 | return "";
107 | });
108 |
109 |
110 | parseEndTag("", stack.last());
111 | }
112 |
113 | if (html == last)
114 | throw "Parse Error: " + html;
115 | last = html;
116 | }
117 |
118 | // Clean up any remaining tags
119 | parseEndTag();
120 |
121 | function parseStartTag(tag, tagName, rest, unary) {
122 | tagName = tagName.toLowerCase();
123 |
124 | if (block[tagName]) {
125 | while (stack.last() && inline[stack.last()]) {
126 | parseEndTag("", stack.last());
127 | }
128 | }
129 |
130 | if (closeSelf[tagName] && stack.last() == tagName) {
131 | parseEndTag("", tagName);
132 | }
133 |
134 | unary = empty[tagName] || !!unary;
135 |
136 | if (!unary)
137 | stack.push(tagName);
138 |
139 | if (handler.start) {
140 | var attrs = [];
141 |
142 | rest.replace(attr, function (match, name) {
143 | var value = arguments[2] ? arguments[2] :
144 | arguments[3] ? arguments[3] :
145 | arguments[4] ? arguments[4] :
146 | fillAttrs[name] ? name : "";
147 |
148 | attrs.push({
149 | name: name,
150 | value: value,
151 | escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
152 | });
153 | });
154 |
155 | if (handler.start) {
156 | handler.start(tagName, attrs, unary);
157 | }
158 |
159 | }
160 | }
161 |
162 | function parseEndTag(tag, tagName) {
163 | // If no tag name is provided, clean shop
164 | if (!tagName)
165 | var pos = 0;
166 |
167 | // Find the closest opened tag of the same type
168 | else {
169 | tagName = tagName.toLowerCase();
170 | for (var pos = stack.length - 1; pos >= 0; pos--)
171 | if (stack[pos] == tagName)
172 | break;
173 | }
174 | if (pos >= 0) {
175 | // Close all the open elements, up the stack
176 | for (var i = stack.length - 1; i >= pos; i--)
177 | if (handler.end)
178 | handler.end(stack[i]);
179 |
180 | // Remove the open elements from the stack
181 | stack.length = pos;
182 | }
183 | }
184 | };
185 |
186 |
187 | function makeMap(str) {
188 | var obj = {}, items = str.split(",");
189 | for (var i = 0; i < items.length; i++)
190 | obj[items[i]] = true;
191 | return obj;
192 | }
193 |
194 | module.exports = HTMLParser;
195 |
--------------------------------------------------------------------------------
/rich-parse/helper/wx-discode.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 |
3 | // HTML 支持的数学符号
4 | function strNumDiscode(str){
5 | str = str.replace(/∀/g, '∀');
6 | str = str.replace(/∂/g, '∂');
7 | str = str.replace(/&exists;/g, '∃');
8 | str = str.replace(/∅/g, '∅');
9 | str = str.replace(/∇/g, '∇');
10 | str = str.replace(/∈/g, '∈');
11 | str = str.replace(/∉/g, '∉');
12 | str = str.replace(/∋/g, '∋');
13 | str = str.replace(/∏/g, '∏');
14 | str = str.replace(/∑/g, '∑');
15 | str = str.replace(/−/g, '−');
16 | str = str.replace(/∗/g, '∗');
17 | str = str.replace(/√/g, '√');
18 | str = str.replace(/∝/g, '∝');
19 | str = str.replace(/∞/g, '∞');
20 | str = str.replace(/∠/g, '∠');
21 | str = str.replace(/∧/g, '∧');
22 | str = str.replace(/∨/g, '∨');
23 | str = str.replace(/∩/g, '∩');
24 | str = str.replace(/∩/g, '∪');
25 | str = str.replace(/∫/g, '∫');
26 | str = str.replace(/∴/g, '∴');
27 | str = str.replace(/∼/g, '∼');
28 | str = str.replace(/≅/g, '≅');
29 | str = str.replace(/≈/g, '≈');
30 | str = str.replace(/≠/g, '≠');
31 | str = str.replace(/≤/g, '≤');
32 | str = str.replace(/≥/g, '≥');
33 | str = str.replace(/⊂/g, '⊂');
34 | str = str.replace(/⊃/g, '⊃');
35 | str = str.replace(/⊄/g, '⊄');
36 | str = str.replace(/⊆/g, '⊆');
37 | str = str.replace(/⊇/g, '⊇');
38 | str = str.replace(/⊕/g, '⊕');
39 | str = str.replace(/⊗/g, '⊗');
40 | str = str.replace(/⊥/g, '⊥');
41 | str = str.replace(/⋅/g, '⋅');
42 | return str;
43 | }
44 |
45 | //HTML 支持的希腊字母
46 | function strGreeceDiscode(str){
47 | str = str.replace(/Α/g, 'Α');
48 | str = str.replace(/Β/g, 'Β');
49 | str = str.replace(/Γ/g, 'Γ');
50 | str = str.replace(/Δ/g, 'Δ');
51 | str = str.replace(/Ε/g, 'Ε');
52 | str = str.replace(/Ζ/g, 'Ζ');
53 | str = str.replace(/Η/g, 'Η');
54 | str = str.replace(/Θ/g, 'Θ');
55 | str = str.replace(/Ι/g, 'Ι');
56 | str = str.replace(/Κ/g, 'Κ');
57 | str = str.replace(/Λ/g, 'Λ');
58 | str = str.replace(/Μ/g, 'Μ');
59 | str = str.replace(/Ν/g, 'Ν');
60 | str = str.replace(/Ξ/g, 'Ν');
61 | str = str.replace(/Ο/g, 'Ο');
62 | str = str.replace(/Π/g, 'Π');
63 | str = str.replace(/Ρ/g, 'Ρ');
64 | str = str.replace(/Σ/g, 'Σ');
65 | str = str.replace(/Τ/g, 'Τ');
66 | str = str.replace(/Υ/g, 'Υ');
67 | str = str.replace(/Φ/g, 'Φ');
68 | str = str.replace(/Χ/g, 'Χ');
69 | str = str.replace(/Ψ/g, 'Ψ');
70 | str = str.replace(/Ω/g, 'Ω');
71 |
72 | str = str.replace(/α/g, 'α');
73 | str = str.replace(/β/g, 'β');
74 | str = str.replace(/γ/g, 'γ');
75 | str = str.replace(/δ/g, 'δ');
76 | str = str.replace(/ε/g, 'ε');
77 | str = str.replace(/ζ/g, 'ζ');
78 | str = str.replace(/η/g, 'η');
79 | str = str.replace(/θ/g, 'θ');
80 | str = str.replace(/ι/g, 'ι');
81 | str = str.replace(/κ/g, 'κ');
82 | str = str.replace(/λ/g, 'λ');
83 | str = str.replace(/μ/g, 'μ');
84 | str = str.replace(/ν/g, 'ν');
85 | str = str.replace(/ξ/g, 'ξ');
86 | str = str.replace(/ο/g, 'ο');
87 | str = str.replace(/π/g, 'π');
88 | str = str.replace(/ρ/g, 'ρ');
89 | str = str.replace(/ς/g, 'ς');
90 | str = str.replace(/σ/g, 'σ');
91 | str = str.replace(/τ/g, 'τ');
92 | str = str.replace(/υ/g, 'υ');
93 | str = str.replace(/φ/g, 'φ');
94 | str = str.replace(/χ/g, 'χ');
95 | str = str.replace(/ψ/g, 'ψ');
96 | str = str.replace(/ω/g, 'ω');
97 | str = str.replace(/ϑ/g, 'ϑ');
98 | str = str.replace(/ϒ/g, 'ϒ');
99 | str = str.replace(/ϖ/g, 'ϖ');
100 | str = str.replace(/·/g, '·');
101 | return str;
102 | }
103 |
104 | //
105 |
106 | function strcharacterDiscode(str){
107 | // 加入常用解析
108 | str = str.replace(/ /g, '\xa0');
109 | str = str.replace(/"/g, "'");
110 | str = str.replace(/&/g, '&');
111 | // str = str.replace(/</g, '‹');
112 | // str = str.replace(/>/g, '›');
113 |
114 | str = str.replace(/</g, '<');
115 | str = str.replace(/>/g, '>');
116 | str = str.replace(/•/g, '•');
117 |
118 | return str;
119 | }
120 |
121 | // HTML 支持的其他实体
122 | function strOtherDiscode(str){
123 | str = str.replace(/Œ/g, 'Œ');
124 | str = str.replace(/œ/g, 'œ');
125 | str = str.replace(/Š/g, 'Š');
126 | str = str.replace(/š/g, 'š');
127 | str = str.replace(/Ÿ/g, 'Ÿ');
128 | str = str.replace(/ƒ/g, 'ƒ');
129 | str = str.replace(/ˆ/g, 'ˆ');
130 | str = str.replace(/˜/g, '˜');
131 | str = str.replace(/ /g, '');
132 | str = str.replace(/ /g, '');
133 | str = str.replace(/ /g, '');
134 | str = str.replace(//g, '');
135 | str = str.replace(//g, '');
136 | str = str.replace(//g, '');
137 | str = str.replace(//g, '');
138 | str = str.replace(/–/g, '–');
139 | str = str.replace(/—/g, '—');
140 | str = str.replace(/‘/g, '‘');
141 | str = str.replace(/’/g, '’');
142 | str = str.replace(/‚/g, '‚');
143 | str = str.replace(/“/g, '“');
144 | str = str.replace(/”/g, '”');
145 | str = str.replace(/„/g, '„');
146 | str = str.replace(/†/g, '†');
147 | str = str.replace(/‡/g, '‡');
148 | str = str.replace(/•/g, '•');
149 | str = str.replace(/…/g, '…');
150 | str = str.replace(/‰/g, '‰');
151 | str = str.replace(/′/g, '′');
152 | str = str.replace(/″/g, '″');
153 | str = str.replace(/‹/g, '‹');
154 | str = str.replace(/›/g, '›');
155 | str = str.replace(/‾/g, '‾');
156 | str = str.replace(/€/g, '€');
157 | str = str.replace(/™/g, '™');
158 |
159 | str = str.replace(/←/g, '←');
160 | str = str.replace(/↑/g, '↑');
161 | str = str.replace(/→/g, '→');
162 | str = str.replace(/↓/g, '↓');
163 | str = str.replace(/↔/g, '↔');
164 | str = str.replace(/↵/g, '↵');
165 | str = str.replace(/⌈/g, '⌈');
166 | str = str.replace(/⌉/g, '⌉');
167 |
168 | str = str.replace(/⌊/g, '⌊');
169 | str = str.replace(/⌋/g, '⌋');
170 | str = str.replace(/◊/g, '◊');
171 | str = str.replace(/♠/g, '♠');
172 | str = str.replace(/♣/g, '♣');
173 | str = str.replace(/♥/g, '♥');
174 |
175 | str = str.replace(/♦/g, '♦');
176 | str = str.replace(/'/g, '\'');
177 | return str;
178 | }
179 |
180 | function strMoreDiscode(str){
181 | str = str.replace(/\r\n/g,"");
182 | str = str.replace(/\n/g,"");
183 |
184 | // str = str.replace(/code/g,"wxxxcode-style");
185 | return str;
186 | }
187 |
188 | function strDiscode(str){
189 | str = strNumDiscode(str);
190 | str = strGreeceDiscode(str);
191 | str = strcharacterDiscode(str);
192 | str = strOtherDiscode(str);
193 | str = strMoreDiscode(str);
194 | return str;
195 | }
196 | function urlToHttpUrl(url,rep){
197 |
198 | var patt1 = new RegExp("^//");
199 | var result = patt1.test(url);
200 | if(result){
201 | url = rep+":"+url;
202 | }
203 | return url;
204 | }
205 |
206 | module.exports = {
207 | strDiscode:strDiscode,
208 | urlToHttpUrl:urlToHttpUrl
209 | }
210 |
--------------------------------------------------------------------------------
/rich-parse/render-nodes/recursion.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/rich-parse/render-nodes/render-nodes.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | addGlobalClass: true,
4 | },
5 |
6 | properties: {
7 | nodes: {
8 | type: Array,
9 | value: [],
10 | },
11 | parse_id: {
12 | type: String,
13 | value: '',
14 | }
15 | },
16 |
17 | data: {
18 | imageWidths: {}
19 | },
20 |
21 | methods: {
22 | onImgTap(e) {
23 | global.richParses[this.data.parse_id].onImgTap(e)
24 | },
25 |
26 | onLinkTap(e) {
27 | global.richParses[this.data.parse_id].onLinkTap(e)
28 | },
29 |
30 | onImgLoad(e) {
31 | this.data.imageWidths[e.target.dataset.src] = e.detail.width + 'px'
32 | this.setData({ imageWidths: this.data.imageWidths })
33 | }
34 | }
35 | })
36 |
--------------------------------------------------------------------------------
/rich-parse/render-nodes/render-nodes.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "render-nodes": "./render-nodes"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/rich-parse/render-nodes/render-nodes.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
100 |
101 |
102 |
103 |
104 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | {{ item.text }}
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | \n
127 |
128 |
--------------------------------------------------------------------------------
/rich-parse/render-nodes/render-nodes.wxss:
--------------------------------------------------------------------------------
1 | view {
2 | word-break: break-all;
3 | overflow: auto;
4 | }
5 | .rich-parse-inline {
6 | display: inline;
7 | margin: 0;
8 | padding: 0;
9 | }
10 | .rich-parse-div {
11 | margin: 0;
12 | padding: 0;
13 | }
14 | .rich-parse-h1 {
15 | font-size: 2em;
16 | margin: 0.67em 0;
17 | }
18 | .rich-parse-h2 {
19 | font-size: 1.5em;
20 | margin: 0.75em 0;
21 | }
22 | .rich-parse-h3 {
23 | font-size: 1.17em;
24 | margin: 0.83em 0;
25 | }
26 | .rich-parse-h4 {
27 | margin: 1.12em 0;
28 | }
29 | .rich-parse-h5 {
30 | font-size: .83em;
31 | margin: 1.5em 0;
32 | }
33 | .rich-parse-h6 {
34 | font-size: .75em;
35 | margin: 1.67em 0;
36 | }
37 | .rich-parse-h1 {
38 | font-size: 36rpx;
39 | font-weight: 400;
40 | margin-bottom: .9em;
41 | }
42 | .rich-parse-h2 {
43 | font-size: 32rpx;
44 | font-weight: 400;
45 | margin-bottom: .34em;
46 | }
47 | .rich-parse-h3 {
48 | font-weight: 400;
49 | font-size: 30rpx;
50 | margin-bottom: .34em;
51 | }
52 | .rich-parse-h4 {
53 | font-weight: 400;
54 | font-size: 28rpx;
55 | margin-bottom: .24em;
56 | }
57 | .rich-parse-h5 {
58 | font-weight: 400;
59 | font-size: 26rpx;
60 | margin-bottom: .14em;
61 | }
62 | .rich-parse-h6 {
63 | font-weight: 400;
64 | font-size: 24rpx;
65 | margin-bottom: .04em;
66 | }
67 | .rich-parse-h1,
68 | .rich-parse-h2,
69 | .rich-parse-h3,
70 | .rich-parse-h4,
71 | .rich-parse-h5,
72 | .rich-parse-h6,
73 | .rich-parse-b,
74 | .rich-parse-strong {
75 | font-weight: bolder;
76 | }
77 | .rich-parse-i,
78 | .rich-parse-cite,
79 | .rich-parse-em,
80 | .rich-parse-var,
81 | .rich-parse-address {
82 | font-style: italic;
83 | }
84 | .rich-parse-pre,
85 | .rich-parse-tt,
86 | .rich-parse-code,
87 | .rich-parse-kbd,
88 | .rich-parse-samp {
89 | font-family: monospace;
90 | }
91 | .rich-parse-pre {
92 | white-space: pre;
93 | }
94 | .rich-parse-big {
95 | font-size: 1.17em;
96 | }
97 | .rich-parse-small,
98 | .rich-parse-sub,
99 | .rich-parse-sup {
100 | font-size: 0.83em;
101 | }
102 | .rich-parse-sub {
103 | vertical-align: sub;
104 | }
105 | .rich-parse-sup {
106 | vertical-align: super;
107 | }
108 | .rich-parse-s,
109 | .rich-parse-strike,
110 | .rich-parse-del {
111 | text-decoration: line-through;
112 | }
113 | /*rich-parse-自定义个性化的css样式*/
114 | /*增加video的css样式*/
115 | .rich-parse-strong,
116 | .rich-parse-s {
117 | display: inline;
118 | }
119 | .rich-parse-a {
120 | color: deepskyblue;
121 | word-break: break-all;
122 | overflow: auto;
123 | }
124 | .rich-parse-video-view {
125 | text-align: center;
126 | margin: 20rpx 0;
127 | }
128 | .rich-parse-video {
129 | width: 100%;
130 | }
131 | .rich-parse-audio-view {
132 | display: -webkit-box;
133 | display: -webkit-flex;
134 | display: flex;
135 | -webkit-box-pack: center;
136 | -webkit-justify-content: center;
137 | justify-content: center;
138 | overflow: hidden;
139 | }
140 | .rich-parse-img {
141 | overflow: hidden;
142 | max-width: 100%;
143 | }
144 | .rich-parse-blockquote {
145 | margin: 0;
146 | padding: 20rpx 0 20rpx 10rpx;
147 | font-family: Courier, Calibri, "宋体";
148 | background: #f5f5f5;
149 | border-left: 6rpx solid #dbdbdb;
150 | }
151 | .rich-parse-code {
152 | display: inline;
153 | background: #f5f5f5;
154 | }
155 | .rich-parse-ul {
156 | margin: 20rpx 10rpx;
157 | }
158 | .rich-parse-li,
159 | .rich-parse-li-inner {
160 | display: -webkit-box;
161 | display: -webkit-flex;
162 | display: flex;
163 | -webkit-box-align: baseline;
164 | -webkit-align-items: baseline;
165 | align-items: baseline;
166 | margin: 10rpx 0;
167 | }
168 | .rich-parse-li-text {
169 | -webkit-box-align: center;
170 | -webkit-align-items: center;
171 | align-items: center;
172 | line-height: 40rpx;
173 | }
174 | .rich-parse-li-circle {
175 | display: -webkit-inline-box;
176 | display: -webkit-inline-flex;
177 | display: inline-flex;
178 | width: 10rpx;
179 | height: 10rpx;
180 | background-color: #333;
181 | margin-right: 10rpx;
182 | }
183 | .rich-parse-li-square {
184 | display: -webkit-inline-box;
185 | display: -webkit-inline-flex;
186 | display: inline-flex;
187 | width: 10rpx;
188 | height: 10rpx;
189 | background-color: #333;
190 | margin-right: 10rpx;
191 | }
192 | .rich-parse-li-ring {
193 | display: -webkit-inline-box;
194 | display: -webkit-inline-flex;
195 | display: inline-flex;
196 | width: 10rpx;
197 | height: 10rpx;
198 | border: 1PX solid #333;
199 | border-radius: 50%;
200 | background-color: #fff;
201 | margin-right: 10rpx;
202 | }
203 | .rich-parse-table {
204 | width: 100%;
205 | height: 800rpx;
206 | }
207 | .rich-parse-thead,
208 | .rich-parse-tfoot,
209 | .rich-parse-tr {
210 | display: -webkit-box;
211 | display: -webkit-flex;
212 | display: flex;
213 | -webkit-box-orient: horizontal;
214 | -webkit-box-direction: normal;
215 | -webkit-flex-direction: row;
216 | flex-direction: row;
217 | }
218 | .rich-parse-th,
219 | .rich-parse-td {
220 | display: -webkit-box;
221 | display: -webkit-flex;
222 | display: flex;
223 | width: 1160rpx;
224 | overflow: auto;
225 | }
226 | .rich-parse-u {
227 | text-decoration: underline;
228 | }
229 | .rich-parse-hide {
230 | display: none;
231 | }
232 | .rich-emoji-view {
233 | -webkit-box-align: center;
234 | -webkit-align-items: center;
235 | align-items: center;
236 | }
237 | .rich-emoji {
238 | width: 32rpx;
239 | height: 32rpx;
240 | }
241 | .rich-parse-tr {
242 | display: -webkit-box;
243 | display: -webkit-flex;
244 | display: flex;
245 | border-right: 1PX solid #e0e0e0;
246 | border-bottom: 1PX solid #e0e0e0;
247 | border-top: 1PX solid #e0e0e0;
248 | }
249 | .rich-parse-th,
250 | .rich-parse-td {
251 | -webkit-box-flex: 1;
252 | -webkit-flex: 1;
253 | flex: 1;
254 | padding: 10rpx;
255 | border-left: 1PX solid #e0e0e0;
256 | word-break: break-all;
257 | }
258 | .rich-parse-td:last-child {
259 | border-top: 1PX solid #e0e0e0;
260 | }
261 | .rich-parse-th {
262 | background: #f0f0f0;
263 | border-top: 1PX solid #e0e0e0;
264 | }
265 | .rich-parse-del {
266 | display: inline;
267 | }
268 | .rich-parse-figure {
269 | overflow: hidden;
270 | }
271 |
--------------------------------------------------------------------------------
/rich-parse/rich-parse.js:
--------------------------------------------------------------------------------
1 | const { html2json } = require('./helper/html2json')
2 |
3 | global.richParses = {}
4 |
5 | Component({
6 | options: {
7 | addGlobalClass: true,
8 | },
9 |
10 | properties: {
11 | content: {
12 | type: String,
13 | value: '',
14 | observer(newVal) {
15 | this.parse(newVal)
16 | }
17 | },
18 | type: {
19 | type: String,
20 | value: 'html',
21 | },
22 | preview: {
23 | type: Boolean,
24 | value: true,
25 | },
26 | },
27 |
28 | data: {
29 | rich: null,
30 | parse_id: null,
31 | },
32 |
33 | attached() {
34 | // 把组件实例放到全局上,让 rich-render 里面可以访问
35 | global.richParses[this.__wxExparserNodeId__] = this
36 | this.setData({ parse_id: this.__wxExparserNodeId__ })
37 | },
38 |
39 | ready() {
40 | this.parse(this.data.content)
41 | global.tt = this
42 | },
43 |
44 | detached() {
45 | delete global.richParses[this.__wxExparserNodeId__]
46 | },
47 |
48 | methods: {
49 | parse(content, cb) {
50 | const { type } = this.data
51 | if (type === 'md' || type === 'markdown') {
52 | const { md2html = v => v } = global
53 | content = md2html(content)
54 | }
55 | const transData = html2json(content, 'rich')
56 | this.setData({ rich: transData }, cb)
57 | },
58 |
59 | onImgTap(e) {
60 | const detail = {
61 | current: e.target.dataset.src, // 当前显示图片的http链接
62 | urls: this.data.rich.imageUrls, // 需要预览的图片http链接列表
63 | }
64 | this.triggerEvent('imgTap', detail, {})
65 | this.data.preview && wx.previewImage(detail)
66 | },
67 |
68 | onLinkTap(e) {
69 | const { href } = e.currentTarget.dataset
70 | this.triggerEvent('linkTo', { href }, {})
71 | }
72 | }
73 | })
74 |
--------------------------------------------------------------------------------
/rich-parse/rich-parse.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "render-nodes": "./render-nodes/render-nodes"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/rich-parse/rich-parse.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/rich-parse/rich-parse.wxss:
--------------------------------------------------------------------------------
1 | .rich-parse {
2 | font-family: Helvetica, sans-serif;
3 | font-size: 28rpx;
4 | color: #666;
5 | line-height: 1.8;
6 | }
7 |
--------------------------------------------------------------------------------