@anselmdk/feature-spec-md 0.1.0 → 0.1.1-rc.1

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 CHANGED
@@ -1,26 +1,37 @@
1
1
  # feature-spec-md
2
2
 
3
- Markdown feature specs with stable rule and scenario IDs, validation, coverage checks, and generated reports.
3
+ Markdown feature specs with stable model, rule, and scenario IDs, validation, coverage checks, and generated reports.
4
4
 
5
5
  The goal is simple:
6
6
 
7
7
  ```txt
8
- human-readable feature spec
8
+ human-readable model + feature specs
9
9
  → exact executable tests
10
10
  → generated coverage report
11
11
  ```
12
12
 
13
- The handwritten spec stays clean. It contains purpose, rules, and scenarios. Test mapping is derived from stable IDs instead of being written manually in the spec.
13
+ The handwritten specs stay clean. Shared domain language lives in `*.model.md` files. User-facing capabilities live in `*.feature.md` files with rules and scenarios. Test mapping is derived from stable IDs instead of being written manually in the spec.
14
14
 
15
15
  ## Format
16
16
 
17
- Feature specs are ordinary Markdown files named `*.feature.md`.
17
+ Feature Spec Markdown uses ordinary Markdown files:
18
18
 
19
- They use:
19
+ ```txt
20
+ *.model.md
21
+ *.feature.md
22
+ ```
23
+
24
+ Model files use:
20
25
 
21
26
  - frontmatter for metadata
22
- - `## Purpose` for intent
23
- - `## Rules` for general business rules
27
+ - `## Model` for shared domain vocabulary
28
+ - optional `## Rules` for global invariants
29
+
30
+ Feature files use:
31
+
32
+ - frontmatter for metadata
33
+ - optional `model` or `models` references
34
+ - `## Rules` for durable product truths
24
35
  - `## Scenarios` for Given / When / Then examples
25
36
 
26
37
  See `SPEC_FORMAT.md` and `examples/account-access.feature.md`.
@@ -31,6 +42,24 @@ See `SPEC_FORMAT.md` and `examples/account-access.feature.md`.
31
42
  npm install
32
43
  npm run dev -- check --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts" --require-scenario-coverage=false
33
44
  npm run dev -- report --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts"
45
+ npm run dev -- report --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts" --screenshots "test-results/spec-report/screenshots-*.json"
46
+ ```
47
+
48
+ Playwright screenshot evidence can be shown in the report by passing one or
49
+ more screenshot manifest JSON files. Each screenshot should point at the spec
50
+ file and line it proves:
51
+
52
+ ```json
53
+ {
54
+ "screenshots": [
55
+ {
56
+ "specPath": "specs/account-access.feature.md",
57
+ "line": 24,
58
+ "path": "screenshots/account-s001-line-24.png",
59
+ "title": "ACCOUNT-S001:24 Given a registered person is on the sign-in page"
60
+ }
61
+ ]
62
+ }
34
63
  ```
35
64
 
36
65
  ## Library API
@@ -52,3 +81,19 @@ npm test
52
81
  npm run typecheck
53
82
  npm run build
54
83
  ```
84
+
85
+ ## Releases
86
+
87
+ Stable releases are published to npm by the `Publish to npm` GitHub Actions workflow when a `v*` tag is pushed, or when the workflow is run manually.
88
+
89
+ Release candidates are published manually from GitHub Actions:
90
+
91
+ 1. Open the `Publish RC to npm` workflow.
92
+ 2. Run the workflow from `main`.
93
+ 3. The workflow verifies the package, creates a prerelease version using the current package version and GitHub run number, and publishes it with the npm `rc` dist-tag.
94
+
95
+ Install the latest release candidate with:
96
+
97
+ ```bash
98
+ npm install @anselmdk/feature-spec-md@rc
99
+ ```
package/SPEC_FORMAT.md CHANGED
@@ -1,22 +1,24 @@
1
1
  # Feature Spec Markdown format
2
2
 
3
- Feature Spec Markdown is a lightweight convention for readable, testable feature specifications.
3
+ Feature Spec Markdown is a lightweight convention for readable, testable specifications.
4
4
 
5
- It intentionally uses ordinary Markdown and stable IDs instead of a dedicated executable specification language.
5
+ It uses ordinary Markdown and stable IDs instead of a dedicated executable specification language.
6
6
 
