@descent-vtt/spec-brief 0.2.5 → 0.2.7
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/CHANGELOG.md +67 -0
- package/README.md +2 -2
- package/dist/glob.d.ts +27 -2
- package/dist/glob.js +166 -4
- package/dist/glob.js.map +1 -1
- package/dist/rules.js +37 -10
- package/dist/rules.js.map +1 -1
- package/dist/vendor/spec-core/pattern/glob.d.ts +3 -0
- package/dist/vendor/spec-core/pattern/glob.js +62 -29
- package/dist/vendor/spec-core/pattern/glob.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes, newest first. Versions follow [semver](https://semver.org).
|
|
4
4
|
|
|
5
|
+
## 0.2.7
|
|
6
|
+
|
|
7
|
+
spec-core at 7e41240: a brace alternative that starts with `/`, such as
|
|
8
|
+
`{/docs,src}`, is refused as a pattern that starts with one is, where the
|
|
9
|
+
new copy roots it at the filesystem's root and `docs` would have left the
|
|
10
|
+
scope unsaid. So is `.//docs`, which spec-core read as `/docs` already.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- spec-core at 7e41240. It reads a leading `/` on a brace alternative as it
|
|
15
|
+
reads one on the whole pattern, so `{/docs,src}` is `/docs`, rooted at
|
|
16
|
+
the filesystem's root, or `src`, where the slash was dropped and it read
|
|
17
|
+
`docs` or `src`. spec-brief refuses it, as it refuses `/docs`: in
|
|
18
|
+
`affectedFiles` or `protectedFiles` it is a `glob` error, `a pattern is
|
|
19
|
+
relative to the repository root, and the braces expand to "/docs", which
|
|
20
|
+
starts with "/"`, and a `files` or `exclude` pattern spelt so is a
|
|
21
|
+
configuration problem, and the run exits 2. Read as the copy reads it,
|
|
22
|
+
`docs` would have fallen out of the scope, the protection or the briefs
|
|
23
|
+
a run reads, with nothing said. `{src,/docs}`, nested braces,
|
|
24
|
+
`{//docs,src}`, `{.//docs,src}`, `./{/docs,src}` and `{a,/b}c` are
|
|
25
|
+
refused the same way, each naming the text the braces give. A `/` after
|
|
26
|
+
a name starts no text, and reads as it did: `docs/{/a,b}` is `docs/a` or
|
|
27
|
+
`docs/b`, and `a{/b,c}` is `a/b` or `ac`.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- A pattern that starts with `./` and then `/`, such as `.//docs`, is
|
|
32
|
+
refused as `/docs` is, `a pattern is relative to the repository root and
|
|
33
|
+
cannot start with "/"`. spec-core drops the `./` and reads `/docs`,
|
|
34
|
+
rooted at the filesystem's root, so in a scope it matched nothing and no
|
|
35
|
+
finding said so, and as `files` it read no briefs. `./docs` reads as it
|
|
36
|
+
did.
|
|
37
|
+
|
|
38
|
+
## 0.2.6
|
|
39
|
+
|
|
40
|
+
spec-core at 56c7e54: a brace alternative that names no path, such as
|
|
41
|
+
`{./,src}`, is refused as the same text alone is, where it read as every
|
|
42
|
+
path. `literal-read-as-file` advises the `/` on the brace alternative it
|
|
43
|
+
names, built from the pattern written.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- spec-core at 56c7e54. A brace alternative that names no path is refused,
|
|
48
|
+
as the same text written alone is. `{./,src}` in `affectedFiles` or
|
|
49
|
+
`protectedFiles` read its `./` as every path, where `./` alone is
|
|
50
|
+
refused: protecting it protected the whole tree, so `scope-contradiction`
|
|
51
|
+
reported every affected pattern, and in `affectedFiles` it overlapped
|
|
52
|
+
every other brief's scope. It is now a `glob` error, `the braces expand
|
|
53
|
+
to "./", which names no path`, and so are `{src,./}`, `{.,src}/` and
|
|
54
|
+
`.{/,src}`. A `files` or `exclude` pattern spelt so matched every name in
|
|
55
|
+
the briefs directory; it is now a configuration problem, and the run
|
|
56
|
+
exits 2. `src/{./,a}`, `{./a,b}` and `a{,.ts}` read as they did.
|
|
57
|
+
- `glob` names the alternative in refusals it already made: `{.,src}` is
|
|
58
|
+
`the braces expand to ".", which names no path`, and `{/,src}` the same
|
|
59
|
+
with `"/"`, where both were `the pattern names no path`; `{,src}`,
|
|
60
|
+
`{src,}` and `{}` are `the braces expand to an empty pattern`.
|
|
61
|
+
- `literal-read-as-file` advises the pattern as written with a `/` ending
|
|
62
|
+
each alternative it names, where it said to write a directory with a
|
|
63
|
+
trailing `/`, in an entry of its own. Since 0.2.5 a trailing `/` on a
|
|
64
|
+
brace alternative says directory, so for `lib/{util,new}` in a tree
|
|
65
|
+
without `lib/new` the hint is `write "lib/{util,new/}" for a directory,
|
|
66
|
+
or "lib/new/" in an entry of its own`. Where more of the pattern follows
|
|
67
|
+
the braces, `{a,b}/new`, a `/` inside them cannot end one alternative
|
|
68
|
+
alone, and the hint names the entries: `write "a/new/" and "b/new/" for
|
|
69
|
+
directories, in entries of their own`. What the note fires on is
|
|
70
|
+
unchanged.
|
|
71
|
+
|
|
5
72
|
## 0.2.5
|
|
6
73
|
|
|
7
74
|
spec-core at f9ce375. A trailing `/` on a brace alternative means that
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Work put off for later is a brief too, with `status: deferred` and a `trigger` n
|
|
|
52
52
|
|
|
53
53
|
The id comes from the file name (`012_rotate-session-tokens.md`) or from an `id` field. `affectedFiles` is the scope the round may write; `protectedFiles` is what it is not empowered to change, and archival refuses a round that changed it. Protection wins: what a round may write is `affectedFiles` less `protectedFiles`, so "all of `src/` but the schema" is `affectedFiles: [src/**]` with `protectedFiles: [src/db/schema.ts]`.
|
|
54
54
|
|
|
55
|
-
Scopes are globs in spec-core's `path` dialect, the one every spec-\* tool reads: `*`, `?`, `[a-z]` and `{a,b}` within a name, `**` for any number of directories, compared case-sensitively on every host. `**` is a whole segment: `docs/**.md` is refused, since tools read it three ways - write `docs/**/*.md` for any depth, or `docs/*.md` for one level. Parentheses are literal, `C++(notes).md`, unless a group holds a `|`: an extended glob such as `+(a|b)` is refused, and written `{a,b}`. A trailing `/**` or `/` is a directory's contents - at least one name below it, never the directory itself - on a brace alternative as on the whole pattern: `{src/,lib}` is `src/` or `lib`. A path with no glob syntax is read from the tree: a file the tree holds is that file, a directory it holds is everything beneath it, and a path it does not hold yet is a file unless it ends in `/`. Write `src/newmod/` for a directory the round creates; `lint` notes a bare `src/newmod` it cannot place.
|
|
55
|
+
Scopes are globs in spec-core's `path` dialect, the one every spec-\* tool reads: `*`, `?`, `[a-z]` and `{a,b}` within a name, `**` for any number of directories, compared case-sensitively on every host. `**` is a whole segment: `docs/**.md` is refused, since tools read it three ways - write `docs/**/*.md` for any depth, or `docs/*.md` for one level. Parentheses are literal, `C++(notes).md`, unless a group holds a `|`: an extended glob such as `+(a|b)` is refused, and written `{a,b}`. A trailing `/**` or `/` is a directory's contents - at least one name below it, never the directory itself - on a brace alternative as on the whole pattern: `{src/,lib}` is `src/` or `lib`. Each alternative names a path under the root, as a whole pattern does: `./` is refused, and so is `{./,src}`. A pattern is relative to the repository root, so a leading `/` is refused, on an alternative as on the whole pattern: `/docs`, `.//docs` and `{/docs,src}` alike. After a name, a `/` inside braces names nothing: `docs/{/a,b}` is `docs/a` or `docs/b`. A path with no glob syntax is read from the tree: a file the tree holds is that file, a directory it holds is everything beneath it, and a path it does not hold yet is a file unless it ends in `/`. Write `src/newmod/` for a directory the round creates; `lint` notes a bare `src/newmod` it cannot place.
|
|
56
56
|
|
|
57
57
|
## Commands
|
|
58
58
|
|
|
@@ -229,7 +229,7 @@ A brief is read as CommonMark reads it wherever that decides what is code or a c
|
|
|
229
229
|
| `glob` | error | A scope pattern spec-brief cannot read. |
|
|
230
230
|
| `scope-contradiction` | error | Patterns in `affectedFiles` that `protectedFiles` cover entirely, so nothing of them is writable - one finding per brief, naming each. A pattern the search cannot decide is a warning. |
|
|
231
231
|
| `glob-matches-nothing` | note | A scope pattern that matches no file git sees, tracked or untracked - expected when the round creates it. |
|
|
232
|
-
| `literal-read-as-file` | note | A path with no glob syntax that the tree does not hold and whose name has no extension, such as `src/newmod`: read as a file, and `src/newmod/` if a directory was meant. |
|
|
232
|
+
| `literal-read-as-file` | note | A path with no glob syntax that the tree does not hold and whose name has no extension, such as `src/newmod`: read as a file, and `src/newmod/` if a directory was meant. Inside braces the advice is the pattern written with the `/` added, `lib/{util,new/}`, or the alternative in an entry of its own, `lib/new/`. |
|
|
233
233
|
| `archive-freeze` | error | An archived brief that changed after it was archived. |
|
|
234
234
|
| `collision` | error | Two briefs in one wave whose scopes can name the same file (`matrix`). |
|
|
235
235
|
| `collision-undecided` | warning | Two briefs in one wave whose collision the search could not decide within its budget (`matrix`), or a wave `schedule` passed over for it. |
|
package/dist/glob.d.ts
CHANGED
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
* spec-brief adds around it:
|
|
9
9
|
*
|
|
10
10
|
* - A pattern is relative to the repository root, so a leading `/` is refused
|
|
11
|
-
* rather than rooted at the filesystem
|
|
12
|
-
*
|
|
11
|
+
* rather than rooted at the filesystem: on the pattern, one after a leading
|
|
12
|
+
* `./` too, as in `.//docs`, and on a text its braces give, since spec-core
|
|
13
|
+
* reads `{/docs,x}` as `/docs` or `x`, and `docs` would fall out of the
|
|
14
|
+
* scope unsaid. A list entry's `!` has no list to belong to in a scope, so
|
|
15
|
+
* it is refused rather than read.
|
|
13
16
|
* - Paths compare case-sensitively on every host, as git's do.
|
|
14
17
|
* - A path with no glob syntax is read as the tree reads it: a file the tree
|
|
15
18
|
* holds is that file, a directory it holds is everything beneath it, and a
|
|
@@ -87,6 +90,28 @@ export declare function intersectGlobs(a: Glob, b: Glob, budget?: number): strin
|
|
|
87
90
|
export declare function globBases(glob: Glob): readonly string[];
|
|
88
91
|
/** The first of {@link globBases}: the 0.1 interface, kept for the library's callers. */
|
|
89
92
|
export declare function globBase(glob: Glob): string;
|
|
93
|
+
/** A brace alternative as its pattern writes it, and the index in the pattern where it ends. */
|
|
94
|
+
export interface WrittenAlternative {
|
|
95
|
+
readonly written: string;
|
|
96
|
+
readonly end: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Each alternative of a pattern as written, in the order the core expands
|
|
100
|
+
* them, and where each ends, when a `/` written there ends that alternative
|
|
101
|
+
* and no other: the pattern itself when it has no braces, or the alternatives
|
|
102
|
+
* of braces that end the pattern and whose own braces end theirs -
|
|
103
|
+
* `lib/{util,new}`, `{a,b/{c,d}}`. `null` when more of the pattern follows
|
|
104
|
+
* braces, `{a,b}/new`, since every alternative they give ends where the
|
|
105
|
+
* pattern does; and for a pattern with a class, which may hold a brace or a
|
|
106
|
+
* comma of its own and which this does not read.
|
|
107
|
+
*
|
|
108
|
+
* spec-core expands braces and keeps nothing of where an alternative was
|
|
109
|
+
* written, and a note's advice is built from what was written, as the core
|
|
110
|
+
* builds its own. So this reads braces as the expansion does, for a pattern
|
|
111
|
+
* that parses: a `\` escapes the next character, and a `}` with no `{` open
|
|
112
|
+
* is a literal.
|
|
113
|
+
*/
|
|
114
|
+
export declare function writtenAlternatives(pattern: string): WrittenAlternative[] | null;
|
|
90
115
|
/** A name with an extension, `login.ts` or `.eslintrc.json`, and not a dot-name such as `.github`. */
|
|
91
116
|
export declare function hasExtension(name: string): boolean;
|
|
92
117
|
/** The files a tree holds, and every directory above one. */
|
package/dist/glob.js
CHANGED
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
* spec-brief adds around it:
|
|
9
9
|
*
|
|
10
10
|
* - A pattern is relative to the repository root, so a leading `/` is refused
|
|
11
|
-
* rather than rooted at the filesystem
|
|
12
|
-
*
|
|
11
|
+
* rather than rooted at the filesystem: on the pattern, one after a leading
|
|
12
|
+
* `./` too, as in `.//docs`, and on a text its braces give, since spec-core
|
|
13
|
+
* reads `{/docs,x}` as `/docs` or `x`, and `docs` would fall out of the
|
|
14
|
+
* scope unsaid. A list entry's `!` has no list to belong to in a scope, so
|
|
15
|
+
* it is refused rather than read.
|
|
13
16
|
* - Paths compare case-sensitively on every host, as git's do.
|
|
14
17
|
* - A path with no glob syntax is read as the tree reads it: a file the tree
|
|
15
18
|
* holds is that file, a directory it holds is everything beneath it, and a
|
|
@@ -33,7 +36,7 @@ export function parseGlob(source, options = {}) {
|
|
|
33
36
|
const pattern = source.trim();
|
|
34
37
|
if (pattern.startsWith('!'))
|
|
35
38
|
return { ok: false, error: 'negated patterns are not supported; narrow the positive pattern' };
|
|
36
|
-
if (pattern.startsWith('/'))
|
|
39
|
+
if (undotted(pattern).startsWith('/'))
|
|
37
40
|
return { ok: false, error: 'a pattern is relative to the repository root and cannot start with "/"' };
|
|
38
41
|
const given = options.literal ?? 'file';
|
|
39
42
|
const literals = [];
|
|
@@ -45,7 +48,107 @@ export function parseGlob(source, options = {}) {
|
|
|
45
48
|
// A pattern too large to compile is refused by the core, with its reason,
|
|
46
49
|
// as a malformed one is; what the reading throws is a defect, and passes on.
|
|
47
50
|
const parsed = coreParse(pattern, { dialect: 'path', caseSensitive: true, literal });
|
|
48
|
-
|
|
51
|
+
if (!parsed.ok)
|
|
52
|
+
return parsed;
|
|
53
|
+
// Read once the core has parsed the pattern, so that its braces close and
|
|
54
|
+
// give no more texts than the core allows.
|
|
55
|
+
const rooted = rootedAlternative(pattern);
|
|
56
|
+
if (rooted !== undefined) {
|
|
57
|
+
return { ok: false, error: `a pattern is relative to the repository root, and the braces expand to "${rooted}", which starts with "/"` };
|
|
58
|
+
}
|
|
59
|
+
return { ok: true, glob: { source, compiled: parsed.glob, literals } };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A pattern less the `./` it starts with. spec-core drops it before it reads
|
|
63
|
+
* a leading `/`, since `.` names nothing: `.//docs` is `/docs`, rooted at the
|
|
64
|
+
* filesystem's root.
|
|
65
|
+
*/
|
|
66
|
+
function undotted(pattern) {
|
|
67
|
+
let rest = pattern;
|
|
68
|
+
while (rest.startsWith('./'))
|
|
69
|
+
rest = rest.slice(2);
|
|
70
|
+
return rest;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The first text a pattern's braces give that starts with `/` once its `./`
|
|
74
|
+
* is dropped, less that `./`: an alternative spec-core roots at the
|
|
75
|
+
* filesystem's root, since braces expand before a leading `/` is read, so
|
|
76
|
+
* that `{/docs,x}` is `/docs` or `x` (spec-core ADR-0003, amended
|
|
77
|
+
* 2026-09-29). `undefined` when there is none. A `/` after anything else
|
|
78
|
+
* starts no text: `a/{/b,c}` gives `a//b`, which is `a/b`.
|
|
79
|
+
*
|
|
80
|
+
* spec-core keeps nothing of the texts its braces give, and the refusal names
|
|
81
|
+
* the text, as the core's own refusals do. So this expands braces as the core
|
|
82
|
+
* does, for a pattern the core parsed, whose braces close and give at most
|
|
83
|
+
* `MAX_ALTERNATIVES` texts: a `\` escapes the next character, a class holds
|
|
84
|
+
* no brace syntax, a `}` with no `{` open is a literal, and the first braces
|
|
85
|
+
* to close are expanded first, each option in turn, so the text named is the
|
|
86
|
+
* first such text the core gives.
|
|
87
|
+
*
|
|
88
|
+
* Its loop, read one step past the end, reads `''`, which no branch acts on,
|
|
89
|
+
* so a bound one further reads the same.
|
|
90
|
+
*/
|
|
91
|
+
function rootedAlternative(pattern) {
|
|
92
|
+
let depth = 0;
|
|
93
|
+
let open = 0;
|
|
94
|
+
const stops = [];
|
|
95
|
+
for (let i = 0; i < pattern.length; i += 1) {
|
|
96
|
+
const ch = pattern.charAt(i);
|
|
97
|
+
if (ch === '\\') {
|
|
98
|
+
i += 1;
|
|
99
|
+
}
|
|
100
|
+
else if (ch === '[') {
|
|
101
|
+
const close = classEnd(pattern, i);
|
|
102
|
+
if (close !== -1)
|
|
103
|
+
i = close;
|
|
104
|
+
}
|
|
105
|
+
else if (ch === '{') {
|
|
106
|
+
if (depth === 0)
|
|
107
|
+
open = i;
|
|
108
|
+
depth += 1;
|
|
109
|
+
}
|
|
110
|
+
else if (ch === ',' && depth === 1) {
|
|
111
|
+
stops.push(i);
|
|
112
|
+
}
|
|
113
|
+
else if (ch === '}' && depth > 0) {
|
|
114
|
+
depth -= 1;
|
|
115
|
+
if (depth === 0) {
|
|
116
|
+
let start = open + 1;
|
|
117
|
+
for (const stop of [...stops, i]) {
|
|
118
|
+
const rooted = rootedAlternative(`${pattern.slice(0, open)}${pattern.slice(start, stop)}${pattern.slice(i + 1)}`);
|
|
119
|
+
if (rooted !== undefined)
|
|
120
|
+
return rooted;
|
|
121
|
+
start = stop + 1;
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const text = undotted(pattern);
|
|
128
|
+
return text.startsWith('/') ? text : undefined;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The index of the `]` closing a class opened at `open`, or -1 when none does
|
|
132
|
+
* within its segment, as spec-core finds it while it expands braces: after a
|
|
133
|
+
* `!` or `^`, the first member is a member even when it is `]`.
|
|
134
|
+
*/
|
|
135
|
+
function classEnd(pattern, open) {
|
|
136
|
+
let i = open + 1;
|
|
137
|
+
if (pattern.charAt(i) === '!' || pattern.charAt(i) === '^')
|
|
138
|
+
i += 1;
|
|
139
|
+
if (pattern.charAt(i) === ']')
|
|
140
|
+
i += 1;
|
|
141
|
+
for (; i < pattern.length; i += 1) {
|
|
142
|
+
const ch = pattern.charAt(i);
|
|
143
|
+
if (ch === '\\')
|
|
144
|
+
i += 1;
|
|
145
|
+
else if (ch === '/')
|
|
146
|
+
return -1;
|
|
147
|
+
else if (ch === ']')
|
|
148
|
+
return i;
|
|
149
|
+
}
|
|
150
|
+
/* v8 ignore next -- in a pattern the core parsed, a "[" is closed, or met by a "/", before the pattern ends. */
|
|
151
|
+
return -1;
|
|
49
152
|
}
|
|
50
153
|
/**
|
|
51
154
|
* Whether a path matches. The path is read as a repository path: empty and
|
|
@@ -92,6 +195,65 @@ export function globBase(glob) {
|
|
|
92
195
|
// One base per alternative, and a pattern has at least one.
|
|
93
196
|
return glob.compiled.bases[0];
|
|
94
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Each alternative of a pattern as written, in the order the core expands
|
|
200
|
+
* them, and where each ends, when a `/` written there ends that alternative
|
|
201
|
+
* and no other: the pattern itself when it has no braces, or the alternatives
|
|
202
|
+
* of braces that end the pattern and whose own braces end theirs -
|
|
203
|
+
* `lib/{util,new}`, `{a,b/{c,d}}`. `null` when more of the pattern follows
|
|
204
|
+
* braces, `{a,b}/new`, since every alternative they give ends where the
|
|
205
|
+
* pattern does; and for a pattern with a class, which may hold a brace or a
|
|
206
|
+
* comma of its own and which this does not read.
|
|
207
|
+
*
|
|
208
|
+
* spec-core expands braces and keeps nothing of where an alternative was
|
|
209
|
+
* written, and a note's advice is built from what was written, as the core
|
|
210
|
+
* builds its own. So this reads braces as the expansion does, for a pattern
|
|
211
|
+
* that parses: a `\` escapes the next character, and a `}` with no `{` open
|
|
212
|
+
* is a literal.
|
|
213
|
+
*/
|
|
214
|
+
export function writtenAlternatives(pattern) {
|
|
215
|
+
let depth = 0;
|
|
216
|
+
let open = 0;
|
|
217
|
+
const stops = [];
|
|
218
|
+
for (let i = 0; i < pattern.length; i += 1) {
|
|
219
|
+
const ch = pattern.charAt(i);
|
|
220
|
+
if (ch === '\\') {
|
|
221
|
+
i += 1;
|
|
222
|
+
}
|
|
223
|
+
else if (ch === '[') {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
else if (ch === '{') {
|
|
227
|
+
if (depth === 0)
|
|
228
|
+
open = i;
|
|
229
|
+
depth += 1;
|
|
230
|
+
}
|
|
231
|
+
else if (ch === ',' && depth === 1) {
|
|
232
|
+
stops.push(i);
|
|
233
|
+
}
|
|
234
|
+
else if (ch === '}' && depth > 0) {
|
|
235
|
+
depth -= 1;
|
|
236
|
+
if (depth === 0)
|
|
237
|
+
return i === pattern.length - 1 ? optionsOf(pattern, open, [...stops, i]) : null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return [{ written: pattern, end: pattern.length }];
|
|
241
|
+
}
|
|
242
|
+
/** The alternatives of the braces opened at `open`, each option ending at one of `stops`. */
|
|
243
|
+
function optionsOf(pattern, open, stops) {
|
|
244
|
+
const prefix = pattern.slice(0, open);
|
|
245
|
+
const alternatives = [];
|
|
246
|
+
let start = open + 1;
|
|
247
|
+
for (const stop of stops) {
|
|
248
|
+
const inner = writtenAlternatives(pattern.slice(start, stop));
|
|
249
|
+
if (inner === null)
|
|
250
|
+
return null;
|
|
251
|
+
for (const { written, end } of inner)
|
|
252
|
+
alternatives.push({ written: prefix + written, end: start + end });
|
|
253
|
+
start = stop + 1;
|
|
254
|
+
}
|
|
255
|
+
return alternatives;
|
|
256
|
+
}
|
|
95
257
|
/** A name with an extension, `login.ts` or `.eslintrc.json`, and not a dot-name such as `.github`. */
|
|
96
258
|
export function hasExtension(name) {
|
|
97
259
|
return /.\.[^.]+$/.test(name);
|
package/dist/glob.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scopes as globs: spec-core's `path` dialect, read the way spec-brief reads a\n * brief.\n *\n * The syntax, the automaton and the witness search are spec-core's, copied\n * into `src/vendor/` and verified by hash, so the family's tools read one\n * pattern the same way (spec-core ADR-0003). What is decided here is what\n * spec-brief adds around it:\n *\n * - A pattern is relative to the repository root, so a leading `/` is refused\n * rather than rooted at the filesystem; and a list entry's `!` has no list to\n * belong to in a scope, so it is refused rather than read.\n * - Paths compare case-sensitively on every host, as git's do.\n * - A path with no glob syntax is read as the tree reads it: a file the tree\n * holds is that file, a directory it holds is everything beneath it, and a\n * path it does not hold is a file, unless it is written with a trailing `/`.\n * The tree, not the spelling, knows that `Dockerfile` is a file and\n * `docs/v1.2` a directory (ADR-0005, amended 2026-09-26).\n * - A trailing `/**` is at least one segment, so `docs/**` is the directory's\n * contents and a collision witness is always a file. A trailing `/` means\n * the same on a brace alternative as on the whole pattern: `{src/,lib}` is\n * `src/` or `lib`, and the tree is asked about `lib` alone.\n *\n * Nothing here compiles to a `RegExp`. Matching costs at most the pattern's\n * size times the path's length, and a question about two scopes that cannot be\n * answered within the search's budget answers `undecided`, never a guess.\n */\n\nimport {\n globCovers as coreCovers,\n globWitness as coreWitness,\n isGlobSyntax,\n parseGlob as coreParse,\n type Glob as CoreGlob,\n type LiteralReading,\n WITNESS_BUDGET,\n type Witness,\n} from './vendor/spec-core/pattern/index.js';\nimport { segments } from './vendor/spec-core/path/index.js';\n\nexport { isGlobSyntax, type LiteralReading, WITNESS_BUDGET, type Witness };\n\n/** A literal path a pattern names, and how it was read. */\nexport interface Literal {\n readonly path: string;\n readonly reading: LiteralReading;\n}\n\nexport interface Glob {\n readonly source: string;\n /** The compiled pattern: spec-core's `path` dialect, case-sensitive. */\n readonly compiled: CoreGlob;\n /**\n * Each path the pattern names with no glob syntax and no trailing `/`, one\n * per brace alternative; empty when it has none.\n */\n readonly literals: readonly Literal[];\n}\n\nexport type GlobParse = { readonly ok: true; readonly glob: Glob } | { readonly ok: false; readonly error: string };\n\nexport interface ParseOptions {\n /**\n * How a path with no glob syntax is read: `file`, that path alone;\n * `directory`, everything beneath it; `either`, both. A function is asked\n * per literal path, as {@link readingIn} answers for a tree. `file` when\n * unset: a path nothing says is a directory is not read as one.\n */\n readonly literal?: LiteralReading | ((path: string) => LiteralReading) | undefined;\n}\n\n/** Parses a scope pattern, or says why it cannot. */\nexport function parseGlob(source: string, options: ParseOptions = {}): GlobParse {\n const pattern = source.trim();\n if (pattern.startsWith('!')) return { ok: false, error: 'negated patterns are not supported; narrow the positive pattern' };\n if (pattern.startsWith('/')) return { ok: false, error: 'a pattern is relative to the repository root and cannot start with \"/\"' };\n const given = options.literal ?? 'file';\n const literals: Literal[] = [];\n const literal = (path: string): LiteralReading => {\n const reading = typeof given === 'function' ? given(path) : given;\n literals.push({ path, reading });\n return reading;\n };\n // A pattern too large to compile is refused by the core, with its reason,\n // as a malformed one is; what the reading throws is a defect, and passes on.\n const parsed = coreParse(pattern, { dialect: 'path', caseSensitive: true, literal });\n return parsed.ok ? { ok: true, glob: { source, compiled: parsed.glob, literals } } : parsed;\n}\n\n/**\n * Whether a path matches. The path is read as a repository path: empty and\n * `.` segments are dropped, so `./src//a.ts` is `src/a.ts`.\n */\nexport function matchGlob(glob: Glob, path: string): boolean {\n const canonical = segments(path).join('/');\n return canonical !== '' && glob.compiled.match(canonical);\n}\n\n/**\n * A shortest path every glob in `include` matches and none in `exclude` does,\n * `none` as a proof that there is no such path, or `undecided` when the search\n * met its budget first.\n */\nexport function globWitness(include: readonly Glob[], exclude: readonly Glob[] = [], budget: number = WITNESS_BUDGET): Witness {\n return coreWitness(\n include.map((g) => g.compiled),\n exclude.map((g) => g.compiled),\n budget,\n );\n}\n\n/** Whether every path `inner` matches is matched by one of `outer`, or `undecided`. */\nexport function globCovers(outer: readonly Glob[], inner: Glob, budget: number = WITNESS_BUDGET): boolean | 'undecided' {\n return coreCovers(\n outer.map((g) => g.compiled),\n inner.compiled,\n budget,\n );\n}\n\n/**\n * A path both globs match, or `null` when there is none: the 0.1 interface,\n * kept for the library's callers. It cannot say `undecided`, so a search that\n * meets its budget throws; {@link globWitness} answers in three ways.\n */\nexport function intersectGlobs(a: Glob, b: Glob, budget: number = WITNESS_BUDGET): string | null {\n const witness = globWitness([a, b], [], budget);\n if (witness.kind === 'undecided') {\n throw new Error(`whether \"${a.source}\" and \"${b.source}\" meet is undecided within the search's budget`);\n }\n return witness.kind === 'found' ? witness.path : null;\n}\n\n/**\n * The directories a walk must enter to find every match, one per brace\n * alternative: the leading literal segments, or a literal file's directory.\n * `''` for an alternative that can match at the root.\n */\nexport function globBases(glob: Glob): readonly string[] {\n return glob.compiled.bases;\n}\n\n/** The first of {@link globBases}: the 0.1 interface, kept for the library's callers. */\nexport function globBase(glob: Glob): string {\n // One base per alternative, and a pattern has at least one.\n return glob.compiled.bases[0] as string;\n}\n\n/** A name with an extension, `login.ts` or `.eslintrc.json`, and not a dot-name such as `.github`. */\nexport function hasExtension(name: string): boolean {\n return /.\\.[^.]+$/.test(name);\n}\n\n/** The files a tree holds, and every directory above one. */\nexport interface Tree {\n readonly files: ReadonlySet<string>;\n readonly directories: ReadonlySet<string>;\n}\n\nconst trees = new WeakMap<readonly string[], Tree>();\n\n/** The tree a list of files describes. Built once per list, which every brief of a run shares. */\nexport function treeOf(files: readonly string[]): Tree {\n const known = trees.get(files);\n if (known !== undefined) return known;\n const directories = new Set<string>();\n for (const file of files) {\n for (let slash = file.indexOf('/'); slash !== -1; slash = file.indexOf('/', slash + 1)) directories.add(file.slice(0, slash));\n }\n const tree = { files: new Set(files), directories };\n trees.set(files, tree);\n return tree;\n}\n\n/** What the tree holds at a path: a file, a directory, or nothing. */\nexport function held(tree: Tree, path: string): 'file' | 'directory' | null {\n if (tree.files.has(path)) return 'file';\n return tree.directories.has(path) ? 'directory' : null;\n}\n\n/**\n * How a tree reads a literal path: a directory it holds is a directory, and\n * anything else is a file. Without a tree nothing is known to be a directory,\n * so every literal is a file; a trailing `/` says otherwise, and never reaches\n * this question.\n */\nexport function readingIn(files: readonly string[] | null): (path: string) => LiteralReading {\n if (files === null) return () => 'file';\n const tree = treeOf(files);\n return (path) => (held(tree, path) === 'directory' ? 'directory' : 'file');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scopes as globs: spec-core's `path` dialect, read the way spec-brief reads a\n * brief.\n *\n * The syntax, the automaton and the witness search are spec-core's, copied\n * into `src/vendor/` and verified by hash, so the family's tools read one\n * pattern the same way (spec-core ADR-0003). What is decided here is what\n * spec-brief adds around it:\n *\n * - A pattern is relative to the repository root, so a leading `/` is refused\n * rather than rooted at the filesystem: on the pattern, one after a leading\n * `./` too, as in `.//docs`, and on a text its braces give, since spec-core\n * reads `{/docs,x}` as `/docs` or `x`, and `docs` would fall out of the\n * scope unsaid. A list entry's `!` has no list to belong to in a scope, so\n * it is refused rather than read.\n * - Paths compare case-sensitively on every host, as git's do.\n * - A path with no glob syntax is read as the tree reads it: a file the tree\n * holds is that file, a directory it holds is everything beneath it, and a\n * path it does not hold is a file, unless it is written with a trailing `/`.\n * The tree, not the spelling, knows that `Dockerfile` is a file and\n * `docs/v1.2` a directory (ADR-0005, amended 2026-09-26).\n * - A trailing `/**` is at least one segment, so `docs/**` is the directory's\n * contents and a collision witness is always a file. A trailing `/` means\n * the same on a brace alternative as on the whole pattern: `{src/,lib}` is\n * `src/` or `lib`, and the tree is asked about `lib` alone.\n *\n * Nothing here compiles to a `RegExp`. Matching costs at most the pattern's\n * size times the path's length, and a question about two scopes that cannot be\n * answered within the search's budget answers `undecided`, never a guess.\n */\n\nimport {\n globCovers as coreCovers,\n globWitness as coreWitness,\n isGlobSyntax,\n parseGlob as coreParse,\n type Glob as CoreGlob,\n type LiteralReading,\n WITNESS_BUDGET,\n type Witness,\n} from './vendor/spec-core/pattern/index.js';\nimport { segments } from './vendor/spec-core/path/index.js';\n\nexport { isGlobSyntax, type LiteralReading, WITNESS_BUDGET, type Witness };\n\n/** A literal path a pattern names, and how it was read. */\nexport interface Literal {\n readonly path: string;\n readonly reading: LiteralReading;\n}\n\nexport interface Glob {\n readonly source: string;\n /** The compiled pattern: spec-core's `path` dialect, case-sensitive. */\n readonly compiled: CoreGlob;\n /**\n * Each path the pattern names with no glob syntax and no trailing `/`, one\n * per brace alternative; empty when it has none.\n */\n readonly literals: readonly Literal[];\n}\n\nexport type GlobParse = { readonly ok: true; readonly glob: Glob } | { readonly ok: false; readonly error: string };\n\nexport interface ParseOptions {\n /**\n * How a path with no glob syntax is read: `file`, that path alone;\n * `directory`, everything beneath it; `either`, both. A function is asked\n * per literal path, as {@link readingIn} answers for a tree. `file` when\n * unset: a path nothing says is a directory is not read as one.\n */\n readonly literal?: LiteralReading | ((path: string) => LiteralReading) | undefined;\n}\n\n/** Parses a scope pattern, or says why it cannot. */\nexport function parseGlob(source: string, options: ParseOptions = {}): GlobParse {\n const pattern = source.trim();\n if (pattern.startsWith('!')) return { ok: false, error: 'negated patterns are not supported; narrow the positive pattern' };\n if (undotted(pattern).startsWith('/')) return { ok: false, error: 'a pattern is relative to the repository root and cannot start with \"/\"' };\n const given = options.literal ?? 'file';\n const literals: Literal[] = [];\n const literal = (path: string): LiteralReading => {\n const reading = typeof given === 'function' ? given(path) : given;\n literals.push({ path, reading });\n return reading;\n };\n // A pattern too large to compile is refused by the core, with its reason,\n // as a malformed one is; what the reading throws is a defect, and passes on.\n const parsed = coreParse(pattern, { dialect: 'path', caseSensitive: true, literal });\n if (!parsed.ok) return parsed;\n // Read once the core has parsed the pattern, so that its braces close and\n // give no more texts than the core allows.\n const rooted = rootedAlternative(pattern);\n if (rooted !== undefined) {\n return { ok: false, error: `a pattern is relative to the repository root, and the braces expand to \"${rooted}\", which starts with \"/\"` };\n }\n return { ok: true, glob: { source, compiled: parsed.glob, literals } };\n}\n\n/**\n * A pattern less the `./` it starts with. spec-core drops it before it reads\n * a leading `/`, since `.` names nothing: `.//docs` is `/docs`, rooted at the\n * filesystem's root.\n */\nfunction undotted(pattern: string): string {\n let rest = pattern;\n while (rest.startsWith('./')) rest = rest.slice(2);\n return rest;\n}\n\n/**\n * The first text a pattern's braces give that starts with `/` once its `./`\n * is dropped, less that `./`: an alternative spec-core roots at the\n * filesystem's root, since braces expand before a leading `/` is read, so\n * that `{/docs,x}` is `/docs` or `x` (spec-core ADR-0003, amended\n * 2026-09-29). `undefined` when there is none. A `/` after anything else\n * starts no text: `a/{/b,c}` gives `a//b`, which is `a/b`.\n *\n * spec-core keeps nothing of the texts its braces give, and the refusal names\n * the text, as the core's own refusals do. So this expands braces as the core\n * does, for a pattern the core parsed, whose braces close and give at most\n * `MAX_ALTERNATIVES` texts: a `\\` escapes the next character, a class holds\n * no brace syntax, a `}` with no `{` open is a literal, and the first braces\n * to close are expanded first, each option in turn, so the text named is the\n * first such text the core gives.\n *\n * Its loop, read one step past the end, reads `''`, which no branch acts on,\n * so a bound one further reads the same.\n */\nfunction rootedAlternative(pattern: string): string | undefined {\n let depth = 0;\n let open = 0;\n const stops: number[] = [];\n for (let i = 0; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\') {\n i += 1;\n } else if (ch === '[') {\n const close = classEnd(pattern, i);\n if (close !== -1) i = close;\n } else if (ch === '{') {\n if (depth === 0) open = i;\n depth += 1;\n } else if (ch === ',' && depth === 1) {\n stops.push(i);\n } else if (ch === '}' && depth > 0) {\n depth -= 1;\n if (depth === 0) {\n let start = open + 1;\n for (const stop of [...stops, i]) {\n const rooted = rootedAlternative(`${pattern.slice(0, open)}${pattern.slice(start, stop)}${pattern.slice(i + 1)}`);\n if (rooted !== undefined) return rooted;\n start = stop + 1;\n }\n return undefined;\n }\n }\n }\n const text = undotted(pattern);\n return text.startsWith('/') ? text : undefined;\n}\n\n/**\n * The index of the `]` closing a class opened at `open`, or -1 when none does\n * within its segment, as spec-core finds it while it expands braces: after a\n * `!` or `^`, the first member is a member even when it is `]`.\n */\nfunction classEnd(pattern: string, open: number): number {\n let i = open + 1;\n if (pattern.charAt(i) === '!' || pattern.charAt(i) === '^') i += 1;\n if (pattern.charAt(i) === ']') i += 1;\n for (; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\') i += 1;\n else if (ch === '/') return -1;\n else if (ch === ']') return i;\n }\n /* v8 ignore next -- in a pattern the core parsed, a \"[\" is closed, or met by a \"/\", before the pattern ends. */\n return -1;\n}\n\n/**\n * Whether a path matches. The path is read as a repository path: empty and\n * `.` segments are dropped, so `./src//a.ts` is `src/a.ts`.\n */\nexport function matchGlob(glob: Glob, path: string): boolean {\n const canonical = segments(path).join('/');\n return canonical !== '' && glob.compiled.match(canonical);\n}\n\n/**\n * A shortest path every glob in `include` matches and none in `exclude` does,\n * `none` as a proof that there is no such path, or `undecided` when the search\n * met its budget first.\n */\nexport function globWitness(include: readonly Glob[], exclude: readonly Glob[] = [], budget: number = WITNESS_BUDGET): Witness {\n return coreWitness(\n include.map((g) => g.compiled),\n exclude.map((g) => g.compiled),\n budget,\n );\n}\n\n/** Whether every path `inner` matches is matched by one of `outer`, or `undecided`. */\nexport function globCovers(outer: readonly Glob[], inner: Glob, budget: number = WITNESS_BUDGET): boolean | 'undecided' {\n return coreCovers(\n outer.map((g) => g.compiled),\n inner.compiled,\n budget,\n );\n}\n\n/**\n * A path both globs match, or `null` when there is none: the 0.1 interface,\n * kept for the library's callers. It cannot say `undecided`, so a search that\n * meets its budget throws; {@link globWitness} answers in three ways.\n */\nexport function intersectGlobs(a: Glob, b: Glob, budget: number = WITNESS_BUDGET): string | null {\n const witness = globWitness([a, b], [], budget);\n if (witness.kind === 'undecided') {\n throw new Error(`whether \"${a.source}\" and \"${b.source}\" meet is undecided within the search's budget`);\n }\n return witness.kind === 'found' ? witness.path : null;\n}\n\n/**\n * The directories a walk must enter to find every match, one per brace\n * alternative: the leading literal segments, or a literal file's directory.\n * `''` for an alternative that can match at the root.\n */\nexport function globBases(glob: Glob): readonly string[] {\n return glob.compiled.bases;\n}\n\n/** The first of {@link globBases}: the 0.1 interface, kept for the library's callers. */\nexport function globBase(glob: Glob): string {\n // One base per alternative, and a pattern has at least one.\n return glob.compiled.bases[0] as string;\n}\n\n/** A brace alternative as its pattern writes it, and the index in the pattern where it ends. */\nexport interface WrittenAlternative {\n readonly written: string;\n readonly end: number;\n}\n\n/**\n * Each alternative of a pattern as written, in the order the core expands\n * them, and where each ends, when a `/` written there ends that alternative\n * and no other: the pattern itself when it has no braces, or the alternatives\n * of braces that end the pattern and whose own braces end theirs -\n * `lib/{util,new}`, `{a,b/{c,d}}`. `null` when more of the pattern follows\n * braces, `{a,b}/new`, since every alternative they give ends where the\n * pattern does; and for a pattern with a class, which may hold a brace or a\n * comma of its own and which this does not read.\n *\n * spec-core expands braces and keeps nothing of where an alternative was\n * written, and a note's advice is built from what was written, as the core\n * builds its own. So this reads braces as the expansion does, for a pattern\n * that parses: a `\\` escapes the next character, and a `}` with no `{` open\n * is a literal.\n */\nexport function writtenAlternatives(pattern: string): WrittenAlternative[] | null {\n let depth = 0;\n let open = 0;\n const stops: number[] = [];\n for (let i = 0; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\') {\n i += 1;\n } else if (ch === '[') {\n return null;\n } else if (ch === '{') {\n if (depth === 0) open = i;\n depth += 1;\n } else if (ch === ',' && depth === 1) {\n stops.push(i);\n } else if (ch === '}' && depth > 0) {\n depth -= 1;\n if (depth === 0) return i === pattern.length - 1 ? optionsOf(pattern, open, [...stops, i]) : null;\n }\n }\n return [{ written: pattern, end: pattern.length }];\n}\n\n/** The alternatives of the braces opened at `open`, each option ending at one of `stops`. */\nfunction optionsOf(pattern: string, open: number, stops: readonly number[]): WrittenAlternative[] | null {\n const prefix = pattern.slice(0, open);\n const alternatives: WrittenAlternative[] = [];\n let start = open + 1;\n for (const stop of stops) {\n const inner = writtenAlternatives(pattern.slice(start, stop));\n if (inner === null) return null;\n for (const { written, end } of inner) alternatives.push({ written: prefix + written, end: start + end });\n start = stop + 1;\n }\n return alternatives;\n}\n\n/** A name with an extension, `login.ts` or `.eslintrc.json`, and not a dot-name such as `.github`. */\nexport function hasExtension(name: string): boolean {\n return /.\\.[^.]+$/.test(name);\n}\n\n/** The files a tree holds, and every directory above one. */\nexport interface Tree {\n readonly files: ReadonlySet<string>;\n readonly directories: ReadonlySet<string>;\n}\n\nconst trees = new WeakMap<readonly string[], Tree>();\n\n/** The tree a list of files describes. Built once per list, which every brief of a run shares. */\nexport function treeOf(files: readonly string[]): Tree {\n const known = trees.get(files);\n if (known !== undefined) return known;\n const directories = new Set<string>();\n for (const file of files) {\n for (let slash = file.indexOf('/'); slash !== -1; slash = file.indexOf('/', slash + 1)) directories.add(file.slice(0, slash));\n }\n const tree = { files: new Set(files), directories };\n trees.set(files, tree);\n return tree;\n}\n\n/** What the tree holds at a path: a file, a directory, or nothing. */\nexport function held(tree: Tree, path: string): 'file' | 'directory' | null {\n if (tree.files.has(path)) return 'file';\n return tree.directories.has(path) ? 'directory' : null;\n}\n\n/**\n * How a tree reads a literal path: a directory it holds is a directory, and\n * anything else is a file. Without a tree nothing is known to be a directory,\n * so every literal is a file; a trailing `/` says otherwise, and never reaches\n * this question.\n */\nexport function readingIn(files: readonly string[] | null): (path: string) => LiteralReading {\n if (files === null) return () => 'file';\n const tree = treeOf(files);\n return (path) => (held(tree, path) === 'directory' ? 'directory' : 'file');\n}\n"]}
|
package/dist/rules.js
CHANGED
|
@@ -12,7 +12,7 @@ import { statusWords } from './config.js';
|
|
|
12
12
|
import { dependencyCycles, duplicateIds, idKey, resolveDependency } from './corpus.js';
|
|
13
13
|
import { findEntry } from './frontmatter.js';
|
|
14
14
|
import { integrityOf } from './integrity.js';
|
|
15
|
-
import { hasExtension, held, isGlobSyntax, matchGlob, parseGlob, readingIn, treeOf, WITNESS_BUDGET } from './glob.js';
|
|
15
|
+
import { hasExtension, held, isGlobSyntax, matchGlob, parseGlob, readingIn, treeOf, WITNESS_BUDGET, writtenAlternatives } from './glob.js';
|
|
16
16
|
import { hasContent } from './markdown.js';
|
|
17
17
|
import { closest } from './schema.js';
|
|
18
18
|
import { contradictions, patternsOf, scopeOf } from './scope.js';
|
|
@@ -76,6 +76,39 @@ export function unheldLiterals(glob, files) {
|
|
|
76
76
|
.map((literal) => literal.path)
|
|
77
77
|
.filter((path) => held(tree, path) === null && !hasExtension(path.slice(path.lastIndexOf('/') + 1)));
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* What to write for a directory where a pattern names paths the tree reads as
|
|
81
|
+
* files, built from the pattern as written, as spec-core builds its own
|
|
82
|
+
* advice: the pattern with a `/` ending each alternative that names one, since
|
|
83
|
+
* a trailing `/` inside braces says directory as it does alone, or each such
|
|
84
|
+
* alternative in an entry of its own (ADR-0005, amended 2026-09-29). Where
|
|
85
|
+
* more of the pattern follows braces, `{a,b}/new`, no `/` written inside them
|
|
86
|
+
* ends one alternative alone, so an entry of its own is the advice; and an
|
|
87
|
+
* alternative the reader refuses as an entry, one opening with `!`, is left as
|
|
88
|
+
* written. The reader trims every list item, so the pattern is as meant.
|
|
89
|
+
*/
|
|
90
|
+
function directoryAdvice(pattern, paths) {
|
|
91
|
+
const alternatives = writtenAlternatives(pattern) ?? [];
|
|
92
|
+
const named = alternatives.filter(({ written }) => {
|
|
93
|
+
const parsed = parseGlob(written);
|
|
94
|
+
return parsed.ok && parsed.glob.literals.some((literal) => paths.includes(literal.path));
|
|
95
|
+
});
|
|
96
|
+
const entries = (named.length === 0 ? paths : named.map(({ written }) => written)).map((entry) => `${entry}/`);
|
|
97
|
+
const one = entries.length === 1;
|
|
98
|
+
const kind = one ? 'a directory' : 'directories';
|
|
99
|
+
const own = one ? 'an entry of its own' : 'entries of their own';
|
|
100
|
+
if (named.length === 0)
|
|
101
|
+
return `write ${quoted(entries)} for ${kind}, in ${own}`;
|
|
102
|
+
if (alternatives.length === 1)
|
|
103
|
+
return `write ${quoted(entries)} for ${kind}`;
|
|
104
|
+
let slashed = '';
|
|
105
|
+
let from = 0;
|
|
106
|
+
for (const { end } of named) {
|
|
107
|
+
slashed += `${pattern.slice(from, end)}/`;
|
|
108
|
+
from = end;
|
|
109
|
+
}
|
|
110
|
+
return `write "${slashed}${pattern.slice(from)}" for ${kind}, or ${quoted(entries)} in ${own}`;
|
|
111
|
+
}
|
|
79
112
|
/**
|
|
80
113
|
* Affected patterns a brief's own protections cover entirely: one error for
|
|
81
114
|
* all of them, and a warning for those the search could not decide.
|
|
@@ -499,21 +532,15 @@ export const RULES = [
|
|
|
499
532
|
if (paths.length === 0)
|
|
500
533
|
return [];
|
|
501
534
|
const line = at(lineOfField(brief, field));
|
|
535
|
+
const hint = directoryAdvice(pattern, paths);
|
|
502
536
|
if (!isGlobSyntax(pattern)) {
|
|
503
|
-
return [
|
|
504
|
-
{
|
|
505
|
-
line,
|
|
506
|
-
message: `"${pattern}" in ${field} is not in the tree and is read as a file`,
|
|
507
|
-
// The reader trims every list item, so the pattern is as meant.
|
|
508
|
-
hint: `write "${pattern}/" for a directory`,
|
|
509
|
-
},
|
|
510
|
-
];
|
|
537
|
+
return [{ line, message: `"${pattern}" in ${field} is not in the tree and is read as a file`, hint }];
|
|
511
538
|
}
|
|
512
539
|
return [
|
|
513
540
|
{
|
|
514
541
|
line,
|
|
515
542
|
message: `"${pattern}" in ${field} names ${inWords(paths)}, which ${paths.length === 1 ? 'is' : 'are'} not in the tree and ${paths.length === 1 ? 'is' : 'are'} read as ${paths.length === 1 ? 'a file' : 'files'}`,
|
|
516
|
-
hint
|
|
543
|
+
hint,
|
|
517
544
|
},
|
|
518
545
|
];
|
|
519
546
|
}));
|
package/dist/rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The built-in rules. Each is a pure function of one brief and the corpus\n * around it, and returns what it found with 1-based lines.\n *\n * Structure is checked on live briefs only. An archived brief is a frozen\n * record of the tree before a round, and holding it to today's schema would\n * ask somebody to edit what must not be edited; the rules that do reach the\n * archive are about identity and the freeze itself.\n */\n\nimport { BUILT_IN_FIELDS, type Brief, knownFields, lineOfField } from './brief.js';\nimport { type Config, type SectionRule, statusWords } from './config.js';\nimport { type Corpus, dependencyCycles, duplicateIds, idKey, resolveDependency } from './corpus.js';\nimport { findEntry } from './frontmatter.js';\nimport { integrityOf } from './integrity.js';\nimport { type Glob, hasExtension, held, isGlobSyntax, matchGlob, parseGlob, readingIn, treeOf, WITNESS_BUDGET } from './glob.js';\nimport { hasContent, type Section } from './markdown.js';\nimport { closest } from './schema.js';\nimport { contradictions, patternsOf, scopeOf, type ScopePattern } from './scope.js';\nimport { inWords, labelMatches } from './text.js';\nimport { namesAnEvent } from './trigger.js';\nimport type { Severity, SeveritySetting } from './types.js';\n\nexport interface RuleResult {\n /** 1-based. */\n readonly line: number;\n readonly message: string;\n readonly hint?: string | undefined;\n /** Lower than the rule's severity for this one finding, as a draft's unwritten sections are. */\n readonly severity?: Severity | undefined;\n}\n\nexport interface RuleContext {\n readonly brief: Brief;\n readonly corpus: Corpus;\n readonly config: Config;\n /** The files git sees, or every file without git; `null` when unknown. A rule that needs them stays quiet without them. */\n readonly repoFiles: readonly string[] | null;\n /** Analyses computed once per run and shared by every brief. */\n readonly shared: SharedAnalysis;\n /** A plugin's options from the configuration. */\n readonly options?: unknown;\n}\n\n/** What a rule is called, how loud it is by default, and what it checks. */\nexport interface RuleInfo {\n readonly id: string;\n readonly severity: SeveritySetting;\n readonly description: string;\n}\n\nexport interface Rule extends RuleInfo {\n check(context: RuleContext): readonly RuleResult[] | Promise<readonly RuleResult[]>;\n}\n\nexport interface SharedAnalysis {\n readonly cycles: readonly (readonly Brief[])[];\n readonly duplicates: ReadonlyMap<string, readonly Brief[]>;\n}\n\nexport function analyse(corpus: Corpus): SharedAnalysis {\n return { cycles: dependencyCycles(corpus), duplicates: duplicateIds(corpus) };\n}\n\nconst at = (line0: number): number => line0 + 1;\n\n/** The sections a brief must carry: the configured ones, then its type's. */\nexport function sectionRules(brief: Brief, config: Config): SectionRule[] {\n const typed = brief.type === null ? [] : (config.types[brief.type] ?? []);\n return [...config.sections, ...typed];\n}\n\n/** The headings that fill a section rule. */\nexport function sectionsFilling(brief: Brief, rule: SectionRule): Section[] {\n const names = [rule.name, ...rule.aliases];\n return brief.sections.filter((s) => names.some((name) => labelMatches(s.heading.text, name)));\n}\n\n/** A section's own lines that carry content: comments dropped, sub-headings not counted. */\nfunction contentLines(brief: Brief, section: Section): number[] {\n const headingLines = new Set(brief.scan.headings.map((h) => h.line));\n const lines: number[] = [];\n for (let i = section.heading.line + 1; i < section.end; i += 1) {\n if (!headingLines.has(i) && hasContent(brief.scan.prose[i] as string)) lines.push(i);\n }\n return lines;\n}\n\nfunction isPlaceholder(line: string, placeholders: readonly string[]): boolean {\n const text = line\n .replace(/^\\s*(?:[-*+]|\\d{1,9}[.)])\\s+/, '')\n .replace(/^\\[[ xX]\\]\\s*/, '')\n .replace(/[*_]/g, '')\n .trim();\n if (text === '') return true;\n const lower = text.toLowerCase();\n return placeholders.some((p) => {\n const word = p.toLowerCase();\n return lower === word || (lower.startsWith(word) && /^[\\s:.\\-\\u2014]/.test(lower.slice(word.length)));\n });\n}\n\n/** Completeness findings on a draft are reminders, not failures. */\nfunction leniency(brief: Brief): Severity | undefined {\n return brief.status === 'draft' ? 'warning' : undefined;\n}\n\nfunction live(check: (context: RuleContext) => RuleResult[]): (context: RuleContext) => RuleResult[] {\n return (context) => (context.brief.phase === 'live' ? check(context) : []);\n}\n\nconst SCOPE_FIELDS = ['affectedFiles', 'protectedFiles'] as const;\n\nconst quoted = (items: readonly string[]): string => inWords(items.map((item) => `\"${item}\"`));\n\n/**\n * The paths a pattern names with no glob syntax that the tree does not hold\n * and whose names carry no extension. The tree reads each as a file, and the\n * spelling cannot say whether a directory was meant.\n */\nexport function unheldLiterals(glob: Glob, files: readonly string[]): string[] {\n const tree = treeOf(files);\n return glob.literals\n .map((literal) => literal.path)\n .filter((path) => held(tree, path) === null && !hasExtension(path.slice(path.lastIndexOf('/') + 1)));\n}\n\n/**\n * Affected patterns a brief's own protections cover entirely: one error for\n * all of them, and a warning for those the search could not decide.\n */\nexport function scopeContradiction(brief: Brief, repoFiles: readonly string[] | null, budget: number = WITNESS_BUDGET): RuleResult[] {\n const { covered, undecided } = contradictions(scopeOf(brief, readingIn(repoFiles)), budget);\n const line = at(lineOfField(brief, 'protectedFiles'));\n const results: RuleResult[] = [];\n if (covered.length > 0) {\n const one = covered.length === 1;\n results.push({\n line,\n message: `${quoted(covered)} in affectedFiles ${one ? 'is' : 'are'} entirely protected, so nothing of ${one ? 'it' : 'them'} is writable`,\n hint: `drop ${one ? 'it' : 'them'} from affectedFiles, or narrow protectedFiles so that some of ${one ? 'it' : 'each'} is writable`,\n });\n }\n if (undecided.length > 0) {\n results.push({\n line,\n message: `whether ${quoted(undecided)} in affectedFiles ${undecided.length === 1 ? 'is' : 'are'} entirely protected is undecided: the search met its budget`,\n hint: 'simplify the patterns until the question can be answered',\n severity: 'warning',\n });\n }\n return results;\n}\n\nexport const RULES: readonly Rule[] = [\n {\n id: 'front-matter',\n severity: 'error',\n description: 'Front matter parses, with no duplicate keys and no YAML beyond the supported subset.',\n check: ({ brief }) =>\n (brief.frontMatter?.problems ?? []).map((p) => ({\n line: at(p.line),\n message: p.message,\n hint: 'front matter is flat \"key: value\" lines, with lists as [a, b] or \"- item\" lines',\n })),\n },\n {\n id: 'field',\n severity: 'error',\n description: 'Fields spec-brief reads hold values of the right shape.',\n check: ({ brief }) => brief.problems.map((p) => ({ line: at(p.line), message: p.message })),\n },\n {\n id: 'unknown-field',\n severity: 'warning',\n description: 'Front-matter keys are ones spec-brief or the configuration knows.',\n check: ({ brief, config }) => {\n const known = knownFields(config);\n return (brief.frontMatter?.entries ?? [])\n .filter((entry) => !known.has(entry.name))\n .map((entry) => {\n const guess = closest(entry.key, BUILT_IN_FIELDS);\n return {\n line: at(entry.line),\n message: `\"${entry.key}\" is not a key spec-brief knows`,\n hint:\n guess === undefined\n ? `if the repository uses it, list it under \"fields\" in the configuration`\n : `did you mean \"${guess}\"? If not, list \"${entry.key}\" under \"fields\" in the configuration`,\n };\n });\n },\n },\n {\n id: 'status',\n severity: 'error',\n description: 'The status agrees with where the brief lives.',\n check: ({ brief, config }) => {\n const field = config.status.field;\n if (field === null) return [];\n const line = at(lineOfField(brief, field));\n const expected = brief.phase === 'archived' ? config.status.archived : config.status.active;\n if (brief.statusWord === null) {\n return [\n {\n line,\n message: `declares no \"${field}\"`,\n hint: `add \"${field}: ${expected}\" to the front matter`,\n },\n ];\n }\n if (brief.status === null) {\n const words = statusWords(config);\n return [\n {\n line,\n message: `\"${brief.statusWord}\" is not a status here`,\n hint: `use one of ${words.map((w) => `\"${w}\"`).join(', ')}`,\n },\n ];\n }\n if (brief.phase === 'live' && brief.status === 'archived') {\n return [\n {\n line,\n message: `is marked \"${brief.statusWord}\" but lives in ${config.briefs}/`,\n hint: `run \"spec-brief archive ${brief.id ?? brief.name}\", which moves it and writes its banner`,\n },\n ];\n }\n if (brief.phase === 'archived' && brief.status !== 'archived') {\n return [\n {\n line,\n message: `lives in ${config.archive}/ but is marked \"${brief.statusWord}\"`,\n hint: `run \"spec-brief unarchive ${brief.id ?? brief.name}\" to reopen it, or set \"${field}: ${config.status.archived}\"`,\n },\n ];\n }\n return [];\n },\n },\n {\n id: 'id',\n severity: 'error',\n description: 'Every brief has an id with no whitespace or slashes in it.',\n check: ({ brief, config }) => {\n if (brief.id === null) {\n return [\n {\n line: 1,\n message: config.id.source === 'frontmatter' ? 'declares no \"id\"' : 'has no id in its file name',\n hint: config.id.source === 'frontmatter' ? 'add \"id: <id>\" to the front matter' : undefined,\n },\n ];\n }\n if (/[\\s/\\\\]/.test(brief.id)) return [{ line: 1, message: `the id \"${brief.id}\" contains whitespace or a slash` }];\n return [];\n },\n },\n {\n id: 'duplicate-id',\n severity: 'error',\n description: 'No two briefs share an id, live or archived.',\n check: ({ brief, shared }) => {\n if (brief.id === null) return [];\n const group = shared.duplicates.get(idKey(brief.id));\n if (group === undefined || group[0] === brief) return [];\n return [\n {\n line: 1,\n message: `the id \"${brief.id}\" is also ${(group[0] as Brief).file}'s`,\n hint: 'ids are allocated once and never reused; give this brief the next free one',\n },\n ];\n },\n },\n {\n id: 'title',\n severity: 'warning',\n description: 'A brief has a title: a \"title\" field or a level-one heading.',\n check: live(({ brief }) =>\n brief.title === null ? [{ line: at(brief.bodyStart), message: 'has no title', hint: 'start the body with \"# <title>\"' }] : [],\n ),\n },\n {\n id: 'unknown-type',\n severity: 'error',\n description: 'A declared type is one the configuration defines.',\n check: live(({ brief, config }) => {\n if (brief.type === null || config.types[brief.type] !== undefined) return [];\n const names = Object.keys(config.types);\n return [\n {\n line: at(lineOfField(brief, 'type')),\n message: `\"${brief.type}\" is not a brief type here`,\n hint: names.length === 0 ? 'the configuration defines no types' : `use one of ${names.map((n) => `\"${n}\"`).join(', ')}`,\n },\n ];\n }),\n },\n {\n id: 'missing-section',\n severity: 'error',\n description: 'Every required section is present.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config)\n .filter((rule) => !rule.optional && sectionsFilling(brief, rule).length === 0)\n .map((rule) => {\n const heading =\n rule.aliases.length === 0\n ? `add a \"## ${rule.name}\" heading`\n : `add a \"## ${rule.name}\" heading (also accepted: ${rule.aliases.map((a) => `\"${a}\"`).join(', ')})`;\n return {\n line: at(brief.bodyStart),\n message: `has no \"${rule.name}\" section`,\n hint: rule.hint === undefined ? heading : `${heading}. ${rule.hint}`,\n };\n }),\n ),\n },\n {\n id: 'duplicate-section',\n severity: 'warning',\n description: 'A section appears once.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(1)\n .map((s) => ({ line: at(s.heading.line), message: `a second \"${rule.name}\" section`, hint: 'merge the two' })),\n ),\n ),\n },\n {\n id: 'empty-section',\n severity: 'error',\n description: 'A section carries content; a comment alone is not content.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(0, 1)\n .filter((s) => contentLines(brief, s).length === 0)\n .map((s) => ({\n line: at(s.heading.line),\n message: `the \"${rule.name}\" section is empty`,\n hint: rule.hint ?? 'write it; a comment alone is not content',\n severity: leniency(brief),\n })),\n ),\n ),\n },\n {\n id: 'placeholder',\n severity: 'error',\n description: 'A section says something: not only \"TBD\", \"TODO\" or an empty box.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(0, 1)\n .filter((s) => {\n const lines = contentLines(brief, s);\n return lines.length > 0 && lines.every((i) => isPlaceholder(brief.scan.prose[i] as string, config.placeholders));\n })\n .map((s) => ({\n line: at(s.heading.line),\n message: `the \"${rule.name}\" section holds only a placeholder`,\n hint: rule.hint ?? 'replace the placeholder with what the section must say',\n severity: leniency(brief),\n })),\n ),\n ),\n },\n {\n id: 'missing-checklist',\n severity: 'error',\n description: 'A checklist section holds at least one task item.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config)\n .filter((rule) => rule.checklist)\n .flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(0, 1)\n .filter((s) => !brief.tasks.some((t) => t.line > s.heading.line && t.line < s.end))\n .map((s) => ({\n line: at(s.heading.line),\n message: `the \"${rule.name}\" section has no \"- [ ]\" items`,\n hint: 'write each check as a task item, so it has a state that can be closed',\n severity: leniency(brief),\n })),\n ),\n ),\n },\n {\n id: 'must-contain',\n severity: 'error',\n description: 'A section contains the text the configuration requires of it.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) => {\n const section = sectionsFilling(brief, rule)[0];\n if (section === undefined) return [];\n const body = brief.scan.prose.slice(section.heading.line + 1, section.end).join('\\n');\n return rule.mustContain\n .filter((text) => !body.includes(text))\n .map((text) => ({ line: at(section.heading.line), message: `the \"${rule.name}\" section must contain \"${text}\"` }));\n }),\n ),\n },\n {\n id: 'section-order',\n severity: 'error',\n description: 'Sections appear in the configured order, when the configuration asks for one.',\n check: live(({ brief, config }) => {\n if (!config.sectionOrder) return [];\n const placed = sectionRules(brief, config)\n .map((rule) => ({ rule, section: sectionsFilling(brief, rule)[0] }))\n .filter((p): p is { rule: SectionRule; section: Section } => p.section !== undefined);\n for (let i = 1; i < placed.length; i += 1) {\n const before = placed[i - 1] as { rule: SectionRule; section: Section };\n const current = placed[i] as { rule: SectionRule; section: Section };\n if (current.section.heading.line < before.section.heading.line) {\n return [\n {\n line: at(current.section.heading.line),\n message: `\"${current.rule.name}\" comes before \"${before.rule.name}\"`,\n hint: `the order is ${sectionRules(brief, config)\n .map((r) => r.name)\n .join(', ')}`,\n },\n ];\n }\n }\n return [];\n }),\n },\n {\n id: 'dependency',\n severity: 'error',\n description: 'Every dependency names another brief that exists.',\n check: live(({ brief, corpus }) =>\n brief.dependsOn.flatMap((dependency) => {\n const line = at(lineOfField(brief, 'dependsOn'));\n if (brief.id !== null && idKey(dependency) === idKey(brief.id)) {\n return [{ line, message: 'depends on itself' }];\n }\n if (resolveDependency(corpus, dependency) === undefined) {\n return [{ line, message: `depends on \"${dependency}\", which is not a brief here` }];\n }\n return [];\n }),\n ),\n },\n {\n id: 'dependency-cycle',\n severity: 'error',\n description: 'Dependencies between live briefs form no cycle.',\n check: live(({ brief, shared }) =>\n shared.cycles\n .filter((cycle) => cycle[0] === brief)\n .map((cycle) => ({\n line: at(lineOfField(brief, 'dependsOn')),\n message: `dependencies form a cycle: ${cycle.map((b) => b.id ?? b.name).join(' -> ')}`,\n hint: 'a cycle can never become ready; remove the dependency that is not real',\n })),\n ),\n },\n {\n id: 'wave-order',\n severity: 'error',\n description: 'A dependency that is still live runs in an earlier wave.',\n check: live(({ brief, corpus }) => {\n const wave = brief.wave;\n if (wave === null) return [];\n return brief.dependsOn.flatMap((dependency) => {\n const target = resolveDependency(corpus, dependency);\n // A self-dependency is reported once, by the dependency rule.\n if (target === undefined || target === brief || target.phase !== 'live' || target.wave === null || target.wave < wave) return [];\n return [\n {\n line: at(lineOfField(brief, 'dependsOn')),\n message: `depends on ${target.id ?? target.name}, which is in wave ${target.wave}, not before wave ${wave}`,\n hint: `move this brief to a wave after ${target.wave}, or ${target.id ?? target.name} to one before ${wave}`,\n },\n ];\n });\n }),\n },\n {\n id: 'deferral-trigger',\n severity: 'error',\n description: 'A deferred brief names in \"trigger\" the observable event that brings it back, not a date.',\n check: live(({ brief, config }) => {\n // A trigger of the wrong shape is the field rule's finding.\n if (brief.status !== 'deferred' || brief.problems.some((p) => p.field === 'trigger')) return [];\n const example = 'such as \"when the second tenant signs\" or \"when p95 exceeds 200 ms\"';\n const trigger = brief.trigger?.trim() ?? '';\n if (trigger === '') {\n const declared = findEntry(brief.frontMatter, 'trigger') !== undefined;\n return [\n {\n line: at(lineOfField(brief, declared ? 'trigger' : (config.status.field as string))),\n message: 'is deferred and names no \"trigger\"',\n hint: `add \"trigger: <the event that brings it back>\", ${example}`,\n },\n ];\n }\n const line = at(lineOfField(brief, 'trigger'));\n const hint = `name what must happen before the work resumes, ${example}`;\n if (config.placeholders.some((p) => p.toLowerCase() === trigger.toLowerCase())) {\n return [{ line, message: `the trigger \"${trigger}\" is a placeholder, not an event`, hint }];\n }\n if (!namesAnEvent(trigger)) {\n return [{ line, message: `the trigger \"${trigger}\" is a date or a time, not an event`, hint: `${hint}; a date arrives whether or not the reason for the work has` }];\n }\n return [];\n }),\n },\n {\n id: 'glob',\n severity: 'error',\n description: 'Every scope pattern is a glob spec-brief can read.',\n check: live(({ brief }) =>\n SCOPE_FIELDS.flatMap((field) =>\n brief[field].flatMap((pattern) => {\n const parsed = parseGlob(pattern);\n if (parsed.ok) return [];\n return [\n {\n line: at(lineOfField(brief, field)),\n message: `\"${pattern}\" in ${field}: ${parsed.error}`,\n hint: 'a scope is a glob relative to the repository root: \"src/auth/\", \"src/**/*.ts\", \"docs/{a,b}.md\"',\n },\n ];\n }),\n ),\n ),\n },\n {\n id: 'scope-contradiction',\n severity: 'error',\n description: 'Something of every affected pattern is writable: no pattern lies wholly inside protectedFiles.',\n check: live(({ brief, repoFiles }) => scopeContradiction(brief, repoFiles)),\n },\n {\n id: 'glob-matches-nothing',\n severity: 'note',\n description: 'A scope pattern matches at least one file in the tree.',\n check: live(({ brief, repoFiles }) => {\n if (repoFiles === null) return [];\n const reading = readingIn(repoFiles);\n return SCOPE_FIELDS.flatMap((field) =>\n patternsOf(brief[field], reading)\n // A literal the tree does not hold is literal-read-as-file's finding.\n .filter((p) => unheldLiterals(p.glob, repoFiles).length === 0 && !repoFiles.some((file) => matchGlob(p.glob, file)))\n .map((p) => ({\n line: at(lineOfField(brief, field)),\n message: `\"${p.pattern}\" in ${field} matches no file in the tree`,\n hint: 'expected when the round creates it; otherwise check the spelling',\n })),\n );\n }),\n },\n {\n id: 'literal-read-as-file',\n severity: 'note',\n description: 'A path with no glob syntax that the tree does not hold, and whose name has no extension, says whether it is a directory.',\n check: live(({ brief, repoFiles }) => {\n if (repoFiles === null) return [];\n const reading = readingIn(repoFiles);\n return SCOPE_FIELDS.flatMap((field) =>\n patternsOf(brief[field], reading).flatMap(({ pattern, glob }: ScopePattern) => {\n const paths = unheldLiterals(glob, repoFiles);\n if (paths.length === 0) return [];\n const line = at(lineOfField(brief, field));\n if (!isGlobSyntax(pattern)) {\n return [\n {\n line,\n message: `\"${pattern}\" in ${field} is not in the tree and is read as a file`,\n // The reader trims every list item, so the pattern is as meant.\n hint: `write \"${pattern}/\" for a directory`,\n },\n ];\n }\n return [\n {\n line,\n message: `\"${pattern}\" in ${field} names ${inWords(paths)}, which ${paths.length === 1 ? 'is' : 'are'} not in the tree and ${paths.length === 1 ? 'is' : 'are'} read as ${paths.length === 1 ? 'a file' : 'files'}`,\n hint: 'write a directory with a trailing \"/\", in an entry of its own',\n },\n ];\n }),\n );\n }),\n },\n {\n id: 'archive-freeze',\n severity: 'error',\n description: 'An archived brief has not changed since it was archived.',\n check: ({ brief }) => {\n if (brief.phase !== 'archived' || brief.integrity === null) return [];\n if (integrityOf(brief.text) === brief.integrity) return [];\n return [\n {\n line: at(lineOfField(brief, 'integrity')),\n message: 'has changed since it was archived',\n hint: 'an archived brief is frozen: restore it from git, or unarchive it to reopen the round',\n },\n ];\n },\n },\n];\n\n/**\n * The rules the wave analyses - `matrix` and `schedule` - report under. They\n * are not run per brief, so they carry no check: they exist so configuration\n * can set their severity and reports can describe them.\n */\nexport const COLLISION_RULES: readonly RuleInfo[] = [\n { id: 'collision', severity: 'error', description: 'Briefs in one wave do not write the same file.' },\n {\n id: 'collision-undecided',\n severity: 'warning',\n description: 'Whether two briefs in one wave can write the same file is decided within the search budget.',\n },\n { id: 'unscoped', severity: 'note', description: 'A brief sharing a wave declares the files it writes.' },\n { id: 'shared-directory', severity: 'off', description: 'Briefs in one wave do not write into the same directory.' },\n {\n id: 'wave-schedule',\n severity: 'error',\n description: 'A brief declares a wave that holds: the one the schedule computes, or one lint and matrix accept, which is a note.',\n },\n];\n\n/**\n * The rules archival reports under beside its refusals. Like the collision\n * rules they carry no check: the planner raises them, and they exist so\n * configuration can set their severity and reports can describe them.\n */\nexport const ARCHIVE_RULES: readonly RuleInfo[] = [\n {\n id: 'scope-unmeasured',\n severity: 'warning',\n description: 'A brief that declares a scope is archived against the changes its round made.',\n },\n {\n id: 'stale-link',\n severity: 'warning',\n description: 'No live brief is left linking to where a moved brief used to be.',\n },\n];\n"]}
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The built-in rules. Each is a pure function of one brief and the corpus\n * around it, and returns what it found with 1-based lines.\n *\n * Structure is checked on live briefs only. An archived brief is a frozen\n * record of the tree before a round, and holding it to today's schema would\n * ask somebody to edit what must not be edited; the rules that do reach the\n * archive are about identity and the freeze itself.\n */\n\nimport { BUILT_IN_FIELDS, type Brief, knownFields, lineOfField } from './brief.js';\nimport { type Config, type SectionRule, statusWords } from './config.js';\nimport { type Corpus, dependencyCycles, duplicateIds, idKey, resolveDependency } from './corpus.js';\nimport { findEntry } from './frontmatter.js';\nimport { integrityOf } from './integrity.js';\nimport { type Glob, hasExtension, held, isGlobSyntax, matchGlob, parseGlob, readingIn, treeOf, WITNESS_BUDGET, writtenAlternatives } from './glob.js';\nimport { hasContent, type Section } from './markdown.js';\nimport { closest } from './schema.js';\nimport { contradictions, patternsOf, scopeOf, type ScopePattern } from './scope.js';\nimport { inWords, labelMatches } from './text.js';\nimport { namesAnEvent } from './trigger.js';\nimport type { Severity, SeveritySetting } from './types.js';\n\nexport interface RuleResult {\n /** 1-based. */\n readonly line: number;\n readonly message: string;\n readonly hint?: string | undefined;\n /** Lower than the rule's severity for this one finding, as a draft's unwritten sections are. */\n readonly severity?: Severity | undefined;\n}\n\nexport interface RuleContext {\n readonly brief: Brief;\n readonly corpus: Corpus;\n readonly config: Config;\n /** The files git sees, or every file without git; `null` when unknown. A rule that needs them stays quiet without them. */\n readonly repoFiles: readonly string[] | null;\n /** Analyses computed once per run and shared by every brief. */\n readonly shared: SharedAnalysis;\n /** A plugin's options from the configuration. */\n readonly options?: unknown;\n}\n\n/** What a rule is called, how loud it is by default, and what it checks. */\nexport interface RuleInfo {\n readonly id: string;\n readonly severity: SeveritySetting;\n readonly description: string;\n}\n\nexport interface Rule extends RuleInfo {\n check(context: RuleContext): readonly RuleResult[] | Promise<readonly RuleResult[]>;\n}\n\nexport interface SharedAnalysis {\n readonly cycles: readonly (readonly Brief[])[];\n readonly duplicates: ReadonlyMap<string, readonly Brief[]>;\n}\n\nexport function analyse(corpus: Corpus): SharedAnalysis {\n return { cycles: dependencyCycles(corpus), duplicates: duplicateIds(corpus) };\n}\n\nconst at = (line0: number): number => line0 + 1;\n\n/** The sections a brief must carry: the configured ones, then its type's. */\nexport function sectionRules(brief: Brief, config: Config): SectionRule[] {\n const typed = brief.type === null ? [] : (config.types[brief.type] ?? []);\n return [...config.sections, ...typed];\n}\n\n/** The headings that fill a section rule. */\nexport function sectionsFilling(brief: Brief, rule: SectionRule): Section[] {\n const names = [rule.name, ...rule.aliases];\n return brief.sections.filter((s) => names.some((name) => labelMatches(s.heading.text, name)));\n}\n\n/** A section's own lines that carry content: comments dropped, sub-headings not counted. */\nfunction contentLines(brief: Brief, section: Section): number[] {\n const headingLines = new Set(brief.scan.headings.map((h) => h.line));\n const lines: number[] = [];\n for (let i = section.heading.line + 1; i < section.end; i += 1) {\n if (!headingLines.has(i) && hasContent(brief.scan.prose[i] as string)) lines.push(i);\n }\n return lines;\n}\n\nfunction isPlaceholder(line: string, placeholders: readonly string[]): boolean {\n const text = line\n .replace(/^\\s*(?:[-*+]|\\d{1,9}[.)])\\s+/, '')\n .replace(/^\\[[ xX]\\]\\s*/, '')\n .replace(/[*_]/g, '')\n .trim();\n if (text === '') return true;\n const lower = text.toLowerCase();\n return placeholders.some((p) => {\n const word = p.toLowerCase();\n return lower === word || (lower.startsWith(word) && /^[\\s:.\\-\\u2014]/.test(lower.slice(word.length)));\n });\n}\n\n/** Completeness findings on a draft are reminders, not failures. */\nfunction leniency(brief: Brief): Severity | undefined {\n return brief.status === 'draft' ? 'warning' : undefined;\n}\n\nfunction live(check: (context: RuleContext) => RuleResult[]): (context: RuleContext) => RuleResult[] {\n return (context) => (context.brief.phase === 'live' ? check(context) : []);\n}\n\nconst SCOPE_FIELDS = ['affectedFiles', 'protectedFiles'] as const;\n\nconst quoted = (items: readonly string[]): string => inWords(items.map((item) => `\"${item}\"`));\n\n/**\n * The paths a pattern names with no glob syntax that the tree does not hold\n * and whose names carry no extension. The tree reads each as a file, and the\n * spelling cannot say whether a directory was meant.\n */\nexport function unheldLiterals(glob: Glob, files: readonly string[]): string[] {\n const tree = treeOf(files);\n return glob.literals\n .map((literal) => literal.path)\n .filter((path) => held(tree, path) === null && !hasExtension(path.slice(path.lastIndexOf('/') + 1)));\n}\n\n/**\n * What to write for a directory where a pattern names paths the tree reads as\n * files, built from the pattern as written, as spec-core builds its own\n * advice: the pattern with a `/` ending each alternative that names one, since\n * a trailing `/` inside braces says directory as it does alone, or each such\n * alternative in an entry of its own (ADR-0005, amended 2026-09-29). Where\n * more of the pattern follows braces, `{a,b}/new`, no `/` written inside them\n * ends one alternative alone, so an entry of its own is the advice; and an\n * alternative the reader refuses as an entry, one opening with `!`, is left as\n * written. The reader trims every list item, so the pattern is as meant.\n */\nfunction directoryAdvice(pattern: string, paths: readonly string[]): string {\n const alternatives = writtenAlternatives(pattern) ?? [];\n const named = alternatives.filter(({ written }) => {\n const parsed = parseGlob(written);\n return parsed.ok && parsed.glob.literals.some((literal) => paths.includes(literal.path));\n });\n const entries = (named.length === 0 ? paths : named.map(({ written }) => written)).map((entry) => `${entry}/`);\n const one = entries.length === 1;\n const kind = one ? 'a directory' : 'directories';\n const own = one ? 'an entry of its own' : 'entries of their own';\n if (named.length === 0) return `write ${quoted(entries)} for ${kind}, in ${own}`;\n if (alternatives.length === 1) return `write ${quoted(entries)} for ${kind}`;\n let slashed = '';\n let from = 0;\n for (const { end } of named) {\n slashed += `${pattern.slice(from, end)}/`;\n from = end;\n }\n return `write \"${slashed}${pattern.slice(from)}\" for ${kind}, or ${quoted(entries)} in ${own}`;\n}\n\n/**\n * Affected patterns a brief's own protections cover entirely: one error for\n * all of them, and a warning for those the search could not decide.\n */\nexport function scopeContradiction(brief: Brief, repoFiles: readonly string[] | null, budget: number = WITNESS_BUDGET): RuleResult[] {\n const { covered, undecided } = contradictions(scopeOf(brief, readingIn(repoFiles)), budget);\n const line = at(lineOfField(brief, 'protectedFiles'));\n const results: RuleResult[] = [];\n if (covered.length > 0) {\n const one = covered.length === 1;\n results.push({\n line,\n message: `${quoted(covered)} in affectedFiles ${one ? 'is' : 'are'} entirely protected, so nothing of ${one ? 'it' : 'them'} is writable`,\n hint: `drop ${one ? 'it' : 'them'} from affectedFiles, or narrow protectedFiles so that some of ${one ? 'it' : 'each'} is writable`,\n });\n }\n if (undecided.length > 0) {\n results.push({\n line,\n message: `whether ${quoted(undecided)} in affectedFiles ${undecided.length === 1 ? 'is' : 'are'} entirely protected is undecided: the search met its budget`,\n hint: 'simplify the patterns until the question can be answered',\n severity: 'warning',\n });\n }\n return results;\n}\n\nexport const RULES: readonly Rule[] = [\n {\n id: 'front-matter',\n severity: 'error',\n description: 'Front matter parses, with no duplicate keys and no YAML beyond the supported subset.',\n check: ({ brief }) =>\n (brief.frontMatter?.problems ?? []).map((p) => ({\n line: at(p.line),\n message: p.message,\n hint: 'front matter is flat \"key: value\" lines, with lists as [a, b] or \"- item\" lines',\n })),\n },\n {\n id: 'field',\n severity: 'error',\n description: 'Fields spec-brief reads hold values of the right shape.',\n check: ({ brief }) => brief.problems.map((p) => ({ line: at(p.line), message: p.message })),\n },\n {\n id: 'unknown-field',\n severity: 'warning',\n description: 'Front-matter keys are ones spec-brief or the configuration knows.',\n check: ({ brief, config }) => {\n const known = knownFields(config);\n return (brief.frontMatter?.entries ?? [])\n .filter((entry) => !known.has(entry.name))\n .map((entry) => {\n const guess = closest(entry.key, BUILT_IN_FIELDS);\n return {\n line: at(entry.line),\n message: `\"${entry.key}\" is not a key spec-brief knows`,\n hint:\n guess === undefined\n ? `if the repository uses it, list it under \"fields\" in the configuration`\n : `did you mean \"${guess}\"? If not, list \"${entry.key}\" under \"fields\" in the configuration`,\n };\n });\n },\n },\n {\n id: 'status',\n severity: 'error',\n description: 'The status agrees with where the brief lives.',\n check: ({ brief, config }) => {\n const field = config.status.field;\n if (field === null) return [];\n const line = at(lineOfField(brief, field));\n const expected = brief.phase === 'archived' ? config.status.archived : config.status.active;\n if (brief.statusWord === null) {\n return [\n {\n line,\n message: `declares no \"${field}\"`,\n hint: `add \"${field}: ${expected}\" to the front matter`,\n },\n ];\n }\n if (brief.status === null) {\n const words = statusWords(config);\n return [\n {\n line,\n message: `\"${brief.statusWord}\" is not a status here`,\n hint: `use one of ${words.map((w) => `\"${w}\"`).join(', ')}`,\n },\n ];\n }\n if (brief.phase === 'live' && brief.status === 'archived') {\n return [\n {\n line,\n message: `is marked \"${brief.statusWord}\" but lives in ${config.briefs}/`,\n hint: `run \"spec-brief archive ${brief.id ?? brief.name}\", which moves it and writes its banner`,\n },\n ];\n }\n if (brief.phase === 'archived' && brief.status !== 'archived') {\n return [\n {\n line,\n message: `lives in ${config.archive}/ but is marked \"${brief.statusWord}\"`,\n hint: `run \"spec-brief unarchive ${brief.id ?? brief.name}\" to reopen it, or set \"${field}: ${config.status.archived}\"`,\n },\n ];\n }\n return [];\n },\n },\n {\n id: 'id',\n severity: 'error',\n description: 'Every brief has an id with no whitespace or slashes in it.',\n check: ({ brief, config }) => {\n if (brief.id === null) {\n return [\n {\n line: 1,\n message: config.id.source === 'frontmatter' ? 'declares no \"id\"' : 'has no id in its file name',\n hint: config.id.source === 'frontmatter' ? 'add \"id: <id>\" to the front matter' : undefined,\n },\n ];\n }\n if (/[\\s/\\\\]/.test(brief.id)) return [{ line: 1, message: `the id \"${brief.id}\" contains whitespace or a slash` }];\n return [];\n },\n },\n {\n id: 'duplicate-id',\n severity: 'error',\n description: 'No two briefs share an id, live or archived.',\n check: ({ brief, shared }) => {\n if (brief.id === null) return [];\n const group = shared.duplicates.get(idKey(brief.id));\n if (group === undefined || group[0] === brief) return [];\n return [\n {\n line: 1,\n message: `the id \"${brief.id}\" is also ${(group[0] as Brief).file}'s`,\n hint: 'ids are allocated once and never reused; give this brief the next free one',\n },\n ];\n },\n },\n {\n id: 'title',\n severity: 'warning',\n description: 'A brief has a title: a \"title\" field or a level-one heading.',\n check: live(({ brief }) =>\n brief.title === null ? [{ line: at(brief.bodyStart), message: 'has no title', hint: 'start the body with \"# <title>\"' }] : [],\n ),\n },\n {\n id: 'unknown-type',\n severity: 'error',\n description: 'A declared type is one the configuration defines.',\n check: live(({ brief, config }) => {\n if (brief.type === null || config.types[brief.type] !== undefined) return [];\n const names = Object.keys(config.types);\n return [\n {\n line: at(lineOfField(brief, 'type')),\n message: `\"${brief.type}\" is not a brief type here`,\n hint: names.length === 0 ? 'the configuration defines no types' : `use one of ${names.map((n) => `\"${n}\"`).join(', ')}`,\n },\n ];\n }),\n },\n {\n id: 'missing-section',\n severity: 'error',\n description: 'Every required section is present.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config)\n .filter((rule) => !rule.optional && sectionsFilling(brief, rule).length === 0)\n .map((rule) => {\n const heading =\n rule.aliases.length === 0\n ? `add a \"## ${rule.name}\" heading`\n : `add a \"## ${rule.name}\" heading (also accepted: ${rule.aliases.map((a) => `\"${a}\"`).join(', ')})`;\n return {\n line: at(brief.bodyStart),\n message: `has no \"${rule.name}\" section`,\n hint: rule.hint === undefined ? heading : `${heading}. ${rule.hint}`,\n };\n }),\n ),\n },\n {\n id: 'duplicate-section',\n severity: 'warning',\n description: 'A section appears once.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(1)\n .map((s) => ({ line: at(s.heading.line), message: `a second \"${rule.name}\" section`, hint: 'merge the two' })),\n ),\n ),\n },\n {\n id: 'empty-section',\n severity: 'error',\n description: 'A section carries content; a comment alone is not content.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(0, 1)\n .filter((s) => contentLines(brief, s).length === 0)\n .map((s) => ({\n line: at(s.heading.line),\n message: `the \"${rule.name}\" section is empty`,\n hint: rule.hint ?? 'write it; a comment alone is not content',\n severity: leniency(brief),\n })),\n ),\n ),\n },\n {\n id: 'placeholder',\n severity: 'error',\n description: 'A section says something: not only \"TBD\", \"TODO\" or an empty box.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(0, 1)\n .filter((s) => {\n const lines = contentLines(brief, s);\n return lines.length > 0 && lines.every((i) => isPlaceholder(brief.scan.prose[i] as string, config.placeholders));\n })\n .map((s) => ({\n line: at(s.heading.line),\n message: `the \"${rule.name}\" section holds only a placeholder`,\n hint: rule.hint ?? 'replace the placeholder with what the section must say',\n severity: leniency(brief),\n })),\n ),\n ),\n },\n {\n id: 'missing-checklist',\n severity: 'error',\n description: 'A checklist section holds at least one task item.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config)\n .filter((rule) => rule.checklist)\n .flatMap((rule) =>\n sectionsFilling(brief, rule)\n .slice(0, 1)\n .filter((s) => !brief.tasks.some((t) => t.line > s.heading.line && t.line < s.end))\n .map((s) => ({\n line: at(s.heading.line),\n message: `the \"${rule.name}\" section has no \"- [ ]\" items`,\n hint: 'write each check as a task item, so it has a state that can be closed',\n severity: leniency(brief),\n })),\n ),\n ),\n },\n {\n id: 'must-contain',\n severity: 'error',\n description: 'A section contains the text the configuration requires of it.',\n check: live(({ brief, config }) =>\n sectionRules(brief, config).flatMap((rule) => {\n const section = sectionsFilling(brief, rule)[0];\n if (section === undefined) return [];\n const body = brief.scan.prose.slice(section.heading.line + 1, section.end).join('\\n');\n return rule.mustContain\n .filter((text) => !body.includes(text))\n .map((text) => ({ line: at(section.heading.line), message: `the \"${rule.name}\" section must contain \"${text}\"` }));\n }),\n ),\n },\n {\n id: 'section-order',\n severity: 'error',\n description: 'Sections appear in the configured order, when the configuration asks for one.',\n check: live(({ brief, config }) => {\n if (!config.sectionOrder) return [];\n const placed = sectionRules(brief, config)\n .map((rule) => ({ rule, section: sectionsFilling(brief, rule)[0] }))\n .filter((p): p is { rule: SectionRule; section: Section } => p.section !== undefined);\n for (let i = 1; i < placed.length; i += 1) {\n const before = placed[i - 1] as { rule: SectionRule; section: Section };\n const current = placed[i] as { rule: SectionRule; section: Section };\n if (current.section.heading.line < before.section.heading.line) {\n return [\n {\n line: at(current.section.heading.line),\n message: `\"${current.rule.name}\" comes before \"${before.rule.name}\"`,\n hint: `the order is ${sectionRules(brief, config)\n .map((r) => r.name)\n .join(', ')}`,\n },\n ];\n }\n }\n return [];\n }),\n },\n {\n id: 'dependency',\n severity: 'error',\n description: 'Every dependency names another brief that exists.',\n check: live(({ brief, corpus }) =>\n brief.dependsOn.flatMap((dependency) => {\n const line = at(lineOfField(brief, 'dependsOn'));\n if (brief.id !== null && idKey(dependency) === idKey(brief.id)) {\n return [{ line, message: 'depends on itself' }];\n }\n if (resolveDependency(corpus, dependency) === undefined) {\n return [{ line, message: `depends on \"${dependency}\", which is not a brief here` }];\n }\n return [];\n }),\n ),\n },\n {\n id: 'dependency-cycle',\n severity: 'error',\n description: 'Dependencies between live briefs form no cycle.',\n check: live(({ brief, shared }) =>\n shared.cycles\n .filter((cycle) => cycle[0] === brief)\n .map((cycle) => ({\n line: at(lineOfField(brief, 'dependsOn')),\n message: `dependencies form a cycle: ${cycle.map((b) => b.id ?? b.name).join(' -> ')}`,\n hint: 'a cycle can never become ready; remove the dependency that is not real',\n })),\n ),\n },\n {\n id: 'wave-order',\n severity: 'error',\n description: 'A dependency that is still live runs in an earlier wave.',\n check: live(({ brief, corpus }) => {\n const wave = brief.wave;\n if (wave === null) return [];\n return brief.dependsOn.flatMap((dependency) => {\n const target = resolveDependency(corpus, dependency);\n // A self-dependency is reported once, by the dependency rule.\n if (target === undefined || target === brief || target.phase !== 'live' || target.wave === null || target.wave < wave) return [];\n return [\n {\n line: at(lineOfField(brief, 'dependsOn')),\n message: `depends on ${target.id ?? target.name}, which is in wave ${target.wave}, not before wave ${wave}`,\n hint: `move this brief to a wave after ${target.wave}, or ${target.id ?? target.name} to one before ${wave}`,\n },\n ];\n });\n }),\n },\n {\n id: 'deferral-trigger',\n severity: 'error',\n description: 'A deferred brief names in \"trigger\" the observable event that brings it back, not a date.',\n check: live(({ brief, config }) => {\n // A trigger of the wrong shape is the field rule's finding.\n if (brief.status !== 'deferred' || brief.problems.some((p) => p.field === 'trigger')) return [];\n const example = 'such as \"when the second tenant signs\" or \"when p95 exceeds 200 ms\"';\n const trigger = brief.trigger?.trim() ?? '';\n if (trigger === '') {\n const declared = findEntry(brief.frontMatter, 'trigger') !== undefined;\n return [\n {\n line: at(lineOfField(brief, declared ? 'trigger' : (config.status.field as string))),\n message: 'is deferred and names no \"trigger\"',\n hint: `add \"trigger: <the event that brings it back>\", ${example}`,\n },\n ];\n }\n const line = at(lineOfField(brief, 'trigger'));\n const hint = `name what must happen before the work resumes, ${example}`;\n if (config.placeholders.some((p) => p.toLowerCase() === trigger.toLowerCase())) {\n return [{ line, message: `the trigger \"${trigger}\" is a placeholder, not an event`, hint }];\n }\n if (!namesAnEvent(trigger)) {\n return [{ line, message: `the trigger \"${trigger}\" is a date or a time, not an event`, hint: `${hint}; a date arrives whether or not the reason for the work has` }];\n }\n return [];\n }),\n },\n {\n id: 'glob',\n severity: 'error',\n description: 'Every scope pattern is a glob spec-brief can read.',\n check: live(({ brief }) =>\n SCOPE_FIELDS.flatMap((field) =>\n brief[field].flatMap((pattern) => {\n const parsed = parseGlob(pattern);\n if (parsed.ok) return [];\n return [\n {\n line: at(lineOfField(brief, field)),\n message: `\"${pattern}\" in ${field}: ${parsed.error}`,\n hint: 'a scope is a glob relative to the repository root: \"src/auth/\", \"src/**/*.ts\", \"docs/{a,b}.md\"',\n },\n ];\n }),\n ),\n ),\n },\n {\n id: 'scope-contradiction',\n severity: 'error',\n description: 'Something of every affected pattern is writable: no pattern lies wholly inside protectedFiles.',\n check: live(({ brief, repoFiles }) => scopeContradiction(brief, repoFiles)),\n },\n {\n id: 'glob-matches-nothing',\n severity: 'note',\n description: 'A scope pattern matches at least one file in the tree.',\n check: live(({ brief, repoFiles }) => {\n if (repoFiles === null) return [];\n const reading = readingIn(repoFiles);\n return SCOPE_FIELDS.flatMap((field) =>\n patternsOf(brief[field], reading)\n // A literal the tree does not hold is literal-read-as-file's finding.\n .filter((p) => unheldLiterals(p.glob, repoFiles).length === 0 && !repoFiles.some((file) => matchGlob(p.glob, file)))\n .map((p) => ({\n line: at(lineOfField(brief, field)),\n message: `\"${p.pattern}\" in ${field} matches no file in the tree`,\n hint: 'expected when the round creates it; otherwise check the spelling',\n })),\n );\n }),\n },\n {\n id: 'literal-read-as-file',\n severity: 'note',\n description: 'A path with no glob syntax that the tree does not hold, and whose name has no extension, says whether it is a directory.',\n check: live(({ brief, repoFiles }) => {\n if (repoFiles === null) return [];\n const reading = readingIn(repoFiles);\n return SCOPE_FIELDS.flatMap((field) =>\n patternsOf(brief[field], reading).flatMap(({ pattern, glob }: ScopePattern) => {\n const paths = unheldLiterals(glob, repoFiles);\n if (paths.length === 0) return [];\n const line = at(lineOfField(brief, field));\n const hint = directoryAdvice(pattern, paths);\n if (!isGlobSyntax(pattern)) {\n return [{ line, message: `\"${pattern}\" in ${field} is not in the tree and is read as a file`, hint }];\n }\n return [\n {\n line,\n message: `\"${pattern}\" in ${field} names ${inWords(paths)}, which ${paths.length === 1 ? 'is' : 'are'} not in the tree and ${paths.length === 1 ? 'is' : 'are'} read as ${paths.length === 1 ? 'a file' : 'files'}`,\n hint,\n },\n ];\n }),\n );\n }),\n },\n {\n id: 'archive-freeze',\n severity: 'error',\n description: 'An archived brief has not changed since it was archived.',\n check: ({ brief }) => {\n if (brief.phase !== 'archived' || brief.integrity === null) return [];\n if (integrityOf(brief.text) === brief.integrity) return [];\n return [\n {\n line: at(lineOfField(brief, 'integrity')),\n message: 'has changed since it was archived',\n hint: 'an archived brief is frozen: restore it from git, or unarchive it to reopen the round',\n },\n ];\n },\n },\n];\n\n/**\n * The rules the wave analyses - `matrix` and `schedule` - report under. They\n * are not run per brief, so they carry no check: they exist so configuration\n * can set their severity and reports can describe them.\n */\nexport const COLLISION_RULES: readonly RuleInfo[] = [\n { id: 'collision', severity: 'error', description: 'Briefs in one wave do not write the same file.' },\n {\n id: 'collision-undecided',\n severity: 'warning',\n description: 'Whether two briefs in one wave can write the same file is decided within the search budget.',\n },\n { id: 'unscoped', severity: 'note', description: 'A brief sharing a wave declares the files it writes.' },\n { id: 'shared-directory', severity: 'off', description: 'Briefs in one wave do not write into the same directory.' },\n {\n id: 'wave-schedule',\n severity: 'error',\n description: 'A brief declares a wave that holds: the one the schedule computes, or one lint and matrix accept, which is a note.',\n },\n];\n\n/**\n * The rules archival reports under beside its refusals. Like the collision\n * rules they carry no check: the planner raises them, and they exist so\n * configuration can set their severity and reports can describe them.\n */\nexport const ARCHIVE_RULES: readonly RuleInfo[] = [\n {\n id: 'scope-unmeasured',\n severity: 'warning',\n description: 'A brief that declares a scope is archived against the changes its round made.',\n },\n {\n id: 'stale-link',\n severity: 'warning',\n description: 'No live brief is left linking to where a moved brief used to be.',\n },\n];\n"]}
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
* - Braces expand first, and each alternative reads as it would written on
|
|
30
30
|
* its own: `{src/,lib}` is `src/` or `lib`, and a trailing `/` means the
|
|
31
31
|
* directory's contents - in an exclusion, the directory and its contents.
|
|
32
|
+
* `{/docs,lib}` is `/docs` or `lib`, the leading `/` rooting or anchoring
|
|
33
|
+
* that alternative as it would the pattern. One that names no path,
|
|
34
|
+
* `{./,lib}` or `{,lib}`, is refused, as `./` and the empty pattern are.
|
|
32
35
|
* - Case is the caller's decision, stated every time. A result must not
|
|
33
36
|
* depend on the host it ran on.
|
|
34
37
|
* - A malformed pattern is an error, never a literal. An unclosed `[` or `{`,
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
* - Braces expand first, and each alternative reads as it would written on
|
|
30
30
|
* its own: `{src/,lib}` is `src/` or `lib`, and a trailing `/` means the
|
|
31
31
|
* directory's contents - in an exclusion, the directory and its contents.
|
|
32
|
+
* `{/docs,lib}` is `/docs` or `lib`, the leading `/` rooting or anchoring
|
|
33
|
+
* that alternative as it would the pattern. One that names no path,
|
|
34
|
+
* `{./,lib}` or `{,lib}`, is refused, as `./` and the empty pattern are.
|
|
32
35
|
* - Case is the caller's decision, stated every time. A result must not
|
|
33
36
|
* depend on the host it ran on.
|
|
34
37
|
* - A malformed pattern is an error, never a literal. An unclosed `[` or `{`,
|
|
@@ -84,32 +87,35 @@ function build(source, options) {
|
|
|
84
87
|
return 'a negated pattern is a list entry, not a glob; narrow the positive pattern';
|
|
85
88
|
if (/(?:^|[^\\])[?*+@!]\([^)]*\|/.test(pattern))
|
|
86
89
|
return EXTGLOB;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
let anchored = false;
|
|
93
|
-
if (pattern.startsWith('/')) {
|
|
94
|
-
if (options.dialect === 'gitignore')
|
|
95
|
-
anchored = true;
|
|
96
|
-
else
|
|
97
|
-
rooted = true;
|
|
98
|
-
pattern = pattern.replace(/^\/+/, '');
|
|
99
|
-
}
|
|
100
|
-
if (pattern.length === 0)
|
|
90
|
+
// The pattern's own leading slash is taken off before the braces expand, so
|
|
91
|
+
// that the root itself, and a text the braces give, are refused in the
|
|
92
|
+
// words they always were: `/{./,a}` is told `./`.
|
|
93
|
+
const whole = unrooted(pattern);
|
|
94
|
+
if (whole.text.length === 0)
|
|
101
95
|
return 'the pattern names the root itself, not a path under it';
|
|
102
|
-
const expanded = expandBraces(
|
|
96
|
+
const expanded = expandBraces(whole.text, escapes);
|
|
103
97
|
if (typeof expanded === 'string')
|
|
104
98
|
return expanded;
|
|
105
99
|
const alternatives = [];
|
|
106
100
|
for (const text of expanded) {
|
|
107
|
-
|
|
101
|
+
// Refused before its trailing slash is read, which would make `./` the
|
|
102
|
+
// contents of `.`, every path: `{./,a}` is refused as `./` alone is.
|
|
103
|
+
// Each text the braces give is shorter than the pattern, so only a
|
|
104
|
+
// pattern without braces is its own text.
|
|
105
|
+
if (namesNoPath(text))
|
|
106
|
+
return text === whole.text ? 'the pattern names no path' : bracesNamingNoPath(text);
|
|
107
|
+
// Its leading slash is read as the pattern's is, since braces expand
|
|
108
|
+
// before anything else is decided: `{/docs,x}` is `/docs` or `x`. Left to
|
|
109
|
+
// `parseAlternative`, the slash would be an empty segment, dropped, and
|
|
110
|
+
// `/docs` would read as `docs`. A slash after a segment, as in
|
|
111
|
+
// `a/{/b,c}`, starts no text, and is the empty segment of `a//b`.
|
|
112
|
+
const alone = unrooted(text);
|
|
113
|
+
const parsed = parseAlternative(trailingSlash(alone.text, options.dialect), escapes);
|
|
108
114
|
if (parsed === GLOBSTAR_IN_NAME)
|
|
109
115
|
return `${GLOBSTAR_IN_NAME}: ${globstarAdvice(written)}`;
|
|
110
116
|
if (typeof parsed === 'string')
|
|
111
117
|
return parsed;
|
|
112
|
-
alternatives.push(parsed);
|
|
118
|
+
alternatives.push({ ...parsed, rooted: whole.rooted || alone.rooted });
|
|
113
119
|
}
|
|
114
120
|
const builder = new Builder();
|
|
115
121
|
const fragments = [];
|
|
@@ -117,7 +123,7 @@ function build(source, options) {
|
|
|
117
123
|
let automaton;
|
|
118
124
|
try {
|
|
119
125
|
for (const alternative of alternatives) {
|
|
120
|
-
const compiled = compileAlternative(builder, alternative, options
|
|
126
|
+
const compiled = compileAlternative(builder, alternative, options);
|
|
121
127
|
fragments.push(compiled.fragment);
|
|
122
128
|
bases.push(compiled.base);
|
|
123
129
|
}
|
|
@@ -253,6 +259,31 @@ function classEnd(pattern, open, escapes) {
|
|
|
253
259
|
return -1;
|
|
254
260
|
}
|
|
255
261
|
/* ---------------------------------------------------------------- segments */
|
|
262
|
+
/**
|
|
263
|
+
* A pattern, or a text its braces give, without the `./` and the slashes it
|
|
264
|
+
* starts with, and whether a slash led it once the `./` was gone. What a
|
|
265
|
+
* leading slash means is the dialect's: it roots a pattern at the
|
|
266
|
+
* filesystem's root in `path` and `ripgrep`, and only anchors it at the
|
|
267
|
+
* repository root in `gitignore`, as git reads one. `.//docs` is led by one,
|
|
268
|
+
* as `/docs` is.
|
|
269
|
+
*/
|
|
270
|
+
function unrooted(text) {
|
|
271
|
+
let rest = text;
|
|
272
|
+
while (rest.startsWith('./'))
|
|
273
|
+
rest = rest.slice(2);
|
|
274
|
+
return { text: rest.replace(/^\/+/, ''), rooted: rest.startsWith('/') };
|
|
275
|
+
}
|
|
276
|
+
/** Whether a pattern's text names no path: nothing in it but `/` and `.` segments. */
|
|
277
|
+
function namesNoPath(text) {
|
|
278
|
+
return text.split('/').every((part) => part === '' || part === '.');
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The refusal of an alternative the braces give that names no path, naming
|
|
282
|
+
* it as it was expanded, so that `.{/,a}` is told `./`, the text refused.
|
|
283
|
+
*/
|
|
284
|
+
function bracesNamingNoPath(text) {
|
|
285
|
+
return text === '' ? 'the braces expand to an empty pattern' : `the braces expand to "${text}", which names no path`;
|
|
286
|
+
}
|
|
256
287
|
/**
|
|
257
288
|
* What a trailing slash means, read on each alternative the braces give, so
|
|
258
289
|
* that `{src/,lib}` reads `src/` as `src/` alone reads: the directory's
|
|
@@ -261,17 +292,21 @@ function classEnd(pattern, open, escapes) {
|
|
|
261
292
|
* In an exclusion `build/` excludes what `build` does. Git's rule is that a
|
|
262
293
|
* trailing slash matches only a directory, and a directory is excluded with
|
|
263
294
|
* everything in it; a matcher that sees only a path cannot tell a directory
|
|
264
|
-
* from a file, so the slash is dropped, and it anchors nothing.
|
|
265
|
-
* alternative that is only slashes names the root, which `parseAlternative`
|
|
266
|
-
* refuses as naming no path.
|
|
295
|
+
* from a file, so the slash is dropped, and it anchors nothing.
|
|
267
296
|
*
|
|
268
|
-
*
|
|
269
|
-
* is
|
|
297
|
+
* Only ever given a text that names a path, so a name is left. The whole run
|
|
298
|
+
* of slashes is taken, but one slash would read the same, since
|
|
299
|
+
* `parseAlternative` drops the empty segments the rest leave; and taken
|
|
300
|
+
* lazily it is the whole run all the same, since it ends the text.
|
|
270
301
|
*/
|
|
271
302
|
function trailingSlash(text, dialect) {
|
|
272
303
|
const name = text.replace(/\/+$/, '');
|
|
273
|
-
return name === text ||
|
|
304
|
+
return name === text || dialect === 'gitignore' ? name : `${name}/**`;
|
|
274
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* The segments of a text that names a path - `build` refuses one that does
|
|
308
|
+
* not - so at least one segment is left.
|
|
309
|
+
*/
|
|
275
310
|
function parseAlternative(text, escapes) {
|
|
276
311
|
const segments = [];
|
|
277
312
|
const raw = text.split('/');
|
|
@@ -290,8 +325,6 @@ function parseAlternative(text, escapes) {
|
|
|
290
325
|
return tokens;
|
|
291
326
|
segments.push({ kind: 'name', tokens });
|
|
292
327
|
}
|
|
293
|
-
if (segments.length === 0)
|
|
294
|
-
return 'the pattern names no path';
|
|
295
328
|
return { segments, slashed: raw.filter((part) => part !== '' && part !== '.').length > 1 };
|
|
296
329
|
}
|
|
297
330
|
const EXTGLOB = 'extended globs such as "+(a|b)" are not supported: write alternatives as "{a,b}", and a literal parenthesis as "[(]"';
|
|
@@ -483,14 +516,14 @@ function segmentsFragment(b, segments) {
|
|
|
483
516
|
});
|
|
484
517
|
return b.sequence(parts);
|
|
485
518
|
}
|
|
486
|
-
function compileAlternative(b, alternative, options
|
|
487
|
-
const { segments } = alternative;
|
|
519
|
+
function compileAlternative(b, alternative, options) {
|
|
520
|
+
const { segments, rooted } = alternative;
|
|
488
521
|
const body = segmentsFragment(b, segments);
|
|
489
522
|
const root = rooted ? '/' : '';
|
|
490
523
|
const literal = literalText(segments);
|
|
491
524
|
const leading = leadingLiteral(segments);
|
|
492
525
|
if (options.dialect === 'gitignore') {
|
|
493
|
-
const floating = !
|
|
526
|
+
const floating = !rooted && !alternative.slashed;
|
|
494
527
|
const parts = [body, b.optional(beneath(b))];
|
|
495
528
|
if (floating)
|
|
496
529
|
parts.unshift(anyDirectories(b));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/pattern/glob.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Globs, in the three dialects the spec-* tools speak, compiled to one kind of\n * automaton.\n *\n * The syntax is the part people type: `*`, `**`, `?`, `[abc]`, `[!a-z]`,\n * `{a,b}`, and `\\` to escape. What differs between the tools is not the\n * syntax but what a pattern is matched against, and those differences are\n * deliberate, so each has a name (docs/adr/0003-glob-dialects.md):\n *\n * - `path` - the whole repository-relative path, anchored at the root. A\n * pattern with no glob syntax names a file, a directory, or either, as the\n * caller says; `src/auth` may cover `src/auth/login.ts`.\n * - `ripgrep` - as ripgrep's `-g`: a pattern with no `/` is matched against\n * the last segment at any depth, so `*.ts` matches `src/deep/a.ts`; one with\n * a `/` is matched against the whole path.\n * - `gitignore` - as an exclusion list reads: a pattern matches a path or any\n * directory above it, so `tests` excludes everything under any `tests`; one\n * with a `/` other than a trailing one is anchored at the root, and a\n * leading `/` only anchors.\n *\n * Shared by all three:\n *\n * - `**` is a globstar only as a whole segment. `a/**\\/b` matches `a/b` and\n * `a/x/y/b`; a trailing `/**` matches everything inside a directory and not\n * the directory itself. Two stars inside a name, `**.md`, are refused: the\n * tools read it three ways, and the quiet reading narrowed their scope. The\n * refusal writes the two patterns it may have meant from the one written.\n * - `*`, `?` and classes never match `/`, and `*` matches a leading dot.\n * - Braces expand first, and each alternative reads as it would written on\n * its own: `{src/,lib}` is `src/` or `lib`, and a trailing `/` means the\n * directory's contents - in an exclusion, the directory and its contents.\n * - Case is the caller's decision, stated every time. A result must not\n * depend on the host it ran on.\n * - A malformed pattern is an error, never a literal. An unclosed `[` or `{`,\n * an extended glob, a `..` - each is refused with a reason, because a typo\n * read as a literal is a scope that silently matches nothing. An extended\n * glob is a group holding a `|`, `+(a|b)`: without one, `C++(notes).md` is\n * a name with parentheses in it, as ripgrep and `.gitignore` read it.\n */\n\nimport {\n AutomatonTooLarge,\n Builder,\n findWitness,\n Matcher,\n WITNESS_BUDGET,\n type Automaton,\n type Fragment,\n type Witness,\n} from './automaton.js';\nimport { ANY, classSet, literalSet, SEPARATOR, type CodeRange } from './charset.js';\n\nexport type GlobDialect = 'path' | 'ripgrep' | 'gitignore';\n\n/** How a `path` pattern with no glob syntax is read. */\nexport type LiteralReading = 'file' | 'directory' | 'either';\n\nexport interface GlobOptions {\n readonly dialect: GlobDialect;\n /** Whether `A` and `a` differ. No default: the caller decides, every time. */\n readonly caseSensitive: boolean;\n /**\n * `path` dialect only: how a pattern with no glob syntax is read - as a\n * file, as a directory and everything beneath it, or as either. A function\n * is asked per literal path, for a caller that knows the tree. `either` when\n * unset. A trailing `/`, on the pattern or on one of its brace alternatives,\n * always means a directory's contents, and is never asked about.\n */\n readonly literal?: LiteralReading | ((path: string) => LiteralReading) | undefined;\n /**\n * `escape` (the default): `\\` escapes the next character, and a `\\` before a\n * letter or digit is refused as a Windows separator typed by mistake.\n * `separator`: every `\\` is a `/`, for patterns typed on a Windows shell.\n */\n readonly backslash?: 'escape' | 'separator' | undefined;\n}\n\nexport interface Glob {\n readonly source: string;\n readonly dialect: GlobDialect;\n readonly caseSensitive: boolean;\n /**\n * The directories a walk must enter to find every match: one per\n * alternative, the leading literal segments. `''` for an alternative that\n * can match at any depth.\n */\n readonly bases: readonly string[];\n readonly automaton: Automaton;\n /** Whether a canonical path - POSIX, no `.`, no empty or trailing segment - matches. */\n match(path: string): boolean;\n}\n\nexport type GlobParse = { readonly ok: true; readonly glob: Glob } | { readonly ok: false; readonly error: string };\n\nexport class GlobError extends Error {\n readonly source: string;\n constructor(source: string, reason: string) {\n super(`invalid glob \"${source}\": ${reason}`);\n this.name = 'GlobError';\n this.source = source;\n }\n}\n\n/** More alternatives than this is a pattern nobody meant. */\nexport const MAX_ALTERNATIVES = 256;\n\ntype Token =\n | { readonly kind: 'literal'; readonly point: number }\n | { readonly kind: 'any' }\n | { readonly kind: 'star' }\n | { readonly kind: 'class'; readonly negated: boolean; readonly ranges: readonly CodeRange[] };\n\ntype Segment = { readonly kind: 'globstar' } | { readonly kind: 'name'; readonly tokens: readonly Token[] };\n\ninterface Alternative {\n readonly segments: readonly Segment[];\n /** Written with a `/` somewhere other than at its end. */\n readonly slashed: boolean;\n}\n\n/** Whether a string uses glob syntax at all. */\nexport function isGlobSyntax(source: string): boolean {\n return /[*?[\\]{}]/.test(source);\n}\n\n/**\n * Parses and compiles a glob, or says why it cannot: malformed, or too large\n * to compile, past {@link MAX_ALTERNATIVES} alternatives or `MAX_STATES`\n * states. It throws only what a `literal` function throws.\n */\nexport function parseGlob(source: string, options: GlobOptions): GlobParse {\n const result = build(source, options);\n return typeof result === 'string' ? { ok: false, error: result } : { ok: true, glob: result };\n}\n\n/**\n * Parses and compiles a glob, throwing {@link GlobError} for every reason\n * {@link parseGlob} gives, and what a `literal` function throws.\n */\nexport function compileGlob(source: string, options: GlobOptions): Glob {\n const result = build(source, options);\n if (typeof result === 'string') throw new GlobError(source, result);\n return result;\n}\n\nfunction build(source: string, options: GlobOptions): Glob | string {\n const escapes = options.backslash !== 'separator';\n let pattern = source.trim();\n if (!escapes) pattern = pattern.replace(/\\\\/g, '/');\n const written = pattern;\n if (pattern.length === 0) return 'the pattern is empty';\n if (pattern.startsWith('!')) return 'a negated pattern is a list entry, not a glob; narrow the positive pattern';\n if (/(?:^|[^\\\\])[?*+@!]\\([^)]*\\|/.test(pattern)) return EXTGLOB;\n while (pattern.startsWith('./')) pattern = pattern.slice(2);\n\n // A leading slash roots a pattern at the filesystem's root in the path and\n // ripgrep dialects, and only anchors it at the repository root in gitignore.\n let rooted = false;\n let anchored = false;\n if (pattern.startsWith('/')) {\n if (options.dialect === 'gitignore') anchored = true;\n else rooted = true;\n pattern = pattern.replace(/^\\/+/, '');\n }\n if (pattern.length === 0) return 'the pattern names the root itself, not a path under it';\n\n const expanded = expandBraces(pattern, escapes);\n if (typeof expanded === 'string') return expanded;\n\n const alternatives: Alternative[] = [];\n for (const text of expanded) {\n const parsed = parseAlternative(trailingSlash(text, options.dialect), escapes);\n if (parsed === GLOBSTAR_IN_NAME) return `${GLOBSTAR_IN_NAME}: ${globstarAdvice(written)}`;\n if (typeof parsed === 'string') return parsed;\n alternatives.push(parsed);\n }\n\n const builder = new Builder();\n const fragments: Fragment[] = [];\n const bases: string[] = [];\n let automaton: Automaton;\n try {\n for (const alternative of alternatives) {\n const compiled = compileAlternative(builder, alternative, options, rooted, anchored);\n fragments.push(compiled.fragment);\n bases.push(compiled.base);\n }\n automaton = builder.finish(builder.either(fragments), options.caseSensitive);\n } catch (error) {\n // A pattern too large to compile is refused with a reason, as a malformed\n // one is. Anything else - a caller's literal reading that throws - is the\n // caller's failure, not the pattern's, and goes on up.\n if (error instanceof AutomatonTooLarge) return error.message;\n throw error;\n }\n let matcher: Matcher | null = null;\n return {\n source,\n dialect: options.dialect,\n caseSensitive: options.caseSensitive,\n bases: [...new Set(bases)],\n automaton,\n match(path: string): boolean {\n matcher ??= new Matcher(automaton);\n return matcher.test(path);\n },\n };\n}\n\n/* ------------------------------------------------------------------ braces */\n\n/**\n * Expands `{a,b}` groups into the patterns they stand for, or says why the\n * pattern is malformed.\n *\n * Classes and escapes are skipped while looking for braces and commas, so\n * `{[,]x,y}` is two alternatives, `[,]x` and `y`. A lone `}` is a literal: it\n * cannot be read as anything else. An unclosed `{` is an error.\n *\n * Here and in the two functions after it, a loop that reads one step past\n * the end reads `''`, which none of them acts on, and `classEnd` answers -1\n * or an index past the `[`, so `close > 0` and `close >= 0` read the same.\n * `open` is set by the `{` that any `}` read here closes, so its first value\n * is never read.\n */\nfunction expandBraces(pattern: string, escapes: boolean): string[] | string {\n let depth = 0;\n let open = -1;\n for (let i = 0; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\' && escapes) {\n i += 1;\n continue;\n }\n if (ch === '[') {\n const close = classEnd(pattern, i, escapes);\n if (close > 0) i = close;\n continue;\n }\n if (ch === '{') {\n if (depth === 0) open = i;\n depth += 1;\n continue;\n }\n if (ch !== '}' || depth === 0) continue;\n depth -= 1;\n if (depth > 0) continue;\n const prefix = pattern.slice(0, open);\n const suffix = pattern.slice(i + 1);\n const results: string[] = [];\n for (const option of splitOptions(pattern.slice(open + 1, i), escapes)) {\n const expanded = expandBraces(`${prefix}${option}${suffix}`, escapes);\n if (typeof expanded === 'string') return expanded;\n results.push(...expanded);\n if (results.length > MAX_ALTERNATIVES) return `the braces expand to more than ${MAX_ALTERNATIVES} patterns`;\n }\n return results;\n }\n if (depth > 0) return 'a \"{\" is never closed';\n return [pattern];\n}\n\n/** Splits a brace body on its top-level commas. */\nfunction splitOptions(body: string, escapes: boolean): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < body.length; i += 1) {\n const ch = body.charAt(i);\n if (ch === '\\\\' && escapes) {\n i += 1;\n } else if (ch === '[') {\n const close = classEnd(body, i, escapes);\n if (close > 0) i = close;\n } else if (ch === '{') {\n depth += 1;\n } else if (ch === '}') {\n depth -= 1;\n } else if (ch === ',' && depth === 0) {\n parts.push(body.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(body.slice(start));\n return parts;\n}\n\n/** The index of the `]` closing a class opened at `open`, or -1 when none does within the segment. */\nfunction classEnd(pattern: string, open: number, escapes: boolean): number {\n let i = open + 1;\n if (pattern.charAt(i) === '!' || pattern.charAt(i) === '^') i += 1;\n // The first member is always a member, even `]`.\n if (pattern.charAt(i) === ']') i += 1;\n for (; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\' && escapes) {\n i += 1;\n continue;\n }\n if (ch === '/') return -1;\n if (ch === ']') return i;\n }\n return -1;\n}\n\n/* ---------------------------------------------------------------- segments */\n\n/**\n * What a trailing slash means, read on each alternative the braces give, so\n * that `{src/,lib}` reads `src/` as `src/` alone reads: the directory's\n * contents, `src/**`, and not a literal that may be the directory itself.\n *\n * In an exclusion `build/` excludes what `build` does. Git's rule is that a\n * trailing slash matches only a directory, and a directory is excluded with\n * everything in it; a matcher that sees only a path cannot tell a directory\n * from a file, so the slash is dropped, and it anchors nothing. An\n * alternative that is only slashes names the root, which `parseAlternative`\n * refuses as naming no path.\n *\n * The whole run of slashes is taken, so that `{//,a}` is refused as `{/,a}`\n * is; taken lazily it is the whole run all the same, since it ends the text.\n */\nfunction trailingSlash(text: string, dialect: GlobDialect): string {\n const name = text.replace(/\\/+$/, '');\n return name === text || name === '' || dialect === 'gitignore' ? name : `${name}/**`;\n}\n\nfunction parseAlternative(text: string, escapes: boolean): Alternative | string {\n const segments: Segment[] = [];\n const raw = text.split('/');\n for (const part of raw) {\n if (part === '' || part === '.') continue;\n if (part === '..') return 'a pattern cannot climb out of its root with \"..\"';\n if (part === '**') {\n if (segments[segments.length - 1]?.kind !== 'globstar') segments.push({ kind: 'globstar' });\n continue;\n }\n const tokens = tokenize(part, escapes);\n if (typeof tokens === 'string') return tokens;\n segments.push({ kind: 'name', tokens });\n }\n if (segments.length === 0) return 'the pattern names no path';\n return { segments, slashed: raw.filter((part) => part !== '' && part !== '.').length > 1 };\n}\n\nconst EXTGLOB = 'extended globs such as \"+(a|b)\" are not supported: write alternatives as \"{a,b}\", and a literal parenthesis as \"[(]\"';\nconst GLOBSTAR_IN_NAME = '\"**\" means any number of directories only as a whole segment';\n\n/**\n * The two patterns a writer of `**` inside a name may have meant, built from\n * what they wrote. Each run of stars that is not a whole segment becomes, for\n * any depth, a globstar segment with a star kept on each side where a name\n * went on - `docs/**.md` to `docs/**\\/*.md`, `src/a**` to `src/a*\\/**`,\n * `a**b` to `a*\\/**\\/*b` - and for one level a single star. Everything else\n * stays as written, braces and classes included, and a globstar that was a\n * whole segment stays one.\n *\n * Only `/` is taken for a boundary. A run beside a brace, `{**.md,x}`, is\n * given a star on that side too, which keeps the advice a pattern that\n * compiles whatever the braces expand to.\n *\n * `written` holds a `\\` only where it escapes: in the `separator` reading\n * each one is already a `/`.\n */\nfunction globstarAdvice(written: string): string {\n let deep = '';\n let flat = '';\n let at = 0;\n // One step past the end reads `''` and appends nothing, so the bound could\n // be one further and give the same advice.\n while (at < written.length) {\n const ch = written.charAt(at);\n let next = at + 1;\n if (ch === '\\\\') {\n next = at + 2;\n } else if (ch === '[') {\n // A class is copied as written. `classEnd` answers an index past the\n // `[`, or -1 for one never closed, so `close >= 0` reads the same; and\n // stopping one short of the `]` copies the class all the same, since\n // its last member and the `]` after it are never a run of stars.\n const close = classEnd(written, at, true);\n if (close > 0) next = close + 1;\n } else if (ch === '*') {\n while (written.charAt(next) === '*') next += 1;\n const before = at > 0 && written.charAt(at - 1) !== '/';\n const after = next < written.length && written.charAt(next) !== '/';\n if (next - at > 2 || (next - at === 2 && (before || after))) {\n deep += `${before ? '*/' : ''}**${after ? '/*' : ''}`;\n flat += '*';\n at = next;\n continue;\n }\n }\n deep += written.slice(at, next);\n flat += written.slice(at, next);\n at = next;\n }\n return `write \"${deep}\" for any depth, or \"${flat}\" for one level`;\n}\n\nfunction tokenize(segment: string, escapes: boolean): Token[] | string {\n const tokens: Token[] = [];\n const chars = Array.from(segment);\n for (let i = 0; i < chars.length; i += 1) {\n const ch = chars[i] as string;\n if (ch === '\\\\' && escapes) {\n const next = chars[i + 1];\n if (next === undefined || /[A-Za-z0-9]/.test(next)) {\n return '\"\\\\\" escapes glob syntax; separate directories with \"/\"';\n }\n tokens.push({ kind: 'literal', point: next.codePointAt(0) as number });\n i += 1;\n } else if (ch === '*') {\n // Two stars inside a name are refused rather than read as one. The\n // tools this replaces read `docs/**.md` three ways - recursive, one\n // level, and as ripgrep does - and reading it as one level silently\n // dropped every nested document from a run that used to include them.\n if (chars[i + 1] === '*') return GLOBSTAR_IN_NAME;\n tokens.push({ kind: 'star' });\n } else if (ch === '?') {\n tokens.push({ kind: 'any' });\n } else if (ch === '[') {\n const parsed = readClass(chars, i, escapes);\n if (typeof parsed === 'string') return parsed;\n tokens.push(parsed.token);\n i = parsed.end;\n } else {\n tokens.push({ kind: 'literal', point: ch.codePointAt(0) as number });\n }\n }\n return tokens;\n}\n\nfunction readClass(chars: readonly string[], open: number, escapes: boolean): { token: Token; end: number } | string {\n let i = open + 1;\n let negated = false;\n if (chars[i] === '!' || chars[i] === '^') {\n negated = true;\n i += 1;\n }\n const ranges: CodeRange[] = [];\n let first = true;\n for (; i < chars.length; i += 1) {\n const ch = chars[i] as string;\n if (ch === ']' && !first) return { token: { kind: 'class', negated, ranges }, end: i };\n first = false;\n let low = ch;\n if (ch === '\\\\' && escapes && chars[i + 1] !== undefined) {\n i += 1;\n low = chars[i] as string;\n }\n let high = low;\n if (chars[i + 1] === '-' && chars[i + 2] !== undefined && chars[i + 2] !== ']') {\n i += 2;\n high = chars[i] as string;\n if (high === '\\\\' && escapes && chars[i + 1] !== undefined) {\n i += 1;\n high = chars[i] as string;\n }\n }\n const from = low.codePointAt(0) as number;\n const to = high.codePointAt(0) as number;\n if (to < from) return `the range \"${low}-${high}\" runs backwards`;\n ranges.push([from, to]);\n }\n return 'a \"[\" is never closed';\n}\n\n/* --------------------------------------------------------------- compiling */\n\nfunction literalText(segments: readonly Segment[]): string | null {\n const names: string[] = [];\n for (const segment of segments) {\n if (segment.kind !== 'name') return null;\n let name = '';\n for (const token of segment.tokens) {\n if (token.kind !== 'literal') return null;\n name += String.fromCodePoint(token.point);\n }\n names.push(name);\n }\n return names.join('/');\n}\n\n/** One segment name: at least one character, none of them `/`. */\nfunction name(b: Builder): Fragment {\n return b.plus(b.char(ANY));\n}\n\n/** Zero or more whole directories: `(name/)*`. */\nfunction anyDirectories(b: Builder): Fragment {\n return b.star(b.sequence([name(b), b.char(SEPARATOR)]));\n}\n\n/** One or more whole segments below a path: `/name(/name)*`. */\nfunction beneath(b: Builder): Fragment {\n return b.sequence([b.char(SEPARATOR), name(b), b.star(b.sequence([b.char(SEPARATOR), name(b)]))]);\n}\n\nfunction tokens(b: Builder, list: readonly Token[]): Fragment {\n return b.sequence(\n list.map((token) => {\n switch (token.kind) {\n case 'literal':\n return b.char(literalSet(token.point));\n case 'any':\n return b.char(ANY);\n case 'star':\n return b.star(b.char(ANY));\n case 'class':\n return b.char(classSet(token.ranges, token.negated));\n }\n }),\n );\n}\n\nfunction segmentsFragment(b: Builder, segments: readonly Segment[]): Fragment {\n const parts: Fragment[] = [];\n segments.forEach((segment, i) => {\n const last = i === segments.length - 1;\n if (segment.kind === 'globstar') {\n // Inside a path a globstar is any number of whole directories, the\n // separator after them included; at its end, at least one segment.\n parts.push(last ? b.sequence([name(b), b.star(b.sequence([b.char(SEPARATOR), name(b)]))]) : anyDirectories(b));\n return;\n }\n parts.push(tokens(b, segment.tokens));\n if (!last) parts.push(b.char(SEPARATOR));\n });\n return b.sequence(parts);\n}\n\nfunction compileAlternative(\n b: Builder,\n alternative: Alternative,\n options: GlobOptions,\n rooted: boolean,\n anchored: boolean,\n): { fragment: Fragment; base: string } {\n const { segments } = alternative;\n const body = segmentsFragment(b, segments);\n const root = rooted ? '/' : '';\n const literal = literalText(segments);\n const leading = leadingLiteral(segments);\n\n if (options.dialect === 'gitignore') {\n const floating = !anchored && !alternative.slashed;\n const parts = [body, b.optional(beneath(b))];\n if (floating) parts.unshift(anyDirectories(b));\n const base = literal !== null ? leading.slice(0, -1) : leading;\n return { fragment: b.sequence(parts), base: floating ? '' : base.join('/') };\n }\n\n if (options.dialect === 'ripgrep' && !rooted && !alternative.slashed) {\n return { fragment: b.sequence([anyDirectories(b), body]), base: '' };\n }\n\n const parts = rooted ? [b.char(SEPARATOR), body] : [body];\n if (options.dialect === 'path' && literal !== null) {\n const reading = typeof options.literal === 'function' ? options.literal(root + literal) : options.literal ?? 'either';\n if (reading === 'directory') {\n parts.push(beneath(b));\n return { fragment: b.sequence(parts), base: root + literal };\n }\n if (reading === 'either') parts.push(b.optional(beneath(b)));\n }\n // A literal path may be a file, whose base is the directory holding it.\n const base = literal !== null ? leading.slice(0, -1) : leading;\n return { fragment: b.sequence(parts), base: root + base.join('/') };\n}\n\nfunction leadingLiteral(segments: readonly Segment[]): string[] {\n const out: string[] = [];\n for (const segment of segments) {\n const text = literalText([segment]);\n if (text === null) break;\n out.push(text);\n }\n return out;\n}\n\n/* ---------------------------------------------------------------- questions */\n\nfunction assertComparable(globs: readonly Glob[]): void {\n for (const glob of globs) {\n if (!glob.caseSensitive) throw new Error(`\"${glob.source}\" ignores case; scopes are compared case-sensitively`);\n }\n}\n\n/**\n * A shortest path every glob in `include` matches and no glob in `exclude`\n * does: the file two scopes would both write, less what either protects.\n * `none` is a proof that there is no such path. Case-sensitive globs only.\n */\nexport function globWitness(\n include: readonly Glob[],\n exclude: readonly Glob[] = [],\n budget: number = WITNESS_BUDGET,\n): Witness {\n assertComparable([...include, ...exclude]);\n return findWitness(\n include.map((glob) => glob.automaton),\n exclude.map((glob) => glob.automaton),\n budget,\n );\n}\n\n/**\n * Whether every path `inner` matches is matched by one of `outer`: `true`,\n * `false`, or `undecided` when the search met its budget.\n */\nexport function globCovers(\n outer: readonly Glob[],\n inner: Glob,\n budget: number = WITNESS_BUDGET,\n): boolean | 'undecided' {\n const witness = globWitness([inner], outer, budget);\n return witness.kind === 'undecided' ? 'undecided' : witness.kind === 'none';\n}\n\n/* -------------------------------------------------------------------- lists */\n\nexport interface GlobList {\n /** Whether a path is in: the last entry that matches it decides, and a `!` entry takes it out. */\n match(path: string): boolean;\n readonly entries: readonly { readonly negated: boolean; readonly glob: Glob }[];\n}\n\nexport type GlobListParse = { readonly ok: true; readonly list: GlobList } | { readonly ok: false; readonly error: string };\n\n/**\n * A list of patterns read the way a `.gitignore` reads: in order, each entry\n * deciding the paths it matches, a leading `!` taking them back out.\n */\nexport function parseGlobList(patterns: readonly string[], options: GlobOptions): GlobListParse {\n const entries: { negated: boolean; glob: Glob }[] = [];\n for (const pattern of patterns) {\n const trimmed = pattern.trim();\n const negated = trimmed.startsWith('!');\n const parsed = parseGlob(negated ? trimmed.slice(1) : trimmed, options);\n if (!parsed.ok) return { ok: false, error: `\"${pattern}\": ${parsed.error}` };\n entries.push({ negated, glob: parsed.glob });\n }\n return {\n ok: true,\n list: {\n entries,\n match(path: string): boolean {\n let included = false;\n for (const entry of entries) if (entry.glob.match(path)) included = !entry.negated;\n return included;\n },\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/pattern/glob.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Globs, in the three dialects the spec-* tools speak, compiled to one kind of\n * automaton.\n *\n * The syntax is the part people type: `*`, `**`, `?`, `[abc]`, `[!a-z]`,\n * `{a,b}`, and `\\` to escape. What differs between the tools is not the\n * syntax but what a pattern is matched against, and those differences are\n * deliberate, so each has a name (docs/adr/0003-glob-dialects.md):\n *\n * - `path` - the whole repository-relative path, anchored at the root. A\n * pattern with no glob syntax names a file, a directory, or either, as the\n * caller says; `src/auth` may cover `src/auth/login.ts`.\n * - `ripgrep` - as ripgrep's `-g`: a pattern with no `/` is matched against\n * the last segment at any depth, so `*.ts` matches `src/deep/a.ts`; one with\n * a `/` is matched against the whole path.\n * - `gitignore` - as an exclusion list reads: a pattern matches a path or any\n * directory above it, so `tests` excludes everything under any `tests`; one\n * with a `/` other than a trailing one is anchored at the root, and a\n * leading `/` only anchors.\n *\n * Shared by all three:\n *\n * - `**` is a globstar only as a whole segment. `a/**\\/b` matches `a/b` and\n * `a/x/y/b`; a trailing `/**` matches everything inside a directory and not\n * the directory itself. Two stars inside a name, `**.md`, are refused: the\n * tools read it three ways, and the quiet reading narrowed their scope. The\n * refusal writes the two patterns it may have meant from the one written.\n * - `*`, `?` and classes never match `/`, and `*` matches a leading dot.\n * - Braces expand first, and each alternative reads as it would written on\n * its own: `{src/,lib}` is `src/` or `lib`, and a trailing `/` means the\n * directory's contents - in an exclusion, the directory and its contents.\n * `{/docs,lib}` is `/docs` or `lib`, the leading `/` rooting or anchoring\n * that alternative as it would the pattern. One that names no path,\n * `{./,lib}` or `{,lib}`, is refused, as `./` and the empty pattern are.\n * - Case is the caller's decision, stated every time. A result must not\n * depend on the host it ran on.\n * - A malformed pattern is an error, never a literal. An unclosed `[` or `{`,\n * an extended glob, a `..` - each is refused with a reason, because a typo\n * read as a literal is a scope that silently matches nothing. An extended\n * glob is a group holding a `|`, `+(a|b)`: without one, `C++(notes).md` is\n * a name with parentheses in it, as ripgrep and `.gitignore` read it.\n */\n\nimport {\n AutomatonTooLarge,\n Builder,\n findWitness,\n Matcher,\n WITNESS_BUDGET,\n type Automaton,\n type Fragment,\n type Witness,\n} from './automaton.js';\nimport { ANY, classSet, literalSet, SEPARATOR, type CodeRange } from './charset.js';\n\nexport type GlobDialect = 'path' | 'ripgrep' | 'gitignore';\n\n/** How a `path` pattern with no glob syntax is read. */\nexport type LiteralReading = 'file' | 'directory' | 'either';\n\nexport interface GlobOptions {\n readonly dialect: GlobDialect;\n /** Whether `A` and `a` differ. No default: the caller decides, every time. */\n readonly caseSensitive: boolean;\n /**\n * `path` dialect only: how a pattern with no glob syntax is read - as a\n * file, as a directory and everything beneath it, or as either. A function\n * is asked per literal path, for a caller that knows the tree. `either` when\n * unset. A trailing `/`, on the pattern or on one of its brace alternatives,\n * always means a directory's contents, and is never asked about.\n */\n readonly literal?: LiteralReading | ((path: string) => LiteralReading) | undefined;\n /**\n * `escape` (the default): `\\` escapes the next character, and a `\\` before a\n * letter or digit is refused as a Windows separator typed by mistake.\n * `separator`: every `\\` is a `/`, for patterns typed on a Windows shell.\n */\n readonly backslash?: 'escape' | 'separator' | undefined;\n}\n\nexport interface Glob {\n readonly source: string;\n readonly dialect: GlobDialect;\n readonly caseSensitive: boolean;\n /**\n * The directories a walk must enter to find every match: one per\n * alternative, the leading literal segments. `''` for an alternative that\n * can match at any depth.\n */\n readonly bases: readonly string[];\n readonly automaton: Automaton;\n /** Whether a canonical path - POSIX, no `.`, no empty or trailing segment - matches. */\n match(path: string): boolean;\n}\n\nexport type GlobParse = { readonly ok: true; readonly glob: Glob } | { readonly ok: false; readonly error: string };\n\nexport class GlobError extends Error {\n readonly source: string;\n constructor(source: string, reason: string) {\n super(`invalid glob \"${source}\": ${reason}`);\n this.name = 'GlobError';\n this.source = source;\n }\n}\n\n/** More alternatives than this is a pattern nobody meant. */\nexport const MAX_ALTERNATIVES = 256;\n\ntype Token =\n | { readonly kind: 'literal'; readonly point: number }\n | { readonly kind: 'any' }\n | { readonly kind: 'star' }\n | { readonly kind: 'class'; readonly negated: boolean; readonly ranges: readonly CodeRange[] };\n\ntype Segment = { readonly kind: 'globstar' } | { readonly kind: 'name'; readonly tokens: readonly Token[] };\n\ninterface Alternative {\n readonly segments: readonly Segment[];\n /** Written with a `/` somewhere other than at its end. */\n readonly slashed: boolean;\n /**\n * Written with a leading `/`, on the pattern or on the alternative: rooted\n * at the filesystem's root in the `path` and `ripgrep` dialects, and only\n * anchored at the repository root in `gitignore`.\n */\n readonly rooted: boolean;\n}\n\n/** Whether a string uses glob syntax at all. */\nexport function isGlobSyntax(source: string): boolean {\n return /[*?[\\]{}]/.test(source);\n}\n\n/**\n * Parses and compiles a glob, or says why it cannot: malformed, or too large\n * to compile, past {@link MAX_ALTERNATIVES} alternatives or `MAX_STATES`\n * states. It throws only what a `literal` function throws.\n */\nexport function parseGlob(source: string, options: GlobOptions): GlobParse {\n const result = build(source, options);\n return typeof result === 'string' ? { ok: false, error: result } : { ok: true, glob: result };\n}\n\n/**\n * Parses and compiles a glob, throwing {@link GlobError} for every reason\n * {@link parseGlob} gives, and what a `literal` function throws.\n */\nexport function compileGlob(source: string, options: GlobOptions): Glob {\n const result = build(source, options);\n if (typeof result === 'string') throw new GlobError(source, result);\n return result;\n}\n\nfunction build(source: string, options: GlobOptions): Glob | string {\n const escapes = options.backslash !== 'separator';\n let pattern = source.trim();\n if (!escapes) pattern = pattern.replace(/\\\\/g, '/');\n const written = pattern;\n if (pattern.length === 0) return 'the pattern is empty';\n if (pattern.startsWith('!')) return 'a negated pattern is a list entry, not a glob; narrow the positive pattern';\n if (/(?:^|[^\\\\])[?*+@!]\\([^)]*\\|/.test(pattern)) return EXTGLOB;\n\n // The pattern's own leading slash is taken off before the braces expand, so\n // that the root itself, and a text the braces give, are refused in the\n // words they always were: `/{./,a}` is told `./`.\n const whole = unrooted(pattern);\n if (whole.text.length === 0) return 'the pattern names the root itself, not a path under it';\n\n const expanded = expandBraces(whole.text, escapes);\n if (typeof expanded === 'string') return expanded;\n\n const alternatives: Alternative[] = [];\n for (const text of expanded) {\n // Refused before its trailing slash is read, which would make `./` the\n // contents of `.`, every path: `{./,a}` is refused as `./` alone is.\n // Each text the braces give is shorter than the pattern, so only a\n // pattern without braces is its own text.\n if (namesNoPath(text)) return text === whole.text ? 'the pattern names no path' : bracesNamingNoPath(text);\n // Its leading slash is read as the pattern's is, since braces expand\n // before anything else is decided: `{/docs,x}` is `/docs` or `x`. Left to\n // `parseAlternative`, the slash would be an empty segment, dropped, and\n // `/docs` would read as `docs`. A slash after a segment, as in\n // `a/{/b,c}`, starts no text, and is the empty segment of `a//b`.\n const alone = unrooted(text);\n const parsed = parseAlternative(trailingSlash(alone.text, options.dialect), escapes);\n if (parsed === GLOBSTAR_IN_NAME) return `${GLOBSTAR_IN_NAME}: ${globstarAdvice(written)}`;\n if (typeof parsed === 'string') return parsed;\n alternatives.push({ ...parsed, rooted: whole.rooted || alone.rooted });\n }\n\n const builder = new Builder();\n const fragments: Fragment[] = [];\n const bases: string[] = [];\n let automaton: Automaton;\n try {\n for (const alternative of alternatives) {\n const compiled = compileAlternative(builder, alternative, options);\n fragments.push(compiled.fragment);\n bases.push(compiled.base);\n }\n automaton = builder.finish(builder.either(fragments), options.caseSensitive);\n } catch (error) {\n // A pattern too large to compile is refused with a reason, as a malformed\n // one is. Anything else - a caller's literal reading that throws - is the\n // caller's failure, not the pattern's, and goes on up.\n if (error instanceof AutomatonTooLarge) return error.message;\n throw error;\n }\n let matcher: Matcher | null = null;\n return {\n source,\n dialect: options.dialect,\n caseSensitive: options.caseSensitive,\n bases: [...new Set(bases)],\n automaton,\n match(path: string): boolean {\n matcher ??= new Matcher(automaton);\n return matcher.test(path);\n },\n };\n}\n\n/* ------------------------------------------------------------------ braces */\n\n/**\n * Expands `{a,b}` groups into the patterns they stand for, or says why the\n * pattern is malformed.\n *\n * Classes and escapes are skipped while looking for braces and commas, so\n * `{[,]x,y}` is two alternatives, `[,]x` and `y`. A lone `}` is a literal: it\n * cannot be read as anything else. An unclosed `{` is an error.\n *\n * Here and in the two functions after it, a loop that reads one step past\n * the end reads `''`, which none of them acts on, and `classEnd` answers -1\n * or an index past the `[`, so `close > 0` and `close >= 0` read the same.\n * `open` is set by the `{` that any `}` read here closes, so its first value\n * is never read.\n */\nfunction expandBraces(pattern: string, escapes: boolean): string[] | string {\n let depth = 0;\n let open = -1;\n for (let i = 0; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\' && escapes) {\n i += 1;\n continue;\n }\n if (ch === '[') {\n const close = classEnd(pattern, i, escapes);\n if (close > 0) i = close;\n continue;\n }\n if (ch === '{') {\n if (depth === 0) open = i;\n depth += 1;\n continue;\n }\n if (ch !== '}' || depth === 0) continue;\n depth -= 1;\n if (depth > 0) continue;\n const prefix = pattern.slice(0, open);\n const suffix = pattern.slice(i + 1);\n const results: string[] = [];\n for (const option of splitOptions(pattern.slice(open + 1, i), escapes)) {\n const expanded = expandBraces(`${prefix}${option}${suffix}`, escapes);\n if (typeof expanded === 'string') return expanded;\n results.push(...expanded);\n if (results.length > MAX_ALTERNATIVES) return `the braces expand to more than ${MAX_ALTERNATIVES} patterns`;\n }\n return results;\n }\n if (depth > 0) return 'a \"{\" is never closed';\n return [pattern];\n}\n\n/** Splits a brace body on its top-level commas. */\nfunction splitOptions(body: string, escapes: boolean): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < body.length; i += 1) {\n const ch = body.charAt(i);\n if (ch === '\\\\' && escapes) {\n i += 1;\n } else if (ch === '[') {\n const close = classEnd(body, i, escapes);\n if (close > 0) i = close;\n } else if (ch === '{') {\n depth += 1;\n } else if (ch === '}') {\n depth -= 1;\n } else if (ch === ',' && depth === 0) {\n parts.push(body.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(body.slice(start));\n return parts;\n}\n\n/** The index of the `]` closing a class opened at `open`, or -1 when none does within the segment. */\nfunction classEnd(pattern: string, open: number, escapes: boolean): number {\n let i = open + 1;\n if (pattern.charAt(i) === '!' || pattern.charAt(i) === '^') i += 1;\n // The first member is always a member, even `]`.\n if (pattern.charAt(i) === ']') i += 1;\n for (; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\' && escapes) {\n i += 1;\n continue;\n }\n if (ch === '/') return -1;\n if (ch === ']') return i;\n }\n return -1;\n}\n\n/* ---------------------------------------------------------------- segments */\n\n/**\n * A pattern, or a text its braces give, without the `./` and the slashes it\n * starts with, and whether a slash led it once the `./` was gone. What a\n * leading slash means is the dialect's: it roots a pattern at the\n * filesystem's root in `path` and `ripgrep`, and only anchors it at the\n * repository root in `gitignore`, as git reads one. `.//docs` is led by one,\n * as `/docs` is.\n */\nfunction unrooted(text: string): { readonly text: string; readonly rooted: boolean } {\n let rest = text;\n while (rest.startsWith('./')) rest = rest.slice(2);\n return { text: rest.replace(/^\\/+/, ''), rooted: rest.startsWith('/') };\n}\n\n/** Whether a pattern's text names no path: nothing in it but `/` and `.` segments. */\nfunction namesNoPath(text: string): boolean {\n return text.split('/').every((part) => part === '' || part === '.');\n}\n\n/**\n * The refusal of an alternative the braces give that names no path, naming\n * it as it was expanded, so that `.{/,a}` is told `./`, the text refused.\n */\nfunction bracesNamingNoPath(text: string): string {\n return text === '' ? 'the braces expand to an empty pattern' : `the braces expand to \"${text}\", which names no path`;\n}\n\n/**\n * What a trailing slash means, read on each alternative the braces give, so\n * that `{src/,lib}` reads `src/` as `src/` alone reads: the directory's\n * contents, `src/**`, and not a literal that may be the directory itself.\n *\n * In an exclusion `build/` excludes what `build` does. Git's rule is that a\n * trailing slash matches only a directory, and a directory is excluded with\n * everything in it; a matcher that sees only a path cannot tell a directory\n * from a file, so the slash is dropped, and it anchors nothing.\n *\n * Only ever given a text that names a path, so a name is left. The whole run\n * of slashes is taken, but one slash would read the same, since\n * `parseAlternative` drops the empty segments the rest leave; and taken\n * lazily it is the whole run all the same, since it ends the text.\n */\nfunction trailingSlash(text: string, dialect: GlobDialect): string {\n const name = text.replace(/\\/+$/, '');\n return name === text || dialect === 'gitignore' ? name : `${name}/**`;\n}\n\n/**\n * The segments of a text that names a path - `build` refuses one that does\n * not - so at least one segment is left.\n */\nfunction parseAlternative(text: string, escapes: boolean): Omit<Alternative, 'rooted'> | string {\n const segments: Segment[] = [];\n const raw = text.split('/');\n for (const part of raw) {\n if (part === '' || part === '.') continue;\n if (part === '..') return 'a pattern cannot climb out of its root with \"..\"';\n if (part === '**') {\n if (segments[segments.length - 1]?.kind !== 'globstar') segments.push({ kind: 'globstar' });\n continue;\n }\n const tokens = tokenize(part, escapes);\n if (typeof tokens === 'string') return tokens;\n segments.push({ kind: 'name', tokens });\n }\n return { segments, slashed: raw.filter((part) => part !== '' && part !== '.').length > 1 };\n}\n\nconst EXTGLOB = 'extended globs such as \"+(a|b)\" are not supported: write alternatives as \"{a,b}\", and a literal parenthesis as \"[(]\"';\nconst GLOBSTAR_IN_NAME = '\"**\" means any number of directories only as a whole segment';\n\n/**\n * The two patterns a writer of `**` inside a name may have meant, built from\n * what they wrote. Each run of stars that is not a whole segment becomes, for\n * any depth, a globstar segment with a star kept on each side where a name\n * went on - `docs/**.md` to `docs/**\\/*.md`, `src/a**` to `src/a*\\/**`,\n * `a**b` to `a*\\/**\\/*b` - and for one level a single star. Everything else\n * stays as written, braces and classes included, and a globstar that was a\n * whole segment stays one.\n *\n * Only `/` is taken for a boundary. A run beside a brace, `{**.md,x}`, is\n * given a star on that side too, which keeps the advice a pattern that\n * compiles whatever the braces expand to.\n *\n * `written` holds a `\\` only where it escapes: in the `separator` reading\n * each one is already a `/`.\n */\nfunction globstarAdvice(written: string): string {\n let deep = '';\n let flat = '';\n let at = 0;\n // One step past the end reads `''` and appends nothing, so the bound could\n // be one further and give the same advice.\n while (at < written.length) {\n const ch = written.charAt(at);\n let next = at + 1;\n if (ch === '\\\\') {\n next = at + 2;\n } else if (ch === '[') {\n // A class is copied as written. `classEnd` answers an index past the\n // `[`, or -1 for one never closed, so `close >= 0` reads the same; and\n // stopping one short of the `]` copies the class all the same, since\n // its last member and the `]` after it are never a run of stars.\n const close = classEnd(written, at, true);\n if (close > 0) next = close + 1;\n } else if (ch === '*') {\n while (written.charAt(next) === '*') next += 1;\n const before = at > 0 && written.charAt(at - 1) !== '/';\n const after = next < written.length && written.charAt(next) !== '/';\n if (next - at > 2 || (next - at === 2 && (before || after))) {\n deep += `${before ? '*/' : ''}**${after ? '/*' : ''}`;\n flat += '*';\n at = next;\n continue;\n }\n }\n deep += written.slice(at, next);\n flat += written.slice(at, next);\n at = next;\n }\n return `write \"${deep}\" for any depth, or \"${flat}\" for one level`;\n}\n\nfunction tokenize(segment: string, escapes: boolean): Token[] | string {\n const tokens: Token[] = [];\n const chars = Array.from(segment);\n for (let i = 0; i < chars.length; i += 1) {\n const ch = chars[i] as string;\n if (ch === '\\\\' && escapes) {\n const next = chars[i + 1];\n if (next === undefined || /[A-Za-z0-9]/.test(next)) {\n return '\"\\\\\" escapes glob syntax; separate directories with \"/\"';\n }\n tokens.push({ kind: 'literal', point: next.codePointAt(0) as number });\n i += 1;\n } else if (ch === '*') {\n // Two stars inside a name are refused rather than read as one. The\n // tools this replaces read `docs/**.md` three ways - recursive, one\n // level, and as ripgrep does - and reading it as one level silently\n // dropped every nested document from a run that used to include them.\n if (chars[i + 1] === '*') return GLOBSTAR_IN_NAME;\n tokens.push({ kind: 'star' });\n } else if (ch === '?') {\n tokens.push({ kind: 'any' });\n } else if (ch === '[') {\n const parsed = readClass(chars, i, escapes);\n if (typeof parsed === 'string') return parsed;\n tokens.push(parsed.token);\n i = parsed.end;\n } else {\n tokens.push({ kind: 'literal', point: ch.codePointAt(0) as number });\n }\n }\n return tokens;\n}\n\nfunction readClass(chars: readonly string[], open: number, escapes: boolean): { token: Token; end: number } | string {\n let i = open + 1;\n let negated = false;\n if (chars[i] === '!' || chars[i] === '^') {\n negated = true;\n i += 1;\n }\n const ranges: CodeRange[] = [];\n let first = true;\n for (; i < chars.length; i += 1) {\n const ch = chars[i] as string;\n if (ch === ']' && !first) return { token: { kind: 'class', negated, ranges }, end: i };\n first = false;\n let low = ch;\n if (ch === '\\\\' && escapes && chars[i + 1] !== undefined) {\n i += 1;\n low = chars[i] as string;\n }\n let high = low;\n if (chars[i + 1] === '-' && chars[i + 2] !== undefined && chars[i + 2] !== ']') {\n i += 2;\n high = chars[i] as string;\n if (high === '\\\\' && escapes && chars[i + 1] !== undefined) {\n i += 1;\n high = chars[i] as string;\n }\n }\n const from = low.codePointAt(0) as number;\n const to = high.codePointAt(0) as number;\n if (to < from) return `the range \"${low}-${high}\" runs backwards`;\n ranges.push([from, to]);\n }\n return 'a \"[\" is never closed';\n}\n\n/* --------------------------------------------------------------- compiling */\n\nfunction literalText(segments: readonly Segment[]): string | null {\n const names: string[] = [];\n for (const segment of segments) {\n if (segment.kind !== 'name') return null;\n let name = '';\n for (const token of segment.tokens) {\n if (token.kind !== 'literal') return null;\n name += String.fromCodePoint(token.point);\n }\n names.push(name);\n }\n return names.join('/');\n}\n\n/** One segment name: at least one character, none of them `/`. */\nfunction name(b: Builder): Fragment {\n return b.plus(b.char(ANY));\n}\n\n/** Zero or more whole directories: `(name/)*`. */\nfunction anyDirectories(b: Builder): Fragment {\n return b.star(b.sequence([name(b), b.char(SEPARATOR)]));\n}\n\n/** One or more whole segments below a path: `/name(/name)*`. */\nfunction beneath(b: Builder): Fragment {\n return b.sequence([b.char(SEPARATOR), name(b), b.star(b.sequence([b.char(SEPARATOR), name(b)]))]);\n}\n\nfunction tokens(b: Builder, list: readonly Token[]): Fragment {\n return b.sequence(\n list.map((token) => {\n switch (token.kind) {\n case 'literal':\n return b.char(literalSet(token.point));\n case 'any':\n return b.char(ANY);\n case 'star':\n return b.star(b.char(ANY));\n case 'class':\n return b.char(classSet(token.ranges, token.negated));\n }\n }),\n );\n}\n\nfunction segmentsFragment(b: Builder, segments: readonly Segment[]): Fragment {\n const parts: Fragment[] = [];\n segments.forEach((segment, i) => {\n const last = i === segments.length - 1;\n if (segment.kind === 'globstar') {\n // Inside a path a globstar is any number of whole directories, the\n // separator after them included; at its end, at least one segment.\n parts.push(last ? b.sequence([name(b), b.star(b.sequence([b.char(SEPARATOR), name(b)]))]) : anyDirectories(b));\n return;\n }\n parts.push(tokens(b, segment.tokens));\n if (!last) parts.push(b.char(SEPARATOR));\n });\n return b.sequence(parts);\n}\n\nfunction compileAlternative(b: Builder, alternative: Alternative, options: GlobOptions): { fragment: Fragment; base: string } {\n const { segments, rooted } = alternative;\n const body = segmentsFragment(b, segments);\n const root = rooted ? '/' : '';\n const literal = literalText(segments);\n const leading = leadingLiteral(segments);\n\n if (options.dialect === 'gitignore') {\n const floating = !rooted && !alternative.slashed;\n const parts = [body, b.optional(beneath(b))];\n if (floating) parts.unshift(anyDirectories(b));\n const base = literal !== null ? leading.slice(0, -1) : leading;\n return { fragment: b.sequence(parts), base: floating ? '' : base.join('/') };\n }\n\n if (options.dialect === 'ripgrep' && !rooted && !alternative.slashed) {\n return { fragment: b.sequence([anyDirectories(b), body]), base: '' };\n }\n\n const parts = rooted ? [b.char(SEPARATOR), body] : [body];\n if (options.dialect === 'path' && literal !== null) {\n const reading = typeof options.literal === 'function' ? options.literal(root + literal) : options.literal ?? 'either';\n if (reading === 'directory') {\n parts.push(beneath(b));\n return { fragment: b.sequence(parts), base: root + literal };\n }\n if (reading === 'either') parts.push(b.optional(beneath(b)));\n }\n // A literal path may be a file, whose base is the directory holding it.\n const base = literal !== null ? leading.slice(0, -1) : leading;\n return { fragment: b.sequence(parts), base: root + base.join('/') };\n}\n\nfunction leadingLiteral(segments: readonly Segment[]): string[] {\n const out: string[] = [];\n for (const segment of segments) {\n const text = literalText([segment]);\n if (text === null) break;\n out.push(text);\n }\n return out;\n}\n\n/* ---------------------------------------------------------------- questions */\n\nfunction assertComparable(globs: readonly Glob[]): void {\n for (const glob of globs) {\n if (!glob.caseSensitive) throw new Error(`\"${glob.source}\" ignores case; scopes are compared case-sensitively`);\n }\n}\n\n/**\n * A shortest path every glob in `include` matches and no glob in `exclude`\n * does: the file two scopes would both write, less what either protects.\n * `none` is a proof that there is no such path. Case-sensitive globs only.\n */\nexport function globWitness(\n include: readonly Glob[],\n exclude: readonly Glob[] = [],\n budget: number = WITNESS_BUDGET,\n): Witness {\n assertComparable([...include, ...exclude]);\n return findWitness(\n include.map((glob) => glob.automaton),\n exclude.map((glob) => glob.automaton),\n budget,\n );\n}\n\n/**\n * Whether every path `inner` matches is matched by one of `outer`: `true`,\n * `false`, or `undecided` when the search met its budget.\n */\nexport function globCovers(\n outer: readonly Glob[],\n inner: Glob,\n budget: number = WITNESS_BUDGET,\n): boolean | 'undecided' {\n const witness = globWitness([inner], outer, budget);\n return witness.kind === 'undecided' ? 'undecided' : witness.kind === 'none';\n}\n\n/* -------------------------------------------------------------------- lists */\n\nexport interface GlobList {\n /** Whether a path is in: the last entry that matches it decides, and a `!` entry takes it out. */\n match(path: string): boolean;\n readonly entries: readonly { readonly negated: boolean; readonly glob: Glob }[];\n}\n\nexport type GlobListParse = { readonly ok: true; readonly list: GlobList } | { readonly ok: false; readonly error: string };\n\n/**\n * A list of patterns read the way a `.gitignore` reads: in order, each entry\n * deciding the paths it matches, a leading `!` taking them back out.\n */\nexport function parseGlobList(patterns: readonly string[], options: GlobOptions): GlobListParse {\n const entries: { negated: boolean; glob: Glob }[] = [];\n for (const pattern of patterns) {\n const trimmed = pattern.trim();\n const negated = trimmed.startsWith('!');\n const parsed = parseGlob(negated ? trimmed.slice(1) : trimmed, options);\n if (!parsed.ok) return { ok: false, error: `\"${pattern}\": ${parsed.error}` };\n entries.push({ negated, glob: parsed.glob });\n }\n return {\n ok: true,\n list: {\n entries,\n match(path: string): boolean {\n let included = false;\n for (const entry of entries) if (entry.glob.match(path)) included = !entry.negated;\n return included;\n },\n },\n };\n}\n"]}
|
package/package.json
CHANGED