@descent-vtt/spec-graph 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +252 -0
- package/README.md +55 -6
- package/dist/cli.d.ts +10 -2
- package/dist/cli.js +192 -60
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +33 -0
- package/dist/config.js +40 -1
- package/dist/config.js.map +1 -1
- package/dist/extract.d.ts +20 -0
- package/dist/extract.js +39 -6
- package/dist/extract.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/regex.d.ts +64 -0
- package/dist/regex.js +708 -0
- package/dist/regex.js.map +1 -0
- package/dist/report.d.ts +19 -0
- package/dist/report.js +109 -0
- package/dist/report.js.map +1 -1
- package/dist/rules.d.ts +13 -0
- package/dist/rules.js +26 -0
- package/dist/rules.js.map +1 -1
- package/dist/select.d.ts +8 -0
- package/dist/select.js +33 -14
- package/dist/select.js.map +1 -1
- package/package.json +1 -1
package/dist/regex.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A regular-expression matcher that cannot backtrack.
|
|
3
|
+
*
|
|
4
|
+
* `~=` is the one predicate in the selector language that used to hand a
|
|
5
|
+
* user-supplied string to `RegExp` and wait. That is tolerable at a prompt,
|
|
6
|
+
* where a human can press Ctrl-C. It is not tolerable in `.spec-graph.json`,
|
|
7
|
+
* where the same string runs unattended in CI against every node in the corpus.
|
|
8
|
+
*
|
|
9
|
+
* The cost is neither theoretical nor exotic. `^([A-Za-z0-9_]+[ ]?)+$` is what
|
|
10
|
+
* somebody writes to say "the title is words separated by single spaces", and
|
|
11
|
+
* against a title that does not match, V8 tries one branch per way of cutting
|
|
12
|
+
* each word into pieces:
|
|
13
|
+
*
|
|
14
|
+
* ```text
|
|
15
|
+
* RegExp here
|
|
16
|
+
* the quick brown fox jumps over the lazy dog! 0.9s 11us
|
|
17
|
+
* the quick brown fox jumps over the lazy dog and! 5.4s 12us
|
|
18
|
+
* the quick brown fox jumps over the lazy dog and keeps! 103s 13us
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Each word of k letters can be cut into pieces 2^(k-1) ways, and the engine
|
|
22
|
+
* tries the product of those, which is why adding one five-letter word costs
|
|
23
|
+
* another factor of sixteen. A sixty-character title does not finish this year.
|
|
24
|
+
*
|
|
25
|
+
* So a pattern here is compiled to a **non-deterministic finite automaton** and
|
|
26
|
+
* simulated over the subject one character at a time (Thompson, 1968), keeping
|
|
27
|
+
* a set of live states instead of a stack of choices. Each state is visited at
|
|
28
|
+
* most once per position, which makes the work exactly O(pattern x subject):
|
|
29
|
+
* the right-hand column above, growing with the subject and not with the
|
|
30
|
+
* pattern's ambiguity.
|
|
31
|
+
*
|
|
32
|
+
* What it costs is a dialect. Backreferences and lookaround are not regular and
|
|
33
|
+
* have no place in a linear automaton, so they are **rejected while compiling**,
|
|
34
|
+
* with a message and an offset, rather than accepted and then slow. That is the
|
|
35
|
+
* whole trade: a predicate that finishes, against a short list of constructs
|
|
36
|
+
* that a documentation selector never needed.
|
|
37
|
+
*
|
|
38
|
+
* Matching is case-insensitive and unanchored because that is what `~=` has
|
|
39
|
+
* always been - `new RegExp(source, 'i')` and `.test()`. There are no capture
|
|
40
|
+
* groups at all: nothing asks where the match was, only whether there was one,
|
|
41
|
+
* which is why this is a plain NFA simulation rather than a Pike VM.
|
|
42
|
+
*
|
|
43
|
+
* See ADR-0017.
|
|
44
|
+
*/
|
|
45
|
+
/** A pattern that will not compile, and where in it the problem starts. */
|
|
46
|
+
export declare class PatternError extends Error {
|
|
47
|
+
/** Offset into the pattern source. */
|
|
48
|
+
readonly offset: number;
|
|
49
|
+
constructor(message: string, offset: number);
|
|
50
|
+
}
|
|
51
|
+
/** A compiled pattern. Immutable, reusable, and safe to cache. */
|
|
52
|
+
export interface Matcher {
|
|
53
|
+
/** True when the pattern matches anywhere in the subject. */
|
|
54
|
+
test(subject: string): boolean;
|
|
55
|
+
/** State count. Published for the size test, and for nothing else. */
|
|
56
|
+
readonly size: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Compiles a pattern into a matcher.
|
|
60
|
+
*
|
|
61
|
+
* Throws {@link PatternError} on anything it cannot run in linear time, which
|
|
62
|
+
* is the point: the alternative to a message here is a build that stops.
|
|
63
|
+
*/
|
|
64
|
+
export declare function compilePattern(source: string): Matcher;
|