当前位置: 首页 > news >正文

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);

相关文章:

  • 赛车游戏(一)通过蓝牙实现两个手机交互
  • 关于npm 发布包的一个完整流程
  • 赛车游戏(二)一个Mascot Capsule v3多人游戏例子
  • 正则捕获的复习
  • 老王咔咔地到处在找之前一个Library的源码~~~!
  • 百度小程序使用lottie 动画组件 taro版本 支持百度小程序 安卓版本 和ios版本
  • 从逻辑分区中划出主分区
  • husky 生成commit 规范
  • 测试富文本代码片
  • Bill 讲座有感
  • 正则匹配替换相应的标签
  • 小程序复制粘贴的两种方式
  • 证据:曾经在Java领域叱咤风云的Borland正在悄悄地拥抱.NET!
  • vue 3.0 proxy替代Object.defineProperty 监听
  • 组件化思考
  • (三)从jvm层面了解线程的启动和停止
  • [Vue CLI 3] 配置解析之 css.extract
  • 【知识碎片】第三方登录弹窗效果
  • Apache Spark Streaming 使用实例
  • es6--symbol
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • PHP变量
  • SegmentFault 2015 Top Rank
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vuex 笔记整理
  • zookeeper系列(七)实战分布式命名服务
  • 产品三维模型在线预览
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 服务器之间,相同帐号,实现免密钥登录
  • 关于springcloud Gateway中的限流
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 看域名解析域名安全对SEO的影响
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 如何进阶一名有竞争力的程序员?
  • 网页视频流m3u8/ts视频下载
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 一天一个设计模式之JS实现——适配器模式
  • 用 Swift 编写面向协议的视图
  • 正则与JS中的正则
  • Hibernate主键生成策略及选择
  • ​比特币大跌的 2 个原因
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #162 (Div. 2)
  • #ifdef 的技巧用法
  • #QT(一种朴素的计算器实现方法)
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (c语言)strcpy函数用法
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (搬运以学习)flask 上下文的实现
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (六)vue-router+UI组件库
  • (三) diretfbrc详解
  • (十) 初识 Docker file
  • .bat文件调用java类的main方法
  • .NET 5.0正式发布,有什么功能特性(翻译)