UNPKG

2.69 kBJavaScriptView Raw
1import process from 'node:process';
2import fs from 'node:fs';
3import path from 'node:path';
4import fastGlob from 'fast-glob';
5import gitIgnore from 'ignore';
6import slash from 'slash';
7import {toPath, isNegativePattern} from './utilities.js';
8
9const ignoreFilesGlobOptions = {
10 ignore: [
11 '**/node_modules',
12 '**/flow-typed',
13 '**/coverage',
14 '**/.git',
15 ],
16 absolute: true,
17 dot: true,
18};
19
20export const GITIGNORE_FILES_PATTERN = '**/.gitignore';
21
22const applyBaseToPattern = (pattern, base) => isNegativePattern(pattern)
23 ? '!' + path.posix.join(base, pattern.slice(1))
24 : path.posix.join(base, pattern);
25
26const parseIgnoreFile = (file, cwd) => {
27 const base = slash(path.relative(cwd, path.dirname(file.filePath)));
28
29 return file.content
30 .split(/\r?\n/)
31 .filter(line => line && !line.startsWith('#'))
32 .map(pattern => applyBaseToPattern(pattern, base));
33};
34
35const toRelativePath = (fileOrDirectory, cwd) => {
36 cwd = slash(cwd);
37 if (path.isAbsolute(fileOrDirectory)) {
38 if (slash(fileOrDirectory).startsWith(cwd)) {
39 return path.relative(cwd, fileOrDirectory);
40 }
41
42 throw new Error(`Path ${fileOrDirectory} is not in cwd ${cwd}`);
43 }
44
45 return fileOrDirectory;
46};
47
48const getIsIgnoredPredicate = (files, cwd) => {
49 const patterns = files.flatMap(file => parseIgnoreFile(file, cwd));
50 const ignores = gitIgnore().add(patterns);
51
52 return fileOrDirectory => {
53 fileOrDirectory = toPath(fileOrDirectory);
54 fileOrDirectory = toRelativePath(fileOrDirectory, cwd);
55 return fileOrDirectory ? ignores.ignores(slash(fileOrDirectory)) : false;
56 };
57};
58
59const normalizeOptions = (options = {}) => ({
60 cwd: toPath(options.cwd) || process.cwd(),
61 suppressErrors: Boolean(options.suppressErrors),
62});
63
64export const isIgnoredByIgnoreFiles = async (patterns, options) => {
65 const {cwd, suppressErrors} = normalizeOptions(options);
66
67 const paths = await fastGlob(patterns, {cwd, suppressErrors, ...ignoreFilesGlobOptions});
68
69 const files = await Promise.all(
70 paths.map(async filePath => ({
71 filePath,
72 content: await fs.promises.readFile(filePath, 'utf8'),
73 })),
74 );
75
76 return getIsIgnoredPredicate(files, cwd);
77};
78
79export const isIgnoredByIgnoreFilesSync = (patterns, options) => {
80 const {cwd, suppressErrors} = normalizeOptions(options);
81
82 const paths = fastGlob.sync(patterns, {cwd, suppressErrors, ...ignoreFilesGlobOptions});
83
84 const files = paths.map(filePath => ({
85 filePath,
86 content: fs.readFileSync(filePath, 'utf8'),
87 }));
88
89 return getIsIgnoredPredicate(files, cwd);
90};
91
92export const isGitIgnored = options => isIgnoredByIgnoreFiles(GITIGNORE_FILES_PATTERN, options);
93export const isGitIgnoredSync = options => isIgnoredByIgnoreFilesSync(GITIGNORE_FILES_PATTERN, options);