svelte-vitals 0.44.1 → 0.44.2

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
@@ -31,14 +31,11 @@ Health: 76/100
31
31
  SEO Score: 51/100 (route avg 61 · site −10)
32
32
  Architecture Score: 100/100 (route avg 100)
33
33
 
34
- Critical (2)
34
+ Critical (1)
35
35
  ────────────────────────
36
36
  ✗ seo/title-presence Missing <title>
37
37
  /
38
38
  src/routes/+page.svelte
39
- ✗ seo/description-presence Missing <meta name="description">
40
- /
41
- src/routes/+page.svelte
42
39
 
43
40
  Warnings (10)
44
41
  ────────────────────────
package/dist/bin.js CHANGED
@@ -2,20 +2,22 @@
2
2
  import {
3
3
  CONFIG_FILENAMES,
4
4
  discoverApps,
5
- findUnknownRuleIds,
6
5
  hasDep,
7
6
  isReporterName,
8
- knownRuleIds,
9
7
  readCoreVersion,
10
8
  readPackageVersion,
11
9
  readPkg,
12
10
  run
13
- } from "./chunk-4MC7STFI.js";
11
+ } from "./chunk-EWDGS52A.js";
14
12
  import {
15
13
  consoleIO,
16
14
  parseCliArgs,
17
15
  toList
18
16
  } from "./chunk-5Q2PT47V.js";
17
+ import {
18
+ findUnknownRuleIds,
19
+ knownRuleIds
20
+ } from "./chunk-TFBLQUAC.js";
19
21
 
20
22
  // src/resolve-args.ts
21
23
  var CATEGORIES = ["seo", "performance", "correctness", "security", "architecture"];
@@ -1785,7 +1787,7 @@ function selectApp(apps) {
1785
1787
  async function main() {
1786
1788
  const rawArgs = process.argv.slice(2);
1787
1789
  if (rawArgs[0] === "docs") {
1788
- const { runDocsCli } = await import("./cli-LGD6NDAO.js");
1790
+ const { runDocsCli } = await import("./cli-L2HHOZDN.js");
1789
1791
  process.exitCode = runDocsCli(rawArgs.slice(1));
1790
1792
  return;
1791
1793
  }
@@ -1,8 +1,14 @@
1
+ import {
2
+ findUnknownRuleIds,
3
+ knownRuleIds,
4
+ ruleOptionsSpec
5
+ } from "./chunk-TFBLQUAC.js";
6
+
1
7
  // src/index.ts
2
8
  import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
3
9
  import { dirname as dirname2, join as join7 } from "path";
4
10
  import {
5
- allRules as allRules3,
11
+ allRules as allRules2,
6
12
  runRules,
7
13
  formatConsoleReport,
8
14
  formatJsonReport,
@@ -392,6 +398,29 @@ function collectSvelteHeads(node, acc) {
392
398
  if (key in node) collectSvelteHeads(childOf(node, key), acc);
393
399
  }
394
400
  }
401
+ var JS_MIME_TYPES = /* @__PURE__ */ new Set([
402
+ "application/ecmascript",
403
+ "application/javascript",
404
+ "application/x-ecmascript",
405
+ "application/x-javascript",
406
+ "text/ecmascript",
407
+ "text/javascript",
408
+ "text/javascript1.0",
409
+ "text/javascript1.1",
410
+ "text/javascript1.2",
411
+ "text/javascript1.3",
412
+ "text/javascript1.4",
413
+ "text/javascript1.5",
414
+ "text/jscript",
415
+ "text/livescript",
416
+ "text/x-ecmascript",
417
+ "text/x-javascript"
418
+ ]);
419
+ function isClassicScriptType(type) {
420
+ if (type === void 0) return true;
421
+ const normalized = type.trim().toLowerCase();
422
+ return normalized === "" || JS_MIME_TYPES.has(normalized);
423
+ }
395
424
  function tagsFromHead(head) {
396
425
  const tags = [];
397
426
  const children = head.fragment.nodes;
@@ -451,7 +480,7 @@ function tagsFromHead(head) {
451
480
  } else {
452
481
  const src = attrText(attributes, "src");
453
482
  if (src) {
454
- const blocking = findAttr3(attributes, "defer") === void 0 && findAttr3(attributes, "async") === void 0 && type !== "module";
483
+ const blocking = isClassicScriptType(type) && findAttr3(attributes, "defer") === void 0 && findAttr3(attributes, "async") === void 0;
455
484
  tags.push({ kind: "script", value: "static", href: src, ...blocking ? { blocking: true } : {} });
456
485
  }
457
486
  }
@@ -593,6 +622,7 @@ function resolveComponentPath(source, fromFileRel) {
593
622
  }
594
623
  async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited, cache = /* @__PURE__ */ new Map()) {
595
624
  const tags = [...parsed.headTags];
625
+ const headings = [];
596
626
  let broad = false;
597
627
  for (const use of parsed.components) {
598
628
  const info = parsed.imports.get(use.name);
@@ -616,10 +646,12 @@ async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited,
616
646
  const child = await resolveFileTags(rt, cwd, childRel, childParsed, config, depth - 1, childVisited, cache);
617
647
  tags.push(...child.tags);
618
648
  broad = broad || child.broad;
649
+ for (const h of childParsed.headings) headings.push({ ...h, file: childRel });
650
+ headings.push(...child.headings);
619
651
  }
620
652
  }
621
653
  }
622
- return { tags, broad };
654
+ return { tags, broad, headings };
623
655
  }
