HTML 转 JSON 的小程序解析组件目前有不少,丸子 WordPress 小程序目前所使用的还是以 wxParse 为主。但是,wxParse 对于文章代码内容显示无高亮,看起来没有那么舒服。于是,经过一番搜索和尝试,可以找到解决方法。方法教程出自日出一点一,点击这里查看原文

以下教程适合于有编程基础或愿意折腾的人,如果不想折腾,或者按教程无法改造出来,可以通过下方的链接地址前往网盘下载,提取码需要通过微信扫描二维码获取。

wxPares 高亮版

WordPress 小程序代码内容高亮组件

小程序下载需要网盘提取码或密码,请使用微信扫描二维码获取

提示:关注 WordPressTalk 公众号后,使用微信扫描二维码获取

WPSTORM - WordPress 小程序主题资源平台_WordPress小程序下载站点

第一步:修改 wxParse

1. 修改代码换行问题

wxParse 默认是替换掉所有的换行,包括“\n”和“\r\n”,因此,对 wxParse 替换掉换行的代码进行修改(下面的代码在 wxDiscode.js 文件的 strMoreDiscode 函数中):

function strMoreDiscode(str){
    //str = str.replace(/\r\n/g,"");  
    str = str.replace(/([^\r])\n/g,'$1');
    //str = str.replace(/code/g,"wxxxcode-style");
    return str;
}

经过上面的修改,在进行替换时,会将“\n”替换掉而“\r\n”并不会,这样就保留了代码段中的换行。

2. 修改 HTML 转义字符

先找到 wxDiscode.js 以下内容

str = str.replace(/</g, '<');
str = str.replace(/>/g, '>');
str = str.replace(/&/g, '&');

在前面加上 // 将内容注释,然后在 html2json.js 中的 transEmojiStr() 函数中添加这三个字符的替换:

