@svelte-vitals/vite 0.28.0 → 0.29.1

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.
@@ -1,5 +1,5 @@
1
1
  // src/providers/rendered/parse-html.ts
2
- import { parse, HTMLElement } from "node-html-parser";
2
+ import { parse } from "node-html-parser";
3
3
  function attrValue(v) {
4
4
  return v !== void 0 && v.trim().length > 0 ? "static" : "absent";
5
5
  }
@@ -85,17 +85,7 @@ function parseHtmlHead(html) {
85
85
  const htmlEl = root.querySelector("html");
86
86
  const lang = htmlEl?.getAttribute("lang");
87
87
  const htmlLang = lang === void 0 || lang === null ? { presence: "none", value: "absent" } : { presence: "own", value: attrValue(lang) };
88
- const headings = [];
89
- const collectHeadings = (el) => {
90
- for (const child of el.childNodes) {
91
- if (child instanceof HTMLElement) {
92
- const m = /^h([1-6])$/i.exec(child.rawTagName ?? "");
93
- if (m) headings.push(Number(m[1]));
94
- collectHeadings(child);
95
- }
96
- }
97
- };
98
- collectHeadings(root.querySelector("body") ?? root);
88
+ const headings = (root.querySelector("body") ?? root).querySelectorAll("h1,h2,h3,h4,h5,h6").map((el) => Number(el.rawTagName[1]));
99
89
  const images = (root.querySelector("body") ?? root).querySelectorAll("img").map((img) => ({
100
90
  hasWidth: img.hasAttribute("width"),
101
91
  hasHeight: img.hasAttribute("height"),
@@ -118,12 +108,7 @@ function isLoopbackOrigin(origin) {
118
108
  }
119
109
  }
120
110
  function isLoopbackHost(host) {
121
- if (host === void 0) return false;
122
- try {
123
- return isLoopbackOrigin(`http://${host}`);
124
- } catch {
125
- return false;
126
- }
111
+ return host !== void 0 && isLoopbackOrigin(`http://${host}`);
127
112
  }
128
113
 
129
114
  export {
@@ -8,7 +8,6 @@ interface SvelteVitalsHookOptions {
8
8
  /** Per-rule overrides keyed by rule id, e.g. `{ 'seo/json-ld': 'off' }`. Mirrors the plugin option. */
9
9
  rules?: Record<string, RuleSetting>;
10
10
  }
11
-
12
11
  /**
13
12
  * SvelteKit `handle` that analyzes each visited page's rendered `<head>`, in dev only,
14
13
  * and (when the live dashboard is enabled) feeds the results in — upgrading that
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  isLoopbackOrigin,
3
3
  parseHtmlHead
4
- } from "../chunk-HURGA7UH.js";
4
+ } from "../chunk-QEIZ5U4M.js";
5
5
 
6
6
  // src/hooks/handle.ts
7
7
  import { DEV } from "esm-env";
@@ -9,20 +9,14 @@ import {
9
9
  allRules,
10
10
  applyRuleSeverities,
11
11
  defineConfig,
12
+ effectiveSeverity,
13
+ isPenalized,
12
14
  runRules,
13
15
  selectRules
14
16
  } from "@svelte-vitals/core";
15
-
16
- // src/hooks/format.ts
17
- import { isPenalized, effectiveSeverity } from "@svelte-vitals/core";
18
- function penalized(results, config) {
19
- return results.filter((r) => isPenalized(r.detection, config.treatDynamicAs));
20
- }
21
17
  function findingSignature(results, config) {
22
- return penalized(results, config).map((r) => `${r.id}:${effectiveSeverity(r, config)}:${r.detection.presence}:${r.detection.value}`).sort().join("|");
18
+ return results.filter((r) => isPenalized(r.detection, config.treatDynamicAs)).map((r) => `${r.id}:${effectiveSeverity(r, config)}:${r.detection.presence}:${r.detection.value}`).sort().join("|");
23
19
  }
24
-
25
- // src/hooks/handle.ts
26
20
  async function postIngest(origin, route, results) {
27
21
  if (!isLoopbackOrigin(origin)) {
28
22
  if (globalThis.process?.env?.SVELTE_VITALS_DEBUG) {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  isLoopbackHost,
3
3
  isLoopbackOrigin,
4
4
  parseHtmlHead
5
- } from "./chunk-HURGA7UH.js";
5
+ } from "./chunk-QEIZ5U4M.js";
6
6
 
7
7
  // src/plugin.ts
8
8
  import { existsSync } from "fs";
@@ -11,12 +11,11 @@ import { join as join4, isAbsolute, dirname, relative as relative3, basename, se
11
11
  import {
12
12
  CATEGORIES as CATEGORIES2,
13
13
  defaultConfig,
14
- defineConfig as defineConfig2,
15
14
  resolveRuleOptions,
16
15
  shouldSkipRangeCheck,
17
16
  validateRuleSetting
18
17
  } from "@svelte-vitals/core";
19
- import { findUnknownRuleIds, knownRuleIds, loadConfigFile as loadConfigFile2, ruleOptionsSpec } from "svelte-vitals";
18
+ import { findUnknownRuleIds, knownRuleIds, ruleOptionsSpec } from "svelte-vitals";
20
19
 
21
20
  // src/analyze.ts
22
21
  import {
@@ -187,13 +186,10 @@ function readCoreVersion() {
187
186
  }
188
187
 
189
188
  // src/analyze.ts
190
- async function analyze(prerenderPagesDir, cwd, options, extraProjectFacts) {
191
- const loaded = await loadConfigFile(cwd);
192
- const fileConfig = loaded?.config;
193
- const warnings = loaded?.warnings ?? [];
189
+ function mergeConfig(options, fileConfig) {
194
190
  const weights = options.weights ?? fileConfig?.weights;
195
191
  const overrides = options.overrides ?? fileConfig?.overrides;
196
- const config = defineConfig({
192
+ return defineConfig({
197
193
  treatDynamicAs: options.treatDynamicAs ?? fileConfig?.treatDynamicAs ?? "pass",
198
194
  metaComponents: options.metaComponents ?? fileConfig?.metaComponents ?? [],
199
195
  rules: options.rules ?? fileConfig?.rules ?? {},
@@ -201,6 +197,14 @@ async function analyze(prerenderPagesDir, cwd, options, extraProjectFacts) {
201
197
  ...weights !== void 0 ? { weights } : {},
202
198
  ...overrides !== void 0 ? { overrides } : {}
203
199
  });
200
+ }
201
+ async function resolveConfig(cwd, options) {
202
+ const loaded = await loadConfigFile(cwd);
203
+ const config = mergeConfig(options, loaded?.config);
204
+ return { config, warnings: loaded?.warnings ?? [] };
205
+ }
206
+ async function analyze(prerenderPagesDir, cwd, options, extraProjectFacts, resolved) {
207
+ const { config, warnings } = resolved ?? await resolveConfig(cwd, options);
204
208
  const { heads, headings, images, htmlLang } = await collectRenderedHeads(prerenderPagesDir);
205
209
  const project = {
206
210
  ...await collectRenderedProject(cwd, htmlLang),
@@ -265,7 +269,7 @@ async function resolveMinifyDisabled(minify, configFile, root) {
265
269
  }
266
270
 
267
271
  // src/ui/middleware.ts
268
- import { renderAppShell } from "@svelte-vitals/core";
272
+ import { CATEGORIES, renderAppShell } from "@svelte-vitals/core";
269
273
 
270
274
  // src/ui/snapshot.ts
271
275
  import { buildJsonReport, safeHref } from "@svelte-vitals/core";
@@ -297,7 +301,7 @@ function buildSnapshot(store, config, meta) {
297
301
 
298
302
  // src/ui/middleware.ts
299
303
  var SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
300
- var CATEGORIES = /* @__PURE__ */ new Set(["seo", "performance", "correctness", "security", "architecture"]);
304
+ var CATEGORY_SET = new Set(CATEGORIES);
301
305
  function isOptionalString(v) {
302
306
  return v === void 0 || typeof v === "string";
303
307
  }
@@ -306,7 +310,7 @@ function isResultLike(x) {
306
310
  const r = x;
307
311
  const d = r.detection;
308
312
  const f = r.fix;
309
- return typeof r.id === "string" && typeof r.message === "string" && typeof r.severity === "string" && SEVERITIES.has(r.severity) && typeof d === "object" && d !== null && typeof d.presence === "string" && typeof d.value === "string" && (r.category === void 0 || typeof r.category === "string" && CATEGORIES.has(r.category)) && isOptionalString(r.location) && isOptionalString(r.recommendation) && isOptionalString(r.docsUrl) && (f === void 0 || typeof f === "object" && f !== null && typeof f.description === "string" && isOptionalString(f.snippet) && isOptionalString(f.lang)) && (r.line === void 0 || typeof r.line === "number") && isOptionalString(r.route);
313
+ return typeof r.id === "string" && typeof r.message === "string" && typeof r.severity === "string" && SEVERITIES.has(r.severity) && typeof d === "object" && d !== null && typeof d.presence === "string" && typeof d.value === "string" && (r.category === void 0 || typeof r.category === "string" && CATEGORY_SET.has(r.category)) && isOptionalString(r.location) && isOptionalString(r.recommendation) && isOptionalString(r.docsUrl) && (f === void 0 || typeof f === "object" && f !== null && typeof f.description === "string" && isOptionalString(f.snippet) && isOptionalString(f.lang)) && (r.line === void 0 || typeof r.line === "number") && isOptionalString(r.route);
310
314
  }
311
315
  function installUiMiddleware(server, config, version, store, coreVersion) {
312
316
  const clients = /* @__PURE__ */ new Set();
@@ -612,10 +616,17 @@ function svelteVitals(options = {}) {
612
616
  const pagesDir = options.prerenderDir ? options.prerenderDir : join4(root, DEFAULT_PRERENDER_DIR);
613
617
  const resolved = isAbsolute(pagesDir) ? pagesDir : join4(root, pagesDir);
614
618
  if (!existsSync(resolved)) return;
619
+ const resolvedConfig = await resolveConfig(root, options);
615
620
  let result;
616
621
  try {
617
622
  const viteMinifyDisabled = minifyFlag ? await resolveMinifyDisabled(minifyFlag.minify, minifyFlag.configFile, root) : void 0;
618
- result = await analyze(resolved, root, options, viteMinifyDisabled ? { viteMinifyDisabled } : void 0);
623
+ result = await analyze(
624
+ resolved,
625
+ root,
626
+ options,
627
+ viteMinifyDisabled ? { viteMinifyDisabled } : void 0,
628
+ resolvedConfig
629
+ );
619
630
  } catch (err) {
620
631
  console.warn(`svelte-vitals: skipped \u2014 analysis failed: ${err instanceof Error ? err.message : String(err)}`);
621
632
  return;
@@ -643,17 +654,18 @@ function svelteVitals(options = {}) {
643
654
  async configureServer(server) {
644
655
  process.env.SVELTE_VITALS_UI = "1";
645
656
  const uiRoot = options.cwd ?? server.config.root;
646
- const loaded = await loadConfigFile2(uiRoot);
647
- const fileConfig = loaded?.config;
648
- for (const w of loaded?.warnings ?? []) console.warn(`svelte-vitals: ${w}`);
649
- const weights = options.weights ?? fileConfig?.weights;
650
- const config = defineConfig2({
651
- treatDynamicAs: options.treatDynamicAs ?? fileConfig?.treatDynamicAs ?? "pass",
652
- metaComponents: options.metaComponents ?? fileConfig?.metaComponents ?? [],
653
- rules: options.rules ?? fileConfig?.rules ?? {},
654
- failOn: options.failOn ?? fileConfig?.failOn ?? "critical",
655
- ...weights !== void 0 ? { weights } : {}
656
- });
657
+ let config;
658
+ let warnings;
659
+ try {
660
+ ({ config, warnings } = await resolveConfig(uiRoot, options));
661
+ } catch (err) {
662
+ console.warn(
663
+ `svelte-vitals: config file invalid \u2014 dashboard using plugin options/defaults: ${err instanceof Error ? err.message : String(err)}`
664
+ );
665
+ config = mergeConfig(options, void 0);
666
+ warnings = [];
667
+ }
668
+ for (const w of warnings) console.warn(`svelte-vitals: ${w}`);
657
669
  const store = createStore();
658
670
  const runner = createAnalysisRunner({
659
671
  root: uiRoot,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@svelte-vitals/vite",
3
- "version": "0.28.0",
4
- "description": "Vite/SvelteKit plugin for svelte-vitals — analyzes prerendered HTML during vite build.",
3
+ "version": "0.29.1",
4
+ "description": "Vite/SvelteKit plugin for svelte-vitals — analyzes prerendered HTML during vite build, plus a live dev dashboard.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Kazuma Oe (https://github.com/oekazuma)",
@@ -42,8 +42,8 @@
42
42
  "esm-env": "^1.2.2",
43
43
  "node-html-parser": "^9.0.1",
44
44
  "tinyglobby": "^0.2.17",
45
- "@svelte-vitals/core": "0.37.0",
46
- "svelte-vitals": "0.43.0"
45
+ "@svelte-vitals/core": "0.39.0",
46
+ "svelte-vitals": "0.44.1"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@sveltejs/kit": "^2.70.2",