第一次参加若川大佬的源码共读活动,希望可以坚持下去!文末附上若川大佬主页和微信!
第一次的源码是一个很简单的工具函数。
如英文名所示,这个工具函数是检测npm包的命名是否符合规范。使用蹩脚的英文水平翻译了一下:
Give me a string and I'll tell you if it's a valid npm package name.
//给我一个字符串并且我将告诉你,它是否是一个有效的npm包名
This package exports a single synchronous function that takes a string as input and returns an object with two properties:
//这个包导出一个单一同步函数,输入一个字符串并且返回一个对象,这个对象有两个属性
源码如下:
'use strict'
var scopedPackagePattern = new RegExp('^(?:@([^/]+?)[/])?([^/]+?)$')
var builtins = require('builtins')
//黑名单
var blacklist = [
'node_modules',
'favicon.ico'
]
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报错 不能为undefined
if (name === undefined) {
errors.push('name cannot be undefined')
return done(warnings, errors)
}
//传入的name不为字符串报错 必须为字符串
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')
}
//第一个字符不能为.
//String.match() 将String使用match(RegExp)进行匹配,并返回结果
if (name.match(/^./)) {
errors.push('name cannot start with a period')
}
//第一个字符不能为_
if (name.match(/^_/)) {
errors.push('name cannot start with an underscore')
}
//首位不能有空格
//String.trim() 删除字符串两端空格,并返回删除后的字符串
if (name.trim() !== name) {
errors.push('name cannot contain leading or trailing spaces')
}
// No funny business
//遍历黑名单,将黑名单上的每个元素与传入的name匹配,相同则报错
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
//同上,遍历引入的builtin,报错改为警告
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
//传入的name需要为小写
if (name.toLowerCase() !== name) {
warnings.push('name can no longer contain capital letters')
}
//name中不能包含[]内的符号
if (/[~'!()*]/.test(name.split('/').slice(-1)[0])) {
warnings.push('name can no longer contain special characters ("~'!()*'")')
}
if (encodeURIComponent(name) !== name) {
//如果转义 应对@vue/core这种情况,
var nameMatch = name.match(scopedPackagePattern)
//若name为 '@vue/core' 经过match转换会变成 ['@vue/core','vue','core']
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
}
收获
第一次参加若川大佬的源码共读的活动,本来应该昨天就开始的,但是处理bug处理了好久,直到今早才处理好,所有耽搁了一天。通过这次源码让我复习与学习了很多数组与字符串的API,也认识到了自己的不足:正则表达式。希望以后每一天可以进步一点点!
String.match() //将String使用match(RegExp)进行匹配,并返回结果
String.trim() //删除字符串两端空格,并返回删除后的字符串
RegExp.test() //检查传入的字符串和正则是否匹配,返回一个布尔
//将一个字符串split返回一个数组,再将数组slice,拿到数组的最后一个元素,是为了拿到 @vue/core中的core去匹配正则
if (/[~'!()*]/.test(name.split('/').slice(-1)[0]))
还了解了 encodeURIComponent() 将传入的字符转义为UTF-8编码,但 A-Z a-z 0-9 - _ . ! ~ * ' ( ) 这些字符不会被转义。
疑问
有点没明白 validate.scopedPackagePattern = scopedPackagePattern 这个语句的作用,感觉没有这个语句也可以执行。但是看了其他人的源码分析后,发现这个好像是故意暴露给引用validata的人看的。
若川大佬主页:juejin.cn/user/141582…
若川大佬微信:juejin.cn/pin/7005372…