@facet-coverage/core 0.1.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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/bin/facet-coverage.js +3 -0
  4. package/dist/cli/commands/analyze.d.ts +13 -0
  5. package/dist/cli/commands/analyze.d.ts.map +1 -0
  6. package/dist/cli/commands/analyze.js +161 -0
  7. package/dist/cli/commands/analyze.js.map +1 -0
  8. package/dist/cli/commands/generate.d.ts +10 -0
  9. package/dist/cli/commands/generate.d.ts.map +1 -0
  10. package/dist/cli/commands/generate.js +67 -0
  11. package/dist/cli/commands/generate.js.map +1 -0
  12. package/dist/cli/commands/validate.d.ts +11 -0
  13. package/dist/cli/commands/validate.d.ts.map +1 -0
  14. package/dist/cli/commands/validate.js +120 -0
  15. package/dist/cli/commands/validate.js.map +1 -0
  16. package/dist/cli/commands/watch.d.ts +10 -0
  17. package/dist/cli/commands/watch.d.ts.map +1 -0
  18. package/dist/cli/commands/watch.js +151 -0
  19. package/dist/cli/commands/watch.js.map +1 -0
  20. package/dist/cli/index.d.ts +2 -0
  21. package/dist/cli/index.d.ts.map +1 -0
  22. package/dist/cli/index.js +47 -0
  23. package/dist/cli/index.js.map +1 -0
  24. package/dist/core/CoverageCalculator.d.ts +34 -0
  25. package/dist/core/CoverageCalculator.d.ts.map +1 -0
  26. package/dist/core/CoverageCalculator.js +167 -0
  27. package/dist/core/CoverageCalculator.js.map +1 -0
  28. package/dist/core/FacetParser.d.ts +39 -0
  29. package/dist/core/FacetParser.d.ts.map +1 -0
  30. package/dist/core/FacetParser.js +114 -0
  31. package/dist/core/FacetParser.js.map +1 -0
  32. package/dist/core/StructureReader.d.ts +37 -0
  33. package/dist/core/StructureReader.d.ts.map +1 -0
  34. package/dist/core/StructureReader.js +126 -0
  35. package/dist/core/StructureReader.js.map +1 -0
  36. package/dist/core/TestScanner.d.ts +36 -0
  37. package/dist/core/TestScanner.d.ts.map +1 -0
  38. package/dist/core/TestScanner.js +192 -0
  39. package/dist/core/TestScanner.js.map +1 -0
  40. package/dist/core/Validator.d.ts +33 -0
  41. package/dist/core/Validator.d.ts.map +1 -0
  42. package/dist/core/Validator.js +183 -0
  43. package/dist/core/Validator.js.map +1 -0
  44. package/dist/core/index.d.ts +6 -0
  45. package/dist/core/index.d.ts.map +1 -0
  46. package/dist/core/index.js +14 -0
  47. package/dist/core/index.js.map +1 -0
  48. package/dist/index.d.ts +6 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +23 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/integrations/playwright.d.ts +95 -0
  53. package/dist/integrations/playwright.d.ts.map +1 -0
  54. package/dist/integrations/playwright.js +168 -0
  55. package/dist/integrations/playwright.js.map +1 -0
  56. package/dist/reporters/HtmlReporter.d.ts +53 -0
  57. package/dist/reporters/HtmlReporter.d.ts.map +1 -0
  58. package/dist/reporters/HtmlReporter.js +484 -0
  59. package/dist/reporters/HtmlReporter.js.map +1 -0
  60. package/dist/reporters/JsonReporter.d.ts +21 -0
  61. package/dist/reporters/JsonReporter.d.ts.map +1 -0
  62. package/dist/reporters/JsonReporter.js +58 -0
  63. package/dist/reporters/JsonReporter.js.map +1 -0
  64. package/dist/reporters/MarkdownReporter.d.ts +25 -0
  65. package/dist/reporters/MarkdownReporter.d.ts.map +1 -0
  66. package/dist/reporters/MarkdownReporter.js +141 -0
  67. package/dist/reporters/MarkdownReporter.js.map +1 -0
  68. package/dist/reporters/index.d.ts +4 -0
  69. package/dist/reporters/index.d.ts.map +1 -0
  70. package/dist/reporters/index.js +10 -0
  71. package/dist/reporters/index.js.map +1 -0
  72. package/dist/types.d.ts +205 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +28 -0
  75. package/dist/types.js.map +1 -0
  76. package/package.json +88 -0
