svelte-vitals 0.54.7 → 0.55.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/{analyze-D5CKrnVf.js → analyze-HCxZ89Gm.js} +1 -1
- package/dist/bin.js +6 -6
- package/dist/{ci-CVMFzrRD.js → ci-BsCX5NZs.js} +1 -1
- package/dist/{complete-DJIjQlEC.js → complete-CU5WZYZT.js} +6 -6
- package/dist/{docs-CfxdUEEe.js → docs-C9bKlGnX.js} +2 -2
- package/dist/{explain-D9Cc6k2G.js → explain-DxY_9zU0.js} +2 -2
- package/dist/gunshi-registry.js +2 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -1
- package/dist/{install-BIpFmwLJ.js → install-71cr0Vpl.js} +2 -2
- package/dist/{src-Oo1FLd1x.js → src-BUwLRzL0.js} +73 -16
- package/package.json +9 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as readCoreVersion, c as findUnknownRuleIds, g as isReporterName, i as run, l as knownRuleIds, v as readPackageVersion } from "./src-
|
|
1
|
+
import { _ as readCoreVersion, c as findUnknownRuleIds, g as isReporterName, i as run, l as knownRuleIds, v as readPackageVersion } from "./src-BUwLRzL0.js";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { terminalSafe } from "@svelte-vitals/core/internal";
|
package/dist/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { g as realIO, i as resolveLocale, m as consoleIO, n as runAnalyzeCliGunshi } from "./analyze-
|
|
2
|
+
import { g as realIO, i as resolveLocale, m as consoleIO, n as runAnalyzeCliGunshi } from "./analyze-HCxZ89Gm.js";
|
|
3
3
|
import { terminalSafe } from "@svelte-vitals/core/internal";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
/**
|
|
@@ -17,35 +17,35 @@ async function runCli(argv, io = consoleIO, env = process.env) {
|
|
|
17
17
|
try {
|
|
18
18
|
const locale = resolveLocale(env);
|
|
19
19
|
if (argv[0] === "complete") {
|
|
20
|
-
const { runCompleteCliGunshi } = await import("./complete-
|
|
20
|
+
const { runCompleteCliGunshi } = await import("./complete-CU5WZYZT.js");
|
|
21
21
|
return {
|
|
22
22
|
code: await runCompleteCliGunshi(argv, io),
|
|
23
23
|
exit: "natural"
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
if (argv[0] === "docs") {
|
|
27
|
-
const { runDocsCliGunshi } = await import("./docs-
|
|
27
|
+
const { runDocsCliGunshi } = await import("./docs-C9bKlGnX.js");
|
|
28
28
|
return {
|
|
29
29
|
code: await runDocsCliGunshi(argv.slice(1), io, locale),
|
|
30
30
|
exit: "natural"
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
if (argv[0] === "explain") {
|
|
34
|
-
const { runExplainCliGunshi } = await import("./explain-
|
|
34
|
+
const { runExplainCliGunshi } = await import("./explain-DxY_9zU0.js");
|
|
35
35
|
return {
|
|
36
36
|
code: await runExplainCliGunshi(argv.slice(1), io, locale),
|
|
37
37
|
exit: "natural"
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
if (argv[0] === "install") {
|
|
41
|
-
const { runInstallCliGunshi } = await import("./install-
|
|
41
|
+
const { runInstallCliGunshi } = await import("./install-71cr0Vpl.js").then((n) => n.n);
|
|
42
42
|
return {
|
|
43
43
|
code: await runInstallCliGunshi(argv.slice(1), io, locale),
|
|
44
44
|
exit: "immediate"
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
if (argv[0] === "ci") {
|
|
48
|
-
const { runCiCliGunshi } = await import("./ci-
|
|
48
|
+
const { runCiCliGunshi } = await import("./ci-BsCX5NZs.js");
|
|
49
49
|
return {
|
|
50
50
|
code: await runCiCliGunshi(argv.slice(1), {
|
|
51
51
|
...realIO(),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as guardArgs, c as stripUnknownFlags, g as realIO, l as suggestClosest, o as splitAtTerminator, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-
|
|
1
|
+
import { a as guardArgs, c as stripUnknownFlags, g as realIO, l as suggestClosest, o as splitAtTerminator, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-HCxZ89Gm.js";
|
|
2
2
|
import { a as planWorkflowWrite, i as buildWorkflowYaml, n as ACTION_VERSION, r as WORKFLOW_PATH, t as ACTION_SHA } from "./action-pin.generated-BkwgIAMh.js";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { cli } from "gunshi/bone";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { h as REPORTER_NAMES } from "./src-
|
|
2
|
-
import { d as FAIL_ON_VALUES, f as TREAT_DYNAMIC_AS_VALUES, m as consoleIO, t as ROOT_ARGS, u as CATEGORIES } from "./analyze-
|
|
3
|
-
import { t as INSTALL_ARGS } from "./install-
|
|
4
|
-
import { CI_ARGS, CI_UPGRADE_ARGS } from "./ci-
|
|
5
|
-
import { DOCS_LIST_ARGS, DOCS_ROOT_ARGS, DOCS_SHOW_ARGS } from "./docs-
|
|
6
|
-
import { EXPLAIN_ARGS } from "./explain-
|
|
1
|
+
import { h as REPORTER_NAMES } from "./src-BUwLRzL0.js";
|
|
2
|
+
import { d as FAIL_ON_VALUES, f as TREAT_DYNAMIC_AS_VALUES, m as consoleIO, t as ROOT_ARGS, u as CATEGORIES } from "./analyze-HCxZ89Gm.js";
|
|
3
|
+
import { t as INSTALL_ARGS } from "./install-71cr0Vpl.js";
|
|
4
|
+
import { CI_ARGS, CI_UPGRADE_ARGS } from "./ci-BsCX5NZs.js";
|
|
5
|
+
import { DOCS_LIST_ARGS, DOCS_ROOT_ARGS, DOCS_SHOW_ARGS } from "./docs-C9bKlGnX.js";
|
|
6
|
+
import { EXPLAIN_ARGS } from "./explain-DxY_9zU0.js";
|
|
7
7
|
import { cli } from "gunshi/bone";
|
|
8
8
|
import { define } from "gunshi/definition";
|
|
9
9
|
import { kebabnize } from "gunshi/utils";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as knownRuleIds } from "./src-
|
|
2
|
-
import { a as guardArgs, c as stripUnknownFlags, l as suggestClosest, m as consoleIO, o as splitAtTerminator, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-
|
|
1
|
+
import { l as knownRuleIds } from "./src-BUwLRzL0.js";
|
|
2
|
+
import { a as guardArgs, c as stripUnknownFlags, l as suggestClosest, m as consoleIO, o as splitAtTerminator, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-HCxZ89Gm.js";
|
|
3
3
|
import { docsUrlFor } from "@svelte-vitals/core/internal";
|
|
4
4
|
import { cli } from "gunshi/bone";
|
|
5
5
|
import { define } from "gunshi/definition";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as knownRuleIds } from "./src-
|
|
2
|
-
import { a as guardArgs, c as stripUnknownFlags, l as suggestClosest, m as consoleIO, o as splitAtTerminator, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-
|
|
1
|
+
import { l as knownRuleIds } from "./src-BUwLRzL0.js";
|
|
2
|
+
import { a as guardArgs, c as stripUnknownFlags, l as suggestClosest, m as consoleIO, o as splitAtTerminator, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-HCxZ89Gm.js";
|
|
3
3
|
import { CATEGORIES } from "@svelte-vitals/core";
|
|
4
4
|
import { allRules, explainRule } from "@svelte-vitals/core/internal";
|
|
5
5
|
import { cli } from "gunshi/bone";
|
package/dist/gunshi-registry.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ROOT_ARGS } from "./analyze-
|
|
2
|
-
import { t as INSTALL_ARGS } from "./install-
|
|
1
|
+
import { t as ROOT_ARGS } from "./analyze-HCxZ89Gm.js";
|
|
2
|
+
import { t as INSTALL_ARGS } from "./install-71cr0Vpl.js";
|
|
3
3
|
import { t as JA_ARG_DESCRIPTIONS } from "./ja-BDLP3KLG.js";
|
|
4
4
|
export { INSTALL_ARGS, JA_ARG_DESCRIPTIONS, ROOT_ARGS };
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,8 @@ interface ParsedFile {
|
|
|
71
71
|
imports: ImportMap;
|
|
72
72
|
images: ParsedImage[];
|
|
73
73
|
headings: ParsedHeading[];
|
|
74
|
+
/** This file has a `<svelte:element>` that may render a heading of an undetermined level. */
|
|
75
|
+
dynamicHeading: boolean;
|
|
74
76
|
a11y: ParsedA11y;
|
|
75
77
|
/** Inline `svelte-vitals-disable-next-line` directives in this file, for the central
|
|
76
78
|
* suppression pass. Collected here because a route-scoped finding can be located in any file
|
|
@@ -317,6 +319,8 @@ export interface AnalyzeOptions {
|
|
|
317
319
|
allowRules?: string[];
|
|
318
320
|
/** Per-category weights for the combined Health score (flag > config file > default 1 each). */
|
|
319
321
|
weights?: Partial<Record<Category, number>>;
|
|
322
|
+
/** SEO-wide switches (config-file field; no CLI flag). `indexable: false` turns off the search-result rules. */
|
|
323
|
+
seo?: Config['seo'];
|
|
320
324
|
/** Restrict analysis to rules in these categories (applied after rules/ignore selection). */
|
|
321
325
|
categories?: Category[];
|
|
322
326
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as ProjectError, S as routeMatcher, a as spinnerEnabled, c as findUnknownRuleIds, d as ruleOptionsSpec, f as SUPPRESSIONS_FILE, i as run, l as knownRuleIds, m as loadSuppressions, n as applyScope, o as CONFIG_FILENAMES, p as applySuppressions, r as defineConfig, s as loadConfigFile, t as analyzeProject, u as registryTag, w as createNodeRuntime } from "./src-
|
|
1
|
+
import { C as ProjectError, S as routeMatcher, a as spinnerEnabled, c as findUnknownRuleIds, d as ruleOptionsSpec, f as SUPPRESSIONS_FILE, i as run, l as knownRuleIds, m as loadSuppressions, n as applyScope, o as CONFIG_FILENAMES, p as applySuppressions, r as defineConfig, s as loadConfigFile, t as analyzeProject, u as registryTag, w as createNodeRuntime } from "./src-BUwLRzL0.js";
|
|
2
2
|
export { CONFIG_FILENAMES, ProjectError, SUPPRESSIONS_FILE, analyzeProject, applyScope, applySuppressions, createNodeRuntime, defineConfig, findUnknownRuleIds, knownRuleIds, loadConfigFile, loadSuppressions, registryTag, routeMatcher, ruleOptionsSpec, run, spinnerEnabled };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { b as hasDep, o as CONFIG_FILENAMES, v as readPackageVersion, x as readPkg, y as discoverApps } from "./src-
|
|
3
|
-
import { a as guardArgs, c as stripUnknownFlags, g as realIO, h as clackPrompts, m as consoleIO, o as splitAtTerminator, p as toList, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-
|
|
2
|
+
import { b as hasDep, o as CONFIG_FILENAMES, v as readPackageVersion, x as readPkg, y as discoverApps } from "./src-BUwLRzL0.js";
|
|
3
|
+
import { a as guardArgs, c as stripUnknownFlags, g as realIO, h as clackPrompts, m as consoleIO, o as splitAtTerminator, p as toList, r as localizedOptionsSection, s as stripAutoVersionLine } from "./analyze-HCxZ89Gm.js";
|
|
4
4
|
import { a as planWorkflowWrite, i as buildWorkflowYaml, n as ACTION_VERSION, r as WORKFLOW_PATH, t as ACTION_SHA } from "./action-pin.generated-BkwgIAMh.js";
|
|
5
5
|
import { buildCursorRules, installHeader } from "./install/skill-content.js";
|
|
6
6
|
import { join } from "node:path";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { CATEGORIES, defineConfig, defineConfig as defineConfig$1 } from "@svelte-vitals/core";
|
|
4
|
-
import { ANCESTRY_DEPENDENT_TAGS, ASIDE_DEMOTING_TAGS, CHILD_NODE_KEYS, IDREF_ATTRS, NAMING_ATTRS, ROBOTS_SOURCE_PATHS, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, VITE_CONFIG_FILES, addFactsDirectives, allRules, attrText, attrTextOf, attrValue, attrValueOf, collectComponentFacts, collectKitModuleFacts, collectSourceFiles, collectSuppressions, compileOverrides, computeHealth, decodeFragmentId, defaultConfig, docsUrlFor, findAttr, findMinifyDisabled, foldOccurrences, formatAgentReport, formatConsoleReport, formatFailedRuleWarning, formatGithubReport, formatHtmlReport, formatJsonReport, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, isClassicScriptType, isPenalized, isPlainObject, isTopFragment, lineOf, noColorPalette, parseSvelte, resolveKitAliases, resolveKitPathsBase, resolveLandmark, resolveRepoLocalPath, resolveRuleOptions, runAnalysis, scoreColor, selectRules, settingSeverity, shouldSkipRangeCheck, skippedFileWarnings, splitTokens, stripTextDirective, summarize, terminalSafe, textFromNodes, unknownDirectiveIds, validateRuleSetting, valueFromNodes, withReadLimit } from "@svelte-vitals/core/internal";
|
|
4
|
+
import { ANCESTRY_DEPENDENT_TAGS, ASIDE_DEMOTING_TAGS, CHILD_NODE_KEYS, IDREF_ATTRS, NAMING_ATTRS, ROBOTS_SOURCE_PATHS, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, VITE_CONFIG_FILES, addFactsDirectives, allRules, attrText, attrTextOf, attrValue, attrValueOf, collectComponentFacts, collectKitModuleFacts, collectSourceFiles, collectSuppressions, compileOverrides, computeHealth, decodeFragmentId, defaultConfig, docsUrlFor, findAttr, findMinifyDisabled, foldOccurrences, formatAgentReport, formatConsoleReport, formatFailedRuleWarning, formatGithubReport, formatHtmlReport, formatJsonReport, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, isClassicScriptType, isPenalized, isPlainObject, isTopFragment, lineOf, noColorPalette, parseSvelte, resolveKitAliases, resolveKitPathsBase, resolveLandmark, resolveRepoLocalPath, resolveRuleOptions, runAnalysis, scoreColor, selectRules, settingSeverity, shouldSkipRangeCheck, skippedFileWarnings, splitTokens, stripTextDirective, summarize, terminalSafe, textFromNodes, unknownDirectiveIds, validateRuleSetting, valueFromNodes, withIndexableOff, withReadLimit } from "@svelte-vitals/core/internal";
|
|
5
5
|
import { access, glob, readFile, stat } from "node:fs/promises";
|
|
6
6
|
import { getAgentProfile } from "gunshi/agent";
|
|
7
7
|
import { execFileSync } from "node:child_process";
|
|
@@ -714,7 +714,30 @@ function collectImages(node, source, acc) {
|
|
|
714
714
|
}
|
|
715
715
|
for (const key of CHILD_NODE_KEYS) if (key in node) collectImages(childOf(node, key), source, acc);
|
|
716
716
|
}
|
|
717
|
-
/**
|
|
717
|
+
/**
|
|
718
|
+
* The tag names a `<svelte:element this={…}>` can render as, or undefined when the expression
|
|
719
|
+
* is not statically determinable. A string literal gives one name; a conditional whose branches
|
|
720
|
+
* are both literals gives both, so the common `this={cond ? 'h1' : 'span'}` reads as the set it
|
|
721
|
+
* really is rather than as an unknown.
|
|
722
|
+
*/
|
|
723
|
+
function svelteElementTags(tag) {
|
|
724
|
+
if (tag.type === "Literal") return typeof tag.value === "string" ? [tag.value] : void 0;
|
|
725
|
+
if (tag.type === "ConditionalExpression") {
|
|
726
|
+
const branches = [tag.consequent, tag.alternate].map((b) => b.type === "Literal" && typeof b.value === "string" ? b.value : void 0);
|
|
727
|
+
return branches.every((b) => b !== void 0) ? [...new Set(branches)] : void 0;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
const HEADING_TAG = /^h[1-6]$/;
|
|
731
|
+
/** The one heading level a resolved tag set renders as, or undefined (no heading, or two levels). */
|
|
732
|
+
function headingLevelOf(tags) {
|
|
733
|
+
const levels = new Set(tags.map((t) => t.toLowerCase()).filter((t) => HEADING_TAG.test(t)).map((t) => Number(t[1])));
|
|
734
|
+
return levels.size === 1 ? [...levels][0] : void 0;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Recursively collect page-body headings (<h1>–<h6>) anywhere in the template (seo/single-h1).
|
|
738
|
+
* `acc.dynamic` records a `<svelte:element>` that may render a heading but whose level is not
|
|
739
|
+
* statically determinable — a route carrying one cannot be reported as having no <h1>.
|
|
740
|
+
*/
|
|
718
741
|
function collectHeadings(node, source, acc) {
|
|
719
742
|
if (Array.isArray(node)) {
|
|
720
743
|
for (const child of node) collectHeadings(child, source, acc);
|
|
@@ -722,10 +745,19 @@ function collectHeadings(node, source, acc) {
|
|
|
722
745
|
}
|
|
723
746
|
if (!node || typeof node !== "object") return;
|
|
724
747
|
if (node.type === "SvelteHead") return;
|
|
725
|
-
if (node.type === "RegularElement" &&
|
|
748
|
+
if (node.type === "RegularElement" && HEADING_TAG.test(node.name)) acc.headings.push({
|
|
726
749
|
level: Number(node.name[1]),
|
|
727
750
|
line: lineOf(source, node.start)
|
|
728
751
|
});
|
|
752
|
+
else if (node.type === "SvelteElement") {
|
|
753
|
+
const tags = svelteElementTags(node.tag);
|
|
754
|
+
const level = tags ? headingLevelOf(tags) : void 0;
|
|
755
|
+
if (level !== void 0) acc.headings.push({
|
|
756
|
+
level,
|
|
757
|
+
line: lineOf(source, node.start)
|
|
758
|
+
});
|
|
759
|
+
else if (!tags || tags.some((t) => HEADING_TAG.test(t.toLowerCase()))) acc.dynamic = true;
|
|
760
|
+
}
|
|
729
761
|
for (const key of CHILD_NODE_KEYS) if (key in node) collectHeadings(childOf(node, key), source, acc);
|
|
730
762
|
}
|
|
731
763
|
/** An `aria-label`/`aria-labelledby` carrying a name: a non-blank literal, or an expression whose
|
|
@@ -826,11 +858,13 @@ function collectA11y(fragment, source) {
|
|
|
826
858
|
});
|
|
827
859
|
return;
|
|
828
860
|
case "RegularElement":
|
|
829
|
-
case "SvelteElement":
|
|
830
|
-
|
|
831
|
-
|
|
861
|
+
case "SvelteElement": {
|
|
862
|
+
const tags = node.type === "SvelteElement" ? svelteElementTags(node.tag) : [node.name];
|
|
863
|
+
if (!tags) elementsUnknowable = true;
|
|
864
|
+
else for (const tag of tags) elementTags.add(tag.toLowerCase());
|
|
832
865
|
walkElement(node, ctx);
|
|
833
866
|
return;
|
|
867
|
+
}
|
|
834
868
|
case "Component":
|
|
835
869
|
case "SvelteComponent":
|
|
836
870
|
case "SvelteSelf":
|
|
@@ -884,7 +918,8 @@ function collectA11y(fragment, source) {
|
|
|
884
918
|
const line = lineOf(source, node.start);
|
|
885
919
|
const attrs = node.attributes;
|
|
886
920
|
const roleAttr = findAttr(attrs, "role");
|
|
887
|
-
const
|
|
921
|
+
const resolved = node.type === "SvelteElement" ? svelteElementTags(node.tag) : [node.name];
|
|
922
|
+
const tag = (resolved?.length === 1 ? resolved[0] : void 0)?.toLowerCase();
|
|
888
923
|
const landmark = resolveLandmark({
|
|
889
924
|
tag,
|
|
890
925
|
roleTokens: roleAttr ? splitTokens(attrTextOf(roleAttr)) : void 0,
|
|
@@ -967,14 +1002,18 @@ function parseFile(source, filename) {
|
|
|
967
1002
|
collectComponents(ast.fragment, components);
|
|
968
1003
|
const images = [];
|
|
969
1004
|
collectImages(ast.fragment, source, images);
|
|
970
|
-
const
|
|
971
|
-
|
|
1005
|
+
const headingAcc = {
|
|
1006
|
+
headings: [],
|
|
1007
|
+
dynamic: false
|
|
1008
|
+
};
|
|
1009
|
+
collectHeadings(ast.fragment, source, headingAcc);
|
|
972
1010
|
return {
|
|
973
1011
|
headTags: heads.flatMap(tagsFromHead),
|
|
974
1012
|
components,
|
|
975
1013
|
imports: collectImports(ast),
|
|
976
1014
|
images,
|
|
977
|
-
headings,
|
|
1015
|
+
headings: headingAcc.headings,
|
|
1016
|
+
dynamicHeading: headingAcc.dynamic,
|
|
978
1017
|
a11y: collectA11y(ast.fragment, source),
|
|
979
1018
|
suppressions: collectSuppressions(source)
|
|
980
1019
|
};
|
|
@@ -1080,6 +1119,7 @@ function resolveComponentPath(source, fromFileRel, aliases) {
|
|
|
1080
1119
|
async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited, cache = /* @__PURE__ */ new Map(), aliases) {
|
|
1081
1120
|
const tags = [...parsed.headTags];
|
|
1082
1121
|
const headings = [];
|
|
1122
|
+
let dynamicHeading = false;
|
|
1083
1123
|
let broad = false;
|
|
1084
1124
|
for (const use of parsed.components) {
|
|
1085
1125
|
const info = parsed.imports.get(use.name);
|
|
@@ -1104,6 +1144,7 @@ async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited,
|
|
|
1104
1144
|
file: childRel
|
|
1105
1145
|
});
|
|
1106
1146
|
headings.push(...child.headings);
|
|
1147
|
+
dynamicHeading = dynamicHeading || childParsed.dynamicHeading || child.dynamicHeading;
|
|
1107
1148
|
continue;
|
|
1108
1149
|
}
|
|
1109
1150
|
}
|
|
@@ -1115,7 +1156,8 @@ async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited,
|
|
|
1115
1156
|
return {
|
|
1116
1157
|
tags,
|
|
1117
1158
|
broad,
|
|
1118
|
-
headings
|
|
1159
|
+
headings,
|
|
1160
|
+
dynamicHeading
|
|
1119
1161
|
};
|
|
1120
1162
|
}
|
|
1121
1163
|
//#endregion
|
|
@@ -1333,6 +1375,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache, aliases, a
|
|
|
1333
1375
|
const images = [];
|
|
1334
1376
|
const headings = [];
|
|
1335
1377
|
const componentHeadings = [];
|
|
1378
|
+
let dynamicHeading = false;
|
|
1336
1379
|
const a11yCtx = {
|
|
1337
1380
|
rt,
|
|
1338
1381
|
cwd,
|
|
@@ -1373,6 +1416,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache, aliases, a
|
|
|
1373
1416
|
...heading,
|
|
1374
1417
|
file: rel
|
|
1375
1418
|
});
|
|
1419
|
+
dynamicHeading = dynamicHeading || parsed.dynamicHeading;
|
|
1376
1420
|
const resolved = await resolveFileTags(rt, cwd, rel, parsed, config, MAX_DEPTH$1, /* @__PURE__ */ new Set([rel]), cache, aliases);
|
|
1377
1421
|
for (const tag of resolved.tags) {
|
|
1378
1422
|
const stamped = {
|
|
@@ -1388,6 +1432,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache, aliases, a
|
|
|
1388
1432
|
else broadInherited = true;
|
|
1389
1433
|
}
|
|
1390
1434
|
componentHeadings.push(...resolved.headings);
|
|
1435
|
+
dynamicHeading = dynamicHeading || resolved.dynamicHeading;
|
|
1391
1436
|
}
|
|
1392
1437
|
if (broadOwn || broadInherited) {
|
|
1393
1438
|
const presence = broadOwn ? "own" : "inherited";
|
|
@@ -1436,7 +1481,8 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache, aliases, a
|
|
|
1436
1481
|
headings: {
|
|
1437
1482
|
route,
|
|
1438
1483
|
headings,
|
|
1439
|
-
componentHeadings
|
|
1484
|
+
componentHeadings,
|
|
1485
|
+
...dynamicHeading ? { dynamicHeading: true } : {}
|
|
1440
1486
|
},
|
|
1441
1487
|
a11y: {
|
|
1442
1488
|
route,
|
|
@@ -2515,7 +2561,8 @@ const KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
2515
2561
|
"rules",
|
|
2516
2562
|
"failOn",
|
|
2517
2563
|
"weights",
|
|
2518
|
-
"overrides"
|
|
2564
|
+
"overrides",
|
|
2565
|
+
"seo"
|
|
2519
2566
|
]);
|
|
2520
2567
|
/**
|
|
2521
2568
|
* Validate one rule setting — the bare severity string or the object form — and
|
|
@@ -2607,6 +2654,15 @@ function validateConfigFile(raw, path) {
|
|
|
2607
2654
|
});
|
|
2608
2655
|
config.overrides = overrides;
|
|
2609
2656
|
}
|
|
2657
|
+
if (raw.seo !== void 0) {
|
|
2658
|
+
if (!isPlainObject(raw.seo)) throw new Error(`${path}: seo must be an object, e.g. { indexable: false }.`);
|
|
2659
|
+
const unknown = Object.keys(raw.seo).filter((k) => k !== "indexable");
|
|
2660
|
+
if (unknown.length > 0) throw new Error(`${path}: unknown key(s) in seo: ${unknown.join(", ")}. Known keys: indexable.`);
|
|
2661
|
+
if (raw.seo.indexable !== void 0) {
|
|
2662
|
+
if (typeof raw.seo.indexable !== "boolean") throw new Error(`${path}: seo.indexable must be a boolean.`);
|
|
2663
|
+
config.seo = { indexable: raw.seo.indexable };
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2610
2666
|
if (raw.weights !== void 0) {
|
|
2611
2667
|
if (!isPlainObject(raw.weights)) throw new Error(`${path}: weights must be an object of category → number.`);
|
|
2612
2668
|
const weights = {};
|
|
@@ -2855,18 +2911,19 @@ async function analyzeProject(opts = {}) {
|
|
|
2855
2911
|
const loaded = opts.loadedConfig !== void 0 ? opts.loadedConfig ?? void 0 : opts.configPath !== void 0 ? await loadConfigFromPath(resolve(opts.configPath)) : await loadConfigFile(cwd);
|
|
2856
2912
|
const file = loaded?.config;
|
|
2857
2913
|
const weights = opts.weights ?? file?.weights;
|
|
2914
|
+
const seo = opts.seo ?? file?.seo;
|
|
2858
2915
|
const config = defineConfig({
|
|
2859
2916
|
treatDynamicAs: opts.treatDynamicAs ?? file?.treatDynamicAs ?? "pass",
|
|
2860
2917
|
metaComponents: opts.metaComponents ?? file?.metaComponents ?? [],
|
|
2861
2918
|
rules: resolveRuleSelection({
|
|
2862
|
-
|
|
2863
|
-
rules: opts.rules,
|
|
2919
|
+
rules: withIndexableOff(opts.rules ?? file?.rules, seo),
|
|
2864
2920
|
allowRules: opts.allowRules,
|
|
2865
2921
|
ignoreRules: opts.ignoreRules
|
|
2866
2922
|
}),
|
|
2867
2923
|
failOn: opts.failOn ?? file?.failOn ?? "critical",
|
|
2868
2924
|
...weights !== void 0 ? { weights } : {},
|
|
2869
|
-
...file?.overrides !== void 0 ? { overrides: file.overrides } : {}
|
|
2925
|
+
...file?.overrides !== void 0 ? { overrides: file.overrides } : {},
|
|
2926
|
+
...seo !== void 0 ? { seo } : {}
|
|
2870
2927
|
});
|
|
2871
2928
|
await detectProject(rt, cwd);
|
|
2872
2929
|
const warnings = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-vitals",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.0",
|
|
4
4
|
"description": "A deterministic SvelteKit code-health scanner (SEO, performance, correctness, security, architecture, accessibility).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,19 +43,19 @@
|
|
|
43
43
|
"dist"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@svelte-vitals/core": "0.
|
|
47
|
-
"@clack/prompts": "^1.8.
|
|
48
|
-
"@gunshi/plugin-completion": "0.37.
|
|
49
|
-
"@gunshi/plugin-i18n": "0.37.
|
|
50
|
-
"@gunshi/plugin-suggestion": "0.37.
|
|
51
|
-
"gunshi": "0.37.
|
|
46
|
+
"@svelte-vitals/core": "0.55.0",
|
|
47
|
+
"@clack/prompts": "^1.8.1",
|
|
48
|
+
"@gunshi/plugin-completion": "0.37.3",
|
|
49
|
+
"@gunshi/plugin-i18n": "0.37.3",
|
|
50
|
+
"@gunshi/plugin-suggestion": "0.37.3",
|
|
51
|
+
"gunshi": "0.37.3",
|
|
52
52
|
"magicast": "^0.5.5",
|
|
53
53
|
"svelte": "^5.57.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@gunshi/docs": "0.37.
|
|
56
|
+
"@gunshi/docs": "0.37.3",
|
|
57
57
|
"@types/estree": "^1.0.9",
|
|
58
|
-
"@types/node": "^24.13.
|
|
58
|
+
"@types/node": "^24.13.5"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "tsdown",
|