ESCheck工具原理解析及增强实现(3)

简介: 完整demo3代码如有一些边界情况也是在 catch err部分根据 message做一下过滤即可比如下代码

ESCheck工具原理解析及增强实现(2):https://developer.aliyun.com/article/1394836?spm=a2c6h.13148508.setting.15.50c84f0e0ugg2G

完整demo3代码

如有一些边界情况也是在 catch err部分根据 message做一下过滤即可

比如下代码

var { boolean:hello } = {}

image.png

完整demo4代码

做一下过滤,catch message添加过滤逻辑

const filterMessage = [/^The keyword /]
if (filterMessage.find((r) => r.test(error.message))) {
  return
}

调整后的报错信息就是解构赋值的语法错误了

image.png

完整demo5代码

至此基本能完成了单文件的多次es-check检测,虽然不像mpx-es-check那样用直白的语言直接说面是什么语法。但还有改进空间嘛,后面再单独写个文章做个工具检测目标代码用了哪些ES6+特性。就不再这里赘述了

sourcemap解析

这个主要针对检测资源是build产物的一项优化,通过source-map解析报错信息对应的源码

前面的代码我们只获取了问题源码的起止字符位置start,end

通过source-map解析,首先要获取报错代码在资源中的行列信息

这里通过acorn.getLineInfo方法可直接获取行列信息

// 省略了重复代码
const codeErrorList: any[] = []
acornWalk.full(ast, (node, _state, _type) => {
  // 节点对应的源码
  const codeSnippet = code.slice(node.start, node.end)
  try {
    acorn.parse(codeSnippet, {
      ecmaVersion: '5'
    } as any)
  } catch (error) {
    const locStart = acorn.getLineInfo(code, node.start)
    const locEnd = acorn.getLineInfo(code, node.end)
    codeErrorList.push({
      loc: {
        start: locStart,
        end: locEnd
      }
    })
  }
})
console.dir(codeErrorList, {
  depth: 3
})

结果如下,完整demo1代码

image.png

有了行列号,我们就可以根据*.map文件进行源码的解析

默认map文件由原文件名加.map后缀

function getSourcemapFileContent(file: string) {
  const sourceMapFile = `${file}.map`
  if (fs.existsSync(sourceMapFile)) {
    return fs.readFileSync(sourceMapFile, 'utf-8')
  }
  return ''
}

解析map文件直接使用 sourceMap.SourceMapConsumer,返回的实例是1个Promise,使用时需注意

function parseSourceMap(code: string) {
  const consumer = new sourceMap.SourceMapConsumer(code)
  return consumer
}

根据前面source-map解析的例子,把这块逻辑放到checkCode之后即可

const code = fs.readFileSync(file, 'utf-8')
// ps: checkCode 即为上一小节实现代码检测能力的封装
const codeErrorList = checkCode(code)
const sourceMapContent = getSourcemapFileContent(file)
if (sourceMapContent) {
  const consumer = await parseSourceMap(sourceMapContent)
  codeErrorList.forEach((v) => {
    // 解析获取原文件信息
    const smStart = consumer.originalPositionFor({
      line: v.loc.start.line,
      column: v.loc.start.column
    })
    const smEnd = consumer.originalPositionFor({
      line: v.loc.end.line,
      column: v.loc.end.column
    })
    // start对应源码所在行的代码
    const sourceStartCode = consumer
      .sourceContentFor(smStart.source!)
      ?.split(/\r?\n/g)[smStart.line! - 1]
    const sourceEndCode = consumer
      .sourceContentFor(smEnd.source!)
      ?.split(/\r?\n/g)[smEnd.line! - 1]
    // 省略 console 打印代码
  })
}

完整demo2代码

image.png

这块就对齐了mpx-es-checksource-map解析能力

HTML支持

这个就比较好办了,只需要将script里的内容提取出来,调用上述的checkCode方法,然后对结果进行一个行列号的优化即可

这里提取的方法很多,可以

  1. 正则匹配
  2. cheerio:像jQuery一样操作
  3. parse5:生成AST,递归遍历需要的节点
  4. htmlparser2:生成AST,相比parse5更加,解析策略更加”包容“

小试对比了一下,最后发现是用parse5更符合这个场景(编写代码更少)

import * as parse5 from 'parse5'
const htmlAST = parse5.parse(code, {
  sourceCodeLocationInfo: true
})

下面是生成的AST示例: astexplorer.net/#/gist/0372…

通过nodeName或者tagName就可以区分节点类型,这里简单写个遍历方法

节点可以通过childNodes属性区分是否包含子节点

function traverse(ast: any, traverseSchema: Record<string, any>) {
  traverseSchema?.[ast?.nodeName]?.(ast)
  if (ast?.nodeName !== ast?.tagName) {
    traverseSchema?.[ast?.tagName]?.(ast)
  }
  ast?.childNodes?.forEach((n) => {
    traverse(n, traverseSchema)
  })
}

这里遍历一下demo代码生成的ast

traverse(htmlAST, {
  script(node: any) {
    const code = `${node.childNodes.map((n) => n.value)}`
    const loc = node.sourceCodeLocation
    if (code) {
      console.log(code)
      console.log(loc)
    }
  }
})

