UNPKG

2.49 kBJavaScriptView Raw
1import { 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 */
31export const BRACES_REGEXP = /(?<![\\$])({)(?:(?!(?<!\\),|\.\.|\{|\}).)*?(?<!\\)(})/g
32
33/**
34 * @param {string} pattern
35 * @returns {string}
36 */
37const withoutIncorrectBraces = (pattern) => {
38 let output = `${pattern}`
39 let match = null
40
41 while ((match = BRACES_REGEXP.exec(pattern))) {
42 const fullMatch = match[0]
43 const withoutBraces = fullMatch.replace(/{/, '').replace(/}/, '')
44 output = output.replace(fullMatch, withoutBraces)
45 }
46
47 return output
48}
49
50/**
51 * Validate and remove incorrect brace expansions from glob pattern.
52 * For example `*.{js}` is incorrect because it doesn't contain a `,` or `..`,
53 * and will be reformatted as `*.js`.
54 *
55 * @param {string} pattern the glob pattern
56 * @param {*} logger
57 * @returns {string}
58 */
59export const validateBraces = (pattern, logger) => {
60 const fixedPattern = withoutIncorrectBraces(pattern)
61
62 if (fixedPattern !== pattern) {
63 logger.warn(incorrectBraces(pattern, fixedPattern))
64 }
65
66 return fixedPattern
67}