@ng-prism/plugin-coverage 21.12.0-beta.2 → 22.0.0-beta.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 CHANGED
@@ -12,10 +12,10 @@ npm install @ng-prism/plugin-coverage
12
12
 
13
13
  ### Peer Dependencies
14
14
 
15
- | Package | Version |
16
- |---|---|
15
+ | Package | Version |
16
+ | ---------------- | ---------- |
17
17
  | `@ng-prism/core` | `>=21.0.0` |
18
- | `@angular/core` | `>=20.0.0` |
18
+ | `@angular/core` | `>=20.0.0` |
19
19
 
20
20
  ## Setup
21
21
 
@@ -43,10 +43,10 @@ export default defineConfig({
43
43
 
44
44
  ## Options
45
45
 
46
- | Option | Default | Description |
47
- |---|---|---|
48
- | `coveragePath` | `'coverage/coverage-summary.json'` | Path to the Istanbul coverage summary file (relative to workspace root) |
49
- | `thresholds` | `80` for all metrics | Minimum acceptable percentage per metric. Files below the threshold are highlighted in red in the per-file table. Number → applied to all metrics; partial object → keys you omit fall back to `80`. |
46
+ | Option | Default | Description |
47
+ | -------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
48
+ | `coveragePath` | `'coverage/coverage-summary.json'` | Path to the Istanbul coverage summary file (relative to workspace root) |
49
+ | `thresholds` | `80` for all metrics | Minimum acceptable percentage per metric. Files below the threshold are highlighted in red in the per-file table. Number → applied to all metrics; partial object → keys you omit fall back to `80`. |
50
50
 
51
51
  ```typescript
52
52
  // Single value — applied to lines, branches, functions, statements
@@ -42,14 +42,15 @@ export class CoverageHeaderBadgeComponent {
42
42
  `Functions ${meta.total.functions.pct}% · ` +
43
43
  `Statements ${meta.total.statements.pct}%`,
44
44
  };
45
- }, ...(ngDevMode ? [{ debugName: "data" }] : []));
45
+ }, /* @ts-ignore */
46
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
46
47
  static ɵfac = function CoverageHeaderBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CoverageHeaderBadgeComponent)(); };
47
48
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CoverageHeaderBadgeComponent, selectors: [["prism-coverage-header-badge"]], decls: 1, vars: 1, consts: [[1, "cov-pill", 3, "cov-pill--ok", "cov-pill--warn", "cov-pill--danger", "title"], [1, "cov-pill", 3, "title"], [1, "cov-pill__dot"], [1, "cov-pill__label"], [1, "cov-pill__value"]], template: function CoverageHeaderBadgeComponent_Template(rf, ctx) { if (rf & 1) {
48
49
  i0.ɵɵconditionalCreate(0, CoverageHeaderBadgeComponent_Conditional_0_Template, 8, 8, "span", 0);
49
50
  } if (rf & 2) {
50
51
  let tmp_0_0;
51
52
  i0.ɵɵconditional((tmp_0_0 = ctx.data()) ? 0 : -1, tmp_0_0);
52
- } }, styles: ["[_nghost-%COMP%] { display: inline-flex; align-items: center; }\n\n .cov-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: var(--font-mono);\n font-size: var(--fs-xs);\n padding: 2px 10px;\n border-radius: 9999px;\n line-height: 1.4;\n border: 1px solid var(--prism-border);\n background: var(--prism-input-bg);\n color: var(--prism-text-muted);\n white-space: nowrap;\n }\n\n .cov-pill__dot[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n }\n\n .cov-pill__label[_ngcontent-%COMP%] {\n color: var(--prism-text-ghost);\n letter-spacing: 0.02em;\n }\n\n .cov-pill__value[_ngcontent-%COMP%] {\n color: var(--prism-text);\n font-weight: 600;\n }\n .cov-pill__value[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 1px;\n color: var(--prism-text-muted);\n font-weight: 500;\n }\n\n .cov-pill--ok[_ngcontent-%COMP%] {\n color: var(--prism-success);\n border-color: color-mix(in srgb, var(--prism-success) 35%, transparent);\n background: color-mix(in srgb, var(--prism-success) 12%, transparent);\n }\n .cov-pill--ok[_ngcontent-%COMP%] .cov-pill__label[_ngcontent-%COMP%], \n .cov-pill--ok[_ngcontent-%COMP%] .cov-pill__value[_ngcontent-%COMP%] { color: var(--prism-success); }\n\n .cov-pill--warn[_ngcontent-%COMP%] {\n color: var(--prism-warn);\n border-color: color-mix(in srgb, var(--prism-warn) 35%, transparent);\n background: color-mix(in srgb, var(--prism-warn) 12%, transparent);\n }\n .cov-pill--warn[_ngcontent-%COMP%] .cov-pill__label[_ngcontent-%COMP%], \n .cov-pill--warn[_ngcontent-%COMP%] .cov-pill__value[_ngcontent-%COMP%] { color: var(--prism-warn); }\n\n .cov-pill--danger[_ngcontent-%COMP%] {\n color: var(--prism-danger);\n border-color: color-mix(in srgb, var(--prism-danger) 35%, transparent);\n background: color-mix(in srgb, var(--prism-danger) 12%, transparent);\n }\n .cov-pill--danger[_ngcontent-%COMP%] .cov-pill__label[_ngcontent-%COMP%], \n .cov-pill--danger[_ngcontent-%COMP%] .cov-pill__value[_ngcontent-%COMP%] { color: var(--prism-danger); }"], changeDetection: 0 });
53
+ } }, styles: ["[_nghost-%COMP%] { display: inline-flex; align-items: center; }\n\n .cov-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: var(--font-mono);\n font-size: var(--fs-xs);\n padding: 2px 10px;\n border-radius: 9999px;\n line-height: 1.4;\n border: 1px solid var(--prism-border);\n background: var(--prism-input-bg);\n color: var(--prism-text-muted);\n white-space: nowrap;\n }\n\n .cov-pill__dot[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n }\n\n .cov-pill__label[_ngcontent-%COMP%] {\n color: var(--prism-text-ghost);\n letter-spacing: 0.02em;\n }\n\n .cov-pill__value[_ngcontent-%COMP%] {\n color: var(--prism-text);\n font-weight: 600;\n }\n .cov-pill__value[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 1px;\n color: var(--prism-text-muted);\n font-weight: 500;\n }\n\n .cov-pill--ok[_ngcontent-%COMP%] {\n color: var(--prism-success);\n border-color: color-mix(in srgb, var(--prism-success) 35%, transparent);\n background: color-mix(in srgb, var(--prism-success) 12%, transparent);\n }\n .cov-pill--ok[_ngcontent-%COMP%] .cov-pill__label[_ngcontent-%COMP%], \n .cov-pill--ok[_ngcontent-%COMP%] .cov-pill__value[_ngcontent-%COMP%] { color: var(--prism-success); }\n\n .cov-pill--warn[_ngcontent-%COMP%] {\n color: var(--prism-warn);\n border-color: color-mix(in srgb, var(--prism-warn) 35%, transparent);\n background: color-mix(in srgb, var(--prism-warn) 12%, transparent);\n }\n .cov-pill--warn[_ngcontent-%COMP%] .cov-pill__label[_ngcontent-%COMP%], \n .cov-pill--warn[_ngcontent-%COMP%] .cov-pill__value[_ngcontent-%COMP%] { color: var(--prism-warn); }\n\n .cov-pill--danger[_ngcontent-%COMP%] {\n color: var(--prism-danger);\n border-color: color-mix(in srgb, var(--prism-danger) 35%, transparent);\n background: color-mix(in srgb, var(--prism-danger) 12%, transparent);\n }\n .cov-pill--danger[_ngcontent-%COMP%] .cov-pill__label[_ngcontent-%COMP%], \n .cov-pill--danger[_ngcontent-%COMP%] .cov-pill__value[_ngcontent-%COMP%] { color: var(--prism-danger); }"] });
53
54
  }
54
55
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CoverageHeaderBadgeComponent, [{
55
56
  type: Component,
@@ -1 +1 @@
1
- {"version":3,"file":"coverage-panel.component.d.ts","sourceRoot":"","sources":["../src/coverage-panel.component.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;;AAS7B,qBA0Ja,sBAAsB;IACjC,QAAQ,CAAC,eAAe,+CAAwB;IAEhD,SAAS,CAAC,QAAQ,CAAC,QAAQ,sDAKxB;IAEH,SAAS,CAAC,QAAQ,CAAC,YAAY;;;SAS5B;IAEH,SAAS,CAAC,QAAQ,CAAC,KAAK,uDAErB;IAEH,SAAS,CAAC,QAAQ,CAAC,UAAU,qDAE1B;IAEH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;yCA7B7B,sBAAsB;2CAAtB,sBAAsB;CAiClC"}
1
+ {"version":3,"file":"coverage-panel.component.d.ts","sourceRoot":"","sources":["../src/coverage-panel.component.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;;AAS7B,qBAkKa,sBAAsB;IACjC,QAAQ,CAAC,eAAe,+CAAwB;IAEhD,SAAS,CAAC,QAAQ,CAAC,QAAQ,sDAKxB;IAEH,SAAS,CAAC,QAAQ,CAAC,YAAY;;;SAS5B;IAEH,SAAS,CAAC,QAAQ,CAAC,KAAK,uDAErB;IAEH,SAAS,CAAC,QAAQ,CAAC,UAAU,qDAE1B;IAEH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;yCA7B7B,sBAAsB;2CAAtB,sBAAsB;CAiClC"}
@@ -109,11 +109,13 @@ const FALLBACK_THRESHOLDS = {
109
109
  statements: 80,
110
110
  };
111
111
  export class CoveragePanelComponent {
112
- activeComponent = input(null, ...(ngDevMode ? [{ debugName: "activeComponent" }] : []));
112
+ activeComponent = input(null, /* @ts-ignore */
113
+ ...(ngDevMode ? [{ debugName: "activeComponent" }] : /* istanbul ignore next */ []));
113
114
  coverage = computed(() => {
114
115
  const comp = this.activeComponent();
115
116
  return (comp?.meta?.showcaseConfig?.meta?.['coverage'] ?? null);
116
- }, ...(ngDevMode ? [{ debugName: "coverage" }] : []));
117
+ }, /* @ts-ignore */
118
+ ...(ngDevMode ? [{ debugName: "coverage" }] : /* istanbul ignore next */ []));
117
119
  summaryStats = computed(() => {
118
120
  const c = this.coverage();
119
121
  if (!c?.found)
@@ -124,13 +126,16 @@ export class CoveragePanelComponent {
124
126
  { label: 'Functions', pct: c.functions.pct },
125
127
  { label: 'Statements', pct: c.statements.pct },
126
128
  ];
127
- }, ...(ngDevMode ? [{ debugName: "summaryStats" }] : []));
129
+ }, /* @ts-ignore */
130
+ ...(ngDevMode ? [{ debugName: "summaryStats" }] : /* istanbul ignore next */ []));
128
131
  files = computed(() => {
129
132
  return this.coverage()?.files ?? [];
130
- }, ...(ngDevMode ? [{ debugName: "files" }] : []));
133
+ }, /* @ts-ignore */
134
+ ...(ngDevMode ? [{ debugName: "files" }] : /* istanbul ignore next */ []));
131
135
  thresholds = computed(() => {
132
136
  return this.coverage()?.thresholds ?? FALLBACK_THRESHOLDS;
133
- }, ...(ngDevMode ? [{ debugName: "thresholds" }] : []));
137
+ }, /* @ts-ignore */
138
+ ...(ngDevMode ? [{ debugName: "thresholds" }] : /* istanbul ignore next */ []));
134
139
  fileName(path) {
135
140
  const parts = path.split('/');
136
141
  return parts[parts.length - 1];
@@ -139,9 +144,8 @@ export class CoveragePanelComponent {
139
144
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CoveragePanelComponent, selectors: [["prism-coverage-panel"]], inputs: { activeComponent: [1, "activeComponent"] }, decls: 2, vars: 1, consts: [[1, "cov-body"], [1, "cov-empty"], [1, "cov-summary"], [1, "cov-stat"], [1, "cov-files"], [1, "cov-stat-k"], [1, "cov-stat-v"], [1, "cov-bar"], [1, "cov-bar-fill"], [1, "cov-file", "cov-file--header"], [1, "cov-file"], [1, "cov-file-name"], [1, "cov-file-val"]], template: function CoveragePanelComponent_Template(rf, ctx) { if (rf & 1) {
140
145
  i0.ɵɵconditionalCreate(0, CoveragePanelComponent_Conditional_0_Template, 5, 1, "div", 0)(1, CoveragePanelComponent_Conditional_1_Template, 3, 0, "div", 1);
141
146
  } if (rf & 2) {
142
- let tmp_0_0;
143
- i0.ɵɵconditional(((tmp_0_0 = ctx.coverage()) == null ? null : tmp_0_0.found) ? 0 : 1);
144
- } }, styles: ["[_nghost-%COMP%] { display: block; height: 100%; overflow: auto; }\n\n .cov-body[_ngcontent-%COMP%] { padding: 20px 24px; }\n\n .cov-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 12px;\n margin-bottom: 18px;\n }\n\n .cov-stat[_ngcontent-%COMP%] {\n padding: 12px 14px;\n background: var(--prism-bg-surface);\n border: 1px solid var(--prism-border);\n border-radius: 8px;\n }\n .cov-stat-k[_ngcontent-%COMP%] {\n font-size: 10.5px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--prism-text-ghost);\n font-weight: 700;\n margin-bottom: 6px;\n }\n .cov-stat-v[_ngcontent-%COMP%] {\n font-family: var(--font-mono);\n font-size: 22px;\n font-weight: 700;\n color: var(--prism-text);\n letter-spacing: -0.02em;\n }\n .cov-stat-v[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--prism-text-muted);\n font-weight: 500;\n }\n .cov-bar[_ngcontent-%COMP%] {\n margin-top: 8px;\n height: 4px;\n background: var(--prism-input-bg);\n border-radius: 2px;\n overflow: hidden;\n }\n .cov-bar-fill[_ngcontent-%COMP%] {\n height: 100%;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n border-radius: 2px;\n transition: width 0.6s;\n }\n\n .cov-files[_ngcontent-%COMP%] {\n padding: 12px;\n background: var(--prism-bg-surface);\n border: 1px solid var(--prism-border);\n border-radius: 8px;\n }\n\n .cov-file[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto auto auto auto;\n align-items: center;\n gap: 16px;\n padding: 7px 4px;\n font-family: var(--font-mono);\n font-size: 12px;\n border-bottom: 1px solid var(--prism-border);\n }\n .cov-file[_ngcontent-%COMP%]:last-child { border-bottom: 0; }\n\n .cov-file--header[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--prism-border-strong);\n padding-bottom: 8px;\n color: var(--prism-text-ghost);\n font-size: 10.5px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n font-weight: 700;\n }\n\n .cov-file-name[_ngcontent-%COMP%] { color: var(--prism-text-2); }\n .cov-file-val[_ngcontent-%COMP%] {\n color: var(--prism-text);\n min-width: 54px;\n text-align: right;\n }\n .cov-file-val.bad[_ngcontent-%COMP%] { color: var(--prism-warn); }\n\n .cov-empty[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 120px;\n color: var(--prism-text-muted);\n font-size: 13px;\n text-align: center;\n }"], changeDetection: 0 });
147
+ i0.ɵɵconditional(ctx.coverage()?.found ? 0 : 1);
148
+ } }, styles: ["[_nghost-%COMP%] { display: block; height: 100%; overflow: auto; }\n\n .cov-body[_ngcontent-%COMP%] { padding: 20px 24px; }\n\n .cov-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 12px;\n margin-bottom: 18px;\n }\n\n .cov-stat[_ngcontent-%COMP%] {\n padding: 12px 14px;\n background: var(--prism-bg-surface);\n border: 1px solid var(--prism-border);\n border-radius: 8px;\n }\n .cov-stat-k[_ngcontent-%COMP%] {\n font-size: 10.5px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--prism-text-ghost);\n font-weight: 700;\n margin-bottom: 6px;\n }\n .cov-stat-v[_ngcontent-%COMP%] {\n font-family: var(--font-mono);\n font-size: 22px;\n font-weight: 700;\n color: var(--prism-text);\n letter-spacing: -0.02em;\n }\n .cov-stat-v[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--prism-text-muted);\n font-weight: 500;\n }\n .cov-bar[_ngcontent-%COMP%] {\n margin-top: 8px;\n height: 4px;\n background: var(--prism-input-bg);\n border-radius: 2px;\n overflow: hidden;\n }\n .cov-bar-fill[_ngcontent-%COMP%] {\n height: 100%;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n border-radius: 2px;\n transition: width 0.6s;\n }\n\n .cov-files[_ngcontent-%COMP%] {\n padding: 12px;\n background: var(--prism-bg-surface);\n border: 1px solid var(--prism-border);\n border-radius: 8px;\n }\n\n .cov-file[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto auto auto auto;\n align-items: center;\n gap: 16px;\n padding: 7px 4px;\n font-family: var(--font-mono);\n font-size: 12px;\n border-bottom: 1px solid var(--prism-border);\n }\n .cov-file[_ngcontent-%COMP%]:last-child { border-bottom: 0; }\n\n .cov-file--header[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--prism-border-strong);\n padding-bottom: 8px;\n color: var(--prism-text-ghost);\n font-size: 10.5px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n font-weight: 700;\n }\n\n .cov-file-name[_ngcontent-%COMP%] { color: var(--prism-text-2); }\n .cov-file-val[_ngcontent-%COMP%] {\n color: var(--prism-text);\n min-width: 54px;\n text-align: right;\n }\n .cov-file-val.bad[_ngcontent-%COMP%] { color: var(--prism-warn); }\n\n .cov-empty[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 120px;\n color: var(--prism-text-muted);\n font-size: 13px;\n text-align: center;\n }"] });
145
149
  }
146
150
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CoveragePanelComponent, [{
147
151
  type: Component,
@@ -172,16 +176,24 @@ export class CoveragePanelComponent {
172
176
  @for (file of files(); track file.path) {
173
177
  <div class="cov-file">
174
178
  <span class="cov-file-name">{{ fileName(file.path) }}</span>
175
- <span class="cov-file-val" [class.bad]="file.lines.pct < thresholds().lines"
179
+ <span
180
+ class="cov-file-val"
181
+ [class.bad]="file.lines.pct < thresholds().lines"
176
182
  >{{ file.lines.pct }}%</span
177
183
  >
178
- <span class="cov-file-val" [class.bad]="file.branches.pct < thresholds().branches"
184
+ <span
185
+ class="cov-file-val"
186
+ [class.bad]="file.branches.pct < thresholds().branches"
179
187
  >{{ file.branches.pct }}%</span
180
188
  >
181
- <span class="cov-file-val" [class.bad]="file.functions.pct < thresholds().functions"
189
+ <span
190
+ class="cov-file-val"
191
+ [class.bad]="file.functions.pct < thresholds().functions"
182
192
  >{{ file.functions.pct }}%</span
183
193
  >
184
- <span class="cov-file-val" [class.bad]="file.statements.pct < thresholds().statements"
194
+ <span
195
+ class="cov-file-val"
196
+ [class.bad]="file.statements.pct < thresholds().statements"
185
197
  >{{ file.statements.pct }}%</span
186
198
  >
187
199
  </div>
@@ -196,4 +208,4 @@ export class CoveragePanelComponent {
196
208
  }
197
209
  `, styles: ["\n :host { display: block; height: 100%; overflow: auto; }\n\n .cov-body { padding: 20px 24px; }\n\n .cov-summary {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 12px;\n margin-bottom: 18px;\n }\n\n .cov-stat {\n padding: 12px 14px;\n background: var(--prism-bg-surface);\n border: 1px solid var(--prism-border);\n border-radius: 8px;\n }\n .cov-stat-k {\n font-size: 10.5px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--prism-text-ghost);\n font-weight: 700;\n margin-bottom: 6px;\n }\n .cov-stat-v {\n font-family: var(--font-mono);\n font-size: 22px;\n font-weight: 700;\n color: var(--prism-text);\n letter-spacing: -0.02em;\n }\n .cov-stat-v small {\n font-size: 13px;\n color: var(--prism-text-muted);\n font-weight: 500;\n }\n .cov-bar {\n margin-top: 8px;\n height: 4px;\n background: var(--prism-input-bg);\n border-radius: 2px;\n overflow: hidden;\n }\n .cov-bar-fill {\n height: 100%;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n border-radius: 2px;\n transition: width 0.6s;\n }\n\n .cov-files {\n padding: 12px;\n background: var(--prism-bg-surface);\n border: 1px solid var(--prism-border);\n border-radius: 8px;\n }\n\n .cov-file {\n display: grid;\n grid-template-columns: 1fr auto auto auto auto;\n align-items: center;\n gap: 16px;\n padding: 7px 4px;\n font-family: var(--font-mono);\n font-size: 12px;\n border-bottom: 1px solid var(--prism-border);\n }\n .cov-file:last-child { border-bottom: 0; }\n\n .cov-file--header {\n border-bottom: 1px solid var(--prism-border-strong);\n padding-bottom: 8px;\n color: var(--prism-text-ghost);\n font-size: 10.5px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n font-weight: 700;\n }\n\n .cov-file-name { color: var(--prism-text-2); }\n .cov-file-val {\n color: var(--prism-text);\n min-width: 54px;\n text-align: right;\n }\n .cov-file-val.bad { color: var(--prism-warn); }\n\n .cov-empty {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 120px;\n color: var(--prism-text-muted);\n font-size: 13px;\n text-align: center;\n }\n "] }]
