view-ignored 0.10.0 → 0.11.0

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.
Files changed (68) hide show
  1. package/README.md +118 -62
  2. package/out/browser.d.ts +1 -0
  3. package/out/browser.js +1 -0
  4. package/out/browser_scan.d.ts +1 -3
  5. package/out/browser_scan.js +11 -46
  6. package/out/browser_stream.d.ts +6 -1
  7. package/out/browser_stream.js +6 -1
  8. package/out/index.d.ts +1 -0
  9. package/out/index.js +1 -0
  10. package/out/patterns/extractor.d.ts +7 -7
  11. package/out/patterns/gitignore.d.ts +2 -2
  12. package/out/patterns/gitignore.js +14 -6
  13. package/out/patterns/ignores.d.ts +23 -8
  14. package/out/patterns/index.d.ts +1 -0
  15. package/out/patterns/index.js +1 -0
  16. package/out/patterns/init.d.ts +2 -2
  17. package/out/patterns/initState.d.ts +0 -7
  18. package/out/patterns/jsrjson.d.ts +2 -3
  19. package/out/patterns/jsrjson.js +25 -38
  20. package/out/patterns/matcherContext.d.ts +12 -9
  21. package/out/patterns/matcherContextPatch.js +158 -75
  22. package/out/patterns/matcherStream.d.ts +30 -11
  23. package/out/patterns/matcherStream.js +70 -25
  24. package/out/patterns/packagejson.d.ts +2 -2
  25. package/out/patterns/packagejson.js +11 -14
  26. package/out/patterns/patternCompile.js +48 -19
  27. package/out/patterns/patternList.d.ts +12 -6
  28. package/out/patterns/patternList.js +8 -4
  29. package/out/patterns/resolveSources.d.ts +22 -5
  30. package/out/patterns/resolveSources.js +153 -97
  31. package/out/patterns/resource.d.ts +16 -0
  32. package/out/patterns/resource.js +1 -0
  33. package/out/patterns/rule.d.ts +63 -9
  34. package/out/patterns/rule.js +101 -66
  35. package/out/patterns/source.d.ts +9 -17
  36. package/out/scan.d.ts +11 -3
  37. package/out/scan.js +16 -4
  38. package/out/scanCb.d.ts +16 -0
  39. package/out/scanCb.js +73 -0
  40. package/out/scanParallel.d.ts +18 -0
  41. package/out/scanParallel.js +146 -0
  42. package/out/stream.d.ts +6 -1
  43. package/out/stream.js +7 -2
  44. package/out/targets/bun.js +43 -36
  45. package/out/targets/deno.js +25 -23
  46. package/out/targets/git.js +3 -3
  47. package/out/targets/jsr.js +25 -23
  48. package/out/targets/jsrManifest.d.ts +8 -7
  49. package/out/targets/jsrManifest.js +40 -9
  50. package/out/targets/npm.js +30 -23
  51. package/out/targets/npmManifest.d.ts +18 -46
  52. package/out/targets/npmManifest.js +96 -23
  53. package/out/targets/target.d.ts +8 -16
  54. package/out/targets/vsce.js +20 -27
  55. package/out/targets/vsceManifest.d.ts +7 -0
  56. package/out/targets/vsceManifest.js +18 -0
  57. package/out/targets/yarn.js +48 -39
  58. package/out/targets/yarnClassic.js +20 -18
  59. package/out/types.d.ts +8 -7
  60. package/out/unixify.d.ts +1 -1
  61. package/out/unixify.js +40 -21
  62. package/out/walk.d.ts +43 -4
  63. package/out/walk.js +146 -84
  64. package/package.json +27 -23
  65. package/out/getDepth.d.ts +0 -4
  66. package/out/getDepth.js +0 -21
  67. package/out/opendir.d.ts +0 -3
  68. package/out/opendir.js +0 -22
@@ -1,4 +1,3 @@
1
- import { type } from "arktype";
2
1
  import { npmManifestParse } from "../targets/npmManifest.js";
3
2
  import { ruleCompile } from "./resolveSources.js";
4
3
  import { resolveNegatable } from "./source.js";
