井井客

搜索

【微信小程序】将富文本解析为rich-text支持的JSON格式

微信小程序在遇到解析富文本的坑时,小伙伴可能用wxParse插件,github中也可以搜索到,但是我自己的博客文章就不太合适,里面比较多的pre的标签,插件的支持不太好。

【微信小程序】将富文本解析为rich-text支持的JSON格式

所以自己写了一个解析代码,比较精简,当然也有不完美的地方,但也暂时满足了我的需求。

代码核心是将html文本解析成一棵树,类似于DOM结构。按照微信小程序中的“rich-text”,将值传进去即可。

可以从http://www.jingjingke.com/web/weixin/richTextParse.rar下载代码包并解压到你微信程序中的utils文件夹中。

里面一个JS文件,一个样式文件,在合适的位置引入,这一步应该不需要多做解释的。

  // "app.wxss" 中引入样式文件
  @import 'utils/richTextParse/richText.wxss';

  // "pages/article/index.js"中引入JS文件
  var richTextParse = require('../../utils/richTextParse/richText.js');

其中这个JS里面抛出的方法名字叫"go",使用“richTextParse.go(富文本)”进行使用。例如我的:

  bodyHtml: richTextParse.go(rs.data.body),

而在“pages/article/index.js”中完成最后一步即可:

<rich-text nodes='{{bodyHtml}}'></rich-text>

完整的JS代码如下:

function richTextParse(data) {
  //支持标签
  //	let nameArr = ['a','abbr','b','blockquote','br','code','col','colgroup','dd','del','div','dl','dt','em','fieldset','h1','h2','h3','h4','h5','h6','hr','i','img','ins','label','legend','li','ol','p','q','span','strong','sub','sup','table','tbody','td','tfoot','th','thead','tr','ul'];
  let nameArr = ['a', 'b', 'code', 'dd', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'i', 'img', 'label', 'li', 'ol', 'p', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul'];
  //最终结构树
  let tree = [];
  //初索引
  let index = 0;
  //匹配到的所有标签
  let tagArr = data.match(/<[^>]*>/gi);
  //记录标签索引位置
  let indexArr = [];
  //计算索引位置
  for (let i = 0; i < tagArr.length; i++) {
    //添加索引值
    indexArr.push(data.indexOf(tagArr[i]))
    //从字符数据中删除标签
    data = data.replace(tagArr[i], '')
  }

  //记录基本的信息值定义
  let cls, alt, src, width, height, step;

  let i = 0;
  //按标签个数进行循环
  while (i < tagArr.length - 1) {
    //获取基本信息
    tree[index] = sendInfoTree(i)
    index++;
  }

  return tree;

  //将元素添加到tree中
  function sendInfoTree(idx) {
    getStartInfo(tagArr[idx])
    var label = tagArr[idx].match(/<*([^> ]*)/)[1];
    //第一级分支
    var obj = {
      name: checkName(label),
      attrs: {
        class: cls + ' rich-' + label
      },
      children: []
    }
    //相应的一些判断
    if (label === 'img') {
      //判断如果是img特殊标签
      obj.attrs['src'] = src;
      obj.attrs['alt'] = alt;
      obj.attrs['width'] = width;
      obj.attrs['height'] = height;
    } else if (step === 0) {
      //判断是否为单闭合标签(除img外的单闭合标签)-清空内容-方便处理
      obj.children.push({
        type: 'text',
        text: ''
      })
    } else if (tagArr[idx + 1] === '</' + label + '>') {
      //判断紧跟它的下一个标签是否为它的闭合标签
      obj.children.push({
        type: 'text',
        text: data.substring(indexArr[idx], indexArr[idx + 1])
      })
      //索引指向闭合标签
      i++;
    } else {
      //剩下的则可能这是个标签嵌套的一个标签
      //截取两个开始标签中间的内容
      if (indexArr[idx] !== indexArr[idx + 1]) {
        obj.children.push({
          type: 'text',
          text: data.substring(indexArr[idx], indexArr[idx + 1])
        })
      }
      //循环向下去找
      i++;
      while (i < tagArr.length - 1) {
        obj.children.push(sendInfoTree(i));
        //如果标签中间有文本(即索引不一致)
        if (indexArr[i - 1] !== indexArr[i]) {
          obj.children.push({
            type: 'text',
            text: data.substring(indexArr[i - 1], indexArr[i])
          })
        }
        //如果下一个是该结束的话则跳出
        if (tagArr[i] === '</' + label + '>') break;
      }
    }
    i++;
    return obj;
  }

  //获取基本信息
  function getStartInfo(str) {
    //取得一些基本信息
    cls = matchRule(str, 'class');
    src = '';
    alt = '';
    width = '';
    height = '';
    //如果此标签为img标签
    if (str.match(/<*([^> ]*)/)[1] === 'img') {
      src = matchRule(str, 'src');
      alt = matchRule(str, 'alt');
      width = matchRule(str, 'width');
      height = matchRule(str, 'height');
    }
    //判断是否为单闭合标签
    step = str[str.length - 2] === '/' ? 0 : 1;
  }

  //获取部分属性的值
  function matchRule(str, rule) {
    let value = '';
    let re = new RegExp(rule + '=[\'"]?([^\'"]*)');
    if (str.match(re) !== null) {
      value = str.match(re)[1];
    }
    return value;
  }
  //检查是否为支持的标签
  function checkName(str) {
    let name = 'div';
    for (let i = 0; i < nameArr.length; i++){
      if (str === nameArr[i]) {
        name = str;
        break;
      }
    }
    return name;
  }
}

module.exports = {
  go: richTextParse
};

实际上代码只有100多行,里面的注释也比较多,仔细看的话应该还是能顺通的。

比较核心的代码就是getStartInfo函数中,在判断一系列条件之后,如果不满足则会在下面调用getStartInfo。这一步完成了一个树干向下延伸一个分支。

另外还有它的样式文件,样式名源自class: cls + ' rich-' + label这行代码。其中label就是当前的标签。组合起来,意义就能明确了。

例如html中原来是一对pre闭合标签,我使用的样式就是“rich-pre”。

在我的Github中可以看到完整代码:https://github.com/jingjingke/richTextParse.

代码就讲到这里了,如果有不好的地方,欢迎指正~

文章TAG:JS

作者:井井客原创来源:原创
本文标题:【微信小程序】将富文本解析为rich-text支持的JSON格式
本文链接:http://www.jingjingke.com/c/26304.html

上一篇:练手JQ代码实现鼠标移上去显示浮动两边菜单
下一篇:七牛云JS上传文件DEMO

文章分类

相关阅读

随便看看