@svelte-vitals/vite 0.15.1 → 0.16.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/README.md +13 -3
- package/dist/index.js +83 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@svelte-vitals/vite)
|
|
4
4
|
|
|
5
|
-
Vite/SvelteKit plugin for [svelte-vitals](https://github.com/oekazuma/svelte-vitals).
|
|
5
|
+
Vite/SvelteKit plugin for [svelte-vitals](https://github.com/oekazuma/svelte-vitals). Two things in one package:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Build-time gate** — piggybacks on `vite build`, parses the **prerendered HTML's `<head>`**, and runs the same rule engine as the CLI (SEO, Performance, Correctness, Security, Architecture) — library-agnostic, because it inspects the real output. Fails the build when findings reach `failOn`.
|
|
8
|
+
- **Live dev dashboard** — on by default during `vite dev`: a searchable, filterable code-health dashboard at `/__svelte-vitals/`, covering the whole project from startup via static analysis, refined to real rendered values as you browse.
|
|
9
|
+
|
|
10
|
+
> **ESM-only** (Node 22.13+). Ships ES modules only; `require()` is unsupported by design.
|
|
8
11
|
|
|
9
12
|
## Usage
|
|
10
13
|
|
|
@@ -18,15 +21,22 @@ export default {
|
|
|
18
21
|
};
|
|
19
22
|
```
|
|
20
23
|
|
|
24
|
+
`vite dev` prints the dashboard's URL next to its own `Local:`/`Network:` lines. Add the `svelteVitalsHandle` hook (from `@svelte-vitals/vite/hooks`) to `src/hooks.server.ts` for per-route `measured` accuracy as you browse — the dashboard works without it too, from whole-project static analysis alone.
|
|
25
|
+
|
|
21
26
|
## Options
|
|
22
27
|
|
|
23
28
|
- `failOn` — minimum severity that fails the build (default `critical`).
|
|
24
29
|
- `report` — `'console' | 'json' | false` (default `console`).
|
|
25
30
|
- `outFile` — write the JSON report to a path.
|
|
26
31
|
- `rules` / `metaComponents` / `treatDynamicAs` — same as the CLI/core config.
|
|
32
|
+
- `weights` — per-category weight overrides for the combined Health score.
|
|
27
33
|
- `prerenderDir` — override the prerendered-pages directory.
|
|
34
|
+
- `cwd` — project root (defaults to the Vite config root).
|
|
35
|
+
- `ui` — serve the live dev dashboard (default `true`); pass `false` to keep only the build-time gate.
|
|
36
|
+
|
|
37
|
+
Only **prerendered** routes are analyzed at build time; for SSR/dynamic routes use the `svelte-vitals` CLI, or browse them in the live dashboard during `vite dev`.
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
See [Live dashboard](https://oekazuma.github.io/svelte-vitals/guides/dev-dashboard/) and [Plugin mode](https://oekazuma.github.io/svelte-vitals/guides/plugin-mode/) for the full picture.
|
|
30
40
|
|
|
31
41
|
## License
|
|
32
42
|
|
package/dist/index.js
CHANGED
|
@@ -294,6 +294,16 @@ body{background:var(--ground);color:var(--ink);font-family:var(--sans);line-heig
|
|
|
294
294
|
.tok-pn{color:#8da0bd}
|
|
295
295
|
.dv-f-link{display:inline-block;margin-top:12px;font-size:13px;font-weight:600;color:var(--accent);text-decoration:none}
|
|
296
296
|
.dv-f-link:hover{text-decoration:underline}
|
|
297
|
+
.dv-ai-prompt{margin-top:12px;border:1px solid var(--line);border-radius:8px;overflow:hidden}
|
|
298
|
+
.dv-ai-prompt>summary{cursor:pointer;list-style:none;padding:8px 12px;font-size:12px;font-weight:600;color:var(--muted);display:flex;align-items:center;gap:6px;user-select:none}
|
|
299
|
+
.dv-ai-prompt>summary::-webkit-details-marker{display:none}
|
|
300
|
+
.dv-ai-prompt>summary::before{content:"\u25B8";display:inline-block;transition:transform .15s ease}
|
|
301
|
+
.dv-ai-prompt[open]>summary::before{transform:rotate(90deg)}
|
|
302
|
+
.dv-ai-prompt-body{padding:0 12px 12px;display:flex;flex-direction:column;gap:8px}
|
|
303
|
+
.dv-ai-prompt-pre{margin:0;padding:10px 12px;background:var(--code-bg);color:var(--code-ink);border-radius:8px;font-family:var(--mono);font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-word;max-height:280px;overflow-y:auto}
|
|
304
|
+
.dv-ai-copy-btn{align-self:flex-start;font:inherit;font-size:12px;font-weight:600;cursor:pointer;background:var(--panel);border:1px solid var(--line-strong);color:var(--ink);padding:5px 12px;border-radius:999px}
|
|
305
|
+
.dv-ai-copy-btn:hover{border-color:var(--faint)}
|
|
306
|
+
.dv-ai-copy-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
|
297
307
|
.dv-empty{color:var(--muted);font-size:13px}
|
|
298
308
|
@media (max-width:640px){.dv-app{grid-template-columns:1fr;grid-template-areas:"top" "main"}.dv-menu-toggle{display:inline-flex}.dv-sidebar{position:fixed;inset:0 20% 0 0;transform:translateX(-100%);transition:transform .2s ease;z-index:10}.dv-sidebar.open{transform:translateX(0)}}
|
|
299
309
|
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
|
|
@@ -406,6 +416,76 @@ var DASHBOARD_SCRIPT = `
|
|
|
406
416
|
return pre;
|
|
407
417
|
}
|
|
408
418
|
|
|
419
|
+
// Plain-text, copy-pasteable prompt for a single finding \u2014 same ingredients as the
|
|
420
|
+
// agent reporter's per-finding block (rule id, location, recommendation, fix, docs),
|
|
421
|
+
// reshaped for a standalone request rather than a whole-project remediation doc.
|
|
422
|
+
function buildAiPrompt(issue, route) {
|
|
423
|
+
var lines = ['Fix this svelte-vitals finding:', ''];
|
|
424
|
+
lines.push('- Rule: ' + issue.id + ' \u2014 ' + issue.title + ' (' + issue.severity + ')');
|
|
425
|
+
if (route) lines.push('- Route: ' + route);
|
|
426
|
+
if (issue.location) {
|
|
427
|
+
lines.push('- Location: ' + issue.location + (issue.line !== undefined ? ':' + issue.line : ''));
|
|
428
|
+
}
|
|
429
|
+
if (issue.recommendation) lines.push('- Recommendation: ' + issue.recommendation);
|
|
430
|
+
if (issue.fix) {
|
|
431
|
+
lines.push('- Fix: ' + issue.fix.description);
|
|
432
|
+
if (issue.fix.snippet) {
|
|
433
|
+
lines.push('', '\`\`\`' + (issue.fix.lang || 'svelte'), issue.fix.snippet, '\`\`\`');
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (issue.docsUrl) lines.push('- Docs: ' + issue.docsUrl);
|
|
437
|
+
lines.push(
|
|
438
|
+
'',
|
|
439
|
+
'After fixing, re-run \`svelte-vitals --diff\` (or revisit this route) to confirm ' +
|
|
440
|
+
issue.id +
|
|
441
|
+
' passes' +
|
|
442
|
+
(route ? ' for ' + route : '') +
|
|
443
|
+
'.'
|
|
444
|
+
);
|
|
445
|
+
return lines.join('\\n');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function copyToClipboard(text, btn) {
|
|
449
|
+
var original = 'Copy';
|
|
450
|
+
function reset(label) {
|
|
451
|
+
btn.textContent = label;
|
|
452
|
+
setTimeout(function () { btn.textContent = original; }, 1500);
|
|
453
|
+
}
|
|
454
|
+
function done() { reset('Copied!'); }
|
|
455
|
+
function fail() { reset('Copy failed'); }
|
|
456
|
+
function fallbackCopy() {
|
|
457
|
+
var ta = document.createElement('textarea');
|
|
458
|
+
ta.value = text;
|
|
459
|
+
ta.setAttribute('readonly', '');
|
|
460
|
+
ta.style.position = 'fixed';
|
|
461
|
+
ta.style.opacity = '0';
|
|
462
|
+
document.body.appendChild(ta);
|
|
463
|
+
ta.select();
|
|
464
|
+
var ok = false;
|
|
465
|
+
try { ok = document.execCommand('copy'); } catch (e) {}
|
|
466
|
+
document.body.removeChild(ta);
|
|
467
|
+
return ok;
|
|
468
|
+
}
|
|
469
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
470
|
+
navigator.clipboard.writeText(text).then(done, function () { fallbackCopy() ? done() : fail(); });
|
|
471
|
+
} else {
|
|
472
|
+
fallbackCopy() ? done() : fail();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function renderAiPrompt(issue, route) {
|
|
477
|
+
var text = buildAiPrompt(issue, route);
|
|
478
|
+
var btn = h('button', { type: 'button', class: 'dv-ai-copy-btn', text: 'Copy' }, []);
|
|
479
|
+
btn.addEventListener('click', function () { copyToClipboard(text, btn); });
|
|
480
|
+
return h('details', { class: 'dv-ai-prompt' }, [
|
|
481
|
+
h('summary', { text: 'AI Prompt' }, []),
|
|
482
|
+
h('div', { class: 'dv-ai-prompt-body' }, [
|
|
483
|
+
h('pre', { class: 'dv-ai-prompt-pre', text: text }, []),
|
|
484
|
+
btn
|
|
485
|
+
])
|
|
486
|
+
]);
|
|
487
|
+
}
|
|
488
|
+
|
|
409
489
|
var state = {
|
|
410
490
|
snapshot: null,
|
|
411
491
|
selected: 'overview',
|
|
@@ -593,7 +673,7 @@ var DASHBOARD_SCRIPT = `
|
|
|
593
673
|
|
|
594
674
|
var SEVERITY_ORDER = { critical: 0, warning: 1, info: 2 };
|
|
595
675
|
|
|
596
|
-
function renderFinding(issue, route) {
|
|
676
|
+
function renderFinding(issue, route, promptRoute) {
|
|
597
677
|
var kids = [
|
|
598
678
|
h('div', { class: 'dv-f-head' }, [
|
|
599
679
|
h('span', { class: 'dv-ruleid', text: issue.id }, []),
|
|
@@ -616,6 +696,7 @@ var DASHBOARD_SCRIPT = `
|
|
|
616
696
|
if (issue.docsUrl) {
|
|
617
697
|
kids.push(h('a', { class: 'dv-f-link', href: issue.docsUrl, text: 'Learn more' }, []));
|
|
618
698
|
}
|
|
699
|
+
kids.push(renderAiPrompt(issue, promptRoute !== undefined ? promptRoute : route));
|
|
619
700
|
return h('article', { class: 'dv-finding dv-finding-' + issue.severity }, kids);
|
|
620
701
|
}
|
|
621
702
|
|
|
@@ -690,7 +771,7 @@ var DASHBOARD_SCRIPT = `
|
|
|
690
771
|
var chips = renderFilterChips(state.snapshot.report.categories);
|
|
691
772
|
var findings = route.issues.filter(passesFilter);
|
|
692
773
|
var body = findings.length
|
|
693
|
-
? findings.map(function (issue) { return renderFinding(issue); })
|
|
774
|
+
? findings.map(function (issue) { return renderFinding(issue, undefined, route.route); })
|
|
694
775
|
: [h('p', { class: 'dv-empty', text: 'No issues match the current filter.' }, [])];
|
|
695
776
|
return h('div', { class: 'dv-route-detail' }, [header, chips].concat(body));
|
|
696
777
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svelte-vitals/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.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.0",
|
|
44
44
|
"tinyglobby": "^0.2.17",
|
|
45
|
-
"
|
|
46
|
-
"svelte-vitals": "0.
|
|
45
|
+
"svelte-vitals": "0.27.0",
|
|
46
|
+
"@svelte-vitals/core": "0.24.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@sveltejs/kit": "^2.69.2",
|