source: imaps-frontend/node_modules/@eslint/eslintrc/lib/config-array/ignore-pattern.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/**
2 * @fileoverview `IgnorePattern` class.
3 *
4 * `IgnorePattern` class has the set of glob patterns and the base path.
5 *
6 * It provides two static methods.
7 *
8 * - `IgnorePattern.createDefaultIgnore(cwd)`
9 * Create the default predicate function.
10 * - `IgnorePattern.createIgnore(ignorePatterns)`
11 * Create the predicate function from multiple `IgnorePattern` objects.
12 *
13 * It provides two properties and a method.
14 *
15 * - `patterns`
16 * The glob patterns that ignore to lint.
17 * - `basePath`
18 * The base path of the glob patterns. If absolute paths existed in the
19 * glob patterns, those are handled as relative paths to the base path.
20 * - `getPatternsRelativeTo(basePath)`
21 * Get `patterns` as modified for a given base path. It modifies the
22 * absolute paths in the patterns as prepending the difference of two base
23 * paths.
24 *
25 * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
26 * `ignorePatterns` properties.
27 *
28 * @author Toru Nagashima <https://github.com/mysticatea>
29 */
30
31//------------------------------------------------------------------------------
32// Requirements
33//------------------------------------------------------------------------------
34
35import assert from "assert";
36import path from "path";
37import ignore from "ignore";
38import debugOrig from "debug";
39
40const debug = debugOrig("eslintrc:ignore-pattern");
41
42/** @typedef {ReturnType<import("ignore").default>} Ignore */
43
44//------------------------------------------------------------------------------
45// Helpers
46//------------------------------------------------------------------------------
47
48/**
49 * Get the path to the common ancestor directory of given paths.
50 * @param {string[]} sourcePaths The paths to calculate the common ancestor.
51 * @returns {string} The path to the common ancestor directory.
52 */
53function getCommonAncestorPath(sourcePaths) {
54 let result = sourcePaths[0];
55
56 for (let i = 1; i < sourcePaths.length; ++i) {
57 const a = result;
58 const b = sourcePaths[i];
59
60 // Set the shorter one (it's the common ancestor if one includes the other).
61 result = a.length < b.length ? a : b;
62
63 // Set the common ancestor.
64 for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
65 if (a[j] !== b[j]) {
66 result = a.slice(0, lastSepPos);
67 break;
68 }
69 if (a[j] === path.sep) {
70 lastSepPos = j;
71 }
72 }
73 }
74
75 let resolvedResult = result || path.sep;
76
77 // if Windows common ancestor is root of drive must have trailing slash to be absolute.
78 if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
79 resolvedResult += path.sep;
80 }
81 return resolvedResult;
82}
83
84/**
85 * Make relative path.
86 * @param {string} from The source path to get relative path.
87 * @param {string} to The destination path to get relative path.
88 * @returns {string} The relative path.
89 */
90function relative(from, to) {
91 const relPath = path.relative(from, to);
92
93 if (path.sep === "/") {
94 return relPath;
95 }
96 return relPath.split(path.sep).join("/");
97}
98
99/**
100 * Get the trailing slash if existed.
101 * @param {string} filePath The path to check.
102 * @returns {string} The trailing slash if existed.
103 */
104function dirSuffix(filePath) {
105 const isDir = (
106 filePath.endsWith(path.sep) ||
107 (process.platform === "win32" && filePath.endsWith("/"))
108 );
109
110 return isDir ? "/" : "";
111}
112
113const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
114const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
115
116//------------------------------------------------------------------------------
117// Public
118//------------------------------------------------------------------------------
119
120class IgnorePattern {
121
122 /**
123 * The default patterns.
124 * @type {string[]}
125 */
126 static get DefaultPatterns() {
127 return DefaultPatterns;
128 }
129
130 /**
131 * Create the default predicate function.
132 * @param {string} cwd The current working directory.
133 * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
134 * The preficate function.
135 * The first argument is an absolute path that is checked.
136 * The second argument is the flag to not ignore dotfiles.
137 * If the predicate function returned `true`, it means the path should be ignored.
138 */
139 static createDefaultIgnore(cwd) {
140 return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
141 }
142
143 /**
144 * Create the predicate function from multiple `IgnorePattern` objects.
145 * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
146 * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
147 * The preficate function.
148 * The first argument is an absolute path that is checked.
149 * The second argument is the flag to not ignore dotfiles.
150 * If the predicate function returned `true`, it means the path should be ignored.
151 */
152 static createIgnore(ignorePatterns) {
153 debug("Create with: %o", ignorePatterns);
154
155 const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
156 const patterns = [].concat(
157 ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
158 );
159 const ig = ignore({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);
160 const dotIg = ignore({ allowRelativePaths: true }).add(patterns);
161
162 debug(" processed: %o", { basePath, patterns });
163
164 return Object.assign(
165 (filePath, dot = false) => {
166 assert(path.isAbsolute(filePath), "'filePath' should be an absolute path.");
167 const relPathRaw = relative(basePath, filePath);
168 const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
169 const adoptedIg = dot ? dotIg : ig;
170 const result = relPath !== "" && adoptedIg.ignores(relPath);
171
172 debug("Check", { filePath, dot, relativePath: relPath, result });
173 return result;
174 },
175 { basePath, patterns }
176 );
177 }
178
179 /**
180 * Initialize a new `IgnorePattern` instance.
181 * @param {string[]} patterns The glob patterns that ignore to lint.
182 * @param {string} basePath The base path of `patterns`.
183 */
184 constructor(patterns, basePath) {
185 assert(path.isAbsolute(basePath), "'basePath' should be an absolute path.");
186
187 /**
188 * The glob patterns that ignore to lint.
189 * @type {string[]}
190 */
191 this.patterns = patterns;
192
193 /**
194 * The base path of `patterns`.
195 * @type {string}
196 */
197 this.basePath = basePath;
198
199 /**
200 * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
201 *
202 * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
203 * It's `false` as-is for `ignorePatterns` property in config files.
204 * @type {boolean}
205 */
206 this.loose = false;
207 }
208
209 /**
210 * Get `patterns` as modified for a given base path. It modifies the
211 * absolute paths in the patterns as prepending the difference of two base
212 * paths.
213 * @param {string} newBasePath The base path.
214 * @returns {string[]} Modifired patterns.
215 */
216 getPatternsRelativeTo(newBasePath) {
217 assert(path.isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
218 const { basePath, loose, patterns } = this;
219
220 if (newBasePath === basePath) {
221 return patterns;
222 }
223 const prefix = `/${relative(newBasePath, basePath)}`;
224
225 return patterns.map(pattern => {
226 const negative = pattern.startsWith("!");
227 const head = negative ? "!" : "";
228 const body = negative ? pattern.slice(1) : pattern;
229
230 if (body.startsWith("/") || body.startsWith("../")) {
231 return `${head}${prefix}${body}`;
232 }
233 return loose ? pattern : `${head}${prefix}/**/${body}`;
234 });
235 }
236}
237
238export { IgnorePattern };
Note: See TracBrowser for help on using the repository browser.