svelte-vitals 0.45.0 → 0.46.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/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runAnalyzeCliGunshi
4
- } from "./chunk-2NMVPG4P.js";
5
- import "./chunk-2UGE6HMQ.js";
4
+ } from "./chunk-Z2DBOC5X.js";
5
+ import "./chunk-FVN7R2YK.js";
6
6
  import "./chunk-MUIOPL5F.js";
7
7
  import "./chunk-M5KM5SV7.js";
8
8
  import {
@@ -18,29 +18,34 @@ import {
18
18
 
19
19
  // src/cli.ts
20
20
  async function runCli(argv, io = consoleIO, env = process.env) {
21
- const locale = resolveLocale(env);
22
- if (argv[0] === "complete") {
23
- const { runCompleteCliGunshi } = await import("./complete-KVRPOFNR.js");
24
- return { code: await runCompleteCliGunshi(argv, io), exit: "natural" };
21
+ try {
22
+ const locale = resolveLocale(env);
23
+ if (argv[0] === "complete") {
24
+ const { runCompleteCliGunshi } = await import("./complete-7TW5PTE6.js");
25
+ return { code: await runCompleteCliGunshi(argv, io), exit: "natural" };
26
+ }
27
+ if (argv[0] === "docs") {
28
+ const { runDocsCliGunshi } = await import("./docs-WRZT4ZJN.js");
29
+ return { code: await runDocsCliGunshi(argv.slice(1), io, locale), exit: "natural" };
30
+ }
31
+ if (argv[0] === "explain") {
32
+ const { runExplainCliGunshi } = await import("./explain-W3BU3CYJ.js");
33
+ return { code: await runExplainCliGunshi(argv.slice(1), io, locale), exit: "natural" };
34
+ }
35
+ if (argv[0] === "install") {
36
+ const { runInstallCliGunshi } = await import("./install-EP364SRT.js");
37
+ return { code: await runInstallCliGunshi(argv.slice(1), io, locale), exit: "immediate" };
38
+ }
39
+ if (argv[0] === "ci") {
40
+ const { runCiCliGunshi } = await import("./ci-TFTS5QAU.js");
41
+ const code = await runCiCliGunshi(argv.slice(1), { ...realIO(), log: io.log, errorLog: io.errorLog }, locale);
42
+ return { code, exit: "immediate" };
43
+ }
44
+ return await runAnalyzeCliGunshi(argv, io, locale);
45
+ } catch (err) {
46
+ io.errorLog(`svelte-vitals: ${err instanceof Error ? err.message : String(err)}`);
47
+ return { code: 2, exit: "natural" };
25
48
  }
26
- if (argv[0] === "docs") {
27
- const { runDocsCliGunshi } = await import("./docs-CRZC47P7.js");
28
- return { code: await runDocsCliGunshi(argv.slice(1), io, locale), exit: "natural" };
29
- }
30
- if (argv[0] === "explain") {
31
- const { runExplainCliGunshi } = await import("./explain-52QDQUOY.js");
32
- return { code: await runExplainCliGunshi(argv.slice(1), io, locale), exit: "natural" };
33
- }
34
- if (argv[0] === "install") {
35
- const { runInstallCliGunshi } = await import("./install-3FI7M5BM.js");
36
- return { code: await runInstallCliGunshi(argv.slice(1), io, locale), exit: "immediate" };
37
- }
38
- if (argv[0] === "ci") {
39
- const { runCiCliGunshi } = await import("./ci-CLKU3TR6.js");
40
- const code = await runCiCliGunshi(argv.slice(1), { ...realIO(), log: io.log, errorLog: io.errorLog }, locale);
41
- return { code, exit: "immediate" };
42
- }
43
- return runAnalyzeCliGunshi(argv, io, locale);
44
49
  }
45
50
 
46
51
  // src/bin.ts
@@ -52,4 +57,7 @@ async function main() {
52
57
  process.exitCode = code;
53
58
  }
54
59
  }
55
- void main();
60
+ main().catch((err) => {
61
+ console.error(`svelte-vitals: ${err instanceof Error ? err.message : String(err)}`);
62
+ process.exit(2);
63
+ });
@@ -17,7 +17,7 @@ import {
17
17
  WORKFLOW_PATH,
18
18
  buildWorkflowYaml,
19
19
  planWorkflowWrite
20
- } from "./chunk-F5P3REI7.js";
20
+ } from "./chunk-CTMKTFST.js";
21
21
  import {
22
22
  clackPrompts,
23
23
  realIO
@@ -17,10 +17,7 @@ import {
17
17
  import { cli } from "gunshi/bone";
18
18
  import { define } from "gunshi/definition";
19
19
  import "gunshi/generator";
20
- import { explainRule as explainRule2, allRules as allRules2 } from "@svelte-vitals/core";
21
-
22
- // src/explain.ts
23
- import { allRules, CATEGORIES } from "@svelte-vitals/core";
20
+ import { explainRule, allRules, CATEGORIES } from "@svelte-vitals/core";
24
21
  function describeOptions(id, options) {
25
22
  const MERGE = {
26
23
  integer: "replaces the default",
@@ -56,8 +53,6 @@ function renderRuleList() {
56
53
  "\n\n"
57
54
  );
58
55
  }
59
-
60
- // src/gunshi/explain.ts
61
56
  var BOOLEAN_FLAGS = ["json", "list", "help"];
62
57
  var KNOWN_LONG_FLAGS = new Set(BOOLEAN_FLAGS);
63
58
  var KNOWN_SHORT_FLAGS = /* @__PURE__ */ new Set(["h"]);
@@ -113,7 +108,7 @@ async function runExplainCliGunshi(args, io = consoleIO, locale = "en") {
113
108
  }
114
109
  io.log(
115
110
  ctx.values.json ? JSON.stringify(
116
- allRules2.map((r) => ({ id: r.id, category: r.category, severity: r.severity, title: r.title })),
111
+ allRules.map((r) => ({ id: r.id, category: r.category, severity: r.severity, title: r.title })),
117
112
  null,
118
113
  2
119
114
  ) : renderRuleList()
@@ -130,7 +125,7 @@ async function runExplainCliGunshi(args, io = consoleIO, locale = "en") {
130
125
  exitCode = 2;
131
126
  return;
132
127
  }
133
- const info = explainRule2(id);
128
+ const info = explainRule(id);
134
129
  if (!info) {
135
130
  io.errorLog(`svelte-vitals: unknown rule id '${id}'.`);
136
131
  const hint = suggestClosest(id, knownRuleIds());
@@ -4,7 +4,7 @@ import {
4
4
  WORKFLOW_PATH,
5
5
  buildWorkflowYaml,
6
6
  planWorkflowWrite
7
- } from "./chunk-F5P3REI7.js";
7
+ } from "./chunk-CTMKTFST.js";
8
8
  import {
9
9
  realIO
10
10
  } from "./chunk-GE7TKVTX.js";
@@ -1,7 +1,7 @@
1
1
  // src/ci/workflow.ts
2
2
  var WORKFLOW_PATH = ".github/workflows/svelte-vitals.yml";
3
- var CHECKOUT_SHA = "9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0";
4
- var CHECKOUT_VERSION = "v7.0.0";
3
+ var CHECKOUT_SHA = "3d3c42e5aac5ba805825da76410c181273ba90b1";
4
+ var CHECKOUT_VERSION = "v7.0.1";
5
5
  function planWorkflowWrite(existing, force) {
6
6
  if (existing === void 0) return { status: "created" };
7
7
  if (!force) return { status: "exists" };
@@ -28,6 +28,7 @@ function buildWorkflowYaml(opts) {
28
28
  ` - uses: actions/checkout@${CHECKOUT_SHA} # ${CHECKOUT_VERSION}`,
29
29
  " with:",
30
30
  " fetch-depth: 0",
31
+ " persist-credentials: false",
31
32
  ` - uses: oekazuma/svelte-vitals-action@${actionSha} # v${actionVersion}`,
32
33
  " with:",
33
34
  " diff: origin/${{ github.base_ref }}",
@@ -31,7 +31,10 @@ import {
31
31
  selectRules,
32
32
  applyRuleSeverities,
33
33
  applyOverrides,
34
- settingSeverity
34
+ settingSeverity,
35
+ withFailedRulesOff,
36
+ formatFailedRuleWarning,
37
+ terminalSafe
35
38
  } from "@svelte-vitals/core";
36
39
 
37
40
  // src/runtime/node.ts
@@ -221,6 +224,9 @@ import {
221
224
  // src/providers/source/routes.ts
222
225
  import { defaultConfig } from "@svelte-vitals/core";
223
226
 
227
+ // src/providers/source/resolve.ts
228
+ import { resolveRepoLocalPath } from "@svelte-vitals/core";
229
+
224
230
  // src/providers/source/adapters/svelte-meta-tags.ts
225
231
  import { attrValueOf, attrTextOf } from "@svelte-vitals/core";
226
232
 
@@ -606,28 +612,15 @@ function tagKey(tag) {
606
612
  return `script:${tag.href ?? "?"}`;
607
613
  }
608
614
  }
609
- function resolveComponentPath(source, fromFileRel) {
610
- let path;
611
- if (source.startsWith("$lib/")) {
612
- path = `src/lib/${source.slice("$lib/".length)}`;
613
- } else if (source === "$lib") {
614
- return void 0;
615
- } else if (source.startsWith("./") || source.startsWith("../")) {
616
- const dir = fromFileRel.split("/").slice(0, -1);
617
- for (const seg of source.split("/")) {
618
- if (seg === "." || seg === "") continue;
619
- if (seg === "..") dir.pop();
620
- else dir.push(seg);
621
- }
622
- path = dir.join("/");
623
- } else {
624
- return void 0;
625
- }
615
+ function resolveComponentPath(source, fromFileRel, aliases) {
616
+ if (source === "$lib") return void 0;
617
+ const path = resolveRepoLocalPath(source, fromFileRel, aliases);
618
+ if (path === void 0) return void 0;
626
619
  if (path.endsWith(".svelte")) return path;
627
620
  if (/\.[^/]+$/.test(path)) return void 0;
628
621
  return `${path}.svelte`;
629
622
  }
630
- async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited, cache = /* @__PURE__ */ new Map()) {
623
+ async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited, cache = /* @__PURE__ */ new Map(), aliases) {
631
624
  const tags = [...parsed.headTags];
632
625
  const headings = [];
633
626
  let broad = false;
@@ -644,13 +637,23 @@ async function resolveFileTags(rt, cwd, fileRel, parsed, config, depth, visited,
644
637
  broad = true;
645
638
  continue;
646
639
  }
647
- const childRel = info ? resolveComponentPath(info.source, fileRel) : void 0;
640
+ const childRel = info ? resolveComponentPath(info.source, fileRel, aliases) : void 0;
648
641
  if (childRel && depth > 0 && !visited.has(childRel)) {
649
642
  const abs = rt.join(cwd, childRel);
650
643
  if (await rt.exists(abs)) {
651
644
  const childParsed = await readAndParse(rt, cwd, childRel, cache);
652
645
  const childVisited = new Set(visited).add(childRel);
653
- const child = await resolveFileTags(rt, cwd, childRel, childParsed, config, depth - 1, childVisited, cache);
646
+ const child = await resolveFileTags(
647
+ rt,
648
+ cwd,
649
+ childRel,
650
+ childParsed,
651
+ config,
652
+ depth - 1,
653
+ childVisited,
654
+ cache,
655
+ aliases
656
+ );
654
657
  tags.push(...child.tags);
655
658
  broad = broad || child.broad;
656
659
  for (const h of childParsed.headings) headings.push({ ...h, file: childRel });
@@ -727,7 +730,7 @@ function chainFiles(pageRel, layouts) {
727
730
  }
728
731
  return [...chain.map((rel) => ({ rel, isPage: false })), { rel: pageRel, isPage: true }];
729
732
  }
730
- async function resolveRoute(rt, cwd, pageRel, config, layouts, cache) {
733
+ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache, aliases) {
731
734
  const files = chainFiles(pageRel, layouts);
732
735
  const composed = /* @__PURE__ */ new Map();
733
736
  const jsonldTags = [];
@@ -744,7 +747,7 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache) {
744
747
  for (const heading of parsed.headings) {
745
748
  headings.push({ ...heading, file: rel });
746
749
  }
747
- const resolved = await resolveFileTags(rt, cwd, rel, parsed, config, MAX_DEPTH, /* @__PURE__ */ new Set([rel]), cache);
750
+ const resolved = await resolveFileTags(rt, cwd, rel, parsed, config, MAX_DEPTH, /* @__PURE__ */ new Set([rel]), cache, aliases);
748
751
  for (const tag of resolved.tags) {
749
752
  const stamped = { ...tag, presence: isPage ? "own" : "inherited", file: rel };
750
753
  if (tag.kind === "jsonld") jsonldTags.push(stamped);
@@ -770,9 +773,9 @@ async function resolveRoute(rt, cwd, pageRel, config, layouts, cache) {
770
773
  headings: { route, headings, componentHeadings }
771
774
  };
772
775
  }
773
- async function collectRoutes(rt, cwd, config = defaultConfig, cache = /* @__PURE__ */ new Map()) {
776
+ async function collectRoutes(rt, cwd, config = defaultConfig, cache = /* @__PURE__ */ new Map(), aliases) {
774
777
  const [pages, layouts] = await Promise.all([enumerateRoutePages(rt, cwd), collectLayouts(rt, cwd)]);
775
- const facts = await Promise.all(pages.map((page) => resolveRoute(rt, cwd, page, config, layouts, cache)));
778
+ const facts = await Promise.all(pages.map((page) => resolveRoute(rt, cwd, page, config, layouts, cache, aliases)));
776
779
  return {
777
780
  heads: facts.map((f) => f.head),
778
781
  images: facts.map((f) => f.images),
@@ -793,7 +796,7 @@ async function collectAll(rt, cwd, config, opts = {}) {
793
796
  const matches = routeMatcher(opts.route);
794
797
  const project = await collectProjectFacts(rt, cwd);
795
798
  const [collected, components, kitModules, sourceFiles] = await Promise.all([
796
- collectRoutes(rt, cwd, config, opts.parseCache),
799
+ collectRoutes(rt, cwd, config, opts.parseCache, project.kitAliases),
797
800
  // Component (Correctness) facts are file-scoped with no route attribution yet, so a
798
801
  // route-filtered run skips them rather than reporting unrelated components (#68 review);
799
802
  // kitModules is skipped for the same reason.
@@ -1001,15 +1004,16 @@ function applySuppressions(results, entries, config, allResults) {
1001
1004
  }
1002
1005
 
1003
1006
  // src/color.ts
1007
+ import { styleText } from "util";
1004
1008
  import { noColorPalette } from "@svelte-vitals/core";
1005
- var wrap = (open, close = 0) => (s) => `\x1B[${open}m${s}\x1B[${close}m`;
1009
+ var wrap = (format) => (s) => styleText(format, s, { validateStream: false });
1006
1010
  var ansiPalette = {
1007
- bold: wrap(1, 22),
1008
- dim: wrap(2, 22),
1009
- red: wrap(31, 39),
1010
- yellow: wrap(33, 39),
1011
- green: wrap(32, 39),
1012
- cyan: wrap(36, 39)
1011
+ bold: wrap("bold"),
1012
+ dim: wrap("dim"),
1013
+ red: wrap("red"),
1014
+ yellow: wrap("yellow"),
1015
+ green: wrap("green"),
1016
+ cyan: wrap("cyan")
1013
1017
  };
1014
1018
  function colorEnabled(opts) {
1015
1019
  if (opts.noColorFlag) return false;
@@ -1020,28 +1024,6 @@ function colorEnabled(opts) {
1020
1024
  }
1021
1025
  var paletteFor = (enabled) => enabled ? ansiPalette : noColorPalette;
1022
1026
 
1023
- // src/spinner.ts
1024
- var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1025
- function startSpinner(text, opts) {
1026
- const stream = opts.stream ?? process.stderr;
1027
- if (!opts.enabled) return { stop() {
1028
- } };
1029
- let i = 0;
1030
- const tick = () => {
1031
- stream.write(`\r${FRAMES[i % FRAMES.length]} ${text}`);
1032
- i++;
1033
- };
1034
- tick();
1035
- const timer = setInterval(tick, 80);
1036
- if (typeof timer.unref === "function") timer.unref();
1037
- return {
1038
- stop() {
1039
- clearInterval(timer);
1040
- stream.write("\r\x1B[K");
1041
- }
1042
- };
1043
- }
1044
-
1045
1027
  // src/mascot.ts
1046
1028
  import { createLogUpdate } from "log-update";
1047
1029
  function mascotStateFor(score) {
@@ -1118,24 +1100,28 @@ function renderConfettiFrame(offset, mascotBlock) {
1118
1100
  return [confettiRow(offset), mascotBlock, confettiRow(offset + 2)].join("\n");
1119
1101
  }
1120
1102
  var IDLE_TICK_MS = 160;
1103
+ var PLAIN_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1104
+ var PLAIN_TICK_MS = 80;
1121
1105
  function startMascotSpinner(text, opts) {
1122
1106
  if (!opts.enabled) return { stop() {
1123
1107
  } };
1124
1108
  const stream = opts.stream ?? process.stderr;
1109
+ const mascot = opts.mascot ?? true;
1125
1110
  const render = createLogUpdate(stream);
1126
1111
  let i = 0;
1127
1112
  const tick = () => {
1128
- render(`${renderMascotIdleFrame(i)}
1129
- ${text}`);
1113
+ render(mascot ? `${renderMascotIdleFrame(i)}
1114
+ ${text}` : `${PLAIN_FRAMES[i % PLAIN_FRAMES.length]} ${text}`);
1130
1115
  i++;
1131
1116
  };
1132
1117
  tick();
1133
- const timer = setInterval(tick, IDLE_TICK_MS);
1118
+ const timer = setInterval(tick, mascot ? IDLE_TICK_MS : PLAIN_TICK_MS);
1134
1119
  if (typeof timer.unref === "function") timer.unref();
1135
1120
  return {
1136
1121
  stop() {
1137
1122
  clearInterval(timer);
1138
1123
  render.clear();
1124
+ render.done();
1139
1125
  }
1140
1126
  };
1141
1127
  }
@@ -1305,6 +1291,9 @@ function skippedFileWarnings(facts) {
1305
1291
  "findings for these files are unavailable until they parse."
1306
1292
  ];
1307
1293
  }
1294
+ function failedRuleWarnings(failedRules) {
1295
+ return failedRules.map(formatFailedRuleWarning);
1296
+ }
1308
1297
  async function analyzeProject(opts = {}) {
1309
1298
  const cwd = opts.cwd ?? process.cwd();
1310
1299
  const rt = createNodeRuntime();
@@ -1336,7 +1325,11 @@ async function analyzeProject(opts = {}) {
1336
1325
  });
1337
1326
  const selected = selectRules(allRules2, config);
1338
1327
  const rules = opts.categories ? selected.filter((r) => opts.categories.includes(r.category)) : selected;
1339
- const { results: rawResults, examined } = await runRules(rules, {
1328
+ const {
1329
+ results: rawResults,
1330
+ examined,
1331
+ failedRules
1332
+ } = await runRules(rules, {
1340
1333
  heads,
1341
1334
  images,
1342
1335
  headings,
@@ -1347,18 +1340,22 @@ async function analyzeProject(opts = {}) {
1347
1340
  sourceFiles
1348
1341
  });
1349
1342
  const results = applyOverrides(applyRuleSeverities(rawResults, config), config);
1343
+ const failedRuleIds = failedRules.map((f) => f.id);
1344
+ const scoringConfig = withFailedRulesOff(config, failedRuleIds);
1350
1345
  return {
1351
1346
  results,
1352
- config,
1347
+ config: scoringConfig,
1353
1348
  version: readPackageVersion(),
1354
1349
  ruleIds: rules.map((r) => r.id),
1355
1350
  examined,
1356
- warnings: [...warnings, ...skippedFileWarnings([...components, ...kitModules])],
1351
+ failedRuleIds,
1352
+ warnings: [...warnings, ...skippedFileWarnings([...components, ...kitModules]), ...failedRuleWarnings(failedRules)],
1357
1353
  loadedConfig: loaded
1358
1354
  };
1359
1355
  }
1360
1356
  async function applyScope(results, opts) {
1361
- const errorLog = opts.errorLog ?? ((line) => console.error(line));
1357
+ const rawErrorLog = opts.errorLog ?? ((line) => console.error(line));
1358
+ const errorLog = (line) => rawErrorLog(terminalSafe(line));
1362
1359
  let scoped = results;
1363
1360
  if (opts.staged || opts.diffBase !== void 0) {
1364
1361
  const changed = opts.staged ? getChangedFiles(opts.cwd, { staged: true }) : getChangedFiles(opts.cwd, { base: opts.diffBase });
@@ -1421,7 +1418,8 @@ function runAnalyzeOptions(opts) {
1421
1418
  }
1422
1419
  async function run(opts = {}) {
1423
1420
  const log = opts.log ?? ((line) => console.log(line));
1424
- const errorLog = opts.errorLog ?? ((line) => console.error(line));
1421
+ const rawErrorLog = opts.errorLog ?? ((line) => console.error(line));
1422
+ const errorLog = (line) => rawErrorLog(terminalSafe(line));
1425
1423
  if (opts.minHealth != null && (!Number.isFinite(opts.minHealth) || opts.minHealth < 0 || opts.minHealth > 100)) {
1426
1424
  errorLog(`svelte-vitals: invalid minHealth '${opts.minHealth}'; expected a number 0-100.`);
1427
1425
  return 2;
@@ -1440,7 +1438,11 @@ async function run(opts = {}) {
1440
1438
  if (useMascotSpinner && bubbleFitsWidth(stderrStream.columns)) {
1441
1439
  await playMascotGreeting({ enabled: true, stream: stderrStream, holdMs: opts.animationFrameDelayMs });
1442
1440
  }
1443
- const spinner = useMascotSpinner ? startMascotSpinner("Analyzing\u2026", { enabled: true, stream: stderrStream }) : startSpinner("Analyzing\u2026", { enabled: spinnerBaseEnabled, stream: stderrStream });
1441
+ const spinner = startMascotSpinner("Analyzing\u2026", {
1442
+ enabled: spinnerBaseEnabled,
1443
+ stream: stderrStream,
1444
+ mascot: useMascotSpinner
1445
+ });
1444
1446
  let cwd = opts.cwd ?? process.cwd();
1445
1447
  let analysis;
1446
1448
  try {
@@ -53,7 +53,7 @@ var EMBEDDED_DOCS = [
53
53
  }
54
54
  ];
55
55
 
56
- // src/docs/cli.ts
56
+ // src/gunshi/docs.ts
57
57
  var DOCS_HELP = `svelte-vitals docs \u2014 read the bundled guides without leaving the terminal
58
58
 
59
59
  Usage:
@@ -83,8 +83,6 @@ function renderList() {
83
83
  "Rule-level detail is a separate command: `svelte-vitals explain --list`."
84
84
  ].join("\n");
85
85
  }
86
-
87
- // src/gunshi/docs.ts
88
86
  var BOOLEAN_FLAGS = ["json", "help"];
89
87
  var HELP_ARG = { help: { type: "boolean", short: "h", description: "Show this help" } };
90
88
  var JSON_ARG = { json: { type: "boolean", description: "Machine-readable output (list only)" } };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-2UGE6HMQ.js";
3
+ } from "./chunk-FVN7R2YK.js";
4
4
  import {
5
5
  VALUE_FLAGS,
6
6
  parseRunArgs,
@@ -2,8 +2,8 @@ import {
2
2
  CI_ARGS,
3
3
  CI_UPGRADE_ARGS,
4
4
  runCiCliGunshi
5
- } from "./chunk-ACQ5HB32.js";
6
- import "./chunk-F5P3REI7.js";
5
+ } from "./chunk-6BUOZU6F.js";
6
+ import "./chunk-CTMKTFST.js";
7
7
  import "./chunk-GE7TKVTX.js";
8
8
  import "./chunk-NMVBVKLX.js";
9
9
  export {
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  ROOT_ARGS
3
- } from "./chunk-2NMVPG4P.js";
4
- import "./chunk-2UGE6HMQ.js";
3
+ } from "./chunk-Z2DBOC5X.js";
4
+ import "./chunk-FVN7R2YK.js";
5
5
  import {
6
6
  DOCS_LIST_ARGS,
7
7
  DOCS_ROOT_ARGS,
8
8
  DOCS_SHOW_ARGS
9
- } from "./chunk-MBOONBC4.js";
9
+ } from "./chunk-X7BU4DLG.js";
10
10
  import {
11
11
  EXPLAIN_ARGS
12
- } from "./chunk-O2CQPUSP.js";
12
+ } from "./chunk-4ZE7NBVE.js";
13
13
  import {
14
14
  INSTALL_ARGS
15
- } from "./chunk-4O5F7EUJ.js";
15
+ } from "./chunk-2RQRPUCR.js";
16
16
  import {
17
17
  CATEGORIES,
18
18
  FAIL_ON_VALUES,
@@ -28,8 +28,8 @@ import "./chunk-TFBLQUAC.js";
28
28
  import {
29
29
  CI_ARGS,
30
30
  CI_UPGRADE_ARGS
31
- } from "./chunk-ACQ5HB32.js";
32
- import "./chunk-F5P3REI7.js";
31
+ } from "./chunk-6BUOZU6F.js";
32
+ import "./chunk-CTMKTFST.js";
33
33
  import "./chunk-GE7TKVTX.js";
34
34
  import "./chunk-NMVBVKLX.js";
35
35
 
@@ -43,7 +43,15 @@ function forCompletion(args) {
43
43
  const out = {};
44
44
  for (const [key, schema] of Object.entries(args)) {
45
45
  if (schema.hidden) continue;
46
- out[schema.type === "positional" || !schema.toKebab ? key : kebabnize(key)] = schema;
46
+ const outKey = schema.type === "positional" || !schema.toKebab ? key : kebabnize(key);
47
+ const description = schema.description?.replace(/\s*\n\s*/g, " ");
48
+ out[outKey] = description === schema.description ? schema : { ...schema, description };
49
+ }
50
+ for (const [key, schema] of Object.entries(out)) {
51
+ const stripped = key.startsWith("no-") ? key.slice(3) : void 0;
52
+ if (stripped && !(stripped in out)) {
53
+ out[stripped] = { type: "positional", required: false, description: schema.description };
54
+ }
47
55
  }
48
56
  return out;
49
57
  }
@@ -3,7 +3,7 @@ import {
3
3
  DOCS_ROOT_ARGS,
4
4
  DOCS_SHOW_ARGS,
5
5
  runDocsCliGunshi
6
- } from "./chunk-MBOONBC4.js";
6
+ } from "./chunk-X7BU4DLG.js";
7
7
  import "./chunk-SLUMRYUD.js";
8
8
  import "./chunk-TFBLQUAC.js";
9
9
  import "./chunk-NMVBVKLX.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  EXPLAIN_ARGS,
3
3
  runExplainCliGunshi
4
- } from "./chunk-O2CQPUSP.js";
4
+ } from "./chunk-4ZE7NBVE.js";
5
5
  import "./chunk-SLUMRYUD.js";
6
6
  import "./chunk-TFBLQUAC.js";
7
7
  import "./chunk-NMVBVKLX.js";
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  ROOT_ARGS
3
- } from "./chunk-2NMVPG4P.js";
4
- import "./chunk-2UGE6HMQ.js";
3
+ } from "./chunk-Z2DBOC5X.js";
4
+ import "./chunk-FVN7R2YK.js";
5
5
  import {
6
6
  JA_ARG_DESCRIPTIONS
7
7
  } from "./chunk-MHRO4GU7.js";
8
8
  import {
9
9
  INSTALL_ARGS
10
- } from "./chunk-4O5F7EUJ.js";
10
+ } from "./chunk-2RQRPUCR.js";
11
11
  import "./chunk-MUIOPL5F.js";
12
12
  import "./chunk-M5KM5SV7.js";
13
13
  import "./chunk-SLUMRYUD.js";
14
14
  import "./chunk-TFBLQUAC.js";
15
- import "./chunk-F5P3REI7.js";
15
+ import "./chunk-CTMKTFST.js";
16
16
  import "./chunk-GE7TKVTX.js";
17
17
  import "./chunk-NMVBVKLX.js";
18
18
  export {
package/dist/index.d.ts CHANGED
@@ -231,6 +231,8 @@ interface AnalyzeResult {
231
231
  ruleIds: string[];
232
232
  /** Per-rule, per-declaration counts of places examined, unfiltered by `--diff`/`--baseline`/suppressions. */
233
233
  examined: Record<string, Record<string, number>>;
234
+ /** Ids of rules `runRules` caught throwing — already folded into `config` via `withFailedRulesOff`; exposed separately so a caller with its own base config (the vite dev dashboard) can apply the same correction without adopting this call's `config`. */
235
+ failedRuleIds: string[];
234
236
  /** Non-fatal issues surfaced during analysis: config-file problems (unknown top-level keys, invalid enum values), version-floor notices, `--rules`/overrides conflicts, and skipped-file notices. Empty when none apply. */
235
237
  warnings: string[];
236
238
  /**
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  routeMatcher,
7
7
  run,
8
8
  spinnerEnabled
9
- } from "./chunk-2UGE6HMQ.js";
9
+ } from "./chunk-FVN7R2YK.js";
10
10
  import {
11
11
  loadConfigFile
12
12
  } from "./chunk-M5KM5SV7.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  INSTALL_ARGS,
3
3
  runInstallCliGunshi
4
- } from "./chunk-4O5F7EUJ.js";
4
+ } from "./chunk-2RQRPUCR.js";
5
5
  import "./chunk-MUIOPL5F.js";
6
6
  import "./chunk-M5KM5SV7.js";
7
7
  import "./chunk-SLUMRYUD.js";
8
8
  import "./chunk-TFBLQUAC.js";
9
- import "./chunk-F5P3REI7.js";
9
+ import "./chunk-CTMKTFST.js";
10
10
  import "./chunk-GE7TKVTX.js";
11
11
  import "./chunk-NMVBVKLX.js";
12
12
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-vitals",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "A deterministic SvelteKit code-health scanner (SEO, performance, correctness, security, architecture) — not a runtime Web Vitals reporter.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -52,7 +52,7 @@
52
52
  "magicast": "^0.5.4",
53
53
  "svelte": "^5.56.8",
54
54
  "tinyglobby": "^0.2.17",
55
- "@svelte-vitals/core": "0.41.0"
55
+ "@svelte-vitals/core": "0.42.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@gunshi/docs": "0.37.1",