view-ignored 0.4.7 → 0.5.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.
- package/README.md +64 -96
- package/out/index.d.ts +1 -4
- package/out/index.js +1 -4
- package/out/patterns/gitignore.d.ts +3 -0
- package/out/patterns/gitignore.js +35 -0
- package/out/patterns/index.d.ts +4 -0
- package/out/patterns/index.js +4 -0
- package/out/patterns/jsrjson.d.ts +4 -0
- package/out/patterns/jsrjson.js +39 -0
- package/out/patterns/matcher.d.ts +39 -0
- package/out/patterns/matcher.js +118 -0
- package/out/patterns/packagejson.d.ts +3 -0
- package/out/patterns/packagejson.js +25 -0
- package/out/scan.d.ts +46 -0
- package/out/scan.js +113 -0
- package/out/targets/git.d.ts +2 -0
- package/out/targets/git.js +22 -0
- package/out/targets/index.d.ts +6 -0
- package/out/targets/index.js +6 -0
- package/out/targets/jsr.d.ts +2 -0
- package/out/targets/jsr.js +25 -0
- package/out/targets/npm.d.ts +2 -0
- package/out/targets/npm.js +46 -0
- package/out/targets/target.d.ts +7 -0
- package/out/targets/target.js +1 -0
- package/out/targets/vsce.d.ts +2 -0
- package/out/targets/vsce.js +24 -0
- package/out/targets/yarn.d.ts +2 -0
- package/out/targets/yarn.js +49 -0
- package/out/walk.d.ts +2 -0
- package/out/walk.js +19 -0
- package/package.json +21 -55
- package/bin/viewig +0 -4
- package/out/browser/binds/index.d.ts +0 -56
- package/out/browser/binds/index.d.ts.map +0 -1
- package/out/browser/binds/index.js +0 -95
- package/out/browser/binds/index.js.map +0 -1
- package/out/browser/binds/plugins/git.d.ts +0 -23
- package/out/browser/binds/plugins/git.d.ts.map +0 -1
- package/out/browser/binds/plugins/git.js +0 -67
- package/out/browser/binds/plugins/git.js.map +0 -1
- package/out/browser/binds/plugins/jsr.d.ts +0 -39
- package/out/browser/binds/plugins/jsr.d.ts.map +0 -1
- package/out/browser/binds/plugins/jsr.js +0 -117
- package/out/browser/binds/plugins/jsr.js.map +0 -1
- package/out/browser/binds/plugins/npm.d.ts +0 -39
- package/out/browser/binds/plugins/npm.d.ts.map +0 -1
- package/out/browser/binds/plugins/npm.js +0 -146
- package/out/browser/binds/plugins/npm.js.map +0 -1
- package/out/browser/binds/plugins/vsce.d.ts +0 -26
- package/out/browser/binds/plugins/vsce.d.ts.map +0 -1
- package/out/browser/binds/plugins/vsce.js +0 -71
- package/out/browser/binds/plugins/vsce.js.map +0 -1
- package/out/browser/binds/plugins/yarn.d.ts +0 -12
- package/out/browser/binds/plugins/yarn.d.ts.map +0 -1
- package/out/browser/binds/plugins/yarn.js +0 -36
- package/out/browser/binds/plugins/yarn.js.map +0 -1
- package/out/browser/binds/scanner.d.ts +0 -47
- package/out/browser/binds/scanner.d.ts.map +0 -1
- package/out/browser/binds/scanner.js +0 -166
- package/out/browser/binds/scanner.js.map +0 -1
- package/out/browser/binds/targets.d.ts +0 -78
- package/out/browser/binds/targets.d.ts.map +0 -1
- package/out/browser/binds/targets.js +0 -46
- package/out/browser/binds/targets.js.map +0 -1
- package/out/browser/conc.d.ts +0 -2
- package/out/browser/conc.d.ts.map +0 -1
- package/out/browser/conc.js +0 -19
- package/out/browser/conc.js.map +0 -1
- package/out/browser/errors.d.ts +0 -47
- package/out/browser/errors.d.ts.map +0 -1
- package/out/browser/errors.js +0 -35
- package/out/browser/errors.js.map +0 -1
- package/out/browser/filtering.d.ts +0 -13
- package/out/browser/filtering.d.ts.map +0 -1
- package/out/browser/filtering.js +0 -12
- package/out/browser/filtering.js.map +0 -1
- package/out/browser/fs/directory.d.ts +0 -145
- package/out/browser/fs/directory.d.ts.map +0 -1
- package/out/browser/fs/directory.js +0 -244
- package/out/browser/fs/directory.js.map +0 -1
- package/out/browser/fs/file-info.d.ts +0 -89
- package/out/browser/fs/file-info.d.ts.map +0 -1
- package/out/browser/fs/file-info.js +0 -101
- package/out/browser/fs/file-info.js.map +0 -1
- package/out/browser/fs/file.d.ts +0 -39
- package/out/browser/fs/file.d.ts.map +0 -1
- package/out/browser/fs/file.js +0 -42
- package/out/browser/fs/file.js.map +0 -1
- package/out/browser/fs/index.d.ts +0 -5
- package/out/browser/fs/index.d.ts.map +0 -1
- package/out/browser/fs/index.js +0 -5
- package/out/browser/fs/index.js.map +0 -1
- package/out/browser/fs/source-info.d.ts +0 -29
- package/out/browser/fs/source-info.d.ts.map +0 -1
- package/out/browser/fs/source-info.js +0 -31
- package/out/browser/fs/source-info.js.map +0 -1
- package/out/browser/index.d.ts +0 -4
- package/out/browser/index.d.ts.map +0 -1
- package/out/browser/index.js +0 -4
- package/out/browser/index.js.map +0 -1
- package/out/browser/lib.d.ts +0 -138
- package/out/browser/lib.d.ts.map +0 -1
- package/out/browser/lib.js +0 -89
- package/out/browser/lib.js.map +0 -1
- package/out/browser/sorting.d.ts +0 -52
- package/out/browser/sorting.d.ts.map +0 -1
- package/out/browser/sorting.js +0 -137
- package/out/browser/sorting.js.map +0 -1
- package/out/browser/styling.d.ts +0 -92
- package/out/browser/styling.d.ts.map +0 -1
- package/out/browser/styling.js +0 -66
- package/out/browser/styling.js.map +0 -1
- package/out/cli.d.ts +0 -90
- package/out/cli.d.ts.map +0 -1
- package/out/cli.js +0 -361
- package/out/cli.js.map +0 -1
- package/out/config.d.ts +0 -186
- package/out/config.d.ts.map +0 -1
- package/out/config.js +0 -370
- package/out/config.js.map +0 -1
- package/out/errors.d.ts +0 -7
- package/out/errors.d.ts.map +0 -1
- package/out/errors.js +0 -3
- package/out/errors.js.map +0 -1
- package/out/index.d.ts.map +0 -1
- package/out/index.js.map +0 -1
- package/out/lib.d.ts +0 -5
- package/out/lib.d.ts.map +0 -1
- package/out/lib.js +0 -5
- package/out/lib.js.map +0 -1
- package/out/styling.d.ts +0 -5
- package/out/styling.d.ts.map +0 -1
- package/out/styling.js +0 -49
- package/out/styling.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,124 +5,88 @@
|
|
|
5
5
|
[](https://github.com/Mopsgamer/view-ignored)
|
|
6
6
|
[](https://github.com/Mopsgamer/view-ignored/issues)
|
|
7
7
|
|
|
8
|
-
Retrieve list of files ignored/included
|
|
9
|
-
tools.
|
|
8
|
+
Retrieve list of files ignored/included
|
|
9
|
+
by Git, NPM, Yarn, JSR, VSCE or other tools.
|
|
10
10
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- Node.js 18 or later for production
|
|
14
|
+
- Node.js 20 or later for production type definitions
|
|
15
|
+
- Node.js 22 or later for development type definitions
|
|
14
16
|
|
|
15
17
|
## Highlights
|
|
16
18
|
|
|
17
|
-
- **
|
|
19
|
+
- **Native.** Get a list of included files using configuration file
|
|
18
20
|
readers, not command-line wrappers.
|
|
19
|
-
- **
|
|
20
|
-
|
|
21
|
-
- **
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
- **Plugins.** Built-in [targets](#targets) for popular tools. Use custom
|
|
22
|
+
targets by implementing the `Target` interface.
|
|
23
|
+
- **TypeScript.** Written in TypeScript with type definitions included.
|
|
24
|
+
- **Lightweight.** Minimal dependencies for fast performance and small bundle size.
|
|
25
|
+
- **Easy-to-modify.** Well-written and MIT-licensed.
|
|
26
|
+
|
|
27
|
+
> [!NOTE]
|
|
28
|
+
> Despite the name of the package being "view-ignored",
|
|
29
|
+
> the primary purpose is to get the list of
|
|
30
|
+
> **included** files, i.e., files that are **not ignored**.
|
|
31
|
+
> You can invert the results if you need the ignored files
|
|
32
|
+
> by setting the `invert` option to `true`.
|
|
27
33
|
|
|
28
34
|
## Usage
|
|
29
35
|
|
|
30
|
-
###
|
|
31
|
-
|
|
32
|
-
After installing globally, you can use the following commands:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
# get started
|
|
36
|
-
npm i -g view-ignored
|
|
37
|
-
viewig --help
|
|
38
|
-
view-ignored --help
|
|
39
|
-
|
|
40
|
-
# scan: git (default) and npm
|
|
41
|
-
viewig scan
|
|
42
|
-
viewig scan --target=npm
|
|
43
|
-
viewig sc -t npm
|
|
44
|
-
viewig scan --parsable
|
|
45
|
-
|
|
46
|
-
# scan: plugins (space, comma or pipe separated)
|
|
47
|
-
# all built-in plugins loaded automatically
|
|
48
|
-
# Replace example1/example2 with real plugin names
|
|
49
|
-
viewig scan --plugins="example1, example2"
|
|
50
|
-
viewig scan --plugins="example1 example2"
|
|
51
|
-
viewig scan --plugins example1 example2
|
|
52
|
-
viewig scan --plugins example1, example2
|
|
53
|
-
|
|
54
|
-
# config: print configuration entries
|
|
55
|
-
viewig config get
|
|
56
|
-
viewig config get --real
|
|
57
|
-
# config: set npm as default target and scan for npm
|
|
58
|
-
viewig config set target=npm
|
|
59
|
-
viewig scan
|
|
60
|
-
# config: always use nerdfonts
|
|
61
|
-
viewig config set style=tree
|
|
62
|
-
# config: always use Nerd Fonts for decoration
|
|
63
|
-
viewig config set decor=nerdfonts
|
|
64
|
-
# config: always use plugins
|
|
65
|
-
viewig config set plugins=example1,example2
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Programmatically
|
|
36
|
+
### Basic example
|
|
69
37
|
|
|
70
|
-
|
|
38
|
+
```ts
|
|
39
|
+
import * as vign from "view-ignored";
|
|
40
|
+
import { Git } from "view-ignored/targets";
|
|
71
41
|
|
|
72
|
-
|
|
73
|
-
|
|
42
|
+
const results = await vign.scan({ target: Git });
|
|
43
|
+
results.paths.has(".git/HEAD");
|
|
44
|
+
```
|
|
74
45
|
|
|
75
|
-
|
|
76
|
-
await vign.Plugins.loadBuiltIns(); // load all built-in plugins
|
|
77
|
-
await vign.Plugins.loadPlugins(["example"]); // load third-party plugins
|
|
46
|
+
### Using custom target
|
|
78
47
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
48
|
+
```ts
|
|
49
|
+
import * as vign from "view-ignored";
|
|
50
|
+
import {
|
|
51
|
+
type SourceExtractor,
|
|
52
|
+
type SignedPattern,
|
|
53
|
+
extractGitignore
|
|
54
|
+
findAndExtract,
|
|
55
|
+
signedPatternIgnores,
|
|
56
|
+
} from "view-ignored/patterns";
|
|
57
|
+
import type { Target } from "view-ignored/targets";
|
|
58
|
+
|
|
59
|
+
const gitSources = ['.gitignore'];
|
|
60
|
+
const gitSourceMap = new Map<string, SourceExtractor>([
|
|
61
|
+
['.gitignore', extractGitignore]
|
|
62
|
+
]);
|
|
63
|
+
const gitPattern: SignedPattern = {
|
|
64
|
+
exclude: [
|
|
65
|
+
'.git',
|
|
66
|
+
'.DS_Store',
|
|
67
|
+
],
|
|
68
|
+
include: []
|
|
69
|
+
};
|
|
88
70
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
71
|
+
export const Git: Target = {
|
|
72
|
+
async matcher(entry, isDir, ctx) {
|
|
73
|
+
if (isDir) {
|
|
74
|
+
await findAndExtract(entry, gitSources, gitSourceMap, ctx);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return await signedPatternIgnores(gitPattern, entry, gitSources, gitSourceMap, ctx);
|
|
93
78
|
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
#### Sorting
|
|
98
|
-
|
|
99
|
-
```js
|
|
100
|
-
const sorter = vign.Sorting.firstFolders;
|
|
101
|
-
const fileInfoList = await vign.scan(".", { target: "npm" });
|
|
102
|
-
const fileInfoSorted = fileInfoList.sort((a, b) =>
|
|
103
|
-
sorter(String(a), String(b))
|
|
104
|
-
);
|
|
79
|
+
};
|
|
105
80
|
```
|
|
106
81
|
|
|
107
|
-
#### Plugin export example
|
|
108
|
-
|
|
109
82
|
```ts
|
|
110
|
-
|
|
111
|
-
id,
|
|
112
|
-
icon,
|
|
113
|
-
name,
|
|
114
|
-
testCommand,
|
|
115
|
-
scanOptions: {
|
|
116
|
-
target: methodologyGitignoreLike(".gitignore"),
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
const git: Plugins.PluginExport = { viewignored: { addTargets: [bind] } };
|
|
120
|
-
export default git;
|
|
83
|
+
vign.scan({ target: Git });
|
|
121
84
|
```
|
|
122
85
|
|
|
123
|
-
|
|
86
|
+
## Targets
|
|
87
|
+
|
|
124
88
|
|
|
125
|
-
The following built-in
|
|
89
|
+
The following built-in targets are available:
|
|
126
90
|
|
|
127
91
|
- `git`
|
|
128
92
|
- `npm` (compatible with Bun, PNPM, and others)
|
|
@@ -133,3 +97,7 @@ The following built-in plugins are available:
|
|
|
133
97
|
## License
|
|
134
98
|
|
|
135
99
|
MIT License. See [LICENSE.txt](LICENSE.txt) for details.
|
|
100
|
+
|
|
101
|
+
## Target implementations
|
|
102
|
+
<!-- .ts links -->
|
|
103
|
+
See [Target implementations](src/targets/README.md) for details.
|
package/out/index.d.ts
CHANGED
package/out/index.js
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { minimatch } from 'minimatch';
|
|
2
|
+
export function extractGitignore(source, content) {
|
|
3
|
+
for (let line of content.toString().split('\n')) {
|
|
4
|
+
line = line.trim();
|
|
5
|
+
if (line === '' || line.startsWith('#')) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
const cdx = line.indexOf('#');
|
|
9
|
+
if (cdx >= 0) {
|
|
10
|
+
line = line.substring(-cdx);
|
|
11
|
+
}
|
|
12
|
+
if (line.startsWith('!')) {
|
|
13
|
+
source.pattern.include.push(line.substring(1));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
source.pattern.exclude.push(line);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// TODO: validate gitignore
|
|
20
|
+
}
|
|
21
|
+
extractGitignore;
|
|
22
|
+
export function gitignoreMatch(pattern, path) {
|
|
23
|
+
const o = { dot: true };
|
|
24
|
+
if (pattern.startsWith('/')) {
|
|
25
|
+
pattern = pattern.substring(1);
|
|
26
|
+
}
|
|
27
|
+
else if (!pattern.startsWith('**/')) {
|
|
28
|
+
if (minimatch(path, '**/' + pattern, o))
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
if (pattern.endsWith('/')) {
|
|
32
|
+
pattern = pattern.substring(-1);
|
|
33
|
+
}
|
|
34
|
+
return minimatch(path, pattern, o) || minimatch(path, pattern + '/**', o);
|
|
35
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type } from 'arktype';
|
|
2
|
+
import type { Source } from './matcher.js';
|
|
3
|
+
export declare function extractJsrJson(source: Source, content: Buffer<ArrayBuffer>): type.errors | undefined;
|
|
4
|
+
export declare function extractJsrJsonc(source: Source, content: Buffer<ArrayBuffer>): type.errors | undefined;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type } from 'arktype';
|
|
2
|
+
import stripJsonComments from 'strip-json-comments';
|
|
3
|
+
const jsrManifest = type({
|
|
4
|
+
exclude: 'string[]?',
|
|
5
|
+
include: 'string[]?',
|
|
6
|
+
publish: {
|
|
7
|
+
exclude: 'string[]?',
|
|
8
|
+
include: 'string[]?',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
const parse = jsrManifest.pipe((s) => JSON.parse(s));
|
|
12
|
+
export function extractJsrJson(source, content) {
|
|
13
|
+
const dist = parse(content.toString());
|
|
14
|
+
if (dist instanceof type.errors) {
|
|
15
|
+
return dist;
|
|
16
|
+
}
|
|
17
|
+
if (!dist.publish) {
|
|
18
|
+
if (dist.exclude) {
|
|
19
|
+
source.pattern.exclude.push(...dist.exclude);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (dist.publish.exclude) {
|
|
23
|
+
source.pattern.exclude.push(...dist.publish.exclude);
|
|
24
|
+
}
|
|
25
|
+
if (!dist.publish) {
|
|
26
|
+
if (dist.include) {
|
|
27
|
+
source.pattern.include.push(...dist.include);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else if (dist.publish.include) {
|
|
31
|
+
source.pattern.include.push(...dist.publish.include);
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
extractJsrJson;
|
|
36
|
+
export function extractJsrJsonc(source, content) {
|
|
37
|
+
return extractJsrJson(source, Buffer.from(stripJsonComments(content.toString())));
|
|
38
|
+
}
|
|
39
|
+
extractJsrJsonc;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type MatcherContext = {
|
|
2
|
+
paths: Set<string>;
|
|
3
|
+
external: Map<string, Source>;
|
|
4
|
+
depthPaths: Map<string, number>;
|
|
5
|
+
sourceErrors: Error[];
|
|
6
|
+
totalFiles: number;
|
|
7
|
+
totalMatchedFiles: number;
|
|
8
|
+
totalDirs: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Represents a list of positive minimatch patterns.
|
|
12
|
+
*/
|
|
13
|
+
export type Pattern = string[];
|
|
14
|
+
export declare function patternMatches(pattern: Pattern, path: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Represents a set of include and exclude patterns.
|
|
17
|
+
* These patterns are positive minimatch patterns.
|
|
18
|
+
*/
|
|
19
|
+
export type SignedPattern = {
|
|
20
|
+
include: Pattern;
|
|
21
|
+
exclude: Pattern;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Combined internal and external patterns for matching.
|
|
25
|
+
* Used in {@link signedPatternIgnores} function.
|
|
26
|
+
*/
|
|
27
|
+
export type PatternMatcher = {
|
|
28
|
+
internal: SignedPattern;
|
|
29
|
+
external: SignedPattern;
|
|
30
|
+
};
|
|
31
|
+
export type PathChecker = (path: string, isDir: boolean, ctx: MatcherContext) => Promise<boolean>;
|
|
32
|
+
export type Source = {
|
|
33
|
+
pattern: SignedPattern;
|
|
34
|
+
name: string;
|
|
35
|
+
inverted: boolean;
|
|
36
|
+
};
|
|
37
|
+
export type SourceExtractor = (source: Source, content: Buffer<ArrayBuffer>) => void;
|
|
38
|
+
export declare function findAndExtract(directory: string, sources: string[], matcher: Map<string, SourceExtractor>, ctx: MatcherContext): Promise<void>;
|
|
39
|
+
export declare function signedPatternIgnores(internal: SignedPattern, file: string, sources: string[], sourceMap: Map<string, SourceExtractor>, ctx: MatcherContext): Promise<boolean>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as fsp from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { gitignoreMatch } from './gitignore.js';
|
|
4
|
+
export function patternMatches(pattern, path) {
|
|
5
|
+
for (const p of pattern) {
|
|
6
|
+
const matched = gitignoreMatch(p, path);
|
|
7
|
+
if (matched) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
export async function findAndExtract(directory, sources, matcher, ctx) {
|
|
14
|
+
const keys = [];
|
|
15
|
+
for (const sourceFileName of sources) {
|
|
16
|
+
for (;;) {
|
|
17
|
+
let buff;
|
|
18
|
+
try {
|
|
19
|
+
buff = await fsp.readFile(directory + '/' + sourceFileName);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const error = err;
|
|
23
|
+
if (error.code !== 'ENOENT') {
|
|
24
|
+
ctx.sourceErrors.push(error);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const dir = dirname(directory);
|
|
29
|
+
if (!ctx.external.has(directory)) {
|
|
30
|
+
keys.push(directory);
|
|
31
|
+
}
|
|
32
|
+
if (!buff) {
|
|
33
|
+
if (directory === '.') {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
directory = dir;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (directory === '.' && !keys.length) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
const sourceExtractor = matcher.get(sourceFileName);
|
|
43
|
+
if (!sourceExtractor) {
|
|
44
|
+
const err = new Error('No extractor for source file: ' + sourceFileName);
|
|
45
|
+
ctx.sourceErrors.push(err);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
const source = {
|
|
49
|
+
inverted: false,
|
|
50
|
+
name: sourceFileName,
|
|
51
|
+
pattern: {
|
|
52
|
+
exclude: [],
|
|
53
|
+
include: [],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
try {
|
|
57
|
+
sourceExtractor(source, buff);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
ctx.sourceErrors.push(err);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
for (const key of keys) {
|
|
64
|
+
const m = ctx.external.get(key);
|
|
65
|
+
if (!m) {
|
|
66
|
+
ctx.external.set(key, source);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (directory === '.') {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
keys.length = 0;
|
|
73
|
+
directory = dir;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function signedPatternIgnores(internal, file, sources, sourceMap, ctx) {
|
|
78
|
+
const parent = dirname(file);
|
|
79
|
+
let source = ctx.external.get(parent);
|
|
80
|
+
if (!source) {
|
|
81
|
+
await findAndExtract(parent, sources, sourceMap, ctx);
|
|
82
|
+
if (ctx.sourceErrors.length) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
source = ctx.external.get(parent);
|
|
86
|
+
if (!source) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const matcher = {
|
|
91
|
+
internal,
|
|
92
|
+
external: source.pattern,
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
let check = false;
|
|
96
|
+
check = patternMatches(matcher.internal.exclude, file);
|
|
97
|
+
if (check) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
check = patternMatches(matcher.internal.include, file);
|
|
101
|
+
if (check) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
check = patternMatches(matcher.external.exclude, file);
|
|
105
|
+
if (check) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
check = patternMatches(matcher.external.include, file);
|
|
109
|
+
if (check) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
ctx.sourceErrors.push(err);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
return source.inverted;
|
|
118
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type } from 'arktype';
|
|
2
|
+
const nodeJsManifest = type({
|
|
3
|
+
files: 'string[]?',
|
|
4
|
+
});
|
|
5
|
+
const parse = nodeJsManifest.pipe((s) => JSON.parse(s));
|
|
6
|
+
export function extractPackageJson(source, content) {
|
|
7
|
+
source.inverted = true;
|
|
8
|
+
const dist = parse(content.toString());
|
|
9
|
+
if (dist instanceof type.errors) {
|
|
10
|
+
return dist;
|
|
11
|
+
}
|
|
12
|
+
if (!dist.files) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
for (const p of dist.files) {
|
|
16
|
+
if (p.startsWith('!')) {
|
|
17
|
+
source.pattern.exclude.push(...p.substring(1));
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
source.pattern.include.push(...p);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
extractPackageJson;
|
package/out/scan.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MatcherContext } from './patterns/matcher.js';
|
|
2
|
+
import type { Target } from './targets/target.js';
|
|
3
|
+
export type DepthMode = 'files' | undefined;
|
|
4
|
+
export type ScanOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Provides the matcher to use for scanning.
|
|
7
|
+
*/
|
|
8
|
+
target: Target;
|
|
9
|
+
/**
|
|
10
|
+
* Current working directory to start the scan from.
|
|
11
|
+
*/
|
|
12
|
+
cwd?: string;
|
|
13
|
+
/**
|
|
14
|
+
* If enabled, the scan will return files that are ignored by the target matchers.
|
|
15
|
+
*/
|
|
16
|
+
invert?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Starting from depth `0` means you will see
|
|
19
|
+
* children of the current working directory.
|
|
20
|
+
*/
|
|
21
|
+
depth?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Return as soon as possible.
|
|
24
|
+
*/
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
/**
|
|
27
|
+
* If enabled, Depth will be calculated faster by skipping
|
|
28
|
+
* other files after first match.
|
|
29
|
+
* This makes the scan faster but affects
|
|
30
|
+
* {@link MatcherContext.totalDirs},
|
|
31
|
+
* {@link MatcherContext.totalFiles},
|
|
32
|
+
* {@link MatcherContext.totalMatchedFiles}
|
|
33
|
+
* and {@link MatcherContext.depthPaths}.
|
|
34
|
+
*/
|
|
35
|
+
fastDepth?: boolean;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Scan the directory for included files based on the provided targets.
|
|
39
|
+
*
|
|
40
|
+
* Note that this function uses `fs/promises.opendir` with recursive option,
|
|
41
|
+
* and `fs/promises.readFile`. It also normalizes paths to use forward slashes..
|
|
42
|
+
*
|
|
43
|
+
* @param options Scan options.
|
|
44
|
+
* @returns A promise that resolves to a map of targets to their matcher contexts.
|
|
45
|
+
*/
|
|
46
|
+
export declare function scan(options: ScanOptions): Promise<MatcherContext>;
|
package/out/scan.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { posix } from 'node:path';
|
|
2
|
+
import { opendir } from './walk.js';
|
|
3
|
+
/**
|
|
4
|
+
* Scan the directory for included files based on the provided targets.
|
|
5
|
+
*
|
|
6
|
+
* Note that this function uses `fs/promises.opendir` with recursive option,
|
|
7
|
+
* and `fs/promises.readFile`. It also normalizes paths to use forward slashes..
|
|
8
|
+
*
|
|
9
|
+
* @param options Scan options.
|
|
10
|
+
* @returns A promise that resolves to a map of targets to their matcher contexts.
|
|
11
|
+
*/
|
|
12
|
+
export async function scan(options) {
|
|
13
|
+
const { target, cwd: cwdo = (await import('node:process')).cwd(), depth: maxDepth = Infinity, invert = false, signal = undefined, fastDepth = false, } = options;
|
|
14
|
+
const cwd = cwdo.replaceAll('\\', '/');
|
|
15
|
+
const ctx = {
|
|
16
|
+
paths: new Set(),
|
|
17
|
+
external: new Map(),
|
|
18
|
+
depthPaths: new Map(),
|
|
19
|
+
sourceErrors: [],
|
|
20
|
+
totalFiles: 0,
|
|
21
|
+
totalMatchedFiles: 0,
|
|
22
|
+
totalDirs: 0,
|
|
23
|
+
};
|
|
24
|
+
await opendir(cwd, async (entry) => {
|
|
25
|
+
if (signal?.aborted) {
|
|
26
|
+
return 2;
|
|
27
|
+
}
|
|
28
|
+
const path = posix.join(posix.relative(cwd, entry.parentPath.replaceAll('\\', '/')), entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
ctx.totalDirs++;
|
|
31
|
+
if (!fastDepth) {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
const { depth } = getDepth(path, maxDepth);
|
|
35
|
+
if (depth <= maxDepth) {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
ctx.totalFiles++;
|
|
41
|
+
if (fastDepth) {
|
|
42
|
+
const { depth, depthSlash } = getDepth(path, maxDepth);
|
|
43
|
+
if (depth > maxDepth) {
|
|
44
|
+
let ignored = await target.matcher(path, false, ctx);
|
|
45
|
+
if (ctx.sourceErrors.length > 0) {
|
|
46
|
+
return 2;
|
|
47
|
+
}
|
|
48
|
+
if (invert) {
|
|
49
|
+
ignored = !ignored;
|
|
50
|
+
}
|
|
51
|
+
if (ignored) {
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
const dir = path.substring(0, depthSlash);
|
|
55
|
+
ctx.depthPaths.set(dir, (ctx.depthPaths.get(dir) ?? 0) + 1);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let ignored = await target.matcher(path, false, ctx);
|
|
60
|
+
if (ctx.sourceErrors.length > 0) {
|
|
61
|
+
return 2;
|
|
62
|
+
}
|
|
63
|
+
if (invert) {
|
|
64
|
+
ignored = !ignored;
|
|
65
|
+
}
|
|
66
|
+
if (ignored) {
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
ctx.totalMatchedFiles++;
|
|
70
|
+
const { depth, depthSlash } = getDepth(path, maxDepth);
|
|
71
|
+
if (depth > maxDepth) {
|
|
72
|
+
const dir = path.substring(0, depthSlash);
|
|
73
|
+
ctx.depthPaths.set(dir, (ctx.depthPaths.get(dir) ?? 0) + 1);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
ctx.paths.add(path);
|
|
77
|
+
}
|
|
78
|
+
return 0;
|
|
79
|
+
});
|
|
80
|
+
if (signal?.aborted) {
|
|
81
|
+
return ctx;
|
|
82
|
+
}
|
|
83
|
+
for (const [dir, count] of ctx.depthPaths) {
|
|
84
|
+
if (count === 0) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
ctx.paths.add(dir + '/');
|
|
88
|
+
}
|
|
89
|
+
console.log(ctx.paths);
|
|
90
|
+
return ctx;
|
|
91
|
+
}
|
|
92
|
+
function getDepth(path, maxDepth) {
|
|
93
|
+
const result = {
|
|
94
|
+
depth: 0,
|
|
95
|
+
depthSlash: 0,
|
|
96
|
+
};
|
|
97
|
+
result.depthSlash = -1;
|
|
98
|
+
if (maxDepth < 0) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
for (const [i, c] of Array.from(path).entries()) {
|
|
102
|
+
if (c !== '/') {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
result.depth++;
|
|
106
|
+
if (result.depth < maxDepth) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
result.depthSlash = i;
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { signedPatternIgnores, findAndExtract } from '../patterns/matcher.js';
|
|
2
|
+
import { extractGitignore } from '../patterns/gitignore.js';
|
|
3
|
+
const gitSources = ['.gitignore'];
|
|
4
|
+
const gitSourceMap = new Map([
|
|
5
|
+
['.gitignore', extractGitignore],
|
|
6
|
+
]);
|
|
7
|
+
const gitPattern = {
|
|
8
|
+
exclude: [
|
|
9
|
+
'.git',
|
|
10
|
+
'.DS_Store',
|
|
11
|
+
],
|
|
12
|
+
include: [],
|
|
13
|
+
};
|
|
14
|
+
export const Git = {
|
|
15
|
+
async matcher(entry, isDir, ctx) {
|
|
16
|
+
if (isDir) {
|
|
17
|
+
await findAndExtract(entry, gitSources, gitSourceMap, ctx);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return await signedPatternIgnores(gitPattern, entry, gitSources, gitSourceMap, ctx);
|
|
21
|
+
},
|
|
22
|
+
};
|