@nielspeter/eess-crossvalidate 0.1.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -5
- package/dist/files.d.ts +1 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js.map +1 -1
- package/dist/gherkin-ts.d.ts +126 -0
- package/dist/gherkin-ts.d.ts.map +1 -0
- package/dist/gherkin-ts.js +218 -0
- package/dist/gherkin-ts.js.map +1 -0
- package/dist/it-title.d.ts +72 -0
- package/dist/it-title.d.ts.map +1 -0
- package/dist/it-title.js +115 -0
- package/dist/it-title.js.map +1 -0
- package/dist/md-gherkin.d.ts +2 -0
- package/dist/md-gherkin.d.ts.map +1 -1
- package/dist/md-gherkin.js +0 -0
- package/dist/md-gherkin.js.map +1 -1
- package/dist/md-mermaid-er.d.ts +2 -0
- package/dist/md-mermaid-er.d.ts.map +1 -1
- package/dist/md-mermaid-er.js +2 -0
- package/dist/md-mermaid-er.js.map +1 -1
- package/dist/md-mermaid.d.ts +2 -0
- package/dist/md-mermaid.d.ts.map +1 -1
- package/dist/md-mermaid.js +2 -0
- package/dist/md-mermaid.js.map +1 -1
- package/dist/md-ts.d.ts +12 -0
- package/dist/md-ts.d.ts.map +1 -1
- package/dist/md-ts.js +60 -12
- package/dist/md-ts.js.map +1 -1
- package/dist/mermaid-ts.d.ts +2 -0
- package/dist/mermaid-ts.d.ts.map +1 -1
- package/dist/mermaid-ts.js +5 -0
- package/dist/mermaid-ts.js.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @nielspeter/eess-crossvalidate
|
|
2
2
|
|
|
3
|
-
Cross-validation presets for the [eess](
|
|
3
|
+
Cross-validation presets for the [eess](https://github.com/nielspeter/eess/blob/main/README.md) family — bind two dialects' artifacts and fail the build when they drift.
|
|
4
4
|
|
|
5
|
-
The generic engine lives in the kernel: [`correspondence()`](
|
|
5
|
+
The generic engine lives in the kernel: [`correspondence()`](https://www.npmjs.com/package/@nielspeter/eess) binds two element `Selection`s (from any dialects) and checks completeness both ways plus relation preservation. This package ships the **dialect-coupled presets** — the pairs that must import two concrete dialects.
|
|
6
6
|
|
|
7
7
|
## Mermaid ↔ TypeScript
|
|
8
8
|
|
|
@@ -11,8 +11,8 @@ import { diagramMatchesCode } from '@nielspeter/eess-crossvalidate/mermaid-ts'
|
|
|
11
11
|
import { project } from '@nielspeter/eess-ts'
|
|
12
12
|
import { diagram } from '@nielspeter/eess-mermaid'
|
|
13
13
|
|
|
14
|
-
// every class in the diagram exists in code, and vice versa
|
|
15
|
-
diagramMatchesCode(diagram('docs/architecture.mmd'), project('tsconfig.json'))
|
|
14
|
+
// every class in the diagram exists in code, and vice versa — throws on drift
|
|
15
|
+
diagramMatchesCode(diagram('docs/architecture.mmd'), project('tsconfig.json'))
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
If the code gains a `ModuloOperation` class the diagram doesn't have (or vice
|
|
@@ -34,10 +34,115 @@ AST-grounded: cited titles are resolved against actual `it()` call expressions
|
|
|
34
34
|
(via eess-ts's public API — no ts-morph here, per ADR-007), so it also catches
|
|
35
35
|
no-substitution template titles the text-level check misses.
|
|
36
36
|
|
|
37
|
+
## Markdown ↔ Gherkin
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { scenarioCitationsResolve } from '@nielspeter/eess-crossvalidate/md-gherkin'
|
|
41
|
+
import { corpus } from '@nielspeter/eess-md'
|
|
42
|
+
import { features } from '@nielspeter/eess-gherkin'
|
|
43
|
+
|
|
44
|
+
// every scenario a story cites — `checkout.feature` · 'Apply a valid code' —
|
|
45
|
+
// resolves to a real scenario in the feature set
|
|
46
|
+
scenarioCitationsResolve(
|
|
47
|
+
corpus({ roots: ['docs/**'] }),
|
|
48
|
+
features({ roots: ['features/**/*.feature'] }),
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Spec↔spec: a markdown story cites a behavior — a backticked `.feature` path plus
|
|
53
|
+
an optional quoted scenario title — and the citation is resolved against the
|
|
54
|
+
loaded feature set. Three failure modes fail the build: the feature file is
|
|
55
|
+
missing, the path is ambiguous, or the scenario title doesn't exist. The
|
|
56
|
+
`gherkin-ts` preset below is its code↔spec mirror.
|
|
57
|
+
|
|
58
|
+
## Gherkin ↔ TypeScript
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { scenarioTestsResolve } from '@nielspeter/eess-crossvalidate/gherkin-ts'
|
|
62
|
+
import { features } from '@nielspeter/eess-gherkin'
|
|
63
|
+
import { project } from '@nielspeter/eess-ts'
|
|
64
|
+
|
|
65
|
+
// every scenario a test cites — it('checkout.feature › Apply a valid code') —
|
|
66
|
+
// resolves to a real scenario in the feature set
|
|
67
|
+
scenarioTestsResolve(project('tsconfig.json'), features({ roots: ['features/**/*.feature'] }))
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The mirror image of md↔gherkin's story citations: here the citing side is the
|
|
71
|
+
**test AST** (`it('…')` titles, read via eess-ts's public API — no ts-morph, per
|
|
72
|
+
ADR-007). A scenario renamed or deleted out from under the test that cites it
|
|
73
|
+
fails the build. It resolves the citation; it does not claim the test exercises
|
|
74
|
+
the scenario's steps (Tier 2, still open).
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { scenariosCovered } from '@nielspeter/eess-crossvalidate/gherkin-ts'
|
|
78
|
+
|
|
79
|
+
// every scenario must be cited by at least one test — the coverage
|
|
80
|
+
// (right→left) direction, the complement of scenarioTestsResolve. `include`
|
|
81
|
+
// narrows the requirement so not-yet-implemented flows don't force a red
|
|
82
|
+
// build.
|
|
83
|
+
scenariosCovered(project('tsconfig.json'), features({ roots: ['features/**/*.feature'] }), {
|
|
84
|
+
include: (s) => !s.tags.includes('wip'),
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
A scenario shipped with no citing test fails the build. Pair `include` with
|
|
89
|
+
`scenarioExemptionsCurrent`'s `isExempt`, below — the two must use the same
|
|
90
|
+
tag, and neither has a default, on purpose: a `@wip` scenario excluded from
|
|
91
|
+
one but not the other would fail one gate or the other unconditionally.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { scenarioExemptionsCurrent } from '@nielspeter/eess-crossvalidate/gherkin-ts'
|
|
95
|
+
|
|
96
|
+
// the reverse of scenariosCovered: an exempt scenario must NOT already have a
|
|
97
|
+
// citing test. Once a test proves it, the exemption has outlived its reason.
|
|
98
|
+
scenarioExemptionsCurrent(
|
|
99
|
+
project('tsconfig.json'),
|
|
100
|
+
features({ roots: ['features/**/*.feature'] }),
|
|
101
|
+
{
|
|
102
|
+
isExempt: (s) => s.tags.includes('wip'),
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
An exemption (`@wip` by the convention above, or any tag `isExempt` reads) that
|
|
108
|
+
is still in force when a real test starts citing the scenario is a silent hole
|
|
109
|
+
in the coverage gate it was meant to narrow — the exemption should have been
|
|
110
|
+
removed the moment the work landed. The violation names both the scenario and
|
|
111
|
+
the citing test's own `file`/`line`.
|
|
112
|
+
|
|
113
|
+
## Markdown ↔ Mermaid
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { embeddedDiagramsMatchCode } from '@nielspeter/eess-crossvalidate/md-mermaid'
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
A ```mermaid fence embedded in a Markdown page must match the code it claims to
|
|
120
|
+
describe — a diagram that drifts from the source is a document that lies while
|
|
121
|
+
looking authoritative.
|
|
122
|
+
|
|
123
|
+
## Markdown ↔ Mermaid ER
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { tableErAgree, tableErStats } from '@nielspeter/eess-crossvalidate/md-mermaid-er'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
An ER diagram and the table it documents must agree. `tableErStats` reports what
|
|
130
|
+
was compared, so a pass is evidence rather than a default.
|
|
131
|
+
|
|
132
|
+
## Files
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { files } from '@nielspeter/eess-crossvalidate/files'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
A file-set loader for binding a side of a correspondence to paths on disk rather
|
|
139
|
+
than to a parsed dialect.
|
|
140
|
+
|
|
37
141
|
## Peers
|
|
38
142
|
|
|
39
143
|
The dialects are optional peer dependencies — install the ones your presets use
|
|
40
|
-
(`@nielspeter/eess-ts`, `@nielspeter/eess-mermaid`, `@nielspeter/eess-md
|
|
144
|
+
(`@nielspeter/eess-ts`, `@nielspeter/eess-mermaid`, `@nielspeter/eess-md`,
|
|
145
|
+
`@nielspeter/eess-gherkin`).
|
|
41
146
|
|
|
42
147
|
## License
|
|
43
148
|
|
package/dist/files.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Selection, ElementInfo } from '@nielspeter/eess';
|
|
2
|
+
export type { Selection, ElementInfo } from '@nielspeter/eess';
|
|
2
3
|
/**
|
|
3
4
|
* A file matched by [[files]]. Its content is **not** read — this is a
|
|
4
5
|
* path-selection brick. Callers that need the file's content (e.g. parse a
|
package/dist/files.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9D;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,6BAA6B;AAC7B,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IACzC,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,WAAW,CAAA;CACpD;AAoCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,CAgB9D"}
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAG9D,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9D;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,6BAA6B;AAC7B,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IACzC,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,WAAW,CAAA;CACpD;AAoCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,CAgB9D"}
|
package/dist/files.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,SAAS,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,SAAS,MAAM,WAAW,CAAA;AAgCjC,+EAA+E;AAC/E,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,cAAc;IACd,MAAM;IACN,MAAM;IACN,UAAU;IACV,SAAS;IACT,OAAO;IACP,SAAS;CACV,CAAC,CAAA;AAEF,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,IAAY,EAAE,GAAa;IACpD,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,KAAK,GAAG,CAAA,CAAC,wEAAwE;QACjF,OAAM;IACR,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;QAC7B,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACpB,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAC7C,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;QACtB,CAAC;aAAM,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,KAAK,CAAC,IAAkB;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAA;IACtC,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IAErB,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1E,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IACpC,MAAM,aAAa,GACjB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAA;IAEnF,MAAM,QAAQ,GAAgB,GAAG;SAC9B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;SACxD,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAE1D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;AACjE,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { type ArchViolation, type PresetReportOptions } from '@nielspeter/eess';
|
|
2
|
+
import { type ArchProject } from '@nielspeter/eess-ts';
|
|
3
|
+
import type { FeatureSet, GherkinScenario } from '@nielspeter/eess-gherkin';
|
|
4
|
+
export { finishPreset } from '@nielspeter/eess';
|
|
5
|
+
export type { ArchViolation, PresetReportOptions } from '@nielspeter/eess';
|
|
6
|
+
/**
|
|
7
|
+
* Custom citation extractor — receives one `it('…')` title and returns the
|
|
8
|
+
* scenario it cites, or `undefined` if the title is not a citation. Shared by
|
|
9
|
+
* every gherkin-ts export that reads citations (plan 0145; previously three
|
|
10
|
+
* copies of the same inline signature).
|
|
11
|
+
*/
|
|
12
|
+
export type TestCitationExtractor = (itTitle: string) => ExtractedTestCitation | undefined;
|
|
13
|
+
export interface ScenarioTestsResolveOptions extends PresetReportOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Custom citation extractor for transition periods. Default: the frozen
|
|
16
|
+
* convention adapted to a single string — `` it('<path>.feature › <Scenario
|
|
17
|
+
* title>') `` (plan 0080).
|
|
18
|
+
*/
|
|
19
|
+
readonly extract?: TestCitationExtractor;
|
|
20
|
+
}
|
|
21
|
+
export interface ScenariosCoveredOptions extends PresetReportOptions {
|
|
22
|
+
/** Custom citation extractor — same contract as {@link ScenarioTestsResolveOptions.extract}. */
|
|
23
|
+
readonly extract?: TestCitationExtractor;
|
|
24
|
+
/**
|
|
25
|
+
* Require coverage only for scenarios matching this predicate — the opt-in
|
|
26
|
+
* scope. Default: every scenario. Use it to exclude un-implemented flows,
|
|
27
|
+
* e.g. `(s) => !s.tags.includes('wip')`.
|
|
28
|
+
*/
|
|
29
|
+
readonly include?: (scenario: GherkinScenario) => boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface ExtractedTestCitation {
|
|
32
|
+
/** The cited feature path, as written (may be a unique suffix). */
|
|
33
|
+
readonly path: string;
|
|
34
|
+
/** The cited scenario title. */
|
|
35
|
+
readonly title: string;
|
|
36
|
+
}
|
|
37
|
+
/** Where one `it('…')` citation lives — exported (plan 0145) so a consumer
|
|
38
|
+
* can report a citation's own location, not just that one exists. */
|
|
39
|
+
export interface TestCitationSite {
|
|
40
|
+
readonly title: string;
|
|
41
|
+
readonly file: string;
|
|
42
|
+
readonly line: number;
|
|
43
|
+
}
|
|
44
|
+
/** The default `it()`-title convention: `<path>.feature › <title>`. */
|
|
45
|
+
declare function defaultExtract(itTitle: string): ExtractedTestCitation | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Cross-validate that every scenario citation in the *test* AST resolves against
|
|
48
|
+
* the loaded feature set — the mirror image of `scenarioCitationsResolve`, whose
|
|
49
|
+
* left side is the markdown corpus; here it is the project's `it('…')` titles.
|
|
50
|
+
* This is the code↔spec half plan 0069 deferred ("this one is spec↔spec only").
|
|
51
|
+
*
|
|
52
|
+
* A citation is an `it()` whose title matches the convention `<path>.feature ›
|
|
53
|
+
* <Scenario title>` (overridable via `extract`). Three failure modes are gated:
|
|
54
|
+
* the cited feature file doesn't exist in the set, the path is ambiguous
|
|
55
|
+
* (matches several files), or the cited scenario title doesn't exist in that
|
|
56
|
+
* file. A test whose title is not a citation is ignored.
|
|
57
|
+
*
|
|
58
|
+
* Resolves a citation; it does NOT claim the test exercises the scenario's
|
|
59
|
+
* steps — that is Tier 2, still open (plan 0079).
|
|
60
|
+
*/
|
|
61
|
+
export declare function scenarioTestsResolve(project: ArchProject, set: FeatureSet, options?: ScenarioTestsResolveOptions): ArchViolation[];
|
|
62
|
+
/**
|
|
63
|
+
* Every test citation, keyed by the scenario it cites (`relPath title`) —
|
|
64
|
+
* exported (plan 0145) so a consumer can report where a citation lives, not
|
|
65
|
+
* just that one exists. Ambiguous citations (matching more than one feature
|
|
66
|
+
* file) are excluded, same as the prior `citedScenarioKeys`'s behavior. If
|
|
67
|
+
* two tests cite the same scenario, the map keeps one of them (which one is
|
|
68
|
+
* unspecified) — enough to point an author at *a* citing test, which is all
|
|
69
|
+
* any consumer here needs.
|
|
70
|
+
*/
|
|
71
|
+
export declare function citedScenarioSites(project: ArchProject, set: FeatureSet, extract: TestCitationExtractor): Map<string, TestCitationSite>;
|
|
72
|
+
/**
|
|
73
|
+
* Cross-validate that every in-scope scenario is cited by at least one test —
|
|
74
|
+
* the coverage (right→left) direction, the complement of `scenarioTestsResolve`.
|
|
75
|
+
* A scenario shipped with no citing test fails; `include` narrows the scope so
|
|
76
|
+
* `@wip` / un-implemented flows do not force a red build.
|
|
77
|
+
*
|
|
78
|
+
* Assumes scenario titles are unique within a file — coverage keys on
|
|
79
|
+
* `relPath + title`, so two identically-titled scenarios share one key and
|
|
80
|
+
* citing one marks its twin covered. Pair with eess-gherkin's `haveUniqueTitles`
|
|
81
|
+
* to close that gap.
|
|
82
|
+
*
|
|
83
|
+
* Coverage means "a test cites this scenario", not "a test exercises its steps"
|
|
84
|
+
* (Tier 2, still open — plan 0079).
|
|
85
|
+
*/
|
|
86
|
+
export declare function scenariosCovered(project: ArchProject, set: FeatureSet, options?: ScenariosCoveredOptions): ArchViolation[];
|
|
87
|
+
export interface ScenarioExemptionsCurrentOptions extends PresetReportOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Which scenarios are currently exempt from the coverage requirement.
|
|
90
|
+
* Required — no default, unlike `scenariosCovered`'s `include`: the two
|
|
91
|
+
* options must never be able to silently disagree about the same tag.
|
|
92
|
+
* Found in proposal 005's third review round — if both defaulted to
|
|
93
|
+
* `@wip`, a `@wip` scenario would be simultaneously required to be cited
|
|
94
|
+
* (`scenariosCovered`, default `include`) and required to be uncited
|
|
95
|
+
* (this export, a hypothetical default `isExempt`), unconditionally.
|
|
96
|
+
* There is no default under which the pair is not self-contradictory, so
|
|
97
|
+
* there is no default at all — the caller states the tag explicitly,
|
|
98
|
+
* e.g. `(s) => s.tags.includes('wip')`, paired with the matching
|
|
99
|
+
* `scenariosCovered({ include: (s) => !s.tags.includes('wip') })`.
|
|
100
|
+
*/
|
|
101
|
+
readonly isExempt: (scenario: GherkinScenario) => boolean;
|
|
102
|
+
/** Custom citation extractor — same contract as the siblings' `extract`. */
|
|
103
|
+
readonly extract?: TestCitationExtractor;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Cross-validate that no scenario currently exempted (via `isExempt`) already
|
|
107
|
+
* has a real citing test — the complement of `scenariosCovered`: that gate
|
|
108
|
+
* proves a non-exempt scenario IS cited; this one proves an exempt scenario
|
|
109
|
+
* is NOT YET cited. An exemption that outlives its reason is a silent hole
|
|
110
|
+
* in the coverage gate it was meant to narrow (proposal 005).
|
|
111
|
+
*
|
|
112
|
+
* A citation from a `.skip`-modified test still counts as "cites it," same
|
|
113
|
+
* as `scenariosCovered`'s own treatment (`itTitles` binds a citation; it
|
|
114
|
+
* does not require the test to run) — consistency across the three
|
|
115
|
+
* gherkin-ts gates is worth more than a bespoke carve-out here. A caller
|
|
116
|
+
* who wants a skipped-placeholder citation to NOT trigger staleness narrows
|
|
117
|
+
* `isExempt` to exclude it (or tags it `@wip @tracked` and narrows on that).
|
|
118
|
+
*/
|
|
119
|
+
export declare function scenarioExemptionsCurrent(project: ArchProject, set: FeatureSet, options: ScenarioExemptionsCurrentOptions): ArchViolation[];
|
|
120
|
+
/** Count citing tests / scenarios for a caller's non-vacuity summary line. */
|
|
121
|
+
export declare function scenarioTestStats(project: ArchProject, set: FeatureSet, options?: ScenarioTestsResolveOptions): {
|
|
122
|
+
citations: number;
|
|
123
|
+
scenarios: number;
|
|
124
|
+
};
|
|
125
|
+
export { defaultExtract };
|
|
126
|
+
//# sourceMappingURL=gherkin-ts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gherkin-ts.d.ts","sourceRoot":"","sources":["../src/gherkin-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAS,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAK3E,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,qBAAqB,GAAG,SAAS,CAAA;AAE1F,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAA;CACzC;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAA;IACxC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAA;CAC1D;AAED,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;qEACqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAQD,uEAAuE;AACvE,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAM1E;AA+CD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,2BAAgC,GACxC,aAAa,EAAE,CA0CjB;AAcD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,qBAAqB,GAC7B,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAU/B;AAWD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,uBAA4B,GACpC,aAAa,EAAE,CAgBjB;AAED,MAAM,WAAW,gCAAiC,SAAQ,mBAAmB;IAC3E;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAA;IACzD,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAA;CACzC;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,gCAAgC,GACxC,aAAa,EAAE,CA2BjB;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,2BAAgC,GACxC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAM1C;AAGD,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { finishPreset } from '@nielspeter/eess';
|
|
2
|
+
import { calls } from '@nielspeter/eess-ts';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { itOrTestTitleOf } from './it-title.js';
|
|
5
|
+
// Kernel re-exports (plan 0089 — standalone sufficiency): see mermaid-ts.ts.
|
|
6
|
+
export { finishPreset } from '@nielspeter/eess';
|
|
7
|
+
// The gherkin↔ts citation convention (plan 0080): a test names the scenario it
|
|
8
|
+
// proves in its `it()` title — a feature path (unique `/`-boundary suffix, like
|
|
9
|
+
// md↔gherkin) then the scenario title, separated by `›` or `·`.
|
|
10
|
+
const IT_CITE_RE = /^(?<path>.*\.feature)\s*[›·]\s*(?<title>.+)$/;
|
|
11
|
+
const RULE = 'tests that cite a scenario should cite one that exists';
|
|
12
|
+
/** The default `it()`-title convention: `<path>.feature › <title>`. */
|
|
13
|
+
function defaultExtract(itTitle) {
|
|
14
|
+
const m = IT_CITE_RE.exec(itTitle);
|
|
15
|
+
const path = m?.groups?.path;
|
|
16
|
+
const title = m?.groups?.title;
|
|
17
|
+
if (path === undefined || title === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
return { path, title };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Read every `it('…')` title from the project via eess-ts's public call API —
|
|
23
|
+
* no ts-morph here, per ADR-007, exactly as `adrCitationsResolve` does. Sees
|
|
24
|
+
* `` it(`no-substitution template`) `` titles a source regex would miss. The
|
|
25
|
+
* title grammar itself lives in `it-title.ts`, shared with md↔ts (bug 0104).
|
|
26
|
+
*/
|
|
27
|
+
function itTitles(project) {
|
|
28
|
+
const allCalls = calls(project).select({
|
|
29
|
+
label: 'call',
|
|
30
|
+
identify: (c) => ({ name: c.getName() ?? '' }),
|
|
31
|
+
}).elements;
|
|
32
|
+
const out = [];
|
|
33
|
+
for (const call of allCalls) {
|
|
34
|
+
// Accept `it(...)` / `test(...)` and their modifier forms (`it.only`,
|
|
35
|
+
// `it.skip`, `test.concurrent`, …) — the root callee is what matters, not
|
|
36
|
+
// the modifier. The gate binds a citation, it does not run the test, so a
|
|
37
|
+
// skipped test's citation is still checked (consistent with "cites, not
|
|
38
|
+
// exercises"). `it.each(table)(...)` is a call-of-a-call with a templated
|
|
39
|
+
// `%s` title — no static citation — so `root` is undefined and it is skipped.
|
|
40
|
+
const root = call.getObjectName() ?? call.getMethodName();
|
|
41
|
+
if (root !== 'it' && root !== 'test')
|
|
42
|
+
continue;
|
|
43
|
+
const title = itOrTestTitleOf(call.getName({ withArgument: 0 }) ?? '');
|
|
44
|
+
if (title === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
out.push({ title, file: call.getSourceFile().getFilePath(), line: call.getStartLineNumber() });
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/** Resolve a cited path against the set: exact relPath, or unique `/`-boundary suffix. */
|
|
51
|
+
function resolveFeature(path, set) {
|
|
52
|
+
const all = set.features().map((f) => f.relPath);
|
|
53
|
+
if (all.includes(path))
|
|
54
|
+
return [path];
|
|
55
|
+
return all.filter((rel) => rel.endsWith(`/${path}`));
|
|
56
|
+
}
|
|
57
|
+
const v = (site, message, because) => ({
|
|
58
|
+
rule: RULE,
|
|
59
|
+
ruleId: 'crossval/scenario-tests-resolve',
|
|
60
|
+
element: `${site.file}:${site.line}`,
|
|
61
|
+
file: site.file,
|
|
62
|
+
line: site.line,
|
|
63
|
+
message,
|
|
64
|
+
because,
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Cross-validate that every scenario citation in the *test* AST resolves against
|
|
68
|
+
* the loaded feature set — the mirror image of `scenarioCitationsResolve`, whose
|
|
69
|
+
* left side is the markdown corpus; here it is the project's `it('…')` titles.
|
|
70
|
+
* This is the code↔spec half plan 0069 deferred ("this one is spec↔spec only").
|
|
71
|
+
*
|
|
72
|
+
* A citation is an `it()` whose title matches the convention `<path>.feature ›
|
|
73
|
+
* <Scenario title>` (overridable via `extract`). Three failure modes are gated:
|
|
74
|
+
* the cited feature file doesn't exist in the set, the path is ambiguous
|
|
75
|
+
* (matches several files), or the cited scenario title doesn't exist in that
|
|
76
|
+
* file. A test whose title is not a citation is ignored.
|
|
77
|
+
*
|
|
78
|
+
* Resolves a citation; it does NOT claim the test exercises the scenario's
|
|
79
|
+
* steps — that is Tier 2, still open (plan 0079).
|
|
80
|
+
*/
|
|
81
|
+
export function scenarioTestsResolve(project, set, options = {}) {
|
|
82
|
+
const extract = options.extract ?? defaultExtract;
|
|
83
|
+
const scenarioKeys = new Set(set.scenarios().map((s) => `${s.relPath} ${s.title}`));
|
|
84
|
+
const violations = [];
|
|
85
|
+
for (const site of itTitles(project)) {
|
|
86
|
+
const cite = extract(site.title);
|
|
87
|
+
if (cite === undefined)
|
|
88
|
+
continue; // not a scenario-citing test
|
|
89
|
+
const resolved = resolveFeature(cite.path, set);
|
|
90
|
+
if (resolved.length === 0) {
|
|
91
|
+
violations.push(v(site, `cites \`${cite.path}\` — no such feature file in the set`, 'a test citing a missing behavior spec is a dangling reference'));
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (resolved.length > 1) {
|
|
95
|
+
violations.push(v(site, `cites \`${cite.path}\` — ambiguous, matches ${resolved.length} feature files (${resolved.join(', ')})`, 'an ambiguous citation cannot be mechanically resolved; cite a longer suffix'));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const rel = resolved[0];
|
|
99
|
+
if (rel !== undefined && !scenarioKeys.has(`${rel} ${cite.title}`)) {
|
|
100
|
+
violations.push(v(site, `cites '${cite.title}' in \`${rel}\` — no such scenario in that feature file`, 'a renamed or deleted scenario must not silently orphan the test that proves it'));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return finishPreset(violations, options);
|
|
104
|
+
}
|
|
105
|
+
const COVER_RULE = 'every scenario should be proven by a citing test';
|
|
106
|
+
const sv = (scenario, message, because) => ({
|
|
107
|
+
rule: COVER_RULE,
|
|
108
|
+
ruleId: 'crossval/scenarios-covered',
|
|
109
|
+
element: `${scenario.relPath} › ${scenario.title}`,
|
|
110
|
+
file: scenario.file,
|
|
111
|
+
line: scenario.line,
|
|
112
|
+
message,
|
|
113
|
+
because,
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* Every test citation, keyed by the scenario it cites (`relPath title`) —
|
|
117
|
+
* exported (plan 0145) so a consumer can report where a citation lives, not
|
|
118
|
+
* just that one exists. Ambiguous citations (matching more than one feature
|
|
119
|
+
* file) are excluded, same as the prior `citedScenarioKeys`'s behavior. If
|
|
120
|
+
* two tests cite the same scenario, the map keeps one of them (which one is
|
|
121
|
+
* unspecified) — enough to point an author at *a* citing test, which is all
|
|
122
|
+
* any consumer here needs.
|
|
123
|
+
*/
|
|
124
|
+
export function citedScenarioSites(project, set, extract) {
|
|
125
|
+
const sites = new Map();
|
|
126
|
+
for (const site of itTitles(project)) {
|
|
127
|
+
const cite = extract(site.title);
|
|
128
|
+
if (cite === undefined)
|
|
129
|
+
continue;
|
|
130
|
+
const resolved = resolveFeature(cite.path, set);
|
|
131
|
+
const rel = resolved.length === 1 ? resolved[0] : undefined;
|
|
132
|
+
if (rel !== undefined)
|
|
133
|
+
sites.set(`${rel} ${cite.title}`, site);
|
|
134
|
+
}
|
|
135
|
+
return sites;
|
|
136
|
+
}
|
|
137
|
+
/** The set of `relPath title` keys a test unambiguously cites in the project. */
|
|
138
|
+
function citedScenarioKeys(project, set, extract) {
|
|
139
|
+
return new Set(citedScenarioSites(project, set, extract).keys());
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Cross-validate that every in-scope scenario is cited by at least one test —
|
|
143
|
+
* the coverage (right→left) direction, the complement of `scenarioTestsResolve`.
|
|
144
|
+
* A scenario shipped with no citing test fails; `include` narrows the scope so
|
|
145
|
+
* `@wip` / un-implemented flows do not force a red build.
|
|
146
|
+
*
|
|
147
|
+
* Assumes scenario titles are unique within a file — coverage keys on
|
|
148
|
+
* `relPath + title`, so two identically-titled scenarios share one key and
|
|
149
|
+
* citing one marks its twin covered. Pair with eess-gherkin's `haveUniqueTitles`
|
|
150
|
+
* to close that gap.
|
|
151
|
+
*
|
|
152
|
+
* Coverage means "a test cites this scenario", not "a test exercises its steps"
|
|
153
|
+
* (Tier 2, still open — plan 0079).
|
|
154
|
+
*/
|
|
155
|
+
export function scenariosCovered(project, set, options = {}) {
|
|
156
|
+
const extract = options.extract ?? defaultExtract;
|
|
157
|
+
const include = options.include ?? (() => true);
|
|
158
|
+
const covered = citedScenarioKeys(project, set, extract);
|
|
159
|
+
const violations = set
|
|
160
|
+
.scenarios()
|
|
161
|
+
.filter(include)
|
|
162
|
+
.filter((s) => !covered.has(`${s.relPath} ${s.title}`))
|
|
163
|
+
.map((s) => sv(s, 'no test cites this scenario', 'an unproven use-case flow is a spec with no gate behind it'));
|
|
164
|
+
return finishPreset(violations, options);
|
|
165
|
+
}
|
|
166
|
+
const EXEMPTION_RULE = 'an exempt scenario should have its exemption removed once a test cites it';
|
|
167
|
+
/**
|
|
168
|
+
* Cross-validate that no scenario currently exempted (via `isExempt`) already
|
|
169
|
+
* has a real citing test — the complement of `scenariosCovered`: that gate
|
|
170
|
+
* proves a non-exempt scenario IS cited; this one proves an exempt scenario
|
|
171
|
+
* is NOT YET cited. An exemption that outlives its reason is a silent hole
|
|
172
|
+
* in the coverage gate it was meant to narrow (proposal 005).
|
|
173
|
+
*
|
|
174
|
+
* A citation from a `.skip`-modified test still counts as "cites it," same
|
|
175
|
+
* as `scenariosCovered`'s own treatment (`itTitles` binds a citation; it
|
|
176
|
+
* does not require the test to run) — consistency across the three
|
|
177
|
+
* gherkin-ts gates is worth more than a bespoke carve-out here. A caller
|
|
178
|
+
* who wants a skipped-placeholder citation to NOT trigger staleness narrows
|
|
179
|
+
* `isExempt` to exclude it (or tags it `@wip @tracked` and narrows on that).
|
|
180
|
+
*/
|
|
181
|
+
export function scenarioExemptionsCurrent(project, set, options) {
|
|
182
|
+
const extract = options.extract ?? defaultExtract;
|
|
183
|
+
const sites = citedScenarioSites(project, set, extract);
|
|
184
|
+
const violations = set
|
|
185
|
+
.scenarios()
|
|
186
|
+
.filter((s) => options.isExempt(s))
|
|
187
|
+
.flatMap((s) => {
|
|
188
|
+
const site = sites.get(`${s.relPath} ${s.title}`);
|
|
189
|
+
if (site === undefined)
|
|
190
|
+
return [];
|
|
191
|
+
const citedAt = `${path.relative(process.cwd(), site.file)}:${String(site.line)}`;
|
|
192
|
+
return [
|
|
193
|
+
{
|
|
194
|
+
rule: EXEMPTION_RULE,
|
|
195
|
+
ruleId: 'crossval/scenario-exemption-stale',
|
|
196
|
+
element: `${s.relPath} › ${s.title}`,
|
|
197
|
+
file: s.file,
|
|
198
|
+
line: s.line,
|
|
199
|
+
message: `scenario "${s.title}" is exempt but ${citedAt} already cites it`,
|
|
200
|
+
because: 'an exemption that has outlived its reason is a silent hole in the coverage gate',
|
|
201
|
+
suggestion: 'if the scenario is genuinely done, remove the exempting tag; if the exemption is ' +
|
|
202
|
+
'still intentional (flaky, partial, tracked elsewhere), narrow isExempt to exclude it',
|
|
203
|
+
},
|
|
204
|
+
];
|
|
205
|
+
});
|
|
206
|
+
return finishPreset(violations, options);
|
|
207
|
+
}
|
|
208
|
+
/** Count citing tests / scenarios for a caller's non-vacuity summary line. */
|
|
209
|
+
export function scenarioTestStats(project, set, options = {}) {
|
|
210
|
+
const extract = options.extract ?? defaultExtract;
|
|
211
|
+
return {
|
|
212
|
+
citations: itTitles(project).filter((s) => extract(s.title) !== undefined).length,
|
|
213
|
+
scenarios: set.scenarios().length,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// Referenced by tests to keep the default convention itself under test.
|
|
217
|
+
export { defaultExtract };
|
|
218
|
+
//# sourceMappingURL=gherkin-ts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gherkin-ts.js","sourceRoot":"","sources":["../src/gherkin-ts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `it('…')` title grammar for this package — one definition, because both of
|
|
3
|
+
* its presets read it. Not the family's only copy: `eess-md`'s `adr.ts` carries a
|
|
4
|
+
* third, on the same ADR-citation contract, and cannot import this one (the
|
|
5
|
+
* dependency runs crossvalidate → md, and `eess/md-isolated` forbids the
|
|
6
|
+
* reverse). See bug 0111 for that, and 0114 for why the grammar arguably belongs
|
|
7
|
+
* behind eess-ts's engine boundary rather than here at all.
|
|
8
|
+
*
|
|
9
|
+
* `md-ts` (ADR citations) and `gherkin-ts` (scenario citations) both have to
|
|
10
|
+
* recover the title a test declares from source text, and both got it wrong the
|
|
11
|
+
* same way: `['"`]([^'"`]+)['"`]` ends the capture at **any** quote character,
|
|
12
|
+
* not at the one that opened the string. A character class cannot express "up to
|
|
13
|
+
* the *matching* delimiter" — the opening quote is matched but never captured,
|
|
14
|
+
* so the closing side has no way to require the same character.
|
|
15
|
+
*
|
|
16
|
+
* The cost is bug 0104, a false green: a single-quoted title containing a
|
|
17
|
+
* backtick — the ordinary way to name a symbol in prose, and this repo's own
|
|
18
|
+
* house style — truncated at that backtick, so
|
|
19
|
+
*
|
|
20
|
+
* it('catches `HACK` inside a body') ─┐
|
|
21
|
+
* it('catches `any` in a return position') ┴─→ both key on `catches `
|
|
22
|
+
*
|
|
23
|
+
* collapsed onto one key. Because the markdown side truncated identically, a
|
|
24
|
+
* citation to a test that had been renamed away still resolved — against a
|
|
25
|
+
* *different* test that happened to share the truncated prefix. The gate passed
|
|
26
|
+
* over exactly the drift it exists to catch.
|
|
27
|
+
*
|
|
28
|
+
* Capturing the delimiter as `q` and back-referencing it fixes both halves at
|
|
29
|
+
* once; the `\\.` alternative keeps an escaped delimiter inside the title.
|
|
30
|
+
*
|
|
31
|
+
* Titles are compared as **raw source text**, so `it('it\'s fine')` keys on
|
|
32
|
+
* `it\'s fine`, backslash included. That is a deliberate consequence of reading
|
|
33
|
+
* one grammar on both sides: an ADR cites what is written in the test file, not
|
|
34
|
+
* what the string evaluates to, and both sides read it identically.
|
|
35
|
+
*
|
|
36
|
+
* That has a cost worth knowing before you write a citation: a title's raw text
|
|
37
|
+
* is **prettier's to change**. `it("say 'hi' to \"them\"")` is reformatted to
|
|
38
|
+
* `it('say \'hi\' to "them"')` — same string, different source, different key —
|
|
39
|
+
* while the ADR's citation sits in a markdown code span prettier will not touch.
|
|
40
|
+
* A correct citation can go red after a routine `npm run format`. It fails loud
|
|
41
|
+
* rather than silent, which is the right direction, but prefer a title that
|
|
42
|
+
* needs no escaping at all.
|
|
43
|
+
*
|
|
44
|
+
* ## Two input classes, two grammars
|
|
45
|
+
*
|
|
46
|
+
* The anchored readers are handed an enriched call name built from ts-morph's
|
|
47
|
+
* `getText()` — guaranteed-valid TypeScript, where a `\` is always an escape and
|
|
48
|
+
* the delimiters always balance. `citedItTitles` reads **arbitrary prose** from
|
|
49
|
+
* a table cell, where neither holds. Sharing one permissive grammar across both
|
|
50
|
+
* cost a real regression, caught in review before this shipped: given a cell
|
|
51
|
+
* holding a malformed citation followed by a good one,
|
|
52
|
+
*
|
|
53
|
+
* `it('first` and `it('second')`
|
|
54
|
+
*
|
|
55
|
+
* the permissive body ran past the second citation's opening quote and closed
|
|
56
|
+
* there — yielding one bogus key and **dropping a real citation from the check
|
|
57
|
+
* entirely**. A citation nobody checks is the same false green this module was
|
|
58
|
+
* written to remove. So the prose variant is tempered: it cannot cross a line,
|
|
59
|
+
* and it cannot swallow the start of another citation.
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* The title in an enriched call name like `it('does a thing')`, or `undefined`
|
|
63
|
+
* if the argument is not a literal string. Accepts modifier forms (`it.skip`,
|
|
64
|
+
* `it.only`) — whether a *definition* in one of those forms counts is the
|
|
65
|
+
* caller's call, made by the callee filter above this.
|
|
66
|
+
*/
|
|
67
|
+
export declare function itTitleOf(enriched: string): string | undefined;
|
|
68
|
+
/** As {@link itTitleOf}, also accepting the `test` alias — gherkin↔ts's convention. */
|
|
69
|
+
export declare function itOrTestTitleOf(enriched: string): string | undefined;
|
|
70
|
+
/** Every `it('…')` title cited inside a fragment of prose, in order. */
|
|
71
|
+
export declare function citedItTitles(text: string): string[];
|
|
72
|
+
//# sourceMappingURL=it-title.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"it-title.d.ts","sourceRoot":"","sources":["../src/it-title.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAwCH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9D;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOpD"}
|
package/dist/it-title.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `it('…')` title grammar for this package — one definition, because both of
|
|
3
|
+
* its presets read it. Not the family's only copy: `eess-md`'s `adr.ts` carries a
|
|
4
|
+
* third, on the same ADR-citation contract, and cannot import this one (the
|
|
5
|
+
* dependency runs crossvalidate → md, and `eess/md-isolated` forbids the
|
|
6
|
+
* reverse). See bug 0111 for that, and 0114 for why the grammar arguably belongs
|
|
7
|
+
* behind eess-ts's engine boundary rather than here at all.
|
|
8
|
+
*
|
|
9
|
+
* `md-ts` (ADR citations) and `gherkin-ts` (scenario citations) both have to
|
|
10
|
+
* recover the title a test declares from source text, and both got it wrong the
|
|
11
|
+
* same way: `['"`]([^'"`]+)['"`]` ends the capture at **any** quote character,
|
|
12
|
+
* not at the one that opened the string. A character class cannot express "up to
|
|
13
|
+
* the *matching* delimiter" — the opening quote is matched but never captured,
|
|
14
|
+
* so the closing side has no way to require the same character.
|
|
15
|
+
*
|
|
16
|
+
* The cost is bug 0104, a false green: a single-quoted title containing a
|
|
17
|
+
* backtick — the ordinary way to name a symbol in prose, and this repo's own
|
|
18
|
+
* house style — truncated at that backtick, so
|
|
19
|
+
*
|
|
20
|
+
* it('catches `HACK` inside a body') ─┐
|
|
21
|
+
* it('catches `any` in a return position') ┴─→ both key on `catches `
|
|
22
|
+
*
|
|
23
|
+
* collapsed onto one key. Because the markdown side truncated identically, a
|
|
24
|
+
* citation to a test that had been renamed away still resolved — against a
|
|
25
|
+
* *different* test that happened to share the truncated prefix. The gate passed
|
|
26
|
+
* over exactly the drift it exists to catch.
|
|
27
|
+
*
|
|
28
|
+
* Capturing the delimiter as `q` and back-referencing it fixes both halves at
|
|
29
|
+
* once; the `\\.` alternative keeps an escaped delimiter inside the title.
|
|
30
|
+
*
|
|
31
|
+
* Titles are compared as **raw source text**, so `it('it\'s fine')` keys on
|
|
32
|
+
* `it\'s fine`, backslash included. That is a deliberate consequence of reading
|
|
33
|
+
* one grammar on both sides: an ADR cites what is written in the test file, not
|
|
34
|
+
* what the string evaluates to, and both sides read it identically.
|
|
35
|
+
*
|
|
36
|
+
* That has a cost worth knowing before you write a citation: a title's raw text
|
|
37
|
+
* is **prettier's to change**. `it("say 'hi' to \"them\"")` is reformatted to
|
|
38
|
+
* `it('say \'hi\' to "them"')` — same string, different source, different key —
|
|
39
|
+
* while the ADR's citation sits in a markdown code span prettier will not touch.
|
|
40
|
+
* A correct citation can go red after a routine `npm run format`. It fails loud
|
|
41
|
+
* rather than silent, which is the right direction, but prefer a title that
|
|
42
|
+
* needs no escaping at all.
|
|
43
|
+
*
|
|
44
|
+
* ## Two input classes, two grammars
|
|
45
|
+
*
|
|
46
|
+
* The anchored readers are handed an enriched call name built from ts-morph's
|
|
47
|
+
* `getText()` — guaranteed-valid TypeScript, where a `\` is always an escape and
|
|
48
|
+
* the delimiters always balance. `citedItTitles` reads **arbitrary prose** from
|
|
49
|
+
* a table cell, where neither holds. Sharing one permissive grammar across both
|
|
50
|
+
* cost a real regression, caught in review before this shipped: given a cell
|
|
51
|
+
* holding a malformed citation followed by a good one,
|
|
52
|
+
*
|
|
53
|
+
* `it('first` and `it('second')`
|
|
54
|
+
*
|
|
55
|
+
* the permissive body ran past the second citation's opening quote and closed
|
|
56
|
+
* there — yielding one bogus key and **dropping a real citation from the check
|
|
57
|
+
* entirely**. A citation nobody checks is the same false green this module was
|
|
58
|
+
* written to remove. So the prose variant is tempered: it cannot cross a line,
|
|
59
|
+
* and it cannot swallow the start of another citation.
|
|
60
|
+
*/
|
|
61
|
+
/** The opening of a citation: `it(`, `it.skip(`, … up to and including its quote. */
|
|
62
|
+
const IT_OPEN = `it(?:\\.\\w+)?\\(\\s*['"\`]`;
|
|
63
|
+
/**
|
|
64
|
+
* A quoted string whose closing delimiter must match its opening one — group `q`
|
|
65
|
+
* is the delimiter, group `title` the payload. `body` is what may sit between
|
|
66
|
+
* them; the two alternatives have disjoint first characters (`\\.` starts with a
|
|
67
|
+
* backslash, the other excludes it), so the alternation is deterministic and the
|
|
68
|
+
* `+` cannot fork — no backtracking blowup on a long unterminated title.
|
|
69
|
+
*/
|
|
70
|
+
const quoted = (body) => `(?<q>['"\`])(?<title>(?:\\\\.|${body})+)\\k<q>`;
|
|
71
|
+
/** Valid TypeScript source: anything but the delimiter that opened the string. */
|
|
72
|
+
const SOURCE_BODY = `(?!\\k<q>)[^\\\\]`;
|
|
73
|
+
/**
|
|
74
|
+
* Arbitrary prose: additionally refuses to cross a newline (a Mechanism cell is
|
|
75
|
+
* one line) or to consume the start of another citation, so one malformed
|
|
76
|
+
* citation cannot eat its neighbour. Tempering on the full opening — callee,
|
|
77
|
+
* paren *and* quote — keeps a title that merely mentions `it(x)` intact.
|
|
78
|
+
*/
|
|
79
|
+
const PROSE_BODY = `(?!\\k<q>)(?!${IT_OPEN})[^\\\\\\n]`;
|
|
80
|
+
/**
|
|
81
|
+
* `<callee>(` with an optional modifier — `it(`, `it.skip(`, `test.concurrent(`.
|
|
82
|
+
* The lookbehind is what keeps `submit('save')`, `emit('drift')` and `audit('x')`
|
|
83
|
+
* from reading as citations; it is redundant under `^` and load-bearing in prose.
|
|
84
|
+
*/
|
|
85
|
+
const CALL = (callee) => `(?<![\\w$.])(?:${callee})(?:\\.\\w+)?\\(\\s*`;
|
|
86
|
+
// Anchored: the input is an enriched call name produced by eess-ts's
|
|
87
|
+
// `getName({ withArgument: 0 })`, e.g. `it('does a thing')`.
|
|
88
|
+
const IT_TITLE = new RegExp(`^${CALL('it')}${quoted(SOURCE_BODY)}`);
|
|
89
|
+
const IT_OR_TEST_TITLE = new RegExp(`^${CALL('it|test')}${quoted(SOURCE_BODY)}`);
|
|
90
|
+
// Unanchored + global: citations are embedded in prose (an ADR's Mechanism cell).
|
|
91
|
+
const IT_CITATION = new RegExp(`${CALL('it')}${quoted(PROSE_BODY)}`, 'g');
|
|
92
|
+
/**
|
|
93
|
+
* The title in an enriched call name like `it('does a thing')`, or `undefined`
|
|
94
|
+
* if the argument is not a literal string. Accepts modifier forms (`it.skip`,
|
|
95
|
+
* `it.only`) — whether a *definition* in one of those forms counts is the
|
|
96
|
+
* caller's call, made by the callee filter above this.
|
|
97
|
+
*/
|
|
98
|
+
export function itTitleOf(enriched) {
|
|
99
|
+
return IT_TITLE.exec(enriched)?.groups?.title;
|
|
100
|
+
}
|
|
101
|
+
/** As {@link itTitleOf}, also accepting the `test` alias — gherkin↔ts's convention. */
|
|
102
|
+
export function itOrTestTitleOf(enriched) {
|
|
103
|
+
return IT_OR_TEST_TITLE.exec(enriched)?.groups?.title;
|
|
104
|
+
}
|
|
105
|
+
/** Every `it('…')` title cited inside a fragment of prose, in order. */
|
|
106
|
+
export function citedItTitles(text) {
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const m of text.matchAll(IT_CITATION)) {
|
|
109
|
+
const title = m.groups?.title;
|
|
110
|
+
if (title !== undefined)
|
|
111
|
+
out.push(title);
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=it-title.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"it-title.js","sourceRoot":"","sources":["../src/it-title.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAEH,qFAAqF;AACrF,MAAM,OAAO,GAAG,6BAA6B,CAAA;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,iCAAiC,IAAI,WAAW,CAAA;AAEzF,kFAAkF;AAClF,MAAM,WAAW,GAAG,mBAAmB,CAAA;AAEvC;;;;;GAKG;AACH,MAAM,UAAU,GAAG,gBAAgB,OAAO,aAAa,CAAA;AAEvD;;;;GAIG;AACH,MAAM,IAAI,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,kBAAkB,MAAM,sBAAsB,CAAA;AAEvF,qEAAqE;AACrE,6DAA6D;AAC7D,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;AACnE,MAAM,gBAAgB,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;AAEhF,kFAAkF;AAClF,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;AAEzE;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAA;AAC/C,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAA;AACvD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,CAAA;QAC7B,IAAI,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
package/dist/md-gherkin.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type ArchViolation, type PresetReportOptions } from '@nielspeter/eess';
|
|
2
2
|
import type { Corpus } from '@nielspeter/eess-md';
|
|
3
3
|
import type { FeatureSet } from '@nielspeter/eess-gherkin';
|
|
4
|
+
export { finishPreset } from '@nielspeter/eess';
|
|
5
|
+
export type { ArchViolation, PresetReportOptions } from '@nielspeter/eess';
|
|
4
6
|
export interface ScenarioCitationsResolveOptions extends PresetReportOptions {
|
|
5
7
|
/** Glob selecting the markdown documents to scan. Default `**` (whole corpus). */
|
|
6
8
|
readonly dir?: string;
|
package/dist/md-gherkin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-gherkin.d.ts","sourceRoot":"","sources":["../src/md-gherkin.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"md-gherkin.d.ts","sourceRoot":"","sources":["../src/md-gherkin.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAG1D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE1E,MAAM,WAAW,+BAAgC,SAAQ,mBAAmB;IAC1E,kFAAkF;IAClF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,iBAAiB,EAAE,CAAA;CAClE;AAED,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAaD,iBAAS,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAUzD;AA6CD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,+BAAoC,GAC5C,aAAa,EAAE,CA2CjB;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,+BAAoC,GAC5C;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAQ5D;AAGD,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
package/dist/md-gherkin.js
CHANGED
|
Binary file
|
package/dist/md-gherkin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-gherkin.js","sourceRoot":"","sources":["../src/md-gherkin.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,YAAY,EAAgD,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"md-gherkin.js","sourceRoot":"","sources":["../src/md-gherkin.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,YAAY,EAAgD,MAAM,kBAAkB,CAAA;AAI7F,6EAA6E;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AA2B/C,2EAA2E;AAC3E,4EAA4E;AAC5E,MAAM,eAAe,GAAG,uBAAuB,CAAA;AAC/C,MAAM,QAAQ,GAAG,wBAAwB,CAAA;AACzC,MAAM,IAAI,GAAG,oEAAoE,CAAA;AAEjF,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,GAAG,GAAwB,EAAE,CAAA;IACnC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACjB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAQ;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACtC,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,8EAA8E;AAC9E,+DAA+D;AAC/D,MAAM,QAAQ,GAAG,sBAAsB,CAAA;AACvC,SAAS,eAAe,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAC/E,CAAC;AAED,SAAS,gBAAgB,CACvB,MAAc,EACd,GAAW,EACX,OAAuD;IAEvD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,GAAG,GAAe,EAAE,CAAA;IAC1B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,SAAQ;QACjC,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,0FAA0F;AAC1F,SAAS,cAAc,CAAC,IAAY,EAAE,GAAe;IACnD,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAA;AACtD,CAAC;AAED,MAAM,CAAC,GAAG,CAAC,CAAW,EAAE,OAAe,EAAE,OAAe,EAAiB,EAAE,CAAC,CAAC;IAC3E,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,qCAAqC;IAC7C,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE;IACrC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI;IAChB,IAAI,EAAE,CAAC,CAAC,IAAI;IACZ,OAAO;IACP,OAAO;CACR,CAAC,CAAA;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAAc,EACd,GAAe,EACf,UAA2C,EAAE;IAE7C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAA;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,CAAA;IAEjD,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IACxD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACpF,MAAM,UAAU,GAAoB,EAAE,CAAA;IAEtC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,UAAU,CAAC,IAAI,CACb,CAAC,CACC,CAAC,EACD,WAAW,CAAC,CAAC,IAAI,sCAAsC,EACvD,oEAAoE,CACrE,CACF,CAAA;YACD,SAAQ;QACV,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CACb,CAAC,CACC,CAAC,EACD,WAAW,CAAC,CAAC,IAAI,2BAA2B,QAAQ,CAAC,MAAM,mBAAmB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EACpG,6EAA6E,CAC9E,CACF,CAAA;YACD,SAAQ;QACV,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;YAC1F,UAAU,CAAC,IAAI,CACb,CAAC,CACC,CAAC,EACD,UAAU,CAAC,CAAC,KAAK,UAAU,GAAG,4CAA4C,EAC1E,gFAAgF,CACjF,CACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;AAC1C,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,qBAAqB,CACnC,MAAc,EACd,GAAe,EACf,UAA2C,EAAE;IAE7C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAA;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,CAAA;IACjD,OAAO;QACL,SAAS,EAAE,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,MAAM;QACxD,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,MAAM;QAC/B,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,MAAM;KAClC,CAAA;AACH,CAAC;AAED,wEAAwE;AACxE,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
package/dist/md-mermaid-er.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ArchViolation, type PresetReportOptions } from '@nielspeter/eess';
|
|
2
2
|
import type { Corpus, MdDocument } from '@nielspeter/eess-md';
|
|
3
|
+
export { finishPreset } from '@nielspeter/eess';
|
|
4
|
+
export type { ArchViolation, PresetReportOptions } from '@nielspeter/eess';
|
|
3
5
|
export interface TableErAgreeOptions extends PresetReportOptions {
|
|
4
6
|
/** Glob selecting the documents to check. Default `**`. */
|
|
5
7
|
readonly docs?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-mermaid-er.d.ts","sourceRoot":"","sources":["../src/md-mermaid-er.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"md-mermaid-er.d.ts","sourceRoot":"","sources":["../src/md-mermaid-er.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAI7D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE1E,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IACD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,SAAS,CAAA;CACzD;AAoCD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa,EAAE,CAoG1F;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAiBxD"}
|
package/dist/md-mermaid-er.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import picomatch from 'picomatch';
|
|
2
2
|
import { finishPreset } from '@nielspeter/eess';
|
|
3
3
|
import { parseErDiagram, collectEntities } from '@nielspeter/eess-mermaid';
|
|
4
|
+
// Kernel re-exports (plan 0089 — standalone sufficiency): see mermaid-ts.ts.
|
|
5
|
+
export { finishPreset } from '@nielspeter/eess';
|
|
4
6
|
const RULE = 'entity property tables and their erDiagram should agree';
|
|
5
7
|
const ER_HEADER = /^\s*erDiagram\b/;
|
|
6
8
|
const v = (doc, line, message, because) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-mermaid-er.js","sourceRoot":"","sources":["../src/md-mermaid-er.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,YAAY,EAAgD,MAAM,kBAAkB,CAAA;AAE7F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAqB,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"md-mermaid-er.js","sourceRoot":"","sources":["../src/md-mermaid-er.ts"],"names":[],"mappings":"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"}
|
package/dist/md-mermaid.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type ArchViolation, type Direction, type PresetReportOptions } from '@nielspeter/eess';
|
|
2
2
|
import type { Corpus } from '@nielspeter/eess-md';
|
|
3
3
|
import { type ArchProject } from '@nielspeter/eess-ts';
|
|
4
|
+
export { correspondence, finishPreset } from '@nielspeter/eess';
|
|
5
|
+
export type { ArchViolation, Direction, PresetReportOptions } from '@nielspeter/eess';
|
|
4
6
|
export interface EmbeddedDiagramsMatchCodeOptions extends PresetReportOptions {
|
|
5
7
|
/** Glob (matched against a class's directory) restricting which TS classes participate. */
|
|
6
8
|
readonly scope?: string;
|
package/dist/md-mermaid.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-mermaid.d.ts","sourceRoot":"","sources":["../src/md-mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"md-mermaid.d.ts","sourceRoot":"","sources":["../src/md-mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAG5E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/D,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAErF,MAAM,WAAW,gCAAiC,SAAQ,mBAAmB;IAC3E,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,gCAAqC,GAC7C,aAAa,EAAE,CAoCjB"}
|
package/dist/md-mermaid.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { correspondence, finishPreset, } from '@nielspeter/eess';
|
|
2
2
|
import { diagram, classes as mmdClasses } from '@nielspeter/eess-mermaid';
|
|
3
3
|
import { classes as tsClasses } from '@nielspeter/eess-ts';
|
|
4
|
+
// Kernel re-exports (plan 0089 — standalone sufficiency): see mermaid-ts.ts.
|
|
5
|
+
export { correspondence, finishPreset } from '@nielspeter/eess';
|
|
4
6
|
/**
|
|
5
7
|
* Cross-validate Mermaid diagrams embedded as fenced ```mermaid blocks in the
|
|
6
8
|
* markdown corpus against TypeScript code — each embedded diagram is validated
|
package/dist/md-mermaid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-mermaid.js","sourceRoot":"","sources":["../src/md-mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,GAIb,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAoB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"md-mermaid.js","sourceRoot":"","sources":["../src/md-mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,GAIb,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAoB,MAAM,qBAAqB,CAAA;AAE5E,6EAA6E;AAC7E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAc/D;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAc,EACd,OAAoB,EACpB,UAA4C,EAAE;IAE9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAA;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,IAAI,eAAe,CAAA;IAEzD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC;SAC7B,IAAI,EAAE;SACN,cAAc,CAAC,KAAK,CAAC;SACrB,MAAM,CAAC;QACN,KAAK,EAAE,UAAU;QACjB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChB,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,aAAa;YAClC,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,WAAW,EAAE;YACrC,IAAI,EAAE,CAAC,CAAC,kBAAkB,EAAE;SAC7B,CAAC;KACH,CAAC,CAAA;IAEJ,MAAM,UAAU,GAAoB,EAAE,CAAA;IACtC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;QACrC,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;gBAAE,SAAQ;YACtC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBAChC,KAAK,EAAE,qBAAqB,GAAG,CAAC,OAAO,GAAG;gBAC1C,6EAA6E;gBAC7E,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;aACtE,CAAC,CAAA;YACF,UAAU,CAAC,IAAI,CACb,GAAG,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;iBAC/B,MAAM,EAAE;iBACR,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;iBACzB,IAAI,CAAC,EAAE,EAAE,EAAE,2BAA2B,EAAE,CAAC;iBACzC,UAAU,EAAE,CAChB,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;AAC1C,CAAC"}
|
package/dist/md-ts.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Corpus } from '@nielspeter/eess-md';
|
|
2
2
|
import { type ArchProject } from '@nielspeter/eess-ts';
|
|
3
|
+
export { correspondence } from '@nielspeter/eess';
|
|
4
|
+
export type { Selection } from '@nielspeter/eess';
|
|
3
5
|
export interface AdrCitationsResolveOptions {
|
|
4
6
|
/** Glob selecting ADR files. Default `docs/adr/**`. */
|
|
5
7
|
readonly dir?: string;
|
|
@@ -8,6 +10,16 @@ export interface AdrCitationsResolveOptions {
|
|
|
8
10
|
/** Header pattern locating the mechanism column. Default `/mechanism/i` — non-English corpora pass their own (e.g. `/mekanisme/i`). */
|
|
9
11
|
readonly mechanismColumn?: RegExp;
|
|
10
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Count what this preset would actually scan — the caller's non-vacuity guard.
|
|
15
|
+
* `adrCitationsResolve` reports OK when it resolves zero citations, so a drifted
|
|
16
|
+
* `dir` or `roots` reads exactly like a clean pass; a gate that prints this
|
|
17
|
+
* number can tell the two apart. Mirrors `scenarioTestStats` in gherkin↔ts.
|
|
18
|
+
*/
|
|
19
|
+
export declare function adrCitationStats(corpus: Corpus, options?: AdrCitationsResolveOptions): {
|
|
20
|
+
citations: number;
|
|
21
|
+
adrs: number;
|
|
22
|
+
};
|
|
11
23
|
/**
|
|
12
24
|
* Cross-validate that every `it('…')` cited in an ADR's enforcement table
|
|
13
25
|
* actually exists as a test in the project. The AST-grounded upgrade of the
|
package/dist/md-ts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-ts.d.ts","sourceRoot":"","sources":["../src/md-ts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAS,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"md-ts.d.ts","sourceRoot":"","sources":["../src/md-ts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAS,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAI7D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,MAAM,WAAW,0BAA0B;IACzC,uDAAuD;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAClC,uIAAuI;IACvI,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAClC;AA6CD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,0BAA+B,GACvC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAYrC;AAqCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,0BAA+B,GACvC,IAAI,CA8CN"}
|
package/dist/md-ts.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import picomatch from 'picomatch';
|
|
2
2
|
import { correspondence } from '@nielspeter/eess';
|
|
3
3
|
import { calls } from '@nielspeter/eess-ts';
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
|
|
4
|
+
import { citedItTitles, itTitleOf } from './it-title.js';
|
|
5
|
+
// Kernel re-exports (plan 0089 — standalone sufficiency): see mermaid-ts.ts.
|
|
6
|
+
export { correspondence } from '@nielspeter/eess';
|
|
7
7
|
function matchName(value, name) {
|
|
8
8
|
return typeof name === 'string' ? value === name : name.test(value);
|
|
9
9
|
}
|
|
@@ -23,15 +23,32 @@ function extractCitations(opts) {
|
|
|
23
23
|
continue;
|
|
24
24
|
for (const row of table.rows) {
|
|
25
25
|
const mech = row[mechIdx] ?? '';
|
|
26
|
-
for (const
|
|
27
|
-
|
|
28
|
-
if (title !== undefined)
|
|
29
|
-
out.push({ title, adr: doc.relPath, line: table.line });
|
|
26
|
+
for (const title of citedItTitles(mech)) {
|
|
27
|
+
out.push({ title, adr: doc.relPath, line: table.line });
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
31
|
return out;
|
|
34
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Count what this preset would actually scan — the caller's non-vacuity guard.
|
|
35
|
+
* `adrCitationsResolve` reports OK when it resolves zero citations, so a drifted
|
|
36
|
+
* `dir` or `roots` reads exactly like a clean pass; a gate that prints this
|
|
37
|
+
* number can tell the two apart. Mirrors `scenarioTestStats` in gherkin↔ts.
|
|
38
|
+
*/
|
|
39
|
+
export function adrCitationStats(corpus, options = {}) {
|
|
40
|
+
const dir = options.dir ?? 'docs/adr/**';
|
|
41
|
+
const inDir = picomatch(dir);
|
|
42
|
+
return {
|
|
43
|
+
citations: extractCitations({
|
|
44
|
+
corpus,
|
|
45
|
+
dir,
|
|
46
|
+
section: options.section ?? /^enforcement$/i,
|
|
47
|
+
mechanismColumn: options.mechanismColumn ?? /mechanism/i,
|
|
48
|
+
}).length,
|
|
49
|
+
adrs: corpus.documents().filter((d) => inDir(d.relPath)).length,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
35
52
|
/** Collect actual `it('…')` definitions from the project via eess-ts's public call API. */
|
|
36
53
|
function extractTestDefs(project) {
|
|
37
54
|
const allCalls = calls(project).select({
|
|
@@ -40,12 +57,29 @@ function extractTestDefs(project) {
|
|
|
40
57
|
}).elements;
|
|
41
58
|
const out = [];
|
|
42
59
|
for (const call of allCalls) {
|
|
43
|
-
|
|
60
|
+
// The ROOT callee, not the full name. eess-ts names a modifier call by its
|
|
61
|
+
// whole member expression, so `it.skip(…)` is `'it.skip'` and comparing the
|
|
62
|
+
// full name dropped every skipped, focused or concurrent test before its
|
|
63
|
+
// title was read — while the citation side had always accepted those forms
|
|
64
|
+
// (bug 0105). The gate binds a citation; it does not run the test, so a
|
|
65
|
+
// skipped test's citation is still checked. Same reasoning, same shape as
|
|
66
|
+
// `gherkin-ts.ts` — which is where it was already written down.
|
|
67
|
+
//
|
|
68
|
+
// **This guard is not what decides.** `itTitleOf` is anchored on the literal
|
|
69
|
+
// callee (`^` + `(?:it)(?:\.\w+)?\(`), so the grammar alone already rejects
|
|
70
|
+
// `describe(…)`, `test(…)`, `suite.it(…)`, `it.a.b(…)` and the outer
|
|
71
|
+
// `it.each([…])(…)`. Review measured it: delete these two lines and the whole
|
|
72
|
+
// suite stays green. What the guard buys is a cheap pre-filter — it skips
|
|
73
|
+
// `getArguments()` + `getText()` for every call expression in the project —
|
|
74
|
+
// and defence in depth: widening what counts as a test takes BOTH this line
|
|
75
|
+
// and the grammar, so neither can smuggle one in alone. Keep it for those
|
|
76
|
+
// reasons, not for a rejection it does not perform.
|
|
77
|
+
const root = call.getObjectName() ?? call.getMethodName();
|
|
78
|
+
if (root !== 'it')
|
|
44
79
|
continue;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
out.push({ title: m[1], file: call.getSourceFile().getFilePath() });
|
|
80
|
+
const title = itTitleOf(call.getName({ withArgument: 0 }) ?? '');
|
|
81
|
+
if (title !== undefined) {
|
|
82
|
+
out.push({ title, file: call.getSourceFile().getFilePath() });
|
|
49
83
|
}
|
|
50
84
|
}
|
|
51
85
|
return out;
|
|
@@ -78,6 +112,20 @@ export function adrCitationsResolve(corpus, project, options = {}) {
|
|
|
78
112
|
left,
|
|
79
113
|
right,
|
|
80
114
|
keyBy: (e) => e.title,
|
|
115
|
+
// `suggest.left`, not `.rule({ suggestion })`, and now for the right reason.
|
|
116
|
+
// The original comment here said rule-level suggestions never render on a
|
|
117
|
+
// correspondence (true until bug 0122 fixed it) and that appending to the
|
|
118
|
+
// message "does" render — which was never true: the terminal formatter
|
|
119
|
+
// dropped `message` entirely, so this remedy was invisible in the one format
|
|
120
|
+
// an agent reads. Both halves are fixed. `suggest` stays because the remedy
|
|
121
|
+
// is per-branch: a rule-level `suggestion` is stamped onto every branch of
|
|
122
|
+
// the correspondence, and "match the citation character for character" is
|
|
123
|
+
// advice for a *dangling* citation, not for an ambiguous or an uncited one.
|
|
124
|
+
suggest: {
|
|
125
|
+
left: () => 'Fix: the cited title is compared as raw source text — if the test was renamed, ' +
|
|
126
|
+
'match the citation to it character for character (escapes included); ' +
|
|
127
|
+
'if it was deleted, restore it or retire the clause it enforced.',
|
|
128
|
+
},
|
|
81
129
|
})
|
|
82
130
|
.should()
|
|
83
131
|
.beComplete({ direction: 'left-to-right' })
|
package/dist/md-ts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md-ts.js","sourceRoot":"","sources":["../src/md-ts.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,cAAc,EAAkB,MAAM,kBAAkB,CAAA;AAEjE,OAAO,EAAE,KAAK,EAAoB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"md-ts.js","sourceRoot":"","sources":["../src/md-ts.ts"],"names":[],"mappings":"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"}
|
package/dist/mermaid-ts.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Direction } from '@nielspeter/eess';
|
|
2
2
|
import { type ArchProject as MermaidDiagram } from '@nielspeter/eess-mermaid';
|
|
3
3
|
import { type ArchProject } from '@nielspeter/eess-ts';
|
|
4
|
+
export { correspondence } from '@nielspeter/eess';
|
|
5
|
+
export type { Direction } from '@nielspeter/eess';
|
|
4
6
|
export interface DiagramMatchesCodeOptions {
|
|
5
7
|
/** Glob (matched against a class's directory) restricting which TS classes
|
|
6
8
|
* participate. Defaults to a `src` folder anywhere in the tree. */
|
package/dist/mermaid-ts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mermaid-ts.d.ts","sourceRoot":"","sources":["../src/mermaid-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjE,OAAO,EAAyB,KAAK,WAAW,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACpG,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"mermaid-ts.d.ts","sourceRoot":"","sources":["../src/mermaid-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjE,OAAO,EAAyB,KAAK,WAAW,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACpG,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAM5E,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,MAAM,WAAW,yBAAyB;IACxC;uEACmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,yBAA8B,GACtC,IAAI,CA4BN"}
|
package/dist/mermaid-ts.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { correspondence } from '@nielspeter/eess';
|
|
2
2
|
import { classes as mmdClasses } from '@nielspeter/eess-mermaid';
|
|
3
3
|
import { classes as tsClasses } from '@nielspeter/eess-ts';
|
|
4
|
+
// Kernel re-exports (plan 0089 — standalone sufficiency): crossvalidate is
|
|
5
|
+
// the family's binding tool, so unlike the other dialects it MUST re-export
|
|
6
|
+
// what its own body imports — a caller composing a custom cross-dialect
|
|
7
|
+
// binding needs these same primitives.
|
|
8
|
+
export { correspondence } from '@nielspeter/eess';
|
|
4
9
|
/**
|
|
5
10
|
* Cross-validate a Mermaid class diagram against TypeScript code: every class in
|
|
6
11
|
* the diagram has a matching TS class and vice versa. Built on the kernel
|
package/dist/mermaid-ts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mermaid-ts.js","sourceRoot":"","sources":["../src/mermaid-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,MAAM,kBAAkB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAsC,MAAM,0BAA0B,CAAA;AACpG,OAAO,EAAE,OAAO,IAAI,SAAS,EAAoB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"mermaid-ts.js","sourceRoot":"","sources":["../src/mermaid-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,MAAM,kBAAkB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAsC,MAAM,0BAA0B,CAAA;AACpG,OAAO,EAAE,OAAO,IAAI,SAAS,EAAoB,MAAM,qBAAqB,CAAA;AAE5E,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AACxE,uCAAuC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAcjD;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAuB,EACvB,OAAoB,EACpB,UAAqC,EAAE;IAEvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAA;IAE1C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QACtC,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;KACpC,CAAC,CAAA;IAEF,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC;SAC7B,IAAI,EAAE;SACN,cAAc,CAAC,KAAK,CAAC;SACrB,MAAM,CAAC;QACN,KAAK,EAAE,UAAU;QACjB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChB,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,aAAa;YAClC,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,WAAW,EAAE;YACrC,IAAI,EAAE,CAAC,CAAC,kBAAkB,EAAE;SAC7B,CAAC;KACH,CAAC,CAAA;IAEJ,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;SAC5B,MAAM,EAAE;SACR,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC;SACzD,IAAI,CAAC;QACJ,EAAE,EAAE,+BAA+B;QACnC,OAAO,EAAE,4DAA4D;KACtE,CAAC;SACD,KAAK,EAAE,CAAA;AACZ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nielspeter/eess-crossvalidate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Cross-validation presets for the eess family — bind two dialects' artifacts and fail when they drift.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"types": "./dist/md-gherkin.d.ts",
|
|
25
25
|
"import": "./dist/md-gherkin.js"
|
|
26
26
|
},
|
|
27
|
+
"./gherkin-ts": {
|
|
28
|
+
"types": "./dist/gherkin-ts.d.ts",
|
|
29
|
+
"import": "./dist/gherkin-ts.js"
|
|
30
|
+
},
|
|
27
31
|
"./md-mermaid-er": {
|
|
28
32
|
"types": "./dist/md-mermaid-er.d.ts",
|
|
29
33
|
"import": "./dist/md-mermaid-er.js"
|
|
@@ -58,7 +62,7 @@
|
|
|
58
62
|
"markdown"
|
|
59
63
|
],
|
|
60
64
|
"dependencies": {
|
|
61
|
-
"@nielspeter/eess": "^0.
|
|
65
|
+
"@nielspeter/eess": "^0.4.0",
|
|
62
66
|
"picomatch": "^4.0.4"
|
|
63
67
|
},
|
|
64
68
|
"peerDependencies": {
|