7
- ## File name
7
+ ## File types
8
8
 
9
- Use:
9
+ The format has four document types:
10
10
 
11
11
  ```txt
12
+ *.model.md
12
13
  *.feature.md
14
+ *.stack.md
15
+ *.design.md
13
16
  ```
14
17
 
15
- Example:
16
-
17
- ```txt
18
- account-access.feature.md
19
- ```
18
+ - `*.model.md` defines shared domain vocabulary.
19
+ - `*.feature.md` defines user-facing behavior with rules and scenarios.
20
+ - `*.stack.md` defines technical platform choices.
21
+ - `*.design.md` defines product, UI, and interaction design direction.
20
22
 
21
23
  ## Frontmatter
22
24
 
@@ -24,9 +26,10 @@ Every file starts with YAML-like frontmatter:
24
26
 
25
27
  ```md
26
28
  ---
27
- id: ACCOUNT
28
- title: Account access
29
+ id: KANBAN-CARD-AUTHORING
30
+ title: Card authoring
29
31
  status: draft
32
+ model: KANBAN
30
33
  ---
31
34
  ```
32
35
 
@@ -39,48 +42,75 @@ Optional fields:
39
42
 
40
43
  - `status`: `draft`, `active`, or `deprecated`
41
44
  - `owner`
45
+ - `model`: a single referenced model id, for feature and design files
46
+ - `models`: comma-separated referenced model ids, for feature and design files
47
+
48
+ ## Purpose
42
49
 
43
- ## Required sections
50
+ Every model, feature, stack, and design file MUST include a short `## Purpose` section.
51
+
52
+ Purpose explains the document boundary and intent. It SHOULD be one or two short paragraphs and SHOULD NOT contain rules, scenarios, implementation details, or roadmap notes.
53
+
54
+ ## Model files
55
+
56
+ Model files use the `.model.md` suffix.
57
+
58
+ Required sections:
44
59
 
45
60
  ```md
46
- # Account access
61
+ # Kanban model
47
62
 
48
63
  ## Purpose
49
64
 
50
- ## Rules
51
-
52
- ## Scenarios
65
+ ## Model
53
66
  ```
54
67
 
68
+ Optional sections:
69
+
70
+ ```md
55
71
  ## Rules
72
+ ```
56
73
 
57
- Rules are durable business truths. They use stable IDs and requirement keywords.
74
+ Model items use stable `-M001` IDs:
58
75
 
59
76
  ```md
60
- - ACCOUNT-R001: A person MUST prove control of a registered email address before accessing an account.
61
- - ACCOUNT-R002: The system MUST NOT reveal whether an unknown email address belongs to an account.
62
- - ACCOUNT-R003: A signed-in person SHOULD be returned to the page they originally requested.
77
+ ### KANBAN-M001: Card
78
+
79
+ A card represents one work item on the board.
63
80
  ```
64
81
 
65
- Use these keywords:
82
+ Model rules use stable `-R001` IDs and should describe global invariants for the domain vocabulary.
83
+
84
+ ## Feature files
85
+
86
+ Feature files use the `.feature.md` suffix.
87
+
88
+ Required sections:
89
+
90
+ ```md
91
+ # Card authoring
92
+
93
+ ## Purpose
66
94
 
67
- - `MUST`
68
- - `MUST NOT`
69
- - `SHOULD`
70
- - `SHOULD NOT`
71
- - `MAY`
72
- - `OPTIONAL`
95
+ ## Rules
73
96
 
74
97
  ## Scenarios
98
+ ```
99
+
100
+ Rules use stable `-R001` IDs:
101
+
102
+ ```md
103
+ - KANBAN-CARD-AUTHORING-R001: A new card MUST start in the To do column.
104
+ ```
75
105
 
76
- Scenarios are concrete examples. They use stable IDs and Given / When / Then steps.
106
+ Scenarios use stable `-S001` IDs and Given / When / Then steps:
77
107
 
78
108
  ```md
79
- ### ACCOUNT-S001: Registered person signs in
109
+ ### KANBAN-CARD-AUTHORING-S001: User creates a card
80
110
 
81
- Given a registered person is on the sign-in page
82
- When they request and open a valid sign-in link
83
- Then they are signed in
111
+ Given the user is on the board
112
+ When they create a card with the title "Write release notes"
113
+ Then the card "Write release notes" is visible in the To do column
84
114
  ```
