This commit is contained in:
2025-08-18 23:06:34 +08:00
parent 0bc04fb659
commit ed18af0cad
1926 changed files with 275098 additions and 0 deletions

15
package/node_modules/normalize-package-data/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,15 @@
This package contains code originally written by Isaac Z. Schlueter.
Used with permission.
Copyright (c) Meryn Stol ("Author")
All rights reserved.
The BSD License
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,24 @@
module.exports = extractDescription
// Extracts description from contents of a readme file in markdown format
function extractDescription (d) {
if (!d) {
return
}
if (d === 'ERROR: No README data found!') {
return
}
// the first block of text before the first heading
// that isn't the first line heading
d = d.trim().split('\n')
let s = 0
while (d[s] && d[s].trim().match(/^(#|$)/)) {
s++
}
const l = d.length
let e = s + 1
while (e < l && d[e].trim()) {
e++
}
return d.slice(s, e).join(' ').trim()
}

View File

@@ -0,0 +1,475 @@
var isValidSemver = require('semver/functions/valid')
var cleanSemver = require('semver/functions/clean')
var validateLicense = require('validate-npm-package-license')
var hostedGitInfo = require('hosted-git-info')
var moduleBuiltin = require('node:module')
var depTypes = ['dependencies', 'devDependencies', 'optionalDependencies']
var extractDescription = require('./extract_description')
var url = require('url')
var typos = require('./typos.json')
var isEmail = str => str.includes('@') && (str.indexOf('@') < str.lastIndexOf('.'))
module.exports = {
// default warning function
warn: function () {},
fixRepositoryField: function (data) {
if (data.repositories) {
this.warn('repositories')
data.repository = data.repositories[0]
}
if (!data.repository) {
return this.warn('missingRepository')
}
if (typeof data.repository === 'string') {
data.repository = {
type: 'git',
url: data.repository,
}
}
var r = data.repository.url || ''
if (r) {
var hosted = hostedGitInfo.fromUrl(r)
if (hosted) {
r = data.repository.url
= hosted.getDefaultRepresentation() === 'shortcut' ? hosted.https() : hosted.toString()
}
}
if (r.match(/github.com\/[^/]+\/[^/]+\.git\.git$/)) {
this.warn('brokenGitUrl', r)
}
},
fixTypos: function (data) {
Object.keys(typos.topLevel).forEach(function (d) {
if (Object.prototype.hasOwnProperty.call(data, d)) {
this.warn('typo', d, typos.topLevel[d])
}
}, this)
},
fixScriptsField: function (data) {
if (!data.scripts) {
return
}
if (typeof data.scripts !== 'object') {
this.warn('nonObjectScripts')
delete data.scripts
return
}
Object.keys(data.scripts).forEach(function (k) {
if (typeof data.scripts[k] !== 'string') {
this.warn('nonStringScript')
delete data.scripts[k]
} else if (typos.script[k] && !data.scripts[typos.script[k]]) {
this.warn('typo', k, typos.script[k], 'scripts')
}
}, this)
},
fixFilesField: function (data) {
var files = data.files
if (files && !Array.isArray(files)) {
this.warn('nonArrayFiles')
delete data.files
} else if (data.files) {
data.files = data.files.filter(function (file) {
if (!file || typeof file !== 'string') {
this.warn('invalidFilename', file)
return false
} else {
return true
}
}, this)
}
},
fixBinField: function (data) {
if (!data.bin) {
return
}
if (typeof data.bin === 'string') {
var b = {}
var match
if (match = data.name.match(/^@[^/]+[/](.*)$/)) {
b[match[1]] = data.bin
} else {
b[data.name] = data.bin
}
data.bin = b
}
},
fixManField: function (data) {
if (!data.man) {
return
}
if (typeof data.man === 'string') {
data.man = [data.man]
}
},
fixBundleDependenciesField: function (data) {
var bdd = 'bundledDependencies'
var bd = 'bundleDependencies'
if (data[bdd] && !data[bd]) {
data[bd] = data[bdd]
delete data[bdd]
}
if (data[bd] && !Array.isArray(data[bd])) {
this.warn('nonArrayBundleDependencies')
delete data[bd]
} else if (data[bd]) {
data[bd] = data[bd].filter(function (filtered) {
if (!filtered || typeof filtered !== 'string') {
this.warn('nonStringBundleDependency', filtered)
return false
} else {
if (!data.dependencies) {
data.dependencies = {}
}
if (!Object.prototype.hasOwnProperty.call(data.dependencies, filtered)) {
this.warn('nonDependencyBundleDependency', filtered)
data.dependencies[filtered] = '*'
}
return true
}
}, this)
}
},
fixDependencies: function (data) {
objectifyDeps(data, this.warn)
addOptionalDepsToDeps(data, this.warn)
this.fixBundleDependenciesField(data)
;['dependencies', 'devDependencies'].forEach(function (deps) {
if (!(deps in data)) {
return
}
if (!data[deps] || typeof data[deps] !== 'object') {
this.warn('nonObjectDependencies', deps)
delete data[deps]
return
}
Object.keys(data[deps]).forEach(function (d) {
var r = data[deps][d]
if (typeof r !== 'string') {
this.warn('nonStringDependency', d, JSON.stringify(r))
delete data[deps][d]
}
var hosted = hostedGitInfo.fromUrl(data[deps][d])
if (hosted) {
data[deps][d] = hosted.toString()
}
}, this)
}, this)
},
fixModulesField: function (data) {
if (data.modules) {
this.warn('deprecatedModules')
delete data.modules
}
},
fixKeywordsField: function (data) {
if (typeof data.keywords === 'string') {
data.keywords = data.keywords.split(/,\s+/)
}
if (data.keywords && !Array.isArray(data.keywords)) {
delete data.keywords
this.warn('nonArrayKeywords')
} else if (data.keywords) {
data.keywords = data.keywords.filter(function (kw) {
if (typeof kw !== 'string' || !kw) {
this.warn('nonStringKeyword')
return false
} else {
return true
}
}, this)
}
},
fixVersionField: function (data, strict) {
// allow "loose" semver 1.0 versions in non-strict mode
// enforce strict semver 2.0 compliance in strict mode
var loose = !strict
if (!data.version) {
data.version = ''
return true
}
if (!isValidSemver(data.version, loose)) {
throw new Error('Invalid version: "' + data.version + '"')
}
data.version = cleanSemver(data.version, loose)
return true
},
fixPeople: function (data) {
modifyPeople(data, unParsePerson)
modifyPeople(data, parsePerson)
},
fixNameField: function (data, options) {
if (typeof options === 'boolean') {
options = { strict: options }
} else if (typeof options === 'undefined') {
options = {}
}
var strict = options.strict
if (!data.name && !strict) {
data.name = ''
return
}
if (typeof data.name !== 'string') {
throw new Error('name field must be a string.')
}
if (!strict) {
data.name = data.name.trim()
}
ensureValidName(data.name, strict, options.allowLegacyCase)
if (moduleBuiltin.builtinModules.includes(data.name)) {
this.warn('conflictingName', data.name)
}
},
fixDescriptionField: function (data) {
if (data.description && typeof data.description !== 'string') {
this.warn('nonStringDescription')
delete data.description
}
if (data.readme && !data.description) {
data.description = extractDescription(data.readme)
}
if (data.description === undefined) {
delete data.description
}
if (!data.description) {
this.warn('missingDescription')
}
},
fixReadmeField: function (data) {
if (!data.readme) {
this.warn('missingReadme')
data.readme = 'ERROR: No README data found!'
}
},
fixBugsField: function (data) {
if (!data.bugs && data.repository && data.repository.url) {
var hosted = hostedGitInfo.fromUrl(data.repository.url)
if (hosted && hosted.bugs()) {
data.bugs = { url: hosted.bugs() }
}
} else if (data.bugs) {
if (typeof data.bugs === 'string') {
if (isEmail(data.bugs)) {
data.bugs = { email: data.bugs }
/* eslint-disable-next-line node/no-deprecated-api */
} else if (url.parse(data.bugs).protocol) {
data.bugs = { url: data.bugs }
} else {
this.warn('nonEmailUrlBugsString')
}
} else {
bugsTypos(data.bugs, this.warn)
var oldBugs = data.bugs
data.bugs = {}
if (oldBugs.url) {
/* eslint-disable-next-line node/no-deprecated-api */
if (typeof (oldBugs.url) === 'string' && url.parse(oldBugs.url).protocol) {
data.bugs.url = oldBugs.url
} else {
this.warn('nonUrlBugsUrlField')
}
}
if (oldBugs.email) {
if (typeof (oldBugs.email) === 'string' && isEmail(oldBugs.email)) {
data.bugs.email = oldBugs.email
} else {
this.warn('nonEmailBugsEmailField')
}
}
}
if (!data.bugs.email && !data.bugs.url) {
delete data.bugs
this.warn('emptyNormalizedBugs')
}
}
},
fixHomepageField: function (data) {
if (!data.homepage && data.repository && data.repository.url) {
var hosted = hostedGitInfo.fromUrl(data.repository.url)
if (hosted && hosted.docs()) {
data.homepage = hosted.docs()
}
}
if (!data.homepage) {
return
}
if (typeof data.homepage !== 'string') {
this.warn('nonUrlHomepage')
return delete data.homepage
}
/* eslint-disable-next-line node/no-deprecated-api */
if (!url.parse(data.homepage).protocol) {
data.homepage = 'http://' + data.homepage
}
},
fixLicenseField: function (data) {
const license = data.license || data.licence
if (!license) {
return this.warn('missingLicense')
}
if (
typeof (license) !== 'string' ||
license.length < 1 ||
license.trim() === ''
) {
return this.warn('invalidLicense')
}
if (!validateLicense(license).validForNewPackages) {
return this.warn('invalidLicense')
}
},
}
function isValidScopedPackageName (spec) {
if (spec.charAt(0) !== '@') {
return false
}
var rest = spec.slice(1).split('/')
if (rest.length !== 2) {
return false
}
return rest[0] && rest[1] &&
rest[0] === encodeURIComponent(rest[0]) &&
rest[1] === encodeURIComponent(rest[1])
}
function isCorrectlyEncodedName (spec) {
return !spec.match(/[/@\s+%:]/) &&
spec === encodeURIComponent(spec)
}
function ensureValidName (name, strict, allowLegacyCase) {
if (name.charAt(0) === '.' ||
!(isValidScopedPackageName(name) || isCorrectlyEncodedName(name)) ||
(strict && (!allowLegacyCase) && name !== name.toLowerCase()) ||
name.toLowerCase() === 'node_modules' ||
name.toLowerCase() === 'favicon.ico') {
throw new Error('Invalid name: ' + JSON.stringify(name))
}
}
function modifyPeople (data, fn) {
if (data.author) {
data.author = fn(data.author)
}['maintainers', 'contributors'].forEach(function (set) {
if (!Array.isArray(data[set])) {
return
}
data[set] = data[set].map(fn)
})
return data
}
function unParsePerson (person) {
if (typeof person === 'string') {
return person
}
var name = person.name || ''
var u = person.url || person.web
var wrappedUrl = u ? (' (' + u + ')') : ''
var e = person.email || person.mail
var wrappedEmail = e ? (' <' + e + '>') : ''
return name + wrappedEmail + wrappedUrl
}
function parsePerson (person) {
if (typeof person !== 'string') {
return person
}
var matchedName = person.match(/^([^(<]+)/)
var matchedUrl = person.match(/\(([^()]+)\)/)
var matchedEmail = person.match(/<([^<>]+)>/)
var obj = {}
if (matchedName && matchedName[0].trim()) {
obj.name = matchedName[0].trim()
}
if (matchedEmail) {
obj.email = matchedEmail[1]
}
if (matchedUrl) {
obj.url = matchedUrl[1]
}
return obj
}
function addOptionalDepsToDeps (data) {
var o = data.optionalDependencies
if (!o) {
return
}
var d = data.dependencies || {}
Object.keys(o).forEach(function (k) {
d[k] = o[k]
})
data.dependencies = d
}
function depObjectify (deps, type, warn) {
if (!deps) {
return {}
}
if (typeof deps === 'string') {
deps = deps.trim().split(/[\n\r\s\t ,]+/)
}
if (!Array.isArray(deps)) {
return deps
}
warn('deprecatedArrayDependencies', type)
var o = {}
deps.filter(function (d) {
return typeof d === 'string'
}).forEach(function (d) {
d = d.trim().split(/(:?[@\s><=])/)
var dn = d.shift()
var dv = d.join('')
dv = dv.trim()
dv = dv.replace(/^@/, '')
o[dn] = dv
})
return o
}
function objectifyDeps (data, warn) {
depTypes.forEach(function (type) {
if (!data[type]) {
return
}
data[type] = depObjectify(data[type], type, warn)
})
}
function bugsTypos (bugs, warn) {
if (!bugs) {
return
}
Object.keys(bugs).forEach(function (k) {
if (typos.bugs[k]) {
warn('typo', k, typos.bugs[k], 'bugs')
bugs[typos.bugs[k]] = bugs[k]
delete bugs[k]
}
})
}

View File

@@ -0,0 +1,22 @@
var util = require('util')
var messages = require('./warning_messages.json')
module.exports = function () {
var args = Array.prototype.slice.call(arguments, 0)
var warningName = args.shift()
if (warningName === 'typo') {
return makeTypoWarning.apply(null, args)
} else {
var msgTemplate = messages[warningName] ? messages[warningName] : warningName + ": '%s'"
args.unshift(msgTemplate)
return util.format.apply(null, args)
}
}
function makeTypoWarning (providedName, probableName, field) {
if (field) {
providedName = field + "['" + providedName + "']"
probableName = field + "['" + probableName + "']"
}
return util.format(messages.typo, providedName, probableName)
}

View File

@@ -0,0 +1,48 @@
module.exports = normalize
var fixer = require('./fixer')
normalize.fixer = fixer
var makeWarning = require('./make_warning')
var fieldsToFix = ['name', 'version', 'description', 'repository', 'modules', 'scripts',
'files', 'bin', 'man', 'bugs', 'keywords', 'readme', 'homepage', 'license']
var otherThingsToFix = ['dependencies', 'people', 'typos']
var thingsToFix = fieldsToFix.map(function (fieldName) {
return ucFirst(fieldName) + 'Field'
})
// two ways to do this in CoffeeScript on only one line, sub-70 chars:
// thingsToFix = fieldsToFix.map (name) -> ucFirst(name) + "Field"
// thingsToFix = (ucFirst(name) + "Field" for name in fieldsToFix)
thingsToFix = thingsToFix.concat(otherThingsToFix)
function normalize (data, warn, strict) {
if (warn === true) {
warn = null
strict = true
}
if (!strict) {
strict = false
}
if (!warn || data.private) {
warn = function () { /* noop */ }
}
if (data.scripts &&
data.scripts.install === 'node-gyp rebuild' &&
!data.scripts.preinstall) {
data.gypfile = true
}
fixer.warn = function () {
warn(makeWarning.apply(null, arguments))
}
thingsToFix.forEach(function (thingName) {
fixer['fix' + ucFirst(thingName)](data, strict)
})
data._id = data.name + '@' + data.version
}
function ucFirst (string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}

View File

@@ -0,0 +1,11 @@
var util = require('util')
module.exports = function () {
var args = Array.prototype.slice.call(arguments, 0)
args.forEach(function (arg) {
if (!arg) {
throw new TypeError('Bad arguments.')
}
})
return util.format.apply(null, arguments)
}

View File

@@ -0,0 +1,25 @@
{
"topLevel": {
"dependancies": "dependencies"
,"dependecies": "dependencies"
,"depdenencies": "dependencies"
,"devEependencies": "devDependencies"
,"depends": "dependencies"
,"dev-dependencies": "devDependencies"
,"devDependences": "devDependencies"
,"devDepenencies": "devDependencies"
,"devdependencies": "devDependencies"
,"repostitory": "repository"
,"repo": "repository"
,"prefereGlobal": "preferGlobal"
,"hompage": "homepage"
,"hampage": "homepage"
,"autohr": "author"
,"autor": "author"
,"contributers": "contributors"
,"publicationConfig": "publishConfig"
,"script": "scripts"
},
"bugs": { "web": "url", "name": "url" },
"script": { "server": "start", "tests": "test" }
}

View File

@@ -0,0 +1,30 @@
{
"repositories": "'repositories' (plural) Not supported. Please pick one as the 'repository' field"
,"missingRepository": "No repository field."
,"brokenGitUrl": "Probably broken git url: %s"
,"nonObjectScripts": "scripts must be an object"
,"nonStringScript": "script values must be string commands"
,"nonArrayFiles": "Invalid 'files' member"
,"invalidFilename": "Invalid filename in 'files' list: %s"
,"nonArrayBundleDependencies": "Invalid 'bundleDependencies' list. Must be array of package names"
,"nonStringBundleDependency": "Invalid bundleDependencies member: %s"
,"nonDependencyBundleDependency": "Non-dependency in bundleDependencies: %s"
,"nonObjectDependencies": "%s field must be an object"
,"nonStringDependency": "Invalid dependency: %s %s"
,"deprecatedArrayDependencies": "specifying %s as array is deprecated"
,"deprecatedModules": "modules field is deprecated"
,"nonArrayKeywords": "keywords should be an array of strings"
,"nonStringKeyword": "keywords should be an array of strings"
,"conflictingName": "%s is also the name of a node core module."
,"nonStringDescription": "'description' field should be a string"
,"missingDescription": "No description"
,"missingReadme": "No README data"
,"missingLicense": "No license field."
,"nonEmailUrlBugsString": "Bug string field must be url, email, or {email,url}"
,"nonUrlBugsUrlField": "bugs.url field must be a string url. Deleted."
,"nonEmailBugsEmailField": "bugs.email field must be a string email. Deleted."
,"emptyNormalizedBugs": "Normalized value of bugs field is an empty object. Deleted."
,"nonUrlHomepage": "homepage field must be a string url. Deleted."
,"invalidLicense": "license should be a valid SPDX license expression"
,"typo": "%s should probably be %s."
}

View File

@@ -0,0 +1,55 @@
{
"name": "normalize-package-data",
"version": "6.0.2",
"author": "GitHub Inc.",
"description": "Normalizes data that can be found in package.json files.",
"license": "BSD-2-Clause",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/normalize-package-data.git"
},
"main": "lib/normalize.js",
"scripts": {
"test": "tap",
"npmclilint": "npmcli-lint",
"lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
"lintfix": "npm run lint -- --fix",
"posttest": "npm run lint",
"postsnap": "npm run lintfix --",
"postlint": "template-oss-check",
"snap": "tap",
"template-oss-apply": "template-oss-apply --force"
},
"dependencies": {
"hosted-git-info": "^7.0.0",
"semver": "^7.3.5",
"validate-npm-package-license": "^3.0.4"
},
"devDependencies": {
"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.22.0",
"tap": "^16.0.1"
},
"files": [
"bin/",
"lib/"
],
"engines": {
"node": "^16.14.0 || >=18.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "4.22.0",
"publish": "true"
},
"tap": {
"branches": 86,
"functions": 92,
"lines": 86,
"statements": 86,
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
]
}
}