class towxml { constructor(option) { const _ts = this; option = option || {}; for (let i in option) { _ts.config[i] = option[i]; }; _ts.m = {}; let mdOption = { html: true, xhtmlOut: true, typographer: true, highlight: function (code, lang, callback) { return _ts.m.highlight.highlightAuto(code).value; } }; if (global) { _ts.m.html2json = require('./lib/html2json'); _ts.m.highlight = require('./plugins/hljs/index'); _ts.m.md = require('./lib/markdown-it')(mdOption); _ts.m.md_sub = require('./plugins/markdown-it-sub'); _ts.m.md_sup = require('./plugins/markdown-it-sup'); _ts.m.md_ins = require('./plugins/markdown-it-ins'); _ts.m.md_mark = require('./plugins/markdown-it-mark'); _ts.m.md_emoji = require('./plugins/markdown-it-emoji'); } else if (window) { _ts.m.html2json = window.html2json; _ts.m.highlight = window.hljs; _ts.m.md = new window.markdownit(mdOption); _ts.m.md_sub = window.markdownitSub; _ts.m.md_sup = window.markdownitSup; _ts.m.md_ins = window.markdownitIns; _ts.m.md_mark = window.markdownitMark; _ts.m.md_emoji = window.markdownitEmoji; }; _ts.m.md.use(_ts.m.md_sub); _ts.m.md.use(_ts.m.md_sup); _ts.m.md.use(_ts.m.md_ins); _ts.m.md.use(_ts.m.md_mark); _ts.m.md.use(_ts.m.md_emoji); _ts.m.md.renderer.rules.emoji = function (token, idx) { // return ''; return '' + token[idx].content + ''; }; _ts.wxmlTag = ['view', 'video', 'swiper', 'block', 'swiper-item', 'button', 'slider', 'scroll-view', 'movable-area', 'movable-view', 'text', 'progress', 'checkbox-group', 'label', 'checkbox', 'form', 'switch', 'input', 'radio-group', 'radio', 'picker', 'picker-view', 'switch', 'textarea', 'navigator', 'audio', 'image', 'map', 'canvas', 'contact-button']; } //markdown转html md2html(mdContent) { const _ts = this; return _ts.m.md.render(mdContent); } //html转wxml html2wxml(htmlContent) { const _ts = this; let re = /<[^<]*>/ig, wxml = htmlContent.replace(re, (word) => { //检查是否为关闭标签 let isCloseLabel = (() => { let star = word.substr(0, 2); return star === ''; }; } //处理开始标签替换 else { let delWordBbrackets = word.substr(1, word.length - 2), //剔除首尾尖括号 wordSplit = delWordBbrackets.split(' '), //得到元素标签与属性 labelName = wordSplit[0].toLowerCase(), //取得tagName className_htmlTag = 'h2w__' + labelName; if (_ts.isConversion(labelName)) { wordSplit.splice(0, 1); //剔除元素的标签 //检查元素是否已经有className,有的话在原基础上添加新的类名 let wordSplitLen = wordSplit.length, isClassExist = (() => { if (wordSplitLen) { for (let i = 0; i < wordSplitLen; i++) { let item = wordSplit[i], re = /class="/ig; if (re.test(item)) { wordSplit[i] = item.replace(re, (word) => { return word + className_htmlTag + ' '; }); return true; }; }; }; return false; })(); //如果元素没有className,则新加上className if (!isClassExist) { wordSplit.unshift('class="' + className_htmlTag + '"'); }; //组合属性 let newAttrs = (() => { let s = ''; wordSplit.forEach((item, index) => { s += item + ' '; }); s = s.substr(0, s.length - 1); return s; })(); //如果是图片 if (labelName === 'img') { return '' }; return '<' + _ts.newLabel(labelName) + ' ' + newAttrs + '>' + _ts.needClose(labelName); }; }; return word; }); return wxml; } //markdown转wxml md2wxml(mdContent) { const _ts = this; let html = _ts.md2html(mdContent), wxml = _ts.html2wxml(html), deCode = str => { let s = ''; if(str.length === 0){ return s; }; s = str.replace(/&/ig,'&'); s = s.replace(/</ig, "<"); s = s.replace(/>/ig, ">"); s = s.replace(/ /g, " "); s = s.replace(/'/g, "'"); s = s.replace(/"/g, """); return s; }; return deCode(wxml); } //检查标签是否需要转换 isConversion(labelName) { const _ts = this; return !_ts.wxmlTag.some((item, index) => { return labelName === item; }); } //处理自关闭标签,hr,br这些需要添加关闭标签 needClose(labelName) { let arr = ['hr', 'br'], s = '', closeTag = arr.some((item, index) => { return labelName === item; }); if (closeTag) { s = ''; }; return s; } //html与wxml对应的标签 newLabel(labelName) { let temp = 'view'; switch (labelName) { case 'a': temp = 'navigator'; break; case 'span': case 'b': case 'strong': case 'i': case 'em': case 'code': case 'sub': case 'sup': case 'g-emoji': case 'mark': case 'ins': temp = 'text'; break; }; return temp; } //html2json //content html、markdown字符串 //type 'html|markdown|xml' toJson(content, type) { const _ts = this; type = type || 'html'; let json = '', sortOutJson; if (type === 'markdown') { json = _ts.m.html2json(_ts.md2wxml(content)); } else if (type === 'html') { json = _ts.m.html2json(_ts.html2wxml(content)); }; //遍历json将多个class属性合为一个 (sortOutJson = (json) => { for (let i in json) { if (i === 'child' && typeof json[i] === 'object' && json[i].length) { json[i].forEach((item, index) => { sortOutJson(item); }); }; if (i === 'attr') { if (typeof json[i].class === 'string') { json[i].className = json[i].class; } else if (typeof json[i].class === 'object' && json[i].class.length) { json[i].className = json[i].class.toString().replace(/,/g, ' '); }; }; }; })(json); json.theme = 'light'; return json; } }; module.exports = towxml;