@svelte-vitals/vite 0.36.1 → 0.36.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/dist/hooks/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as parseHtmlHead, r as toOccurrenceMap, t as isLoopbackOrigin } from "../loopback-OZjFnUGp.js";
|
|
2
2
|
import { defineConfig } from "@svelte-vitals/core";
|
|
3
|
-
import { allRules,
|
|
3
|
+
import { allRules, defaultProject, effectiveSeverity, formatFailedRuleWarning, isPenalized, runAnalysis, selectRules, terminalSafe } from "@svelte-vitals/core/internal";
|
|
4
4
|
import { DEV } from "esm-env";
|
|
5
5
|
//#region src/hooks/handle.ts
|
|
6
6
|
/** Stable signature of a route's penalized findings, so ingest is skipped when a repeat visit finds nothing new. */
|
|
@@ -66,16 +66,14 @@ async function analyzeAndIngest(html, route, origin, rules, config, lastSignatur
|
|
|
66
66
|
idCandidates: [...new Set(ids)],
|
|
67
67
|
fullyResolved: true
|
|
68
68
|
}];
|
|
69
|
-
const { results
|
|
69
|
+
const { results, failedRules, failedRuleIds } = await runAnalysis(rules, {
|
|
70
70
|
heads: [head],
|
|
71
71
|
headings,
|
|
72
72
|
images,
|
|
73
73
|
a11y,
|
|
74
74
|
project: defaultProject,
|
|
75
75
|
config
|
|
76
|
-
});
|
|
77
|
-
const results = applyRuleSeverities(ruleResults, config);
|
|
78
|
-
const failedRuleIds = failedRules.map((f) => f.id);
|
|
76
|
+
}, /* @__PURE__ */ new Map());
|
|
79
77
|
if (failedRules.length > 0 && globalThis.process?.env?.SVELTE_VITALS_DEBUG) for (const f of failedRules) warn(formatFailedRuleWarning(f));
|
|
80
78
|
const signature = `${findingSignature(results, config)}|failed:${[...failedRuleIds].sort().join(",")}`;
|
|
81
79
|
if (lastSignature.get(route) === signature) return;
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { n as collectRenderedHeads, t as isLoopbackOrigin } from "./loopback-
|
|
1
|
+
import { i as globFiles, n as collectRenderedHeads, t as isLoopbackOrigin } from "./loopback-OZjFnUGp.js";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
5
5
|
import { CATEGORIES, defineConfig } from "@svelte-vitals/core";
|
|
6
|
-
import { ROBOTS_SOURCE_PATHS, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, VITE_CONFIG_FILES,
|
|
6
|
+
import { ROBOTS_SOURCE_PATHS, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, VITE_CONFIG_FILES, addFactsDirectives, allRules, buildJsonReport, collectComponentFacts, collectKitModuleFacts, collectSourceFiles, collectSuppressions, computeScore, defaultConfig, findMinifyDisabled, formatConsoleReport, formatFailedRuleWarning, formatJsonReport, hasFailureAtOrAbove, renderAppShell, resolveKitAliases, resolveKitPathsBase, resolveRuleOptions, runAnalysis, safeHref, selectRules, shouldSkipRangeCheck, skippedFileWarnings, summarize, terminalSafe, unknownDirectiveIds, validateRuleSetting, withFailedRulesOff, withReadLimit } from "@svelte-vitals/core/internal";
|
|
7
7
|
import { CONFIG_FILENAMES, analyzeProject, findUnknownRuleIds, knownRuleIds, loadConfigFile, registryTag, ruleOptionsSpec } from "svelte-vitals";
|
|
8
|
-
import { glob } from "tinyglobby";
|
|
9
8
|
//#region src/providers/rendered/project.ts
|
|
10
9
|
async function exists(path) {
|
|
11
10
|
try {
|
|
@@ -78,10 +77,7 @@ const nodeRuntime = {
|
|
|
78
77
|
return false;
|
|
79
78
|
}
|
|
80
79
|
},
|
|
81
|
-
glob: (pattern, cwd) =>
|
|
82
|
-
cwd,
|
|
83
|
-
dot: false
|
|
84
|
-
}),
|
|
80
|
+
glob: (pattern, cwd) => globFiles(pattern, cwd),
|
|
85
81
|
join: (...parts) => join(...parts)
|
|
86
82
|
};
|
|
87
83
|
/**
|
|
@@ -185,7 +181,13 @@ async function analyze(prerenderPagesDir, cwd, options, extraProjectFacts, resol
|
|
|
185
181
|
const kitModules = await collectKitModuleFacts$1(cwd, project.kitAliases);
|
|
186
182
|
const selected = selectRules(allRules, config);
|
|
187
183
|
if (selected.some((r) => r.id === "a11y/unverified-id-ref")) warnings.push("a11y/unverified-id-ref has no effect in rendered mode — the prerendered document is always fully resolved.");
|
|
188
|
-
const
|
|
184
|
+
const directives = /* @__PURE__ */ new Map();
|
|
185
|
+
addFactsDirectives(directives, {
|
|
186
|
+
components,
|
|
187
|
+
kitModules,
|
|
188
|
+
viteMinifyDisabled: project.viteMinifyDisabled
|
|
189
|
+
});
|
|
190
|
+
const { results, examined, failedRules, scoringConfig } = await runAnalysis(selected, {
|
|
189
191
|
heads,
|
|
190
192
|
headings,
|
|
191
193
|
images,
|
|
@@ -195,16 +197,10 @@ async function analyze(prerenderPagesDir, cwd, options, extraProjectFacts, resol
|
|
|
195
197
|
config,
|
|
196
198
|
kitModules,
|
|
197
199
|
sourceFiles
|
|
198
|
-
});
|
|
199
|
-
const directives = /* @__PURE__ */ new Map();
|
|
200
|
-
for (const c of components) directives.set(c.file, c.suppressions ?? []);
|
|
201
|
-
for (const m of kitModules) directives.set(m.file, m.suppressions ?? []);
|
|
202
|
-
if (project.viteMinifyDisabled?.file) directives.set(project.viteMinifyDisabled.file, project.viteMinifyDisabled.suppressions ?? []);
|
|
203
|
-
const results = applyInlineDirectives(applyOverrides(applyRuleSeverities(rawResults, config), config), directives, selected, config);
|
|
200
|
+
}, directives);
|
|
204
201
|
warnings.push(...skippedFileWarnings([...components, ...kitModules]));
|
|
205
202
|
warnings.push(...unknownDirectiveIds(directives, allRules));
|
|
206
203
|
for (const f of failedRules) warnings.push(formatFailedRuleWarning(f));
|
|
207
|
-
const scoringConfig = withFailedRulesOff(config, failedRules.map((f) => f.id));
|
|
208
204
|
const { score } = computeScore(results, scoringConfig);
|
|
209
205
|
const summary = summarize(results, scoringConfig);
|
|
210
206
|
const failed = hasFailureAtOrAbove(summary, scoringConfig.failOn);
|
|
@@ -1,48 +1,11 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { IDREF_ATTRS,
|
|
4
|
-
import { glob } from "tinyglobby";
|
|
1
|
+
import { glob, readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { join, relative, sep } from "node:path";
|
|
3
|
+
import { ASIDE_DEMOTING_TAGS, IDREF_ATTRS, NAMING_ATTRS, SECTIONING_TAGS, decodeFragmentId, isClassicScriptType, isTopFragment, resolveLandmark, splitTokens, stripTextDirective } from "@svelte-vitals/core/internal";
|
|
5
4
|
import { parse } from "node-html-parser";
|
|
6
5
|
//#region src/providers/rendered/parse-html.ts
|
|
7
6
|
function attrValue(v) {
|
|
8
7
|
return v !== void 0 && v.trim().length > 0 ? "static" : "absent";
|
|
9
8
|
}
|
|
10
|
-
const JS_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
11
|
-
"application/ecmascript",
|
|
12
|
-
"application/javascript",
|
|
13
|
-
"application/x-ecmascript",
|
|
14
|
-
"application/x-javascript",
|
|
15
|
-
"text/ecmascript",
|
|
16
|
-
"text/javascript",
|
|
17
|
-
"text/javascript1.0",
|
|
18
|
-
"text/javascript1.1",
|
|
19
|
-
"text/javascript1.2",
|
|
20
|
-
"text/javascript1.3",
|
|
21
|
-
"text/javascript1.4",
|
|
22
|
-
"text/javascript1.5",
|
|
23
|
-
"text/jscript",
|
|
24
|
-
"text/livescript",
|
|
25
|
-
"text/x-ecmascript",
|
|
26
|
-
"text/x-javascript"
|
|
27
|
-
]);
|
|
28
|
-
function isClassicScriptType(type) {
|
|
29
|
-
if (type === void 0) return true;
|
|
30
|
-
const normalized = type.trim().toLowerCase();
|
|
31
|
-
return normalized === "" || JS_MIME_TYPES.has(normalized);
|
|
32
|
-
}
|
|
33
|
-
const SECTIONING_TAGS = /* @__PURE__ */ new Set([
|
|
34
|
-
"article",
|
|
35
|
-
"aside",
|
|
36
|
-
"main",
|
|
37
|
-
"nav",
|
|
38
|
-
"section"
|
|
39
|
-
]);
|
|
40
|
-
const ASIDE_DEMOTING_TAGS = /* @__PURE__ */ new Set([
|
|
41
|
-
"article",
|
|
42
|
-
"aside",
|
|
43
|
-
"nav",
|
|
44
|
-
"section"
|
|
45
|
-
]);
|
|
46
9
|
/** Whole-document scan (not body-scoped: app.html shell ids/refs are real occurrences too). */
|
|
47
10
|
function collectA11y(root) {
|
|
48
11
|
const landmarks = [];
|
|
@@ -54,16 +17,13 @@ function collectA11y(root) {
|
|
|
54
17
|
const tag = el.rawTagName?.toLowerCase();
|
|
55
18
|
if (tag && ctx.inBody) elementTags.add(tag);
|
|
56
19
|
const roleAttr = el.getAttribute("role");
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const named = ["aria-label", "aria-labelledby"].some((a) => (el.getAttribute(a) ?? "").trim().length > 0);
|
|
65
|
-
landmark = ctx.asideDemoting === 0 || named ? "complementary" : void 0;
|
|
66
|
-
}
|
|
20
|
+
const landmark = resolveLandmark({
|
|
21
|
+
tag,
|
|
22
|
+
roleTokens: roleAttr !== void 0 ? splitTokens(roleAttr) : void 0,
|
|
23
|
+
named: tag === "aside" && NAMING_ATTRS.some((a) => (el.getAttribute(a) ?? "").trim().length > 0),
|
|
24
|
+
insideSectioning: ctx.sectioning > 0,
|
|
25
|
+
insideAsideDemoting: ctx.asideDemoting > 0
|
|
26
|
+
});
|
|
67
27
|
if (landmark) {
|
|
68
28
|
landmarks.push(landmark);
|
|
69
29
|
const within = ctx.landmarks.at(-1);
|
|
@@ -221,6 +181,32 @@ function parseHtmlHead(html) {
|
|
|
221
181
|
};
|
|
222
182
|
}
|
|
223
183
|
//#endregion
|
|
184
|
+
//#region src/glob.ts
|
|
185
|
+
/**
|
|
186
|
+
* `node:fs` glob constrained to the contract callers rely on: files only (fs.glob also matches
|
|
187
|
+
* directories), cwd-relative POSIX-separated paths on every platform (fs.glob returns platform
|
|
188
|
+
* separators), dotfiles excluded (fs.glob's default). A symlink's Dirent never reports isFile(),
|
|
189
|
+
* so symlinks are stat'd and kept when they point at a file; symlinked *directories* are not
|
|
190
|
+
* traversed — fs.glob never descends into them. Duplicated in the CLI package — core purity
|
|
191
|
+
* (no `node:` imports in core) rules out the shared home.
|
|
192
|
+
*/
|
|
193
|
+
async function globFiles(pattern, cwd) {
|
|
194
|
+
const out = [];
|
|
195
|
+
for await (const entry of glob(pattern, {
|
|
196
|
+
cwd,
|
|
197
|
+
withFileTypes: true
|
|
198
|
+
})) {
|
|
199
|
+
const path = join(entry.parentPath, entry.name);
|
|
200
|
+
if (!entry.isFile()) {
|
|
201
|
+
if (!entry.isSymbolicLink()) continue;
|
|
202
|
+
if (!(await stat(path).catch(() => null))?.isFile()) continue;
|
|
203
|
+
}
|
|
204
|
+
const rel = relative(cwd, path);
|
|
205
|
+
out.push(sep === "/" ? rel : rel.split(sep).join("/"));
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
224
210
|
//#region src/providers/rendered/collect.ts
|
|
225
211
|
/** Group raw occurrence keys (one entry per hit, in document order) by key, `file` attached, `line: 0` (rendered mode does not track source lines). */
|
|
226
212
|
function toOccurrenceMap(keys, file) {
|
|
@@ -240,7 +226,7 @@ function deriveRouteFromHtmlPath(relPath) {
|
|
|
240
226
|
}
|
|
241
227
|
/** Read every prerendered HTML page under `prerenderPagesDir` into ResolvedHead[]. */
|
|
242
228
|
async function collectRenderedHeads(prerenderPagesDir) {
|
|
243
|
-
const files = (await
|
|
229
|
+
const files = (await globFiles("**/*.html", prerenderPagesDir)).sort();
|
|
244
230
|
const parsedFiles = await Promise.all(files.map(async (rel) => ({
|
|
245
231
|
rel,
|
|
246
232
|
parsed: parseHtmlHead(await readFile(join(prerenderPagesDir, rel), "utf8"))
|
|
@@ -318,4 +304,4 @@ function isLoopbackOrigin(origin) {
|
|
|
318
304
|
}
|
|
319
305
|
}
|
|
320
306
|
//#endregion
|
|
321
|
-
export { parseHtmlHead as i, collectRenderedHeads as n, toOccurrenceMap as r, isLoopbackOrigin as t };
|
|
307
|
+
export { parseHtmlHead as a, globFiles as i, collectRenderedHeads as n, toOccurrenceMap as r, isLoopbackOrigin as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svelte-vitals/vite",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.2",
|
|
4
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",
|
|
@@ -40,13 +40,12 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"esm-env": "^1.2.2",
|
|
43
|
-
"node-html-parser": "^9.0.
|
|
44
|
-
"tinyglobby": "^0.2.17"
|
|
43
|
+
"node-html-parser": "^9.0.2"
|
|
45
44
|
},
|
|
46
45
|
"peerDependencies": {
|
|
47
|
-
"@svelte-vitals/core": "^0.
|
|
46
|
+
"@svelte-vitals/core": "^0.51.0",
|
|
48
47
|
"@sveltejs/kit": "^2.70.3",
|
|
49
|
-
"svelte-vitals": "^0.54.
|
|
48
|
+
"svelte-vitals": "^0.54.2",
|
|
50
49
|
"vite": "^8.2.2"
|
|
51
50
|
},
|
|
52
51
|
"peerDependenciesMeta": {
|
|
@@ -55,12 +54,12 @@
|
|
|
55
54
|
}
|
|
56
55
|
},
|
|
57
56
|
"devDependencies": {
|
|
58
|
-
"@svelte-vitals/core": "0.
|
|
57
|
+
"@svelte-vitals/core": "0.51.0",
|
|
59
58
|
"@sveltejs/kit": "^2.70.3",
|
|
60
59
|
"@types/node": "^24.13.3",
|
|
61
|
-
"happy-dom": "^20.11.
|
|
62
|
-
"svelte": "^5.
|
|
63
|
-
"svelte-vitals": "0.54.
|
|
60
|
+
"happy-dom": "^20.11.15",
|
|
61
|
+
"svelte": "^5.57.0",
|
|
62
|
+
"svelte-vitals": "0.54.2",
|
|
64
63
|
"vite": "^8.2.2"
|
|
65
64
|
},
|
|
66
65
|
"scripts": {
|