npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

getprochinese

v1.1.1

Published

获取项目中文

Downloads

37

Readme

脚本使用说明

当前脚本适用于检测对应项目目录下的中文匹配,如果需要匹配其他内容可以直接修改正则表达式规则

小白使用流程

命令行 npm使用流程

npm install -g getprochinese
//path项目目录 filterDist是否过滤dist
getCH check [path] [filterDist] | getCH c [path] [filterDist]
//ps: getCH check /user/mac/vuepro 简便实用方式(path可直接拖入)
//走命令行筛选目录
getCH check | getCH c

命令行 项目使用流程

node项目执行请打开主目录下的index.js中的autorun // autoRun() node项目执行请打开 node项目执行请打开 node项目执行请打开

git clone https://gitee.com/guomeng/get-pro-chinese.git
cd get-pro-chinese
npm i
npm run start

如图所示,运行之后会按流程这些问题,项目地址可以直接拖入文件夹

| 问题 | 对应字段 | 是否必填 | 默认值 | 备注 | | -------- | ----------- | ----- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | 项目地址 | projectPath | true | 无 | 必须填写目录,可直接通过拖拽文件夹到命令行将目录引入 | | 是否过滤dist | filterDist | false | true | 过滤dist编译目录下的文件可直接enter略过 | | 自定义过滤目录 | filterRule | false | 无 | 自定义过滤哪些规则文件[ 'node_module', '.git', 'wp.cfg', '.vscode', 'images', '.jpg', '.png', 'docs', '.jpeg'] 目前过滤文件规则可直接enter略过 | | xlsx路径 | xlsxPath | false | 无 | 不填写就默认项目目录 docs下可直接enter略过 | | xlsx名称 | xlsxName | false | "项目中英文参照文档" | xlsx输出文档名称项目中英文参照文档可直接enter略过 | | 确定开始 | confirm | 是 | true | enter之后执行脚本可直接enter略过 |

运行过程讲解

  • 第1部分命令行交互

  • 第2部分执行项目文件检索

  • 最后一步输出检索文件信息以及xlsx输出位置和耗时

代码讲解见代码注释index.js

主要代码讲解

inquirer交互过程

//question交互
inquirer
  .prompt(questions)
  .then((res) => {
    if (!res) console.log(chalk.red('参数错误,请重试!'))
    if (!res.confirm) console.log(chalk.gray('取消了检索操作!'))
    if (!res.projectPath) console.log(chalk.gray('文件目录为空!'))
    //设置过滤规则
    if (res.filterDist) {
      dirRegArr.push('dist')
    }
    if (res.filterRule) {
      dirRegArr.push(...res.filterRule?.split(','))
    }
    //赋值xlsx输出目录
    if (res.xlsxPath) {
      xlsxPath = res.xlsxPath
    } else {
      xlsxPath = res.projectPath
    }
    //赋值xlsx名称
    if (res.xlsxName) {
      xlsxName = res.xlsxName
    }
    console.log(chalk.green('开始文件检索---------------------------------'))
    console.log(chalk.green('过滤文件列表------>' + JSON.stringify(dirRegArr)))
    date = new Date().getTime()
    readFilePathSync(res.projectPath)
    console.log(
      chalk.green(
        '========================文件检索完成========================'
      )
    )
    if (!typeObject) return
    //统计检索文件类型 数量
    const keys = Object.keys(typeObject)
    if (keys && keys.length) {
      let total = 0,
        msg = ''
      keys.map((key, index) => {
        total = total + (typeObject[key]?.count || 0)
        msg = msg + `${key}文件:${typeObject[key]?.count || 0}\n`
      })
      msg = '总共检索文件:' + total + '\n' + msg
      console.log(chalk.blueBright(msg))
    }
    console.log(
      chalk.blueBright(
        '\nxlsx文件输出目录:' + xlsxPath + '/docs/' + xlsxName + '.xlsx'
      )
    )
    //统计花费时间
    console.log(chalk.yellow(`\n总用时:${new Date().getTime() - date}ms\n`))
  })
  .catch((e) => {
    //错误处理
    console.log(chalk.red('==============文件检索失败=============='))
    console.log(chalk.red('error:' + e))
  })

