@svelte-vitals/core 0.8.0 → 0.10.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 +14 -3
- package/dist/index.js +30 -11
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ interface Result {
|
|
|
53
53
|
line?: number;
|
|
54
54
|
}
|
|
55
55
|
type Scope = 'route' | 'project';
|
|
56
|
-
type Category = 'seo' | 'performance'
|
|
56
|
+
type Category = 'seo' | 'performance';
|
|
57
57
|
/** How dynamic (`{data.title}`) values are treated by scoring (design §4, §12). */
|
|
58
58
|
type TreatDynamicAs = 'pass' | 'warn' | 'fail';
|
|
59
59
|
/** Per-rule override: disable, or change severity. */
|
|
@@ -66,6 +66,8 @@ interface Config {
|
|
|
66
66
|
rules: Record<string, RuleSetting>;
|
|
67
67
|
/** Minimum severity that fails the run / CI (design §6). */
|
|
68
68
|
failOn: Severity;
|
|
69
|
+
/** Per-category weights for the combined Health score (default: equal, 1 each) (#10). */
|
|
70
|
+
weights?: Partial<Record<Category, number>>;
|
|
69
71
|
}
|
|
70
72
|
declare const defaultConfig: Config;
|
|
71
73
|
/** Merge user config over defaults. Identity helper for config files (design §6). */
|
|
@@ -320,6 +322,15 @@ interface ScoreOptions {
|
|
|
320
322
|
declare function computeScore(results: Result[], config: Config, options?: ScoreOptions): ScoreResult;
|
|
321
323
|
/** Compute an independent score per category present in `results` (issue #10). */
|
|
322
324
|
declare function scoresByCategory(results: Result[], config: Config): Partial<Record<Category, ScoreResult>>;
|
|
325
|
+
interface HealthResult {
|
|
326
|
+
/** Weighted overall score across present categories (0–100). */
|
|
327
|
+
health: number;
|
|
328
|
+
categories: Partial<Record<Category, ScoreResult>>;
|
|
329
|
+
/** Effective weight used per present category. */
|
|
330
|
+
weights: Partial<Record<Category, number>>;
|
|
331
|
+
}
|
|
332
|
+
/** Combined weighted Health score over the categories present in `results` (#10). */
|
|
333
|
+
declare function computeHealth(results: Result[], config: Config): HealthResult;
|
|
323
334
|
|
|
324
335
|
declare function issueOf(result: Result): {
|
|
325
336
|
fix?: Fix | undefined;
|
|
@@ -338,7 +349,7 @@ type JsonIssue = ReturnType<typeof issueOf> & {
|
|
|
338
349
|
interface JsonReport {
|
|
339
350
|
version: string;
|
|
340
351
|
score: number;
|
|
341
|
-
|
|
352
|
+
weights: Partial<Record<Category, number>>;
|
|
342
353
|
categories: Record<string, {
|
|
343
354
|
score: number;
|
|
344
355
|
scoreModel: ScoreModel;
|
|
@@ -379,4 +390,4 @@ declare function selectRules(rules: Rule[], config: Config): Rule[];
|
|
|
379
390
|
/** Apply per-rule severity overrides to results (design §6). */
|
|
380
391
|
declare function applyRuleSeverities(results: Result[], config: Config): Result[];
|
|
381
392
|
|
|
382
|
-
export { type Category, type Classification, type Config, type ConsoleReportOptions, type Detection, type Fix, type HeadProvider, type HeadTag, type ImageInfo, type JsonReport, type Presence, type Project, ROBOTS_SOURCE_PATHS, type ResolvedHead, 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 Summary, type TreatDynamicAs, type Value, allRules, applyRuleSeverities, buildJsonReport, classify, computeScore, defaultConfig, defaultProject, defineConfig, docsUrlFor, effectiveSeverity, explainRule, formatAgentReport, formatConsoleReport, formatGithubReport, formatJsonReport, formatSarifReport, hasFailureAtOrAbove, headTagRule, imageRule, isPenalized, perf001ImageDimensions, perf002ImageLoading, runRules, scoresByCategory, selectRules, seo001Title, seo002Description, seo003Canonical, seo004OgImage, seo005OgTitle, seo006Robots, seo007Sitemap, seo008JsonLd, seo009HtmlLang, summarize };
|
|
393
|
+
export { type Category, type Classification, type Config, type ConsoleReportOptions, type Detection, type Fix, type HeadProvider, type HeadTag, type HealthResult, type ImageInfo, type JsonReport, type Presence, type Project, ROBOTS_SOURCE_PATHS, type ResolvedHead, 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 Summary, type TreatDynamicAs, type Value, allRules, applyRuleSeverities, buildJsonReport, classify, computeHealth, computeScore, defaultConfig, defaultProject, defineConfig, docsUrlFor, effectiveSeverity, explainRule, formatAgentReport, formatConsoleReport, formatGithubReport, formatJsonReport, formatSarifReport, hasFailureAtOrAbove, headTagRule, imageRule, isPenalized, perf001ImageDimensions, perf002ImageLoading, runRules, scoresByCategory, selectRules, seo001Title, seo002Description, seo003Canonical, seo004OgImage, seo005OgTitle, seo006Robots, seo007Sitemap, seo008JsonLd, seo009HtmlLang, summarize };
|
package/dist/index.js
CHANGED
|
@@ -490,6 +490,27 @@ function scoresByCategory(results, config) {
|
|
|
490
490
|
for (const [cat, rs] of byCat) out[cat] = computeScore(rs, config);
|
|
491
491
|
return out;
|
|
492
492
|
}
|
|
493
|
+
function computeHealth(results, config) {
|
|
494
|
+
const categories = scoresByCategory(results, config);
|
|
495
|
+
const weights = {};
|
|
496
|
+
let weighted = 0;
|
|
497
|
+
let total = 0;
|
|
498
|
+
for (const cat of Object.keys(categories)) {
|
|
499
|
+
const w = config.weights?.[cat] ?? 1;
|
|
500
|
+
if (!Number.isFinite(w) || w < 0) {
|
|
501
|
+
throw new RangeError(`invalid weight for '${cat}'; expected a finite number >= 0.`);
|
|
502
|
+
}
|
|
503
|
+
weights[cat] = w;
|
|
504
|
+
weighted += categories[cat].score * w;
|
|
505
|
+
total += w;
|
|
506
|
+
}
|
|
507
|
+
if (Object.keys(weights).length === 0) return { health: 100, categories, weights };
|
|
508
|
+
if (total === 0) {
|
|
509
|
+
throw new RangeError("Health weights sum to 0; at least one present category must have a positive weight.");
|
|
510
|
+
}
|
|
511
|
+
const health = Math.round(weighted / total);
|
|
512
|
+
return { health, categories, weights };
|
|
513
|
+
}
|
|
493
514
|
|
|
494
515
|
// src/reporter/console.ts
|
|
495
516
|
var RULE = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
|
|
@@ -500,11 +521,9 @@ var SEVERITY_TITLE = {
|
|
|
500
521
|
};
|
|
501
522
|
var CATEGORY_LABEL = {
|
|
502
523
|
seo: "SEO",
|
|
503
|
-
performance: "Performance"
|
|
504
|
-
a11y: "Accessibility",
|
|
505
|
-
maintainability: "Maintainability"
|
|
524
|
+
performance: "Performance"
|
|
506
525
|
};
|
|
507
|
-
var CATEGORY_ORDER = ["seo", "performance"
|
|
526
|
+
var CATEGORY_ORDER = ["seo", "performance"];
|
|
508
527
|
function scoreLine(label, { score, scoreModel }) {
|
|
509
528
|
const parts = [`route avg ${scoreModel.routeAverage}`];
|
|
510
529
|
if (scoreModel.sitePenalty > 0) parts.push(`site \u2212${scoreModel.sitePenalty}`);
|
|
@@ -531,9 +550,9 @@ function byRouteTree(results, config) {
|
|
|
531
550
|
}
|
|
532
551
|
function formatConsoleReport(results, config, options = {}) {
|
|
533
552
|
const summary = summarize(results, config);
|
|
534
|
-
const byCat =
|
|
553
|
+
const { health, categories: byCat } = computeHealth(results, config);
|
|
535
554
|
const present2 = CATEGORY_ORDER.filter((c) => byCat[c] !== void 0);
|
|
536
|
-
const header = [`Svelte Vitals \xB7 ${options.mode ?? "static mode"}`, ""];
|
|
555
|
+
const header = [`Svelte Vitals \xB7 ${options.mode ?? "static mode"}`, "", `Health: ${health}/100`];
|
|
537
556
|
for (const c of present2) {
|
|
538
557
|
header.push(scoreLine(CATEGORY_LABEL[c] ?? c, byCat[c]));
|
|
539
558
|
}
|
|
@@ -580,10 +599,8 @@ function issueOf(result) {
|
|
|
580
599
|
};
|
|
581
600
|
}
|
|
582
601
|
function buildJsonReport(results, config, meta) {
|
|
583
|
-
const
|
|
584
|
-
const { score, scoreModel } = computeScore(seoResults, config);
|
|
602
|
+
const { health, categories: byCat, weights } = computeHealth(results, config);
|
|
585
603
|
const summary = summarize(results, config);
|
|
586
|
-
const byCat = scoresByCategory(results, config);
|
|
587
604
|
const categories = Object.fromEntries(
|
|
588
605
|
Object.entries(byCat).map(([cat, sr]) => [cat, { score: sr.score, scoreModel: sr.scoreModel }])
|
|
589
606
|
);
|
|
@@ -599,7 +616,7 @@ function buildJsonReport(results, config, meta) {
|
|
|
599
616
|
issues: rs.filter((r) => isPenalized(r.detection, config.treatDynamicAs)).map((r) => ({ ...issueOf(r), severity: effectiveSeverity(r, config) }))
|
|
600
617
|
}));
|
|
601
618
|
const siteIssues = results.filter((r) => r.route === void 0 && isPenalized(r.detection, config.treatDynamicAs)).map((r) => ({ ...issueOf(r), severity: effectiveSeverity(r, config) }));
|
|
602
|
-
return { version: meta.version, score,
|
|
619
|
+
return { version: meta.version, score: health, weights, categories, summary, routes, siteIssues };
|
|
603
620
|
}
|
|
604
621
|
function formatJsonReport(results, config, meta) {
|
|
605
622
|
return JSON.stringify(buildJsonReport(results, config, meta), null, 2);
|
|
@@ -612,7 +629,8 @@ function mdTags(text) {
|
|
|
612
629
|
}
|
|
613
630
|
function formatAgentReport(results, config) {
|
|
614
631
|
const failing = results.filter((r) => classify(r, config) === "fail");
|
|
615
|
-
const
|
|
632
|
+
const { health } = computeHealth(results, config);
|
|
633
|
+
const lines = ["# svelte-vitals \u2014 fixes", "", `Health: ${health}/100`, ""];
|
|
616
634
|
if (failing.length === 0) {
|
|
617
635
|
lines.push("No issues to fix.", "");
|
|
618
636
|
return lines.join("\n").replace(/\n+$/, "\n");
|
|
@@ -771,6 +789,7 @@ export {
|
|
|
771
789
|
applyRuleSeverities,
|
|
772
790
|
buildJsonReport,
|
|
773
791
|
classify,
|
|
792
|
+
computeHealth,
|
|
774
793
|
computeScore,
|
|
775
794
|
defaultConfig,
|
|
776
795
|
defaultProject,
|