<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          每天一個npm包:validate-npm-package-name

          共 5887字,需瀏覽 12分鐘

           ·

          2021-06-21 03:39

           當(dāng)你熱愛生活,你才會變得快樂。


          validate-npm-package-name這個包相信大家都不陌生,存在于大多數(shù)CLI腳手架類工具中被使用。比如在create-react-app[1]中。

          function checkAppName(appName) {  const validationResult = validateProjectName(appName); // 根據(jù)validForNewPackages字段判斷是否是合法的包名  if (!validationResult.validForNewPackages) {    console.error(      chalk.red(        `Cannot create a project named ${chalk.green(          `"${appName}"`        )} because of npm naming restrictions:\n`      )    );    // 打印錯誤、警告    [      ...(validationResult.errors || []),      ...(validationResult.warnings || []),    ].forEach(error => {      console.error(chalk.red(`  * ${error}`));    });    console.error(chalk.red('\nPlease choose a different project name.'));    // 退出進(jìn)程    process.exit(1);  }  ...}

          那么接下來跟我一起翻一番源碼吧。

          由于源碼不多,直接就貼注釋了,通過源碼可以學(xué)習(xí)到一個合格的包名應(yīng)該符合哪些規(guī)則,以及里面有一小代碼還是挺有意思的。

          builtins模塊


          'use strict'
          var semver = require('semver')
          module.exports = function (version) { // 獲取node版本 version = version || process.version
          var coreModules = [ 'assert', 'buffer', 'child_process', 'cluster', 'console', 'constants', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'module', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'sys', 'timers', 'tls', 'tty', 'url', 'util', 'vm', 'zlib' ]
          if (semver.lt(version, '6.0.0')) coreModules.push('freelist') if (semver.gte(version, '1.0.0')) coreModules.push('v8') if (semver.gte(version, '1.1.0')) coreModules.push('process') if (semver.gte(version, '8.1.0')) coreModules.push('async_hooks') if (semver.gte(version, '8.4.0')) coreModules.push('http2') if (semver.gte(version, '8.5.0')) coreModules.push('perf_hooks')
          return coreModules}

          validate-npm-package-name


          'use strict'
          var scopedPackagePattern = new RegExp('^(?:@([^/]+?)[/])?([^/]+?)$')// 這個包是包括node內(nèi)置 module的列表var builtins = require('builtins')// 保留名(黑名單)var blacklist = [ 'node_modules', 'favicon.ico']
          var validate = module.exports = function (name) { // 警告:用于表示過去package name允許、如今不允許的兼容error var warnings = [] // 存儲不符號合格的包名的規(guī)則 var errors = []
          // 校驗格式 if (name === null) { errors.push('name cannot be null') return done(warnings, errors) }
          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) }
          // 校驗包名長度必須大于0 if (!name.length) { errors.push('name length must be greater than zero') }
          // 校驗包名不能以.開頭 if (name.match(/^\./)) { errors.push('name cannot start with a period') }
          // 校驗包名不能以_開頭、這里復(fù)習(xí)了下match用法 // '.'.match(/^_/) === null if (name.match(/^_/)) { errors.push('name cannot start with an underscore') }
          // 校驗包名不能包含任何的前導(dǎo)、后導(dǎo)空格 if (name.trim() !== name) { errors.push('name cannot contain leading or trailing spaces') }
          // 校驗包名不能為保留字 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 內(nèi)置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') }
          // 校驗包名不能包含特殊字段 ~'!()* // name.split('/').slice(-1)[0] => 獲取包名、之所以要這樣處理是因為 // name.split('/') 處理 npm package scope場景 // slice(-1)[0] 保證永遠(yuǎn)截取包名正確 // 'koa'.split('/').slice(-1)[0] // 'koa' // '@babel/core'.split('/').slice(-1)[0] // 'core' // /[~'!()*]/.test('@babel/core'.split('/').slice(-1)) // false // /[~'!()*]/.test('@babel/co*re'.split('/').slice(-1)) // true if (/[~'!()*]/.test(name.split('/').slice(-1)[0])) { warnings.push('name can no longer contain special characters ("~\'!()*")') }
          // 包名不能包含non-url-safe字符 // 關(guān)于encodeURIComponent不轉(zhuǎn)義哪些字符 // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent if (encodeURIComponent(name) !== name) { // 這里主要處理 scope package name 比如 @babel/core var nameMatch = name.match(scopedPackagePattern) if (nameMatch) { var user = nameMatch[1] // 比如 bebel var pkg = nameMatch[2] // 比如得到 core // 如果沒有異常 直接返回 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
          // 返回結(jié)果的util方法var done = function (warnings, errors) { var result = { // 我們一般用該屬性來判斷一個包名是否合法 validForNewPackages: errors.length === 0 && warnings.length === 0, // 這個屬性是用于兼容最開始node package name帶來的遺留問題,那個時候有些包名不規(guī)范 validForOldPackages: errors.length === 0, warnings: warnings, errors: errors } if (!result.warnings.length) delete result.warnings if (!result.errors.length) delete result.errors return result}

          好了,今天就到這結(jié)束了,下期見。

          References

          [1] create-react-app: https://link.zhihu.com/?target=https%3A//github.com/facebook/create-react-app/blob/2d1829eaf6ff1308da00720fa9984620dd0fb296/packages/create-react-app/createReactApp.js%23L850


          結(jié)尾

          1. 如果覺得這篇文章還不錯,來個分享、點贊、在看三連吧,讓更多小伙伴看到~




          瀏覽 83
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲在线黄片 | 国产操逼视频免费看 | 最新亚洲黄色视频 | 精品国产一区二 | 日韩在线黄色大片 |