index.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. const parse2 = require('./parse2/index'),
  2. // parse5 = require('./parse5/index').parse,
  3. config = require('../config'),
  4. // html与wxml转换关系
  5. correspondTag = (()=>{
  6. let result = {
  7. a:'navigator',
  8. todogroup:'checkbox-group',
  9. audio:'audio-player'
  10. };
  11. // 该系列的标签都转换为text
  12. // ['span','b','strong','i','em','code','sub','sup','g-emoji','mark','ins','u'].forEach(item => {
  13. // result[item] = 'text';
  14. // });
  15. // 该系列小程序原生tag,不需转换
  16. [...config.wxml,...config.components].forEach(item => {
  17. result[item] = item;
  18. });
  19. return result;
  20. })(),
  21. // 元素与html对应的wxml标签名
  22. getWxmlTag = tagStr => !tagStr ? undefined : correspondTag[tagStr] || 'view',
  23. // 依赖父级的元素
  24. relyList = ['li'],
  25. // 精简数据,并初始化相关事件等
  26. initObj = (obj,option)=>{
  27. const result = {
  28. theme:option.theme || 'light',
  29. _e:{}
  30. },
  31. events = global._events = {},
  32. base = option.base;
  33. // 主题保存到全局
  34. global._theme = result.theme;
  35. // 事件添加到全局中,各个组件在触发事件时会从全局调用
  36. if(option.events){
  37. for(let key in option.events){
  38. events[key] = option.events[key];
  39. };
  40. };
  41. // 遍历原始数据,处理成能解析的数据
  42. let eachFn;
  43. (eachFn = (arr,obj,_e,isRichTextContent) => {
  44. obj.children = obj.children || [];
  45. _e.child = _e.child || [];
  46. let child = obj.children,
  47. child_e = _e.child;
  48. arr.forEach(item => {
  49. if(item.type === 'comment'){
  50. return;
  51. };
  52. let o = {
  53. type:item.type === 'text' ? 'text' : isRichTextContent ? 'node' : item.type
  54. },
  55. e = {},
  56. attrs = o.attrs = item.attribs || {};
  57. if(item.type === 'text'){
  58. o.text = e.text = item.data;
  59. }else{
  60. if(isRichTextContent){
  61. o.name = item.name;
  62. }else{
  63. o.tag = getWxmlTag(item.name); // 转换之后的标签
  64. // o.tag = o.tag === 'text' ? 'view' : o.tag;
  65. e.tag = item.name; // 原始
  66. o.attrs = item.attribs;
  67. e.attrs = JSON.parse(JSON.stringify(attrs));
  68. };
  69. attrs.class = attrs.class ? `h2w__${item.name} ${attrs.class}` : `h2w__${item.name}`;
  70. // 处理资源相对路径
  71. if(base && attrs.src){
  72. let src = attrs.src;
  73. switch (src.indexOf('//')) {
  74. case 0:
  75. attrs.src = `https:${src}`;
  76. break;
  77. case -1:
  78. attrs.src = `${base}${src}`;
  79. break;
  80. };
  81. };
  82. };
  83. o.rely = relyList.indexOf(e.tag) > -1; // 判断是否不能嵌套其它标签
  84. if(item.children){
  85. eachFn(item.children,o,e,isRichTextContent || item.name === 'rich-text');
  86. };
  87. child.push(o);
  88. child_e.push(e);
  89. });
  90. })(obj,result,result._e,false);
  91. return result;
  92. };
  93. module.exports = (str,option) => {
  94. str = (()=>{
  95. let re = /<body[^>]*>([\s\S]*)<\/body>/i;
  96. if(re.test(str)){
  97. let result = re.exec(str);
  98. return result[1] || str;
  99. }else{
  100. return str;
  101. };
  102. })();
  103. return initObj(parse2(str,{decodeEntities:true}),option);
  104. };