view-ignored 0.7.0 → 0.8.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 (42) hide show
  1. package/README.md +9 -3
  2. package/out/browser_scan.d.ts +1 -1
  3. package/out/browser_scan.js +15 -16
  4. package/out/browser_stream.js +1 -43
  5. package/out/patterns/extractor.d.ts +6 -0
  6. package/out/patterns/gitignore.d.ts +8 -0
  7. package/out/patterns/gitignore.js +16 -2
  8. package/out/patterns/ignores.d.ts +12 -6
  9. package/out/patterns/index.d.ts +3 -0
  10. package/out/patterns/index.js +3 -0
  11. package/out/patterns/init.d.ts +9 -0
  12. package/out/patterns/init.js +1 -0
  13. package/out/patterns/initState.d.ts +31 -0
  14. package/out/patterns/initState.js +1 -0
  15. package/out/patterns/matcherContextPatch.js +6 -7
  16. package/out/patterns/matcherStream.d.ts +15 -0
  17. package/out/patterns/matcherStream.js +57 -0
  18. package/out/patterns/packagejson.d.ts +8 -0
  19. package/out/patterns/packagejson.js +27 -5
  20. package/out/patterns/pattern.d.ts +2 -1
  21. package/out/patterns/pattern.js +2 -2
  22. package/out/patterns/resolveSources.d.ts +2 -1
  23. package/out/patterns/resolveSources.js +22 -10
  24. package/out/patterns/stringCompile.d.ts +15 -2
  25. package/out/patterns/stringCompile.js +4 -3
  26. package/out/scan.d.ts +1 -1
  27. package/out/scan.js +1 -1
  28. package/out/targets/index.d.ts +1 -0
  29. package/out/targets/index.js +1 -0
  30. package/out/targets/npm.js +35 -13
  31. package/out/targets/target.d.ts +13 -0
  32. package/out/targets/vsce.js +34 -1
  33. package/out/targets/yarn.js +72 -26
  34. package/out/targets/yarnClassic.d.ts +5 -0
  35. package/out/targets/yarnClassic.js +77 -0
  36. package/out/types.d.ts +1 -1
  37. package/out/unixify.d.ts +3 -0
  38. package/out/unixify.js +33 -0
  39. package/out/walk.js +4 -4
  40. package/package.json +4 -1
  41. package/out/normalizeCwd.d.ts +0 -1
  42. package/out/normalizeCwd.js +0 -4
package/README.md CHANGED
@@ -43,7 +43,11 @@ const ctx = await vign.scan({ target })
43
43
  ctx.paths.has(".git/HEAD") // false
44
44
  ctx.paths.has("src") // true
45
45
 
46
- ctx.paths.get("src") // { ignored, match, kind, ... }
46
+ const match = ctx.paths.get("src")
47
+ if (match.kind === "external") {
48
+ console.log(match.source.path) // ".gitignore"
49
+ console.log(match.pattern) // "src/**"
50
+ }
47
51
  ```
48
52
 
49
53
  ### Using custom target
@@ -107,6 +111,7 @@ stream.on("end", (ctx) => {
107
111
  ctx.paths.has("node_modules/") // false
108
112
  ctx.paths.has("package.json") // true
109
113
  })
114
+ stream.start() // important
110
115
  ```
111
116
 
112
117
  ### Browser and custom FS
@@ -144,14 +149,15 @@ The following built-in scanners are available:
144
149
  - Starts searching from `/`.
145
150
  - Check this scanner by running `git ls-files --others --exclude-standard --cached`.
