@svelte-vitals/vite 0.27.1 → 0.29.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/{chunk-HURGA7UH.js → chunk-QEIZ5U4M.js} +3 -18
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.js +6 -14
- package/dist/index.js +48 -40
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/providers/rendered/parse-html.ts
|
|
2
|
-
import { parse
|
|
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
|
-
|
|
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 {
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -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
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isLoopbackOrigin,
|
|
3
3
|
parseHtmlHead
|
|
4
|
-
} from "../chunk-
|
|
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
|
|
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) {
|
|
@@ -50,10 +44,8 @@ async function analyzeAndIngest(html, route, origin, rules, config, lastSignatur
|
|
|
50
44
|
];
|
|
51
45
|
const images = [{ route, images: imgs.map((img) => ({ ...img, file: route })) }];
|
|
52
46
|
const project = { hasRobotsTxt: true, hasSitemap: true, htmlLang };
|
|
53
|
-
const results =
|
|
54
|
-
|
|
55
|
-
config
|
|
56
|
-
);
|
|
47
|
+
const { results: ruleResults } = await runRules(rules, { heads: [head], headings, images, project, config });
|
|
48
|
+
const results = applyRuleSeverities(ruleResults, config);
|
|
57
49
|
const signature = findingSignature(results, config);
|
|
58
50
|
if (lastSignature.get(route) === signature) return;
|
|
59
51
|
lastSignature.set(route, signature);
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isLoopbackHost,
|
|
3
3
|
isLoopbackOrigin,
|
|
4
4
|
parseHtmlHead
|
|
5
|
-
} from "./chunk-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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),
|
|
@@ -210,22 +214,17 @@ async function analyze(prerenderPagesDir, cwd, options, extraProjectFacts) {
|
|
|
210
214
|
const kitModules = await collectKitModuleFacts(cwd, project.kitAliases);
|
|
211
215
|
const sourceFiles = await collectSourceFiles(cwd);
|
|
212
216
|
const selected = selectRules(allRules, config);
|
|
213
|
-
const results =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}),
|
|
225
|
-
config
|
|
226
|
-
),
|
|
227
|
-
config
|
|
228
|
-
);
|
|
217
|
+
const { results: rawResults, examined } = await runRules(selected, {
|
|
218
|
+
heads,
|
|
219
|
+
headings,
|
|
220
|
+
images,
|
|
221
|
+
project,
|
|
222
|
+
components,
|
|
223
|
+
config,
|
|
224
|
+
kitModules,
|
|
225
|
+
sourceFiles
|
|
226
|
+
});
|
|
227
|
+
const results = applyOverrides(applyRuleSeverities(rawResults, config), config);
|
|
229
228
|
const { score } = computeScore(results, config);
|
|
230
229
|
const summary = summarize(results, config);
|
|
231
230
|
const failed = hasFailureAtOrAbove(summary, config.failOn);
|
|
@@ -236,7 +235,8 @@ Scanned ${components.length} component(s) under src/ for Correctness/Security/Ar
|
|
|
236
235
|
results,
|
|
237
236
|
config,
|
|
238
237
|
{ version: readPackageVersion() },
|
|
239
|
-
selected.map((r) => r.id)
|
|
238
|
+
selected.map((r) => r.id),
|
|
239
|
+
examined
|
|
240
240
|
);
|
|
241
241
|
return {
|
|
242
242
|
score,
|
|
@@ -269,7 +269,7 @@ async function resolveMinifyDisabled(minify, configFile, root) {
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
// src/ui/middleware.ts
|
|
272
|
-
import { renderAppShell } from "@svelte-vitals/core";
|
|
272
|
+
import { CATEGORIES, renderAppShell } from "@svelte-vitals/core";
|
|
273
273
|
|
|
274
274
|
// src/ui/snapshot.ts
|
|
275
275
|
import { buildJsonReport, safeHref } from "@svelte-vitals/core";
|
|
@@ -301,7 +301,7 @@ function buildSnapshot(store, config, meta) {
|
|
|
301
301
|
|
|
302
302
|
// src/ui/middleware.ts
|
|
303
303
|
var SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
|
|
304
|
-
var
|
|
304
|
+
var CATEGORY_SET = new Set(CATEGORIES);
|
|
305
305
|
function isOptionalString(v) {
|
|
306
306
|
return v === void 0 || typeof v === "string";
|
|
307
307
|
}
|
|
@@ -310,7 +310,7 @@ function isResultLike(x) {
|
|
|
310
310
|
const r = x;
|
|
311
311
|
const d = r.detection;
|
|
312
312
|
const f = r.fix;
|
|
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" &&
|
|
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);
|
|
314
314
|
}
|
|
315
315
|
function installUiMiddleware(server, config, version, store, coreVersion) {
|
|
316
316
|
const clients = /* @__PURE__ */ new Set();
|
|
@@ -616,10 +616,17 @@ function svelteVitals(options = {}) {
|
|
|
616
616
|
const pagesDir = options.prerenderDir ? options.prerenderDir : join4(root, DEFAULT_PRERENDER_DIR);
|
|
617
617
|
const resolved = isAbsolute(pagesDir) ? pagesDir : join4(root, pagesDir);
|
|
618
618
|
if (!existsSync(resolved)) return;
|
|
619
|
+
const resolvedConfig = await resolveConfig(root, options);
|
|
619
620
|
let result;
|
|
620
621
|
try {
|
|
621
622
|
const viteMinifyDisabled = minifyFlag ? await resolveMinifyDisabled(minifyFlag.minify, minifyFlag.configFile, root) : void 0;
|
|
622
|
-
result = await analyze(
|
|
623
|
+
result = await analyze(
|
|
624
|
+
resolved,
|
|
625
|
+
root,
|
|
626
|
+
options,
|
|
627
|
+
viteMinifyDisabled ? { viteMinifyDisabled } : void 0,
|
|
628
|
+
resolvedConfig
|
|
629
|
+
);
|
|
623
630
|
} catch (err) {
|
|
624
631
|
console.warn(`svelte-vitals: skipped \u2014 analysis failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
625
632
|
return;
|
|
@@ -647,17 +654,18 @@ function svelteVitals(options = {}) {
|
|
|
647
654
|
async configureServer(server) {
|
|
648
655
|
process.env.SVELTE_VITALS_UI = "1";
|
|
649
656
|
const uiRoot = options.cwd ?? server.config.root;
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
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}`);
|
|
661
669
|
const store = createStore();
|
|
662
670
|
const runner = createAnalysisRunner({
|
|
663
671
|
root: uiRoot,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svelte-vitals/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Vite/SvelteKit plugin for svelte-vitals — analyzes prerendered HTML during vite build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -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
|
-
"
|
|
46
|
-
"svelte-vitals": "0.
|
|
45
|
+
"svelte-vitals": "0.44.0",
|
|
46
|
+
"@svelte-vitals/core": "0.38.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@sveltejs/kit": "^2.70.2",
|