ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【源码】validate-npm-package-name 检测 npm 包是否符合标准

2021-11-19 17:03:09  阅读:182  来源: 互联网

标签:npm errors name warnings var 源码 push validate


1.学习目标

  • 了解validate-npm-package-name
  • 它的作用和场景

2.资料准备

git clone https://github.com/npm/validate-npm-package-name.git

3 初识–README.md

3.1 什么是validate-npm-package-name?

  • 检测 npm 包的名称是否符合标准
  • 此包导出一个同步函数,该函数以字符串作为输入,并返回一个具有两个属性的对象:
validForNewPackages :: Boolean
validForOldPackages :: Boolean

3.2. Naming Rules(命名规则)

  1. 包名称长度应大于零
  2. 包名称中的所有字符必须为小写,即不允许使用大写或混合大写的名称
  3. 包名称可以由连字符组成
  4. 包名称不得包含任何非url安全字符(因为名称最终是url的一部分)
  5. 包名称不应以开头。或_
  6. 包名称不应包含任何前导或尾随空格
  7. 包名称不应包含以下任何字符:~)(’*
  8. 包名称不能与node.js/io.js核心模块或保留/黑名单名称相同。例如,以下名称无效:
    http、流动、节点单元、图标文件
  9. 包名称长度不能超过214

3.3 例子

3.3.1 Valid Names(有效名称)

var validate = require("validate-npm-package-name")

validate("some-package")
validate("example.com")
validate("under_score")
validate("123numeric")
validate("@npm/thingy")
validate("@jane/foo.js")

// 有效 则返回如下对象
{
 validForNewPackages: true,
 validForOldPackages: true
}

3.3.2 无效名称

validate("excited!")
validate(" leading-space:and:weirdchars")

// 无效 则返回如下对象
{
  validForNewPackages: false,
  validForOldPackages: false,
  errors: [
    'name cannot contain leading or trailing spaces',
    'name can only contain URL-friendly characters'
  ]
}

4. 深入–源码阅读

'use strict'
// 惰性匹配-正则表达式    链接地址:jex.im/regulex/
var scopedPackagePattern = new RegExp('^(?:@([^/]+?)[/])?([^/]+?)$')
// node 所有的node内置模块
var builtins = require('builtins')
// 黑名单
var blacklist = [
  'node_modules',
  'favicon.ico'
]

/**
 * validate:验证函数
 * name:包名
 */
var validate = module.exports = function (name) {

  var warnings = []
  var errors = []
  // 是否为null
  if (name === null) {
    errors.push('name cannot be null')
    return done(warnings, errors)
  }
  // 是否为undefined
  if (name === undefined) {
    errors.push('name cannot be undefined')
    return done(warnings, errors)
  }
  // 是否为string
  if (typeof name !== 'string') {
    errors.push('name must be a string')
    return done(warnings, errors)
  }
  // 验证包名的长度不能为0
  if (!name.length) {
    errors.push('name length must be greater than zero')
  }
  // 验证包名是否以.开始
  // .match(/^\./) 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \.
  if (name.match(/^\./)) {
    errors.push('name cannot start with a period')
  }
  //验证包名是否以 _开头
  if (name.match(/^_/)) {
    errors.push('name cannot start with an underscore')
  }
  //验证包名前后是否有空格
  if (name.trim() !== name) {
    errors.push('name cannot contain leading or trailing spaces')
  }

  // No funny business 不能是黑名单里的名字,虽然作者说了很无聊,但是还的判断哈哈哈
  blacklist.forEach(function (blacklistedName) {
    if (name.toLowerCase() === blacklistedName) {
      errors.push(blacklistedName + ' is a blacklisted name')
    }
  })

  // Generate warnings for stuff that used to be allowed 为以前允许的内容生成警告

  // core module names like http, events, util, etc 核心模块名称,如http、events、util等
  //包名不能是node.js/io.js 核心模块 或者保留的名称
  builtins.forEach(function (builtin) {
    if (name.toLowerCase() === builtin) {
      warnings.push(builtin + ' is a core module name')
    }
  })

  // really-long-package-names-------------------------------such--length-----many---wow
  // the thisisareallyreallylongpackagenameitshouldpublishdowenowhavealimittothelengthofpackagenames-poch.
  // 包名称长度不能超过214
  if (name.length > 214) {
    warnings.push('name can no longer contain more than 214 characters')
  }

  // mIxeD CaSe nAMEs 必须小写
  if (name.toLowerCase() !== name) {
    warnings.push('name can no longer contain capital letters')
  }
  // 校验包名不能包含特殊字段 ~'!()*
  if (/[~'!()*]/.test(name.split('/').slice(-1)[0])) {
    warnings.push('name can no longer contain special characters ("~\'!()*")')
  }
  // 包名不得包含任何非 url 安全字符
  // 关于encodeURIComponent不转义哪些字符
  // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
  if (encodeURIComponent(name) !== name) {
    // Maybe it's a scoped package name, like @user/package
    var nameMatch = name.match(scopedPackagePattern)
    if (nameMatch) {
      var user = nameMatch[1]
      var pkg = nameMatch[2]
      //对user和pkg分别进行校验
      if (encodeURIComponent(user) === user && encodeURIComponent(pkg) === pkg) {
        return done(warnings, errors)
      }
    }

    errors.push('name can only contain URL-friendly characters')
  }

  return done(warnings, errors)
}
// scopedPackagePattern 暴露给外面使用,方便私域定制npm发布设置校验规则
validate.scopedPackagePattern = scopedPackagePattern

/**
 * 结果返回函数
 * @param {*} warnings 警告的数组
 * @param {*} errors 错误的数组
 * @returns
 */
var done = function (warnings, errors) {
  var result = {
    //一般用这个属性来判断一个包名是否合法
    validForNewPackages: errors.length === 0 && warnings.length === 0,
    //用于兼容最开始node package name 带来的遗留问题,比如报名不规范等
    validForOldPackages: errors.length === 0,
    warnings: warnings,
    errors: errors
  }
  if (!result.warnings.length) delete result.warnings
  if (!result.errors.length) delete result.errors
  return result
}

5.总结

这一期简简单单,整整齐齐,可可爱爱

标签:npm,errors,name,warnings,var,源码,push,validate
来源: https://blog.csdn.net/rbgg_mp/article/details/121423532

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有