85
115
 
86
116
  Allowed step keywords:
@@ -91,14 +121,124 @@ Allowed step keywords:
91
121
  - `And`
92
122
  - `But`
93
123
 
124
+ ## Stack files
125
+
126
+ Stack files use the `.stack.md` suffix.
127
+
128
+ A stack file defines technical platform choices and the reasoning behind them.
129
+
130
+ Required sections:
131
+
132
+ ```md
133
+ # Kanban tech stack
134
+
135
+ ## Purpose
136
+
137
+ ## Stack
138
+ ```
139
+
140
+ Optional sections:
141
+
142
+ ```md
143
+ ## Context
144
+
145
+ ## Rationale
146
+
147
+ ## Consequences
148
+ ```
149
+
150
+ Example:
151
+
152
+ ```md
153
+ ---
154
+ id: KANBAN-STACK
155
+ title: Kanban tech stack
156
+ status: draft
157
+ ---
158
+
159
+ # Kanban tech stack
160
+
161
+ ## Purpose
162
+
163
+ Define the initial technical stack for implementing the Kanban board.
164
+
165
+ ## Stack
166
+
167
+ | Area | Choice |
168
+ |---|---|
169
+ | Frontend | React |
170
+ | Language | TypeScript |
171
+ | Testing | Playwright |
172
+ ```
173
+
174
+ ## Design files
175
+
176
+ Design files use the `.design.md` suffix.
177
+
178
+ A design file defines product, UI, layout, visual, and interaction direction.
179
+
180
+ Required sections:
181
+
182
+ ```md
183
+ # Kanban board design
184
+
185
+ ## Purpose
186
+
187
+ ## Design
188
+ ```
189
+
190
+ Optional sections:
191
+
192
+ ```md
193
+ ## Principles
194
+
195
+ ## Layout
196
+
197
+ ## Interaction
198
+
199
+ ## Visual style
200
+ ```
201
+
202
+ Example:
203
+
204
+ ```md
205
+ ---
206
+ id: KANBAN-DESIGN
207
+ title: Kanban board design
208
+ status: draft
209
+ model: KANBAN
210
+ ---
211
+
212
+ # Kanban board design
213
+
214
+ ## Purpose
215
+
216
+ Define the visual and interaction design direction for the Kanban board.
217
+
218
+ ## Design
219
+
220
+ The board should feel lightweight, immediate, and calm.
221
+ ```
222
+
223
+ ## Splitting guidance
224
+
225
+ Split model files by coherent domain vocabulary, ownership, or lifecycle.
226
+
227
+ Feature files SHOULD be split by user capability.
228
+
229
+ Use stack files for broad technical choices such as framework, language, testing, persistence, and deployment.
230
+
231
+ Use design files for product/UI direction such as layout, interaction, visual style, and design principles.
232
+
94
233
  ## Test coverage convention
95
234
 
96
- The spec file does not contain test mappings.
235
+ Spec files do not contain test mappings.
97
236
 
98
- Tests reference rule and scenario IDs in test titles, tags, annotations, comments, or metadata.
237
+ Tests reference model item, rule, and scenario IDs in test titles, tags, annotations, comments, or metadata.
99
238
 
100
- Generated tooling can then answer:
239
+ Generated tooling can answer:
101
240
 
241
+ - Which model items are referenced?
102
242
  - Which scenarios have tests?
103
243
  - Which rules have executable coverage?
104
244
  - Which tests reference deleted or unknown spec IDs?
