index.js 4.0 KB

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