perfgraph 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.
- package/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/causal/builder.d.ts +34 -0
- package/dist/causal/builder.d.ts.map +1 -0
- package/dist/causal/builder.js +132 -0
- package/dist/causal/builder.js.map +1 -0
- package/dist/causal/index.d.ts +11 -0
- package/dist/causal/index.d.ts.map +1 -0
- package/dist/causal/index.js +10 -0
- package/dist/causal/index.js.map +1 -0
- package/dist/causal/rules/js.d.ts +49 -0
- package/dist/causal/rules/js.d.ts.map +1 -0
- package/dist/causal/rules/js.js +209 -0
- package/dist/causal/rules/js.js.map +1 -0
- package/dist/causal/rules/layout.d.ts +39 -0
- package/dist/causal/rules/layout.d.ts.map +1 -0
- package/dist/causal/rules/layout.js +169 -0
- package/dist/causal/rules/layout.js.map +1 -0
- package/dist/causal/rules/lcp.d.ts +49 -0
- package/dist/causal/rules/lcp.d.ts.map +1 -0
- package/dist/causal/rules/lcp.js +250 -0
- package/dist/causal/rules/lcp.js.map +1 -0
- package/dist/causal/rules/network.d.ts +39 -0
- package/dist/causal/rules/network.d.ts.map +1 -0
- package/dist/causal/rules/network.js +140 -0
- package/dist/causal/rules/network.js.map +1 -0
- package/dist/causal/types.d.ts +142 -0
- package/dist/causal/types.d.ts.map +1 -0
- package/dist/causal/types.js +88 -0
- package/dist/causal/types.js.map +1 -0
- package/dist/cli/analyze.d.ts +33 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +137 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/collect.d.ts +28 -0
- package/dist/cli/collect.d.ts.map +1 -0
- package/dist/cli/collect.js +125 -0
- package/dist/cli/collect.js.map +1 -0
- package/dist/cli/extract.d.ts +31 -0
- package/dist/cli/extract.d.ts.map +1 -0
- package/dist/cli/extract.js +135 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/mcp.d.ts +14 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +53 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/normalize.d.ts +58 -0
- package/dist/cli/normalize.d.ts.map +1 -0
- package/dist/cli/normalize.js +179 -0
- package/dist/cli/normalize.js.map +1 -0
- package/dist/cli/report.d.ts +33 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +137 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/run.d.ts +49 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +243 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/collect/buffer-monitor.d.ts +25 -0
- package/dist/collect/buffer-monitor.d.ts.map +1 -0
- package/dist/collect/buffer-monitor.js +69 -0
- package/dist/collect/buffer-monitor.js.map +1 -0
- package/dist/collect/console.d.ts +25 -0
- package/dist/collect/console.d.ts.map +1 -0
- package/dist/collect/console.js +82 -0
- package/dist/collect/console.js.map +1 -0
- package/dist/collect/coverage.d.ts +26 -0
- package/dist/collect/coverage.d.ts.map +1 -0
- package/dist/collect/coverage.js +99 -0
- package/dist/collect/coverage.js.map +1 -0
- package/dist/collect/dom.d.ts +37 -0
- package/dist/collect/dom.d.ts.map +1 -0
- package/dist/collect/dom.js +118 -0
- package/dist/collect/dom.js.map +1 -0
- package/dist/collect/lighthouse.d.ts +41 -0
- package/dist/collect/lighthouse.d.ts.map +1 -0
- package/dist/collect/lighthouse.js +111 -0
- package/dist/collect/lighthouse.js.map +1 -0
- package/dist/collect/network.d.ts +32 -0
- package/dist/collect/network.d.ts.map +1 -0
- package/dist/collect/network.js +236 -0
- package/dist/collect/network.js.map +1 -0
- package/dist/collect/orchestrator.d.ts +23 -0
- package/dist/collect/orchestrator.d.ts.map +1 -0
- package/dist/collect/orchestrator.js +350 -0
- package/dist/collect/orchestrator.js.map +1 -0
- package/dist/collect/performance.d.ts +28 -0
- package/dist/collect/performance.d.ts.map +1 -0
- package/dist/collect/performance.js +108 -0
- package/dist/collect/performance.js.map +1 -0
- package/dist/collect/runtime.d.ts +26 -0
- package/dist/collect/runtime.d.ts.map +1 -0
- package/dist/collect/runtime.js +81 -0
- package/dist/collect/runtime.js.map +1 -0
- package/dist/collect/session.d.ts +58 -0
- package/dist/collect/session.d.ts.map +1 -0
- package/dist/collect/session.js +162 -0
- package/dist/collect/session.js.map +1 -0
- package/dist/collect/trace.d.ts +40 -0
- package/dist/collect/trace.d.ts.map +1 -0
- package/dist/collect/trace.js +127 -0
- package/dist/collect/trace.js.map +1 -0
- package/dist/collect/types.d.ts +317 -0
- package/dist/collect/types.d.ts.map +1 -0
- package/dist/collect/types.js +12 -0
- package/dist/collect/types.js.map +1 -0
- package/dist/distill/insights.d.ts +67 -0
- package/dist/distill/insights.d.ts.map +1 -0
- package/dist/distill/insights.js +317 -0
- package/dist/distill/insights.js.map +1 -0
- package/dist/distill/summaries.d.ts +71 -0
- package/dist/distill/summaries.d.ts.map +1 -0
- package/dist/distill/summaries.js +165 -0
- package/dist/distill/summaries.js.map +1 -0
- package/dist/extract/critical-path.d.ts +17 -0
- package/dist/extract/critical-path.d.ts.map +1 -0
- package/dist/extract/critical-path.js +95 -0
- package/dist/extract/critical-path.js.map +1 -0
- package/dist/extract/index.d.ts +16 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +32 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/extract/js-hotspots.d.ts +15 -0
- package/dist/extract/js-hotspots.d.ts.map +1 -0
- package/dist/extract/js-hotspots.js +22 -0
- package/dist/extract/js-hotspots.js.map +1 -0
- package/dist/extract/layout-shifts.d.ts +19 -0
- package/dist/extract/layout-shifts.d.ts.map +1 -0
- package/dist/extract/layout-shifts.js +47 -0
- package/dist/extract/layout-shifts.js.map +1 -0
- package/dist/extract/lcp-breakdown.d.ts +19 -0
- package/dist/extract/lcp-breakdown.d.ts.map +1 -0
- package/dist/extract/lcp-breakdown.js +110 -0
- package/dist/extract/lcp-breakdown.js.map +1 -0
- package/dist/extract/main-thread.d.ts +16 -0
- package/dist/extract/main-thread.d.ts.map +1 -0
- package/dist/extract/main-thread.js +41 -0
- package/dist/extract/main-thread.js.map +1 -0
- package/dist/extract/render-blocking.d.ts +16 -0
- package/dist/extract/render-blocking.d.ts.map +1 -0
- package/dist/extract/render-blocking.js +79 -0
- package/dist/extract/render-blocking.js.map +1 -0
- package/dist/extract/third-party.d.ts +15 -0
- package/dist/extract/third-party.d.ts.map +1 -0
- package/dist/extract/third-party.js +127 -0
- package/dist/extract/third-party.js.map +1 -0
- package/dist/extract/types.d.ts +183 -0
- package/dist/extract/types.d.ts.map +1 -0
- package/dist/extract/types.js +118 -0
- package/dist/extract/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers.d.ts +72 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +285 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/progress.d.ts +37 -0
- package/dist/mcp/progress.d.ts.map +1 -0
- package/dist/mcp/progress.js +51 -0
- package/dist/mcp/progress.js.map +1 -0
- package/dist/mcp/prompts.d.ts +57 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +225 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +48 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +149 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +34 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +452 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/types.d.ts +47 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +67 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/normalize/clock.d.ts +40 -0
- package/dist/normalize/clock.d.ts.map +1 -0
- package/dist/normalize/clock.js +96 -0
- package/dist/normalize/clock.js.map +1 -0
- package/dist/normalize/dom-ir.d.ts +16 -0
- package/dist/normalize/dom-ir.d.ts.map +1 -0
- package/dist/normalize/dom-ir.js +48 -0
- package/dist/normalize/dom-ir.js.map +1 -0
- package/dist/normalize/index.d.ts +23 -0
- package/dist/normalize/index.d.ts.map +1 -0
- package/dist/normalize/index.js +118 -0
- package/dist/normalize/index.js.map +1 -0
- package/dist/normalize/lighthouse-insights.d.ts +27 -0
- package/dist/normalize/lighthouse-insights.d.ts.map +1 -0
- package/dist/normalize/lighthouse-insights.js +318 -0
- package/dist/normalize/lighthouse-insights.js.map +1 -0
- package/dist/normalize/lighthouse-ir.d.ts +25 -0
- package/dist/normalize/lighthouse-ir.d.ts.map +1 -0
- package/dist/normalize/lighthouse-ir.js +151 -0
- package/dist/normalize/lighthouse-ir.js.map +1 -0
- package/dist/normalize/network-ir.d.ts +23 -0
- package/dist/normalize/network-ir.d.ts.map +1 -0
- package/dist/normalize/network-ir.js +180 -0
- package/dist/normalize/network-ir.js.map +1 -0
- package/dist/normalize/runtime-ir.d.ts +18 -0
- package/dist/normalize/runtime-ir.d.ts.map +1 -0
- package/dist/normalize/runtime-ir.js +114 -0
- package/dist/normalize/runtime-ir.js.map +1 -0
- package/dist/normalize/trace-ir.d.ts +20 -0
- package/dist/normalize/trace-ir.d.ts.map +1 -0
- package/dist/normalize/trace-ir.js +224 -0
- package/dist/normalize/trace-ir.js.map +1 -0
- package/dist/normalize/types.d.ts +536 -0
- package/dist/normalize/types.d.ts.map +1 -0
- package/dist/normalize/types.js +242 -0
- package/dist/normalize/types.js.map +1 -0
- package/dist/output/manifest.d.ts +44 -0
- package/dist/output/manifest.d.ts.map +1 -0
- package/dist/output/manifest.js +232 -0
- package/dist/output/manifest.js.map +1 -0
- package/dist/output/toon.d.ts +19 -0
- package/dist/output/toon.d.ts.map +1 -0
- package/dist/output/toon.js +22 -0
- package/dist/output/toon.js.map +1 -0
- package/dist/output/writer.d.ts +31 -0
- package/dist/output/writer.d.ts.map +1 -0
- package/dist/output/writer.js +51 -0
- package/dist/output/writer.js.map +1 -0
- package/dist/report/analyzer.d.ts +29 -0
- package/dist/report/analyzer.d.ts.map +1 -0
- package/dist/report/analyzer.js +330 -0
- package/dist/report/analyzer.js.map +1 -0
- package/dist/report/index.d.ts +13 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +12 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/markdown.d.ts +21 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +182 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/remediations.d.ts +42 -0
- package/dist/report/remediations.d.ts.map +1 -0
- package/dist/report/remediations.js +179 -0
- package/dist/report/remediations.js.map +1 -0
- package/dist/report/scorer.d.ts +35 -0
- package/dist/report/scorer.d.ts.map +1 -0
- package/dist/report/scorer.js +72 -0
- package/dist/report/scorer.js.map +1 -0
- package/dist/report/types.d.ts +201 -0
- package/dist/report/types.d.ts.map +1 -0
- package/dist/report/types.js +149 -0
- package/dist/report/types.js.map +1 -0
- package/dist/shared/fs-utils.d.ts +12 -0
- package/dist/shared/fs-utils.d.ts.map +1 -0
- package/dist/shared/fs-utils.js +44 -0
- package/dist/shared/fs-utils.js.map +1 -0
- package/dist/shared/types.d.ts +69 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +18 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/utils.d.ts +6 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/shared/utils.js +9 -0
- package/dist/shared/utils.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown report generator — produces a human-readable performance report
|
|
3
|
+
* from a PerfGraph {@link Report} and optional {@link Insights}.
|
|
4
|
+
*
|
|
5
|
+
* The output is designed for direct consumption by developers and includes
|
|
6
|
+
* score summary, all issues with severities, causal chains, recommendations,
|
|
7
|
+
* and Lighthouse insights when available.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Severity → emoji helpers
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
function severityBadge(severity) {
|
|
15
|
+
switch (severity) {
|
|
16
|
+
case 'critical':
|
|
17
|
+
return '🔴';
|
|
18
|
+
case 'warning':
|
|
19
|
+
return '🟡';
|
|
20
|
+
case 'high':
|
|
21
|
+
return '🟡';
|
|
22
|
+
case 'info':
|
|
23
|
+
return '🔵';
|
|
24
|
+
default:
|
|
25
|
+
return '⚪';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Public API
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
/**
|
|
32
|
+
* Generate a human-readable markdown report from a PerfGraph Report + Insights.
|
|
33
|
+
*
|
|
34
|
+
* @param report - The structured report from `buildReport()`
|
|
35
|
+
* @param insights - Optional Lighthouse-derived insights from `buildInsights()`
|
|
36
|
+
* @returns A formatted Markdown string
|
|
37
|
+
*/
|
|
38
|
+
export function buildReportMarkdown(report, insights) {
|
|
39
|
+
const lines = [];
|
|
40
|
+
// -----------------------------------------------------------------------
|
|
41
|
+
// Header
|
|
42
|
+
// -----------------------------------------------------------------------
|
|
43
|
+
lines.push('# PerfGraph Performance Report');
|
|
44
|
+
lines.push('');
|
|
45
|
+
lines.push(`**URL:** ${report.meta.url}`);
|
|
46
|
+
lines.push(`**Analyzed at:** ${report.meta.analyzedAt}`);
|
|
47
|
+
lines.push(`**Score:** ${report.summary.score.toUpperCase()}`);
|
|
48
|
+
if (report.summary.lighthousePerformance != null) {
|
|
49
|
+
lines.push(`**Lighthouse Performance:** ${(report.summary.lighthousePerformance * 100).toFixed(0)}/100`);
|
|
50
|
+
}
|
|
51
|
+
if (report.summary.scoreExplanation) {
|
|
52
|
+
lines.push(`**Note:** ${report.summary.scoreExplanation}`);
|
|
53
|
+
}
|
|
54
|
+
lines.push('');
|
|
55
|
+
// -----------------------------------------------------------------------
|
|
56
|
+
// Summary stats
|
|
57
|
+
// -----------------------------------------------------------------------
|
|
58
|
+
lines.push('## Summary');
|
|
59
|
+
lines.push('');
|
|
60
|
+
lines.push('| Metric | Count |');
|
|
61
|
+
lines.push('|--------|-------|');
|
|
62
|
+
lines.push(`| Critical issues | ${report.summary.criticalIssues} |`);
|
|
63
|
+
lines.push(`| Warnings | ${report.summary.warnings} |`);
|
|
64
|
+
lines.push(`| Info | ${report.summary.infos} |`);
|
|
65
|
+
lines.push('');
|
|
66
|
+
// -----------------------------------------------------------------------
|
|
67
|
+
// Top Issues
|
|
68
|
+
// -----------------------------------------------------------------------
|
|
69
|
+
if (report.summary.topIssues.length > 0) {
|
|
70
|
+
lines.push('## Top Issues');
|
|
71
|
+
lines.push('');
|
|
72
|
+
for (const issue of report.summary.topIssues) {
|
|
73
|
+
lines.push(`### ${severityBadge(issue.severity)} ${issue.label}`);
|
|
74
|
+
lines.push('');
|
|
75
|
+
lines.push(`- **Confidence:** ${issue.confidence}`);
|
|
76
|
+
lines.push('');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// -----------------------------------------------------------------------
|
|
80
|
+
// All Issues
|
|
81
|
+
// -----------------------------------------------------------------------
|
|
82
|
+
if (report.issues.length > 0) {
|
|
83
|
+
lines.push('## All Issues');
|
|
84
|
+
lines.push('');
|
|
85
|
+
for (const issue of report.issues) {
|
|
86
|
+
lines.push(`### ${severityBadge(issue.severity)} ${issue.label}`);
|
|
87
|
+
lines.push('');
|
|
88
|
+
lines.push(`**ID:** \`${issue.id}\``);
|
|
89
|
+
lines.push(`**Severity:** ${issue.severity}`);
|
|
90
|
+
if (issue.value != null) {
|
|
91
|
+
lines.push(`**Value:** ${issue.value}${issue.unit ? ` ${issue.unit}` : ''}`);
|
|
92
|
+
}
|
|
93
|
+
if (issue.evidence?.urls && issue.evidence.urls.length > 0) {
|
|
94
|
+
lines.push('**URLs:**');
|
|
95
|
+
for (const url of issue.evidence.urls) {
|
|
96
|
+
lines.push(`- \`${url}\``);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (issue.evidence?.selector) {
|
|
100
|
+
lines.push(`**Selector:** \`${issue.evidence.selector}\``);
|
|
101
|
+
}
|
|
102
|
+
lines.push('');
|
|
103
|
+
lines.push(issue.remediation);
|
|
104
|
+
lines.push('');
|
|
105
|
+
lines.push('---');
|
|
106
|
+
lines.push('');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// -----------------------------------------------------------------------
|
|
110
|
+
// Causal Chains
|
|
111
|
+
// -----------------------------------------------------------------------
|
|
112
|
+
if (report.chains.length > 0) {
|
|
113
|
+
lines.push('## Causal Chains');
|
|
114
|
+
lines.push('');
|
|
115
|
+
for (const chain of report.chains) {
|
|
116
|
+
lines.push(`### ${severityBadge(chain.severity)} ${chain.rootCause}`);
|
|
117
|
+
lines.push('');
|
|
118
|
+
lines.push(`**Impact:** ${chain.impact}`);
|
|
119
|
+
lines.push(`**Confidence:** ${chain.confidence}`);
|
|
120
|
+
lines.push(`**Path:** \`${chain.path.map((n) => n.label).join(' → ')}\``);
|
|
121
|
+
lines.push('');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// -----------------------------------------------------------------------
|
|
125
|
+
// Recommendations
|
|
126
|
+
// -----------------------------------------------------------------------
|
|
127
|
+
if (report.recommendations.length > 0) {
|
|
128
|
+
lines.push('## Recommendations');
|
|
129
|
+
lines.push('');
|
|
130
|
+
for (const rec of report.recommendations) {
|
|
131
|
+
const badge = severityBadge(rec.priority);
|
|
132
|
+
lines.push(`### ${badge} [${rec.category}] ${rec.title}`);
|
|
133
|
+
lines.push('');
|
|
134
|
+
lines.push(rec.action);
|
|
135
|
+
if (rec.expectedImpact) {
|
|
136
|
+
lines.push('');
|
|
137
|
+
lines.push(`**Expected impact:** ${rec.expectedImpact}`);
|
|
138
|
+
}
|
|
139
|
+
lines.push('');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// -----------------------------------------------------------------------
|
|
143
|
+
// Lighthouse Insights
|
|
144
|
+
// -----------------------------------------------------------------------
|
|
145
|
+
if (insights?.lighthouse) {
|
|
146
|
+
lines.push('## Lighthouse Insights');
|
|
147
|
+
lines.push('');
|
|
148
|
+
lines.push('| Metric | Value |');
|
|
149
|
+
lines.push('|--------|-------|');
|
|
150
|
+
if (insights.lighthouse.performance != null) {
|
|
151
|
+
lines.push(`| Performance | ${(insights.lighthouse.performance * 100).toFixed(0)} |`);
|
|
152
|
+
}
|
|
153
|
+
if (insights.lighthouse.lcpMs != null) {
|
|
154
|
+
lines.push(`| LCP | ${insights.lighthouse.lcpMs} ms |`);
|
|
155
|
+
}
|
|
156
|
+
if (insights.lighthouse.fcpMs != null) {
|
|
157
|
+
lines.push(`| FCP | ${insights.lighthouse.fcpMs} ms |`);
|
|
158
|
+
}
|
|
159
|
+
if (insights.lighthouse.cls != null) {
|
|
160
|
+
lines.push(`| CLS | ${insights.lighthouse.cls.toFixed(3)} |`);
|
|
161
|
+
}
|
|
162
|
+
if (insights.lighthouse.tbtMs != null) {
|
|
163
|
+
lines.push(`| TBT | ${insights.lighthouse.tbtMs} ms |`);
|
|
164
|
+
}
|
|
165
|
+
lines.push('');
|
|
166
|
+
if (insights.lcpElement) {
|
|
167
|
+
lines.push(`**LCP Element:** \`${insights.lcpElement.selector}\``);
|
|
168
|
+
lines.push('');
|
|
169
|
+
}
|
|
170
|
+
if (insights.renderBlocking && insights.renderBlocking.length > 0) {
|
|
171
|
+
lines.push(`**Render-blocking resources:** ${insights.renderBlocking.length} total`);
|
|
172
|
+
lines.push('');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// -----------------------------------------------------------------------
|
|
176
|
+
// Footer
|
|
177
|
+
// -----------------------------------------------------------------------
|
|
178
|
+
lines.push('---');
|
|
179
|
+
lines.push(`*Generated by PerfGraph at ${report.meta.analyzedAt}*`);
|
|
180
|
+
return lines.join('\n');
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/report/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remediation texts — lookup table of human-readable recommendations
|
|
3
|
+
* keyed by node ID or node type / rule ID patterns.
|
|
4
|
+
*
|
|
5
|
+
* Each entry is a plain-English suggestion for fixing the issue.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export interface RemediationContext {
|
|
10
|
+
/** Evidence payload (URLs, selector, lighthouse audit, metric) */
|
|
11
|
+
evidence?: {
|
|
12
|
+
urls?: string[];
|
|
13
|
+
selector?: string;
|
|
14
|
+
lighthouseAuditId?: string;
|
|
15
|
+
metric?: {
|
|
16
|
+
name: string;
|
|
17
|
+
value: number;
|
|
18
|
+
unit: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/** The issue's value/metric for context (e.g. TTFB=1200) */
|
|
22
|
+
value?: number;
|
|
23
|
+
/** Unit label for the value */
|
|
24
|
+
unit?: string;
|
|
25
|
+
/** Node type for fallback lookup (metric, bottleneck, impact) */
|
|
26
|
+
nodeType?: string;
|
|
27
|
+
/** Rule ID for fallback lookup by prefix */
|
|
28
|
+
ruleId?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get remediation text for an issue by its ID, with optional evidence context
|
|
32
|
+
* to produce parameterized, specific guidance.
|
|
33
|
+
*
|
|
34
|
+
* When `context` provides evidence (URLs, metric values), the returned text
|
|
35
|
+
* includes those details. Without context, falls back to static boilerplate
|
|
36
|
+
* then to rule-prefix and node-type fallbacks.
|
|
37
|
+
*
|
|
38
|
+
* @param issueId - The issue / node ID to remediate
|
|
39
|
+
* @param context - Optional evidence, values, and fallback hints
|
|
40
|
+
*/
|
|
41
|
+
export declare function getRemediation(issueId: string, context?: RemediationContext): string;
|
|
42
|
+
//# sourceMappingURL=remediations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediations.d.ts","sourceRoot":"","sources":["../../src/report/remediations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,MAAM,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;KACxD,CAAC;IACF,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAoID;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,CAsFR"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remediation texts — lookup table of human-readable recommendations
|
|
3
|
+
* keyed by node ID or node type / rule ID patterns.
|
|
4
|
+
*
|
|
5
|
+
* Each entry is a plain-English suggestion for fixing the issue.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
const REMEDIATIONS = {
|
|
10
|
+
// ---- LCP rules ----
|
|
11
|
+
'high-ttfb': 'Optimise TTFB: use a CDN, enable server-side caching, ' +
|
|
12
|
+
'move static assets to the edge, optimise server logic (fastify/compression). ' +
|
|
13
|
+
'Target: TTFB < 800ms.',
|
|
14
|
+
'delayed-html-parse': 'Ensure HTML is streamed without delay — enable chunked transfer encoding, ' +
|
|
15
|
+
'remove blocking middleware on the server.',
|
|
16
|
+
'delayed-css-discovery': 'Inline critical CSS in <head>, load non-critical CSS asynchronously ' +
|
|
17
|
+
'via <link rel="preload" as="style" ...> + onload=this.rel="stylesheet".',
|
|
18
|
+
'blocked-render': 'Eliminate render-blocking resources: inline critical CSS, async/defer for JS, ' +
|
|
19
|
+
'preconnect to third-party origins.',
|
|
20
|
+
'increased-lcp': 'Optimise LCP: ensure the LCP element loads early, use modern image formats ' +
|
|
21
|
+
'(WebP/AVIF) with correct dimensions, ' +
|
|
22
|
+
'add fetchpriority="high" on the LCP image.',
|
|
23
|
+
'rb-resources': 'Reduce the number of render-blocking resources: inline critical CSS, ' +
|
|
24
|
+
'defer non-critical CSS via media="print" onload, use async/defer for scripts.',
|
|
25
|
+
'blocked-render-rb': 'Analyse the render-blocking resource chain in DevTools (Performance → View: KPI Warning). ' +
|
|
26
|
+
'Move non-critical CSS/JS off the critical path.',
|
|
27
|
+
'increased-lcp-rb': 'Use Lighthouse "Eliminate render-blocking resources" for precise recommendations. ' +
|
|
28
|
+
'Consider code splitting and lazy loading for non-critical scripts.',
|
|
29
|
+
'lcp-resource-delay': 'Optimise LCP resource loading: use preload <link rel="preload"> for the LCP image, ' +
|
|
30
|
+
'set fetchpriority="high", optimise the resource itself (compression, modern formats).',
|
|
31
|
+
'increased-lcp-resource': 'Check that the LCP resource is not blocked by other loads. ' +
|
|
32
|
+
'Use HTTP/2 Server Push (with caution) or early preload.',
|
|
33
|
+
// ---- Network rules ----
|
|
34
|
+
'deep-critical-chain': 'Reduce critical chain depth: bundle scripts, use code splitting, ' +
|
|
35
|
+
'lazy-load non-critical resources. A Webpack/Rollup bundle analyser helps find optimisations.',
|
|
36
|
+
'waterfall-delay': 'Analyse the load waterfall in DevTools (Network → Waterfall). ' +
|
|
37
|
+
'Eliminate sequential loads, use preload/preconnect ' +
|
|
38
|
+
'for critical resources.',
|
|
39
|
+
'slow-page-load': 'General slow page load: use Lighthouse to prioritise improvements. ' +
|
|
40
|
+
'Focus on TTFB, render-blocking resources, image optimisation, and JS bundle size.',
|
|
41
|
+
'excessive-requests': 'Reduce the number of requests on the critical path: bundle files, use ' +
|
|
42
|
+
'sprites/SVG, HTTP/2 multiplexing, tree shaking, code splitting.',
|
|
43
|
+
'bandwidth-contention': 'Reduce bandwidth contention: prioritise critical resources (preload), ' +
|
|
44
|
+
'defer non-critical ones (lazy load, async/defer), use HTTP/2.',
|
|
45
|
+
// ---- JS rules ----
|
|
46
|
+
'high-main-thread-blocking': 'Reduce main thread blocking: break up long tasks (<50ms), use ' +
|
|
47
|
+
'Web Workers for background computation, remove heavy polyfills.',
|
|
48
|
+
'high-tbt': 'Use Lighthouse "Reduce JavaScript execution time" for precise recommendations. ' +
|
|
49
|
+
'Optimise heavy scripts, remove dead code (tree shaking).',
|
|
50
|
+
'delayed-inp-tbt': 'INP may be high due to long tasks: break tasks into 50ms chunks with ' +
|
|
51
|
+
'setTimeout(yield) or scheduler.postTask(). Use Browser Timeline to find culprits.',
|
|
52
|
+
'js-hotspots': 'Profile JS hotspots in DevTools (Performance → Main thread). ' +
|
|
53
|
+
'Optimise hot functions, use debounce/throttle for frequent handlers.',
|
|
54
|
+
'long-tasks-js': 'Long tasks block the main thread and delay interaction: ' +
|
|
55
|
+
'break into micro-tasks, use Web Workers, optimise rendering.',
|
|
56
|
+
'delayed-inp-hotspots': 'Improve INP: use passive event listeners, eliminate scroll jank, ' +
|
|
57
|
+
'optimise animations via requestAnimationFrame.',
|
|
58
|
+
'many-scripts': 'Reduce the number of scripts: bundle modules, use code splitting, ' +
|
|
59
|
+
'tree shaking, remove unused dependencies.',
|
|
60
|
+
'long-parse-time': 'Long JS parse/compile time: use code splitting, lazy loading, ' +
|
|
61
|
+
'remove unused code. Modern bundlers (esbuild/swc) reduce compilation time.',
|
|
62
|
+
// ---- Layout rules ----
|
|
63
|
+
'layout-shifts': 'Fix layout shifts: set explicit dimensions (width/height) on images and iframes, ' +
|
|
64
|
+
'use aspect-ratio CSS, reserve space for dynamic content.',
|
|
65
|
+
'high-cls': 'Use Lighthouse "Avoid large layout shifts" for precise recommendations. ' +
|
|
66
|
+
'Inline critical CSS, avoid inserting content above existing content (insertBefore).',
|
|
67
|
+
'layout-shift-clusters': 'Shift clusters indicate dynamic content insertion problems: ' +
|
|
68
|
+
'use CSS contain, reserve space, avoid DOM mutations above visible content.',
|
|
69
|
+
'complex-dom-tree': 'DOM tree is too complex: reduce nesting, use simpler semantic ' +
|
|
70
|
+
'markup, virtualise large lists (Virtual Scroller).',
|
|
71
|
+
'layout-instability': 'Use CSS contain: layout to isolate each component. ' +
|
|
72
|
+
'This limits layout recalculation scope on changes.',
|
|
73
|
+
};
|
|
74
|
+
// Fallback by node type
|
|
75
|
+
const TYPE_FALLBACKS = {
|
|
76
|
+
metric: 'Analyse this metric against your project baseline. ' +
|
|
77
|
+
'Target compliance with Google Core Web Vitals.',
|
|
78
|
+
bottleneck: 'Eliminate this bottleneck: it may cascade into other metric regressions.',
|
|
79
|
+
impact: 'This metric indicates a negative impact on user experience. ' +
|
|
80
|
+
'Fix the root causes listed in the dependency chain.',
|
|
81
|
+
};
|
|
82
|
+
// Fallback by rule ID prefix
|
|
83
|
+
const RULE_FALLBACKS = {
|
|
84
|
+
lcp: 'Check Lighthouse recommendations for Largest Contentful Paint improvements (Performance → LCP).',
|
|
85
|
+
net: 'Optimise network resource loading: reduce request count, ' +
|
|
86
|
+
'use HTTP/2, preload critical resources.',
|
|
87
|
+
js: 'Optimise JavaScript: reduce bundle size, use code splitting, ' +
|
|
88
|
+
'remove dead code, break up long tasks.',
|
|
89
|
+
layout: 'Stabilise the layout: set element dimensions, avoid unexpected ' +
|
|
90
|
+
'content insertion, use CSS contain.',
|
|
91
|
+
};
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Public API
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
/**
|
|
96
|
+
* Get remediation text for an issue by its ID, with optional evidence context
|
|
97
|
+
* to produce parameterized, specific guidance.
|
|
98
|
+
*
|
|
99
|
+
* When `context` provides evidence (URLs, metric values), the returned text
|
|
100
|
+
* includes those details. Without context, falls back to static boilerplate
|
|
101
|
+
* then to rule-prefix and node-type fallbacks.
|
|
102
|
+
*
|
|
103
|
+
* @param issueId - The issue / node ID to remediate
|
|
104
|
+
* @param context - Optional evidence, values, and fallback hints
|
|
105
|
+
*/
|
|
106
|
+
export function getRemediation(issueId, context) {
|
|
107
|
+
// ---- Parameterized remediations (evidence-aware) ----
|
|
108
|
+
if (context) {
|
|
109
|
+
// Render-blocking resources with specific URLs
|
|
110
|
+
if (issueId === 'rb-resources' && context.evidence?.urls && context.evidence.urls.length > 0) {
|
|
111
|
+
const urls = context.evidence.urls.join(', ');
|
|
112
|
+
return `Render-blocking resources: ${urls}. Consider inlining critical CSS, deferring non-critical stylesheets, and adding preload hints.`;
|
|
113
|
+
}
|
|
114
|
+
// TTFB with measured value
|
|
115
|
+
if (issueId === 'high-ttfb' && context.value != null) {
|
|
116
|
+
return `High TTFB (${context.value}ms). Optimize server response time: use CDN, enable caching, upgrade hosting, or move server closer to users.`;
|
|
117
|
+
}
|
|
118
|
+
// Deep critical chain with URLs
|
|
119
|
+
if (issueId === 'deep-critical-chain' && context.evidence?.urls && context.evidence.urls.length > 0) {
|
|
120
|
+
return `Deep critical chain (${context.value ?? '?'} levels): ${context.evidence.urls.join(' → ')}. Optimize dependency ordering and lazy-load non-critical resources.`;
|
|
121
|
+
}
|
|
122
|
+
// Layout shifts with CLS value
|
|
123
|
+
if (issueId === 'layout-shifts' && context.value != null) {
|
|
124
|
+
return `Layout shifts detected (CLS: ${context.value.toFixed(3)}). Ensure all elements have explicit dimensions, avoid inserting content above existing content.`;
|
|
125
|
+
}
|
|
126
|
+
// CLS with value
|
|
127
|
+
if (issueId === 'high-cls' && context.value != null) {
|
|
128
|
+
return `High CLS (${context.value.toFixed(3)}). Use Lighthouse "Avoid large layout shifts" for precise recommendations. Inline critical CSS, avoid inserting content above existing content (insertBefore).`;
|
|
129
|
+
}
|
|
130
|
+
// Main thread blocking with value
|
|
131
|
+
if (issueId === 'high-main-thread-blocking' && context.value != null) {
|
|
132
|
+
return `High main thread blocking (${context.value}ms). Break up long tasks, defer non-critical JavaScript, use web workers for heavy computation.`;
|
|
133
|
+
}
|
|
134
|
+
// Render-blocking chain with URLs
|
|
135
|
+
if (issueId === 'rb-chain' && context.evidence?.urls && context.evidence.urls.length > 0) {
|
|
136
|
+
const urls = context.evidence.urls.join(', ');
|
|
137
|
+
return `Render-blocking chain: ${urls}. Analyse the waterfall in DevTools (Performance → View: KPI Warning). Move unused CSS/JS off the critical path.`;
|
|
138
|
+
}
|
|
139
|
+
// Render-blocking LCP with URLs
|
|
140
|
+
if (issueId === 'render-blocking-lcp' && context.evidence?.urls && context.evidence.urls.length > 0) {
|
|
141
|
+
const urls = context.evidence.urls.join(', ');
|
|
142
|
+
return `Render-blocking resources delaying LCP: ${urls}. Use Lighthouse "Eliminate render-blocking resources" for precise recommendations. Consider code splitting and lazy loading for non-critical scripts.`;
|
|
143
|
+
}
|
|
144
|
+
// Increased LCP with value
|
|
145
|
+
if (issueId === 'increased-lcp' && context.value != null) {
|
|
146
|
+
return `LCP is high (${context.value}ms). Optimise the LCP element: ensure it loads early, use modern image formats (WebP/AVIF) with correct dimensions, add fetchpriority="high" on the LCP image.`;
|
|
147
|
+
}
|
|
148
|
+
// High TBT with value
|
|
149
|
+
if (issueId === 'high-tbt' && context.value != null) {
|
|
150
|
+
return `High Total Blocking Time (${context.value}ms). Use Lighthouse "Reduce JavaScript execution time" for precise recommendations. Optimise heavy scripts, remove dead code (tree shaking).`;
|
|
151
|
+
}
|
|
152
|
+
// Waterfall delay with URLs
|
|
153
|
+
if (issueId === 'waterfall-delay' && context.evidence?.urls && context.evidence.urls.length > 0) {
|
|
154
|
+
const urls = context.evidence.urls.join(', ');
|
|
155
|
+
return `Sequential waterfall detected: ${urls}. Analyse the Network waterfall in DevTools, use preload/preconnect for critical resources.`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// ---- Static exact match ----
|
|
159
|
+
if (REMEDIATIONS[issueId]) {
|
|
160
|
+
return REMEDIATIONS[issueId];
|
|
161
|
+
}
|
|
162
|
+
// ---- Rule-based fallback ----
|
|
163
|
+
const ruleId = context?.ruleId;
|
|
164
|
+
if (ruleId) {
|
|
165
|
+
for (const [prefix, text] of Object.entries(RULE_FALLBACKS)) {
|
|
166
|
+
if (ruleId.startsWith(prefix)) {
|
|
167
|
+
return text;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ---- Type-based fallback ----
|
|
172
|
+
const nodeType = context?.nodeType;
|
|
173
|
+
if (nodeType && TYPE_FALLBACKS[nodeType]) {
|
|
174
|
+
return TYPE_FALLBACKS[nodeType];
|
|
175
|
+
}
|
|
176
|
+
return 'Diagnose the issue with Chrome DevTools (Performance → Measure → Reload) ' +
|
|
177
|
+
'and follow Lighthouse recommendations.';
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=remediations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediations.js","sourceRoot":"","sources":["../../src/report/remediations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report scoring — compute overall performance score from CausalGraph.
|
|
3
|
+
*
|
|
4
|
+
* The score is a simple heuristic based on severity distribution:
|
|
5
|
+
* - Any critical nodes → "poor"
|
|
6
|
+
* - Any warning nodes → "moderate"
|
|
7
|
+
* - Info only / empty → "good"
|
|
8
|
+
*
|
|
9
|
+
* Optionally accepts a Lighthouse performance score to override the
|
|
10
|
+
* heuristic when Lighthouse indicates acceptable performance despite
|
|
11
|
+
* causal-rule triggers (e.g., 2 small render-blocking stylesheets).
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
import type { CausalGraph } from '../causal/types.js';
|
|
16
|
+
import type { ReportScore } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Compute overall performance score from a CausalGraph.
|
|
19
|
+
*
|
|
20
|
+
* When `lighthousePerformance` is provided the score may be promoted:
|
|
21
|
+
* - Lighthouse >= 0.9 and no genuine regression → "good"
|
|
22
|
+
* - Lighthouse >= 0.7, criticalCount <= 1, no genuine regression → "moderate"
|
|
23
|
+
* - Otherwise the heuristic score is returned unchanged.
|
|
24
|
+
*
|
|
25
|
+
* @param graph - The causal graph to evaluate
|
|
26
|
+
* @param lighthousePerformance - Optional Lighthouse performance score (0–1)
|
|
27
|
+
* @returns A string score when called without lighthouse data; otherwise
|
|
28
|
+
* either a string or an object with `score` and optional `explanation`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function computeScore(graph: CausalGraph): ReportScore;
|
|
31
|
+
export declare function computeScore(graph: CausalGraph, lighthousePerformance?: number): ReportScore | {
|
|
32
|
+
score: ReportScore;
|
|
33
|
+
explanation?: string;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../../src/report/scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA2B9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAAC;AAC9D,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,EAClB,qBAAqB,CAAC,EAAE,MAAM,GAC7B,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report scoring — compute overall performance score from CausalGraph.
|
|
3
|
+
*
|
|
4
|
+
* The score is a simple heuristic based on severity distribution:
|
|
5
|
+
* - Any critical nodes → "poor"
|
|
6
|
+
* - Any warning nodes → "moderate"
|
|
7
|
+
* - Info only / empty → "good"
|
|
8
|
+
*
|
|
9
|
+
* Optionally accepts a Lighthouse performance score to override the
|
|
10
|
+
* heuristic when Lighthouse indicates acceptable performance despite
|
|
11
|
+
* causal-rule triggers (e.g., 2 small render-blocking stylesheets).
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Check whether a node represents a genuinely bad performance regression,
|
|
17
|
+
* as opposed to a rule-triggered flag. Used to decide whether Lighthouse
|
|
18
|
+
* data should override the heuristic score.
|
|
19
|
+
*
|
|
20
|
+
* A genuine regression is:
|
|
21
|
+
* - Any node (metric or impact) with a value > 4000 (e.g. LCP > 4 s)
|
|
22
|
+
* - Any ms-valued node with a value > 2500 (e.g. TTFB > 2.5 s)
|
|
23
|
+
*/
|
|
24
|
+
function isGenuineRegression(node) {
|
|
25
|
+
if (node.value == null)
|
|
26
|
+
return false;
|
|
27
|
+
// Any value above 4000 is a clear regression regardless of semantics
|
|
28
|
+
if (node.value > 4000)
|
|
29
|
+
return true;
|
|
30
|
+
// ms-valued metrics above 2500 are "poor" by Google thresholds
|
|
31
|
+
if (node.unit === 'ms' && node.value > 2500)
|
|
32
|
+
return true;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function hasGenuineRegression(nodes) {
|
|
36
|
+
return nodes.some(isGenuineRegression);
|
|
37
|
+
}
|
|
38
|
+
export function computeScore(graph, lighthousePerformance) {
|
|
39
|
+
let criticalCount = 0;
|
|
40
|
+
let warningCount = 0;
|
|
41
|
+
for (const node of graph.nodes) {
|
|
42
|
+
if (node.severity === 'critical') {
|
|
43
|
+
criticalCount++;
|
|
44
|
+
}
|
|
45
|
+
if (node.severity === 'warning') {
|
|
46
|
+
warningCount++;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// When Lighthouse data is available, consider overriding the heuristic
|
|
50
|
+
if (lighthousePerformance !== undefined) {
|
|
51
|
+
const genuineRegression = hasGenuineRegression(graph.nodes);
|
|
52
|
+
if (lighthousePerformance >= 0.9 && !genuineRegression) {
|
|
53
|
+
return {
|
|
54
|
+
score: 'good',
|
|
55
|
+
explanation: 'Lighthouse performance >= 0.9, no genuine regressions detected',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (lighthousePerformance >= 0.7 && criticalCount <= 1 && !genuineRegression) {
|
|
59
|
+
return {
|
|
60
|
+
score: 'moderate',
|
|
61
|
+
explanation: 'Lighthouse performance >= 0.7, minimal critical issues, no genuine regressions',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Fallback heuristic (unchanged from original)
|
|
66
|
+
if (criticalCount > 0)
|
|
67
|
+
return 'poor';
|
|
68
|
+
if (warningCount > 0)
|
|
69
|
+
return 'moderate';
|
|
70
|
+
return 'good';
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../src/report/scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;;;;;GAQG;AACH,SAAS,mBAAmB,CAAC,IAAgB;IAC3C,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAErC,qEAAqE;IACrE,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI;QAAE,OAAO,IAAI,CAAC;IAEnC,+DAA+D;IAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI;QAAE,OAAO,IAAI,CAAC;IAEzD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAmB;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AACzC,CAAC;AAoBD,MAAM,UAAU,YAAY,CAC1B,KAAkB,EAClB,qBAA8B;IAE9B,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YACjC,aAAa,EAAE,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,YAAY,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;QACxC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAE5D,IAAI,qBAAqB,IAAI,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvD,OAAO;gBACL,KAAK,EAAE,MAAM;gBACb,WAAW,EACT,gEAAgE;aACnE,CAAC;QACJ,CAAC;QAED,IAAI,qBAAqB,IAAI,GAAG,IAAI,aAAa,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC7E,OAAO;gBACL,KAAK,EAAE,UAAU;gBACjB,WAAW,EACT,gFAAgF;aACnF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,IAAI,aAAa,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IACrC,IAAI,YAAY,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|