完整demo1代码

image.png

获得对应的源码后就可以调用之前的checkCode方法,对错误行号做一个拼接即可得到错误信息

traverse(htmlAST, {
  script(node: any) {
    const code = `${node.childNodes.map((n) => n.value)}`
    const loc = node.sourceCodeLocation
    if (code) {
      const errList = checkCode(code)
      errList.forEach((err) => {
        console.log(
          'line:',
          loc.startLine + err.loc.start.line - 1,
          'column:',
          err.loc.start.column
        )
        console.log(err.source)
        console.log()
      })
    }
  }
})

完整demo2代码

image.png

组建CLI能力

这里就不再赘述CLI过程代码,核心的已在前面阐述,这里直接上最终成品的使用演示,参数同es-check保持一致

npm i @sugarat/es-check -g

检测目标文件

escheck es5 testProject/**/*.js testProject/**/*.html

image.png

日志输出到文件

escheck es5 testProject/**/*.js testProject/**/*.html --out

image.png

最终对比

image.png

取了2者的优点相结合然后做了一定的增强

最后

当然这个工具可能存在bug,遗漏部分场景等情况,读者试用可以评论区给反馈,或者库里直接提issues

有其它功能上的建议也可评论区留言交流

完整源码移步=>Github

参考

  • es-check:社区出品
  • mpx-es-check:滴滴出品 MPX 框架的配套工具


相关文章
|
8月前
|
机器学习/深度学习 人工智能 JSON
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
Resume Matcher 是一款开源AI简历优化工具,通过解析简历和职位描述,提取关键词并计算文本相似性,帮助求职者优化简历内容,提升通过自动化筛选系统(ATS)的概率,增加面试机会。
902 18
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
|
7月前
|
存储 人工智能 API
离线VS强制登录?Apipost与Apifox的API工具理念差异深度解析
在代码开发中,工具是助手还是枷锁?本文通过对比Apipost和Apifox在断网环境下的表现,探讨API工具的选择对开发自由度的影响。Apifox强制登录限制了离线使用,而Apipost支持游客模式与本地存储,尊重开发者数据主权。文章从登录策略、离线能力、协作模式等方面深入分析,揭示工具背后的设计理念与行业趋势,帮助开发者明智选择,掌握数据控制权并提升工作效率。
|
8月前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
578 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
8月前
|
数据可视化 测试技术 API
前后端分离开发:如何高效调试API?有工具 vs 无工具全解析
在前后端分离开发中,API调试至关重要。本文探讨有无调试工具时如何高效调试API,重点分析Postman、Swagger等工具优势及无工具代码调试方法。通过实际场景如用户登录接口,对比两者特性。同时介绍Apipost-Hepler(IDEA插件),将可视化与代码调试结合,提供全局请求头配置、历史记录保存等功能,优化团队协作与开发效率,助力API调试进入全新阶段。
|
8月前
|
传感器 人工智能 监控
反向寻车系统怎么做?基本原理与系统组成解析
本文通过反向寻车系统的核心组成部分与技术分析,阐述反向寻车系统的工作原理,适用于适用于商场停车场、医院停车场及火车站停车场等。如需获取智慧停车场反向寻车技术方案前往文章最下方获取,如有项目合作及技术交流欢迎私信作者。
569 2
|
8月前
|
JSON 监控 物联网
WebSocket 调试全攻略:核心解析、工具选择与对比!
WebSocket 是一种全双工、实时交互的网络通信协议,适用于即时通信、实时数据流、多人协作、IoT 等场景。调试 WebSocket 时,工具应具备握手管理、实时消息收发、自定义 Header、消息大小告警、分组管理、多连接支持和断线重现等功能。主流调试工具如 Postman、ApiPost 和 ApiFox 各有优劣:Postman 界面友好适合基础调试;ApiPost 支持高级功能如消息分组和自动重连;ApiFox 则强化了多连接支持。选择工具时需根据具体需求和团队熟悉度决定。
|
8月前
|
数据可视化 测试技术 API
前后端分离开发:如何高效调试API?有工具 vs 无工具全解析
在前后端分离的开发模式中,API 调试的效率直接影响项目的质量和交付速度。通过本文的对比分析,我们可以看到无工具调试模式虽具备灵活性和代码复用能力,但在操作便利性和团队协作上稍显不足。而传统的外部调试工具带来了可视化、高效协作与扩展性,却可能存在工具切换带来的开发链路断层问题。Apipost-Hepler 融合了两者的优势,让开发者无需离开熟悉的 IDEA 环境,就能享受可视化调试工具的强大功能。
236 5
|
8月前
|
JSON 监控 物联网
#WebSocket 调试全攻略:Postman、Apipost和Apifox核心解析、工具选择与对比!
WebSocket 是一种现代化的全双工通信协议,允许客户端和服务端通过持久连接实时双向传输数据。它适用于即时通讯、实时通知、金融行情、在线协作、物联网等场景。调试 WebSocket 时,工具应具备握手管理、实时消息收发、自定义 Header、消息大小监控、分组管理、多连接支持等功能。
694 1
|
8月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
8月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
774 29

推荐镜像

更多
  • DNS