@svelte-vitals/core 0.20.0 → 0.22.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/dist/index.d.ts +15 -1
- package/dist/index.js +91 -6
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -717,6 +717,16 @@ declare function formatSarifReport(results: Result[], config: Config, meta: {
|
|
|
717
717
|
*/
|
|
718
718
|
declare function formatGithubReport(results: Result[], config: Config): string;
|
|
719
719
|
|
|
720
|
+
/**
|
|
721
|
+
* Render a compact Markdown summary — Health score, per-category table, severity counts, and
|
|
722
|
+
* a findings table — suitable for a GitHub Actions job summary or a sticky PR comment
|
|
723
|
+
* (`svelte-vitals ci install`). Delegates all aggregation to `buildJsonReport` so the numbers
|
|
724
|
+
* never drift from the JSON/console reporters.
|
|
725
|
+
*/
|
|
726
|
+
declare function formatMarkdownReport(results: Result[], config: Config, meta: {
|
|
727
|
+
version: string;
|
|
728
|
+
}): string;
|
|
729
|
+
|
|
720
730
|
type Band = 'good' | 'warn' | 'poor';
|
|
721
731
|
declare const BAND_COLOR: Record<Band, string>;
|
|
722
732
|
declare function scoreBand(score: number): Band;
|
|
@@ -733,9 +743,13 @@ declare function escapeHtml(s: string): string;
|
|
|
733
743
|
declare function safeHref(url: string): string | null;
|
|
734
744
|
declare function buildHtmlDocument(report: JsonReport, meta: {
|
|
735
745
|
version: string;
|
|
746
|
+
coreVersion?: string;
|
|
747
|
+
}, opts?: {
|
|
748
|
+
routeBadges?: Record<string, 'measured' | 'static'>;
|
|
736
749
|
}): string;
|
|
737
750
|
declare function formatHtmlReport(results: Result[], config: Config, meta: {
|
|
738
751
|
version: string;
|
|
752
|
+
coreVersion?: string;
|
|
739
753
|
}): string;
|
|
740
754
|
|
|
741
755
|
/** Drop rules disabled via config (design §6). */
|
|
@@ -743,4 +757,4 @@ declare function selectRules(rules: Rule[], config: Config): Rule[];
|
|
|
743
757
|
/** Apply per-rule severity overrides to results (design §6). */
|
|
744
758
|
declare function applyRuleSeverities(results: Result[], config: Config): Result[];
|
|
745
759
|
|
|
746
|
-
export { BAND_COLOR, CHILD_NODE_KEYS, type Category, type Classification, type ComponentFacts, type Config, type ConsoleReportOptions, type Detection, type EachBlockFact, type EffectFact, type Fix, type HeadProvider, type HeadTag, type HeadingInfo, type HealthResult, type ImageInfo, type JsonReport, type Palette, type Presence, type Project, ROBOTS_SOURCE_PATHS, type ResolvedHead, type ResolvedHeadings, type ResolvedImages, type Result, type Rule, type RuleContext, type RuleInfo, type RuleSetting, type Runtime, SITEMAP_SOURCE_PATHS, type Scope, type ScoreModel, type ScoreOptions, type ScoreResult, type Severity, type SourceSpan, type Summary, type SuppressionDirective, type TreatDynamicAs, type Value, allRules, applyRuleSeverities, arch001ComponentSize, arch002PropCount, attrText, attrTextOf, attrValue, attrValueOf, buildHtmlDocument, buildJsonReport, classify, collectComponentFacts, computeHealth, computeScore, correct001EachKey, correct002EffectDerived, correct003EffectAsOnMount, correct004UnmutatedState, correct005PropMutation, defaultConfig, defaultProject, defineConfig, docsUrlFor, effectiveSeverity, emptyComponentFacts, escapeHtml, explainRule, findAttr, formatAgentReport, formatConsoleReport, formatGithubReport, formatHtmlReport, formatJsonReport, formatSarifReport, hasFailureAtOrAbove, headTagRule, imageRule, isPenalized, lineOf, linkRule, noColorPalette, parseComponentFacts, perf001ImageDimensions, perf002ImageLoading, perf003PreloadAs, perf004FontPreloadCrossorigin, perf005LcpImage, perf006ResponsiveImage, perf007RenderBlockingScript, perf008Preconnect, perf009HeavyImport, perf010NamespaceImport, runRules, safeHref, scoreBand, scoreColor, scoresByCategory, sec001Html, sec002JavascriptUrl, selectRules, seo001Title, seo002Description, seo003Canonical, seo004OgImage, seo005OgTitle, seo006Robots, seo007Sitemap, seo008JsonLd, seo009HtmlLang, seo010Indexability, seo011TwitterCard, seo012OgDescription, seo013OgUrl, seo014Viewport, seo015SitemapInRobots, seo016JsonLdValidity, seo017DeprecatedType, seo018RelativeUrl, seo019DateFormat, seo020Placeholder, seo021RequiredProps, seo022TitleLength, seo023DescriptionLength, seo024Charset, seo025ImageAlt, seo026Hreflang, seo027Heading, seo028TitleUnique, seo029DescriptionUnique, seo030HeadingOrder, summarize, textFromNodes, valueFromNodes };
|
|
760
|
+
export { BAND_COLOR, CHILD_NODE_KEYS, type Category, type Classification, type ComponentFacts, type Config, type ConsoleReportOptions, type Detection, type EachBlockFact, type EffectFact, type Fix, type HeadProvider, type HeadTag, type HeadingInfo, type HealthResult, type ImageInfo, type JsonReport, type Palette, type Presence, type Project, ROBOTS_SOURCE_PATHS, type ResolvedHead, type ResolvedHeadings, type ResolvedImages, type Result, type Rule, type RuleContext, type RuleInfo, type RuleSetting, type Runtime, SITEMAP_SOURCE_PATHS, type Scope, type ScoreModel, type ScoreOptions, type ScoreResult, type Severity, type SourceSpan, type Summary, type SuppressionDirective, type TreatDynamicAs, type Value, allRules, applyRuleSeverities, arch001ComponentSize, arch002PropCount, attrText, attrTextOf, attrValue, attrValueOf, buildHtmlDocument, buildJsonReport, classify, collectComponentFacts, computeHealth, computeScore, correct001EachKey, correct002EffectDerived, correct003EffectAsOnMount, correct004UnmutatedState, correct005PropMutation, defaultConfig, defaultProject, defineConfig, docsUrlFor, effectiveSeverity, emptyComponentFacts, escapeHtml, explainRule, findAttr, formatAgentReport, formatConsoleReport, formatGithubReport, formatHtmlReport, formatJsonReport, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, headTagRule, imageRule, isPenalized, lineOf, linkRule, noColorPalette, parseComponentFacts, perf001ImageDimensions, perf002ImageLoading, perf003PreloadAs, perf004FontPreloadCrossorigin, perf005LcpImage, perf006ResponsiveImage, perf007RenderBlockingScript, perf008Preconnect, perf009HeavyImport, perf010NamespaceImport, runRules, safeHref, scoreBand, scoreColor, scoresByCategory, sec001Html, sec002JavascriptUrl, selectRules, seo001Title, seo002Description, seo003Canonical, seo004OgImage, seo005OgTitle, seo006Robots, seo007Sitemap, seo008JsonLd, seo009HtmlLang, seo010Indexability, seo011TwitterCard, seo012OgDescription, seo013OgUrl, seo014Viewport, seo015SitemapInRobots, seo016JsonLdValidity, seo017DeprecatedType, seo018RelativeUrl, seo019DateFormat, seo020Placeholder, seo021RequiredProps, seo022TitleLength, seo023DescriptionLength, seo024Charset, seo025ImageAlt, seo026Hreflang, seo027Heading, seo028TitleUnique, seo029DescriptionUnique, seo030HeadingOrder, summarize, textFromNodes, valueFromNodes };
|
package/dist/index.js
CHANGED
|
@@ -2654,6 +2654,82 @@ function formatGithubReport(results, config) {
|
|
|
2654
2654
|
return lines.join("\n");
|
|
2655
2655
|
}
|
|
2656
2656
|
|
|
2657
|
+
// src/reporter/markdown.ts
|
|
2658
|
+
var MAX_FINDINGS = 50;
|
|
2659
|
+
var SEVERITY_EMOJI = { critical: "\u{1F534}", warning: "\u{1F7E1}", info: "\u{1F535}" };
|
|
2660
|
+
var SEVERITY_RANK2 = { critical: 0, warning: 1, info: 2 };
|
|
2661
|
+
function escapeCell(s) {
|
|
2662
|
+
return s.replace(/\|/g, "\\|").replace(/\r\n|\r|\n/g, " ");
|
|
2663
|
+
}
|
|
2664
|
+
function locationOf(issue, route) {
|
|
2665
|
+
if (issue.location) return issue.line !== void 0 ? `${issue.location}:${issue.line}` : issue.location;
|
|
2666
|
+
return route ?? "-";
|
|
2667
|
+
}
|
|
2668
|
+
function flattenFindings(report) {
|
|
2669
|
+
const findings = [];
|
|
2670
|
+
for (const r of report.routes) {
|
|
2671
|
+
for (const issue of r.issues) {
|
|
2672
|
+
findings.push({
|
|
2673
|
+
severity: issue.severity,
|
|
2674
|
+
id: issue.id,
|
|
2675
|
+
location: locationOf(issue, r.route),
|
|
2676
|
+
message: issue.title
|
|
2677
|
+
});
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
for (const issue of report.siteIssues) {
|
|
2681
|
+
findings.push({
|
|
2682
|
+
severity: issue.severity,
|
|
2683
|
+
id: issue.id,
|
|
2684
|
+
location: locationOf(issue, void 0),
|
|
2685
|
+
message: issue.title
|
|
2686
|
+
});
|
|
2687
|
+
}
|
|
2688
|
+
return findings.map((f, index) => ({ f, index })).sort((a, b) => SEVERITY_RANK2[a.f.severity] - SEVERITY_RANK2[b.f.severity] || a.index - b.index).map(({ f }) => f);
|
|
2689
|
+
}
|
|
2690
|
+
function categoryRows(categories) {
|
|
2691
|
+
const names = Object.keys(categories).sort();
|
|
2692
|
+
return names.map((cat) => `| ${cat} | ${categories[cat].score} |`);
|
|
2693
|
+
}
|
|
2694
|
+
function formatMarkdownReport(results, config, meta) {
|
|
2695
|
+
const report = buildJsonReport(results, config, meta);
|
|
2696
|
+
const lines = [];
|
|
2697
|
+
lines.push(`<!-- svelte-vitals v${meta.version} -->`);
|
|
2698
|
+
lines.push(`## svelte-vitals \u2014 Health ${report.score}/100`);
|
|
2699
|
+
lines.push("");
|
|
2700
|
+
const catRows = categoryRows(report.categories);
|
|
2701
|
+
if (catRows.length > 0) {
|
|
2702
|
+
lines.push("| Category | Score |");
|
|
2703
|
+
lines.push("| --- | --- |");
|
|
2704
|
+
lines.push(...catRows);
|
|
2705
|
+
lines.push("");
|
|
2706
|
+
}
|
|
2707
|
+
const { critical, warning, info, passed } = report.summary;
|
|
2708
|
+
lines.push(`**${critical} critical \xB7 ${warning} warning \xB7 ${info} info** (${passed} checks passed)`);
|
|
2709
|
+
lines.push("");
|
|
2710
|
+
const findings = flattenFindings(report);
|
|
2711
|
+
if (findings.length === 0) {
|
|
2712
|
+
lines.push("\u2705 No issues found.");
|
|
2713
|
+
} else {
|
|
2714
|
+
lines.push("### Findings");
|
|
2715
|
+
lines.push("");
|
|
2716
|
+
lines.push("| Severity | Rule | Location | Message |");
|
|
2717
|
+
lines.push("| --- | --- | --- | --- |");
|
|
2718
|
+
const shown = findings.slice(0, MAX_FINDINGS);
|
|
2719
|
+
for (const f of shown) {
|
|
2720
|
+
const rule = `[${f.id}](${docsUrlFor(f.id)})`;
|
|
2721
|
+
lines.push(
|
|
2722
|
+
`| ${SEVERITY_EMOJI[f.severity]} ${f.severity} | ${rule} | ${escapeCell(f.location)} | ${escapeCell(f.message)} |`
|
|
2723
|
+
);
|
|
2724
|
+
}
|
|
2725
|
+
if (findings.length > MAX_FINDINGS) {
|
|
2726
|
+
lines.push("");
|
|
2727
|
+
lines.push(`\u2026and ${findings.length - MAX_FINDINGS} more (run \`npx svelte-vitals\` locally for the full report)`);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
return lines.join("\n");
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2657
2733
|
// src/reporter/html.ts
|
|
2658
2734
|
var BAND_COLOR = {
|
|
2659
2735
|
good: "#2FA968",
|
|
@@ -2687,7 +2763,8 @@ function renderFinding(issue) {
|
|
|
2687
2763
|
}
|
|
2688
2764
|
function renderTopbar(report, meta) {
|
|
2689
2765
|
const findings = report.routes.reduce((n, r) => n + r.issues.length, 0) + report.siteIssues.length;
|
|
2690
|
-
|
|
2766
|
+
const core = meta.coreVersion ? `<span title="@svelte-vitals/core version">core v${escapeHtml(meta.coreVersion)}</span>` : "";
|
|
2767
|
+
return `<header class="topbar"><div class="brand"><span class="bolt">\u21AF</span>svelte-<span class="v">vitals</span></div><div class="meta"><span>v${escapeHtml(meta.version)}</span>` + core + `<span>${report.routes.length} routes</span><span>${findings} findings</span></div></header>`;
|
|
2691
2768
|
}
|
|
2692
2769
|
function renderHero(report) {
|
|
2693
2770
|
const C = 2 * Math.PI * 58;
|
|
@@ -2704,7 +2781,8 @@ function renderHero(report) {
|
|
|
2704
2781
|
}).join("");
|
|
2705
2782
|
return `<section class="hero"><div class="gauge"><svg width="132" height="132" viewBox="0 0 132 132" aria-hidden="true"><circle cx="66" cy="66" r="58" fill="none" stroke="#e4e7ec" stroke-width="11"></circle><circle id="arc" cx="66" cy="66" r="58" fill="none" stroke="${BAND_COLOR[hb]}" stroke-width="11" stroke-linecap="round" stroke-dasharray="${C.toFixed(1)}" stroke-dashoffset="${offset}"></circle></svg><div class="num"><strong id="hnum">${report.score}</strong><span>Health</span></div></div><div class="readout"><div class="eyebrow">SvelteKit \xB7 SEO & Performance</div><div class="tallies"><span class="tally"><span class="dot crit"></span>Critical <span class="n">${s.critical}</span></span><span class="tally"><span class="dot warn"></span>Warning <span class="n">${s.warning}</span></span><span class="tally"><span class="dot info"></span>Info <span class="n">${s.info}</span></span><span class="tally"><span class="dot pass"></span>Passed <span class="n">${s.passed}</span></span>` + dynNote + `</div><div class="cats">${cats}</div></div></section>`;
|
|
2706
2783
|
}
|
|
2707
|
-
|
|
2784
|
+
var ROUTE_BADGES = ["measured", "static"];
|
|
2785
|
+
function renderRoutes(report, routeBadges) {
|
|
2708
2786
|
if (report.routes.length === 0) return "";
|
|
2709
2787
|
const rows = report.routes.map((r) => {
|
|
2710
2788
|
const b = scoreBand(r.score);
|
|
@@ -2717,7 +2795,10 @@ function renderRoutes(report) {
|
|
|
2717
2795
|
if (info) parts.push(`${info} info`);
|
|
2718
2796
|
const sum = parts.length ? parts.join(" \xB7 ") : '<span class="none">no issues</span>';
|
|
2719
2797
|
const body = r.issues.length ? r.issues.map(renderFinding).join("") : '<p class="empty">No issues found on this route.</p>';
|
|
2720
|
-
|
|
2798
|
+
const rawBadge = routeBadges?.[r.route];
|
|
2799
|
+
const badge = rawBadge && ROUTE_BADGES.includes(rawBadge) ? rawBadge : void 0;
|
|
2800
|
+
const badgeHtml = badge ? ` <span class="badge badge-${badge}">${escapeHtml(badge)}</span>` : "";
|
|
2801
|
+
return `<details class="route" id="${slug(r.route)}" data-score="${r.score}"${r.issues.length ? " open" : ""}><summary><span class="route-name"><span class="path">${escapeHtml(r.route)}</span>${badgeHtml}</span><span class="issue-sum">${sum}</span><span class="score-chip"><span class="ring" style="background:${BAND_COLOR[b]}"></span>${r.score}</span><span class="chev">\u203A</span></summary><div class="route-body">${body}</div></details>`;
|
|
2721
2802
|
}).join("");
|
|
2722
2803
|
return `<section class="section"><h2>Routes</h2><div class="routes">${rows}</div></section>`;
|
|
2723
2804
|
}
|
|
@@ -2770,8 +2851,11 @@ body{margin:0;background:var(--ground);color:var(--ink);font-family:var(--sans);
|
|
|
2770
2851
|
.route>summary{display:grid;grid-template-columns:1fr auto auto auto;gap:16px;align-items:center;padding:13px 16px;cursor:pointer;list-style:none}
|
|
2771
2852
|
.route>summary::-webkit-details-marker{display:none}
|
|
2772
2853
|
.route>summary:hover{background:#fbfcfd}
|
|
2773
|
-
.route-name{font-family:var(--mono);font-size:13.5px;min-width:0}
|
|
2854
|
+
.route-name{font-family:var(--mono);font-size:13.5px;min-width:0;display:flex;align-items:center;gap:8px}
|
|
2774
2855
|
.route-name .path{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
2856
|
+
.badge{font-family:var(--sans);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;padding:2px 7px;border-radius:999px;flex-shrink:0}
|
|
2857
|
+
.badge-measured{background:rgba(47,169,104,.14);color:var(--good)}
|
|
2858
|
+
.badge-static{background:rgba(140,149,163,.18);color:var(--muted)}
|
|
2775
2859
|
.issue-sum{font-size:12.5px;color:var(--muted);font-family:var(--mono);white-space:nowrap}.issue-sum .none{color:var(--good)}
|
|
2776
2860
|
.score-chip{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-weight:600;font-variant-numeric:tabular-nums;font-size:14px}
|
|
2777
2861
|
.score-chip .ring{width:10px;height:10px;border-radius:50%}
|
|
@@ -2833,8 +2917,8 @@ var SCRIPT = `
|
|
|
2833
2917
|
});
|
|
2834
2918
|
})();
|
|
2835
2919
|
`;
|
|
2836
|
-
function buildHtmlDocument(report, meta) {
|
|
2837
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>svelte-vitals report</title><style>${STYLE}</style></head><body><div class="wrap">` + renderTopbar(report, meta) + renderHero(report) + renderFilters(report) + renderRoutes(report) + renderSiteChecks(report) + `<footer class="foot"><span>Generated by svelte-vitals \xB7 static analysis, no browser</span><span>oekazuma.github.io/svelte-vitals</span></footer></div><script>${SCRIPT}</script></body></html>`;
|
|
2920
|
+
function buildHtmlDocument(report, meta, opts) {
|
|
2921
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>svelte-vitals report</title><style>${STYLE}</style></head><body><div class="wrap">` + renderTopbar(report, meta) + renderHero(report) + renderFilters(report) + renderRoutes(report, opts?.routeBadges) + renderSiteChecks(report) + `<footer class="foot"><span>Generated by svelte-vitals \xB7 static analysis, no browser</span><span>oekazuma.github.io/svelte-vitals</span></footer></div><script>${SCRIPT}</script></body></html>`;
|
|
2838
2922
|
}
|
|
2839
2923
|
function formatHtmlReport(results, config, meta) {
|
|
2840
2924
|
return buildHtmlDocument(buildJsonReport(results, config, meta), meta);
|
|
@@ -2888,6 +2972,7 @@ export {
|
|
|
2888
2972
|
formatGithubReport,
|
|
2889
2973
|
formatHtmlReport,
|
|
2890
2974
|
formatJsonReport,
|
|
2975
|
+
formatMarkdownReport,
|
|
2891
2976
|
formatSarifReport,
|
|
2892
2977
|
hasFailureAtOrAbove,
|
|
2893
2978
|
headTagRule,
|