624
656
 
625
657
  // src/providers/source/routes.ts
@@ -695,6 +727,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache) {
695
727
  let broadInherited = false;
696
728
  const images = [];
697
729
  const headings = [];
730
+ const componentHeadings = [];
698
731
  for (const { rel, isPage } of files) {
699
732
  const parsed = await readAndParse(rt, cwd, rel, cache);
700
733
  for (const img of parsed.images) {
@@ -711,6 +744,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache) {
711
744
  if (isPage) broadOwn = true;
712
745
  else broadInherited = true;
713
746
  }
747
+ componentHeadings.push(...resolved.headings);
714
748
  }
715
749
  if (broadOwn || broadInherited) {
716
750
  const presence = broadOwn ? "own" : "inherited";
@@ -723,7 +757,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache) {
723
757
  return {
724
758
  head: { route, source: "static", tags: [...composed.values()], file: pageRel },
725
759
  images: { route, images },
726
- headings: { route, headings }
760
+ headings: { route, headings, componentHeadings }
727
761
  };
728
762
  }
729
763
  async function collectRoutes(rt, cwd, config = defaultConfig, cache = /* @__PURE__ */ new Map()) {
@@ -959,22 +993,6 @@ import {
959
993
  shouldSkipRangeCheck,
960
994
  validateRuleSetting
961
995
  } from "@svelte-vitals/core";
962
-
963
- // src/rules-config.ts
964
- import { allRules } from "@svelte-vitals/core";
965
- var KNOWN_IDS = new Set(allRules.map((r) => r.id));
966
- var RULE_BY_ID = new Map(allRules.map((r) => [r.id, r]));
967
- function findUnknownRuleIds(ids) {
968
- return [...new Set(ids.filter((id) => !KNOWN_IDS.has(id)))];
969
- }
970
- function knownRuleIds() {
971
- return [...KNOWN_IDS].sort();
972
- }
973
- function ruleOptionsSpec(id) {
974
- return RULE_BY_ID.get(id)?.options;
975
- }
976
-
977
- // src/config-file.ts
978
996
  var CONFIG_FILENAMES = ["svelte-vitals.config.mjs", "svelte-vitals.config.js", "svelte-vitals.config.ts"];
979
997
  var TREAT_DYNAMIC_AS_VALUES = ["pass", "warn", "fail"];
980
998
  var FAIL_ON_VALUES = ["critical", "warning", "info"];
@@ -1472,13 +1490,13 @@ function scoreAnimationEnabled(opts) {
1472
1490
  }
1473
1491
 
1474
1492
  // src/rule-selection.ts
1475
- import { allRules as allRules2 } from "@svelte-vitals/core";
1493
+ import { allRules } from "@svelte-vitals/core";
1476
1494
  function resolveRuleSelection(input) {
1477
1495
  const out = { ...input.rules ?? input.fileRules };
1478
1496
  const allow = input.allowRules ?? [];
1479
1497
  if (allow.length > 0) {
1480
1498
  const allowed = new Set(allow);
1481
- for (const rule of allRules2) if (!allowed.has(rule.id)) out[rule.id] = "off";
1499
+ for (const rule of allRules) if (!allowed.has(rule.id)) out[rule.id] = "off";
1482
1500
  for (const id of allowed) {
1483
1501
  const setting = out[id];
1484
1502
  if (setting === void 0) continue;
@@ -1551,7 +1569,7 @@ async function analyzeProject(opts = {}) {
1551
1569
  route: opts.route,
1552
1570
  parseCache: opts.parseCache
1553
1571
  });
1554
- const selected = selectRules(allRules3, config);
1572
+ const selected = selectRules(allRules2, config);
1555
1573
  const rules = opts.categories ? selected.filter((r) => opts.categories.includes(r.category)) : selected;
1556
1574
  const { results: rawResults, examined } = await runRules(rules, {
1557
1575
  heads,
@@ -1828,9 +1846,6 @@ export {
1828
1846
  readPackageVersion,
1829
1847
  readCoreVersion,
1830
1848
  isReporterName,
1831
- findUnknownRuleIds,
1832
- knownRuleIds,
1833
- ruleOptionsSpec,
1834
1849
  CONFIG_FILENAMES,
1835
1850
  loadConfigFile,
1836
1851
  spinnerEnabled,
@@ -0,0 +1,19 @@
1
+ // src/rules-config.ts
2
+ import { allRules } from "@svelte-vitals/core";
3
+ var KNOWN_IDS = new Set(allRules.map((r) => r.id));
4
+ var RULE_BY_ID = new Map(allRules.map((r) => [r.id, r]));
5
+ function findUnknownRuleIds(ids) {
6
+ return [...new Set(ids.filter((id) => !KNOWN_IDS.has(id)))];
7
+ }
8
+ function knownRuleIds() {
9
+ return [...KNOWN_IDS].sort();
10
+ }
11
+ function ruleOptionsSpec(id) {
12
+ return RULE_BY_ID.get(id)?.options;
13
+ }
14
+
15
+ export {
16
+ findUnknownRuleIds,
17
+ knownRuleIds,
18
+ ruleOptionsSpec
19
+ };
@@ -2,6 +2,12 @@ import {
2
2
  consoleIO,
3
3
  parseCliArgs
4
4
  } from "./chunk-5Q2PT47V.js";
5
+ import {
6
+ knownRuleIds
7
+ } from "./chunk-TFBLQUAC.js";
8
+
9
+ // src/docs/cli.ts
10
+ import { docsUrlFor } from "@svelte-vitals/core";
5
11
 
6
12
  // src/docs/generated.ts
7
13
  var EMBEDDED_DOCS = [
@@ -100,9 +106,16 @@ function runDocsCli(args, io = consoleIO) {
100
106
  io.errorLog(`svelte-vitals: known topics: ${knownTopicNames()}.`);
101
107
  return 2;
102
108
  }
103
- const doc = EMBEDDED_DOCS.find((d) => d.name === rest[0]);
109
+ const name = rest[0];
110
+ const doc = EMBEDDED_DOCS.find((d) => d.name === name);
104
111
  if (!doc) {
105
- io.errorLog(`svelte-vitals: unknown docs topic '${rest[0]}'.`);
112
+ const ruleId = name.startsWith("rules/") ? name.slice("rules/".length) : name;
113
+ if (knownRuleIds().includes(ruleId)) {
114
+ io.errorLog(`svelte-vitals: '${ruleId}' is a rule, not a docs topic.`);
115
+ io.errorLog(`svelte-vitals: rule detail: \`svelte-vitals explain ${ruleId}\`; web: ${docsUrlFor(ruleId)}`);
116
+ return 2;
117
+ }
118
+ io.errorLog(`svelte-vitals: unknown docs topic '${name}'.`);
106
119
  io.errorLog(`svelte-vitals: known topics: ${knownTopicNames()}.`);
107
120
  return 2;
108
121
  }
package/dist/index.js CHANGED
@@ -3,14 +3,16 @@ import {
3
3
  analyzeProject,
4
4
  applyScope,
5
5
  defineConfig,
6
- findUnknownRuleIds,
7
- knownRuleIds,
8
6
  loadConfigFile,
9
7
  routeMatcher,
10
- ruleOptionsSpec,
11
8
  run,
12
9
  spinnerEnabled
13
- } from "./chunk-4MC7STFI.js";
10
+ } from "./chunk-EWDGS52A.js";
11
+ import {
12
+ findUnknownRuleIds,
13
+ knownRuleIds,
14
+ ruleOptionsSpec
15
+ } from "./chunk-TFBLQUAC.js";
14
16
  export {
15
17
  ProjectError,
16
18
  analyzeProject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-vitals",
3
- "version": "0.44.1",
3
+ "version": "0.44.2",
4
4
  "description": "A deterministic SvelteKit code-health scanner (SEO, performance, correctness, security, architecture) — not a runtime Web Vitals reporter.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  "magicast": "^0.5.4",
49
49
  "svelte": "^5.56.8",
50
50
  "tinyglobby": "^0.2.17",
51
- "@svelte-vitals/core": "0.39.0"
51
+ "@svelte-vitals/core": "0.40.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/estree": "^1.0.9",