const Audio = require('./Audio'), tagsAndAttrs = require('./tagsAndAttrs'); class ToJson { constructor(html,app){ const _ts = this; let m = _ts.m = {}; m.parse = require('./parse5'); _ts.html = html; _ts.data = {}; _ts.app = app; // 得到整体页面的数据 _ts.data.document = m.parse.parse(_ts.html); // 得到body部分的数据 _ts.data.body = _ts.getBodyData(_ts.data.document); // 生成当前的数据ID _ts.id = `dataId_${+new Date}_${(Math.random()+'').slice(2)}`; // 将数据保存到全局 global.__towxmldata__ = global.__towxmldata__ || {}; global.__towxmldata__[_ts.id] = global.__towxmldata__[_ts.id] || {}; global.__towxmldata__[_ts.id].audio = {}; } getData(){ const _ts = this, m = _ts.m; let data = _ts.data, outData = _ts.sortOut(data.body); outData.node = 'root'; // 为数据添加ID outData.id = _ts.id; global.__towxmldata__[_ts.id].article = outData; return global.__towxmldata__[_ts.id].article; } /** * 遍历页面数据整理成小程序想要的 */ sortOut(bodyData){ const _ts = this, app = _ts.app, appData = app.data ; let result = {}, arrange; (arrange = (data,result)=>{ // 当有数据且有子元素时则遍历 if(data && data.childNodes && data.childNodes.length){ // 子元素数据不存在时,创建一个空的数组用以存储子元素数据 if(!result.child){ result.child = []; }; // 遍历子节点,处理节点的数据 for(let i=0,len=data.childNodes.length; i<len; i++){ let node = data.childNodes[i], // 得到具体的节点 attrs = node.attrs, // 得到节点的属性(一个数组) attrsLength = attrs && attrs.length ? attrs.length : 0, // 得到节点属性的长度 current = { // 创建一个空对象,用于存储节点属性及处理之后的属性 _e:{}, attr:{} // html的原始数据 }; if(node){ result.child.push(current); }; // 如果有属性则处理其属性 if (attrsLength) { if (current._e.attr === undefined) { //current.attr = {}; current._e.attr = {}; }; for (let i = 0; i < attrsLength; i++) { let attrsItem = attrs[i], key = attrsItem.name, val = attrsItem.value; current.attr[key] = val; current._e.attr[key] = val; }; }; for(let key in node){ // 保留最原始的html数据,父节点数据去掉(小程序会报错) if(typeof node[key] !== 'object'){ current._e[key] = node[key]; }; switch (node.nodeName) { case 'body': current['node'] = 'root'; break; case '#text': current['node'] = 'text'; current['text'] = node.value; break; default: current['node'] = 'element'; break; }; }; // 当前标签是audio的情况下 if(node.tagName === 'audio'){ current.tag = "view"; current.attr = {}; current.attr.class = 'audioForH2w'; current._id = `audio_${+new Date()}_${(Math.random()+'').slice(2)}`; // // 用于保存播放器数据(小程序在setData完成之后,新的数据会重新占用内存空间,故此处保存没有必要) // if(appData){ // appData.__audioData__ = appData.__audio__ || {}; // appData.__audioData__[current._id] = current; // }; // 创建播放器子元素 current.child = [ { node:"element", tag:"view", attr:{ class:"h2w__view audioForH2w__icon" } },{ node:"element", tag:"view", attr:{ class:"h2w__view audioForH2w__cover" }, child:[ { node:"element", tag:"image", type:"audio", attr:{ class:"h2w__img" } } ] },{ node:"element", tag:"view", attr:{ class:"h2w__view audioForH2w__info" }, child:[ { node:"element", tag:"view", attr:{ class: "h2w__view audioForH2w__schedule", style: "width:0px;" } },{ node:"element", tag:"view", attr:{ class:"audioForH2w__title" }, child:[ { node:"text", text: "--", attr: {} } ] },{ node:"element", tag:"view", attr:{ class:"audioForH2w__author" }, child:[ { node:"text", text: "佚名", attr: {} } ] },{ node:"element", tag:"view", attr:{ class:"audioForH2w__time" }, child:[ { node:"text", text: "00:00:00 / 00:00:00", attr: {} } ] } ] } ]; if(appData){ // 得到音频选项 let audioOption = ((node)=>{ let option = {}, nodeAttrs = node.attrs; for(let i=0,len=nodeAttrs.length; i<len; i++){ let attrItem = nodeAttrs[i]; option[attrItem.name] = attrItem.value; }; return option; })(node); // 保存当前播放器数据 global.__towxmldata__[_ts.id].audio[current._id] = current; //用于保存播放器对象 appData.__audioObj__ = appData.__audioObj__ || {}; appData.__audioObj__[current._id] = Audio({ app:app, // 传入APP playerId:current._id, // 当前播放器ID dataId:_ts.id, // 数据ID option:audioOption // 传入音频选项 }); }; }else if(node.tagName){ current.tag = _ts.getTag(node.tagName); current.attr.class = current.attr.class ? `h2w__${node.tagName} ${current.attr.class}` : `h2w__${node.tagName}`; }; arrange(node,current); }; }; })(bodyData,result); return result; } /** * 获取属于body那部分的数据 */ getBodyData(documentData){ let data, getBody; (getBody = (list)=>{ for(let i=0,len=list.length; i<len; i++){ let item = list[i]; if(item.nodeName === 'body' && item.tagName === 'body'){ data = item; break; }else if (item.childNodes){ getBody(item.childNodes); }; } })(documentData.childNodes); return data; } /** * 得到转换对应的tag */ getTag(tagName){ let correspondTag = this.correspondTag(), wxmlTag = correspondTag[tagName] === undefined ? 'view' : correspondTag[tagName]; return wxmlTag; } /** * 组织html与小程序的tag对应关系 */ correspondTag(){ let data = { 'a':'navigator', 'img':'image', 'todogroup':'checkbox-group' }; // 该系列的标签都转换为text ['span','b','strong','i','em','code','sub','sup','g-emoji','mark','ins'].forEach(item => { data[item] = 'text'; }); // 该系列是小程序原生tag,不需要转换 tagsAndAttrs.wxml.forEach(item => { data[item] = item; }); return data; } }; module.exports = ToJson;