146
151
  - See the implementation of [Git target](https://github.com/Mopsgamer/view-ignored/tree/main/src/targets/git.ts) for details.
147
- - NPM (compatible with Bun, PNPM, and others)
152
+ - NPM (expecting to be compatible with Bun, PNPM, and others)
148
153
  - Reads `.npmignore` and `package.json` `files` field.
149
154
  - Starts searching from `.` (current working directory).
150
155
  - No additional checks for `name`, `version` or `publishConfig`.
151
156
  - Check this scanner by running `npm pack --dry-run`.
152
157
  - See the implementation of [NPM target](https://github.com/Mopsgamer/view-ignored/tree/main/src/targets/npm.ts) for details.
153
158
  - Yarn
154
- - Same behavior as `npm`, but also reads `.yarnignore`.
159
+ - Modern Berry behavior, but does not include paths from `package.json` `main`, `module`, `browser` and `bin`.
160
+ - `YarnClassic` is available.
155
161
  - Starts searching from `.` (current working directory).
156
162
  - See the implementation of [Yarn target](https://github.com/Mopsgamer/view-ignored/tree/main/src/targets/yarn.ts) for details.
157
163
  - VSCE
@@ -4,7 +4,7 @@ export type * from "./types.js";
4
4
  /**
5
5
  * Scan the directory for included files based on the provided targets.
6
6
  *
7
- * Note that this function uses `fs/promises.readFile` and `fs/promises.opendir` without options within
7
+ * Note that this function uses `fs.promises.readFile` and `fs.promises.opendir` without options within
8
8
  * custom recursion, instead of `fs.promises.readdir` with `{ withFileTypes: true }.
9
9
  * It also normalizes paths to use forward slashes.
10
10
  * Please report any issues if you encounter problems related to this behavior.
@@ -1,12 +1,10 @@
1
- import { resolve } from "node:path";
2
- import { relative } from "node:path/posix";
3
- import { normalizeCwd } from "./normalizeCwd.js";
4
1
  import { opendir } from "./opendir.js";
2
+ import { unixify, relative, join } from "./unixify.js";
5
3
  import { walkIncludes } from "./walk.js";
6
4
  /**
7
5
  * Scan the directory for included files based on the provided targets.
8
6
  *
9
- * Note that this function uses `fs/promises.readFile` and `fs/promises.opendir` without options within
7
+ * Note that this function uses `fs.promises.readFile` and `fs.promises.opendir` without options within
10
8
  * custom recursion, instead of `fs.promises.readdir` with `{ withFileTypes: true }.
11
9
  * It also normalizes paths to use forward slashes.
12
10
  * Please report any issues if you encounter problems related to this behavior.
@@ -30,7 +28,7 @@ export function scan(options) {
30
28
  totalMatchedFiles: 0,
31
29
  totalDirs: 0,
32
30
  };
33
- const normalCwd = normalizeCwd(cwd);
31
+ const normalCwd = unixify(cwd);
34
32
  const scanOptions = {
35
33
  cwd: normalCwd,
36
34
  within,
@@ -42,18 +40,19 @@ export function scan(options) {
42
40
  signal,
43
41
  target,
44
42
  };
45
- const result = opendir(fs, normalizeCwd(resolve(normalCwd, within)), (entry) => {
46
- const path = relative(normalCwd, normalizeCwd(entry.parentPath) + "/" + entry.name);
47
- return walkIncludes({
48
- path,
49
- entry,
50
- ctx,
51
- stream: undefined,
52
- scanOptions,
53
- });
54
- });
55
43
  return (async () => {
56
- await result;
44
+ await target.init?.({ ctx, cwd, fs, signal });
45
+ let from = join(unixify(normalCwd), within);
46
+ await opendir(fs, from, (entry) => {
47
+ const path = relative(normalCwd, unixify(entry.parentPath) + "/" + entry.name);
48
+ return walkIncludes({
49
+ path,
50
+ entry,
51
+ ctx,
52
+ stream: undefined,
53
+ scanOptions,
54
+ });
55
+ });
57
56
  return ctx;
58
57
  })();
59
58
  }
@@ -1,51 +1,9 @@
1
- import { resolve } from "node:path";
2
- import { relative } from "node:path/posix";
3
- import { normalizeCwd } from "./normalizeCwd.js";
4
- import { opendir } from "./opendir.js";
5
1
  import { MatcherStream } from "./patterns/matcherStream.js";
6
- import { walkIncludes } from "./walk.js";
7
2
  /**
8
3
  * @see {@link browserScan}
9
4
  *
10
5
  * @since 0.6.0
11
6
  */
12
7
  export function scanStream(options) {
13
- const { target, cwd, within = ".", invert = false, depth: maxDepth = Infinity, signal = null, fastDepth = false, fastInternal = false, fs, } = options;
14
- const ctx = {
15
- paths: new Map(),
16
- external: new Map(),
17
- failed: [],
18
- depthPaths: new Map(),
19
- totalFiles: 0,
20
- totalMatchedFiles: 0,
21
- totalDirs: 0,
22
- };
23
- const stream = new MatcherStream({ captureRejections: false });
24
- const normalCwd = normalizeCwd(cwd);
25
- const scanOptions = {
26
- cwd: normalCwd,
27
- within,
28
- depth: maxDepth,
29
- fastDepth,
30
- fastInternal,
31
- fs,
32
- invert,
33
- signal,
34
- target,
35
- };
36
- const result = opendir(fs, normalizeCwd(resolve(normalCwd, within)), (entry) => {
37
- const path = relative(normalCwd, normalizeCwd(entry.parentPath) + "/" + entry.name);
38
- return walkIncludes({
39
- path,
40
- entry,
41
- ctx,
42
- stream,
43
- scanOptions,
44
- });
45
- });
46
- void (async () => {
47
- await result;
48
- stream.emit("end", ctx);
49
- })();
50
- return stream;
8
+ return new MatcherStream(options);
51
9
  }
@@ -77,4 +77,10 @@ export interface PatternFinderOptions {
77
77
  * @since 0.6.0
78
78
  */
79
79
  root: string;
80
+ /**
81
+ * Return as soon as possible.
82
+ *
83
+ * @since 0.7.1
84
+ */
85
+ signal: AbortSignal | null;
80
86
  }
@@ -7,3 +7,11 @@ import { type Source } from "./source.js";
7
7
  * @since 0.6.0
8
8
  */
9
9
  export declare function extractGitignore(source: Source, content: Buffer): void;
10
+ /**
11
+ * Extracts and compiles patterns from the file.
12
+ *
13
+ * @see {@link signedPatternCompile}
14
+ *
15
+ * @since 0.6.0
16
+ */
17
+ export declare function extractGitignoreNocase(source: Source, content: Buffer): void;
@@ -8,6 +8,22 @@ import { sourcePushNegatable } from "./source.js";
8
8
  * @since 0.6.0
9
9
  */
10
10
  export function extractGitignore(source, content) {
11
+ extract(source, content);
12
+ signedPatternCompile(source.pattern);
13
+ }
14
+ /**
15
+ * Extracts and compiles patterns from the file.
16
+ *
17
+ * @see {@link signedPatternCompile}
18
+ *
19
+ * @since 0.6.0
20
+ */
21
+ export function extractGitignoreNocase(source, content) {
22
+ extract(source, content);
23
+ signedPatternCompile(source.pattern, { nocase: true });
24
+ }
25
+ extractGitignore;
26
+ function extract(source, content) {
11
27
  for (let line of content.toString().split("\n")) {
12
28
  line = line.trim();
13
29
  if (line === "" || line.startsWith("#")) {
@@ -19,6 +35,4 @@ export function extractGitignore(source, content) {
19
35
  }
20
36
  sourcePushNegatable(source, line);
21
37
  }
22
- signedPatternCompile(source.pattern);
23
38
  }
24
- extractGitignore;
@@ -1,11 +1,17 @@
1
- import type { MatcherContext } from "../patterns/matcherContext.js";
2
1
  import type { SignedPatternMatch } from "../patterns/signedPattern.js";
3
- import type { FsAdapter } from "../types.js";
4
- export interface IgnoresOptions {
5
- fs: FsAdapter;
6
- cwd: string;
2
+ import type { InitState } from "./initState.js";
3
+ /**
4
+ * Used in {@link Ignores}.
5
+ *
6
+ * @since 0.6.0
7
+ */
8
+ export interface IgnoresOptions extends InitState {
9
+ /**
10
+ * File or directory without the slash suffix.
11
+ *
12
+ * @since 0.6.0
13
+ */
7
14
  entry: string;
8
- ctx: MatcherContext;
9
15
  }
10
16
  /**
11
17
  * Checks whether a given entry path should be ignored based on its patterns.
@@ -1,6 +1,8 @@
1
1
  export * from "./extractor.js";
2
2
  export * from "./gitignore.js";
3
3
  export * from "./ignores.js";
4
+ export * from "./init.js";
5
+ export * from "./initState.js";
4
6
  export * from "./jsrjson.js";
5
7
  export * from "./matcherContext.js";
6
8
  export * from "./matcherContextPatch.js";
@@ -11,3 +13,4 @@ export * from "./patternMatcher.js";
11
13
  export * from "./resolveSources.js";
12
14
  export * from "./signedPattern.js";
13
15
  export * from "./source.js";
16
+ export * from "./stringCompile.js";
@@ -1,6 +1,8 @@
1
1
  export * from "./extractor.js";
2
2
  export * from "./gitignore.js";
3
3
  export * from "./ignores.js";
4
+ export * from "./init.js";
5
+ export * from "./initState.js";
4
6
  export * from "./jsrjson.js";
5
7
  export * from "./matcherContext.js";
6
8
  export * from "./matcherContextPatch.js";
@@ -11,3 +13,4 @@ export * from "./patternMatcher.js";
11
13
  export * from "./resolveSources.js";
12
14
  export * from "./signedPattern.js";
13
15
  export * from "./source.js";
16
+ export * from "./stringCompile.js";
@@ -0,0 +1,9 @@
1
+ import type { InitState } from "./initState.js";
2
+ /**
3
+ * Initializes the target. For example,
4
+ * Yarn reads `package.json` to find `main` and `bin` values,
5
+ * so it can forcefully include them.
6
+ *
7
+ * @since 0.8.0
8
+ */
9
+ export type Init = (options: InitState) => Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { FsAdapter } from "../types.js";
2
+ import type { MatcherContext } from "./matcherContext.js";
3
+ /**
4
+ * Used in {@link IgnoresOptions}.
5
+ *
6
+ * @since 0.8.0
7
+ */
8
+ export interface InitState {
9
+ /**
10
+ * The file system adapter for directory walking and reading files.
11
+ *
12
+ * @since 0.6.0
13
+ */
14
+ fs: FsAdapter;
15
+ /**
16
+ * @since 0.6.0
17
+ */
18
+ cwd: string;
19
+ /**
20
+ * The context to populate.
21
+ *
22
+ * @since 0.6.0
23
+ */
24
+ ctx: MatcherContext;
25
+ /**
26
+ * Return as soon as possible.
27
+ *
28
+ * @since 0.7.1
29
+ */
30
+ signal: AbortSignal | null;
31
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,8 +1,7 @@
1
1
  import { resolve, dirname } from "node:path";
2
- import { relative } from "node:path/posix";
3
2
  import { getDepth } from "../getDepth.js";
4
- import { normalizeCwd } from "../normalizeCwd.js";
5
3
  import { opendir } from "../opendir.js";
4
+ import { unixify, relative } from "../unixify.js";
6
5
  import { walkIncludes } from "../walk.js";
7
6
  /**
8
7
  * Provides patching abilities for the given {@link MatcherContext}.
@@ -14,7 +13,7 @@ export async function matcherContextAddPath(ctx, options, entry) {
14
13
  if (ctx.paths.has(entry)) {
15
14
  return false;
16
15
  }
17
- const { target, fs, cwd } = options;
16
+ const { target, fs, cwd, signal } = options;
18
17
  const isDir = entry.endsWith("/");
19
18
  if (isDir) {
20
19
  // recursive parent population
@@ -22,7 +21,7 @@ export async function matcherContextAddPath(ctx, options, entry) {
22
21
  if (direntPath === ".") {
23
22
  return true;
24
23
  }
25
- ctx.paths.set(entry, await target.ignores({ fs, cwd, entry: direntPath, ctx }));
24
+ ctx.paths.set(entry, await target.ignores({ fs, cwd, entry: direntPath, ctx, signal }));
26
25
  if (ctx.totalFiles >= 0) {
27
26
  ctx.totalDirs++;
28
27
  }
@@ -43,7 +42,7 @@ export async function matcherContextAddPath(ctx, options, entry) {
43
42
  // 1. recursively populate parents
44
43
  await matcherContextAddPath(ctx, options, parent + "/");
45
44
  // 2. if ignored, remove, otherwise add
46
- const match = await target.ignores({ fs, cwd, entry, ctx });
45
+ const match = await target.ignores({ fs, cwd, entry, ctx, signal });
47
46
  if (match.ignored) {
48
47
  // 2.1. remove
49
48
  await matcherContextRemovePath(ctx, options, entry);
@@ -141,9 +140,9 @@ export async function matcherContextRemovePath(ctx, options, entry) {
141
140
  return true;
142
141
  }
143
142
  async function rescan(ctx, options) {
144
- const normalCwd = normalizeCwd(options.cwd);
143
+ const normalCwd = unixify(options.cwd);
145
144
  await opendir(options.fs, resolve(normalCwd, options.within), (entry) => {
146
- const path = relative(normalCwd, normalizeCwd(entry.parentPath) + "/" + entry.name);
145
+ const path = relative(normalCwd, unixify(entry.parentPath) + "/" + entry.name);
147
146
  return walkIncludes({
148
147
  path,
149
148
  entry,
@@ -1,6 +1,7 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import type { Dirent } from "node:fs";
3
3
  import type { MatcherContext } from "../patterns/matcherContext.js";
4
+ import type { ScanOptions, FsAdapter } from "../types.js";
4
5
  import type { SignedPatternMatch } from "./signedPattern.js";
5
6
  /**
6
7
  * Post-scan entry information.
@@ -61,4 +62,18 @@ export type EventMap = {
61
62
  * @since 0.6.0
62
63
  */
63
64
  export declare class MatcherStream extends EventEmitter<EventMap> {
65
+ #private;
66
+ constructor(options: ScanOptions & {
67
+ fs: FsAdapter;
68
+ cwd: string;
69
+ noTimeout?: boolean;
70
+ } & {
71
+ captureRejections?: boolean;
72
+ });
73
+ /**
74
+ * Resolves when everything is scanned.
75
+ *
76
+ * @since 0.8.0
77
+ */
78
+ start(): Promise<void>;
64
79
  }
@@ -1,4 +1,7 @@
1
1
  import { EventEmitter } from "node:events";
2
+ import { opendir } from "../opendir.js";
3
+ import { join, relative, unixify } from "../unixify.js";
4
+ import { walkIncludes } from "../walk.js";
2
5
  /**
3
6
  * Event emitter.
4
7
  * @extends EventEmitter
@@ -6,4 +9,58 @@ import { EventEmitter } from "node:events";
6
9
  * @since 0.6.0
7
10
  */
8
11
  export class MatcherStream extends EventEmitter {
12
+ #timeout;
13
+ #options;
14
+ constructor(options) {
15
+ super({ captureRejections: options.captureRejections });
16
+ this.#options = options;
17
+ if (!options.noTimeout) {
18
+ this.#timeout = setTimeout(() => {
19
+ throw new Error("Stream did not start within 5 seconds. Call MatcherStream.start() or enable noTimeout.");
20
+ }, 5e3);
21
+ }
22
+ }
23
+ /**
24
+ * Resolves when everything is scanned.
25
+ *
26
+ * @since 0.8.0
27
+ */
28
+ async start() {
29
+ clearTimeout(this.#timeout);
30
+ const { target, cwd, within = ".", invert = false, depth: maxDepth = Infinity, signal = null, fastDepth = false, fastInternal = false, fs, } = this.#options;
31
+ const ctx = {
32
+ paths: new Map(),
33
+ external: new Map(),
34
+ failed: [],
35
+ depthPaths: new Map(),
36
+ totalFiles: 0,
37
+ totalMatchedFiles: 0,
38
+ totalDirs: 0,
39
+ };
40
+ const normalCwd = unixify(cwd);
41
+ const scanOptions = {
42
+ cwd: normalCwd,
43
+ within,
44
+ depth: maxDepth,
45
+ fastDepth,
46
+ fastInternal,
47
+ fs,
48
+ invert,
49
+ signal,
50
+ target,
51
+ };
52
+ await target.init?.({ ctx, cwd, fs, signal });
53
+ let from = join(unixify(normalCwd), within);
54
+ await opendir(fs, from, (entry) => {
55
+ const path = relative(normalCwd, unixify(entry.parentPath) + "/" + entry.name);
56
+ return walkIncludes({
57
+ path,
58
+ entry,
59
+ ctx,
60
+ stream: this,
61
+ scanOptions,
62
+ });
63
+ });
64
+ this.emit("end", ctx);
65
+ }
9
66
  }
@@ -7,3 +7,11 @@ import { type Source } from "./source.js";
7
7
  * @since 0.6.0
8
8
  */
9
9
  export declare function extractPackageJson(source: Source, content: Buffer): void | "none";
10
+ /**
11
+ * Extracts and compiles patterns from the file.
12
+ *
13
+ * @see {@link signedPatternCompile}
14
+ *
15
+ * @since 0.8.0
16
+ */
17
+ export declare function extractPackageJsonNocase(source: Source, content: Buffer): void | "none";
@@ -1,12 +1,12 @@
1
1
  import { type } from "arktype";
2
2
  import { signedPatternCompile } from "./resolveSources.js";
3
3
  import { sourcePushNegatable } from "./source.js";
4
- const nodeJsManifest = type({
5
- files: "string[]?",
4
+ const npmManifest = type({
5
+ "files?": "string[]",
6
6
  });
7
7
  const parse = type("string")
8
8
  .pipe((s) => JSON.parse(s))
9
- .pipe(nodeJsManifest);
9
+ .pipe(npmManifest);
10
10
  /**
11
11
  * Extracts and compiles patterns from the file.
12
12
  *
@@ -15,11 +15,34 @@ const parse = type("string")
15
15
  * @since 0.6.0
16
16
  */
17
17
  export function extractPackageJson(source, content) {
18
+ const result = extract(source, content);
19
+ if (result === undefined)
20
+ signedPatternCompile(source.pattern);
21
+ if (result === "error")
22
+ return;
23
+ return result;
24
+ }
25
+ /**
26
+ * Extracts and compiles patterns from the file.
27
+ *
28
+ * @see {@link signedPatternCompile}
29
+ *
30
+ * @since 0.8.0
31
+ */
32
+ export function extractPackageJsonNocase(source, content) {
33
+ const result = extract(source, content);
34
+ if (result === undefined)
35
+ signedPatternCompile(source.pattern, { nocase: true });
36
+ if (result === "error")
37
+ return;
38
+ return result;
39
+ }
40
+ function extract(source, content) {
18
41
  source.inverted = true;
19
42
  const dist = parse(content.toString());
20
43
  if (dist instanceof type.errors) {
21
44
  source.error = new Error("Invalid '" + source.path + "': " + dist.summary, { cause: dist });
22
- return;
45
+ return "error";
23
46
  }
24
47
  if (!dist.files) {
25
48
  return "none";
@@ -27,6 +50,5 @@ export function extractPackageJson(source, content) {
27
50
  for (const pattern of dist.files) {
28
51
  sourcePushNegatable(source, pattern);
29
52
  }
30
- signedPatternCompile(source.pattern);
31
53
  }
32
54
  extractPackageJson;
@@ -1,3 +1,4 @@
1
+ import { type StringCompileOptions } from "./stringCompile.js";
1
2
  /**
2
3
  * Compiled pattern.
3
4
  *
@@ -41,4 +42,4 @@ export type Pattern = string[];
41
42
  *
42
43
  * @since 0.6.0
43
44
  */
44
- export declare function patternCompile(pattern: Pattern): PatternMinimatch[];
45
+ export declare function patternCompile(pattern: Pattern, options?: StringCompileOptions): PatternMinimatch[];
@@ -16,6 +16,6 @@ export function patternMinimatchTest(pattern, path) {
16
16
  *
17
17
  * @since 0.6.0
18
18
  */
19
- export function patternCompile(pattern) {
20
- return pattern.map(stringCompile);
19
+ export function patternCompile(pattern, options) {
20
+ return pattern.map((p, _, pattern) => stringCompile(p, pattern, options));
21
21
  }
@@ -1,5 +1,6 @@
1
1
  import type { PatternFinderOptions } from "./extractor.js";
2
2
  import type { SignedPattern } from "./signedPattern.js";
3
+ import type { StringCompileOptions } from "./stringCompile.js";
3
4
  /**
4
5
  * Compiles the {@link SignedPattern} (forced).
5
6
  * Can be compiled at any time.
@@ -9,7 +10,7 @@ import type { SignedPattern } from "./signedPattern.js";
9
10
  *
10
11
  * @since 0.6.0
11
12
  */
12
- export declare function signedPatternCompile(signedPattern: SignedPattern): SignedPattern;
13
+ export declare function signedPatternCompile(signedPattern: SignedPattern, options?: StringCompileOptions): SignedPattern;
13
14
  /**
14
15
  * @see {@link resolveSources}
15
16
  *
@@ -1,4 +1,5 @@
1
- import { dirname, relative, resolve } from "node:path";
1
+ import { dirname } from "node:path";
2
+ import { unixify, relative, join } from "../unixify.js";
2
3
  import { patternCompile } from "./pattern.js";
3
4
  /**
4
5
  * Compiles the {@link SignedPattern} (forced).
@@ -9,10 +10,10 @@ import { patternCompile } from "./pattern.js";
9
10
  *
10
11
  * @since 0.6.0
11
12
  */
12
- export function signedPatternCompile(signedPattern) {
13
+ export function signedPatternCompile(signedPattern, options) {
13
14
  signedPattern.compiled = {
14
- include: patternCompile(signedPattern.include),
15
- exclude: patternCompile(signedPattern.exclude),
15
+ include: patternCompile(signedPattern.include, options),
16
+ exclude: patternCompile(signedPattern.exclude, options),
16
17
  };
17
18
  return signedPattern;
18
19
  }
@@ -22,7 +23,7 @@ export function signedPatternCompile(signedPattern) {
22
23
  * @since 0.6.0
23
24
  */
24
25
  export async function resolveSources(options) {
25
- const { fs, ctx, cwd, target, root } = options;
26
+ const { fs, ctx, cwd, target, root, signal } = options;
26
27
  let dir = options.dir;
27
28
  if (ctx.external.has(dir)) {
28
29
  return;
@@ -33,6 +34,7 @@ export async function resolveSources(options) {
33
34
  dir = dirname(dir);
34
35
  // find source from an ancestor [dir < ... < cwd]
35
36
  while (true) {
37
+ signal?.throwIfAborted();
36
38
  source = ctx.external.get(dir);
37
39
  if (source !== undefined) {
38
40
  // if cache is found populate descendants [cwd > ... > dir]
@@ -56,6 +58,7 @@ export async function resolveSources(options) {
56
58
  {
57
59
  let c = dirname(cwd);
58
60
  while (true) {
61
+ signal?.throwIfAborted();
59
62
  preCwdSegments.push(c);
60
63
  if (c === "/" || c === root)
61
64
  break;
@@ -64,23 +67,26 @@ export async function resolveSources(options) {
64
67
  }
65
68
  preCwdSegments.reverse();
66
69
  }
67
- source = await findSourceForAbsoluteDirs(preCwdSegments, ctx, fs, target);
70
+ source = await findSourceForAbsoluteDirs(preCwdSegments, ctx, fs, target, signal);
68
71
  if (typeof source === "object") {
69
72
  for (const noSourceDir of noSourceDirList) {
73
+ signal?.throwIfAborted();
70
74
  ctx.external.set(noSourceDir, source);
71
75
  }
72
76
  }
73
- const rels = noSourceDirList.map((rel) => resolve(cwd, rel).replaceAll("\\", "/").replace(/\w:/, ""));
74
- source = await findSourceForAbsoluteDirs(rels, ctx, fs, target);
77
+ const absPaths = noSourceDirList.map((rel) => join(cwd, rel));
78
+ source = await findSourceForAbsoluteDirs(absPaths, ctx, fs, target, signal);
75
79
  if (source !== undefined) {
76
80
  for (const noSourceDir of noSourceDirList) {
81
+ signal?.throwIfAborted();
77
82
  ctx.external.set(noSourceDir, source);
78
83
  }
79
84
  }
80
85
  }
81
- async function findSourceForAbsoluteDirs(paths, ctx, fs, target) {
86
+ async function findSourceForAbsoluteDirs(paths, ctx, fs, target, signal) {
82
87
  for (const parent of paths) {
83
88
  for (const extractor of target.extractors) {
89
+ signal?.throwIfAborted();
84
90
  const s = await tryExtractor(parent, fs, ctx, extractor);
85
91
  if (typeof s === "object" && s.error) {
86
92
  ctx.failed.push(s);
@@ -94,7 +100,13 @@ async function findSourceForAbsoluteDirs(paths, ctx, fs, target) {
94
100
  return "none";
95
101
  }
96
102
  async function tryExtractor(cwd, fs, ctx, extractor) {
97
- const abs = resolve(cwd, extractor.path);
103
+ let abs = unixify(cwd);
104
+ if (abs.endsWith("/")) {
105
+ abs += extractor.path;
106
+ }
107
+ else {
108
+ abs += "/" + extractor.path;
109
+ }
98
110
  const path = relative(cwd, abs);
99
111
  const name = path.substring(path.lastIndexOf("/") + 1);
100
112
  const newSource = {
@@ -1,9 +1,22 @@
1
1
  import type { PatternMinimatch, Pattern } from "./pattern.js";
2
+ /**
3
+ * @since 0.8.0
4
+ */
5
+ export type StringCompileOptions = {
6
+ /**
7
+ * Disables case sensitivity.
8
+ *
9
+ * @default false
10
+ *
11
+ * @since 0.8.0
12
+ */
13
+ nocase?: boolean;
14
+ };
2
15
  /**
3
16
  * Compiles a string of the {@link Pattern}.
4
17
  *
5
18
  * @see {@link patternCompile}
6
19
  *
7
- * @since 0.6.0
20
+ * @since 0.8.0
8
21
  */
9
- export declare function stringCompile(pattern: string, _?: number, array?: Pattern): PatternMinimatch;
22
+ export declare function stringCompile(pattern: string, context?: Pattern, options?: StringCompileOptions): PatternMinimatch;
@@ -4,9 +4,9 @@ import { makeRe } from "minimatch";
4
4
  *
5
5
  * @see {@link patternCompile}
6
6
  *
7
- * @since 0.6.0
7
+ * @since 0.8.0
8
8
  */
9
- export function stringCompile(pattern, _ = -1, array = []) {
9
+ export function stringCompile(pattern, context = [], options) {
10
10
  const original = pattern;
11
11
  if (pattern.endsWith("/")) {
12
12
  pattern = pattern.substring(0, pattern.length - 1);
@@ -23,6 +23,7 @@ export function stringCompile(pattern, _ = -1, array = []) {
23
23
  nonegate: true,
24
24
  nocomment: true,
25
25
  nobrace: true,
26
+ nocase: options?.nocase ?? false,
26
27
  });
27
- return { re, pattern: original, patternContext: array };
28
+ return { re, pattern: original, patternContext: context };
28
29
  }
package/out/scan.d.ts CHANGED
@@ -4,7 +4,7 @@ export type * from "./types.js";
4
4
  /**
5
5
  * Scan the directory for included files based on the provided targets.
6
6
  *
7
- * Note that this function uses `fs/promises.readFile` and `fs/promises.opendir` without options within
7
+ * Note that this function uses `fs.promises.readFile` and `fs.promises.opendir` without options within
8
8
  * custom recursion, instead of `fs.promises.readdir` with `{ withFileTypes: true }.
9
9
  * It also normalizes paths to use forward slashes.
10
10
  * Please report any issues if you encounter problems related to this behavior.
package/out/scan.js CHANGED
@@ -4,7 +4,7 @@ import { scan as browserScan } from "./browser_scan.js";
4
4
  /**
5
5
  * Scan the directory for included files based on the provided targets.
6
6
  *
7
- * Note that this function uses `fs/promises.readFile` and `fs/promises.opendir` without options within
7
+ * Note that this function uses `fs.promises.readFile` and `fs.promises.opendir` without options within
8
8
  * custom recursion, instead of `fs.promises.readdir` with `{ withFileTypes: true }.
9
9
  * It also normalizes paths to use forward slashes.
10
10
  * Please report any issues if you encounter problems related to this behavior.
@@ -4,3 +4,4 @@ export * from "./npm.js";
4
4
  export * from "./target.js";
5
5
  export * from "./vsce.js";
6
6
  export * from "./yarn.js";
7
+ export * from "./yarnClassic.js";
@@ -4,3 +4,4 @@ export * from "./npm.js";
4
4
  export * from "./target.js";
5
5
  export * from "./vsce.js";
6
6
  export * from "./yarn.js";
7
+ export * from "./yarnClassic.js";
@@ -15,25 +15,47 @@ const extractors = [
15
15
  ];
16
16
  const internal = {
17
17
  exclude: [
18
- ".git",
19
- ".DS_Store",
20
- "node_modules",
21
- ".*.swp",
22
- "._*",
23
- ".DS_Store",
24
- ".git",
18
+ // https://github.com/npm/npm-packlist/blob/main/lib/index.js#L16
19
+ ".npmignore",
25
20
  ".gitignore",
21
+ ".git",
22
+ ".svn",
26
23
  ".hg",
27
- ".npmignore",
28
- ".npmrc",
29
- ".lock-wscript",
24
+ "CVS",
25
+ ".git",
30
26
  ".svn",
31
- ".wafpickle-*",
32
- "config.gypi",
27
+ ".hg",
33
28
  "CVS",
29
+ "/.lock-wscript",
30
+ "/.wafpickle-*",
31
+ "/build/config.gypi",
34
32
  "npm-debug.log",
33
+ ".npmrc",
34
+ ".*.swp",
35
+ ".DS_Store",
36
+ "._*",
37
+ "*.orig",
38
+ "/archived-packages/**",
39
+ // https://github.com/npm/npm-packlist/blob/main/lib/index.js#L294
40
+ "/node_modules",
41
+ "/package-lock.json",
42
+ "/yarn.lock",
43
+ "/pnpm-lock.yaml",
44
+ "/bun.lockb",
45
+ ],
46
+ include: [
47
+ // https://github.com/npm/npm-packlist/blob/main/lib/index.js#L287
48
+ "bin",
49
+ "package.json",
50
+ "README",
51
+ "COPYING",
52
+ "LICENSE",
53
+ "LICENCE",
54
+ "README.*",
55
+ "COPYING.*",
56
+ "LICENSE.*",
57
+ "LICENCE.*",
35
58
  ],
36
- include: ["bin", "package.json", "README*", "LICENSE*", "LICENCE*"],
37
59
  compiled: null,
38
60
  };
39
61
  signedPatternCompile(internal);
@@ -1,5 +1,6 @@
1
1
  import type { Extractor } from "../patterns/extractor.js";
2
2
  import type { Ignores } from "../patterns/ignores.js";
3
+ import type { Init } from "../patterns/init.js";
3
4
  /**
4
5
  * Contains the matcher used for scanning.
5
6
  *
@@ -21,4 +22,16 @@ export interface Target {
21
22
  * @since 0.6.0
22
23
  */
23
24
  ignores: Ignores;
25
+ /**
26
+ * Initialization function.
27
+ * Called by the scanner method.
28
+ *
29
+ * @example
30
+ * scan({ target: { ...Git, init: undefined } })
31
+ *
32
+ * @see {@link Init}
33
+ *
34
+ * @since 0.8.0
35
+ */
36
+ init?: Init;
24
37
  }
@@ -14,7 +14,40 @@ const extractors = [
14
14
  },
15
15
  ];
16
16
  const internal = {
17
- exclude: [".git", ".DS_Store"],
17
+ exclude: [
18
+ // https://github.com/microsoft/vscode-vsce/blob/main/src/package.ts#L1633
19
+ ".vscodeignore",
20
+ "package-lock.json",
21
+ "npm-debug.log",
22
+ "yarn.lock",
23
+ "yarn-error.log",
24
+ "npm-shrinkwrap.json",
25
+ ".editorconfig",
26
+ ".npmrc",
27
+ ".yarnrc",
28
+ ".gitattributes",
29
+ "*.todo",
30
+ "tslint.yaml",
31
+ ".eslintrc*",
32
+ ".babelrc*",
33
+ ".prettierrc*",
34
+ ".cz-config.js",
35
+ ".commitlintrc*",
36
+ "webpack.config.js",
37
+ "ISSUE_TEMPLATE.md",
38
+ "CONTRIBUTING.md",
39
+ "PULL_REQUEST_TEMPLATE.md",
40
+ "CODE_OF_CONDUCT.md",
41
+ ".github",
42
+ ".travis.yml",
43
+ "appveyor.yml",
44
+ ".git",
45
+ "*.vsix",
46
+ ".DS_Store",
47
+ "*.vsixmanifest",
48
+ ".vscode-test",
49
+ ".vscode-test-web",
50
+ ],
18
51
  include: [],
19
52
  compiled: null,
20
53
  };
@@ -1,52 +1,98 @@
1
- import { signedPatternIgnores, signedPatternCompile, extractPackageJson, extractGitignore, } from "../patterns/index.js";
1
+ import { type } from "arktype";
2
+ import { signedPatternIgnores, signedPatternCompile, extractPackageJsonNocase, extractGitignoreNocase, } from "../patterns/index.js";
3
+ import { join, unixify } from "../unixify.js";
2
4
  const extractors = [
3
5
  {
4
- extract: extractPackageJson,
6
+ extract: extractPackageJsonNocase,
5
7
  path: "package.json",
6
8
  },
7
9
  {
8
- extract: extractGitignore,
9
- path: ".yarnignore",
10
- },
11
- {
12
- extract: extractGitignore,
10
+ extract: extractGitignoreNocase,
13
11
  path: ".npmignore",
14
12
  },
15
13
  {
16
- extract: extractGitignore,
14
+ extract: extractGitignoreNocase,
17
15
  path: ".gitignore",
18
16
  },
19
17
  ];
18
+ const include = [
19
+ // https://github.com/yarnpkg/berry/blob/master/packages/plugin-pack/sources/packUtils.ts#L10
20
+ "/package.json",
21
+ "/README",
22
+ "/README.*",
23
+ "/LICENSE",
24
+ "/LICENSE.*",
25
+ "/LICENCE",
26
+ "/LICENCE.*",
27
+ ];
20
28
  const internal = {
21
29
  exclude: [
30
+ // https://github.com/yarnpkg/berry/blob/master/packages/plugin-pack/sources/packUtils.ts#L26
31
+ "/package.tgz",
32
+ ".github",
22
33
  ".git",
23
- ".DS_Store",
24
- "node_modules",
25
- ".*.swp",
26
- "._*",
27
- ".DS_Store",
28
- ".git",
29
- ".gitignore",
30
34
  ".hg",
35
+ "node_modules",
31
36
  ".npmignore",
32
- ".npmrc",
33
- ".lock-wscript",
34
- ".svn",
35
- ".wafpickle-*",
36
- "config.gypi",
37
- "CVS",
38
- "npm-debug.log",
39
- ".yarnignore",
40
- ".yarnrc",
37
+ ".gitignore",
38
+ ".#*",
39
+ ".DS_Store",
41
40
  ],
42
- include: ["bin", "package.json", "README*", "LICENSE*", "LICENCE*"],
41
+ include: [...include],
43
42
  compiled: null,
44
43
  };
45
- signedPatternCompile(internal);
44
+ signedPatternCompile(internal, { nocase: true });
45
+ const npmManifest = type({
46
+ "main?": "string",
47
+ "module?": "string",
48
+ "browser?": "string",
49
+ "bin?": "string | Record<string, string>",
50
+ });
51
+ const parse = type("string")
52
+ .pipe((s) => JSON.parse(s))
53
+ .pipe(npmManifest);
46
54
  /**
47
55
  * @since 0.6.0
48
56
  */
49
57
  export const Yarn = {
58
+ async init({ fs, cwd }) {
59
+ let content;
60
+ const normalCwd = unixify(cwd);
61
+ try {
62
+ content = await fs.promises.readFile(normalCwd + "/" + "package.json");
63
+ }
64
+ catch (error) {
65
+ if (error.code === "ENOENT") {
66
+ return; // no package.json
67
+ }
68
+ throw new Error("Error while initializing Yarn's ignoring implementation", { cause: error });
69
+ }
70
+ const dist = parse(content.toString());
71
+ if (dist instanceof type.errors) {
72
+ throw new Error("Invalid 'package.json': " + dist.summary, { cause: dist });
73
+ }
74
+ // https://github.com/yarnpkg/berry/blob/master/packages/plugin-pack/sources/packUtils.ts#L215-L231
75
+ const set = new Set(include);
76
+ function normal(path) {
77
+ const result = unixify(join(normalCwd, path)).substring(normalCwd.length);
78
+ return result;
79
+ }
80
+ if (dist.main)
81
+ set.add(normal(dist.main));
82
+ if (dist.module)
83
+ set.add(normal(dist.module));
84
+ if (dist.browser)
85
+ set.add(normal(dist.browser));
86
+ if (typeof dist.bin === "string") {
87
+ set.add(normal(dist.bin));
88
+ }
89
+ else if (typeof dist.bin === "object" && dist.bin !== null) {
90
+ Object.values(dist.bin).forEach((binPath) => set.add(normal(binPath)));
91
+ }
92
+ internal.include.length = 0;
93
+ internal.include.push(...set);
94
+ signedPatternCompile(internal, { nocase: true });
95
+ },
50
96
  extractors,
51
97
  ignores(o) {
52
98
  return signedPatternIgnores({
@@ -0,0 +1,5 @@
1
+ import type { Target } from "./target.js";
2
+ /**
3
+ * @since 0.8.0
4
+ */
5
+ export declare const YarnClassic: Target;
@@ -0,0 +1,77 @@
1
+ import { signedPatternIgnores, signedPatternCompile, extractPackageJsonNocase, extractGitignoreNocase, } from "../patterns/index.js";
2
+ const extractors = [
3
+ {
4
+ extract: extractPackageJsonNocase,
5
+ path: "package.json",
6
+ },
7
+ {
8
+ extract: extractGitignoreNocase,
9
+ path: ".yarnignore",
10
+ },
11
+ {
12
+ extract: extractGitignoreNocase,
13
+ path: ".npmignore",
14
+ },
15
+ {
16
+ extract: extractGitignoreNocase,
17
+ path: ".gitignore",
18
+ },
19
+ ];
20
+ const internal = {
21
+ exclude: [
22
+ // https://github.com/yarnpkg/berry/blob/master/packages/plugin-pack/sources/packUtils.ts#L26
23
+ ".git",
24
+ "CVS",
25
+ ".svn",
26
+ ".hg",
27
+ "node_modules",
28
+ "yarn.lock",
29
+ ".lock-wscript",
30
+ ".wafpickle-0",
31
+ ".wafpickle-1",
32
+ ".wafpickle-2",
33
+ ".wafpickle-3",
34
+ ".wafpickle-4",
35
+ ".wafpickle-5",
36
+ ".wafpickle-6",
37
+ ".wafpickle-7",
38
+ ".wafpickle-8",
39
+ ".wafpickle-9",
40
+ "*.swp",
41
+ "._*",
42
+ "npm-debug.log",
43
+ "yarn-error.log",
44
+ ".npmrc",
45
+ ".yarnrc",
46
+ ".yarnrc.yml",
47
+ ".npmignore",
48
+ ".gitignore",
49
+ ".DS_Store",
50
+ ],
51
+ include: [
52
+ // https://github.com/yarnpkg/berry/blob/master/packages/plugin-pack/sources/packUtils.ts#L10
53
+ "/package.json",
54
+ "/readme*",
55
+ "/license*",
56
+ "/licence*",
57
+ "/changes*",
58
+ "/changelog*",
59
+ "/history*",
60
+ ],
61
+ compiled: null,
62
+ };
63
+ signedPatternCompile(internal, { nocase: true });
64
+ /**
65
+ * @since 0.8.0
66
+ */
67
+ export const YarnClassic = {
68
+ extractors,
69
+ ignores(o) {
70
+ return signedPatternIgnores({
71
+ ...o,
72
+ internal,
73
+ root: ".",
74
+ target: YarnClassic,
75
+ });
76
+ },
77
+ };
package/out/types.d.ts CHANGED
@@ -26,7 +26,7 @@ export type ScanOptions = {
26
26
  /**
27
27
  * Current working directory to start the scan from.
28
28
  *
29
- * @default `normalizeCwd(process.cwd())`
29
+ * @default `unixify(process.cwd())`
30
30
  *
31
31
  * @since 0.6.0
32
32
  */
@@ -0,0 +1,3 @@
1
+ export declare function unixify(path: string): string;
2
+ export declare function join(from: string, p2: string): string;
3
+ export declare function relative(base: string, to: string): string;
package/out/unixify.js ADDED
@@ -0,0 +1,33 @@
1
+ const strippedCwd = strip(process.cwd());
2
+ export function unixify(path) {
3
+ let result = strip(path);
4
+ if (result.startsWith("./")) {
5
+ result = strippedCwd + result.substring(1);
6
+ }
7
+ else if (!result.startsWith("/")) {
8
+ result = strippedCwd + "/" + result;
9
+ }
10
+ return result;
11
+ }
12
+ export function join(from, p2) {
13
+ if (p2 === "." || p2 === "./") {
14
+ return from;
15
+ }
16
+ else if (p2.startsWith("./")) {
17
+ from += "/" + p2.substring(2);
18
+ }
19
+ else {
20
+ from += "/" + p2;
21
+ }
22
+ return from;
23
+ }
24
+ export function relative(base, to) {
25
+ if (!base.endsWith("/")) {
26
+ base += "/";
27
+ }
28
+ const result = to.replace(base, "");
29
+ return result;
30
+ }
31
+ function strip(path) {
32
+ return path.replaceAll("\\", "/").replace(/\w:/, "");
33
+ }
package/out/walk.js CHANGED
@@ -17,7 +17,7 @@ export async function walkIncludes(options) {
17
17
  const { depth, depthSlash } = getDepth(path, maxDepth);
18
18
  if (depth > maxDepth) {
19
19
  const failedPrev = ctx.failed.length;
20
- let match = await target.ignores({ fs, cwd, entry: path, ctx });
20
+ let match = await target.ignores({ fs, cwd, entry: path, ctx, signal });
21
21
  if (invert) {
22
22
  match.ignored = !match.ignored;
23
23
  }
@@ -45,7 +45,7 @@ export async function walkIncludes(options) {
45
45
  }
46
46
  }
47
47
  const failedPrev = ctx.failed.length;
48
- let match = await target.ignores({ fs, cwd, entry: path, ctx });
48
+ let match = await target.ignores({ fs, cwd, entry: path, ctx, signal });
49
49
  if (invert) {
50
50
  match.ignored = !match.ignored;
51
51
  }
@@ -88,10 +88,10 @@ export async function walkIncludes(options) {
88
88
  if (lastSlash >= 0) {
89
89
  const dir = path.substring(0, lastSlash) + "/";
90
90
  const dirMatch = ctx.paths.get(dir);
91
- if (dirMatch?.ignored) {
91
+ if (dirMatch === undefined || dirMatch.ignored) {
92
92
  ctx.paths.set(dir, match);
93
93
  if (stream) {
94
- stream.emit("dirent", { dirent: entry, match, path: direntPath, ctx });
94
+ stream.emit("dirent", { dirent: entry, match, path: dir, ctx });
95
95
  }
96
96
  }
97
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "view-ignored",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Retrieve list of files ignored/included by Git, NPM, Yarn, JSR, VSCE or other tools.",
5
5
  "keywords": [
6
6
  ".gitignore",
@@ -100,9 +100,12 @@
100
100
  "devDependencies": {
101
101
  "@release-it/keep-a-changelog": "^7.0.1",
102
102
  "@types/bun": "^1.3.8",
103
+ "@types/ignore-walk": "^4.0.3",
103
104
  "@types/node": "^18.19.130",
104
105
  "@typescript/native-preview": "^7.0.0-dev.20260209.1",
106
+ "ignore-walk": "^8.0.0",
105
107
  "memfs": "^4.56.10",
108
+ "mitata": "^1.0.34",
106
109
  "oxfmt": "^0.28.0",
107
110
  "oxlint": "^1.43.0",
108
111
  "oxlint-tsgolint": "^0.11.5",
@@ -1 +0,0 @@
1
- export declare function normalizeCwd(cwd: string): string;
@@ -1,4 +0,0 @@
1
- import { resolve } from "node:path";
2
- export function normalizeCwd(cwd) {
3
- return resolve(cwd).replaceAll("\\", "/").replace(/\w:/, "");
4
- }