package/dist/cli.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { mkdir, writeFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
- import { checkFeatureSpecs, renderHtmlReport, writeTextFile } from "./index.js";
5
- const defaultSpecPattern = "specs/**/*.feature.md";
4
+ import { collectSpecScreenshots, renderHtmlReport, writeTextFile } from "./index.js";
5
+ import { checkSpecDocuments } from "./specDocuments.js";
6
+ const defaultSpecPattern = "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md";
6
7
  const defaultTestPattern = "tests/**/*.spec.ts";
7
8
  main().catch((error) => {
8
9
  console.error(error instanceof Error ? error.message : error);
@@ -21,38 +22,47 @@ async function main() {
21
22
  process.exit(command === "help" || command === "--help" || command === "-h" ? 0 : 1);
22
23
  }
23
24
  async function runCheck(options) {
24
- const result = await checkFeatureSpecs({
25
+ const result = await checkSpecDocuments({
25
26
  specs: optionList(options.specs, defaultSpecPattern),
26
27
  tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
28
+ requireModelCoverage: options["require-model-coverage"] === "true",
27
29
  requireRuleCoverage: options["require-rule-coverage"] === "true",
28
30
  requireScenarioCoverage: options["require-scenario-coverage"] !== "false",
29
31
  });
30
32
  printIssues([...result.validationIssues, ...result.coverageIssues]);
31
33
  if (!result.ok)
32
34
  process.exit(1);
33
- const scenarioCount = result.specs.reduce((sum, spec) => sum + spec.scenarios.length, 0);
34
- const ruleCount = result.specs.reduce((sum, spec) => sum + spec.rules.length, 0);
35
- console.log(`Feature spec check passed: ${result.specs.length} spec(s), ${ruleCount} rule(s), ${scenarioCount} scenario(s).`);
35
+ const modelItemCount = result.models.reduce((sum, spec) => sum + spec.modelItems.length, 0);
36
+ const ruleCount = result.documents.reduce((sum, spec) => sum + spec.rules.length, 0);
37
+ const scenarioCount = result.features.reduce((sum, spec) => sum + spec.scenarios.length, 0);
38
+ console.log(`Spec check passed: ${result.models.length} model(s), ${result.features.length} feature(s), ${result.stacks.length} stack(s), ${result.designs.length} design(s), ${modelItemCount} model item(s), ${ruleCount} rule(s), ${scenarioCount} scenario(s).`);
36
39
  }
37
40
  async function runReport(options) {
38
- const result = await checkFeatureSpecs({
41
+ const result = await checkSpecDocuments({
39
42
  specs: optionList(options.specs, defaultSpecPattern),
40
43
  tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
44
+ requireModelCoverage: options["require-model-coverage"] === "true",
41
45
  requireRuleCoverage: options["require-rule-coverage"] === "true",
42
46
  requireScenarioCoverage: false,
43
47
  });
44
48
  const out = options.out ?? "test-results/feature-spec-report/index.html";
45
- await writeTextFile(out, renderHtmlReport(result.specs, {
49
+ const screenshots = options.screenshots ? await collectSpecScreenshots(optionList(options.screenshots, "")) : [];
50
+ await writeTextFile(out, renderHtmlReport(result.features, {
51
+ models: result.models,
52
+ stacks: result.stacks,
53
+ designs: result.designs,
46
54
  coverage: result.coverage,
55
+ screenshots,
47
56
  validationIssues: [...result.validationIssues, ...result.coverageIssues],
48
57
  }));
49
58
  console.log(`Feature spec report written to ${out}`);
50
59
  }
51
60
  async function runInit(options) {
52
61
  const dir = options.dir ?? "specs";
53
- const target = path.join(dir, "account-access.feature.md");
62
+ const kind = options.kind ?? "feature";
63
+ const target = path.join(dir, fileNameForKind(kind));
54
64
  await mkdir(dir, { recursive: true });
55
- await writeFile(target, exampleSpec, "utf8");
65
+ await writeFile(target, exampleForKind(kind), "utf8");
56
66
  console.log(`Created ${target}`);
57
67
  }
58
68
  function parseArgs(args) {
@@ -89,20 +99,59 @@ function printHelp() {
89
99
  console.log(`feature-spec-md
90
100
 
91
101
  Usage:
92
- feature-spec-md init [--dir specs]
93
- feature-spec-md check [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"]
94
- feature-spec-md report [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"] [--out test-results/feature-spec-report/index.html]
102
+ feature-spec-md init [--kind feature|model|stack|design] [--dir specs]
103
+ feature-spec-md check [--specs "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md"] [--tests "tests/**/*.spec.ts"]
104
+ feature-spec-md report [--specs "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md"] [--tests "tests/**/*.spec.ts"] [--screenshots "test-results/spec-report/screenshots.json"] [--out test-results/feature-spec-report/index.html]
95
105
 
96
106
  Options:
107
+ --require-model-coverage Fail when model items have no matching test references.
97
108
  --require-rule-coverage Fail when rules have no matching test references.
98
109
  --require-scenario-coverage Defaults to true for check. Use --require-scenario-coverage=false to disable.
110
+ --screenshots Screenshot manifest JSON glob for report evidence.
99
111
  --tests "" Disable test coverage lookup.
100
112
  `);
101
113
  }
102
- const exampleSpec = `---
114
+ function fileNameForKind(kind) {
115
+ if (kind === "model")
116
+ return "example.model.md";
117
+ if (kind === "stack")
118
+ return "example.stack.md";
119
+ if (kind === "design")
120
+ return "example.design.md";
121
+ return "account-access.feature.md";
122
+ }
123
+ function exampleForKind(kind) {
124
+ if (kind === "model")
125
+ return exampleModel;
126
+ if (kind === "stack")
127
+ return exampleStack;
128
+ if (kind === "design")
129
+ return exampleDesign;
130
+ return exampleFeature;
131
+ }
132
+ const exampleModel = `---
103
133
  id: ACCOUNT
134
+ title: Account model
135
+ status: draft
136
+ ---
137
+
138
+ # Account model
139
+
140
+ ## Purpose
141
+
142
+ Define the shared account concepts used by account access features.
143
+
144
+ ## Model
145
+
146
+ ### ACCOUNT-M001: Account
147
+
148
+ An account represents one registered person.
149
+ `;
150
+ const exampleFeature = `---
151
+ id: ACCOUNT-ACCESS
104
152
  title: Account access
105
153
  status: draft
154
+ model: ACCOUNT
106
155
  ---
107
156
 
108
157
  # Account access
@@ -113,24 +162,82 @@ People can access their own account after proving their identity.
113
162
 
114
163
  ## Rules
115
164
 
116
- - ACCOUNT-R001: A person MUST prove control of a registered email address before accessing an account.
117
- - ACCOUNT-R002: The system MUST NOT reveal whether an unknown email address belongs to an account.
118
- - ACCOUNT-R003: A signed-in person SHOULD be returned to the page they originally requested.
165
+ - ACCOUNT-ACCESS-R001: A person MUST prove control of a registered email address before accessing an account.
166
+ - ACCOUNT-ACCESS-R002: The system MUST NOT reveal whether an unknown email address belongs to an account.
119
167
 
120
168
  ## Scenarios
121
169
 
122
- ### ACCOUNT-S001: Registered person signs in
170
+ ### ACCOUNT-ACCESS-S001: Registered person signs in
171
+
172
+ Given a registered person is on the sign-in page
173
+ When they request and open a valid sign-in link
174
+ Then they are signed in
175
+ `;
176
+ const exampleStack = `---
177
+ id: ACCOUNT-STACK
178
+ title: Account stack
179
+ status: draft
180
+ ---
181
+
182
+ # Account stack
183
+
184
+ ## Purpose
185
+
186
+ Define the initial technical stack for the account access demo.
187
+
188
+ ## Context
189
+
190
+ The demo is a small browser-based application with automated tests.
191
+
192
+ ## Stack
193
+
194
+ | Area | Choice |
195
+ |---|---|
196
+ | Frontend | React |
197
+ | Language | TypeScript |
198
+ | Testing | Playwright |
199
+
200
+ ## Rationale
201
+
202
+ React, TypeScript, and Playwright fit the interaction-heavy UI and scenario-based testing style.
203
+
204
+ ## Consequences
205
+
206
+ The stack is optimized for a browser UI and static deployment.
207
+ `;
208
+ const exampleDesign = `---
209
+ id: ACCOUNT-DESIGN
210
+ title: Account design
211
+ status: draft
212
+ model: ACCOUNT
213
+ ---
214
+
215
+ # Account design
216
+
217
+ ## Purpose
218
+
219
+ Define the initial interaction and visual design direction for account access.
220
+
221
+ ## Design
222
+
223
+ The account access flow should feel simple, calm, and direct.
224
+
225
+ ## Principles
226
+
227
+ - Keep the sign-in flow short.
228
+ - Avoid revealing whether an email address exists.
229
+ - Make recovery states easy to understand.
230
+
231
+ ## Layout
232
+
233
+ The sign-in page uses one primary form and one primary action.
234
+
235
+ ## Interaction
123
236
 
124
- Given a registered person is on the sign-in page
125
- When they request and open a valid sign-in link
126
- Then they are signed in
127
- And they are returned to the page they originally requested
237
+ Validation messages appear near the field they describe.
128
238
 
129
- ### ACCOUNT-S002: Unknown email receives a neutral response
239
+ ## Visual style
130
240
 
131
- Given a person enters an email address that is not registered
132
- When they request a sign-in link
133
- Then the response says to check their email
134
- And the response does not reveal whether the email address is registered
241
+ Use a clean, low-distraction visual style.
135
242
  `;
136
243
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AAEtG,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AACnD,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAEhD,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhD,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,OAAmB;IACzC,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACrC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,CAAC;QACpD,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,CAAC;QAChF,mBAAmB,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,MAAM;QAChE,uBAAuB,EAAE,OAAO,CAAC,2BAA2B,CAAC,KAAK,OAAO;KAC1E,CAAC,CAAC;IAEH,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,gBAAgB,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEhC,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACzF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,8BAA8B,MAAM,CAAC,KAAK,CAAC,MAAM,aAAa,SAAS,aAAa,aAAa,eAAe,CAAC,CAAC;AAChI,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAAmB;IAC1C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACrC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,CAAC;QACpD,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,CAAC;QAChF,mBAAmB,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,MAAM;QAChE,uBAAuB,EAAE,KAAK;KAC/B,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,6CAA6C,CAAC;IACzE,MAAM,aAAa,CAAC,GAAG,EAAE,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE;QACtD,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,gBAAgB,EAAE,CAAC,GAAG,MAAM,CAAC,gBAAgB,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC;KACzE,CAAC,CAAC,CAAC;IACJ,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,OAAmB;IACxC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,2BAA2B,CAAC,CAAC;IAC3D,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;AACnC,CAAC;AAID,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QACpC,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACtD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACpB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,KAAyB,EAAE,QAAgB;IAC7D,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,WAAW,CAAC,MAAyB;IAC5C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChG,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACpH,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;CAWb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCnB,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Expand user-provided source globs while ignoring generated directories. */
2
+ export declare function expandFilePatterns(patterns: string[]): Promise<string[]>;
3
+ /** Expand report artifact globs, including files under `test-results`. */
4
+ export declare function expandArtifactPatterns(patterns: string[]): Promise<string[]>;
5
+ //# sourceMappingURL=filePatterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filePatterns.d.ts","sourceRoot":"","sources":["../src/filePatterns.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,qBAO1D;AAED,0EAA0E;AAC1E,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,qBAE9D"}
@@ -0,0 +1,24 @@
1
+ import { glob } from "node:fs/promises";
2
+ /** Expand user-provided source globs while ignoring generated directories. */
3
+ export async function expandFilePatterns(patterns) {
4
+ return expandPatterns(patterns, [
5
+ "node_modules/**",
6
+ ".git/**",
7
+ "dist/**",
8
+ "test-results/**",
9
+ ]);
10
+ }
11
+ /** Expand report artifact globs, including files under `test-results`. */
12
+ export async function expandArtifactPatterns(patterns) {
13
+ return expandPatterns(patterns, ["node_modules/**", ".git/**", "dist/**"]);
14
+ }
15
+ async function expandPatterns(patterns, exclude) {
16
+ const files = new Set();
17
+ for (const pattern of patterns) {
18
+ for await (const file of glob(pattern, { exclude })) {
19
+ files.add(file);
20
+ }
21
+ }
22
+ return Array.from(files).sort();
23
+ }
24
+ //# sourceMappingURL=filePatterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filePatterns.js","sourceRoot":"","sources":["../src/filePatterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAkB;IACzD,OAAO,cAAc,CAAC,QAAQ,EAAE;QAC9B,iBAAiB;QACjB,SAAS;QACT,SAAS;QACT,iBAAiB;KAClB,CAAC,CAAC;AACL,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAkB;IAC7D,OAAO,cAAc,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,QAAkB,EAAE,OAAiB;IACjE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC"}
package/dist/html.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function html(value: string): string;
2
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,UAOjC"}
package/dist/html.js ADDED
@@ -0,0 +1,9 @@
1
+ export function html(value) {
2
+ return value
3
+ .replace(/&/g, "&amp;")
4
+ .replace(/</g, "&lt;")
5
+ .replace(/>/g, "&gt;")
6
+ .replace(/\"/g, "&quot;")
7
+ .replace(/'/g, "&#039;");
8
+ }
9
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}