svelte-vitals 0.30.0 → 0.31.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 +3 -3
- package/dist/bin.js +5 -5
- package/dist/{chunk-QBXO46PU.js → chunk-3YO2A3YF.js} +80 -54
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -33,16 +33,16 @@ Architecture Score: 100/100 (route avg 100)
|
|
|
33
33
|
|
|
34
34
|
Critical (2)
|
|
35
35
|
────────────────────────
|
|
36
|
-
✗
|
|
36
|
+
✗ seo/title-presence Missing <title>
|
|
37
37
|
/
|
|
38
38
|
src/routes/+page.svelte
|
|
39
|
-
✗
|
|
39
|
+
✗ seo/description-presence Missing <meta name="description">
|
|
40
40
|
/
|
|
41
41
|
src/routes/+page.svelte
|
|
42
42
|
|
|
43
43
|
Warnings (10)
|
|
44
44
|
────────────────────────
|
|
45
|
-
✗
|
|
45
|
+
✗ seo/canonical-url Missing <link rel="canonical">
|
|
46
46
|
/
|
|
47
47
|
src/routes/+page.svelte
|
|
48
48
|
…and 1 more
|
package/dist/bin.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
readCoreVersion,
|
|
10
10
|
readPackageVersion,
|
|
11
11
|
run
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3YO2A3YF.js";
|
|
13
13
|
|
|
14
14
|
// src/bin.ts
|
|
15
15
|
import mri3 from "mri";
|
|
@@ -505,7 +505,7 @@ without a judgment call of its own.
|
|
|
505
505
|
none today, by design), no code edits, no commits, no formatters, no
|
|
506
506
|
dependency installs. Run svelte-vitals read-only, for evidence only.
|
|
507
507
|
3. **Plans must be fully self-contained.** The executor has zero context
|
|
508
|
-
from this conversation. Never write "fix it like
|
|
508
|
+
from this conversation. Never write "fix it like seo/title-presence above" \u2014 inline
|
|
509
509
|
the exact file, line, current code, and the exact fix (svelte-vitals'
|
|
510
510
|
\`fix.snippet\`/\`fix.description\` for the rule, quoted verbatim \u2014 see
|
|
511
511
|
below).
|
|
@@ -789,7 +789,7 @@ function buildConfigFileTemplate(opts = {}) {
|
|
|
789
789
|
const header = "// svelte-vitals config file \u2014 https://oekazuma.github.io/svelte-vitals/guides/configuration/\n";
|
|
790
790
|
const options = ` // treatDynamicAs: 'pass', // 'pass' | 'warn' | 'fail' \u2014 how {data.title}-style dynamic values are scored
|
|
791
791
|
// metaComponents: ['Seo'], // component names that resolve SEO tags into <head>
|
|
792
|
-
// rules: {}, // e.g. {
|
|
792
|
+
// rules: {}, // e.g. { 'seo/title-presence': 'off' } to disable a rule
|
|
793
793
|
// failOn: 'critical', // 'critical' | 'warning' | 'info'
|
|
794
794
|
// weights: {} // e.g. { seo: 2 } \u2014 per-category weight for the combined Health score`;
|
|
795
795
|
if (opts.useDefineConfig) {
|
|
@@ -998,8 +998,8 @@ function readInstalledViteVersion(io) {
|
|
|
998
998
|
}
|
|
999
999
|
|
|
1000
1000
|
// src/ci/action-pin.generated.ts
|
|
1001
|
-
var ACTION_SHA = "
|
|
1002
|
-
var ACTION_VERSION = "0.3.
|
|
1001
|
+
var ACTION_SHA = "4625e1a6266d99282463c8882bbd600b14123d92";
|
|
1002
|
+
var ACTION_VERSION = "0.3.6";
|
|
1003
1003
|
|
|
1004
1004
|
// src/install/index.ts
|
|
1005
1005
|
function detectPackageManagerNear(io, appDir) {
|
|
@@ -53,7 +53,8 @@ import { defaultConfig } from "@svelte-vitals/core";
|
|
|
53
53
|
// src/providers/source/project.ts
|
|
54
54
|
import {
|
|
55
55
|
ROBOTS_SOURCE_PATHS,
|
|
56
|
-
SITEMAP_SOURCE_PATHS
|
|
56
|
+
SITEMAP_SOURCE_PATHS,
|
|
57
|
+
findMinifyDisabled
|
|
57
58
|
} from "@svelte-vitals/core";
|
|
58
59
|
var ProjectError = class extends Error {
|
|
59
60
|
constructor(message) {
|
|
@@ -110,18 +111,39 @@ async function robotsRefsSitemap(rt, cwd) {
|
|
|
110
111
|
return void 0;
|
|
111
112
|
}
|
|
112
113
|
}
|
|
114
|
+
var VITE_CONFIG_FILES = [
|
|
115
|
+
"vite.config.js",
|
|
116
|
+
"vite.config.mjs",
|
|
117
|
+
"vite.config.ts",
|
|
118
|
+
"vite.config.cjs",
|
|
119
|
+
"vite.config.mts",
|
|
120
|
+
"vite.config.cts"
|
|
121
|
+
];
|
|
122
|
+
async function detectViteMinifyDisabled(rt, cwd) {
|
|
123
|
+
const exists = await Promise.all(VITE_CONFIG_FILES.map((f) => rt.exists(rt.join(cwd, f))));
|
|
124
|
+
const file = VITE_CONFIG_FILES[exists.indexOf(true)];
|
|
125
|
+
if (!file) return void 0;
|
|
126
|
+
try {
|
|
127
|
+
const hit = findMinifyDisabled(await rt.readFile(rt.join(cwd, file)));
|
|
128
|
+
return hit ? { file, line: hit.line } : void 0;
|
|
129
|
+
} catch {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
113
133
|
async function collectProjectFacts(rt, cwd) {
|
|
114
|
-
const [hasRobotsTxt, hasSitemap, htmlLang] = await Promise.all([
|
|
134
|
+
const [hasRobotsTxt, hasSitemap, htmlLang, viteMinifyDisabled] = await Promise.all([
|
|
115
135
|
existsAny(rt, cwd, ROBOTS_SOURCE_PATHS),
|
|
116
136
|
existsAny(rt, cwd, SITEMAP_SOURCE_PATHS),
|
|
117
|
-
detectAppHtmlLang(rt, cwd)
|
|
137
|
+
detectAppHtmlLang(rt, cwd),
|
|
138
|
+
detectViteMinifyDisabled(rt, cwd)
|
|
118
139
|
]);
|
|
119
140
|
const robotsReferencesSitemap = await robotsRefsSitemap(rt, cwd);
|
|
120
141
|
return {
|
|
121
142
|
hasRobotsTxt,
|
|
122
143
|
hasSitemap,
|
|
123
144
|
htmlLang,
|
|
124
|
-
...robotsReferencesSitemap !== void 0 ? { robotsReferencesSitemap } : {}
|
|
145
|
+
...robotsReferencesSitemap !== void 0 ? { robotsReferencesSitemap } : {},
|
|
146
|
+
...viteMinifyDisabled ? { viteMinifyDisabled } : {}
|
|
125
147
|
};
|
|
126
148
|
}
|
|
127
149
|
|
|
@@ -139,16 +161,16 @@ function exprValue(node) {
|
|
|
139
161
|
}
|
|
140
162
|
function resolveMetaObject(attr, keyMap) {
|
|
141
163
|
if (!attr) return { tags: [], opaque: false };
|
|
142
|
-
const expr = attr.value
|
|
164
|
+
const expr = attr.value !== true && !Array.isArray(attr.value) ? attr.value.expression : void 0;
|
|
143
165
|
if (!expr || expr.type !== "ObjectExpression") return { tags: [], opaque: true };
|
|
144
166
|
const tags = [];
|
|
145
167
|
let opaque = false;
|
|
146
|
-
for (const prop of expr.properties
|
|
147
|
-
if (prop
|
|
168
|
+
for (const prop of expr.properties) {
|
|
169
|
+
if (prop.type !== "Property" || prop.computed) {
|
|
148
170
|
opaque = true;
|
|
149
171
|
continue;
|
|
150
172
|
}
|
|
151
|
-
const key = prop.key
|
|
173
|
+
const key = prop.key.type === "Identifier" ? prop.key.name : prop.key.type === "Literal" ? prop.key.value : void 0;
|
|
152
174
|
const make = typeof key === "string" ? keyMap[key] : void 0;
|
|
153
175
|
if (make) tags.push(make(exprValue(prop.value)));
|
|
154
176
|
}
|
|
@@ -168,7 +190,7 @@ var TWITTER_KEYS = {
|
|
|
168
190
|
|
|
169
191
|
// src/providers/source/adapters/svelte-meta-tags.ts
|
|
170
192
|
function findAttr(attributes, name) {
|
|
171
|
-
return attributes.find((a) => a
|
|
193
|
+
return attributes.find((a) => a.type === "Attribute" && a.name === name);
|
|
172
194
|
}
|
|
173
195
|
var svelteMetaTagsAdapter = {
|
|
174
196
|
match(info) {
|
|
@@ -221,7 +243,7 @@ var svelteMetaTagsJsonLdAdapter = {
|
|
|
221
243
|
// src/providers/source/adapters/svelte-seo.ts
|
|
222
244
|
import { attrValueOf as attrValueOf2, attrTextOf as attrTextOf2 } from "@svelte-vitals/core";
|
|
223
245
|
function findAttr2(attributes, name) {
|
|
224
|
-
return attributes.find((a) => a
|
|
246
|
+
return attributes.find((a) => a.type === "Attribute" && a.name === name);
|
|
225
247
|
}
|
|
226
248
|
var svelteSeoAdapter = {
|
|
227
249
|
match(info) {
|
|
@@ -273,28 +295,31 @@ import {
|
|
|
273
295
|
// src/providers/source/imports.ts
|
|
274
296
|
function addImportsFromProgram(program, map) {
|
|
275
297
|
for (const node of program?.body ?? []) {
|
|
276
|
-
if (node
|
|
277
|
-
const source = String(node.source
|
|
278
|
-
for (const spec of node.specifiers
|
|
279
|
-
const local = spec
|
|
298
|
+
if (node.type !== "ImportDeclaration") continue;
|
|
299
|
+
const source = String(node.source.value ?? "");
|
|
300
|
+
for (const spec of node.specifiers) {
|
|
301
|
+
const local = spec.local?.name;
|
|
280
302
|
if (!local) continue;
|
|
281
303
|
if (spec.type === "ImportDefaultSpecifier") {
|
|
282
304
|
map.set(local, { source, imported: "default" });
|
|
283
305
|
} else if (spec.type === "ImportSpecifier") {
|
|
284
|
-
|
|
306
|
+
const imported = spec.imported.type === "Identifier" ? spec.imported.name : spec.imported.value;
|
|
307
|
+
map.set(local, { source, imported: typeof imported === "string" ? imported : local });
|
|
285
308
|
}
|
|
286
309
|
}
|
|
287
310
|
}
|
|
288
311
|
}
|
|
289
312
|
function collectImports(ast) {
|
|
290
|
-
const root = ast;
|
|
291
313
|
const map = /* @__PURE__ */ new Map();
|
|
292
|
-
addImportsFromProgram(
|
|
293
|
-
addImportsFromProgram(
|
|
314
|
+
addImportsFromProgram(ast.instance?.content, map);
|
|
315
|
+
addImportsFromProgram(ast.module?.content, map);
|
|
294
316
|
return map;
|
|
295
317
|
}
|
|
296
318
|
|
|
297
319
|
// src/providers/source/parse.ts
|
|
320
|
+
function childOf(node, key) {
|
|
321
|
+
return node[key];
|
|
322
|
+
}
|
|
298
323
|
function collectSvelteHeads(node, acc) {
|
|
299
324
|
if (Array.isArray(node)) {
|
|
300
325
|
for (const child of node) collectSvelteHeads(child, acc);
|
|
@@ -303,32 +328,33 @@ function collectSvelteHeads(node, acc) {
|
|
|
303
328
|
if (!node || typeof node !== "object") return;
|
|
304
329
|
if (node.type === "SvelteHead") acc.push(node);
|
|
305
330
|
for (const key of CHILD_NODE_KEYS) {
|
|
306
|
-
if (key in node) collectSvelteHeads(node
|
|
331
|
+
if (key in node) collectSvelteHeads(childOf(node, key), acc);
|
|
307
332
|
}
|
|
308
333
|
}
|
|
309
334
|
function tagsFromHead(head) {
|
|
310
335
|
const tags = [];
|
|
311
|
-
const children = head
|
|
336
|
+
const children = head.fragment.nodes;
|
|
312
337
|
for (const node of children) {
|
|
313
|
-
if (node
|
|
314
|
-
const titleNodes = node.fragment
|
|
338
|
+
if (node.type === "TitleElement") {
|
|
339
|
+
const titleNodes = node.fragment.nodes;
|
|
315
340
|
const text = textFromNodes(titleNodes);
|
|
316
341
|
tags.push({ kind: "title", value: valueFromNodes(titleNodes), ...text !== void 0 ? { text } : {} });
|
|
317
342
|
continue;
|
|
318
343
|
}
|
|
319
|
-
if (node
|
|
344
|
+
if (node.type !== "RegularElement") continue;
|
|
345
|
+
const attributes = node.attributes;
|
|
320
346
|
if (node.name === "meta") {
|
|
321
|
-
const charset = attrValue(
|
|
347
|
+
const charset = attrValue(attributes, "charset");
|
|
322
348
|
if (charset !== "absent") {
|
|
323
349
|
tags.push({ kind: "meta", name: "charset", value: charset });
|
|
324
350
|
continue;
|
|
325
351
|
}
|
|
326
|
-
const name = attrText(
|
|
327
|
-
const property = attrText(
|
|
328
|
-
const content = name === "robots" ? attrText(
|
|
352
|
+
const name = attrText(attributes, "name");
|
|
353
|
+
const property = attrText(attributes, "property");
|
|
354
|
+
const content = name === "robots" ? attrText(attributes, "content") : void 0;
|
|
329
355
|
const noindex = content !== void 0 && /(^|[\s,])(noindex|none)([\s,]|$)/i.test(content);
|
|
330
|
-
const contentValue = attrValue(
|
|
331
|
-
const descText = name === "description" && contentValue === "static" ? attrText(
|
|
356
|
+
const contentValue = attrValue(attributes, "content");
|
|
357
|
+
const descText = name === "description" && contentValue === "static" ? attrText(attributes, "content") : void 0;
|
|
332
358
|
tags.push({
|
|
333
359
|
kind: "meta",
|
|
334
360
|
...name ? { name } : {},
|
|
@@ -338,33 +364,33 @@ function tagsFromHead(head) {
|
|
|
338
364
|
...descText !== void 0 ? { text: descText } : {}
|
|
339
365
|
});
|
|
340
366
|
} else if (node.name === "link") {
|
|
341
|
-
const rel = attrText(
|
|
342
|
-
const hasAs = findAttr3(
|
|
343
|
-
const asLiteral = attrText(
|
|
344
|
-
const hasCrossorigin = findAttr3(
|
|
345
|
-
const hreflang = attrText(
|
|
346
|
-
const href = attrText(
|
|
367
|
+
const rel = attrText(attributes, "rel");
|
|
368
|
+
const hasAs = findAttr3(attributes, "as") !== void 0;
|
|
369
|
+
const asLiteral = attrText(attributes, "as");
|
|
370
|
+
const hasCrossorigin = findAttr3(attributes, "crossorigin") !== void 0;
|
|
371
|
+
const hreflang = attrText(attributes, "hreflang");
|
|
372
|
+
const href = attrText(attributes, "href");
|
|
347
373
|
tags.push({
|
|
348
374
|
kind: "link",
|
|
349
375
|
...rel ? { rel } : {},
|
|
350
|
-
value: attrValue(
|
|
376
|
+
value: attrValue(attributes, "href"),
|
|
351
377
|
...hasAs ? { hasAs: true } : {},
|
|
352
378
|
...asLiteral ? { as: asLiteral } : {},
|
|
353
379
|
...hasCrossorigin ? { hasCrossorigin: true } : {},
|
|
354
|
-
// Keep a literal empty hreflang="" (present-but-invalid) so
|
|
380
|
+
// Keep a literal empty hreflang="" (present-but-invalid) so seo/hreflang can flag it.
|
|
355
381
|
...hreflang !== void 0 ? { hreflang } : {},
|
|
356
382
|
...href ? { href } : {}
|
|
357
383
|
});
|
|
358
384
|
} else if (node.name === "script") {
|
|
359
|
-
const type = attrText(
|
|
385
|
+
const type = attrText(attributes, "type");
|
|
360
386
|
if (type === "application/ld+json") {
|
|
361
|
-
const nodes = node.fragment
|
|
387
|
+
const nodes = node.fragment.nodes;
|
|
362
388
|
const raw = textFromNodes(nodes);
|
|
363
389
|
tags.push({ kind: "jsonld", value: valueFromNodes(nodes), ...raw !== void 0 ? { jsonld: raw } : {} });
|
|
364
390
|
} else {
|
|
365
|
-
const src = attrText(
|
|
391
|
+
const src = attrText(attributes, "src");
|
|
366
392
|
if (src) {
|
|
367
|
-
const blocking = findAttr3(
|
|
393
|
+
const blocking = findAttr3(attributes, "defer") === void 0 && findAttr3(attributes, "async") === void 0 && type !== "module";
|
|
368
394
|
tags.push({ kind: "script", value: "static", href: src, ...blocking ? { blocking: true } : {} });
|
|
369
395
|
}
|
|
370
396
|
}
|
|
@@ -378,16 +404,16 @@ function collectComponents(node, acc) {
|
|
|
378
404
|
return;
|
|
379
405
|
}
|
|
380
406
|
if (!node || typeof node !== "object") return;
|
|
381
|
-
if (node.type === "Component"
|
|
382
|
-
const attributes = node.attributes
|
|
407
|
+
if (node.type === "Component") {
|
|
408
|
+
const attributes = node.attributes;
|
|
383
409
|
acc.push({
|
|
384
410
|
name: node.name,
|
|
385
411
|
attributes,
|
|
386
|
-
hasSpread: attributes.some((a) => a
|
|
412
|
+
hasSpread: attributes.some((a) => a.type === "SpreadAttribute")
|
|
387
413
|
});
|
|
388
414
|
}
|
|
389
415
|
for (const key of CHILD_NODE_KEYS) {
|
|
390
|
-
if (key in node) collectComponents(node
|
|
416
|
+
if (key in node) collectComponents(childOf(node, key), acc);
|
|
391
417
|
}
|
|
392
418
|
}
|
|
393
419
|
function collectImages(node, source, acc) {
|
|
@@ -397,8 +423,8 @@ function collectImages(node, source, acc) {
|
|
|
397
423
|
}
|
|
398
424
|
if (!node || typeof node !== "object") return;
|
|
399
425
|
if (node.type === "RegularElement" && node.name === "img") {
|
|
400
|
-
const attrs = node.attributes
|
|
401
|
-
const hasSpread =
|
|
426
|
+
const attrs = node.attributes;
|
|
427
|
+
const hasSpread = node.attributes.some((a) => a.type === "SpreadAttribute");
|
|
402
428
|
acc.push({
|
|
403
429
|
hasWidth: hasSpread || Boolean(findAttr3(attrs, "width")),
|
|
404
430
|
hasHeight: hasSpread || Boolean(findAttr3(attrs, "height")),
|
|
@@ -411,7 +437,7 @@ function collectImages(node, source, acc) {
|
|
|
411
437
|
});
|
|
412
438
|
}
|
|
413
439
|
for (const key of CHILD_NODE_KEYS) {
|
|
414
|
-
if (key in node) collectImages(node
|
|
440
|
+
if (key in node) collectImages(childOf(node, key), source, acc);
|
|
415
441
|
}
|
|
416
442
|
}
|
|
417
443
|
function collectHeadings(node, source, acc) {
|
|
@@ -421,23 +447,23 @@ function collectHeadings(node, source, acc) {
|
|
|
421
447
|
}
|
|
422
448
|
if (!node || typeof node !== "object") return;
|
|
423
449
|
if (node.type === "SvelteHead") return;
|
|
424
|
-
if (node.type === "RegularElement" &&
|
|
450
|
+
if (node.type === "RegularElement" && /^h[1-6]$/.test(node.name)) {
|
|
425
451
|
acc.push({ level: Number(node.name[1]), line: lineOf(source, node.start) });
|
|
426
452
|
}
|
|
427
453
|
for (const key of CHILD_NODE_KEYS) {
|
|
428
|
-
if (key in node) collectHeadings(node
|
|
454
|
+
if (key in node) collectHeadings(childOf(node, key), source, acc);
|
|
429
455
|
}
|
|
430
456
|
}
|
|
431
457
|
function parseFile(source, filename) {
|
|
432
458
|
const ast = parse(source, { modern: true, filename });
|
|
433
459
|
const heads = [];
|
|
434
|
-
collectSvelteHeads(ast.fragment
|
|
460
|
+
collectSvelteHeads(ast.fragment, heads);
|
|
435
461
|
const components = [];
|
|
436
|
-
collectComponents(ast.fragment
|
|
462
|
+
collectComponents(ast.fragment, components);
|
|
437
463
|
const images = [];
|
|
438
|
-
collectImages(ast.fragment
|
|
464
|
+
collectImages(ast.fragment, source, images);
|
|
439
465
|
const headings = [];
|
|
440
|
-
collectHeadings(ast.fragment
|
|
466
|
+
collectHeadings(ast.fragment, source, headings);
|
|
441
467
|
return {
|
|
442
468
|
headTags: heads.flatMap(tagsFromHead),
|
|
443
469
|
components,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HeadTag, RuleSetting, Config, Severity, Category, Result } from '@svelte-vitals/core';
|
|
2
2
|
export { defineConfig } from '@svelte-vitals/core';
|
|
3
|
+
import { AST } from 'svelte/compiler';
|
|
3
4
|
|
|
4
5
|
/** A resolved import binding: which module, and which export ('default' for default imports). */
|
|
5
6
|
interface ImportInfo {
|
|
@@ -11,10 +12,9 @@ type ImportMap = Map<string, ImportInfo>;
|
|
|
11
12
|
|
|
12
13
|
/** A head tag parsed from one file, before layout-chain presence is assigned. */
|
|
13
14
|
type ParsedTag = Omit<HeadTag, 'presence' | 'file'>;
|
|
14
|
-
type Node = any;
|
|
15
15
|
interface ComponentUse {
|
|
16
16
|
name: string;
|
|
17
|
-
attributes:
|
|
17
|
+
attributes: AST.Component['attributes'];
|
|
18
18
|
hasSpread: boolean;
|
|
19
19
|
}
|
|
20
20
|
interface ParsedImage {
|
|
@@ -27,7 +27,7 @@ interface ParsedImage {
|
|
|
27
27
|
/** 1-based source line, or 0 if unknown. */
|
|
28
28
|
line: number;
|
|
29
29
|
}
|
|
30
|
-
/** A page-body heading (<h1>–<h6>) parsed from one file (
|
|
30
|
+
/** A page-body heading (<h1>–<h6>) parsed from one file (seo/single-h1). */
|
|
31
31
|
interface ParsedHeading {
|
|
32
32
|
/** Heading level 1–6. */
|
|
33
33
|
level: number;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-vitals",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "A SvelteKit SEO checker — not a runtime Web Vitals reporter. Static analysis of your routes' head metadata.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,11 +44,12 @@
|
|
|
44
44
|
"magicast": "^0.5.3",
|
|
45
45
|
"mri": "^1.2.0",
|
|
46
46
|
"smol-toml": "^1.7.0",
|
|
47
|
-
"svelte": "^5.56.
|
|
47
|
+
"svelte": "^5.56.6",
|
|
48
48
|
"tinyglobby": "^0.2.17",
|
|
49
|
-
"@svelte-vitals/core": "0.
|
|
49
|
+
"@svelte-vitals/core": "0.28.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
+
"@types/estree": "^1.0.9",
|
|
52
53
|
"@types/node": "^24.13.3"
|
|
53
54
|
},
|
|
54
55
|
"scripts": {
|