html-validate 8.24.0 → 8.24.1
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/dist/cjs/core.js +771 -749
- package/dist/cjs/core.js.map +1 -1
- package/dist/es/core.js +770 -748
- package/dist/es/core.js.map +1 -1
- package/package.json +8 -8
package/dist/cjs/core.js
CHANGED
|
@@ -252,139 +252,149 @@ function getDefaultExportFromCjs (x) {
|
|
|
252
252
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
var
|
|
256
|
-
|
|
257
|
-
&& !isSpecial(value)
|
|
258
|
-
};
|
|
255
|
+
var cjs;
|
|
256
|
+
var hasRequiredCjs;
|
|
259
257
|
|
|
260
|
-
function
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
function requireCjs () {
|
|
259
|
+
if (hasRequiredCjs) return cjs;
|
|
260
|
+
hasRequiredCjs = 1;
|
|
263
261
|
|
|
264
|
-
function
|
|
265
|
-
|
|
262
|
+
var isMergeableObject = function isMergeableObject(value) {
|
|
263
|
+
return isNonNullObject(value)
|
|
264
|
+
&& !isSpecial(value)
|
|
265
|
+
};
|
|
266
266
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
267
|
+
function isNonNullObject(value) {
|
|
268
|
+
return !!value && typeof value === 'object'
|
|
269
|
+
}
|
|
271
270
|
|
|
272
|
-
|
|
273
|
-
var
|
|
274
|
-
var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
|
|
271
|
+
function isSpecial(value) {
|
|
272
|
+
var stringValue = Object.prototype.toString.call(value);
|
|
275
273
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
274
|
+
return stringValue === '[object RegExp]'
|
|
275
|
+
|| stringValue === '[object Date]'
|
|
276
|
+
|| isReactElement(value)
|
|
277
|
+
}
|
|
279
278
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
|
|
280
|
+
var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
|
|
281
|
+
var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
|
|
283
282
|
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
: value
|
|
288
|
-
}
|
|
283
|
+
function isReactElement(value) {
|
|
284
|
+
return value.$$typeof === REACT_ELEMENT_TYPE
|
|
285
|
+
}
|
|
289
286
|
|
|
290
|
-
function
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
})
|
|
294
|
-
}
|
|
287
|
+
function emptyTarget(val) {
|
|
288
|
+
return Array.isArray(val) ? [] : {}
|
|
289
|
+
}
|
|
295
290
|
|
|
296
|
-
function
|
|
297
|
-
|
|
298
|
-
|
|
291
|
+
function cloneUnlessOtherwiseSpecified(value, options) {
|
|
292
|
+
return (options.clone !== false && options.isMergeableObject(value))
|
|
293
|
+
? deepmerge(emptyTarget(value), value, options)
|
|
294
|
+
: value
|
|
299
295
|
}
|
|
300
|
-
var customMerge = options.customMerge(key);
|
|
301
|
-
return typeof customMerge === 'function' ? customMerge : deepmerge
|
|
302
|
-
}
|
|
303
296
|
|
|
304
|
-
function
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return Object.propertyIsEnumerable.call(target, symbol)
|
|
297
|
+
function defaultArrayMerge(target, source, options) {
|
|
298
|
+
return target.concat(source).map(function(element) {
|
|
299
|
+
return cloneUnlessOtherwiseSpecified(element, options)
|
|
308
300
|
})
|
|
309
|
-
|
|
310
|
-
}
|
|
301
|
+
}
|
|
311
302
|
|
|
312
|
-
function
|
|
313
|
-
|
|
314
|
-
|
|
303
|
+
function getMergeFunction(key, options) {
|
|
304
|
+
if (!options.customMerge) {
|
|
305
|
+
return deepmerge
|
|
306
|
+
}
|
|
307
|
+
var customMerge = options.customMerge(key);
|
|
308
|
+
return typeof customMerge === 'function' ? customMerge : deepmerge
|
|
309
|
+
}
|
|
315
310
|
|
|
316
|
-
function
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
311
|
+
function getEnumerableOwnPropertySymbols(target) {
|
|
312
|
+
return Object.getOwnPropertySymbols
|
|
313
|
+
? Object.getOwnPropertySymbols(target).filter(function(symbol) {
|
|
314
|
+
return Object.propertyIsEnumerable.call(target, symbol)
|
|
315
|
+
})
|
|
316
|
+
: []
|
|
321
317
|
}
|
|
322
|
-
}
|
|
323
318
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
|
|
328
|
-
&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
|
|
329
|
-
}
|
|
319
|
+
function getKeys(target) {
|
|
320
|
+
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
|
|
321
|
+
}
|
|
330
322
|
|
|
331
|
-
function
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
323
|
+
function propertyIsOnObject(object, property) {
|
|
324
|
+
try {
|
|
325
|
+
return property in object
|
|
326
|
+
} catch(_) {
|
|
327
|
+
return false
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Protects from prototype poisoning and unexpected merging up the prototype chain.
|
|
332
|
+
function propertyIsUnsafe(target, key) {
|
|
333
|
+
return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
|
|
334
|
+
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
|
|
335
|
+
&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
|
|
337
336
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
337
|
+
|
|
338
|
+
function mergeObject(target, source, options) {
|
|
339
|
+
var destination = {};
|
|
340
|
+
if (options.isMergeableObject(target)) {
|
|
341
|
+
getKeys(target).forEach(function(key) {
|
|
342
|
+
destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
|
|
343
|
+
});
|
|
341
344
|
}
|
|
345
|
+
getKeys(source).forEach(function(key) {
|
|
346
|
+
if (propertyIsUnsafe(target, key)) {
|
|
347
|
+
return
|
|
348
|
+
}
|
|
342
349
|
|
|
343
|
-
|
|
344
|
-
|
|
350
|
+
if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
|
|
351
|
+
destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
|
|
352
|
+
} else {
|
|
353
|
+
destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
return destination
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function deepmerge(target, source, options) {
|
|
360
|
+
options = options || {};
|
|
361
|
+
options.arrayMerge = options.arrayMerge || defaultArrayMerge;
|
|
362
|
+
options.isMergeableObject = options.isMergeableObject || isMergeableObject;
|
|
363
|
+
// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
|
|
364
|
+
// implementations can use it. The caller may not replace it.
|
|
365
|
+
options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
|
|
366
|
+
|
|
367
|
+
var sourceIsArray = Array.isArray(source);
|
|
368
|
+
var targetIsArray = Array.isArray(target);
|
|
369
|
+
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
|
|
370
|
+
|
|
371
|
+
if (!sourceAndTargetTypesMatch) {
|
|
372
|
+
return cloneUnlessOtherwiseSpecified(source, options)
|
|
373
|
+
} else if (sourceIsArray) {
|
|
374
|
+
return options.arrayMerge(target, source, options)
|
|
345
375
|
} else {
|
|
346
|
-
|
|
376
|
+
return mergeObject(target, source, options)
|
|
347
377
|
}
|
|
348
|
-
});
|
|
349
|
-
return destination
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function deepmerge(target, source, options) {
|
|
353
|
-
options = options || {};
|
|
354
|
-
options.arrayMerge = options.arrayMerge || defaultArrayMerge;
|
|
355
|
-
options.isMergeableObject = options.isMergeableObject || isMergeableObject;
|
|
356
|
-
// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
|
|
357
|
-
// implementations can use it. The caller may not replace it.
|
|
358
|
-
options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
|
|
359
|
-
|
|
360
|
-
var sourceIsArray = Array.isArray(source);
|
|
361
|
-
var targetIsArray = Array.isArray(target);
|
|
362
|
-
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
|
|
363
|
-
|
|
364
|
-
if (!sourceAndTargetTypesMatch) {
|
|
365
|
-
return cloneUnlessOtherwiseSpecified(source, options)
|
|
366
|
-
} else if (sourceIsArray) {
|
|
367
|
-
return options.arrayMerge(target, source, options)
|
|
368
|
-
} else {
|
|
369
|
-
return mergeObject(target, source, options)
|
|
370
378
|
}
|
|
371
|
-
}
|
|
372
379
|
|
|
373
|
-
deepmerge.all = function deepmergeAll(array, options) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
380
|
+
deepmerge.all = function deepmergeAll(array, options) {
|
|
381
|
+
if (!Array.isArray(array)) {
|
|
382
|
+
throw new Error('first argument should be an array')
|
|
383
|
+
}
|
|
377
384
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
};
|
|
385
|
+
return array.reduce(function(prev, next) {
|
|
386
|
+
return deepmerge(prev, next, options)
|
|
387
|
+
}, {})
|
|
388
|
+
};
|
|
382
389
|
|
|
383
|
-
var deepmerge_1 = deepmerge;
|
|
390
|
+
var deepmerge_1 = deepmerge;
|
|
384
391
|
|
|
385
|
-
|
|
392
|
+
cjs = deepmerge_1;
|
|
393
|
+
return cjs;
|
|
394
|
+
}
|
|
386
395
|
|
|
387
|
-
var
|
|
396
|
+
var cjsExports = /*@__PURE__*/ requireCjs();
|
|
397
|
+
var deepmerge = /*@__PURE__*/getDefaultExportFromCjs(cjsExports);
|
|
388
398
|
|
|
389
399
|
function stringify(value) {
|
|
390
400
|
if (typeof value === "string") {
|
|
@@ -1217,7 +1227,7 @@ class MetaTable {
|
|
|
1217
1227
|
*/
|
|
1218
1228
|
extendValidationSchema(patch) {
|
|
1219
1229
|
if (patch.properties) {
|
|
1220
|
-
this.schema = deepmerge
|
|
1230
|
+
this.schema = deepmerge(this.schema, {
|
|
1221
1231
|
patternProperties: {
|
|
1222
1232
|
"^[^$].*$": {
|
|
1223
1233
|
properties: patch.properties
|
|
@@ -1226,7 +1236,7 @@ class MetaTable {
|
|
|
1226
1236
|
});
|
|
1227
1237
|
}
|
|
1228
1238
|
if (patch.definitions) {
|
|
1229
|
-
this.schema = deepmerge
|
|
1239
|
+
this.schema = deepmerge(this.schema, {
|
|
1230
1240
|
definitions: patch.definitions
|
|
1231
1241
|
});
|
|
1232
1242
|
}
|
|
@@ -1364,7 +1374,7 @@ class MetaTable {
|
|
|
1364
1374
|
}
|
|
1365
1375
|
}
|
|
1366
1376
|
mergeElement(a, b) {
|
|
1367
|
-
const merged = deepmerge
|
|
1377
|
+
const merged = deepmerge(a, b, { arrayMerge: overwriteMerge$1 });
|
|
1368
1378
|
const filteredAttrs = Object.entries(
|
|
1369
1379
|
merged.attributes
|
|
1370
1380
|
).filter(([, attr]) => {
|
|
@@ -1980,7 +1990,7 @@ const table = {
|
|
|
1980
1990
|
"nth-child": nthChild,
|
|
1981
1991
|
scope
|
|
1982
1992
|
};
|
|
1983
|
-
function factory
|
|
1993
|
+
function factory(name, context) {
|
|
1984
1994
|
const fn = table[name];
|
|
1985
1995
|
if (fn) {
|
|
1986
1996
|
return fn.bind(context);
|
|
@@ -2079,7 +2089,7 @@ function isQuotationMark(ch) {
|
|
|
2079
2089
|
function isPseudoElement(ch, buffer) {
|
|
2080
2090
|
return ch === ":" && buffer === ":";
|
|
2081
2091
|
}
|
|
2082
|
-
function* splitPattern
|
|
2092
|
+
function* splitPattern(pattern) {
|
|
2083
2093
|
if (pattern === "") {
|
|
2084
2094
|
return;
|
|
2085
2095
|
}
|
|
@@ -2173,7 +2183,7 @@ class PseudoClassMatcher extends Matcher {
|
|
|
2173
2183
|
this.args = args;
|
|
2174
2184
|
}
|
|
2175
2185
|
match(node, context) {
|
|
2176
|
-
const fn = factory
|
|
2186
|
+
const fn = factory(this.name, context);
|
|
2177
2187
|
return fn(node, this.args);
|
|
2178
2188
|
}
|
|
2179
2189
|
}
|
|
@@ -2187,7 +2197,7 @@ class Pattern {
|
|
|
2187
2197
|
this.selector = pattern;
|
|
2188
2198
|
this.combinator = parseCombinator(match.shift(), pattern);
|
|
2189
2199
|
this.tagName = match.shift() || "*";
|
|
2190
|
-
this.pattern = Array.from(splitPattern
|
|
2200
|
+
this.pattern = Array.from(splitPattern(match[0]), (it) => this.createMatcher(it));
|
|
2191
2201
|
}
|
|
2192
2202
|
match(node, context) {
|
|
2193
2203
|
return node.is(this.tagName) && this.pattern.every((cur) => cur.match(node, context));
|
|
@@ -4514,6 +4524,9 @@ class AttrQuotes extends Rule {
|
|
|
4514
4524
|
}
|
|
4515
4525
|
setup() {
|
|
4516
4526
|
this.on("attr", (event) => {
|
|
4527
|
+
if (event.originalAttribute) {
|
|
4528
|
+
return;
|
|
4529
|
+
}
|
|
4517
4530
|
if (event.value === null) {
|
|
4518
4531
|
return;
|
|
4519
4532
|
}
|
|
@@ -10839,9 +10852,9 @@ function overwriteMerge(a, b) {
|
|
|
10839
10852
|
return b;
|
|
10840
10853
|
}
|
|
10841
10854
|
function mergeInternal(base, rhs) {
|
|
10842
|
-
const dst = deepmerge
|
|
10855
|
+
const dst = deepmerge(base, { ...rhs, rules: {} });
|
|
10843
10856
|
if (rhs.rules) {
|
|
10844
|
-
dst.rules = deepmerge
|
|
10857
|
+
dst.rules = deepmerge(dst.rules, rhs.rules, { arrayMerge: overwriteMerge });
|
|
10845
10858
|
}
|
|
10846
10859
|
const root = Boolean(base.root) || Boolean(rhs.root);
|
|
10847
10860
|
if (root) {
|
|
@@ -12868,651 +12881,660 @@ class HtmlValidate {
|
|
|
12868
12881
|
}
|
|
12869
12882
|
|
|
12870
12883
|
const name = "html-validate";
|
|
12871
|
-
const version = "8.24.
|
|
12884
|
+
const version = "8.24.1";
|
|
12872
12885
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
12873
12886
|
|
|
12874
12887
|
function definePlugin(plugin) {
|
|
12875
12888
|
return plugin;
|
|
12876
12889
|
}
|
|
12877
12890
|
|
|
12878
|
-
|
|
12879
|
-
|
|
12880
|
-
return Array.isArray(subject)
|
|
12881
|
-
? subject
|
|
12882
|
-
: [subject]
|
|
12883
|
-
}
|
|
12884
|
-
|
|
12885
|
-
const EMPTY = '';
|
|
12886
|
-
const SPACE = ' ';
|
|
12887
|
-
const ESCAPE = '\\';
|
|
12888
|
-
const REGEX_TEST_BLANK_LINE = /^\s+$/;
|
|
12889
|
-
const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
|
|
12890
|
-
const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
|
|
12891
|
-
const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
|
|
12892
|
-
const REGEX_SPLITALL_CRLF = /\r?\n/g;
|
|
12893
|
-
// /foo,
|
|
12894
|
-
// ./foo,
|
|
12895
|
-
// ../foo,
|
|
12896
|
-
// .
|
|
12897
|
-
// ..
|
|
12898
|
-
const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/;
|
|
12899
|
-
|
|
12900
|
-
const SLASH = '/';
|
|
12901
|
-
|
|
12902
|
-
// Do not use ternary expression here, since "istanbul ignore next" is buggy
|
|
12903
|
-
let TMP_KEY_IGNORE = 'node-ignore';
|
|
12904
|
-
/* istanbul ignore else */
|
|
12905
|
-
if (typeof Symbol !== 'undefined') {
|
|
12906
|
-
TMP_KEY_IGNORE = Symbol.for('node-ignore');
|
|
12907
|
-
}
|
|
12908
|
-
const KEY_IGNORE = TMP_KEY_IGNORE;
|
|
12909
|
-
|
|
12910
|
-
const define = (object, key, value) =>
|
|
12911
|
-
Object.defineProperty(object, key, {value});
|
|
12912
|
-
|
|
12913
|
-
const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
|
|
12914
|
-
|
|
12915
|
-
const RETURN_FALSE = () => false;
|
|
12916
|
-
|
|
12917
|
-
// Sanitize the range of a regular expression
|
|
12918
|
-
// The cases are complicated, see test cases for details
|
|
12919
|
-
const sanitizeRange = range => range.replace(
|
|
12920
|
-
REGEX_REGEXP_RANGE,
|
|
12921
|
-
(match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)
|
|
12922
|
-
? match
|
|
12923
|
-
// Invalid range (out of order) which is ok for gitignore rules but
|
|
12924
|
-
// fatal for JavaScript regular expression, so eliminate it.
|
|
12925
|
-
: EMPTY
|
|
12926
|
-
);
|
|
12927
|
-
|
|
12928
|
-
// See fixtures #59
|
|
12929
|
-
const cleanRangeBackSlash = slashes => {
|
|
12930
|
-
const {length} = slashes;
|
|
12931
|
-
return slashes.slice(0, length - length % 2)
|
|
12932
|
-
};
|
|
12933
|
-
|
|
12934
|
-
// > If the pattern ends with a slash,
|
|
12935
|
-
// > it is removed for the purpose of the following description,
|
|
12936
|
-
// > but it would only find a match with a directory.
|
|
12937
|
-
// > In other words, foo/ will match a directory foo and paths underneath it,
|
|
12938
|
-
// > but will not match a regular file or a symbolic link foo
|
|
12939
|
-
// > (this is consistent with the way how pathspec works in general in Git).
|
|
12940
|
-
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
|
|
12941
|
-
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
|
|
12942
|
-
// you could use option `mark: true` with `glob`
|
|
12943
|
-
|
|
12944
|
-
// '`foo/`' should not continue with the '`..`'
|
|
12945
|
-
const REPLACERS = [
|
|
12946
|
-
|
|
12947
|
-
[
|
|
12948
|
-
// remove BOM
|
|
12949
|
-
// TODO:
|
|
12950
|
-
// Other similar zero-width characters?
|
|
12951
|
-
/^\uFEFF/,
|
|
12952
|
-
() => EMPTY
|
|
12953
|
-
],
|
|
12954
|
-
|
|
12955
|
-
// > Trailing spaces are ignored unless they are quoted with backslash ("\")
|
|
12956
|
-
[
|
|
12957
|
-
// (a\ ) -> (a )
|
|
12958
|
-
// (a ) -> (a)
|
|
12959
|
-
// (a ) -> (a)
|
|
12960
|
-
// (a \ ) -> (a )
|
|
12961
|
-
/((?:\\\\)*?)(\\?\s+)$/,
|
|
12962
|
-
(_, m1, m2) => m1 + (
|
|
12963
|
-
m2.indexOf('\\') === 0
|
|
12964
|
-
? SPACE
|
|
12965
|
-
: EMPTY
|
|
12966
|
-
)
|
|
12967
|
-
],
|
|
12968
|
-
|
|
12969
|
-
// replace (\ ) with ' '
|
|
12970
|
-
// (\ ) -> ' '
|
|
12971
|
-
// (\\ ) -> '\\ '
|
|
12972
|
-
// (\\\ ) -> '\\ '
|
|
12973
|
-
[
|
|
12974
|
-
/(\\+?)\s/g,
|
|
12975
|
-
(_, m1) => {
|
|
12976
|
-
const {length} = m1;
|
|
12977
|
-
return m1.slice(0, length - length % 2) + SPACE
|
|
12978
|
-
}
|
|
12979
|
-
],
|
|
12980
|
-
|
|
12981
|
-
// Escape metacharacters
|
|
12982
|
-
// which is written down by users but means special for regular expressions.
|
|
12983
|
-
|
|
12984
|
-
// > There are 12 characters with special meanings:
|
|
12985
|
-
// > - the backslash \,
|
|
12986
|
-
// > - the caret ^,
|
|
12987
|
-
// > - the dollar sign $,
|
|
12988
|
-
// > - the period or dot .,
|
|
12989
|
-
// > - the vertical bar or pipe symbol |,
|
|
12990
|
-
// > - the question mark ?,
|
|
12991
|
-
// > - the asterisk or star *,
|
|
12992
|
-
// > - the plus sign +,
|
|
12993
|
-
// > - the opening parenthesis (,
|
|
12994
|
-
// > - the closing parenthesis ),
|
|
12995
|
-
// > - and the opening square bracket [,
|
|
12996
|
-
// > - the opening curly brace {,
|
|
12997
|
-
// > These special characters are often called "metacharacters".
|
|
12998
|
-
[
|
|
12999
|
-
/[\\$.|*+(){^]/g,
|
|
13000
|
-
match => `\\${match}`
|
|
13001
|
-
],
|
|
13002
|
-
|
|
13003
|
-
[
|
|
13004
|
-
// > a question mark (?) matches a single character
|
|
13005
|
-
/(?!\\)\?/g,
|
|
13006
|
-
() => '[^/]'
|
|
13007
|
-
],
|
|
13008
|
-
|
|
13009
|
-
// leading slash
|
|
13010
|
-
[
|
|
13011
|
-
|
|
13012
|
-
// > A leading slash matches the beginning of the pathname.
|
|
13013
|
-
// > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
|
|
13014
|
-
// A leading slash matches the beginning of the pathname
|
|
13015
|
-
/^\//,
|
|
13016
|
-
() => '^'
|
|
13017
|
-
],
|
|
13018
|
-
|
|
13019
|
-
// replace special metacharacter slash after the leading slash
|
|
13020
|
-
[
|
|
13021
|
-
/\//g,
|
|
13022
|
-
() => '\\/'
|
|
13023
|
-
],
|
|
13024
|
-
|
|
13025
|
-
[
|
|
13026
|
-
// > A leading "**" followed by a slash means match in all directories.
|
|
13027
|
-
// > For example, "**/foo" matches file or directory "foo" anywhere,
|
|
13028
|
-
// > the same as pattern "foo".
|
|
13029
|
-
// > "**/foo/bar" matches file or directory "bar" anywhere that is directly
|
|
13030
|
-
// > under directory "foo".
|
|
13031
|
-
// Notice that the '*'s have been replaced as '\\*'
|
|
13032
|
-
/^\^*\\\*\\\*\\\//,
|
|
13033
|
-
|
|
13034
|
-
// '**/foo' <-> 'foo'
|
|
13035
|
-
() => '^(?:.*\\/)?'
|
|
13036
|
-
],
|
|
13037
|
-
|
|
13038
|
-
// starting
|
|
13039
|
-
[
|
|
13040
|
-
// there will be no leading '/'
|
|
13041
|
-
// (which has been replaced by section "leading slash")
|
|
13042
|
-
// If starts with '**', adding a '^' to the regular expression also works
|
|
13043
|
-
/^(?=[^^])/,
|
|
13044
|
-
function startingReplacer () {
|
|
13045
|
-
// If has a slash `/` at the beginning or middle
|
|
13046
|
-
return !/\/(?!$)/.test(this)
|
|
13047
|
-
// > Prior to 2.22.1
|
|
13048
|
-
// > If the pattern does not contain a slash /,
|
|
13049
|
-
// > Git treats it as a shell glob pattern
|
|
13050
|
-
// Actually, if there is only a trailing slash,
|
|
13051
|
-
// git also treats it as a shell glob pattern
|
|
13052
|
-
|
|
13053
|
-
// After 2.22.1 (compatible but clearer)
|
|
13054
|
-
// > If there is a separator at the beginning or middle (or both)
|
|
13055
|
-
// > of the pattern, then the pattern is relative to the directory
|
|
13056
|
-
// > level of the particular .gitignore file itself.
|
|
13057
|
-
// > Otherwise the pattern may also match at any level below
|
|
13058
|
-
// > the .gitignore level.
|
|
13059
|
-
? '(?:^|\\/)'
|
|
13060
|
-
|
|
13061
|
-
// > Otherwise, Git treats the pattern as a shell glob suitable for
|
|
13062
|
-
// > consumption by fnmatch(3)
|
|
13063
|
-
: '^'
|
|
13064
|
-
}
|
|
13065
|
-
],
|
|
13066
|
-
|
|
13067
|
-
// two globstars
|
|
13068
|
-
[
|
|
13069
|
-
// Use lookahead assertions so that we could match more than one `'/**'`
|
|
13070
|
-
/\\\/\\\*\\\*(?=\\\/|$)/g,
|
|
13071
|
-
|
|
13072
|
-
// Zero, one or several directories
|
|
13073
|
-
// should not use '*', or it will be replaced by the next replacer
|
|
13074
|
-
|
|
13075
|
-
// Check if it is not the last `'/**'`
|
|
13076
|
-
(_, index, str) => index + 6 < str.length
|
|
13077
|
-
|
|
13078
|
-
// case: /**/
|
|
13079
|
-
// > A slash followed by two consecutive asterisks then a slash matches
|
|
13080
|
-
// > zero or more directories.
|
|
13081
|
-
// > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
|
|
13082
|
-
// '/**/'
|
|
13083
|
-
? '(?:\\/[^\\/]+)*'
|
|
13084
|
-
|
|
13085
|
-
// case: /**
|
|
13086
|
-
// > A trailing `"/**"` matches everything inside.
|
|
13087
|
-
|
|
13088
|
-
// #21: everything inside but it should not include the current folder
|
|
13089
|
-
: '\\/.+'
|
|
13090
|
-
],
|
|
13091
|
-
|
|
13092
|
-
// normal intermediate wildcards
|
|
13093
|
-
[
|
|
13094
|
-
// Never replace escaped '*'
|
|
13095
|
-
// ignore rule '\*' will match the path '*'
|
|
13096
|
-
|
|
13097
|
-
// 'abc.*/' -> go
|
|
13098
|
-
// 'abc.*' -> skip this rule,
|
|
13099
|
-
// coz trailing single wildcard will be handed by [trailing wildcard]
|
|
13100
|
-
/(^|[^\\]+)(\\\*)+(?=.+)/g,
|
|
13101
|
-
|
|
13102
|
-
// '*.js' matches '.js'
|
|
13103
|
-
// '*.js' doesn't match 'abc'
|
|
13104
|
-
(_, p1, p2) => {
|
|
13105
|
-
// 1.
|
|
13106
|
-
// > An asterisk "*" matches anything except a slash.
|
|
13107
|
-
// 2.
|
|
13108
|
-
// > Other consecutive asterisks are considered regular asterisks
|
|
13109
|
-
// > and will match according to the previous rules.
|
|
13110
|
-
const unescaped = p2.replace(/\\\*/g, '[^\\/]*');
|
|
13111
|
-
return p1 + unescaped
|
|
13112
|
-
}
|
|
13113
|
-
],
|
|
13114
|
-
|
|
13115
|
-
[
|
|
13116
|
-
// unescape, revert step 3 except for back slash
|
|
13117
|
-
// For example, if a user escape a '\\*',
|
|
13118
|
-
// after step 3, the result will be '\\\\\\*'
|
|
13119
|
-
/\\\\\\(?=[$.|*+(){^])/g,
|
|
13120
|
-
() => ESCAPE
|
|
13121
|
-
],
|
|
13122
|
-
|
|
13123
|
-
[
|
|
13124
|
-
// '\\\\' -> '\\'
|
|
13125
|
-
/\\\\/g,
|
|
13126
|
-
() => ESCAPE
|
|
13127
|
-
],
|
|
13128
|
-
|
|
13129
|
-
[
|
|
13130
|
-
// > The range notation, e.g. [a-zA-Z],
|
|
13131
|
-
// > can be used to match one of the characters in a range.
|
|
13132
|
-
|
|
13133
|
-
// `\` is escaped by step 3
|
|
13134
|
-
/(\\)?\[([^\]/]*?)(\\*)($|\])/g,
|
|
13135
|
-
(match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE
|
|
13136
|
-
// '\\[bar]' -> '\\\\[bar\\]'
|
|
13137
|
-
? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`
|
|
13138
|
-
: close === ']'
|
|
13139
|
-
? endEscape.length % 2 === 0
|
|
13140
|
-
// A normal case, and it is a range notation
|
|
13141
|
-
// '[bar]'
|
|
13142
|
-
// '[bar\\\\]'
|
|
13143
|
-
? `[${sanitizeRange(range)}${endEscape}]`
|
|
13144
|
-
// Invalid range notaton
|
|
13145
|
-
// '[bar\\]' -> '[bar\\\\]'
|
|
13146
|
-
: '[]'
|
|
13147
|
-
: '[]'
|
|
13148
|
-
],
|
|
13149
|
-
|
|
13150
|
-
// ending
|
|
13151
|
-
[
|
|
13152
|
-
// 'js' will not match 'js.'
|
|
13153
|
-
// 'ab' will not match 'abc'
|
|
13154
|
-
/(?:[^*])$/,
|
|
13155
|
-
|
|
13156
|
-
// WTF!
|
|
13157
|
-
// https://git-scm.com/docs/gitignore
|
|
13158
|
-
// changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
|
|
13159
|
-
// which re-fixes #24, #38
|
|
13160
|
-
|
|
13161
|
-
// > If there is a separator at the end of the pattern then the pattern
|
|
13162
|
-
// > will only match directories, otherwise the pattern can match both
|
|
13163
|
-
// > files and directories.
|
|
13164
|
-
|
|
13165
|
-
// 'js*' will not match 'a.js'
|
|
13166
|
-
// 'js/' will not match 'a.js'
|
|
13167
|
-
// 'js' will match 'a.js' and 'a.js/'
|
|
13168
|
-
match => /\/$/.test(match)
|
|
13169
|
-
// foo/ will not match 'foo'
|
|
13170
|
-
? `${match}$`
|
|
13171
|
-
// foo matches 'foo' and 'foo/'
|
|
13172
|
-
: `${match}(?=$|\\/$)`
|
|
13173
|
-
],
|
|
13174
|
-
|
|
13175
|
-
// trailing wildcard
|
|
13176
|
-
[
|
|
13177
|
-
/(\^|\\\/)?\\\*$/,
|
|
13178
|
-
(_, p1) => {
|
|
13179
|
-
const prefix = p1
|
|
13180
|
-
// '\^':
|
|
13181
|
-
// '/*' does not match EMPTY
|
|
13182
|
-
// '/*' does not match everything
|
|
13183
|
-
|
|
13184
|
-
// '\\\/':
|
|
13185
|
-
// 'abc/*' does not match 'abc/'
|
|
13186
|
-
? `${p1}[^/]+`
|
|
13187
|
-
|
|
13188
|
-
// 'a*' matches 'a'
|
|
13189
|
-
// 'a*' matches 'aa'
|
|
13190
|
-
: '[^/]*';
|
|
13191
|
-
|
|
13192
|
-
return `${prefix}(?=$|\\/$)`
|
|
13193
|
-
}
|
|
13194
|
-
],
|
|
13195
|
-
];
|
|
13196
|
-
|
|
13197
|
-
// A simple cache, because an ignore rule only has only one certain meaning
|
|
13198
|
-
const regexCache = Object.create(null);
|
|
13199
|
-
|
|
13200
|
-
// @param {pattern}
|
|
13201
|
-
const makeRegex = (pattern, ignoreCase) => {
|
|
13202
|
-
let source = regexCache[pattern];
|
|
13203
|
-
|
|
13204
|
-
if (!source) {
|
|
13205
|
-
source = REPLACERS.reduce(
|
|
13206
|
-
(prev, [matcher, replacer]) =>
|
|
13207
|
-
prev.replace(matcher, replacer.bind(pattern)),
|
|
13208
|
-
pattern
|
|
13209
|
-
);
|
|
13210
|
-
regexCache[pattern] = source;
|
|
13211
|
-
}
|
|
13212
|
-
|
|
13213
|
-
return ignoreCase
|
|
13214
|
-
? new RegExp(source, 'i')
|
|
13215
|
-
: new RegExp(source)
|
|
13216
|
-
};
|
|
13217
|
-
|
|
13218
|
-
const isString = subject => typeof subject === 'string';
|
|
13219
|
-
|
|
13220
|
-
// > A blank line matches no files, so it can serve as a separator for readability.
|
|
13221
|
-
const checkPattern = pattern => pattern
|
|
13222
|
-
&& isString(pattern)
|
|
13223
|
-
&& !REGEX_TEST_BLANK_LINE.test(pattern)
|
|
13224
|
-
&& !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
|
|
13225
|
-
|
|
13226
|
-
// > A line starting with # serves as a comment.
|
|
13227
|
-
&& pattern.indexOf('#') !== 0;
|
|
13228
|
-
|
|
13229
|
-
const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF);
|
|
13230
|
-
|
|
13231
|
-
class IgnoreRule {
|
|
13232
|
-
constructor (
|
|
13233
|
-
origin,
|
|
13234
|
-
pattern,
|
|
13235
|
-
negative,
|
|
13236
|
-
regex
|
|
13237
|
-
) {
|
|
13238
|
-
this.origin = origin;
|
|
13239
|
-
this.pattern = pattern;
|
|
13240
|
-
this.negative = negative;
|
|
13241
|
-
this.regex = regex;
|
|
13242
|
-
}
|
|
13243
|
-
}
|
|
13244
|
-
|
|
13245
|
-
const createRule = (pattern, ignoreCase) => {
|
|
13246
|
-
const origin = pattern;
|
|
13247
|
-
let negative = false;
|
|
13248
|
-
|
|
13249
|
-
// > An optional prefix "!" which negates the pattern;
|
|
13250
|
-
if (pattern.indexOf('!') === 0) {
|
|
13251
|
-
negative = true;
|
|
13252
|
-
pattern = pattern.substr(1);
|
|
13253
|
-
}
|
|
13254
|
-
|
|
13255
|
-
pattern = pattern
|
|
13256
|
-
// > Put a backslash ("\") in front of the first "!" for patterns that
|
|
13257
|
-
// > begin with a literal "!", for example, `"\!important!.txt"`.
|
|
13258
|
-
.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')
|
|
13259
|
-
// > Put a backslash ("\") in front of the first hash for patterns that
|
|
13260
|
-
// > begin with a hash.
|
|
13261
|
-
.replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#');
|
|
13262
|
-
|
|
13263
|
-
const regex = makeRegex(pattern, ignoreCase);
|
|
13264
|
-
|
|
13265
|
-
return new IgnoreRule(
|
|
13266
|
-
origin,
|
|
13267
|
-
pattern,
|
|
13268
|
-
negative,
|
|
13269
|
-
regex
|
|
13270
|
-
)
|
|
13271
|
-
};
|
|
13272
|
-
|
|
13273
|
-
const throwError = (message, Ctor) => {
|
|
13274
|
-
throw new Ctor(message)
|
|
13275
|
-
};
|
|
13276
|
-
|
|
13277
|
-
const checkPath = (path, originalPath, doThrow) => {
|
|
13278
|
-
if (!isString(path)) {
|
|
13279
|
-
return doThrow(
|
|
13280
|
-
`path must be a string, but got \`${originalPath}\``,
|
|
13281
|
-
TypeError
|
|
13282
|
-
)
|
|
13283
|
-
}
|
|
13284
|
-
|
|
13285
|
-
// We don't know if we should ignore EMPTY, so throw
|
|
13286
|
-
if (!path) {
|
|
13287
|
-
return doThrow(`path must not be empty`, TypeError)
|
|
13288
|
-
}
|
|
13289
|
-
|
|
13290
|
-
// Check if it is a relative path
|
|
13291
|
-
if (checkPath.isNotRelative(path)) {
|
|
13292
|
-
const r = '`path.relative()`d';
|
|
13293
|
-
return doThrow(
|
|
13294
|
-
`path should be a ${r} string, but got "${originalPath}"`,
|
|
13295
|
-
RangeError
|
|
13296
|
-
)
|
|
13297
|
-
}
|
|
13298
|
-
|
|
13299
|
-
return true
|
|
13300
|
-
};
|
|
13301
|
-
|
|
13302
|
-
const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path);
|
|
13303
|
-
|
|
13304
|
-
checkPath.isNotRelative = isNotRelative;
|
|
13305
|
-
checkPath.convert = p => p;
|
|
13306
|
-
|
|
13307
|
-
class Ignore {
|
|
13308
|
-
constructor ({
|
|
13309
|
-
ignorecase = true,
|
|
13310
|
-
ignoreCase = ignorecase,
|
|
13311
|
-
allowRelativePaths = false
|
|
13312
|
-
} = {}) {
|
|
13313
|
-
define(this, KEY_IGNORE, true);
|
|
13314
|
-
|
|
13315
|
-
this._rules = [];
|
|
13316
|
-
this._ignoreCase = ignoreCase;
|
|
13317
|
-
this._allowRelativePaths = allowRelativePaths;
|
|
13318
|
-
this._initCache();
|
|
13319
|
-
}
|
|
13320
|
-
|
|
13321
|
-
_initCache () {
|
|
13322
|
-
this._ignoreCache = Object.create(null);
|
|
13323
|
-
this._testCache = Object.create(null);
|
|
13324
|
-
}
|
|
13325
|
-
|
|
13326
|
-
_addPattern (pattern) {
|
|
13327
|
-
// #32
|
|
13328
|
-
if (pattern && pattern[KEY_IGNORE]) {
|
|
13329
|
-
this._rules = this._rules.concat(pattern._rules);
|
|
13330
|
-
this._added = true;
|
|
13331
|
-
return
|
|
13332
|
-
}
|
|
13333
|
-
|
|
13334
|
-
if (checkPattern(pattern)) {
|
|
13335
|
-
const rule = createRule(pattern, this._ignoreCase);
|
|
13336
|
-
this._added = true;
|
|
13337
|
-
this._rules.push(rule);
|
|
13338
|
-
}
|
|
13339
|
-
}
|
|
13340
|
-
|
|
13341
|
-
// @param {Array<string> | string | Ignore} pattern
|
|
13342
|
-
add (pattern) {
|
|
13343
|
-
this._added = false;
|
|
13344
|
-
|
|
13345
|
-
makeArray(
|
|
13346
|
-
isString(pattern)
|
|
13347
|
-
? splitPattern(pattern)
|
|
13348
|
-
: pattern
|
|
13349
|
-
).forEach(this._addPattern, this);
|
|
13350
|
-
|
|
13351
|
-
// Some rules have just added to the ignore,
|
|
13352
|
-
// making the behavior changed.
|
|
13353
|
-
if (this._added) {
|
|
13354
|
-
this._initCache();
|
|
13355
|
-
}
|
|
13356
|
-
|
|
13357
|
-
return this
|
|
13358
|
-
}
|
|
12891
|
+
var ignore$1;
|
|
12892
|
+
var hasRequiredIgnore;
|
|
13359
12893
|
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
// 1 | TESTIF | SKIP | TEST | X
|
|
13370
|
-
|
|
13371
|
-
// - SKIP: always skip
|
|
13372
|
-
// - TEST: always test
|
|
13373
|
-
// - TESTIF: only test if checkUnignored
|
|
13374
|
-
// - X: that never happen
|
|
13375
|
-
|
|
13376
|
-
// @param {boolean} whether should check if the path is unignored,
|
|
13377
|
-
// setting `checkUnignored` to `false` could reduce additional
|
|
13378
|
-
// path matching.
|
|
13379
|
-
|
|
13380
|
-
// @returns {TestResult} true if a file is ignored
|
|
13381
|
-
_testOne (path, checkUnignored) {
|
|
13382
|
-
let ignored = false;
|
|
13383
|
-
let unignored = false;
|
|
13384
|
-
|
|
13385
|
-
this._rules.forEach(rule => {
|
|
13386
|
-
const {negative} = rule;
|
|
13387
|
-
if (
|
|
13388
|
-
unignored === negative && ignored !== unignored
|
|
13389
|
-
|| negative && !ignored && !unignored && !checkUnignored
|
|
13390
|
-
) {
|
|
13391
|
-
return
|
|
13392
|
-
}
|
|
13393
|
-
|
|
13394
|
-
const matched = rule.regex.test(path);
|
|
13395
|
-
|
|
13396
|
-
if (matched) {
|
|
13397
|
-
ignored = !negative;
|
|
13398
|
-
unignored = negative;
|
|
13399
|
-
}
|
|
13400
|
-
});
|
|
13401
|
-
|
|
13402
|
-
return {
|
|
13403
|
-
ignored,
|
|
13404
|
-
unignored
|
|
13405
|
-
}
|
|
13406
|
-
}
|
|
13407
|
-
|
|
13408
|
-
// @returns {TestResult}
|
|
13409
|
-
_test (originalPath, cache, checkUnignored, slices) {
|
|
13410
|
-
const path = originalPath
|
|
13411
|
-
// Supports nullable path
|
|
13412
|
-
&& checkPath.convert(originalPath);
|
|
13413
|
-
|
|
13414
|
-
checkPath(
|
|
13415
|
-
path,
|
|
13416
|
-
originalPath,
|
|
13417
|
-
this._allowRelativePaths
|
|
13418
|
-
? RETURN_FALSE
|
|
13419
|
-
: throwError
|
|
13420
|
-
);
|
|
13421
|
-
|
|
13422
|
-
return this._t(path, cache, checkUnignored, slices)
|
|
13423
|
-
}
|
|
13424
|
-
|
|
13425
|
-
_t (path, cache, checkUnignored, slices) {
|
|
13426
|
-
if (path in cache) {
|
|
13427
|
-
return cache[path]
|
|
13428
|
-
}
|
|
13429
|
-
|
|
13430
|
-
if (!slices) {
|
|
13431
|
-
// path/to/a.js
|
|
13432
|
-
// ['path', 'to', 'a.js']
|
|
13433
|
-
slices = path.split(SLASH);
|
|
13434
|
-
}
|
|
13435
|
-
|
|
13436
|
-
slices.pop();
|
|
13437
|
-
|
|
13438
|
-
// If the path has no parent directory, just test it
|
|
13439
|
-
if (!slices.length) {
|
|
13440
|
-
return cache[path] = this._testOne(path, checkUnignored)
|
|
13441
|
-
}
|
|
13442
|
-
|
|
13443
|
-
const parent = this._t(
|
|
13444
|
-
slices.join(SLASH) + SLASH,
|
|
13445
|
-
cache,
|
|
13446
|
-
checkUnignored,
|
|
13447
|
-
slices
|
|
13448
|
-
);
|
|
13449
|
-
|
|
13450
|
-
// If the path contains a parent directory, check the parent first
|
|
13451
|
-
return cache[path] = parent.ignored
|
|
13452
|
-
// > It is not possible to re-include a file if a parent directory of
|
|
13453
|
-
// > that file is excluded.
|
|
13454
|
-
? parent
|
|
13455
|
-
: this._testOne(path, checkUnignored)
|
|
13456
|
-
}
|
|
13457
|
-
|
|
13458
|
-
ignores (path) {
|
|
13459
|
-
return this._test(path, this._ignoreCache, false).ignored
|
|
13460
|
-
}
|
|
13461
|
-
|
|
13462
|
-
createFilter () {
|
|
13463
|
-
return path => !this.ignores(path)
|
|
13464
|
-
}
|
|
13465
|
-
|
|
13466
|
-
filter (paths) {
|
|
13467
|
-
return makeArray(paths).filter(this.createFilter())
|
|
13468
|
-
}
|
|
13469
|
-
|
|
13470
|
-
// @returns {TestResult}
|
|
13471
|
-
test (path) {
|
|
13472
|
-
return this._test(path, this._testCache, true)
|
|
13473
|
-
}
|
|
13474
|
-
}
|
|
13475
|
-
|
|
13476
|
-
const factory = options => new Ignore(options);
|
|
13477
|
-
|
|
13478
|
-
const isPathValid = path =>
|
|
13479
|
-
checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
|
|
13480
|
-
|
|
13481
|
-
factory.isPathValid = isPathValid;
|
|
13482
|
-
|
|
13483
|
-
// Fixes typescript
|
|
13484
|
-
factory.default = factory;
|
|
13485
|
-
|
|
13486
|
-
var ignore = factory;
|
|
12894
|
+
function requireIgnore () {
|
|
12895
|
+
if (hasRequiredIgnore) return ignore$1;
|
|
12896
|
+
hasRequiredIgnore = 1;
|
|
12897
|
+
// A simple implementation of make-array
|
|
12898
|
+
function makeArray (subject) {
|
|
12899
|
+
return Array.isArray(subject)
|
|
12900
|
+
? subject
|
|
12901
|
+
: [subject]
|
|
12902
|
+
}
|
|
13487
12903
|
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
12904
|
+
const EMPTY = '';
|
|
12905
|
+
const SPACE = ' ';
|
|
12906
|
+
const ESCAPE = '\\';
|
|
12907
|
+
const REGEX_TEST_BLANK_LINE = /^\s+$/;
|
|
12908
|
+
const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
|
|
12909
|
+
const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
|
|
12910
|
+
const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
|
|
12911
|
+
const REGEX_SPLITALL_CRLF = /\r?\n/g;
|
|
12912
|
+
// /foo,
|
|
12913
|
+
// ./foo,
|
|
12914
|
+
// ../foo,
|
|
12915
|
+
// .
|
|
12916
|
+
// ..
|
|
12917
|
+
const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/;
|
|
12918
|
+
|
|
12919
|
+
const SLASH = '/';
|
|
12920
|
+
|
|
12921
|
+
// Do not use ternary expression here, since "istanbul ignore next" is buggy
|
|
12922
|
+
let TMP_KEY_IGNORE = 'node-ignore';
|
|
12923
|
+
/* istanbul ignore else */
|
|
12924
|
+
if (typeof Symbol !== 'undefined') {
|
|
12925
|
+
TMP_KEY_IGNORE = Symbol.for('node-ignore');
|
|
12926
|
+
}
|
|
12927
|
+
const KEY_IGNORE = TMP_KEY_IGNORE;
|
|
12928
|
+
|
|
12929
|
+
const define = (object, key, value) =>
|
|
12930
|
+
Object.defineProperty(object, key, {value});
|
|
12931
|
+
|
|
12932
|
+
const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
|
|
12933
|
+
|
|
12934
|
+
const RETURN_FALSE = () => false;
|
|
12935
|
+
|
|
12936
|
+
// Sanitize the range of a regular expression
|
|
12937
|
+
// The cases are complicated, see test cases for details
|
|
12938
|
+
const sanitizeRange = range => range.replace(
|
|
12939
|
+
REGEX_REGEXP_RANGE,
|
|
12940
|
+
(match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)
|
|
12941
|
+
? match
|
|
12942
|
+
// Invalid range (out of order) which is ok for gitignore rules but
|
|
12943
|
+
// fatal for JavaScript regular expression, so eliminate it.
|
|
12944
|
+
: EMPTY
|
|
12945
|
+
);
|
|
12946
|
+
|
|
12947
|
+
// See fixtures #59
|
|
12948
|
+
const cleanRangeBackSlash = slashes => {
|
|
12949
|
+
const {length} = slashes;
|
|
12950
|
+
return slashes.slice(0, length - length % 2)
|
|
12951
|
+
};
|
|
12952
|
+
|
|
12953
|
+
// > If the pattern ends with a slash,
|
|
12954
|
+
// > it is removed for the purpose of the following description,
|
|
12955
|
+
// > but it would only find a match with a directory.
|
|
12956
|
+
// > In other words, foo/ will match a directory foo and paths underneath it,
|
|
12957
|
+
// > but will not match a regular file or a symbolic link foo
|
|
12958
|
+
// > (this is consistent with the way how pathspec works in general in Git).
|
|
12959
|
+
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
|
|
12960
|
+
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
|
|
12961
|
+
// you could use option `mark: true` with `glob`
|
|
12962
|
+
|
|
12963
|
+
// '`foo/`' should not continue with the '`..`'
|
|
12964
|
+
const REPLACERS = [
|
|
12965
|
+
|
|
12966
|
+
[
|
|
12967
|
+
// remove BOM
|
|
12968
|
+
// TODO:
|
|
12969
|
+
// Other similar zero-width characters?
|
|
12970
|
+
/^\uFEFF/,
|
|
12971
|
+
() => EMPTY
|
|
12972
|
+
],
|
|
12973
|
+
|
|
12974
|
+
// > Trailing spaces are ignored unless they are quoted with backslash ("\")
|
|
12975
|
+
[
|
|
12976
|
+
// (a\ ) -> (a )
|
|
12977
|
+
// (a ) -> (a)
|
|
12978
|
+
// (a ) -> (a)
|
|
12979
|
+
// (a \ ) -> (a )
|
|
12980
|
+
/((?:\\\\)*?)(\\?\s+)$/,
|
|
12981
|
+
(_, m1, m2) => m1 + (
|
|
12982
|
+
m2.indexOf('\\') === 0
|
|
12983
|
+
? SPACE
|
|
12984
|
+
: EMPTY
|
|
12985
|
+
)
|
|
12986
|
+
],
|
|
12987
|
+
|
|
12988
|
+
// replace (\ ) with ' '
|
|
12989
|
+
// (\ ) -> ' '
|
|
12990
|
+
// (\\ ) -> '\\ '
|
|
12991
|
+
// (\\\ ) -> '\\ '
|
|
12992
|
+
[
|
|
12993
|
+
/(\\+?)\s/g,
|
|
12994
|
+
(_, m1) => {
|
|
12995
|
+
const {length} = m1;
|
|
12996
|
+
return m1.slice(0, length - length % 2) + SPACE
|
|
12997
|
+
}
|
|
12998
|
+
],
|
|
12999
|
+
|
|
13000
|
+
// Escape metacharacters
|
|
13001
|
+
// which is written down by users but means special for regular expressions.
|
|
13002
|
+
|
|
13003
|
+
// > There are 12 characters with special meanings:
|
|
13004
|
+
// > - the backslash \,
|
|
13005
|
+
// > - the caret ^,
|
|
13006
|
+
// > - the dollar sign $,
|
|
13007
|
+
// > - the period or dot .,
|
|
13008
|
+
// > - the vertical bar or pipe symbol |,
|
|
13009
|
+
// > - the question mark ?,
|
|
13010
|
+
// > - the asterisk or star *,
|
|
13011
|
+
// > - the plus sign +,
|
|
13012
|
+
// > - the opening parenthesis (,
|
|
13013
|
+
// > - the closing parenthesis ),
|
|
13014
|
+
// > - and the opening square bracket [,
|
|
13015
|
+
// > - the opening curly brace {,
|
|
13016
|
+
// > These special characters are often called "metacharacters".
|
|
13017
|
+
[
|
|
13018
|
+
/[\\$.|*+(){^]/g,
|
|
13019
|
+
match => `\\${match}`
|
|
13020
|
+
],
|
|
13021
|
+
|
|
13022
|
+
[
|
|
13023
|
+
// > a question mark (?) matches a single character
|
|
13024
|
+
/(?!\\)\?/g,
|
|
13025
|
+
() => '[^/]'
|
|
13026
|
+
],
|
|
13027
|
+
|
|
13028
|
+
// leading slash
|
|
13029
|
+
[
|
|
13030
|
+
|
|
13031
|
+
// > A leading slash matches the beginning of the pathname.
|
|
13032
|
+
// > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
|
|
13033
|
+
// A leading slash matches the beginning of the pathname
|
|
13034
|
+
/^\//,
|
|
13035
|
+
() => '^'
|
|
13036
|
+
],
|
|
13037
|
+
|
|
13038
|
+
// replace special metacharacter slash after the leading slash
|
|
13039
|
+
[
|
|
13040
|
+
/\//g,
|
|
13041
|
+
() => '\\/'
|
|
13042
|
+
],
|
|
13043
|
+
|
|
13044
|
+
[
|
|
13045
|
+
// > A leading "**" followed by a slash means match in all directories.
|
|
13046
|
+
// > For example, "**/foo" matches file or directory "foo" anywhere,
|
|
13047
|
+
// > the same as pattern "foo".
|
|
13048
|
+
// > "**/foo/bar" matches file or directory "bar" anywhere that is directly
|
|
13049
|
+
// > under directory "foo".
|
|
13050
|
+
// Notice that the '*'s have been replaced as '\\*'
|
|
13051
|
+
/^\^*\\\*\\\*\\\//,
|
|
13052
|
+
|
|
13053
|
+
// '**/foo' <-> 'foo'
|
|
13054
|
+
() => '^(?:.*\\/)?'
|
|
13055
|
+
],
|
|
13056
|
+
|
|
13057
|
+
// starting
|
|
13058
|
+
[
|
|
13059
|
+
// there will be no leading '/'
|
|
13060
|
+
// (which has been replaced by section "leading slash")
|
|
13061
|
+
// If starts with '**', adding a '^' to the regular expression also works
|
|
13062
|
+
/^(?=[^^])/,
|
|
13063
|
+
function startingReplacer () {
|
|
13064
|
+
// If has a slash `/` at the beginning or middle
|
|
13065
|
+
return !/\/(?!$)/.test(this)
|
|
13066
|
+
// > Prior to 2.22.1
|
|
13067
|
+
// > If the pattern does not contain a slash /,
|
|
13068
|
+
// > Git treats it as a shell glob pattern
|
|
13069
|
+
// Actually, if there is only a trailing slash,
|
|
13070
|
+
// git also treats it as a shell glob pattern
|
|
13071
|
+
|
|
13072
|
+
// After 2.22.1 (compatible but clearer)
|
|
13073
|
+
// > If there is a separator at the beginning or middle (or both)
|
|
13074
|
+
// > of the pattern, then the pattern is relative to the directory
|
|
13075
|
+
// > level of the particular .gitignore file itself.
|
|
13076
|
+
// > Otherwise the pattern may also match at any level below
|
|
13077
|
+
// > the .gitignore level.
|
|
13078
|
+
? '(?:^|\\/)'
|
|
13079
|
+
|
|
13080
|
+
// > Otherwise, Git treats the pattern as a shell glob suitable for
|
|
13081
|
+
// > consumption by fnmatch(3)
|
|
13082
|
+
: '^'
|
|
13083
|
+
}
|
|
13084
|
+
],
|
|
13085
|
+
|
|
13086
|
+
// two globstars
|
|
13087
|
+
[
|
|
13088
|
+
// Use lookahead assertions so that we could match more than one `'/**'`
|
|
13089
|
+
/\\\/\\\*\\\*(?=\\\/|$)/g,
|
|
13090
|
+
|
|
13091
|
+
// Zero, one or several directories
|
|
13092
|
+
// should not use '*', or it will be replaced by the next replacer
|
|
13093
|
+
|
|
13094
|
+
// Check if it is not the last `'/**'`
|
|
13095
|
+
(_, index, str) => index + 6 < str.length
|
|
13096
|
+
|
|
13097
|
+
// case: /**/
|
|
13098
|
+
// > A slash followed by two consecutive asterisks then a slash matches
|
|
13099
|
+
// > zero or more directories.
|
|
13100
|
+
// > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
|
|
13101
|
+
// '/**/'
|
|
13102
|
+
? '(?:\\/[^\\/]+)*'
|
|
13103
|
+
|
|
13104
|
+
// case: /**
|
|
13105
|
+
// > A trailing `"/**"` matches everything inside.
|
|
13106
|
+
|
|
13107
|
+
// #21: everything inside but it should not include the current folder
|
|
13108
|
+
: '\\/.+'
|
|
13109
|
+
],
|
|
13110
|
+
|
|
13111
|
+
// normal intermediate wildcards
|
|
13112
|
+
[
|
|
13113
|
+
// Never replace escaped '*'
|
|
13114
|
+
// ignore rule '\*' will match the path '*'
|
|
13115
|
+
|
|
13116
|
+
// 'abc.*/' -> go
|
|
13117
|
+
// 'abc.*' -> skip this rule,
|
|
13118
|
+
// coz trailing single wildcard will be handed by [trailing wildcard]
|
|
13119
|
+
/(^|[^\\]+)(\\\*)+(?=.+)/g,
|
|
13120
|
+
|
|
13121
|
+
// '*.js' matches '.js'
|
|
13122
|
+
// '*.js' doesn't match 'abc'
|
|
13123
|
+
(_, p1, p2) => {
|
|
13124
|
+
// 1.
|
|
13125
|
+
// > An asterisk "*" matches anything except a slash.
|
|
13126
|
+
// 2.
|
|
13127
|
+
// > Other consecutive asterisks are considered regular asterisks
|
|
13128
|
+
// > and will match according to the previous rules.
|
|
13129
|
+
const unescaped = p2.replace(/\\\*/g, '[^\\/]*');
|
|
13130
|
+
return p1 + unescaped
|
|
13131
|
+
}
|
|
13132
|
+
],
|
|
13133
|
+
|
|
13134
|
+
[
|
|
13135
|
+
// unescape, revert step 3 except for back slash
|
|
13136
|
+
// For example, if a user escape a '\\*',
|
|
13137
|
+
// after step 3, the result will be '\\\\\\*'
|
|
13138
|
+
/\\\\\\(?=[$.|*+(){^])/g,
|
|
13139
|
+
() => ESCAPE
|
|
13140
|
+
],
|
|
13141
|
+
|
|
13142
|
+
[
|
|
13143
|
+
// '\\\\' -> '\\'
|
|
13144
|
+
/\\\\/g,
|
|
13145
|
+
() => ESCAPE
|
|
13146
|
+
],
|
|
13147
|
+
|
|
13148
|
+
[
|
|
13149
|
+
// > The range notation, e.g. [a-zA-Z],
|
|
13150
|
+
// > can be used to match one of the characters in a range.
|
|
13151
|
+
|
|
13152
|
+
// `\` is escaped by step 3
|
|
13153
|
+
/(\\)?\[([^\]/]*?)(\\*)($|\])/g,
|
|
13154
|
+
(match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE
|
|
13155
|
+
// '\\[bar]' -> '\\\\[bar\\]'
|
|
13156
|
+
? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`
|
|
13157
|
+
: close === ']'
|
|
13158
|
+
? endEscape.length % 2 === 0
|
|
13159
|
+
// A normal case, and it is a range notation
|
|
13160
|
+
// '[bar]'
|
|
13161
|
+
// '[bar\\\\]'
|
|
13162
|
+
? `[${sanitizeRange(range)}${endEscape}]`
|
|
13163
|
+
// Invalid range notaton
|
|
13164
|
+
// '[bar\\]' -> '[bar\\\\]'
|
|
13165
|
+
: '[]'
|
|
13166
|
+
: '[]'
|
|
13167
|
+
],
|
|
13168
|
+
|
|
13169
|
+
// ending
|
|
13170
|
+
[
|
|
13171
|
+
// 'js' will not match 'js.'
|
|
13172
|
+
// 'ab' will not match 'abc'
|
|
13173
|
+
/(?:[^*])$/,
|
|
13174
|
+
|
|
13175
|
+
// WTF!
|
|
13176
|
+
// https://git-scm.com/docs/gitignore
|
|
13177
|
+
// changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
|
|
13178
|
+
// which re-fixes #24, #38
|
|
13179
|
+
|
|
13180
|
+
// > If there is a separator at the end of the pattern then the pattern
|
|
13181
|
+
// > will only match directories, otherwise the pattern can match both
|
|
13182
|
+
// > files and directories.
|
|
13183
|
+
|
|
13184
|
+
// 'js*' will not match 'a.js'
|
|
13185
|
+
// 'js/' will not match 'a.js'
|
|
13186
|
+
// 'js' will match 'a.js' and 'a.js/'
|
|
13187
|
+
match => /\/$/.test(match)
|
|
13188
|
+
// foo/ will not match 'foo'
|
|
13189
|
+
? `${match}$`
|
|
13190
|
+
// foo matches 'foo' and 'foo/'
|
|
13191
|
+
: `${match}(?=$|\\/$)`
|
|
13192
|
+
],
|
|
13193
|
+
|
|
13194
|
+
// trailing wildcard
|
|
13195
|
+
[
|
|
13196
|
+
/(\^|\\\/)?\\\*$/,
|
|
13197
|
+
(_, p1) => {
|
|
13198
|
+
const prefix = p1
|
|
13199
|
+
// '\^':
|
|
13200
|
+
// '/*' does not match EMPTY
|
|
13201
|
+
// '/*' does not match everything
|
|
13202
|
+
|
|
13203
|
+
// '\\\/':
|
|
13204
|
+
// 'abc/*' does not match 'abc/'
|
|
13205
|
+
? `${p1}[^/]+`
|
|
13206
|
+
|
|
13207
|
+
// 'a*' matches 'a'
|
|
13208
|
+
// 'a*' matches 'aa'
|
|
13209
|
+
: '[^/]*';
|
|
13210
|
+
|
|
13211
|
+
return `${prefix}(?=$|\\/$)`
|
|
13212
|
+
}
|
|
13213
|
+
],
|
|
13214
|
+
];
|
|
13215
|
+
|
|
13216
|
+
// A simple cache, because an ignore rule only has only one certain meaning
|
|
13217
|
+
const regexCache = Object.create(null);
|
|
13218
|
+
|
|
13219
|
+
// @param {pattern}
|
|
13220
|
+
const makeRegex = (pattern, ignoreCase) => {
|
|
13221
|
+
let source = regexCache[pattern];
|
|
13222
|
+
|
|
13223
|
+
if (!source) {
|
|
13224
|
+
source = REPLACERS.reduce(
|
|
13225
|
+
(prev, [matcher, replacer]) =>
|
|
13226
|
+
prev.replace(matcher, replacer.bind(pattern)),
|
|
13227
|
+
pattern
|
|
13228
|
+
);
|
|
13229
|
+
regexCache[pattern] = source;
|
|
13230
|
+
}
|
|
13231
|
+
|
|
13232
|
+
return ignoreCase
|
|
13233
|
+
? new RegExp(source, 'i')
|
|
13234
|
+
: new RegExp(source)
|
|
13235
|
+
};
|
|
13236
|
+
|
|
13237
|
+
const isString = subject => typeof subject === 'string';
|
|
13238
|
+
|
|
13239
|
+
// > A blank line matches no files, so it can serve as a separator for readability.
|
|
13240
|
+
const checkPattern = pattern => pattern
|
|
13241
|
+
&& isString(pattern)
|
|
13242
|
+
&& !REGEX_TEST_BLANK_LINE.test(pattern)
|
|
13243
|
+
&& !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
|
|
13244
|
+
|
|
13245
|
+
// > A line starting with # serves as a comment.
|
|
13246
|
+
&& pattern.indexOf('#') !== 0;
|
|
13247
|
+
|
|
13248
|
+
const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF);
|
|
13249
|
+
|
|
13250
|
+
class IgnoreRule {
|
|
13251
|
+
constructor (
|
|
13252
|
+
origin,
|
|
13253
|
+
pattern,
|
|
13254
|
+
negative,
|
|
13255
|
+
regex
|
|
13256
|
+
) {
|
|
13257
|
+
this.origin = origin;
|
|
13258
|
+
this.pattern = pattern;
|
|
13259
|
+
this.negative = negative;
|
|
13260
|
+
this.regex = regex;
|
|
13261
|
+
}
|
|
13262
|
+
}
|
|
13504
13263
|
|
|
13505
|
-
|
|
13264
|
+
const createRule = (pattern, ignoreCase) => {
|
|
13265
|
+
const origin = pattern;
|
|
13266
|
+
let negative = false;
|
|
13267
|
+
|
|
13268
|
+
// > An optional prefix "!" which negates the pattern;
|
|
13269
|
+
if (pattern.indexOf('!') === 0) {
|
|
13270
|
+
negative = true;
|
|
13271
|
+
pattern = pattern.substr(1);
|
|
13272
|
+
}
|
|
13273
|
+
|
|
13274
|
+
pattern = pattern
|
|
13275
|
+
// > Put a backslash ("\") in front of the first "!" for patterns that
|
|
13276
|
+
// > begin with a literal "!", for example, `"\!important!.txt"`.
|
|
13277
|
+
.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')
|
|
13278
|
+
// > Put a backslash ("\") in front of the first hash for patterns that
|
|
13279
|
+
// > begin with a hash.
|
|
13280
|
+
.replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#');
|
|
13281
|
+
|
|
13282
|
+
const regex = makeRegex(pattern, ignoreCase);
|
|
13283
|
+
|
|
13284
|
+
return new IgnoreRule(
|
|
13285
|
+
origin,
|
|
13286
|
+
pattern,
|
|
13287
|
+
negative,
|
|
13288
|
+
regex
|
|
13289
|
+
)
|
|
13290
|
+
};
|
|
13291
|
+
|
|
13292
|
+
const throwError = (message, Ctor) => {
|
|
13293
|
+
throw new Ctor(message)
|
|
13294
|
+
};
|
|
13295
|
+
|
|
13296
|
+
const checkPath = (path, originalPath, doThrow) => {
|
|
13297
|
+
if (!isString(path)) {
|
|
13298
|
+
return doThrow(
|
|
13299
|
+
`path must be a string, but got \`${originalPath}\``,
|
|
13300
|
+
TypeError
|
|
13301
|
+
)
|
|
13302
|
+
}
|
|
13303
|
+
|
|
13304
|
+
// We don't know if we should ignore EMPTY, so throw
|
|
13305
|
+
if (!path) {
|
|
13306
|
+
return doThrow(`path must not be empty`, TypeError)
|
|
13307
|
+
}
|
|
13308
|
+
|
|
13309
|
+
// Check if it is a relative path
|
|
13310
|
+
if (checkPath.isNotRelative(path)) {
|
|
13311
|
+
const r = '`path.relative()`d';
|
|
13312
|
+
return doThrow(
|
|
13313
|
+
`path should be a ${r} string, but got "${originalPath}"`,
|
|
13314
|
+
RangeError
|
|
13315
|
+
)
|
|
13316
|
+
}
|
|
13317
|
+
|
|
13318
|
+
return true
|
|
13319
|
+
};
|
|
13320
|
+
|
|
13321
|
+
const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path);
|
|
13322
|
+
|
|
13323
|
+
checkPath.isNotRelative = isNotRelative;
|
|
13324
|
+
checkPath.convert = p => p;
|
|
13325
|
+
|
|
13326
|
+
class Ignore {
|
|
13327
|
+
constructor ({
|
|
13328
|
+
ignorecase = true,
|
|
13329
|
+
ignoreCase = ignorecase,
|
|
13330
|
+
allowRelativePaths = false
|
|
13331
|
+
} = {}) {
|
|
13332
|
+
define(this, KEY_IGNORE, true);
|
|
13333
|
+
|
|
13334
|
+
this._rules = [];
|
|
13335
|
+
this._ignoreCase = ignoreCase;
|
|
13336
|
+
this._allowRelativePaths = allowRelativePaths;
|
|
13337
|
+
this._initCache();
|
|
13338
|
+
}
|
|
13339
|
+
|
|
13340
|
+
_initCache () {
|
|
13341
|
+
this._ignoreCache = Object.create(null);
|
|
13342
|
+
this._testCache = Object.create(null);
|
|
13343
|
+
}
|
|
13344
|
+
|
|
13345
|
+
_addPattern (pattern) {
|
|
13346
|
+
// #32
|
|
13347
|
+
if (pattern && pattern[KEY_IGNORE]) {
|
|
13348
|
+
this._rules = this._rules.concat(pattern._rules);
|
|
13349
|
+
this._added = true;
|
|
13350
|
+
return
|
|
13351
|
+
}
|
|
13352
|
+
|
|
13353
|
+
if (checkPattern(pattern)) {
|
|
13354
|
+
const rule = createRule(pattern, this._ignoreCase);
|
|
13355
|
+
this._added = true;
|
|
13356
|
+
this._rules.push(rule);
|
|
13357
|
+
}
|
|
13358
|
+
}
|
|
13359
|
+
|
|
13360
|
+
// @param {Array<string> | string | Ignore} pattern
|
|
13361
|
+
add (pattern) {
|
|
13362
|
+
this._added = false;
|
|
13363
|
+
|
|
13364
|
+
makeArray(
|
|
13365
|
+
isString(pattern)
|
|
13366
|
+
? splitPattern(pattern)
|
|
13367
|
+
: pattern
|
|
13368
|
+
).forEach(this._addPattern, this);
|
|
13369
|
+
|
|
13370
|
+
// Some rules have just added to the ignore,
|
|
13371
|
+
// making the behavior changed.
|
|
13372
|
+
if (this._added) {
|
|
13373
|
+
this._initCache();
|
|
13374
|
+
}
|
|
13375
|
+
|
|
13376
|
+
return this
|
|
13377
|
+
}
|
|
13378
|
+
|
|
13379
|
+
// legacy
|
|
13380
|
+
addPattern (pattern) {
|
|
13381
|
+
return this.add(pattern)
|
|
13382
|
+
}
|
|
13383
|
+
|
|
13384
|
+
// | ignored : unignored
|
|
13385
|
+
// negative | 0:0 | 0:1 | 1:0 | 1:1
|
|
13386
|
+
// -------- | ------- | ------- | ------- | --------
|
|
13387
|
+
// 0 | TEST | TEST | SKIP | X
|
|
13388
|
+
// 1 | TESTIF | SKIP | TEST | X
|
|
13389
|
+
|
|
13390
|
+
// - SKIP: always skip
|
|
13391
|
+
// - TEST: always test
|
|
13392
|
+
// - TESTIF: only test if checkUnignored
|
|
13393
|
+
// - X: that never happen
|
|
13394
|
+
|
|
13395
|
+
// @param {boolean} whether should check if the path is unignored,
|
|
13396
|
+
// setting `checkUnignored` to `false` could reduce additional
|
|
13397
|
+
// path matching.
|
|
13398
|
+
|
|
13399
|
+
// @returns {TestResult} true if a file is ignored
|
|
13400
|
+
_testOne (path, checkUnignored) {
|
|
13401
|
+
let ignored = false;
|
|
13402
|
+
let unignored = false;
|
|
13403
|
+
|
|
13404
|
+
this._rules.forEach(rule => {
|
|
13405
|
+
const {negative} = rule;
|
|
13406
|
+
if (
|
|
13407
|
+
unignored === negative && ignored !== unignored
|
|
13408
|
+
|| negative && !ignored && !unignored && !checkUnignored
|
|
13409
|
+
) {
|
|
13410
|
+
return
|
|
13411
|
+
}
|
|
13412
|
+
|
|
13413
|
+
const matched = rule.regex.test(path);
|
|
13414
|
+
|
|
13415
|
+
if (matched) {
|
|
13416
|
+
ignored = !negative;
|
|
13417
|
+
unignored = negative;
|
|
13418
|
+
}
|
|
13419
|
+
});
|
|
13420
|
+
|
|
13421
|
+
return {
|
|
13422
|
+
ignored,
|
|
13423
|
+
unignored
|
|
13424
|
+
}
|
|
13425
|
+
}
|
|
13426
|
+
|
|
13427
|
+
// @returns {TestResult}
|
|
13428
|
+
_test (originalPath, cache, checkUnignored, slices) {
|
|
13429
|
+
const path = originalPath
|
|
13430
|
+
// Supports nullable path
|
|
13431
|
+
&& checkPath.convert(originalPath);
|
|
13432
|
+
|
|
13433
|
+
checkPath(
|
|
13434
|
+
path,
|
|
13435
|
+
originalPath,
|
|
13436
|
+
this._allowRelativePaths
|
|
13437
|
+
? RETURN_FALSE
|
|
13438
|
+
: throwError
|
|
13439
|
+
);
|
|
13440
|
+
|
|
13441
|
+
return this._t(path, cache, checkUnignored, slices)
|
|
13442
|
+
}
|
|
13443
|
+
|
|
13444
|
+
_t (path, cache, checkUnignored, slices) {
|
|
13445
|
+
if (path in cache) {
|
|
13446
|
+
return cache[path]
|
|
13447
|
+
}
|
|
13448
|
+
|
|
13449
|
+
if (!slices) {
|
|
13450
|
+
// path/to/a.js
|
|
13451
|
+
// ['path', 'to', 'a.js']
|
|
13452
|
+
slices = path.split(SLASH);
|
|
13453
|
+
}
|
|
13454
|
+
|
|
13455
|
+
slices.pop();
|
|
13456
|
+
|
|
13457
|
+
// If the path has no parent directory, just test it
|
|
13458
|
+
if (!slices.length) {
|
|
13459
|
+
return cache[path] = this._testOne(path, checkUnignored)
|
|
13460
|
+
}
|
|
13461
|
+
|
|
13462
|
+
const parent = this._t(
|
|
13463
|
+
slices.join(SLASH) + SLASH,
|
|
13464
|
+
cache,
|
|
13465
|
+
checkUnignored,
|
|
13466
|
+
slices
|
|
13467
|
+
);
|
|
13468
|
+
|
|
13469
|
+
// If the path contains a parent directory, check the parent first
|
|
13470
|
+
return cache[path] = parent.ignored
|
|
13471
|
+
// > It is not possible to re-include a file if a parent directory of
|
|
13472
|
+
// > that file is excluded.
|
|
13473
|
+
? parent
|
|
13474
|
+
: this._testOne(path, checkUnignored)
|
|
13475
|
+
}
|
|
13476
|
+
|
|
13477
|
+
ignores (path) {
|
|
13478
|
+
return this._test(path, this._ignoreCache, false).ignored
|
|
13479
|
+
}
|
|
13480
|
+
|
|
13481
|
+
createFilter () {
|
|
13482
|
+
return path => !this.ignores(path)
|
|
13483
|
+
}
|
|
13484
|
+
|
|
13485
|
+
filter (paths) {
|
|
13486
|
+
return makeArray(paths).filter(this.createFilter())
|
|
13487
|
+
}
|
|
13488
|
+
|
|
13489
|
+
// @returns {TestResult}
|
|
13490
|
+
test (path) {
|
|
13491
|
+
return this._test(path, this._testCache, true)
|
|
13492
|
+
}
|
|
13493
|
+
}
|
|
13506
13494
|
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
|
|
13495
|
+
const factory = options => new Ignore(options);
|
|
13496
|
+
|
|
13497
|
+
const isPathValid = path =>
|
|
13498
|
+
checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
|
|
13499
|
+
|
|
13500
|
+
factory.isPathValid = isPathValid;
|
|
13501
|
+
|
|
13502
|
+
// Fixes typescript
|
|
13503
|
+
factory.default = factory;
|
|
13504
|
+
|
|
13505
|
+
ignore$1 = factory;
|
|
13506
|
+
|
|
13507
|
+
// Windows
|
|
13508
|
+
// --------------------------------------------------------------
|
|
13509
|
+
/* istanbul ignore if */
|
|
13510
|
+
if (
|
|
13511
|
+
// Detect `process` so that it can run in browsers.
|
|
13512
|
+
typeof process !== 'undefined'
|
|
13513
|
+
&& (
|
|
13514
|
+
process.env && process.env.IGNORE_TEST_WIN32
|
|
13515
|
+
|| process.platform === 'win32'
|
|
13516
|
+
)
|
|
13517
|
+
) {
|
|
13518
|
+
/* eslint no-control-regex: "off" */
|
|
13519
|
+
const makePosix = str => /^\\\\\?\\/.test(str)
|
|
13520
|
+
|| /["<>|\u0000-\u001F]+/u.test(str)
|
|
13521
|
+
? str
|
|
13522
|
+
: str.replace(/\\/g, '/');
|
|
13523
|
+
|
|
13524
|
+
checkPath.convert = makePosix;
|
|
13525
|
+
|
|
13526
|
+
// 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/'
|
|
13527
|
+
// 'd:\\foo'
|
|
13528
|
+
const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
13529
|
+
checkPath.isNotRelative = path =>
|
|
13530
|
+
REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path)
|
|
13531
|
+
|| isNotRelative(path);
|
|
13532
|
+
}
|
|
13533
|
+
return ignore$1;
|
|
13513
13534
|
}
|
|
13514
13535
|
|
|
13515
|
-
var
|
|
13536
|
+
var ignoreExports = /*@__PURE__*/ requireIgnore();
|
|
13537
|
+
var ignore = /*@__PURE__*/getDefaultExportFromCjs(ignoreExports);
|
|
13516
13538
|
|
|
13517
13539
|
const entities = {
|
|
13518
13540
|
">": ">",
|
|
@@ -13857,12 +13879,12 @@ exports.bugs = bugs;
|
|
|
13857
13879
|
exports.classifyNodeText = classifyNodeText;
|
|
13858
13880
|
exports.codeframe = codeframe;
|
|
13859
13881
|
exports.compatibilityCheckImpl = compatibilityCheckImpl;
|
|
13860
|
-
exports.deepmerge = deepmerge
|
|
13882
|
+
exports.deepmerge = deepmerge;
|
|
13861
13883
|
exports.defineConfig = defineConfig;
|
|
13862
13884
|
exports.definePlugin = definePlugin;
|
|
13863
13885
|
exports.ensureError = ensureError;
|
|
13864
13886
|
exports.getFormatter = getFormatter;
|
|
13865
|
-
exports.ignore = ignore
|
|
13887
|
+
exports.ignore = ignore;
|
|
13866
13888
|
exports.keywordPatternMatcher = keywordPatternMatcher;
|
|
13867
13889
|
exports.name = name;
|
|
13868
13890
|
exports.presets = presets;
|