UNPKG

1.73 kBJavaScriptView Raw
1import path from 'node:path'
2
3import debug from 'debug'
4
5const debugLog = debug('lint-staged:groupFilesByConfig')
6
7export const groupFilesByConfig = async ({ configs, files, singleConfigMode }) => {
8 debugLog('Grouping %d files by %d configurations', files.length, Object.keys(configs).length)
9
10 const filesSet = new Set(files)
11 const filesByConfig = {}
12
13 /** Configs are sorted deepest first by `searchConfigs` */
14 for (const [filepath, config] of Object.entries(configs)) {
15 /** When passed an explicit config object via the Node.js API‚ or an explicit path, skip logic */
16 if (singleConfigMode) {
17 filesByConfig[filepath] = { config, files }
18 break
19 }
20
21 const dir = path.normalize(path.dirname(filepath))
22
23 /** Check if file is inside directory of the configuration file */
24 const isInsideDir = (file) => {
25 const relative = path.relative(dir, file)
26 return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
27 }
28
29 /** This config should match all files since it has a parent glob */
30 const includeAllFiles = Object.keys(config).some((glob) => glob.startsWith('..'))
31
32 const scopedFiles = new Set(includeAllFiles ? filesSet : undefined)
33
34 /**
35 * Without a parent glob, if file is inside the config file's directory,
36 * assign it to that configuration.
37 */
38 if (!includeAllFiles) {
39 filesSet.forEach((file) => {
40 if (isInsideDir(file)) {
41 scopedFiles.add(file)
42 }
43 })
44 }
45
46 /** Files should only match a single config */
47 scopedFiles.forEach((file) => {
48 filesSet.delete(file)
49 })
50
51 filesByConfig[filepath] = { config, files: Array.from(scopedFiles) }
52 }
53
54 return filesByConfig
55}