🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

lint-staged

Package Overview
Dependencies
Maintainers
1
Versions
261
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lint-staged - npm Package Compare versions

Comparing version

to
13.3.0

lib/normalizePath.js

22

bin/lint-staged.js
#!/usr/bin/env node
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import fs from 'node:fs/promises'

@@ -22,4 +20,3 @@ import { supportsColor } from 'chalk'

const packageJsonPath = path.join(fileURLToPath(import.meta.url), '../../package.json')
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath))
const packageJson = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url)))
const version = packageJson.version

@@ -117,3 +114,3 @@

try {
options.config = fs.readFileSync(process.stdin.fd, 'utf8').toString().trim()
options.config = await fs.readFile(process.stdin.fd, 'utf8').toString().trim()
} catch {

@@ -131,8 +128,7 @@ console.error(CONFIG_STDIN_ERROR)

lintStaged(options)
.then((passed) => {
process.exitCode = passed ? 0 : 1
})
.catch(() => {
process.exitCode = 1
})
try {
const passed = await lintStaged(options)
process.exitCode = passed ? 0 : 1
} catch {
process.exitCode = 1
}
import path from 'node:path'
import debug from 'debug'
import normalize from 'normalize-path'
import { normalizePath } from './normalizePath.js'
const debugLog = debug('lint-staged:chunkFiles')

@@ -38,3 +39,3 @@

const normalizedFiles = files.map((file) =>
normalize(relative || !baseDir ? file : path.resolve(baseDir, file))
normalizePath(relative || !baseDir ? file : path.resolve(baseDir, file))
)

@@ -41,0 +42,0 @@

@@ -5,4 +5,5 @@ import path from 'node:path'

import micromatch from 'micromatch'
import normalize from 'normalize-path'
import { normalizePath } from './normalizePath.js'
const debugLog = debug('lint-staged:generateTasks')

@@ -23,3 +24,3 @@

const relativeFiles = files.map((file) => normalize(path.relative(cwd, file)))
const relativeFiles = files.map((file) => normalizePath(path.relative(cwd, file)))

@@ -47,3 +48,3 @@ return Object.entries(config).map(([pattern, commands]) => {

const fileList = matches.map((file) => normalize(relative ? file : path.resolve(cwd, file)))
const fileList = matches.map((file) => normalizePath(relative ? file : path.resolve(cwd, file)))

@@ -50,0 +51,0 @@ const task = { pattern, commands, fileList }

@@ -1,16 +0,51 @@

const getMainRendererOptions = ({ debug, quiet }, env) => {
if (quiet) return { renderer: 'silent' }
import { EOL } from 'node:os'
import { Writable } from 'node:stream'
import { ListrLogger, ProcessOutput } from 'listr2'
const EOLRegex = new RegExp(EOL + '$')
const bindLogger = (consoleLogMethod) =>
new Writable({
write: function (chunk, encoding, next) {
consoleLogMethod(chunk.toString().replace(EOLRegex, ''))
next()
},
})
const getMainRendererOptions = ({ debug, quiet }, logger, env) => {
if (quiet) {
return {
renderer: 'silent',
}
}
if (env.NODE_ENV === 'test') {
return {
renderer: 'test',
rendererOptions: {
logger: new ListrLogger({
processOutput: new ProcessOutput(bindLogger(logger.log), bindLogger(logger.error)),
}),
},
}
}
// Better support for dumb terminals: https://en.wikipedia.org/wiki/Computer_terminal#Dumb_terminals
const isDumbTerminal = env.TERM === 'dumb'
if (debug || isDumbTerminal || env.NODE_ENV === 'test') return { renderer: 'verbose' }
return { renderer: 'update', rendererOptions: { dateFormat: false } }
if (debug || env.TERM === 'dumb') {
return {
renderer: 'verbose',
}
}
return {
renderer: 'update',
rendererOptions: {
formatOutput: 'truncate',
},
}
}
const getFallbackRenderer = ({ renderer }, { FORCE_COLOR }) => {
if (renderer === 'silent') {
return 'silent'
}
// If colors are being forced, then also force non-fallback rendering
if (Number(FORCE_COLOR) > 0) {
if (renderer === 'silent' || renderer === 'test' || Number(FORCE_COLOR) > 0) {
return renderer

@@ -22,8 +57,9 @@ }

export const getRenderer = (options, env = process.env) => {
const mainRendererOptions = getMainRendererOptions(options, env)
export const getRenderer = (options, logger, env = process.env) => {
const mainRendererOptions = getMainRendererOptions(options, logger, env)
return {
...mainRendererOptions,
nonTTYRenderer: getFallbackRenderer(mainRendererOptions, env),
fallbackRenderer: getFallbackRenderer(mainRendererOptions, env),
}
}
import path from 'node:path'
import normalize from 'normalize-path'
import { execGit } from './execGit.js'
import { getDiffCommand } from './getDiffCommand.js'
import { normalizePath } from './normalizePath.js'
import { parseGitZOutput } from './parseGitZOutput.js'

@@ -14,3 +13,3 @@

return parseGitZOutput(lines).map((file) => normalize(path.resolve(cwd, file)))
return parseGitZOutput(lines).map((file) => normalizePath(path.resolve(cwd, file)))
} catch {

@@ -17,0 +16,0 @@ return null

@@ -1,2 +0,1 @@

import cliTruncate from 'cli-truncate'
import debug from 'debug'

@@ -9,20 +8,3 @@

const STDOUT_COLUMNS_DEFAULT = 80
const listrPrefixLength = {
update: ` X `.length, // indented task title where X is a checkmark or a cross (failure)
verbose: `[STARTED] `.length, // verbose renderer uses 7-letter STARTED/SUCCESS prefixes
}
/**
* Get length of title based on the number of available columns prefix length
* @param {string} renderer The name of the Listr renderer
* @returns {number}
*/
const getTitleLength = (renderer, columns = process.stdout.columns) => {
const prefixLength = listrPrefixLength[renderer] || 0
return (columns || STDOUT_COLUMNS_DEFAULT) - prefixLength
}
/**
* Creates and returns an array of listr tasks which map to the given commands.

@@ -35,7 +17,6 @@ *

* @param {string} options.gitDir
* @param {string} options.renderer
* @param {Boolean} shell
* @param {Boolean} verbose
*/
export const makeCmdTasks = async ({ commands, cwd, files, gitDir, renderer, shell, verbose }) => {
export const makeCmdTasks = async ({ commands, cwd, files, gitDir, shell, verbose }) => {
debugLog('Creating listr tasks for commands %o', commands)

@@ -65,6 +46,4 @@ const commandArray = Array.isArray(commands) ? commands : [commands]

// Truncate title to single line based on renderer
const title = cliTruncate(command, getTitleLength(renderer))
const task = resolveTaskFn({ command, cwd, files, gitDir, isFn, shell, verbose })
cmdTasks.push({ title, command, task })
cmdTasks.push({ title: command, command, task })
}

@@ -71,0 +50,0 @@ }

@@ -0,3 +1,4 @@

import { inspect } from 'node:util'
import chalk from 'chalk'
import inspect from 'object-inspect'

@@ -9,5 +10,3 @@ import { error, info, warning } from './figures.js'

Invalid value for '${chalk.bold(opt)}': ${chalk.bold(
inspect(value, { inlineCharacterLimit: Number.POSITIVE_INFINITY })
)}
Invalid value for '${chalk.bold(opt)}': ${chalk.bold(inspect(value))}

@@ -14,0 +13,0 @@ ${helpMsg}`

@@ -5,6 +5,6 @@ import fs from 'node:fs/promises'

import debug from 'debug'
import normalize from 'normalize-path'
import { execGit } from './execGit.js'
import { readFile } from './file.js'
import { normalizePath } from './normalizePath.js'

@@ -19,3 +19,3 @@ const debugLog = debug('lint-staged:resolveGitRepo')

// Get the real path in case it's a symlink
const defaultDir = normalize(await fs.realpath(path.join(gitDir, '.git')))
const defaultDir = normalizePath(await fs.realpath(path.join(gitDir, '.git')))
const stats = await fs.lstat(defaultDir)

@@ -38,6 +38,6 @@ // If .git is a directory, use it

// the current working dir is inside the git top-level directory
return normalize(cwd.substring(0, cwd.lastIndexOf(relativeDir)))
return normalizePath(cwd.substring(0, cwd.lastIndexOf(relativeDir)))
} else {
// the current working dir is the top-level git directory
return normalize(cwd)
return normalizePath(cwd)
}

@@ -61,5 +61,5 @@ }

// don't read the toplevel directly, it will lead to an posix conform path on non posix systems (cygwin)
const gitRel = normalize(await execGit(['rev-parse', '--show-prefix'], { cwd }))
const gitDir = determineGitDir(normalize(cwd), gitRel)
const gitConfigDir = normalize(await resolveGitConfigDir(gitDir))
const gitRel = normalizePath(await execGit(['rev-parse', '--show-prefix'], { cwd }))
const gitDir = determineGitDir(normalizePath(cwd), gitRel)
const gitConfigDir = normalizePath(await resolveGitConfigDir(gitDir))

@@ -66,0 +66,0 @@ debugLog('Resolved git directory to be `%s`', gitDir)

@@ -8,3 +8,2 @@ /** @typedef {import('./index').Logger} Logger */

import { Listr } from 'listr2'
import normalize from 'normalize-path'

@@ -28,2 +27,3 @@ import { chunkFiles } from './chunkFiles.js'

} from './messages.js'
import { normalizePath } from './normalizePath.js'
import { resolveGitRepo } from './resolveGitRepo.js'

@@ -156,3 +156,3 @@ import {

registerSignalListeners: false,
...getRenderer({ debug, quiet }),
...getRenderer({ debug, quiet }, logger),
}

@@ -166,3 +166,3 @@

for (const [configPath, { config, files }] of Object.entries(filesByConfig)) {
const configName = configPath ? normalize(path.relative(cwd, configPath)) : 'Config object'
const configName = configPath ? normalizePath(path.relative(cwd, configPath)) : 'Config object'

@@ -189,3 +189,2 @@ const stagedFileChunks = chunkFiles({ baseDir: gitDir, files, maxArgLength, relative })

gitDir,
renderer: listrOptions.renderer,
shell,

@@ -201,3 +200,3 @@ verbose,

? file
: normalize(path.join(groupCwd, file))
: normalizePath(path.join(groupCwd, file))

@@ -204,0 +203,0 @@ matchedFiles.add(normalizedFile)

@@ -6,6 +6,6 @@ /** @typedef {import('./index').Logger} Logger */

import debug from 'debug'
import normalize from 'normalize-path'
import { execGit } from './execGit.js'
import { loadConfig, searchPlaces } from './loadConfig.js'
import { normalizePath } from './normalizePath.js'
import { parseGitZOutput } from './parseGitZOutput.js'

@@ -25,3 +25,3 @@ import { validateConfig } from './validateConfig.js'

const isInsideDirectory = (dir) => (file) => file.startsWith(normalize(dir))
const isInsideDirectory = (dir) => (file) => file.startsWith(normalizePath(dir))

@@ -73,3 +73,3 @@ /**

const possibleConfigFiles = [...cachedFiles, ...otherFiles]
.map((file) => normalize(path.join(gitDir, file)))
.map((file) => normalizePath(path.join(gitDir, file)))
.filter(isInsideDirectory(cwd))

@@ -76,0 +76,0 @@ .sort(sortDeepestParth)

@@ -20,4 +20,4 @@ import { incorrectBraces } from './messages.js'

* @example <caption>Globs with brace expansions</caption>
* - *.{js,tx} // expanded as *.js, *.ts
* - *.{{j,t}s,css} // expanded as *.js, *.ts, *.css
* - *.{js,tx} // expanded as *.js, *.ts
* - *.{{j,t}s,css} // expanded as *.js, *.ts, *.css
* - file_{1..10}.css // expanded as file_1.css, file_2.css, …, file_10.css

@@ -32,3 +32,3 @@ *

*/
export const BRACES_REGEXP = /(?<![\\$])({)(?:(?!(?<!\\),|\.\.|\{|\}).)*?(?<!\\)(})/g
export const INCORRECT_BRACES_REGEXP = /(?<![\\$])({)(?:(?!(?<!\\),|\.\.|\{|\}).)*?(?<!\\)(})/g

@@ -39,7 +39,7 @@ /**

*/
const withoutIncorrectBraces = (pattern) => {
const stripIncorrectBraces = (pattern) => {
let output = `${pattern}`
let match = null
while ((match = BRACES_REGEXP.exec(pattern))) {
while ((match = INCORRECT_BRACES_REGEXP.exec(pattern))) {
const fullMatch = match[0]

@@ -54,2 +54,26 @@ const withoutBraces = fullMatch.replace(/{/, '').replace(/}/, '')

/**
* This RegExp matches "duplicate" opening and closing braces, without any other braces
* in between, where the duplication is redundant and should be removed.
*
* @example *.{{js,ts}} // should just be *.{js,ts}
*/
export const DOUBLE_BRACES_REGEXP = /{{[^}{]*}}/
/**
* @param {string} pattern
* @returns {string}
*/
const stripDoubleBraces = (pattern) => {
let output = `${pattern}`
const match = DOUBLE_BRACES_REGEXP.exec(pattern)?.[0]
if (match) {
const withoutBraces = match.replace('{{', '{').replace('}}', '}')
output = output.replace(match, withoutBraces)
}
return output
}
/**
* Validate and remove incorrect brace expansions from glob pattern.

@@ -64,3 +88,3 @@ * For example `*.{js}` is incorrect because it doesn't contain a `,` or `..`,

export const validateBraces = (pattern, logger) => {
const fixedPattern = withoutIncorrectBraces(pattern)
const fixedPattern = stripDoubleBraces(stripIncorrectBraces(pattern))

@@ -67,0 +91,0 @@ if (fixedPattern !== pattern) {

/** @typedef {import('./index').Logger} Logger */
import { inspect } from 'node:util'
import debug from 'debug'
import inspect from 'object-inspect'

@@ -112,5 +113,5 @@ import { configurationError } from './messages.js'

debugLog('Validated config from `%s`:', configPath)
debugLog(inspect(config, { indent: 2 }))
debugLog(inspect(config, { compact: false }))
return validatedConfig
}
{
"name": "lint-staged",
"version": "13.2.3",
"version": "13.3.0",
"description": "Lint files staged by git",

@@ -17,3 +17,3 @@ "license": "MIT",

"engines": {
"node": "^14.13.1 || >=16.0.0"
"node": "^16.14.0 || >=18.0.0"
},

@@ -37,33 +37,29 @@ "type": "module",

"dependencies": {
"chalk": "5.2.0",
"cli-truncate": "^3.1.0",
"commander": "^10.0.0",
"debug": "^4.3.4",
"execa": "^7.0.0",
"chalk": "5.3.0",
"commander": "11.0.0",
"debug": "4.3.4",
"execa": "7.2.0",
"lilconfig": "2.1.0",
"listr2": "^5.0.7",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"object-inspect": "^1.12.3",
"pidtree": "^0.6.0",
"string-argv": "^0.3.1",
"yaml": "^2.2.2"
"listr2": "6.6.1",
"micromatch": "4.0.5",
"pidtree": "0.6.0",
"string-argv": "0.3.2",
"yaml": "2.3.1"
},
"devDependencies": {
"@babel/core": "^7.21.0",
"@babel/eslint-parser": "^7.19.1",
"@babel/preset-env": "^7.20.2",
"babel-jest": "^29.5.0",
"@babel/core": "7.22.10",
"@babel/eslint-parser": "7.22.10",
"@babel/preset-env": "7.22.10",
"babel-jest": "29.6.2",
"babel-plugin-transform-imports": "2.0.0",
"consolemock": "^1.1.0",
"eslint": "^8.35.0",
"eslint-config-prettier": "^8.7.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"fs-extra": "^11.1.0",
"husky": "^8.0.3",
"jest": "^29.5.0",
"jest-snapshot-serializer-ansi": "^1.0.0",
"prettier": "^2.8.4"
"consolemock": "1.1.0",
"eslint": "8.46.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.28.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "5.0.0",
"husky": "8.0.3",
"jest": "29.6.2",
"jest-snapshot-serializer-ansi": "2.1.0",
"prettier": "3.0.1"
},

@@ -70,0 +66,0 @@ "keywords": [

@@ -61,3 +61,3 @@ # 🚫💩 lint-staged ![GitHub Actions](https://github.com/okonet/lint-staged/workflows/CI/badge.svg) [![npm version](https://badge.fury.io/js/lint-staged.svg)](https://badge.fury.io/js/lint-staged) [![Codecov](https://codecov.io/gh/okonet/lint-staged/branch/master/graph/badge.svg)](https://codecov.io/gh/okonet/lint-staged)

- for example: `{ "*.js": "eslint" }` to run ESLint for all staged JS files
- See [Configuration](#Configuration) for more info
- See [Configuration](#configuration) for more info

@@ -76,2 +76,6 @@ Don't forget to commit changes to `package.json` and `.husky` to share this setup with your team!

#### v14
- Since `v14.0.0` _lint-staged_ no longer supports Node.js 14. Please upgrade your Node.js version to at least `16.14.0`.
#### v13

@@ -223,7 +227,7 @@

- If the glob pattern contains no slashes (`/`), micromatch's `matchBase` option will enabled, so globs match a file's basename regardless of directory:
- **`"*.js"`** will match all JS files, like `/test.js` and `/foo/bar/test.js`
- **`"!(*test).js"`**. will match all JS files, except those ending in `test.js`, so `foo.js` but not `foo.test.js`
- `"*.js"` will match all JS files, like `/test.js` and `/foo/bar/test.js`
- `"!(*test).js"` will match all JS files, except those ending in `test.js`, so `foo.js` but not `foo.test.js`
- If the glob pattern does contain a slash (`/`), it will match for paths as well:
- **`"./*.js"`** will match all JS files in the git repo root, so `/test.js` but not `/foo/bar/test.js`
- **`"foo/**/*.js"`** will match all JS files inside the `/foo` directory, so `/foo/bar/test.js` but not `/test.js`
- `"./*.js"` will match all JS files in the git repo root, so `/test.js` but not `/foo/bar/test.js`
- `"foo/**/*.js"` will match all JS files inside the `/foo` directory, so `/foo/bar/test.js` but not `/test.js`

@@ -630,5 +634,3 @@ When matching, lint-staged will do the following

const buildEslintCommand = (filenames) =>
`next lint --fix --file ${filenames
.map((f) => path.relative(process.cwd(), f))
.join(' --file ')}`
`next lint --fix --file ${filenames.map((f) => path.relative(process.cwd(), f)).join(' --file ')}`

@@ -635,0 +637,0 @@ module.exports = {