198
210
  }], null, { activeComponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeComponent", required: false }] }] }); })();
199
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CoveragePanelComponent, { className: "CoveragePanelComponent", filePath: "coverage-panel.component.ts", lineNumber: 174 }); })();
211
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CoveragePanelComponent, { className: "CoveragePanelComponent", filePath: "coverage-panel.component.ts", lineNumber: 182 }); })();
@@ -1 +1 @@
1
- {"version":3,"file":"coverage-plugin.d.ts","sourceRoot":"","sources":["../src/coverage-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAIrF,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF,wBAAgB,yBAAyB,CACvC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAC3C,kBAAkB,CAMpB;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAoD7E"}
1
+ {"version":3,"file":"coverage-plugin.d.ts","sourceRoot":"","sources":["../src/coverage-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF,wBAAgB,yBAAyB,CACvC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAC3C,kBAAkB,CAWpB;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAsD7E"}
@@ -9,7 +9,12 @@ export function resolveCoverageThresholds(input) {
9
9
  if (input === undefined)
10
10
  return { ...DEFAULT_COVERAGE_THRESHOLDS };
11
11
  if (typeof input === 'number') {
12
- return { lines: input, branches: input, functions: input, statements: input };
12
+ return {
13
+ lines: input,
14
+ branches: input,
15
+ functions: input,
16
+ statements: input,
17
+ };
13
18
  }
14
19
  return { ...DEFAULT_COVERAGE_THRESHOLDS, ...input };
15
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"coverage-reader.d.ts","sourceRoot":"","sources":["../src/coverage-reader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AA6D7B,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,YAAY,CAoBjG;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAmBpE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAIvE;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
1
+ {"version":3,"file":"coverage-reader.d.ts","sourceRoot":"","sources":["../src/coverage-reader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AAgE7B,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GACxB,YAAY,CAwBd;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAuBpE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAQvE;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -57,7 +57,11 @@ export function readCoverageForFile(coveragePath, componentFilePath) {
57
57
  if (!entryKey)
58
58
  return { ...EMPTY_COVERAGE };
59
59
  const entry = summary[entryKey];
60
- const score = Math.round((entry.statements.pct + entry.branches.pct + entry.functions.pct + entry.lines.pct) / 4);
60
+ const score = Math.round((entry.statements.pct +
61
+ entry.branches.pct +
62
+ entry.functions.pct +
63
+ entry.lines.pct) /
64
+ 4);
61
65
  return {
62
66
  score,
63
67
  statements: { ...entry.statements },
@@ -74,7 +78,11 @@ export function readTotalCoverage(coveragePath) {
74
78
  const total = summary['total'];
75
79
  if (!total)
76
80
  return { ...EMPTY_COVERAGE };
77
- const score = Math.round((total.statements.pct + total.branches.pct + total.functions.pct + total.lines.pct) / 4);
81
+ const score = Math.round((total.statements.pct +
82
+ total.branches.pct +
83
+ total.functions.pct +
84
+ total.lines.pct) /
85
+ 4);
78
86
  return {
79
87
  score,
80
88
  statements: { ...total.statements },
@@ -85,7 +93,11 @@ export function readTotalCoverage(coveragePath) {
85
93
  };
86
94
  }
87
95
  export function averageThreshold(thresholds) {
88
- return Math.round((thresholds.lines + thresholds.branches + thresholds.functions + thresholds.statements) / 4);
96
+ return Math.round((thresholds.lines +
97
+ thresholds.branches +
98
+ thresholds.functions +
99
+ thresholds.statements) /
100
+ 4);
89
101
  }
90
102
  export function clearCoverageCache() {
91
103
  cache.clear();
@@ -0,0 +1,4 @@
1
+ import { type Rule } from '@angular-devkit/schematics';
2
+ import type { NgAddSchemaOptions } from './schema.js';
3
+ export declare function ngAdd(options: NgAddSchemaOptions): Rule;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/schematics/ng-add/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,IAAI,EAGV,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAyBtD,wBAAgB,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAEvD"}
@@ -0,0 +1,25 @@
1
+ import { chain, } from '@angular-devkit/schematics';
2
+ import { addPluginToConfig } from '@ng-prism/core/schematics/utils';
3
+ const PLUGIN_IMPORT_NAME = 'coveragePlugin';
4
+ const PLUGIN_IMPORT_FROM = '@ng-prism/plugin-coverage';
5
+ const PLUGIN_CALL = 'coveragePlugin()';
6
+ function injectPlugin(options) {
7
+ return (tree, context) => {
8
+ const configPath = options.configPath ?? 'ng-prism.config.ts';
9
+ const changed = addPluginToConfig(tree, configPath, {
10
+ importName: PLUGIN_IMPORT_NAME,
11
+ importFrom: PLUGIN_IMPORT_FROM,
12
+ call: PLUGIN_CALL,
13
+ });
14
+ if (changed) {
15
+ context.logger.info(` ${PLUGIN_IMPORT_FROM} → added to ${configPath}`);
16
+ }
17
+ else {
18
+ context.logger.info(` ${PLUGIN_IMPORT_FROM} already configured — skipped`);
19
+ }
20
+ return tree;
21
+ };
22
+ }
23
+ export function ngAdd(options) {
24
+ return chain([injectPlugin(options)]);
25
+ }
@@ -0,0 +1,4 @@
1
+ export interface NgAddSchemaOptions {
2
+ configPath?: string;
3
+ }
4
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/schematics/ng-add/schema.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "@ng-prism/plugin-coverage",
3
- "version": "21.12.0-beta.2",
3
+ "version": "22.0.0-beta.0",
4
4
  "description": "Test coverage panel for ng-prism.",
5
+ "ng-add": {
6
+ "save": "devDependencies"
7
+ },
8
+ "schematics": "./schematics/collection.json",
5
9
  "keywords": [
6
10
  "@ng-prism/core",
7
11
  "coverage",
@@ -26,11 +30,12 @@
26
30
  },
27
31
  "files": [
28
32
  "dist",
33
+ "schematics",
29
34
  "!**/*.tsbuildinfo"
30
35
  ],
31
36
  "peerDependencies": {
32
- "@angular/core": ">=21.0.0",
33
- "@ng-prism/core": "^21.12.0-0"
37
+ "@angular/core": ">=20.0.0",
38
+ "@ng-prism/core": "^22.0.0-0"
34
39
  },
35
40
  "devDependencies": {
36
41
  "@ng-prism/core": "*"
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
3
+ "schematics": {
4
+ "ng-add": {
5
+ "description": "Adds @ng-prism/plugin-coverage to the ng-prism config",
6
+ "factory": "../dist/schematics/ng-add/index#ngAdd",
7
+ "schema": "./ng-add/schema.json"
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "NgPrismPluginCoverageNgAdd",
4
+ "title": "Add @ng-prism/plugin-coverage",
5
+ "description": "Registers @ng-prism/plugin-coverage in ng-prism.config.ts",
6
+ "type": "object",
7
+ "properties": {
8
+ "configPath": {
9
+ "type": "string",
10
+ "description": "Path to ng-prism.config.ts",
11
+ "default": "ng-prism.config.ts"
12
+ }
13
+ },
14
+ "required": [],
15
+ "additionalProperties": false
16
+ }