@@ -12,12 +11,10 @@ import { resolveNegatable } from "./source.js";
12
11
  export function extractPackageJson(source, content) {
13
12
  const result = extract(source, content);
14
13
  if (result === undefined) {
15
- for (const element of source.pattern) {
14
+ for (const element of source.rules) {
16
15
  ruleCompile(element);
17
16
  }
18
17
  }
19
- if (result === "error")
20
- return;
21
18
  return result;
22
19
  }
23
20
  /**
@@ -30,29 +27,29 @@ export function extractPackageJson(source, content) {
30
27
  export function extractPackageJsonNocase(source, content) {
31
28
  const result = extract(source, content);
32
29
  if (result === undefined) {
33
- for (const element of source.pattern) {
30
+ for (const element of source.rules) {
34
31
  ruleCompile(element, { nocase: true });
35
32
  }
36
33
  }
37
- if (result === "error")
38
- return;
39
34
  return result;
40
35
  }
41
36
  function extract(source, content) {
42
37
  source.inverted = true;
43
38
  const include = { compiled: null, excludes: false, pattern: [] };
44
39
  const exclude = { compiled: null, excludes: true, pattern: [] };
45
- const dist = npmManifestParse(content.toString());
46
- if (dist instanceof type.errors) {
47
- source.error = new Error("Invalid '" + source.path + "': " + dist.summary, { cause: dist });
48
- return "error";
40
+ let dist;
41
+ try {
42
+ dist = npmManifestParse(content.toString());
49
43
  }
50
- if (!dist.files) {
51
- return "none";
44
+ catch (err) {
45
+ return new Error("Invalid '" + source.path + "': Expected '}'", { cause: err });
46
+ }
47
+ if (!dist?.files || !Array.isArray(dist.files)) {
48
+ return null;
52
49
  }
53
50
  for (const pattern of dist.files) {
54
51
  resolveNegatable(pattern, true, include, exclude);
55
52
  }
56
- source.pattern.push(include, exclude);
53
+ source.rules.push(include, exclude);
57
54
  }
58
55
  extractPackageJson;
@@ -1,4 +1,4 @@
1
- import { makeRe } from "minimatch";
1
+ import glob from "micromatch";
2
2
  /**
3
3
  * Compiles a string of the {@link PatternList}.
4
4
  *
@@ -7,25 +7,54 @@ import { makeRe } from "minimatch";
7
7
  * @since 0.8.0
8
8
  */
9
9
  export function patternCompile(pattern, context = [], options) {
10
- const original = pattern;
11
- if (pattern.endsWith("/")) {
12
- pattern = pattern.substring(0, pattern.length - 1);
13
- }
14
- if (pattern.startsWith("/")) {
15
- pattern = pattern.substring(1);
10
+ const isRoot = pattern.charCodeAt(0) === 47; // '/'
11
+ const nocase = !!options?.nocase;
12
+ let cleaned = pattern;
13
+ if (cleaned.charCodeAt(cleaned.length - 1) === 47)
14
+ cleaned = cleaned.slice(0, -1);
15
+ if (isRoot)
16
+ cleaned = cleaned.slice(1);
17
+ const lowerCleaned = nocase ? cleaned.toLowerCase() : cleaned;
18
+ const matchBase = !isRoot && !cleaned.includes("/");
19
+ const matcherOpts = {
20
+ dot: true,
21
+ matchBase,
22
+ nobrace: true,
23
+ nocase,
24
+ nonegate: true,
25
+ };
26
+ const isMatch = glob.matcher(lowerCleaned, { ...matcherOpts, nocase: false });
27
+ const re = {
28
+ test: (str, matchCtx) => test(str, matchCtx, isMatch, lowerCleaned, isRoot, nocase, matchBase),
29
+ };
30
+ const cache = { pattern, patternContext: context, re };
31
+ return cache;
32
+ }
33
+ function test(str, matchCtx, isMatch, cleaned, isRoot, nocase, matchBase) {
34
+ const normStr = nocase ? (matchCtx.lower ?? (matchCtx.lower = str.toLowerCase())) : str;
35
+ if (normStr === cleaned || normStr.startsWith(cleaned + "/")) {
36
+ return true;
16
37
  }
17
- else if (!pattern.startsWith("**/")) {
18
- pattern = "**/" + pattern;
38
+ if (matchBase) {
39
+ const len = cleaned.length;
40
+ let pos = normStr.indexOf(cleaned);
41
+ while (pos !== -1) {
42
+ if ((pos === 0 || normStr.charCodeAt(pos - 1) === 47) &&
43
+ (pos + len === normStr.length || normStr.charCodeAt(pos + len) === 47)) {
44
+ return true;
45
+ }
46
+ pos = normStr.indexOf(cleaned, pos + 1);
47
+ }
19
48
  }
20
- if (!pattern.endsWith("/**")) {
21
- pattern += "/**";
49
+ if (isMatch(normStr))
50
+ return true;
51
+ if (!isRoot) {
52
+ let lastSlash = normStr.lastIndexOf("/");
53
+ while (lastSlash !== -1) {
54
+ if (isMatch(normStr.slice(0, lastSlash)))
55
+ return true;
56
+ lastSlash = normStr.lastIndexOf("/", lastSlash - 1);
57
+ }
22
58
  }
23
- const re = makeRe(pattern, {
24
- dot: true,
25
- nonegate: true,
26
- nocomment: true,
27
- nobrace: true,
28
- nocase: options?.nocase ?? false,
29
- });
30
- return { re, pattern: original, patternContext: context };
59
+ return false;
31
60
  }
@@ -9,19 +9,23 @@ import { type PatternCompileOptions } from "./patternCompile.js";
9
9
  */
10
10
  export type PatternCache = {
11
11
  /**
12
- * The regular expression instance.
12
+ * The regular expression interface.
13
13
  *
14
14
  * @since 0.6.0
15
15
  */
16
- re: RegExp;
16
+ re: {
17
+ test(string: string, matchCtx: {
18
+ lower?: string;
19
+ }): boolean;
20
+ };
17
21
  /**
18
- * The original pattern string this minimatch was compiled from.
22
+ * The original pattern string this cache was compiled from.
19
23
  *
20
24
  * @since 0.6.0
21
25
  */
22
26
  pattern: string;
23
27
  /**
24
- * The original pattern list this pattern was compiled from.
28
+ * The original pattern list this cache was compiled from.
25
29
  *
26
30
  * @since 0.6.0
27
31
  */
@@ -32,9 +36,11 @@ export type PatternCache = {
32
36
  *
33
37
  * @since 0.6.0
34
38
  */
35
- export declare function patternCacheTest(cache: PatternCache, path: string): boolean;
39
+ export declare function patternCacheTest(cache: PatternCache, path: string, matchCtx?: {
40
+ lower?: string;
41
+ }): boolean;
36
42
  /**
37
- * Represents a list of positive minimatch patterns.
43
+ * Represents a list of positive glob patterns.
38
44
  *
39
45
  * @since 0.6.0
40
46
  */
@@ -4,9 +4,8 @@ import { patternCompile } from "./patternCompile.js";
4
4
  *
5
5
  * @since 0.6.0
6
6
  */
7
- export function patternCacheTest(cache, path) {
8
- cache.re.lastIndex = 0;
9
- return cache.re.test(path);
7
+ export function patternCacheTest(cache, path, matchCtx = {}) {
8
+ return cache.re.test(path, matchCtx);
10
9
  }
11
10
  /**
12
11
  * Compiles the {@link PatternList}.
@@ -17,5 +16,10 @@ export function patternCacheTest(cache, path) {
17
16
  * @since 0.6.0
18
17
  */
19
18
  export function patternListCompile(list, options) {
20
- return list.map((p, _, pattern) => patternCompile(p, pattern, options));
19
+ const len = list.length;
20
+ const res = Array.from({ length: len });
21
+ for (let i = 0; i < len; i++) {
22
+ res[i] = patternCompile(list[i], list, options);
23
+ }
24
+ return res;
21
25
  }
@@ -1,6 +1,8 @@
1
- import type { PatternFinderOptions } from "./extractor.js";
1
+ import type { Dirent } from "node:fs";
2
2
  import type { PatternCompileOptions } from "./patternCompile.js";
3
+ import type { Resource } from "./resource.js";
3
4
  import type { Rule } from "./rule.js";
5
+ import { type PatternFinderOptions } from "./extractor.js";
4
6
  /**
5
7
  * Compiles the {@link Rule} (forced).
6
8
  * Can be compiled at any time.
@@ -10,7 +12,7 @@ import type { Rule } from "./rule.js";
10
12
  *
11
13
  * @since 0.6.0
12
14
  */
13
- export declare function ruleCompile(signedPattern: Rule, options?: PatternCompileOptions): Rule;
15
+ export declare function ruleCompile(rule: Rule, options?: PatternCompileOptions): Rule;
14
16
  /**
15
17
  * @see {@link resolveSources}
16
18
  *
@@ -26,10 +28,25 @@ export interface ResolveSourcesOptions extends PatternFinderOptions {
26
28
  * @since 0.6.0
27
29
  */
28
30
  dir: string;
31
+ /**
32
+ * Maps directory paths to their corresponding sources.
33
+ *
34
+ * @example
35
+ * "dir" => Resource
36
+ * "dir/subdir" => Resource
37
+ *
38
+ * @since 0.11.0
39
+ */
40
+ external: Map<string, Resource>;
41
+ /**
42
+ * Directory entries of the current directory.
43
+ * Used for optimization to avoid redundant `fs.readFile` calls.
44
+ *
45
+ * @since 0.11.0
46
+ */
47
+ entries?: Dirent[];
29
48
  }
30
49
  /**
31
- * Populates the {@link MatcherContext.external} map with {@link Source} objects.
32
- *
33
50
  * @since 0.6.0
34
51
  */
35
- export declare function resolveSources(options: ResolveSourcesOptions): Promise<void>;
52
+ export declare function resolveSources(options: ResolveSourcesOptions, cb: (err: Error | null, resource: Resource) => void): void;
@@ -1,5 +1,5 @@
1
- import { dirname } from "node:path";
2
- import { join, base } from "../unixify.js";
1
+ import { join } from "../unixify.js";
2
+ import {} from "./extractor.js";
3
3
  import { patternListCompile } from "./patternList.js";
4
4
  /**
5
5
  * Compiles the {@link Rule} (forced).
@@ -10,128 +10,184 @@ import { patternListCompile } from "./patternList.js";
10
10
  *
11
11
  * @since 0.6.0
12
12
  */
13
- export function ruleCompile(signedPattern, options) {
14
- signedPattern.compiled = patternListCompile(signedPattern.pattern, options);
15
- return signedPattern;
13
+ export function ruleCompile(rule, options) {
14
+ rule.compiled = patternListCompile(rule.pattern, options);
15
+ return rule;
16
16
  }
17
17
  /**
18
- * Populates the {@link MatcherContext.external} map with {@link Source} objects.
19
- *
20
18
  * @since 0.6.0
21
19
  */
22
- export async function resolveSources(options) {
23
- const { fs, ctx, cwd, signal, target } = options;
20
+ export function resolveSources(options, cb) {
21
+ const { fs, external, cwd, signal, target, resource: parentResource } = options;
24
22
  let dir = options.dir;
25
- if (ctx.external.has(dir)) {
23
+ if (target.root === "." && dir !== ".") {
24
+ resolveSources({ ...options, dir: "." }, (err, res) => {
25
+ if (err)
26
+ return cb(err, null);
27
+ external.set(dir, res);
28
+ cb(null, res);
29
+ });
30
+ return;
31
+ }
32
+ let source = external.get(dir);
33
+ if (source !== undefined) {
34
+ cb(null, source);
26
35
  return;
27
36
  }
28
- let source;
29
37
  const noSourceDirList = [dir];
30
38
  if (dir !== ".") {
31
- dir = dirname(dir);
32
- // find source from an ancestor [dir < ... < cwd]
33
- while (true) {
34
- signal?.throwIfAborted();
35
- source = ctx.external.get(dir);
36
- if (source !== undefined) {
37
- // if cache is found populate descendants [cwd > ... > dir]
38
- for (const noSourceDir of noSourceDirList) {
39
- ctx.external.set(noSourceDir, source);
40
- }
39
+ const segments = dir.split("/");
40
+ for (let i = segments.length - 1; i >= 0; i--) {
41
+ if (signal?.aborted) {
42
+ cb(signal.reason, null);
41
43
  return;
42
44
  }
43
- noSourceDirList.push(dir);
44
- const parent = dirname(dir);
45
- if (dir === parent)
45
+ const d = segments.slice(0, i).join("/") || ".";
46
+ source = external.get(d);
47
+ if (source !== undefined) {
48
+ dir = d;
46
49
  break;
47
- dir = parent;
48
- continue;
50
+ }
51
+ noSourceDirList.push(d);
52
+ if (d === ".") {
53
+ dir = ".";
54
+ break;
55
+ }
49
56
  }
50
57
  }
51
- // else
52
58
  // find non-cwd source [root > cwd) and populate [cwd > ... > dir]
53
- const preCwdSegments = [];
54
- if (target.root.startsWith("/")) {
55
- let c = dirname(cwd);
56
- while (true) {
57
- signal?.throwIfAborted();
58
- preCwdSegments.push(c);
59
- if (c === target.root)
60
- break;
61
- const parent = dirname(c);
62
- c = parent;
59
+ if (target.root.charCodeAt(0) === 47) {
60
+ // "/"
61
+ const segments = cwd.split("/");
62
+ const preCwdSegments = [];
63
+ let current = "";
64
+ for (let i = 0, len = segments.length - 1; i < len; i++) {
65
+ current += segments[i] + "/";
66
+ const path = current.length > 1 ? current.slice(0, -1) : "/";
67
+ if (path.length >= target.root.length) {
68
+ preCwdSegments.push(path);
69
+ }
63
70
  }
64
- preCwdSegments.reverse();
65
- source = await findSourceForAbsoluteDirs(preCwdSegments, ctx, fs, target, signal);
66
- if (typeof source === "object") {
67
- for (const noSourceDir of noSourceDirList) {
68
- signal?.throwIfAborted();
69
- ctx.external.set(noSourceDir, source);
71
+ findSourceForAbsoluteDirsCb(preCwdSegments, fs, target, signal, (err, source) => {
72
+ if (err) {
73
+ cb(err, null);
74
+ return;
70
75
  }
76
+ const absPaths = Array.from({ length: noSourceDirList.length });
77
+ for (let i = 0, len = noSourceDirList.length; i < len; i++) {
78
+ absPaths[i] = join(cwd, noSourceDirList[i]);
79
+ }
80
+ findSourceForAbsoluteDirsCb(absPaths, fs, target, signal, (err, s) => {
81
+ if (err) {
82
+ cb(err, null);
83
+ return;
84
+ }
85
+ const finalSource = s || source || parentResource || null;
86
+ external.set(options.dir, finalSource);
87
+ cb(null, finalSource);
88
+ }, options.entries);
89
+ });
90
+ return;
91
+ }
92
+ const absPaths = Array.from({ length: noSourceDirList.length });
93
+ for (let i = 0, len = noSourceDirList.length; i < len; i++) {
94
+ absPaths[i] = join(cwd, noSourceDirList[i]);
95
+ }
96
+ findSourceForAbsoluteDirsCb(absPaths, fs, target, signal, (err, source) => {
97
+ if (err) {
98
+ cb(err, null);
71
99
  return;
72
100
  }
101
+ const finalSource = source || parentResource || null;
102
+ external.set(options.dir, finalSource);
103
+ cb(null, finalSource);
104
+ }, options.entries);
105
+ }
106
+ function findSourceForAbsoluteDirsCb(paths, fs, target, signal, cb, entries) {
107
+ if (signal?.aborted) {
108
+ cb(signal.reason, null);
109
+ return;
73
110
  }
74
- const absPaths = noSourceDirList.map((rel) => join(cwd, rel));
75
- source = await findSourceForAbsoluteDirs(absPaths, ctx, fs, target, signal);
76
- if (source !== undefined) {
77
- for (const noSourceDir of noSourceDirList) {
78
- signal?.throwIfAborted();
79
- ctx.external.set(noSourceDir, source);
111
+ const extractors = target.extractors;
112
+ const plen = paths.length;
113
+ const elen = extractors.length;
114
+ let i = 0;
115
+ let j = 0;
116
+ function next() {
117
+ if (i >= plen) {
118
+ cb(null, null);
119
+ return;
80
120
  }
81
- }
82
- }
83
- async function findSourceForAbsoluteDirs(paths, ctx, fs, target, signal) {
84
- for (const parent of paths) {
85
- for (const extractor of target.extractors) {
86
- signal?.throwIfAborted();
87
- const s = await tryExtractor(parent, fs, ctx, extractor);
88
- if (typeof s === "object" && s.error) {
89
- ctx.failed.push(s);
90
- return s;
121
+ const parent = paths[i];
122
+ const extractor = extractors[j];
123
+ j++;
124
+ if (j >= elen) {
125
+ i++;
126
+ j = 0;
127
+ }
128
+ if (entries && plen > 0 && parent === paths[0]) {
129
+ const epath = extractor.path;
130
+ const slashIdx = epath.indexOf("/");
131
+ const firstSegment = slashIdx === -1 ? epath : epath.substring(0, slashIdx);
132
+ let found = false;
133
+ for (let k = 0, len = entries.length; k < len; k++) {
134
+ if (entries[k].name === firstSegment) {
135
+ found = true;
136
+ break;
137
+ }
91
138
  }
92
- if (typeof s === "object") {
93
- return s;
139
+ if (!found) {
140
+ next();
141
+ return;
94
142
  }
95
143
  }
144
+ tryExtractorCb(parent, fs, extractor, (err, source) => {
145
+ if (err) {
146
+ cb(err, null);
147
+ return;
148
+ }
149
+ if (source !== null) {
150
+ cb(null, source);
151
+ return;
152
+ }
153
+ next();
154
+ });
96
155
  }
97
- return "none";
156
+ next();
98
157
  }
99
- async function tryExtractor(cwd, fs, ctx, extractor) {
100
- let abs = join(cwd, extractor.path);
101
- const name = base(extractor.path);
102
- const newSource = {
103
- name,
104
- path: extractor.path,
105
- inverted: false,
106
- pattern: [],
107
- };
108
- let buff;
109
- try {
110
- buff = await fs.promises.readFile(abs);
111
- }
112
- catch (err) {
113
- const error = err;
114
- if (error.code === "ENOENT") {
115
- return "none";
158
+ function tryExtractorCb(cwd, fs, extractor, cb) {
159
+ const abs = join(cwd, extractor.path);
160
+ fs.readFile(abs, (err, buff) => {
161
+ if (err) {
162
+ const error = err;
163
+ if (error.code === "ENOENT") {
164
+ cb(null, null);
165
+ return;
166
+ }
167
+ cb(null, {
168
+ error,
169
+ source: {
170
+ inverted: false,
171
+ path: extractor.path,
172
+ rules: [],
173
+ },
174
+ });
175
+ return;
116
176
  }
117
- newSource.error = error;
118
- return newSource;
119
- }
120
- try {
121
- const act = extractor.extract(newSource, buff, ctx);
122
- if (act === "none") {
123
- return act;
177
+ const newSource = {
178
+ inverted: false,
179
+ path: extractor.path,
180
+ rules: [],
181
+ };
182
+ const act = extractor.extract(newSource, buff);
183
+ if (act === null) {
184
+ cb(null, null);
185
+ return;
124
186
  }
125
- }
126
- catch (err) {
127
- if (err === "none") {
128
- return err;
187
+ if (act instanceof Error) {
188
+ cb(null, { error: act, source: newSource });
189
+ return;
129
190
  }
130
- newSource.error =
131
- err instanceof Error
132
- ? err
133
- : new Error("Unknown error during source extraction", { cause: err });
134
- return newSource;
135
- }
136
- return newSource;
191
+ cb(null, newSource);
192
+ });
137
193
  }
@@ -0,0 +1,16 @@
1
+ import type { Source } from "./source.js";
2
+ /**
3
+ * Represents missing source, existing source or invalid source.
4
+ *
5
+ * @since 0.11.0
6
+ */
7
+ export type Resource = Source | InvalidSource | null;
8
+ /**
9
+ * Represents a source with an associated error.
10
+ *
11
+ * @since 0.11.0
12
+ */
13
+ export type InvalidSource = {
14
+ source: Source;
15
+ error: Error;
16
+ };
@@ -0,0 +1 @@
1
+ export {};