简介
validate-npm-package-name,顾名思义,主要是用来校验包名是否符合规范。传入一个字符串,返回一个包含
以下两个属性的一个对象。
validForNewPackages :: BooleanvalidForOldPackages :: Boolean
用法
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}
源码分析
现在进入源码部分,我们可以看到package.json中包含了一些依赖
package.json
{..."dependencies": {"builtins": "^1.0.3"},"devDependencies": {"standard": "^8.6.0","tap": "^10.0.0"},"scripts": {"cov:test": "TAP_FLAGS='--cov' npm run test:code","test:code": "tap ${TAP_FLAGS:-'--'} test/*.js","test:style": "standard","test": "npm run test:code && npm run test:style"},...}
builtins是获取Node的内置模块,例如可以用以下代码获取Node中模块的信息
const m = require('module');console.log(m);
红框内的就是内置模块的数据,内置模块允许修改,但是不支持新增,可参照Node.js的内置模块说明
standard是JavaScript代码规范,自带linter 和代码修正,可以参考StandardJs中文
tap是NodeJs的一个测试框架,支持覆盖测试等,并且拥有美观的测试输出,Node Tap

所以
npm run test
主要是执行了tap和standard的操作
index.js
代码里的正则可视图
/^(?:@([^/]+?)[/])?([^/]+?)$/

其他部分的直接贴注释:
'use strict'// 包匹配的正则var scopedPackagePattern = new RegExp('^(?:@([^/]+?)[/])?([^/]+?)$')// 获取NodeJs的内置模块var builtins = require('builtins')// 黑明单列表,name不允许存在在黑名单中var blacklist = ['node_modules','favicon.ico']var validate = module.exports = function (name) {// 保存警告var warnings = []// 保存错误var errors = []// 不允许为nullif (name === null) {errors.push('name cannot be null')return done(warnings, errors)}// 不允许为undefinedif (name === undefined) {errors.push('name cannot be undefined')return done(warnings, errors)}// 必须是字符串类型if (typeof name !== 'string') {errors.push('name must be a string')return done(warnings, errors)}// 不能是空字符串if (!name.length) {errors.push('name length must be greater than zero')}// 不能以.开头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 businessblacklist.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, etcbuiltins.forEach(function (builtin) {if (name.toLowerCase() === builtin) {warnings.push(builtin + ' is a core module name')}})// 长度不能超过214// really-long-package-names-------------------------------such--length-----many---wow// the thisisareallyreallylongpackagenameitshouldpublishdowenowhavealimittothelengthofpackagenames-poch.if (name.length > 214) {warnings.push('name can no longer contain more than 214 characters')}// 不允许大小写的情况// mIxeD CaSe nAMEsif (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字符if (encodeURIComponent(name) !== name) {// Maybe it's a scoped package name, like @user/packagevar nameMatch = name.match(scopedPackagePattern)if (nameMatch) {var user = nameMatch[1]var pkg = nameMatch[2]if (encodeURIComponent(user) === user && encodeURIComponent(pkg) === pkg) {return done(warnings, errors)}}errors.push('name can only contain URL-friendly characters')}return done(warnings, errors)}validate.scopedPackagePattern = scopedPackagePattern// 处理的函数var done = function (warnings, errors) {var result = {validForNewPackages: errors.length === 0 && warnings.length === 0,validForOldPackages: errors.length === 0,warnings: warnings,errors: errors}if (!result.warnings.length) delete result.warningsif (!result.errors.length) delete result.errorsreturn result}
总结
1.了解了builtins,standard,tap
2.复习了正则
