@depup/lint-staged 16.3.2-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/MIGRATION.md +72 -0
- package/README.md +1120 -0
- package/bin/lint-staged.js +175 -0
- package/lib/chunkFiles.js +65 -0
- package/lib/colors.js +106 -0
- package/lib/configFiles.js +30 -0
- package/lib/debug.js +27 -0
- package/lib/execGit.js +37 -0
- package/lib/figures.js +9 -0
- package/lib/file.js +53 -0
- package/lib/generateTasks.js +69 -0
- package/lib/getAbortController.js +18 -0
- package/lib/getDiffCommand.js +19 -0
- package/lib/getFunctionTask.js +37 -0
- package/lib/getRenderer.js +63 -0
- package/lib/getSpawnedTask.js +160 -0
- package/lib/getSpawnedTasks.js +76 -0
- package/lib/getStagedFiles.js +86 -0
- package/lib/gitWorkflow.js +434 -0
- package/lib/groupFilesByConfig.js +62 -0
- package/lib/index.d.ts +125 -0
- package/lib/index.js +184 -0
- package/lib/killSubprocesses.js +42 -0
- package/lib/loadConfig.js +102 -0
- package/lib/messages.js +91 -0
- package/lib/normalizePath.js +50 -0
- package/lib/parseGitZOutput.js +11 -0
- package/lib/printTaskOutput.js +12 -0
- package/lib/readStdin.js +19 -0
- package/lib/resolveConfig.js +15 -0
- package/lib/resolveGitRepo.js +65 -0
- package/lib/runAll.js +372 -0
- package/lib/searchConfigs.js +186 -0
- package/lib/state.js +102 -0
- package/lib/symbols.js +29 -0
- package/lib/validateBraces.js +95 -0
- package/lib/validateConfig.js +108 -0
- package/lib/validateOptions.js +33 -0
- package/lib/version.js +6 -0
- package/package.json +93 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { incorrectBraces } from './messages.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A correctly-formed brace expansion must contain unquoted opening and closing braces,
|
|
5
|
+
* and at least one unquoted comma or a valid sequence expression.
|
|
6
|
+
* Any incorrectly formed brace expansion is left unchanged.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html
|
|
9
|
+
*
|
|
10
|
+
* Lint-staged uses `micromatch` for brace expansion, and its behavior is to treat
|
|
11
|
+
* invalid brace expansions as literal strings, which means they (typically) do not match
|
|
12
|
+
* anything.
|
|
13
|
+
*
|
|
14
|
+
* This RegExp tries to match most cases of invalid brace expansions, so that they can be
|
|
15
|
+
* detected, warned about, and re-formatted by removing the braces and thus hopefully
|
|
16
|
+
* matching the files as intended by the user. The only real fix is to remove the incorrect
|
|
17
|
+
* braces from user configuration, but this is left to the user (after seeing the warning).
|
|
18
|
+
*
|
|
19
|
+
* @example <caption>Globs with brace expansions</caption>
|
|
20
|
+
* - *.{js,tx} // expanded as *.js, *.ts
|
|
21
|
+
* - *.{{j,t}s,css} // expanded as *.js, *.ts, *.css
|
|
22
|
+
* - file_{1..10}.css // expanded as file_1.css, file_2.css, …, file_10.css
|
|
23
|
+
*
|
|
24
|
+
* @example <caption>Globs with incorrect brace expansions</caption>
|
|
25
|
+
* - *.{js} // should just be *.js
|
|
26
|
+
* - *.{js,{ts}} // should just be *.{js,ts}
|
|
27
|
+
* - *.\{js\} // escaped braces, so they're treated literally
|
|
28
|
+
* - *.${js} // dollar-sign inhibits expansion, so treated literally
|
|
29
|
+
* - *.{js\,ts} // the comma is escaped, so treated literally
|
|
30
|
+
*/
|
|
31
|
+
export const getIncorrectBracesRegexp = () =>
|
|
32
|
+
/(?<![\\$])({)(?:(?!(?<!\\),|\.\.|\{|\}).)*?(?<!\\)(})/g
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} pattern
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
const stripIncorrectBraces = (pattern) => {
|
|
39
|
+
let output = `${pattern}`
|
|
40
|
+
const regexp = getIncorrectBracesRegexp()
|
|
41
|
+
let match = regexp.exec(output)
|
|
42
|
+
|
|
43
|
+
while (match) {
|
|
44
|
+
const fullMatch = match[0]
|
|
45
|
+
const withoutBraces = fullMatch.replace(/{/, '').replace(/}/, '')
|
|
46
|
+
output = output.replace(fullMatch, withoutBraces)
|
|
47
|
+
regexp.lastIndex = 0 // restart iteration
|
|
48
|
+
match = regexp.exec(output)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return output
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* This RegExp matches "duplicate" opening and closing braces, without any other braces
|
|
56
|
+
* in between, where the duplication is redundant and should be removed.
|
|
57
|
+
*
|
|
58
|
+
* @example *.{{js,ts}} // should just be *.{js,ts}
|
|
59
|
+
*/
|
|
60
|
+
export const DOUBLE_BRACES_REGEXP = /{{[^}{]*}}/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {string} pattern
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
const stripDoubleBraces = (pattern) => {
|
|
67
|
+
let output = `${pattern}`
|
|
68
|
+
const match = DOUBLE_BRACES_REGEXP.exec(pattern)?.[0]
|
|
69
|
+
|
|
70
|
+
if (match) {
|
|
71
|
+
const withoutBraces = match.replace('{{', '{').replace('}}', '}')
|
|
72
|
+
output = output.replace(match, withoutBraces)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return output
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Validate and remove incorrect brace expansions from glob pattern.
|
|
80
|
+
* For example `*.{js}` is incorrect because it doesn't contain a `,` or `..`,
|
|
81
|
+
* and will be reformatted as `*.js`.
|
|
82
|
+
*
|
|
83
|
+
* @param {string} pattern the glob pattern
|
|
84
|
+
* @param {*} logger
|
|
85
|
+
* @returns {string}
|
|
86
|
+
*/
|
|
87
|
+
export const validateBraces = (pattern, logger) => {
|
|
88
|
+
const fixedPattern = stripDoubleBraces(stripIncorrectBraces(pattern))
|
|
89
|
+
|
|
90
|
+
if (fixedPattern !== pattern) {
|
|
91
|
+
logger.warn(incorrectBraces(pattern, fixedPattern))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return fixedPattern
|
|
95
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/** @typedef {import('./index').Logger} Logger */
|
|
2
|
+
|
|
3
|
+
import { inspect } from 'node:util'
|
|
4
|
+
|
|
5
|
+
import { createDebug } from './debug.js'
|
|
6
|
+
import { configurationError, failedToParseConfig } from './messages.js'
|
|
7
|
+
import { ConfigEmptyError, ConfigFormatError } from './symbols.js'
|
|
8
|
+
import { validateBraces } from './validateBraces.js'
|
|
9
|
+
|
|
10
|
+
const debugLog = createDebug('lint-staged:validateConfig')
|
|
11
|
+
|
|
12
|
+
export const validateConfigLogic = (config, configPath, logger) => {
|
|
13
|
+
debugLog('Validating config from `%s`...', configPath)
|
|
14
|
+
|
|
15
|
+
if (!config || (typeof config !== 'object' && typeof config !== 'function')) {
|
|
16
|
+
throw ConfigFormatError
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Function configurations receive all staged files as their argument.
|
|
21
|
+
* They are not further validated here to make sure the function gets
|
|
22
|
+
* evaluated only once.
|
|
23
|
+
*
|
|
24
|
+
* @see getSpawnedTasks
|
|
25
|
+
*/
|
|
26
|
+
if (typeof config === 'function') {
|
|
27
|
+
return { '*': config }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (Object.entries(config).length === 0) {
|
|
31
|
+
throw ConfigEmptyError
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const errors = []
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a new validated config because the keys (patterns) might change.
|
|
38
|
+
* Since the Object.reduce method already loops through each entry in the config,
|
|
39
|
+
* it can be used for validating the values at the same time.
|
|
40
|
+
*/
|
|
41
|
+
const validatedConfig = Object.entries(config).reduce((collection, [pattern, task]) => {
|
|
42
|
+
if (Array.isArray(task)) {
|
|
43
|
+
/** Array with invalid values */
|
|
44
|
+
if (task.some((item) => typeof item !== 'string' && typeof item !== 'function')) {
|
|
45
|
+
errors.push(
|
|
46
|
+
configurationError(pattern, 'Should be an array of strings or functions.', task)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
} else if (typeof task === 'object') {
|
|
50
|
+
/** Invalid function task */
|
|
51
|
+
if (typeof task.title !== 'string' || typeof task.task !== 'function') {
|
|
52
|
+
errors.push(
|
|
53
|
+
configurationError(
|
|
54
|
+
pattern,
|
|
55
|
+
'Function task should contain `title` and `task` fields, where `title` should be a string and `task` should be a function.',
|
|
56
|
+
task
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
} else if (typeof task !== 'string' && typeof task !== 'function') {
|
|
61
|
+
/** Singular invalid value */
|
|
62
|
+
errors.push(
|
|
63
|
+
configurationError(
|
|
64
|
+
pattern,
|
|
65
|
+
'Should be a string, a function, an object or an array of strings and functions.',
|
|
66
|
+
task
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A typical configuration error is using invalid brace expansion, like `*.{js}`.
|
|
73
|
+
* These are automatically fixed and warned about.
|
|
74
|
+
*/
|
|
75
|
+
const fixedPattern = validateBraces(pattern, logger)
|
|
76
|
+
|
|
77
|
+
return Object.assign(collection, { [fixedPattern]: task })
|
|
78
|
+
}, {})
|
|
79
|
+
|
|
80
|
+
if (errors.length) {
|
|
81
|
+
const message = errors.join('\n\n')
|
|
82
|
+
|
|
83
|
+
logger.error(failedToParseConfig(configPath, message))
|
|
84
|
+
|
|
85
|
+
throw new Error(message)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
debugLog('Validated config from `%s`:', configPath)
|
|
89
|
+
debugLog(inspect(config, { compact: false }))
|
|
90
|
+
|
|
91
|
+
return validatedConfig
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Runs config validation. Throws error if the config is not valid.
|
|
96
|
+
* @param {Object} config
|
|
97
|
+
* @param {string} configPath
|
|
98
|
+
* @param {Logger} logger
|
|
99
|
+
* @returns {Object} config
|
|
100
|
+
*/
|
|
101
|
+
export const validateConfig = (config, configPath, logger) => {
|
|
102
|
+
try {
|
|
103
|
+
return validateConfigLogic(config, configPath, logger)
|
|
104
|
+
} catch (error) {
|
|
105
|
+
logger.error(failedToParseConfig(configPath, error))
|
|
106
|
+
throw error
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { constants } from 'node:fs'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { createDebug } from './debug.js'
|
|
6
|
+
import { invalidOption } from './messages.js'
|
|
7
|
+
import { InvalidOptionsError } from './symbols.js'
|
|
8
|
+
|
|
9
|
+
const debugLog = createDebug('lint-staged:validateOptions')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validate lint-staged options, either from the Node.js API or the command line flags.
|
|
13
|
+
* @param {*} options
|
|
14
|
+
* @param {boolean|string} [options.cwd] - Current working directory
|
|
15
|
+
* @throws {InvalidOptionsError}
|
|
16
|
+
*/
|
|
17
|
+
export const validateOptions = async (options = {}, logger) => {
|
|
18
|
+
debugLog('Validating options...')
|
|
19
|
+
|
|
20
|
+
/** Ensure the passed cwd option exists; it might also be relative */
|
|
21
|
+
if (typeof options.cwd === 'string') {
|
|
22
|
+
try {
|
|
23
|
+
const resolved = path.resolve(options.cwd)
|
|
24
|
+
await fs.access(resolved, constants.F_OK)
|
|
25
|
+
} catch (error) {
|
|
26
|
+
debugLog('Failed to validate options: %o', options)
|
|
27
|
+
logger.error(invalidOption('cwd', options.cwd, error.message))
|
|
28
|
+
throw InvalidOptionsError
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
debugLog('Validated options: %o', options)
|
|
33
|
+
}
|
package/lib/version.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@depup/lint-staged",
|
|
3
|
+
"version": "16.3.2-depup.0",
|
|
4
|
+
"description": "Lint files staged by git",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/lint-staged/lint-staged.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/lint-staged/lint-staged#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/lint-staged/lint-staged/issues"
|
|
13
|
+
},
|
|
14
|
+
"author": "Andrey Okonetchnikov <andrey@okonet.ru>",
|
|
15
|
+
"maintainers": [
|
|
16
|
+
"Iiro Jäppinen <iiro@jappinen.fi> (https://iiro.fi)"
|
|
17
|
+
],
|
|
18
|
+
"funding": {
|
|
19
|
+
"url": "https://opencollective.com/lint-staged"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20.17"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"bin": {
|
|
26
|
+
"lint-staged": "bin/lint-staged.js"
|
|
27
|
+
},
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./lib/index.d.ts",
|
|
31
|
+
"default": "./lib/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./bin": "./bin/lint-staged.js",
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"types": "./lib/index.d.ts",
|
|
37
|
+
"files": [
|
|
38
|
+
"bin/",
|
|
39
|
+
"lib/",
|
|
40
|
+
"MIGRATION.md"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"lint": "eslint",
|
|
44
|
+
"test": "vitest",
|
|
45
|
+
"typecheck": "tsc",
|
|
46
|
+
"version": "npx changeset version",
|
|
47
|
+
"postversion": "npm i --package-lock-only && git commit -am \"chore(changeset): release\"",
|
|
48
|
+
"tag": "npx changeset tag"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"commander": "^14.0.3",
|
|
52
|
+
"listr2": "^10.2.1",
|
|
53
|
+
"micromatch": "^4.0.8",
|
|
54
|
+
"string-argv": "^0.3.2",
|
|
55
|
+
"tinyexec": "^1.0.2",
|
|
56
|
+
"yaml": "^2.8.2"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@changesets/changelog-github": "0.5.2",
|
|
60
|
+
"@changesets/cli": "2.29.8",
|
|
61
|
+
"@commitlint/cli": "20.4.2",
|
|
62
|
+
"@commitlint/config-conventional": "20.4.2",
|
|
63
|
+
"@eslint/js": "10.0.1",
|
|
64
|
+
"@vitest/coverage-v8": "4.0.18",
|
|
65
|
+
"@vitest/eslint-plugin": "1.6.9",
|
|
66
|
+
"consolemock": "1.1.0",
|
|
67
|
+
"cross-env": "10.1.0",
|
|
68
|
+
"eslint": "10.0.2",
|
|
69
|
+
"eslint-config-prettier": "10.1.8",
|
|
70
|
+
"eslint-plugin-n": "17.24.0",
|
|
71
|
+
"eslint-plugin-prettier": "5.5.5",
|
|
72
|
+
"eslint-plugin-simple-import-sort": "12.1.1",
|
|
73
|
+
"husky": "9.1.7",
|
|
74
|
+
"mock-stdin": "1.0.0",
|
|
75
|
+
"prettier": "3.8.1",
|
|
76
|
+
"semver": "7.7.4",
|
|
77
|
+
"typescript": "5.9.3",
|
|
78
|
+
"vitest": "4.0.18"
|
|
79
|
+
},
|
|
80
|
+
"keywords": [
|
|
81
|
+
"lint",
|
|
82
|
+
"git",
|
|
83
|
+
"staged",
|
|
84
|
+
"eslint",
|
|
85
|
+
"prettier",
|
|
86
|
+
"stylelint",
|
|
87
|
+
"code",
|
|
88
|
+
"quality",
|
|
89
|
+
"check",
|
|
90
|
+
"format",
|
|
91
|
+
"validate"
|
|
92
|
+
]
|
|
93
|
+
}
|