@@ -0,0 +1,484 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HtmlReporter = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const types_js_1 = require("../types.js");
7
+ /**
8
+ * Generates HTML coverage reports
9
+ */
10
+ class HtmlReporter {
11
+ config;
12
+ constructor(config = {}) {
13
+ this.config = { ...types_js_1.defaultConfig, ...config };
14
+ }
15
+ /**
16
+ * Generate HTML report
17
+ */
18
+ generate(report) {
19
+ return `<!DOCTYPE html>
20
+ <html lang="en">
21
+ <head>
22
+ <meta charset="UTF-8">
23
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
24
+ <title>Facet Coverage Report</title>
25
+ <style>
26
+ ${this.getStyles()}
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <div class="container">
31
+ <header>
32
+ <h1>💎 Facet Coverage Report</h1>
33
+ <p class="timestamp">Generated: ${new Date(report.timestamp).toLocaleString()}</p>
34
+ </header>
35
+
36
+ ${this.generateSummarySection(report)}
37
+ ${this.generateTypeSection(report)}
38
+ ${this.generateFeaturesSection(report)}
39
+ ${this.generateUncoveredSection(report)}
40
+
41
+ <footer>
42
+ <p>Generated by <a href="https://github.com/facet-coverage">facet-coverage</a></p>
43
+ </footer>
44
+ </div>
45
+
46
+ <script>
47
+ ${this.getScript()}
48
+ </script>
49
+ </body>
50
+ </html>`;
51
+ }
52
+ /**
53
+ * Get CSS styles
54
+ */
55
+ getStyles() {
56
+ return `
57
+ :root {
58
+ --color-success: #22c55e;
59
+ --color-warning: #eab308;
60
+ --color-error: #ef4444;
61
+ --color-bg: #0f172a;
62
+ --color-card: #1e293b;
63
+ --color-text: #f1f5f9;
64
+ --color-muted: #94a3b8;
65
+ --color-border: #334155;
66
+ }
67
+
68
+ * {
69
+ margin: 0;
70
+ padding: 0;
71
+ box-sizing: border-box;
72
+ }
73
+
74
+ body {
75
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
76
+ background: var(--color-bg);
77
+ color: var(--color-text);
78
+ line-height: 1.6;
79
+ }
80
+
81
+ .container {
82
+ max-width: 1200px;
83
+ margin: 0 auto;
84
+ padding: 2rem;
85
+ }
86
+
87
+ header {
88
+ text-align: center;
89
+ margin-bottom: 2rem;
90
+ }
91
+
92
+ header h1 {
93
+ font-size: 2.5rem;
94
+ margin-bottom: 0.5rem;
95
+ }
96
+
97
+ .timestamp {
98
+ color: var(--color-muted);
99
+ }
100
+
101
+ .card {
102
+ background: var(--color-card);
103
+ border-radius: 12px;
104
+ padding: 1.5rem;
105
+ margin-bottom: 1.5rem;
106
+ border: 1px solid var(--color-border);
107
+ }
108
+
109
+ .card h2 {
110
+ margin-bottom: 1rem;
111
+ font-size: 1.25rem;
112
+ }
113
+
114
+ .summary-grid {
115
+ display: grid;
116
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
117
+ gap: 1rem;
118
+ }
119
+
120
+ .stat {
121
+ text-align: center;
122
+ padding: 1rem;
123
+ background: var(--color-bg);
124
+ border-radius: 8px;
125
+ }
126
+
127
+ .stat-value {
128
+ font-size: 2rem;
129
+ font-weight: bold;
130
+ }
131
+
132
+ .stat-label {
133
+ color: var(--color-muted);
134
+ font-size: 0.875rem;
135
+ }
136
+
137
+ .coverage-bar {
138
+ height: 8px;
139
+ background: var(--color-border);
140
+ border-radius: 4px;
141
+ overflow: hidden;
142
+ margin-top: 0.5rem;
143
+ }
144
+
145
+ .coverage-fill {
146
+ height: 100%;
147
+ transition: width 0.3s ease;
148
+ }
149
+
150
+ .coverage-fill.success { background: var(--color-success); }
151
+ .coverage-fill.warning { background: var(--color-warning); }
152
+ .coverage-fill.error { background: var(--color-error); }
153
+
154
+ .type-grid {
155
+ display: grid;
156
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
157
+ gap: 1rem;
158
+ }
159
+
160
+ .type-card {
161
+ padding: 1rem;
162
+ background: var(--color-bg);
163
+ border-radius: 8px;
164
+ }
165
+
166
+ .type-header {
167
+ display: flex;
168
+ justify-content: space-between;
169
+ align-items: center;
170
+ margin-bottom: 0.5rem;
171
+ }
172
+
173
+ .type-name {
174
+ font-weight: 600;
175
+ text-transform: capitalize;
176
+ }
177
+
178
+ .type-percentage {
179
+ font-weight: bold;
180
+ }
181
+
182
+ .feature {
183
+ border: 1px solid var(--color-border);
184
+ border-radius: 8px;
185
+ margin-bottom: 1rem;
186
+ overflow: hidden;
187
+ }
188
+
189
+ .feature-header {
190
+ padding: 1rem;
191
+ background: var(--color-bg);
192
+ cursor: pointer;
193
+ display: flex;
194
+ justify-content: space-between;
195
+ align-items: center;
196
+ }
197
+
198
+ .feature-header:hover {
199
+ background: var(--color-border);
200
+ }
201
+
202
+ .feature-name {
203
+ font-weight: 600;
204
+ }
205
+
206
+ .feature-stats {
207
+ display: flex;
208
+ gap: 1rem;
209
+ align-items: center;
210
+ }
211
+
212
+ .feature-body {
213
+ padding: 1rem;
214
+ display: none;
215
+ }
216
+
217
+ .feature.open .feature-body {
218
+ display: block;
219
+ }
220
+
221
+ .facet {
222
+ padding: 0.75rem;
223
+ background: var(--color-bg);
224
+ border-radius: 6px;
225
+ margin-bottom: 0.5rem;
226
+ }
227
+
228
+ .facet-header {
229
+ display: flex;
230
+ justify-content: space-between;
231
+ align-items: center;
232
+ }
233
+
234
+ .facet-id {
235
+ font-family: monospace;
236
+ font-weight: 600;
237
+ }
238
+
239
+ .facet-type {
240
+ font-size: 0.75rem;
241
+ padding: 0.25rem 0.5rem;
242
+ background: var(--color-card);
243
+ border-radius: 4px;
244
+ text-transform: capitalize;
245
+ }
246
+
247
+ .facet-source {
248
+ color: var(--color-muted);
249
+ font-size: 0.875rem;
250
+ margin-top: 0.25rem;
251
+ }
252
+
253
+ .facet-tests {
254
+ margin-top: 0.5rem;
255
+ font-size: 0.875rem;
256
+ }
257
+
258
+ .facet-tests li {
259
+ margin-left: 1rem;
260
+ color: var(--color-muted);
261
+ }
262
+
263
+ .badge {
264
+ display: inline-block;
265
+ padding: 0.125rem 0.5rem;
266
+ border-radius: 4px;
267
+ font-size: 0.75rem;
268
+ font-weight: 600;
269
+ }
270
+
271
+ .badge.success { background: var(--color-success); color: #000; }
272
+ .badge.warning { background: var(--color-warning); color: #000; }
273
+ .badge.error { background: var(--color-error); color: #fff; }
274
+
275
+ .uncovered-list {
276
+ list-style: none;
277
+ }
278
+
279
+ .uncovered-list li {
280
+ padding: 0.75rem;
281
+ background: var(--color-bg);
282
+ border-radius: 6px;
283
+ margin-bottom: 0.5rem;
284
+ border-left: 3px solid var(--color-error);
285
+ }
286
+
287
+ footer {
288
+ text-align: center;
289
+ margin-top: 2rem;
290
+ padding-top: 2rem;
291
+ border-top: 1px solid var(--color-border);
292
+ color: var(--color-muted);
293
+ }
294
+
295
+ footer a {
296
+ color: var(--color-text);
297
+ }
298
+
299
+ .expand-icon {
300
+ transition: transform 0.2s ease;
301
+ }
302
+
303
+ .feature.open .expand-icon {
304
+ transform: rotate(90deg);
305
+ }
306
+ `;
307
+ }
308
+ /**
309
+ * Get JavaScript for interactivity
310
+ */
311
+ getScript() {
312
+ return `
313
+ document.querySelectorAll('.feature-header').forEach(header => {
314
+ header.addEventListener('click', () => {
315
+ header.parentElement.classList.toggle('open');
316
+ });
317
+ });
318
+ `;
319
+ }
320
+ /**
321
+ * Generate summary section HTML
322
+ */
323
+ generateSummarySection(report) {
324
+ const coverageClass = this.getCoverageClass(report.summary.percentage);
325
+ return `
326
+ <section class="card">
327
+ <h2>Overall Coverage</h2>
328
+ <div class="summary-grid">
329
+ <div class="stat">
330
+ <div class="stat-value ${coverageClass}">${report.summary.percentage}%</div>
331
+ <div class="stat-label">Coverage</div>
332
+ <div class="coverage-bar">
333
+ <div class="coverage-fill ${coverageClass}" style="width: ${report.summary.percentage}%"></div>
334
+ </div>
335
+ </div>
336
+ <div class="stat">
337
+ <div class="stat-value">${report.summary.totalFacets}</div>
338
+ <div class="stat-label">Total Facets</div>
339
+ </div>
340
+ <div class="stat">
341
+ <div class="stat-value" style="color: var(--color-success)">${report.summary.coveredFacets}</div>
342
+ <div class="stat-label">Covered</div>
343
+ </div>
344
+ <div class="stat">
345
+ <div class="stat-value" style="color: var(--color-error)">${report.summary.uncoveredFacets}</div>
346
+ <div class="stat-label">Uncovered</div>
347
+ </div>
348
+ </div>
349
+ </section>`;
350
+ }
351
+ /**
352
+ * Generate type breakdown section
353
+ */
354
+ generateTypeSection(report) {
355
+ if (report.byType.length === 0)
356
+ return '';
357
+ const typeCards = report.byType.map(type => {
358
+ const coverageClass = this.getCoverageClass(type.percentage);
359
+ return `
360
+ <div class="type-card">
361
+ <div class="type-header">
362
+ <span class="type-name">${type.type}</span>
363
+ <span class="type-percentage ${coverageClass}">${type.percentage}%</span>
364
+ </div>
365
+ <div class="coverage-bar">
366
+ <div class="coverage-fill ${coverageClass}" style="width: ${type.percentage}%"></div>
367
+ </div>
368
+ <div style="margin-top: 0.5rem; color: var(--color-muted); font-size: 0.875rem;">
369
+ ${type.covered} / ${type.total} covered
370
+ </div>
371
+ </div>`;
372
+ }).join('');
373
+ return `
374
+ <section class="card">
375
+ <h2>Coverage by Type</h2>
376
+ <div class="type-grid">
377
+ ${typeCards}
378
+ </div>
379
+ </section>`;
380
+ }
381
+ /**
382
+ * Generate features section
383
+ */
384
+ generateFeaturesSection(report) {
385
+ const features = report.features.map(feature => this.generateFeatureHtml(feature)).join('');
386
+ return `
387
+ <section class="card">
388
+ <h2>Features</h2>
389
+ ${features}
390
+ </section>`;
391
+ }
392
+ /**
393
+ * Generate HTML for a single feature
394
+ */
395
+ generateFeatureHtml(feature) {
396
+ const coverageClass = this.getCoverageClass(feature.percentage);
397
+ const facetsHtml = feature.facets.map(fc => this.generateFacetHtml(fc)).join('');
398
+ return `
399
+ <div class="feature">
400
+ <div class="feature-header">
401
+ <span class="feature-name">
402
+ <span class="expand-icon">▶</span>
403
+ ${feature.feature}
404
+ </span>
405
+ <div class="feature-stats">
406
+ <span class="badge ${coverageClass}">${feature.percentage}%</span>
407
+ <span style="color: var(--color-muted)">${feature.coveredFacets}/${feature.totalFacets} facets</span>
408
+ </div>
409
+ </div>
410
+ <div class="feature-body">
411
+ ${facetsHtml}
412
+ </div>
413
+ </div>`;
414
+ }
415
+ /**
416
+ * Generate HTML for a single facet
417
+ */
418
+ generateFacetHtml(fc) {
419
+ const statusIcon = fc.covered ? '✅' : '❌';
420
+ let testsHtml = '';
421
+ if (fc.covered && fc.coveredBy.length > 0) {
422
+ const testItems = fc.coveredBy.map(t => `<li>${t.file}: ${t.title}</li>`).join('');
423
+ testsHtml = `
424
+ <div class="facet-tests">
425
+ <strong>Covered by:</strong>
426
+ <ul>${testItems}</ul>
427
+ </div>`;
428
+ }
429
+ return `
430
+ <div class="facet">
431
+ <div class="facet-header">
432
+ <span class="facet-id">${statusIcon} ${fc.facet.id}</span>
433
+ <span class="facet-type">${fc.facet.type}</span>
434
+ </div>
435
+ <div class="facet-source">
436
+ ${fc.facet.source.file}#${fc.facet.source.section}
437
+ </div>
438
+ ${testsHtml}
439
+ </div>`;
440
+ }
441
+ /**
442
+ * Generate uncovered facets section
443
+ */
444
+ generateUncoveredSection(report) {
445
+ if (report.uncovered.length === 0)
446
+ return '';
447
+ const items = report.uncovered.map(facet => `
448
+ <li>
449
+ <strong>${facet.id}</strong> (${facet.type})<br>
450
+ <span style="color: var(--color-muted)">${facet.source.file}#${facet.source.section}</span>
451
+ </li>`).join('');
452
+ return `
453
+ <section class="card">
454
+ <h2>❌ Uncovered Facets</h2>
455
+ <ul class="uncovered-list">
456
+ ${items}
457
+ </ul>
458
+ </section>`;
459
+ }
460
+ /**
461
+ * Get CSS class for coverage percentage
462
+ */
463
+ getCoverageClass(percentage) {
464
+ if (percentage >= 80)
465
+ return 'success';
466
+ if (percentage >= 50)
467
+ return 'warning';
468
+ return 'error';
469
+ }
470
+ /**
471
+ * Write HTML report to file
472
+ */
473
+ write(report, cwd = process.cwd()) {
474
+ const outputDir = (0, path_1.join)(cwd, this.config.output.dir);
475
+ const outputPath = (0, path_1.join)(outputDir, 'coverage.html');
476
+ // Ensure output directory exists
477
+ (0, fs_1.mkdirSync)(outputDir, { recursive: true });
478
+ const content = this.generate(report);
479
+ (0, fs_1.writeFileSync)(outputPath, content, 'utf-8');
480
+ return outputPath;
481
+ }
482
+ }
483
+ exports.HtmlReporter = HtmlReporter;
484
+ //# sourceMappingURL=HtmlReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HtmlReporter.js","sourceRoot":"","sources":["../../src/reporters/HtmlReporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { CoverageReport, FacetConfig } from '../types.js';
2
+ /**
3
+ * Generates JSON coverage reports
4
+ */
5
+ export declare class JsonReporter {
6
+ private config;
7
+ constructor(config?: Partial<FacetConfig>);
8
+ /**
9
+ * Generate JSON report
10
+ */
11
+ generate(report: CoverageReport, cwd?: string): string;
12
+ /**
13
+ * Write JSON report to file
14
+ */
15
+ write(report: CoverageReport, cwd?: string): string;
16
+ /**
17
+ * Generate a minimal summary JSON (useful for CI)
18
+ */
19
+ generateSummary(report: CoverageReport): string;
20
+ }
21
+ //# sourceMappingURL=JsonReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonReporter.d.ts","sourceRoot":"","sources":["../../src/reporters/JsonReporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/D;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAI7C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM;IAIrE;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM;IAalE;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;CAqBhD"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonReporter = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const types_js_1 = require("../types.js");
7
+ /**
8
+ * Generates JSON coverage reports
9
+ */
10
+ class JsonReporter {
11
+ config;
12
+ constructor(config = {}) {
13
+ this.config = { ...types_js_1.defaultConfig, ...config };
14
+ }
15
+ /**
16
+ * Generate JSON report
17
+ */
18
+ generate(report, cwd = process.cwd()) {
19
+ return JSON.stringify(report, null, 2);
20
+ }
21
+ /**
22
+ * Write JSON report to file
23
+ */
24
+ write(report, cwd = process.cwd()) {
25
+ const outputDir = (0, path_1.join)(cwd, this.config.output.dir);
26
+ const outputPath = (0, path_1.join)(outputDir, 'coverage.json');
27
+ // Ensure output directory exists
28
+ (0, fs_1.mkdirSync)(outputDir, { recursive: true });
29
+ const content = this.generate(report, cwd);
30
+ (0, fs_1.writeFileSync)(outputPath, content, 'utf-8');
31
+ return outputPath;
32
+ }
33
+ /**
34
+ * Generate a minimal summary JSON (useful for CI)
35
+ */
36
+ generateSummary(report) {
37
+ const summary = {
38
+ timestamp: report.timestamp,
39
+ coverage: report.summary.percentage,
40
+ total: report.summary.totalFacets,
41
+ covered: report.summary.coveredFacets,
42
+ uncovered: report.summary.uncoveredFacets,
43
+ byType: report.byType.reduce((acc, t) => {
44
+ acc[t.type] = t.percentage;
45
+ return acc;
46
+ }, {}),
47
+ features: report.features.map(f => ({
48
+ name: f.feature,
49
+ coverage: f.percentage,
50
+ total: f.totalFacets,
51
+ covered: f.coveredFacets,
52
+ })),
53
+ };
54
+ return JSON.stringify(summary, null, 2);
55
+ }
56
+ }
57
+ exports.JsonReporter = JsonReporter;
58
+ //# sourceMappingURL=JsonReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonReporter.js","sourceRoot":"","sources":["../../src/reporters/JsonReporter.ts"],"names":[],"mappings":";;;AAAA,2BAA8C;AAC9C,+BAAqC;AAErC,0CAA4C;AAE5C;;GAEG;AACH,MAAa,YAAY;IACf,MAAM,CAAc;IAE5B,YAAY,SAA+B,EAAE;QAC3C,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,wBAAa,EAAE,GAAG,MAAM,EAAE,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,MAAsB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;QAC1D,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAsB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;QACvD,MAAM,SAAS,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAEpD,iCAAiC;QACjC,IAAA,cAAS,EAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAA,kBAAa,EAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAE5C,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,MAAsB;QACpC,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;YACnC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;YACjC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa;YACrC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe;YACzC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;gBACtC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;gBAC3B,OAAO,GAAG,CAAC;YACb,CAAC,EAAE,EAA4B,CAAC;YAChC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAClC,IAAI,EAAE,CAAC,CAAC,OAAO;gBACf,QAAQ,EAAE,CAAC,CAAC,UAAU;gBACtB,KAAK,EAAE,CAAC,CAAC,WAAW;gBACpB,OAAO,EAAE,CAAC,CAAC,aAAa;aACzB,CAAC,CAAC;SACJ,CAAC;QAEF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;CACF;AAtDD,oCAsDC"}
@@ -0,0 +1,25 @@
1
+ import type { CoverageReport, FacetConfig } from '../types.js';
2
+ /**
3
+ * Generates Markdown coverage reports
4
+ */
5
+ export declare class MarkdownReporter {
6
+ private config;
7
+ constructor(config?: Partial<FacetConfig>);
8
+ /**
9
+ * Generate Markdown report
10
+ */
11
+ generate(report: CoverageReport): string;
12
+ /**
13
+ * Generate section for a single feature
14
+ */
15
+ private generateFeatureSection;
16
+ /**
17
+ * Generate details for a single facet
18
+ */
19
+ private generateFacetDetails;
20
+ /**
21
+ * Write Markdown report to file
22
+ */
23
+ write(report: CoverageReport, cwd?: string): string;
24
+ }
25
+ //# sourceMappingURL=MarkdownReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownReporter.d.ts","sourceRoot":"","sources":["../../src/reporters/MarkdownReporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAkC,MAAM,aAAa,CAAC;AAG/F;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAI7C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IA8DxC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA2C9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM;CAYnE"}