脚本开始的方法

/**
 * 脚本开始的方法
 * @param {*} filePath 项目目录path
 */
function readFilePathSync(filePath) {
  readDirSync(filePath)
  // chArr.push(['总计', JSON.stringify(typeObject), null])
  const sheetOptions = { '!cols': [{ wch: 50 }, { wch: 50 }, { wch: 50 }] }
  const buffer = xlsx.build([{ name: xlsxName, data: chArr }], {
    sheetOptions
  })
  if (!fs.existsSync(xlsxPath + '/docs')) {
    //docs不存在就创建一个
    fs.mkdirSync(xlsxPath + '/docs')
  }
  // 写入xlsx文件
  fs.writeFileSync(xlsxPath + '/docs/' + xlsxName + '.xlsx', buffer, 'binary')
}

遍历目录方法

/**
 * 读取dir目录下文件目录
 * @param {*} dir 读取的目录
 */
function readDirSync(dir) {
  const dirRegStr =
    dirRegArr &&
    dirRegArr.length &&
    dirRegArr.reduce((preValue, value) => {
      return preValue ? preValue + '|' + value : value
    })
  const dirReg = new RegExp(dirRegStr)
  if (dir.match(dirReg)) {
    //过滤掉node_modules文件
    console.log(chalk.yellow('过滤文件------>' + dir))
    return
  }
  if (!dir) return
  const filesArr = fs.readdirSync(dir)
  filesArr &&
    filesArr.length &&
    filesArr.map((file) => {
      //得到拼接目录
      const filePath = path.join(dir, file)
      const stats = fs.statSync(filePath)
      if (stats.isDirectory()) {
        //如果是文件夹 递归调用readDir
        readDirSync(filePath)
      } else if (stats.isFile()) {
        readFileSync(filePath)
      } else {
      }
    })
}

读取文件方法

/**
 * 同步读取文件
 * @param {*} filePath
 */
function readFileSync(filePath) {
  if (!filePath) return
  const extension = getExtension(filePath)
  if (typeObject[extension]) {
    //文件计数
    typeObject[extension].count = typeObject[extension].count + 1
  } else {
    typeObject[extension] = { count: 1 }
  }
  let fileData = fs.readFileSync(filePath, 'utf-8')
  if (!fileData) return
  let filterArr = []
  if (extension.match(/html/)) {
    //过滤html注释
    fileData = fileData.replace(chHtmlReg, '')
  }
  if (extension.match(/js|jsx/)) {
    //过滤js|jsx注释
    fileData = fileData.replace(chJSRegMulti, '')
    fileData = fileData.replace(chJSRegSingle, '')
  }
  const fileChArr = fileData.match(chReg)
  if (fileChArr && fileChArr.length > 0) {
    if (chArr.length !== 1) {
      //如果不是第一个页面添加空行
      chArr.push([null, null, null])
    }
    chArr.push([filePath, null, null])
    fileChArr.forEach((item) => {
      if (filterArr.indexOf(item) < 0) {
        //去重添加
        filterArr.push(item)
        chArr.push([filePath, item, null])
      }
    })
  }
  console.log(chalk.green(filePath + '文件检索完成'))
}

主要正则表达式

//匹配中文字符
const chReg = /[\u4E00-\u9FA5]+/g
//匹配html注释
const chHtmlReg = /<!--.*-->/
/**
 * 多行注释匹配
 */
const chJSRegMulti = /(?:^|\n|\r)\s*\/\*[\s\S]*?\*\/\s*(?:\r|\n|$)/g
//单行注释匹配
const chJSRegSingle = /(?:^|\n|\r)\s*\/\/.*(?:\r|\n|$)/g