wemark 在taro环境解析md失效 原生小程序正常 原因是remarkable.js源码使用了void js保留字

https://github.com/TooBug/wemark

 

 

链接中包含了wemark的使用说明 也包括在taro中的使用

但是wemark 在taro中有一个问题 在原生小程序中跑不存在任何的问题 这就是一个十分诡异的问题 所以我的方法是比较了remarkable.js在taro 和原生中运行状态的跟踪 发现了蹊跷 下面就是整个过程

wemark.js 中

if(this.data.type === 'wemark'){
 console.log(parsedData,"wemark=====")
打印出来的parsedData 是一个空数组 进入代码后走到parser.js 
 this.setData({
  parsedData
 });
}

parser.js在执行中返回的数组是空数组

function parse(md, options){
 if(!options) options = {};
 var tokens = parser.parse(md, {});
   console.log('tokentokens99999====',tokens)

在这里就返回了空数组

再深入代码走入remarkable.js的压缩混淆后的源码中

第一步走了这里

s.prototype.parse=function(e,t){
  var r=new n(this,e,t);
    console.log('parse2测ss',r.tokens)
在这里打印出来的r.tokens是有数据的 return 阻断之后是没有数据的 说明是下面的代码问题继续往this.core.process函数中走
    return this.core.process(r),r.tokens
  }
n.prototype.process=function(e){
  var t,r,n;
  //console.log(this.ruler.getRules("")[0](e),"n[t](e)0000")
 // console.log(e,"e=========chulihou")
 //return
 //  function a (e) {
 //
 //    // e.inlineMode ? e.tokens.push({ type: "inline", content: e.src.replace(/\n/g, " ").trim(), level: 0, lines: [0, 1], children: [] }) : e.block.parse(e.src, e.options, e.env, e.tokens);
 //   // debugger
 //    console.log('e.block.parse====',e.block.parse)
 //    e.block.parse(e.src, e.options, e.env, e.tokens);
 //  };
 // a(e)
  console.log("22223e9999",e)
 // console.log(this.ruler.getRules(""),"this.ruler.getRules(\"\")[0]")
走到这里的时候return 发现打出来的r.tokens还是空数组 但是把下面的这行代码放开后 r.tokens就有数据了 
说明tokens的赋值操作还是在下面执行 可见n[t](e) 这个回调函数的作用   e就是我们markdown 传入的md文本 

  for(n=this.ruler.getRules(""),t=0,r=n.length;r>t;t++)n[t](e)
}

于是我们继续进入n[t](e)这个函数中去  打印出这个函数大概是这样子的

//  function a (e) {
//
//    // e.inlineMode ? e.tokens.push({ type: "inline", content: e.src.replace(/\n/g, " ").trim(), level: 0, lines: [0, 1], children: [] }) : e.block.parse(e.src, e.options, e.env, e.tokens);
//   // debugger
//    console.log('e.block.parse====',e.block.parse)
//    e.block.parse(e.src, e.options, e.env, e.tokens);
//  };

由于e.inlineMode是false 所以走了e.block.parse(e.src, e.options, e.env, e.tokens);的逻辑

于是我们再次进入e.block.parse(e.src, e.options, e.env, e.tokens); 调用的是原型上的方法

n.prototype.parse=function(e,t,r,n){
//debugger

 console.log('进入parse函数拉===hahahhahahahhahhahah')
 console.log(n,"block.parse======")
 console.log('e===============e=============ee===e.indexOf("  ")>=0',e.indexOf("  ")>=0)
// var s=new o(e,this,t,r,n)
//  console.log(s,"sssssssssssss")
//  void this.tokenize(s,s.line,s.lineMax)
 //console.log('最后测试r====',n)
 //return
 var s,i=0,u=0;return e?(e=e.replace(c," "),e=e.replace(a,"\n"),e.indexOf("  ")>=0&&(e=e.replace(l,function(t,r){
   console.log(new o(e,this,t,r,n),"new o(e,this,t,r,n)=======")
   var n;return 10===e.charCodeAt(r)?(i=r+1,u=0,t):(n="    ".slice((r-i-u)%4),u=r-i+1,n)})),
   s=new o(e,this,t,r,n),void this.tokenize(s,s.line,s.lineMax)):[]
走到了这里走到 s=new o(e,this,t,r,n) 把return 断掉 输出的r依然是一个空数组 然后把void放开,发现数组有值了,简直是欣喜若狂然后就顺其自然的在void this.tokenize(s,s.line,s.lineMax))中加了一个return  之后发现数组没有值了(这些操作都是在原生小程序中打的断点 否则taro环境是不可能出现数组有值的情况的,因为代码在taro环境遇到障碍并且不报错)
这就验证了this.tokenize 的执行情况,并且把相同的代码放到了taro环境中跑,发现this.tokenize 函数根本就没有执行,而在原生中可跑,并且不return 阻断的情况下就可以输出r.tokens数组并且长度不为0,这就验证了是tokenize在taro中受阻了
那么我们看一看这个函数
这也是原型上的方法
n.prototype.tokenize=function(e,t,r){
  console.log('tokenize执行1======')
  for(var n,s,o=this.ruler.getRules(""),i=o.length,l=t,a=!1;r>l&&(e.line=l=e.skipEmptyLines(l),!(l>=r))&&!(e.tShift[l]<e.blkIndent);){for(s=0;i>s&&!(n=o[s](e,l,r,!1));s++);if(e.tight=!a,e.isEmpty(e.line-1)&&(a=!0),l=e.line,r>l&&e.isEmpty(l)){if(a=!0,l++,r>l&&"list"===e.parentType&&e.isEmpty(l))break;e.line=l}}}

 

看起来没有什么神奇的,其实这个里面ruler全局变量加载了一个函数

大概就是下面这段代码

function n(){this.ruler=new s;for(var e=0;e<i.length;e++)this.ruler.push(i[e][0],i[e][1],{alt:(i[e][2]||[]).slice()})}var s=e("./ruler"),o=e("./rules_block/state_block"),i=[["code",e("./rules_block/code")],["fences",e("./rules_block/fences"),["paragraph","blockquote","list"]],["blockquote",e("./rules_block/blockquote"),["paragraph","blockquote","list"]],["hr",e("./rules_block/hr"),["paragraph","blockquote","list"]],["list",e("./rules_block/list"),["paragraph","blockquote"]],["footnote",e("./rules_block/footnote"),["paragraph"]],["heading",e("./rules_block/heading"),["paragraph","blockquote"]],["lheading",e("./rules_block/lheading")],["htmlblock",e("./rules_block/htmlblock"),["paragraph","blockquote"]],["table",e("./rules_block/table"),["paragraph"]],["deflist",e("./rules_block/deflist"),["paragraph"]],["paragraph",e("./rules_block/paragraph")]];

 

只要是引入了paragraph.js 源码中这个js文件其实是在另一个文件夹中的 引入这个js主要就是生成md的文本切断分片文件 这是一个核心文件

而全局变量ruler承担了一项非常重要的工作,就是根本paragraph类型把传入的md进行分片操作 tokenize 这个函数主要的作用就是这个, 它间接的调用了paragraph.js中push tokens的方法

paragraph.js中 push tokens的方法

找了一段源码贴过来

module.exports = function paragraph(state, startLine/*, endLine*/) {
  var endLine, content, terminate, i, l,
      nextLine = startLine + 1,
      terminatorRules;

  endLine = state.lineMax;

  // jump line-by-line until empty one or EOF
  if (nextLine < endLine && !state.isEmpty(nextLine)) {
    terminatorRules = state.parser.ruler.getRules('paragraph');

    for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
      // this would be a code block normally, but after paragraph
      // it's considered a lazy continuation regardless of what's there
      if (state.tShift[nextLine] - state.blkIndent > 3) { continue; }

      // Some tags can terminate paragraph without empty line.
      terminate = false;
      for (i = 0, l = terminatorRules.length; i < l; i++) {
        if (terminatorRules[i](state, nextLine, endLine, true)) {
          terminate = true;
          break;
        }
      }
      if (terminate) { break; }
    }
  }

  content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();

  state.line = nextLine;
  if (content.length) {
    state.tokens.push({
      type: 'paragraph_open',
      tight: false,
      lines: [ startLine, state.line ],
      level: state.level
    });
    state.tokens.push({
      type: 'inline',
      content: content,
      level: state.level + 1,
      lines: [ startLine, state.line ],
      children: []
    });
    state.tokens.push({
      type: 'paragraph_close',
      tight: false,
      level: state.level
    });
  }

  return true;
};
},

 

说着说着就跑题了,那么问题找到了,我们应该如何解决这个问题呢,我发现js文件中为啥要用void呢,虽然void在原生小程序中不报错,是不是说taro把void这种保留字禁用了呢 如果是这样的话 那么有它的道理,

于是我把void去掉直接通过原型链的查找机制找到原型上的方法即可 ,可能代码比较老,所以容易出现问题

void this.tokenize(s,s.line,s.lineMax))  改成了this.tokenize(s,s.line,s.lineMax))

 

然后在taro环境中顺利的打印出来了r.tokens 我欣喜若狂 这真是一次十分艰难的代码跟踪

不过总算是把问题解决了,我也随机在npm发布了demo   支持taro版本的没有bug的 markdown 解析器 想要的或者是在taro中使用markdown解析的关注我

我的微信号是:gwd1991

}

 

 

 

后续又发现很多markdown文章不能展示的情况

继续删除了remarkable.js中的响应void

改动如下

(r=e.cacheGet(o))>0)return void(e.pos=r);

去掉return 前端的void 后正常返回tokes数组

return void e.cacheSet(o,e.pos);

去掉后为

return e.cacheSet(o,e.pos);

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值