123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- 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 '<img class="h2w__emoji h2w__emoji--'+token[idx].markup+'" src="'+_ts.config.emoji_path + token[idx].content+'.'+ _ts.config.emoji_type+' "/>';
- return '<g-emoji class="h2w__emoji h2w__emoji--' + token[idx].markup + '">' + token[idx].content + '</g-emoji>';
- };
- _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 === '</';
- })();
- //处理关闭标签替换
- if (isCloseLabel) {
- let labelName = word.substr(2, word.length - 3).toLowerCase();
- if (_ts.isConversion(labelName)) {
- return '</' + _ts.newLabel(labelName) + '>';
- };
- }
- //处理开始标签替换
- 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 '<image ' + newAttrs + '></image>'
- };
- 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这些需要添加</view>关闭标签
- needClose(labelName) {
- let arr = ['hr', 'br'],
- s = '',
- closeTag = arr.some((item, index) => {
- return labelName === item;
- });
- if (closeTag) {
- s = '</view>';
- };
- 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;
|