validate-npm-package-name源码解读

115 阅读1分钟
  1. 作用

validate-npm-package-name 的作用就是为了检测 npm 包的名称是否符合标准的;

  1. 使用
var validate = require("validate-npm-package-name")
console.log(validate("some-package"));
console.log(validate("_some-package"));
  1. 源码
'use strict'

var scopedPackagePattern = new RegExp('^(?:@([^/]+?)[/])?([^/]+?)$')
    // 主要是包括node内置module
var builtins = require('builtins')

//保留
var blacklist = [    'node_modules',    'favicon.ico']

var validate = module.exports = function(name) {
    //警告
    var warnings = []
        //存储不合格包名规则
    var errors = []
        //校验格式
    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)
    }
    //处理字符串情况
    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 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
    // 校验包名是否是node内置module名
    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.
    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 ("~'!()*")')
    }

    if (encodeURIComponent(name) !== name) {
        // Maybe it's a scoped package name, like @user/package
        // var scopedPackagePattern = new RegExp('^(?:@([^/]+?)[/])?([^/]+?)$')
        var 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.warnings
    if (!result.errors.length) delete result.errors
    return result
}
  1. 总结

可以通过检验来学习一下npm包的命名规则;

总体来说难度不是很大,花个几分钟就搞定了;