function transEmojiStr(str){
  // var eReg = new RegExp("["+__reg+' '+"]");
  //修复 < > 的显示问题
  str = str.replace(/</g, '<');
  str = str.replace(/>/g, '>');
  str = str.replace(/&/g, '&');

3. /* */注释不显示问题

如果文章内容中含有“/* */” 的注释,wxParse 在解析时会替换掉,解决的办法就是在 html2json.js 中注释掉这个替换语句:

function trimHtml(html) {
  return html
        //.replace(/\n+/g, '')
        .replace(/ /ig, '')
        // 替换掉 /* */
        //.replace(/\/\*.*?\*\//ig, '')
        .replace(/[ ]+&lt;/ig, '&lt;')
}

4. 修改获取文章内容数据

把返回的文章内容替换代码高亮标签,如:

//替换代码标签
var contents = response.data.content.rendered.replace(/<pre[^>]*><code class=\"([^\s]*)\">/g, "<pre class=\"pure-highlightjs $1\">").replace(/<\/code><\/pre>/g, "</pre>");
//替换标签后内容返回
WxParse.wxParse('article', 'html', contents, this, 5);

完成以上步骤,改造完成了一半。

第二步,导入代码高亮插件

1. 获取 Prism 插件

首先要去 Prism 的官网下载相应的 js 和 css 文件,可以根据自己的需要来选择支持的代码语言和代码高亮的样式(Plugins 可以不选),官网下载页面点击这里

将下载下来的 prism.js 和 prism.css(重命名为 prism.wxss)添加到小程序的代码路径下,添加到哪里都行,只要在相应的文件中正确引用就行。比如我这里以添加到“/wxParse/prism.wxss” 和 “/wxParse/prism.js” 为例,如果你添加的路径和我的不同,下面代码中关于这两个的路径一定记得做更改!

然后修改 prism.wxss 把“pre”换成“.wxParse-pre”。因为在 HTML 中,我们是用 “pre” 标签来标识代码,而在小程序中,经过 wxparse 的解析后,“pre” 变为了 “class=wxParse-pre”,即 “pre” 标签元素在解析后变为了 class=“wxParse-pre” 元素,所以 prism.css 中的选择器也要做相应的更改(元素选择变为 class 选择),例如:

/* 原来的 */
pre[class*="language-"] {
	padding: 1em;
	margin: .5em 0;
	overflow: auto;
}
/* 修改后的 */
.wxParse-pre {
	padding: 1em;
	margin: .5em 0;
	overflow: auto;
}

2、添加 HIGHLIGHT.JS

highlight.js 就是处理代码段高亮的核心部分了。当然一些代码是参考“richText”的解析来写的。将下面的代码直接复制为“highlight.js”并添加到小程序的“/wxParse/highlight.js”。

//https://blog.sunriseydy.top/technology/server-blog/wordpress/wordpress-miniapp-code-highlight/

var Prism = require('./prism.js'); // 引入 prism.js ,注意改为自己的路径
function highlight(data) {
  // 用来测试代码执行的时间
  // let beginTime = new Date().getTime();
  // console.log('开始时间:'+beginData);
  let nameArr = ['pre'];
  // Prism 所支持的代码语言数组
  let langArr = new Array();
  langArr = listLanguages(); // 获取 PrismJs 中的代码语言
  // console.log("langArr: "+ langArr);
  // 为了防止代码段中的换行被 wxDiscode 给替换掉,不能使用 str = str.replace(/\n/g,""); 语句,要使用 str = str.replace(/([^\r])\n/g,'$1');。因为在我的代码段中换行都是 /r/n,而文章其他部分都是 /n。我这里注释掉是因为 wxDiscode 中已经添加了 str = str.replace(/([^\r])\n/g,'$1');
  // data = data.replace(/([^\r])\n/g, '$1');
  let html = data; // html 是代码高亮后的 html 内容,小写的 html 对应着下面的“替换”方法用到的变量
  // let HTML = ''; // 这里是整合代码高亮方法二用到的变量,用的是字符串相加方法。
  //匹配到的所有标签<\/pre>
  let tagArr = data.match(/<\/?pre[^>]*>/g);
  // 如果没有 pre 标签就直接返回原来的内容,不做代码高亮处理
  if (tagArr == null) {
    return html;
  }
  //记录每一个 pre 标签在data中的索引位置
  let indexArr = [];
  //计算索引位置
  for (let i = 0; i < tagArr.length; i++) {
    //添加索引值
    if (i == 0) {
      indexArr.push(data.indexOf(tagArr[i]));
    }
    else {
      indexArr.push(data.indexOf(tagArr[i], indexArr[i - 1]));
    }
  }
  // console.log("indexArr: "+indexArr);
  //记录基本的class信息
  let cls;
  // 开始循环处理 pre 标签
  let i = 0;
  while (i < tagArr.length - 1) { // 这里减一是因为不处理最后的 </pre> 标签
    // 调用函数来获取 class 信息
    getStartInfo(tagArr[i])
    // 获取标签的值
    var label = tagArr[i].match(/<*([^> ]*)/)[1];
    // console.log("label: "+label);
    //相应的一些判断
    if (tagArr[i + 1] === '</' + label + '>') { //判断紧跟它的下一个标签是否为它的闭合标签
      // console.log("cls: "+cls);
      if (label === 'pre' && cls.split(' ').indexOf('pure-highlightjs') >= 0) { // 这里的条件判断,第二个要根据自己的代码段情况来自定义。我的代码段 pre 都有一个 class 是 pure-highlightjs
        // 代码语言判断,根据类进行判断,自定义,比如 lang-语言,language-语言。
        // 取第二个 class 的值,根据自己的代码段情况自定义。我的代码语言值是 class 的第二个值
        let lang = cls.split(' ')[1]; // [1] 代表第二个
        if (/lang-(.*)/i.test(lang)) { // 代码语言定义是 lang-XXX 的样式
          lang = lang.replace(/lang-(.*)/i,'$1');
        }
        else if (/languages?-(.*)/i.test(lang)) {
          lang = lang.replace(/languages?-(.*)/i, '$1'); // 代码语言定义是 language(s)-XXX 的样式
        }
        // console.log("lang: "+ lang);
        if (langArr.indexOf(lang) == -1 || lang == null || lang == 'none' || lang == 'null') { // 如果代码语言不在 Prism 存在的语言,或者 class 值是 null,则不执行代码高亮函数
          // 下面的这些注释掉的是方法二,将原来的内容中普通文本和代码段连接起来
          // if (i == 0) {
          //   HTML = HTML + data.substring(0, indexArr[i+1]);
          // }
          // else if (i == (tagArr.length - 2)) {
          //   HTML = HTML + data.substring(indexArr[i - 1]);
          // }
          // else {
          //   HTML = HTML + data.substring(indexArr[i - 1], indexArr[i+1]);
          // }
        }
        else {
          console.log("lang: " + lang);
          // 获取代码段内容为 code
          let code = data.substring(indexArr[i], indexArr[i + 1]).replace(/<pre[^>]*>/, '');

          // console.log('code: ' + code);
          // 执行 Prism 的代码高亮函数,先做一个替换,将转义后的 < > & 恢复
          let hcode = Prism.highlight(escape2Html(code), Prism.languages[lang], lang);
          // console.log("hcode: "+ hcode);
          // 下面同样是方法二
          // if (i == 0) { // 如果是第一个代码段,将代码段前面的内容和高亮后的内容相加
          //   HTML = HTML + data.substring(0,indexArr[i]) + '<pre class="pure-highlightjs ' + lang + '">' + hcode;
          // }
          // else if (i == (tagArr.length - 2) ) { // 如果是最后一个代码段,将上一个</pre>到这个<pre>中的内容和高亮后的内容和代码段后面的内容相加
          //   HTML = HTML + data.substring(indexArr[i-1], indexArr[i]) + '<pre class="pure-highlightjs ' + lang + '">' + hcode + data.substring(indexArr[i+1]);
          // }
          // else { // 将上一个</pre>到这个<pre>中的内容和高亮后的内容相加
          //   HTML = HTML + data.substring(indexArr[i-1], indexArr[i]) + '<pre class="pure-highlightjs ' + lang + '">' + hcode;
          // }
          // 这里是方法一,直接替换原来未被高亮的代码为高亮后的代码段。相比方法一可能会比较耗时,但是简单。
          html = html.replace(code, hcode);
          // console.log('每一个html: '+html);
        }

      }
      // 指向下一个标签(闭合标签)索引
      i++;
    }
    // 指向下一个标签(开始标签)的索引
    i++;
  }
  // console.log("html: "+html);
  // 测试执行时间
  // let endTime = new Date().getTime();
  // let executeTime = endTime - beginTime;
  // console.log('高亮执行时间: ' + executeTime + '毫秒');
  // 如果用的是方法二就将下面的 html 改为 HTML
  return html;
  //获取基本信息
  function getStartInfo(str) {
    //取得一些基本信息
    cls = matchRule(str, 'class');
  }
  //获取部分属性的值
  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;
  }
  //html字符转换 // 注意,顺序不能错
  function escape2Html(str) {
    str = str.replace(/&lt;/g, '<');
    str = str.replace(/&gt;/g, '>');
    str = str.replace(/&amp;/g, '&');
    return str;
  }
  // 列出当前 Prism.js 中已有的代码语言,可以自己在 Prism 的下载页面选择更多的语言。
  function listLanguages() {
    var langs = new Array();
    let i = 0;
    for (let language in Prism.languages) {
      if (Object.prototype.toString.call(Prism.languages[language]) !== '[object Function]') {
        langs[i] = language;
        i++;
      }
    }
    return langs;
  }
}
module.exports = {
  highlight: highlight
};

3、添加相关引用

在添加了 highlight.js 后,就要在 html2json.js 中引用并调用该文件。

首先在 html2json.js 开头引用 highlight.js

var highlight = require(‘./highlight.js’); // 注意路径

然后在 html2json() 函数中调用:

function html2json(html, bindName) {
    //处理字符串
    // console.log('1');
    html = removeDOCTYPE(html);
    html = trimHtml(html);
    html = wxDiscode.strDiscode(html);
    html = highlight.highlight(html);

这里要注意的是,在调用 strDiscode() 函数后再调用 highlight() 函数!

接着是样式表的引用,在 detail.wxss 的开头部分引用 prism.wxss :

@import "../../utils/prism.wxss"; // 注意路径

第三步,测试代码高亮

发布文章的时候,需要使用填写代码语言的 class 。比如

<pre><code class="javascript">这里是 Javascript 代码</code></pre>

wxPares 高亮版

WordPress 小程序代码内容高亮组件

小程序下载需要网盘提取码或密码,请使用微信扫描二维码获取

提示:关注 WordPressTalk 公众号后,使用微信扫描二维码获取

WPSTORM - WordPress 小程序主题资源平台_WordPress小程序下载站点