lint-staged 17.0.7 → 17.1.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/README.md CHANGED
@@ -13,27 +13,21 @@ npm install --save-dev lint-staged # requires further setup
13
13
  ```
14
14
  $ git commit
15
15
 
16
- Backed up original state in git stash (5bda95f)
17
- Running tasks for staged files...
18
- packages/frontend/.lintstagedrc.json 1 file
19
- *.jsno files [SKIPPED]
20
- *.{json,md} — 1 file
21
- ⠹ prettier --write
22
- packages/backend/.lintstagedrc.json — 2 files
23
- ❯ *.js — 2 files
24
- eslint --fix
25
- *.{json,md} no files [SKIPPED]
26
- Updating Git index again...
27
- Cleaning up temporary files...
16
+ Backing up original state
17
+ Done backing up original state (1f4c047d)!
18
+ Running tasks for staged files…
19
+ *.{json,md}1 file
20
+ prettier --write
21
+
22
+ prettier --write
23
+
24
+ Done running tasks for staged files!
25
+ Staging changes from tasks…
26
+ Done staging changes from tasks!
27
+ Cleaning up temporary files
28
+ ✔ Done cleaning up temporary files!
28
29
  ```
29
30
 
30
- <details>
31
- <summary>See asciinema video</summary>
32
-
33
- [![asciicast](https://asciinema.org/a/199934.svg)](https://asciinema.org/a/199934)
34
-
35
- </details>
36
-
37
31
  > [!Tip]
38
32
  > Do you only want to check staged files for errors, but not edit them automatically?
39
33
  > You might be interested in this simpler shell script: [`lint-staged.sh`](https://github.com/lint-staged/lint-staged.sh).
@@ -154,11 +148,7 @@ Change the working directory _lint-staged_ runs tasks in. Defaults to `process.c
154
148
 
155
149
  #### `--debug`
156
150
 
157
- Run in debug mode. When set, it does the following:
158
-
159
- - log additional information about staged files, commands being executed, location of binaries, etc.
160
- - uses [`verbose` renderer](https://listr2.kilic.dev/renderers/verbose-renderer/) for `listr2`; this causes serial, uncoloured output to the terminal, instead of the default (beautified, dynamic) output.
161
- (the [`verbose` renderer](https://listr2.kilic.dev/renderers/verbose-renderer/) can also be activated by setting the `TERM=dumb` or `NODE_ENV=test` environment variables)
151
+ Log additional information about staged files, commands being executed, location of binaries, etc.
162
152
 
163
153
  #### `--diff`
164
154
 
@@ -3,14 +3,15 @@
3
3
  import { userInfo } from 'node:os'
4
4
 
5
5
  import { getVersionNumber, parseCliOptions, printHelpText } from '../lib/cli.js'
6
+ import { enableColors } from '../lib/colors.js'
6
7
  import { createDebug, enableDebug } from '../lib/debug.js'
7
8
  import lintStaged from '../lib/index.js'
8
- import { CONFIG_STDIN_ERROR } from '../lib/messages.js'
9
9
  import { readStdin } from '../lib/readStdin.js'
10
10
 
11
+ enableColors(!!process.stdout.hasColors?.())
11
12
  const debugLog = createDebug('lint-staged:bin')
12
13
 
13
- // Do not terminate main Listr process on SIGINT
14
+ // SIGINT handled by an AbortController
14
15
  process.on('SIGINT', () => {})
15
16
 
16
17
  const cliOptions = parseCliOptions(process.argv)
@@ -44,9 +45,8 @@ if (cliOptions.configPath === '-') {
44
45
  debugLog('Reading config from stdin')
45
46
  cliOptions.config = JSON.parse(await readStdin())
46
47
  } catch (error) {
47
- debugLog(CONFIG_STDIN_ERROR, error)
48
- console.error(CONFIG_STDIN_ERROR)
49
- process.exit(1)
48
+ console.error('Failed to read config from stdin!')
49
+ throw error
50
50
  }
51
51
  }
52
52
 
package/lib/colors.js CHANGED
@@ -1,11 +1,29 @@
1
- /* eslint-disable n/no-unsupported-features/node-builtins */
2
-
3
1
  import util from 'node:util'
4
2
 
5
- export const SUPPORTS_COLOR = !!process.stdout.hasColors?.()
3
+ export let COLORS_ENABLED = false
4
+
5
+ /** @param {boolean} [enabled] */
6
+ export const enableColors = (enabled) => {
7
+ if (enabled) {
8
+ COLORS_ENABLED = true
9
+ }
10
+ }
11
+
12
+ /**
13
+ * @param {util.InspectColor | readonly util.InspectColor[]} format
14
+ * @returns {(text: string) => string}
15
+ */
16
+ const styleText = (format) => (text) =>
17
+ COLORS_ENABLED ? util.styleText(format, text, { validateStream: false }) : text
18
+
19
+ export const green = styleText('green')
20
+
21
+ export const red = styleText('red')
22
+
23
+ export const yellow = styleText('yellow')
24
+
25
+ export const blue = styleText('blue')
26
+
27
+ export const dim = styleText('dim')
6
28
 
7
- export const red = (text) => (SUPPORTS_COLOR ? util.styleText('red', text) : text)
8
- export const yellow = (text) => (SUPPORTS_COLOR ? util.styleText('yellow', text) : text)
9
- export const blue = (text) => (SUPPORTS_COLOR ? util.styleText('blue', text) : text)
10
- export const dim = (text) => (SUPPORTS_COLOR ? util.styleText('dim', text) : text)
11
- export const bold = (text) => (SUPPORTS_COLOR ? util.styleText('bold', text) : text)
29
+ export const bold = styleText('bold')
package/lib/debug.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { formatWithOptions } from 'node:util'
2
2
 
3
- import { dim, SUPPORTS_COLOR } from './colors.js'
3
+ import { COLORS_ENABLED, dim } from './colors.js'
4
4
 
5
- const format = (...args) => formatWithOptions({ colors: SUPPORTS_COLOR }, ...args)
5
+ const format = (...args) => formatWithOptions({ colors: COLORS_ENABLED }, ...args)
6
6
 
7
7
  let activeLogger
8
8
 
package/lib/execGit.js CHANGED
@@ -4,9 +4,6 @@ import { createDebug } from './debug.js'
4
4
 
5
5
  const debugLog = createDebug('lint-staged:execGit')
6
6
 
7
- /** @example "warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it" */
8
- const GIT_CRLF_WARNING = /^warning.*CRLF.*the next time Git touches it/i
9
-
10
7
  /**
11
8
  * Explicitly never recurse commands into submodules, overriding local/global configuration.
12
9
  * @see https://git-scm.com/docs/git-config#Documentation/git-config.txt-submodulerecurse
@@ -19,27 +16,16 @@ export const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE]
19
16
  /** @type {(cmd: string[], options?: { cwd?: string }) => Promise<string>} */
20
17
  export const execGit = async (cmd, options) => {
21
18
  debugLog('Running git command:', cmd)
22
- const result = exec('git', [...NO_SUBMODULE_RECURSE, ...cmd], {
19
+ const result = await exec('git', [...NO_SUBMODULE_RECURSE, ...cmd], {
23
20
  nodeOptions: {
24
21
  env: options?.env,
25
22
  cwd: options?.cwd,
26
23
  },
27
24
  })
28
25
 
29
- let output = ''
30
- for await (const line of result) {
31
- if (GIT_CRLF_WARNING.test(line)) {
32
- debugLog('Stripped Git CRLF warning: %s', line)
33
- continue
34
- }
35
-
36
- output += line + '\n'
37
- }
38
- output = output.trimEnd()
39
-
40
26
  if (result.exitCode > 0) {
41
- throw new Error(output, { cause: result })
27
+ throw new Error(result.stderr.trimEnd(), { cause: result })
42
28
  }
43
29
 
44
- return output
30
+ return result.stdout.trimEnd()
45
31
  }
package/lib/figures.js CHANGED
@@ -1,9 +1,13 @@
1
- import { figures } from 'listr2'
1
+ import { blue, dim, green, red, yellow } from './colors.js'
2
2
 
3
- import { blue, red, yellow } from './colors.js'
3
+ export const wip = () => blue('')
4
4
 
5
- export const info = blue(figures.arrowRight)
5
+ export const done = () => green('✔')
6
6
 
7
- export const error = red(figures.cross)
7
+ export const info = () => blue('→')
8
8
 
9
- export const warning = yellow(figures.warning)
9
+ export const error = () => red('✖')
10
+
11
+ export const warning = () => yellow('⚠')
12
+
13
+ export const cancelled = () => dim('↓')
@@ -1,4 +1,5 @@
1
1
  import { createDebug } from './debug.js'
2
+ import { Signal } from './getAbortController.js'
2
3
  import { createTaskError } from './getSpawnedTask.js'
3
4
 
4
5
  const debugLog = createDebug('lint-staged:getFunctionTasks')
@@ -13,17 +14,25 @@ export const isFunctionTask = (commands) => typeof commands === 'object' && !Arr
13
14
  /**
14
15
  * Handles function configuration and pushes the tasks into the task array
15
16
  *
16
- * @param {object} command
17
- * @param {import('./getStagedFiles.js').StagedFile[]} files
17
+ * @param {object} options
18
+ * @param {AbortController} options.abortController
19
+ * @param {FunctionTask} options.command
20
+ * @param {boolean} options.continueOnError
21
+ * @param {import('./getStagedFiles.js').StagedFile[]} options.files
18
22
  * @throws {Error} If the function configuration is not valid
19
23
  */
20
- export const getFunctionTask = async (command, files) => {
21
- debugLog('Creating Listr tasks for function %o', command)
24
+ export const getFunctionTask = async ({ abortController, command, continueOnError, files }) => {
25
+ debugLog('Creating task for function %o', command)
22
26
 
23
27
  const task = async (ctx) => {
24
28
  try {
25
29
  await command.task(files.map((file) => file.filepath))
26
30
  } catch (e) {
31
+ if (continueOnError !== true) {
32
+ /** Other tasks should be killed */
33
+ abortController.abort(Signal.SIGKILL)
34
+ }
35
+
27
36
  throw createTaskError(command.title, e, ctx)
28
37
  }
29
38
  }
@@ -1,9 +1,9 @@
1
1
  import { parseArgsStringToArgv } from 'string-argv'
2
2
  import { exec } from 'tinyexec'
3
3
 
4
- import { dim, red } from './colors.js'
4
+ import { COLORS_ENABLED, dim, red } from './colors.js'
5
5
  import { createDebug } from './debug.js'
6
- import { error, info } from './figures.js'
6
+ import * as figures from './figures.js'
7
7
  import { Signal } from './getAbortController.js'
8
8
  import { killSubProcesses } from './killSubprocesses.js'
9
9
  import { getInitialState } from './state.js'
@@ -22,7 +22,9 @@ const debugLog = createDebug('lint-staged:getSpawnedTask')
22
22
  */
23
23
  const handleTaskOutput = (command, output, ctx, signal, errorResult) => {
24
24
  if (output) {
25
- const outputTitle = errorResult ? red(`${error} ${command}:`) : `${info} ${command}:`
25
+ const outputTitle = errorResult
26
+ ? red(`${figures.error()} ${command}:`)
27
+ : `${figures.info()} ${command}:`
26
28
  ctx.output.push([...(ctx.quiet ? [] : ['', outputTitle]), output].join('\n'))
27
29
  return
28
30
  }
@@ -32,11 +34,11 @@ const handleTaskOutput = (command, output, ctx, signal, errorResult) => {
32
34
  }
33
35
 
34
36
  if (signal === 'SIGINT') {
35
- ctx.output.push(red(`\n${error} Task interrupted: ${command}`))
37
+ ctx.output.push(red(`\n${figures.error()} Task interrupted: ${command}`))
36
38
  } else if (signal === 'SIGKILL') {
37
- ctx.output.push(red(`\n${error} Task killed: ${command}`))
39
+ ctx.output.push(red(`\n${figures.error()} Task killed: ${command}`))
38
40
  } else if (errorResult) {
39
- ctx.output.push(red(`\n${error} Task failed to spawn: ${command}`), signal)
41
+ ctx.output.push(red(`\n${figures.error()} Task failed to spawn: ${command}`), signal)
40
42
  }
41
43
  }
42
44
 
@@ -59,7 +61,6 @@ export const createTaskError = (command, result, ctx, signal = 'FAILED') => {
59
61
  *
60
62
  * @param {Object} options
61
63
  * @param {AbortController} options.abortController
62
- * @param {boolean} [options.color]
63
64
  * @param {string} options.command — Linter task
64
65
  * @param {string} [options.continueOnError]
65
66
  * @param {string} [options.cwd]
@@ -71,7 +72,6 @@ export const createTaskError = (command, result, ctx, signal = 'FAILED') => {
71
72
  */
72
73
  export const getSpawnedTask = ({
73
74
  abortController,
74
- color,
75
75
  command,
76
76
  continueOnError = false,
77
77
  cwd = process.cwd(),
@@ -90,7 +90,7 @@ export const getSpawnedTask = ({
90
90
  // Only use topLevelDir as CWD if we are using the git binary
91
91
  // e.g `npm` should run tasks in the actual CWD
92
92
  cwd: /^git(\.exe)?/i.test(cmd) ? topLevelDir : cwd,
93
- env: color ? { FORCE_COLOR: 'true' } : { NO_COLOR: 'true' },
93
+ env: COLORS_ENABLED ? { FORCE_COLOR: 'true' } : { NO_COLOR: 'true' },
94
94
  },
95
95
  }
96
96
 
@@ -5,11 +5,10 @@ import { configurationError } from './messages.js'
5
5
  const debugLog = createDebug('lint-staged:getSpawnedTasks')
6
6
 
7
7
  /**
8
- * Creates and returns an array of listr tasks which map to the given commands.
8
+ * Creates and returns an array of tasks which map to the given commands.
9
9
  *
10
10
  * @param {object} options
11
11
  * @param {AbortController} options.abortController
12
- * @param {boolean} [options.color]
13
12
  * @param {Array<string|Function>|string|Function} options.commands
14
13
  * @param {string} options.continueOnError
15
14
  * @param {string} options.cwd
@@ -19,7 +18,6 @@ const debugLog = createDebug('lint-staged:getSpawnedTasks')
19
18
  */
20
19
  export const getSpawnedTasks = async ({
21
20
  abortController,
22
- color,
23
21
  commands,
24
22
  continueOnError,
25
23
  cwd,
@@ -27,7 +25,7 @@ export const getSpawnedTasks = async ({
27
25
  topLevelDir,
28
26
  verbose,
29
27
  }) => {
30
- debugLog('Creating Listr tasks for commands %o', commands)
28
+ debugLog('Creating tasks for commands %o', commands)
31
29
  const cmdTasks = []
32
30
 
33
31
  const commandArray = Array.isArray(commands) ? commands : [commands]
@@ -58,7 +56,6 @@ export const getSpawnedTasks = async ({
58
56
 
59
57
  const task = getSpawnedTask({
60
58
  abortController,
61
- color,
62
59
  command,
63
60
  continueOnError,
64
61
  cwd,
@@ -68,7 +65,7 @@ export const getSpawnedTasks = async ({
68
65
  verbose,
69
66
  })
70
67
 
71
- cmdTasks.push({ title: command, command, task })
68
+ cmdTasks.push({ title: command, task })
72
69
  }
73
70
  }
74
71