svelte-vitals 0.9.1 → 0.11.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/bin.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  knownRuleIds,
7
7
  readPackageVersion,
8
8
  run
9
- } from "./chunk-Y56I4RGY.js";
9
+ } from "./chunk-QI6NLWDD.js";
10
10
 
11
11
  // src/bin.ts
12
12
  import mri from "mri";
@@ -39,7 +39,7 @@ function resolveArgs(argv) {
39
39
  } else if (typeof argv.reporter === "string") {
40
40
  if (!isReporterName(argv.reporter)) {
41
41
  errors.push(
42
- `svelte-vitals: unknown reporter '${argv.reporter}'. Valid values: console, json, agent, sarif, github.`
42
+ `svelte-vitals: unknown reporter '${argv.reporter}'. Valid values: console, json, agent, sarif, github, html.`
43
43
  );
44
44
  } else {
45
45
  reporter = argv.reporter;
@@ -61,6 +61,7 @@ function resolveArgs(argv) {
61
61
  treatDynamicAs,
62
62
  route,
63
63
  reporter,
64
+ outFile: typeof argv["out-file"] === "string" ? argv["out-file"] : void 0,
64
65
  byRoute: Boolean(argv["by-route"]),
65
66
  failOn,
66
67
  rules: buildRulesConfig(allow, ignore)
@@ -81,7 +82,8 @@ Options:
81
82
  --treat-dynamic-as <mode> pass | warn | fail (default: pass)
82
83
  --route <glob> Only analyze routes matching this glob
83
84
  --by-route Show per-route score breakdown in console output
84
- --reporter <fmt> console | json | agent | sarif | github (auto: agent under AI-agent envs, github under GitHub Actions)
85
+ --reporter <fmt> console | json | agent | sarif | github | html (auto: agent under AI-agent envs, github under GitHub Actions)
86
+ --out-file <path> Output path for --reporter html (default: svelte-vitals-report.html; '-' for stdout)
85
87
  --json Alias for --reporter=json
86
88
  --fail-on <severity> Fail (exit 1) when any finding reaches this severity: critical | warning | info
87
89
  --fail-on-warning Alias for --fail-on=warning
@@ -100,7 +102,17 @@ async function main() {
100
102
  const argv = mri(process.argv.slice(2), {
101
103
  alias: { h: "help", v: "version" },
102
104
  boolean: ["by-route", "json", "fail-on-warning"],
103
- string: ["meta-components", "treat-dynamic-as", "route", "fail-on", "reporter", "rules", "ignore", "min-health"]
105
+ string: [
106
+ "meta-components",
107
+ "treat-dynamic-as",
108
+ "route",
109
+ "fail-on",
110
+ "reporter",
111
+ "rules",
112
+ "ignore",
113
+ "min-health",
114
+ "out-file"
115
+ ]
104
116
  });
105
117
  if (argv.help) {
106
118
  console.log(HELP);
@@ -1,4 +1,6 @@
1
1
  // src/index.ts
2
+ import { mkdirSync, writeFileSync } from "fs";
3
+ import { dirname } from "path";
2
4
  import {
3
5
  allRules as allRules2,
4
6
  runRules,
@@ -7,6 +9,7 @@ import {
7
9
  formatAgentReport,
8
10
  formatSarifReport,
9
11
  formatGithubReport,
12
+ formatHtmlReport,
10
13
  summarize,
11
14
  hasFailureAtOrAbove,
12
15
  computeHealth,
@@ -207,7 +210,17 @@ function tagsFromHead(head) {
207
210
  });
208
211
  } else if (node.name === "link") {
209
212
  const rel = attrText(node.attributes, "rel");
210
- tags.push({ kind: "link", ...rel ? { rel } : {}, value: attrValue(node.attributes, "href") });
213
+ const hasAs = findAttr(node.attributes, "as") !== void 0;
214
+ const asLiteral = attrText(node.attributes, "as");
215
+ const hasCrossorigin = findAttr(node.attributes, "crossorigin") !== void 0;
216
+ tags.push({
217
+ kind: "link",
218
+ ...rel ? { rel } : {},
219
+ value: attrValue(node.attributes, "href"),
220
+ ...hasAs ? { hasAs: true } : {},
221
+ ...asLiteral ? { as: asLiteral } : {},
222
+ ...hasCrossorigin ? { hasCrossorigin: true } : {}
223
+ });
211
224
  } else if (node.name === "script" && attrText(node.attributes, "type") === "application/ld+json") {
212
225
  tags.push({ kind: "jsonld", value: valueFromNodes(node.fragment?.nodes ?? []) });
213
226
  }
@@ -486,7 +499,7 @@ function readPackageVersion() {
486
499
  // src/reporter-resolve.ts
487
500
  var AGENT_ENV_VARS = ["CLAUDECODE", "SVELTE_VITALS_AGENT"];
488
501
  function isReporterName(value) {
489
- return value === "console" || value === "json" || value === "agent" || value === "sarif" || value === "github";
502
+ return value === "console" || value === "json" || value === "agent" || value === "sarif" || value === "github" || value === "html";
490
503
  }
491
504
  function isAgentEnv(env = process.env) {
492
505
  return AGENT_ENV_VARS.some((key) => {
@@ -604,6 +617,19 @@ async function run(opts = {}) {
604
617
  } else if (reporter === "github") {
605
618
  const output = formatGithubReport(results, config);
606
619
  if (output) log(output);
620
+ } else if (reporter === "html") {
621
+ const html = formatHtmlReport(results, config, { version });
622
+ if (opts.outFile === "-") {
623
+ log(html);
624
+ } else {
625
+ const path = opts.outFile || "svelte-vitals-report.html";
626
+ const write = opts.writeFile ?? ((p, c) => {
627
+ mkdirSync(dirname(p), { recursive: true });
628
+ writeFileSync(p, c);
629
+ });
630
+ write(path, html);
631
+ errorLog(`svelte-vitals: wrote report to ${path}`);
632
+ }
607
633
  } else {
608
634
  log(formatConsoleReport(results, config, { byRoute: opts.byRoute ?? false }));
609
635
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { RuleSetting, Severity, Result, Config } from '@svelte-vitals/core';
2
2
 
3
- type ReporterName = 'console' | 'json' | 'agent' | 'sarif' | 'github';
3
+ type ReporterName = 'console' | 'json' | 'agent' | 'sarif' | 'github' | 'html';
4
4
 
5
5
  /** Thrown when the target directory is not a SvelteKit project (CLI maps to exit 2). */
6
6
  declare class ProjectError extends Error {
@@ -35,6 +35,10 @@ interface RunOptions {
35
35
  env?: NodeJS.ProcessEnv;
36
36
  /** Fail (exit 1) when the combined Health score is below this value (0–100). */
37
37
  minHealth?: number;
38
+ /** Output path for --reporter html (default 'svelte-vitals-report.html'; '-' = stdout). */
39
+ outFile?: string;
40
+ /** Injected file writer for --reporter html (defaults to node:fs writeFileSync). Mainly for tests. */
41
+ writeFile?: (path: string, content: string) => void;
38
42
  }
39
43
  declare function routeMatcher(glob: string | undefined): (route: string) => boolean;
40
44
  interface AnalyzeOptions {
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  knownRuleIds,
7
7
  routeMatcher,
8
8
  run
9
- } from "./chunk-Y56I4RGY.js";
9
+ } from "./chunk-QI6NLWDD.js";
10
10
  export {
11
11
  ProjectError,
12
12
  analyzeProject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-vitals",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "description": "A SvelteKit SEO checker — not a runtime Web Vitals reporter. Static analysis of your routes' head metadata.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -42,7 +42,7 @@
42
42
  "mri": "^1.2.0",
43
43
  "svelte": "^5.56.3",
44
44
  "tinyglobby": "^0.2.17",
45
- "@svelte-vitals/core": "0.10.1"
45
+ "@svelte-vitals/core": "0.12.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^24.7.0"