@svelte-vitals/vite 0.32.1 → 0.32.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.d.ts +9 -9
- package/dist/hooks/index.js +103 -100
- package/dist/index.d.ts +29 -29
- package/dist/index.js +715 -674
- package/dist/loopback-dIwCgCTG.js +321 -0
- package/package.json +5 -5
- package/dist/chunk-KII3SU3J.js +0 -258
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { RuleSetting } from "@svelte-vitals/core";
|
|
2
|
+
import { Handle } from "@sveltejs/kit";
|
|
3
|
+
//#region src/hooks/handle.d.ts
|
|
4
4
|
/** Options for the dev-time SvelteKit handle. A focused subset of the plugin options. */
|
|
5
5
|
interface SvelteVitalsHookOptions {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/** Component names treated as meta sources (design §11 layer 4). Mirrors the plugin option. */
|
|
7
|
+
metaComponents?: string[];
|
|
8
|
+
/** Per-rule overrides keyed by rule id, e.g. `{ 'seo/json-ld': 'off' }`. Mirrors the plugin option. */
|
|
9
|
+
rules?: Record<string, RuleSetting>;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* SvelteKit `handle` that analyzes each visited page's rendered HTML, in dev only,
|
|
@@ -15,5 +15,5 @@ interface SvelteVitalsHookOptions {
|
|
|
15
15
|
* HTML). Add it to `src/hooks.server.ts`, e.g. `sequence(svelteVitalsHandle())`.
|
|
16
16
|
*/
|
|
17
17
|
declare function svelteVitalsHandle(options?: SvelteVitalsHookOptions): Handle;
|
|
18
|
-
|
|
19
|
-
export { type SvelteVitalsHookOptions, svelteVitalsHandle };
|
|
18
|
+
//#endregion
|
|
19
|
+
export { type SvelteVitalsHookOptions, svelteVitalsHandle };
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,109 +1,112 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isLoopbackOrigin,
|
|
3
|
-
parseHtmlHead,
|
|
4
|
-
toOccurrenceMap
|
|
5
|
-
} from "../chunk-KII3SU3J.js";
|
|
6
|
-
|
|
7
|
-
// src/hooks/handle.ts
|
|
8
|
-
import { DEV } from "esm-env";
|
|
1
|
+
import { i as parseHtmlHead, r as toOccurrenceMap, t as isLoopbackOrigin } from "../loopback-dIwCgCTG.js";
|
|
9
2
|
import { defineConfig } from "@svelte-vitals/core";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
effectiveSeverity,
|
|
15
|
-
formatFailedRuleWarning,
|
|
16
|
-
isPenalized,
|
|
17
|
-
runRules,
|
|
18
|
-
selectRules,
|
|
19
|
-
terminalSafe
|
|
20
|
-
} from "@svelte-vitals/core/internal";
|
|
3
|
+
import { allRules, applyRuleSeverities, defaultProject, effectiveSeverity, formatFailedRuleWarning, isPenalized, runRules, selectRules, terminalSafe } from "@svelte-vitals/core/internal";
|
|
4
|
+
import { DEV } from "esm-env";
|
|
5
|
+
//#region src/hooks/handle.ts
|
|
6
|
+
/** Stable signature of a route's penalized findings, so ingest is skipped when a repeat visit finds nothing new. */
|
|
21
7
|
function findingSignature(results, config) {
|
|
22
|
-
|
|
8
|
+
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
9
|
}
|
|
24
|
-
|
|
10
|
+
const warn = (line) => console.warn(terminalSafe(line));
|
|
25
11
|
async function postIngest(origin, route, results, failedRuleIds) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
42
|
-
} catch {
|
|
43
|
-
}
|
|
12
|
+
if (!isLoopbackOrigin(origin)) {
|
|
13
|
+
if (globalThis.process?.env?.SVELTE_VITALS_DEBUG) warn(`[svelte-vitals] live UI ingest skipped for non-loopback origin ${origin} — open the dashboard via localhost`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
await fetch(`${origin}/__svelte-vitals/ingest`, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: { "content-type": "application/json" },
|
|
20
|
+
body: JSON.stringify({
|
|
21
|
+
route,
|
|
22
|
+
results,
|
|
23
|
+
failedRuleIds
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
} catch {}
|
|
44
27
|
}
|
|
45
28
|
async function analyzeAndIngest(html, route, origin, rules, config, lastSignature) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
29
|
+
try {
|
|
30
|
+
const { tags, headings: levels, images: imgs, landmarks, nestedLandmarks, ids, idRefs } = parseHtmlHead(html);
|
|
31
|
+
const head = {
|
|
32
|
+
route,
|
|
33
|
+
source: "rendered",
|
|
34
|
+
tags,
|
|
35
|
+
file: route
|
|
36
|
+
};
|
|
37
|
+
const headings = [{
|
|
38
|
+
route,
|
|
39
|
+
headings: levels.map((level) => ({
|
|
40
|
+
level,
|
|
41
|
+
line: 0,
|
|
42
|
+
file: route
|
|
43
|
+
}))
|
|
44
|
+
}];
|
|
45
|
+
const images = [{
|
|
46
|
+
route,
|
|
47
|
+
images: imgs.map((img) => ({
|
|
48
|
+
...img,
|
|
49
|
+
file: route
|
|
50
|
+
}))
|
|
51
|
+
}];
|
|
52
|
+
const a11y = [{
|
|
53
|
+
route,
|
|
54
|
+
landmarks: toOccurrenceMap(landmarks, route),
|
|
55
|
+
nestedLandmarks: nestedLandmarks.map((n) => ({
|
|
56
|
+
...n,
|
|
57
|
+
file: route,
|
|
58
|
+
line: 0
|
|
59
|
+
})),
|
|
60
|
+
ids: toOccurrenceMap(ids, route),
|
|
61
|
+
idRefs: idRefs.map((r) => ({
|
|
62
|
+
...r,
|
|
63
|
+
file: route,
|
|
64
|
+
line: 0
|
|
65
|
+
})),
|
|
66
|
+
idCandidates: [...new Set(ids)],
|
|
67
|
+
fullyResolved: true
|
|
68
|
+
}];
|
|
69
|
+
const { results: ruleResults, failedRules } = await runRules(rules, {
|
|
70
|
+
heads: [head],
|
|
71
|
+
headings,
|
|
72
|
+
images,
|
|
73
|
+
a11y,
|
|
74
|
+
project: defaultProject,
|
|
75
|
+
config
|
|
76
|
+
});
|
|
77
|
+
const results = applyRuleSeverities(ruleResults, config);
|
|
78
|
+
const failedRuleIds = failedRules.map((f) => f.id);
|
|
79
|
+
if (failedRules.length > 0 && globalThis.process?.env?.SVELTE_VITALS_DEBUG) for (const f of failedRules) warn(formatFailedRuleWarning(f));
|
|
80
|
+
const signature = `${findingSignature(results, config)}|failed:${[...failedRuleIds].sort().join(",")}`;
|
|
81
|
+
if (lastSignature.get(route) === signature) return;
|
|
82
|
+
lastSignature.set(route, signature);
|
|
83
|
+
if (globalThis.process?.env?.SVELTE_VITALS_UI) postIngest(origin, route, results, failedRuleIds);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
if (globalThis.process?.env?.SVELTE_VITALS_DEBUG) warn(`[svelte-vitals] dev analysis failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
86
|
+
}
|
|
86
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* SvelteKit `handle` that analyzes each visited page's rendered HTML, in dev only,
|
|
90
|
+
* and (when the live dashboard is enabled) feeds the results in — upgrading that
|
|
91
|
+
* route's dashboard findings from static (source-only) to `measured` (real rendered
|
|
92
|
+
* HTML). Add it to `src/hooks.server.ts`, e.g. `sequence(svelteVitalsHandle())`.
|
|
93
|
+
*/
|
|
87
94
|
function svelteVitalsHandle(options = {}) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
};
|
|
95
|
+
if (!DEV) return ({ event, resolve }) => resolve(event);
|
|
96
|
+
const config = defineConfig({
|
|
97
|
+
metaComponents: options.metaComponents ?? [],
|
|
98
|
+
rules: options.rules ?? {}
|
|
99
|
+
});
|
|
100
|
+
const rules = selectRules(allRules, config).filter((r) => r.scope === "route" && !r.crossRoute);
|
|
101
|
+
const lastSignature = /* @__PURE__ */ new Map();
|
|
102
|
+
return ({ event, resolve }) => {
|
|
103
|
+
let buffer = "";
|
|
104
|
+
return resolve(event, { transformPageChunk: ({ html, done }) => {
|
|
105
|
+
buffer += html;
|
|
106
|
+
if (done && event.route.id != null) analyzeAndIngest(buffer, event.route.id, event.url.origin, rules, config, lastSignature);
|
|
107
|
+
return html;
|
|
108
|
+
} });
|
|
109
|
+
};
|
|
106
110
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
111
|
+
//#endregion
|
|
112
|
+
export { svelteVitalsHandle };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { Category, RuleOverride, RuleSetting, Severity, TreatDynamicAs } from "@svelte-vitals/core";
|
|
2
|
+
import { Plugin } from "vite";
|
|
3
|
+
//#region src/plugin.d.ts
|
|
4
4
|
interface SvelteVitalsOptions {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
5
|
+
/** Project root (defaults to the Vite config root / cwd). */
|
|
6
|
+
cwd?: string;
|
|
7
|
+
treatDynamicAs?: TreatDynamicAs;
|
|
8
|
+
metaComponents?: string[];
|
|
9
|
+
rules?: Record<string, RuleSetting>;
|
|
10
|
+
/** Route-/file-scoped rule overrides applied to build-gate results (option > config file). */
|
|
11
|
+
overrides?: RuleOverride[];
|
|
12
|
+
/** Minimum severity that fails the build (default: 'critical'). */
|
|
13
|
+
failOn?: Severity;
|
|
14
|
+
/** Per-category weights for the combined Health score shown in the JSON/console report (flag > config file > default 1 each). */
|
|
15
|
+
weights?: Partial<Record<Category, number>>;
|
|
16
|
+
/** Report output (default: 'console'). */
|
|
17
|
+
report?: 'console' | 'json' | false;
|
|
18
|
+
/** Write the JSON report to this path. */
|
|
19
|
+
outFile?: string;
|
|
20
|
+
/** Override the prerendered-pages directory (default: .svelte-kit/output/prerendered/pages). */
|
|
21
|
+
prerenderDir?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Serve a live dashboard at /__svelte-vitals/ during `vite dev` (add
|
|
24
|
+
* svelteVitalsHandle to hooks.server.ts for accurate, per-route `measured` results
|
|
25
|
+
* as you browse — the dashboard still works without it, from whole-project static
|
|
26
|
+
* analysis alone). Default: `true`. Pass `false` to keep only the build-time gate.
|
|
27
|
+
*/
|
|
28
|
+
ui?: boolean;
|
|
29
29
|
}
|
|
30
30
|
/** svelte-vitals Vite/SvelteKit plugin. */
|
|
31
31
|
declare function svelteVitals(options?: SvelteVitalsOptions): Plugin | Plugin[];
|
|
32
|
-
|
|
33
|
-
export { type SvelteVitalsOptions, svelteVitals };
|
|
32
|
+
//#endregion
|
|
33
|
+
export { type SvelteVitalsOptions, svelteVitals };
|