@svelte-vitals/core 0.41.0 → 0.41.1

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/index.d.ts CHANGED
@@ -612,6 +612,29 @@ interface KitModuleFacts {
612
612
  parseFailed?: true;
613
613
  }
614
614
 
615
+ /**
616
+ * Resolve an import specifier to a path relative to the analyzed project's root (the
617
+ * cwd svelte-vitals runs from — not necessarily a repo root; in a monorepo the project
618
+ * may live at e.g. `apps/web/`) against the importing file, or undefined when it cannot
619
+ * be a project-local module: the caller's `aliases` list decides which non-relative
620
+ * specifiers resolve, defaulting to `$lib` → `src/lib`; `./`/`../` resolve against the
621
+ * importing file's directory; bare packages and other aliases are skipped (they can't
622
+ * be resolved to a project-local path at all). Also undefined when a relative
623
+ * specifier's `..` segments escape the project root (see `normalizePosix`), or when a
624
+ * matched alias's value is itself absolute (e.g. `/opt/shared/src`, or a posixified Windows
625
+ * drive-letter path like `C:/shared/src`): an absolute target is outside the analyzed project by
626
+ * definition, and without this check `normalizePosix` would quietly drop the leading empty
627
+ * segment and hand back a project-relative-LOOKING path that actually names a different file.
628
+ *
629
+ * Exported from the package's public barrel because `architecture/private-scope-import`
630
+ * and `architecture/route-component-import` (inside `packages/core`) both need resolution
631
+ * that is not restricted to runes modules, unlike `resolveRunesModuleSpecifier` — and
632
+ * because `resolveComponentPath` (`packages/cli/src/providers/source/resolve.ts`), which
633
+ * drives transitive `<head>`/heading resolution, delegates its alias/`$lib`/relative
634
+ * mapping here too, rather than duplicating it. This is the single site for every
635
+ * repo-local specifier resolution in the repo.
636
+ */
637
+ declare function resolveRepoLocalPath(spec: string, importerFile: string, aliases?: readonly KitAlias[]): string | undefined;
615
638
  /**
616
639
  * Resolve an import specifier to a repo-relative `.svelte.ts`/`.svelte.js` path, or
617
640
  * undefined when it cannot be a runes module: delegates to `resolveRepoLocalPath` with
@@ -780,6 +803,14 @@ declare function settingSeverity(setting: RuleSetting | undefined): Severity | '
780
803
  declare function settingOptions(setting: RuleSetting | undefined): RuleOptions | undefined;
781
804
  /** Drop rules disabled via config (design §6). */
782
805
  declare function selectRules(rules: Rule[], config: Config): Rule[];
806
+ /**
807
+ * `config` with `failedRuleIds` (from `runRules`' `failedRules`) forced `'off'`: a rule that threw
808
+ * examined nothing, so leaving it in the inventory would score it as if it had run clean, silently
809
+ * inflating Health. Reuses the exact mechanism a `rules: { id: 'off' }` config entry already gets —
810
+ * `selectRules`/`buildInventory` both drop an `'off'` id from the denominator — rather than adding a
811
+ * second, parallel notion of "not counted" for callers to keep in sync.
812
+ */
813
+ declare function withFailedRulesOff(config: Config, failedRuleIds: readonly string[]): Config;
783
814
  /** Apply per-rule severity overrides to results (design §6). */
784
815
  declare function applyRuleSeverities(results: Result[], config: Config): Result[];
785
816
  /** An override entry with its globs compiled once. Build with `compileOverrides`. */
@@ -1009,14 +1040,21 @@ declare function docsUrlFor(id: string): string;
1009
1040
  */
1010
1041
  declare function isPenalized(detection: Detection, treatDynamicAs: TreatDynamicAs): boolean;
1011
1042
 
1043
+ interface FailedRule {
1044
+ id: string;
1045
+ message: string;
1046
+ }
1012
1047
  /**
1013
1048
  * Run a set of rules against a shared context and collect their findings.
1014
1049
  * Rules are independent, so they run concurrently; results are flattened in
1015
- * rule order for stable output.
1050
+ * rule order for stable output. A rule that throws (sync or async) contributes
1051
+ * no results instead of taking the whole run down with it — dev tooling must
1052
+ * never throw — and is reported in `failedRules` instead.
1016
1053
  */
1017
1054
  declare function runRules(rules: Rule[], ctx: RuleContext): Promise<{
1018
1055
  results: Result[];
1019
1056
  examined: Record<string, Record<string, number>>;
1057
+ failedRules: FailedRule[];
1020
1058
  }>;
1021
1059
 
1022
1060
  /**
@@ -1696,4 +1734,4 @@ declare function escapeHtml(s: string): string;
1696
1734
  */
1697
1735
  declare function safeHref(url: string): string | null;
1698
1736
 
1699
- export { APP_SCRIPT, APP_STYLE, type AppSnapshot, BAND_COLOR, CATEGORIES, CHILD_NODE_KEYS, type Category, type Classification, type CompiledOverride, type ComponentFacts, type Config, type ConsoleReportOptions, type Detection, type EachBlockFact, type EffectFact, type Fix, type HeadProvider, type HeadTag, type HeadingInfo, type HealthResult, type ImageInfo, type JsonReport, type KitAlias, type KitModuleFacts, type OrphanEffectFact, type Palette, type Presence, type Project, ROBOTS_SOURCE_PATHS, type RawKitAliases, type ResolvedHead, type ResolvedHeadings, type ResolvedImages, type Result, type RouteBadge, type Rule, type RuleContext, type RuleEvidence, type RuleInfo, type RuleOptionInfo, type RuleOptionSpec, type RuleOptions, type RuleOptionsSpec, type RuleOverride, type RuleSetting, type RuleSettingObject, type Runtime, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, type Scope, type ScoreModel, type ScoreOptions, type ScoreResult, type Severity, type SourceSpan, type Summary, type SuppressionDirective, type TreatDynamicAs, VITE_CONFIG_FILES, type Value, type ViteKitConfigResult, allRules, applyOverrides, applyRuleSeverities, architectureComponentSize, architectureDirectoryNaming, architectureDocLinkTarget, architecturePrivateScopeImport, architecturePropCount, architectureReservedDirectoryNames, architectureReservedNamePlacement, architectureRouteComponentImport, architectureUnitEntryFile, attrText, attrTextOf, attrValue, attrValueOf, buildHtmlDocument, buildJsonReport, classify, collectComponentFacts, collectKitModuleFacts, collectSourceFiles, compileOverrides, computeHealth, computeScore, correctnessBasePathNavigation, correctnessCheckableBindValue, correctnessEachIndexKey, correctnessEachKey, correctnessEffectAsDerived, correctnessEffectAsOnMount, correctnessInstanceBrowserGlobal, correctnessNonreactiveBuiltinState, correctnessOrphanEffect, correctnessOrphanLifecycle, correctnessPropMutation, correctnessServerBrowserGlobal, correctnessStalePropDerivation, correctnessUnmutatedState, defaultConfig, defaultProject, defineConfig, docsUrlFor, effectiveSeverity, emptyComponentFacts, emptyKitModuleFacts, escapeHtml, explainRule, findAttr, findKitAliasesInSvelteConfig, findKitPathsBaseInSvelteConfig, findKitPathsBaseInViteConfig, findMinifyDisabled, formatAgentReport, formatConsoleReport, formatGithubReport, formatHtmlReport, formatJsonReport, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, headTagRule, imageRule, intOption, isMentionedAnywhere, isPenalized, lineOf, linkRule, listOption, mapOption, noColorPalette, overrideMatches, parseComponentFacts, parseKitModuleFacts, performanceFontPreloadCrossorigin, performanceHeavyImport, performanceImageDimensions, performanceImageLoadingHint, performanceLcpImage, performanceLoadWaterfall, performanceMinifyDisabled, performanceNamespaceImport, performancePreconnect, performancePreloadMissingAs, performanceRenderBlockingScript, performanceResponsiveImage, performanceSequentialAwaits, performanceStateRaw, renderAppShell, resolveKitAliases, resolveKitPathsBase, resolveRuleOptions, resolveRunesModuleSpecifier, runRules, safeHref, scoreBand, scoreColor, scoresByCategory, securityHandlerStateWrite, securityJavascriptUrl, securityRawHtml, securityServerModuleState, securitySharedStateImport, selectRules, seoCanonicalUrl, seoCharset, seoDescriptionLength, seoDescriptionPresence, seoDuplicateDescription, seoDuplicateTitle, seoHeadingLevelSkip, seoHreflang, seoHtmlLang, seoImageAlt, seoIndexability, seoJsonLd, seoJsonLdDateFormat, seoJsonLdDeprecatedType, seoJsonLdPlaceholder, seoJsonLdRelativeUrl, seoJsonLdRequiredProps, seoJsonLdValidity, seoOgDescription, seoOgImage, seoOgTitle, seoOgUrl, seoRobotsTxt, seoSingleH1, seoSitemapInRobots, seoSitemapXml, seoSsrDisabled, seoTitleLength, seoTitlePresence, seoTwitterCard, seoViewport, settingOptions, settingSeverity, shouldSkipRangeCheck, summarize, textFromNodes, validateRuleOptions, validateRuleSetting, valueFromNodes };
1737
+ export { APP_SCRIPT, APP_STYLE, type AppSnapshot, BAND_COLOR, CATEGORIES, CHILD_NODE_KEYS, type Category, type Classification, type CompiledOverride, type ComponentFacts, type Config, type ConsoleReportOptions, type Detection, type EachBlockFact, type EffectFact, type FailedRule, type Fix, type HeadProvider, type HeadTag, type HeadingInfo, type HealthResult, type ImageInfo, type JsonReport, type KitAlias, type KitModuleFacts, type OrphanEffectFact, type Palette, type Presence, type Project, ROBOTS_SOURCE_PATHS, type RawKitAliases, type ResolvedHead, type ResolvedHeadings, type ResolvedImages, type Result, type RouteBadge, type Rule, type RuleContext, type RuleEvidence, type RuleInfo, type RuleOptionInfo, type RuleOptionSpec, type RuleOptions, type RuleOptionsSpec, type RuleOverride, type RuleSetting, type RuleSettingObject, type Runtime, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, type Scope, type ScoreModel, type ScoreOptions, type ScoreResult, type Severity, type SourceSpan, type Summary, type SuppressionDirective, type TreatDynamicAs, VITE_CONFIG_FILES, type Value, type ViteKitConfigResult, allRules, applyOverrides, applyRuleSeverities, architectureComponentSize, architectureDirectoryNaming, architectureDocLinkTarget, architecturePrivateScopeImport, architecturePropCount, architectureReservedDirectoryNames, architectureReservedNamePlacement, architectureRouteComponentImport, architectureUnitEntryFile, attrText, attrTextOf, attrValue, attrValueOf, buildHtmlDocument, buildJsonReport, classify, collectComponentFacts, collectKitModuleFacts, collectSourceFiles, compileOverrides, computeHealth, computeScore, correctnessBasePathNavigation, correctnessCheckableBindValue, correctnessEachIndexKey, correctnessEachKey, correctnessEffectAsDerived, correctnessEffectAsOnMount, correctnessInstanceBrowserGlobal, correctnessNonreactiveBuiltinState, correctnessOrphanEffect, correctnessOrphanLifecycle, correctnessPropMutation, correctnessServerBrowserGlobal, correctnessStalePropDerivation, correctnessUnmutatedState, defaultConfig, defaultProject, defineConfig, docsUrlFor, effectiveSeverity, emptyComponentFacts, emptyKitModuleFacts, escapeHtml, explainRule, findAttr, findKitAliasesInSvelteConfig, findKitPathsBaseInSvelteConfig, findKitPathsBaseInViteConfig, findMinifyDisabled, formatAgentReport, formatConsoleReport, formatGithubReport, formatHtmlReport, formatJsonReport, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, headTagRule, imageRule, intOption, isMentionedAnywhere, isPenalized, lineOf, linkRule, listOption, mapOption, noColorPalette, overrideMatches, parseComponentFacts, parseKitModuleFacts, performanceFontPreloadCrossorigin, performanceHeavyImport, performanceImageDimensions, performanceImageLoadingHint, performanceLcpImage, performanceLoadWaterfall, performanceMinifyDisabled, performanceNamespaceImport, performancePreconnect, performancePreloadMissingAs, performanceRenderBlockingScript, performanceResponsiveImage, performanceSequentialAwaits, performanceStateRaw, renderAppShell, resolveKitAliases, resolveKitPathsBase, resolveRepoLocalPath, resolveRuleOptions, resolveRunesModuleSpecifier, runRules, safeHref, scoreBand, scoreColor, scoresByCategory, securityHandlerStateWrite, securityJavascriptUrl, securityRawHtml, securityServerModuleState, securitySharedStateImport, selectRules, seoCanonicalUrl, seoCharset, seoDescriptionLength, seoDescriptionPresence, seoDuplicateDescription, seoDuplicateTitle, seoHeadingLevelSkip, seoHreflang, seoHtmlLang, seoImageAlt, seoIndexability, seoJsonLd, seoJsonLdDateFormat, seoJsonLdDeprecatedType, seoJsonLdPlaceholder, seoJsonLdRelativeUrl, seoJsonLdRequiredProps, seoJsonLdValidity, seoOgDescription, seoOgImage, seoOgTitle, seoOgUrl, seoRobotsTxt, seoSingleH1, seoSitemapInRobots, seoSitemapXml, seoSsrDisabled, seoTitleLength, seoTitlePresence, seoTwitterCard, seoViewport, settingOptions, settingSeverity, shouldSkipRangeCheck, summarize, textFromNodes, validateRuleOptions, validateRuleSetting, valueFromNodes, withFailedRulesOff };
package/dist/index.js CHANGED
@@ -2464,9 +2464,21 @@ function isPenalized(detection, treatDynamicAs) {
2464
2464
  async function runRules(rules, ctx) {
2465
2465
  const examined = {};
2466
2466
  const perRule = await Promise.all(
2467
- rules.map((rule) => rule.check({ ...ctx, recordExamined: (counts) => void (examined[rule.id] = counts) }))
2467
+ rules.map(async (rule) => {
2468
+ try {
2469
+ return await rule.check({ ...ctx, recordExamined: (counts) => void (examined[rule.id] = counts) });
2470
+ } catch (err) {
2471
+ return { id: rule.id, message: err instanceof Error ? err.message : String(err) };
2472
+ }
2473
+ })
2468
2474
  );
2469
- return { results: perRule.flat(), examined };
2475
+ const results = [];
2476
+ const failedRules = [];
2477
+ for (const outcome of perRule) {
2478
+ if (Array.isArray(outcome)) results.push(...outcome);
2479
+ else failedRules.push(outcome);
2480
+ }
2481
+ return { results, examined, failedRules };
2470
2482
  }
2471
2483
 
2472
2484
  // src/rules/seo/title-presence.ts
@@ -3061,6 +3073,16 @@ function settingOptions(setting) {
3061
3073
  function selectRules(rules, config) {
3062
3074
  return rules.filter((rule) => settingSeverity(config.rules[rule.id]) !== "off");
3063
3075
  }
3076
+ function withFailedRulesOff(config, failedRuleIds) {
3077
+ if (failedRuleIds.length === 0) return config;
3078
+ return {
3079
+ ...config,
3080
+ rules: {
3081
+ ...config.rules,
3082
+ ...Object.fromEntries(failedRuleIds.map((id) => [id, "off"]))
3083
+ }
3084
+ };
3085
+ }
3064
3086
  function applyRuleSeverities(results, config) {
3065
3087
  return results.map((result) => {
3066
3088
  const severity = settingSeverity(config.rules[result.id]);
@@ -4720,6 +4742,39 @@ var SCHEMA_ORG_CONTEXT_RE = /^https?:\/\/schema\.org\/?$/;
4720
4742
  var LOWERCASE_TO_CANONICAL = new Map(
4721
4743
  [...SCHEMA_ORG_TYPES].map((name) => [name.toLowerCase(), name])
4722
4744
  );
4745
+ var SORTED_TYPES = [...SCHEMA_ORG_TYPES].sort();
4746
+ var MAX_SUGGEST_DISTANCE = 2;
4747
+ function levenshteinWithin(a, b, maxDistance) {
4748
+ if (Math.abs(a.length - b.length) > maxDistance) return maxDistance + 1;
4749
+ let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
4750
+ for (let i = 1; i <= a.length; i++) {
4751
+ const curr = [i];
4752
+ let rowMin = i;
4753
+ for (let j = 1; j <= b.length; j++) {
4754
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
4755
+ const v = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
4756
+ curr.push(v);
4757
+ if (v < rowMin) rowMin = v;
4758
+ }
4759
+ if (rowMin > maxDistance) return maxDistance + 1;
4760
+ prev = curr;
4761
+ }
4762
+ return prev[b.length];
4763
+ }
4764
+ function closestType(name, catalog) {
4765
+ const lower = name.toLowerCase();
4766
+ let best;
4767
+ let bestDistance = MAX_SUGGEST_DISTANCE + 1;
4768
+ for (const candidate of catalog) {
4769
+ if (Math.abs(candidate.length - name.length) > MAX_SUGGEST_DISTANCE) continue;
4770
+ const d = levenshteinWithin(lower, candidate.toLowerCase(), MAX_SUGGEST_DISTANCE);
4771
+ if (d < bestDistance) {
4772
+ bestDistance = d;
4773
+ best = candidate;
4774
+ }
4775
+ }
4776
+ return bestDistance <= MAX_SUGGEST_DISTANCE ? best : void 0;
4777
+ }
4723
4778
  function isSchemaOrgContextValue(v) {
4724
4779
  if (typeof v === "string") return SCHEMA_ORG_CONTEXT_RE.test(v);
4725
4780
  if (Array.isArray(v)) return v.every((m) => typeof m === "string" && SCHEMA_ORG_CONTEXT_RE.test(m));
@@ -4740,7 +4795,7 @@ function unknownTypeNames(nodes) {
4740
4795
  return [...seen];
4741
4796
  }
4742
4797
  function unknownTypeMessage(name) {
4743
- const canonical = LOWERCASE_TO_CANONICAL.get(name.toLowerCase());
4798
+ const canonical = LOWERCASE_TO_CANONICAL.get(name.toLowerCase()) ?? closestType(name, SORTED_TYPES);
4744
4799
  return canonical ? `Unknown @type '${name}' \u2014 not a schema.org type. Did you mean '${canonical}'?` : `Unknown @type '${name}' \u2014 not a schema.org type.`;
4745
4800
  }
4746
4801
  var seoJsonLdValidity = {
@@ -5594,7 +5649,8 @@ var correctnessOrphanEffect = componentRule({
5594
5649
  rationale: "An $effect created outside component initialisation throws effect_orphan at runtime. The compiler does not catch it \u2014 the server compiler deletes $effect calls entirely, so SSR renders without error \u2014 and the crash happens client-side, when the module evaluates in the browser, breaking hydration rather than producing a server error.",
5595
5650
  // `orphanEffects` is typed required, but a facts object built by an older/external
5596
5651
  // constructor may omit it — default to empty rather than let `applies` throw and
5597
- // take the whole `runRules` Promise.all down with it.
5652
+ // surface this rule as failed (the engine isolates a throwing rule, but this one
5653
+ // can just work instead of getting flagged).
5598
5654
  applies: (c) => (c.orphanEffects ?? []).length > 0,
5599
5655
  bad: (c) => (c.orphanEffects ?? []).map((o) => ({
5600
5656
  line: o.line,
@@ -7397,6 +7453,20 @@ function scoreColor(p, score) {
7397
7453
  return p.red;
7398
7454
  }
7399
7455
 
7456
+ // src/reporter/sanitize.ts
7457
+ function inlineCode(text) {
7458
+ const longestRun = Math.max(0, ...(text.match(/`+/g) ?? []).map((run) => run.length));
7459
+ const fence = "`".repeat(longestRun + 1);
7460
+ const pad = text.startsWith("`") || text.endsWith("`") ? " " : "";
7461
+ return `${fence}${pad}${text}${pad}${fence}`;
7462
+ }
7463
+ function mdEscape(text) {
7464
+ return text.replace(/\r\n|\r|\n/g, " ").replace(/<[^>]+>/g, (tag) => inlineCode(tag)).replace(/\[([^\]]*)\]\(([^)]*)\)/g, "[$1]\\($2\\)");
7465
+ }
7466
+ function terminalSafe(text) {
7467
+ return text.replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?/g, "").replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "").replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
7468
+ }
7469
+
7400
7470
  // src/reporter/console.ts
7401
7471
  var RULE = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
7402
7472
  var SEVERITY_TITLE = {
@@ -7445,9 +7515,9 @@ function byRouteTree(p, results, config, verbose) {
7445
7515
  const shown = verbose ? scored : scored.slice(0, MAX_ROUTES_BY_ROUTE);
7446
7516
  const lines = [p.bold("By route"), p.dim(RULE)];
7447
7517
  for (const { route, rs, score } of shown) {
7448
- lines.push(`${route.padEnd(28)} ${scoreColor(p, score)(`${score}`)}`);
7518
+ lines.push(`${terminalSafe(route).padEnd(28)} ${scoreColor(p, score)(`${score}`)}`);
7449
7519
  for (const r of rs.filter((x) => classify(x, config) === "fail")) {
7450
- lines.push(` ${p.red("\u2717")} ${r.id} ${r.message}`);
7520
+ lines.push(` ${p.red("\u2717")} ${r.id} ${terminalSafe(r.message)}`);
7451
7521
  }
7452
7522
  }
7453
7523
  if (!verbose && scored.length > MAX_ROUTES_BY_ROUTE) {
@@ -7491,18 +7561,18 @@ function formatConsoleReport(results, config, options = {}) {
7491
7561
  lines.push(SEVERITY_COLOR[severity](`${SEVERITY_TITLE[severity]} (${bucket.length})`), p.dim(RULE));
7492
7562
  if (options.verbose) {
7493
7563
  for (const r of bucket) {
7494
- lines.push(`${p.red("\u2717")} ${r.id} ${r.message}`);
7495
- if (r.route) lines.push(p.dim(` ${r.route}`));
7496
- if (r.location) lines.push(p.dim(` ${r.location}${r.line ? `:${r.line}` : ""}`));
7564
+ lines.push(`${p.red("\u2717")} ${r.id} ${terminalSafe(r.message)}`);
7565
+ if (r.route) lines.push(p.dim(` ${terminalSafe(r.route)}`));
7566
+ if (r.location) lines.push(p.dim(` ${terminalSafe(r.location)}${r.line ? `:${r.line}` : ""}`));
7497
7567
  }
7498
7568
  } else {
7499
7569
  const groups = groupByRule(bucket);
7500
7570
  const shownGroups = groups.slice(0, MAX_RULE_GROUPS_PER_BUCKET);
7501
7571
  for (const group of shownGroups) {
7502
7572
  const r = group.results[0];
7503
- lines.push(`${p.red("\u2717")} ${r.id} ${r.message}`);
7504
- if (r.route) lines.push(p.dim(` ${r.route}`));
7505
- if (r.location) lines.push(p.dim(` ${r.location}${r.line ? `:${r.line}` : ""}`));
7573
+ lines.push(`${p.red("\u2717")} ${r.id} ${terminalSafe(r.message)}`);
7574
+ if (r.route) lines.push(p.dim(` ${terminalSafe(r.route)}`));
7575
+ if (r.location) lines.push(p.dim(` ${terminalSafe(r.location)}${r.line ? `:${r.line}` : ""}`));
7506
7576
  if (group.results.length > 1) {
7507
7577
  lines.push(p.dim(` \u2026and ${group.results.length - 1} more`));
7508
7578
  }
@@ -7523,8 +7593,8 @@ function formatConsoleReport(results, config, options = {}) {
7523
7593
  for (const r of passed) {
7524
7594
  const marker = classify(r, config) === "dynamic" ? p.cyan(" \u21AF dynamic") : "";
7525
7595
  const where = r.location ?? r.route;
7526
- const suffix = where ? ` ${where}` : "";
7527
- lines.push(`${p.green("\u2713")} ${r.id} ${r.message}${marker}${suffix}`);
7596
+ const suffix = where ? ` ${terminalSafe(where)}` : "";
7597
+ lines.push(`${p.green("\u2713")} ${r.id} ${terminalSafe(r.message)}${marker}${suffix}`);
7528
7598
  }
7529
7599
  }
7530
7600
  lines.push("");
@@ -7607,9 +7677,6 @@ function formatJsonReport(results, config, meta, ruleIds, examined) {
7607
7677
 
7608
7678
  // src/reporter/agent.ts
7609
7679
  var SEVERITY_RANK = { critical: 0, warning: 1, info: 2 };
7610
- function mdTags(text) {
7611
- return text.replace(/<[^>]+>/g, (tag) => `\`${tag}\``);
7612
- }
7613
7680
  function formatAgentReport(results, config) {
7614
7681
  const failing = results.filter((r) => classify(r, config) === "fail");
7615
7682
  const { health } = computeHealth(results, config);
@@ -7636,17 +7703,17 @@ function formatAgentReport(results, config) {
7636
7703
  rs.sort(
7637
7704
  (x, y) => SEVERITY_RANK[effectiveSeverity(x, config)] - SEVERITY_RANK[effectiveSeverity(y, config)] || x.id.localeCompare(y.id)
7638
7705
  );
7639
- lines.push(`## ${loc}`, "");
7706
+ lines.push(`## ${mdEscape(loc)}`, "");
7640
7707
  for (const r of rs) {
7641
- lines.push(`### ${r.id} \xB7 ${mdTags(r.message)} (${effectiveSeverity(r, config)})`);
7708
+ lines.push(`### ${r.id} \xB7 ${mdEscape(r.message)} (${effectiveSeverity(r, config)})`);
7642
7709
  if (r.fix) {
7643
- lines.push(`- Fix: ${mdTags(r.fix.description)}`);
7710
+ lines.push(`- Fix: ${mdEscape(r.fix.description)}`);
7644
7711
  if (r.fix.snippet) lines.push("", "```" + (r.fix.lang ?? "svelte"), r.fix.snippet, "```");
7645
7712
  } else if (r.recommendation) {
7646
- lines.push(`- Fix: ${mdTags(r.recommendation)}`);
7713
+ lines.push(`- Fix: ${mdEscape(r.recommendation)}`);
7647
7714
  }
7648
7715
  if (r.docsUrl) lines.push(`- Docs: ${r.docsUrl}`);
7649
- lines.push(`- Accept: re-run svelte-vitals; ${r.id} passes${r.route ? ` for ${r.route}` : ""}.`, "");
7716
+ lines.push(`- Accept: re-run svelte-vitals; ${r.id} passes${r.route ? ` for ${mdEscape(r.route)}` : ""}.`, "");
7650
7717
  }
7651
7718
  }
7652
7719
  return lines.join("\n").replace(/\n+$/, "\n");
@@ -7757,7 +7824,7 @@ var MAX_FINDINGS = 50;
7757
7824
  var SEVERITY_EMOJI = { critical: "\u{1F534}", warning: "\u{1F7E1}", info: "\u{1F535}" };
7758
7825
  var SEVERITY_RANK2 = { critical: 0, warning: 1, info: 2 };
7759
7826
  function escapeCell(s) {
7760
- return s.replace(/\|/g, "\\|").replace(/\r\n|\r|\n/g, " ");
7827
+ return mdEscape(s).replace(/(\\*)\|/g, (_, bs) => bs + bs + "\\|");
7761
7828
  }
7762
7829
  function locationOf(issue, route) {
7763
7830
  if (issue.location) return issue.line !== void 0 ? `${issue.location}:${issue.line}` : issue.location;
@@ -8629,6 +8696,7 @@ export {
8629
8696
  renderAppShell,
8630
8697
  resolveKitAliases,
8631
8698
  resolveKitPathsBase,
8699
+ resolveRepoLocalPath,
8632
8700
  resolveRuleOptions,
8633
8701
  resolveRunesModuleSpecifier,
8634
8702
  runRules,
@@ -8680,5 +8748,6 @@ export {
8680
8748
  textFromNodes,
8681
8749
  validateRuleOptions,
8682
8750
  validateRuleSetting,
8683
- valueFromNodes
8751
+ valueFromNodes,
8752
+ withFailedRulesOff
8684
8753
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svelte-vitals/core",
3
- "version": "0.41.0",
3
+ "version": "0.41.1",
4
4
  "description": "Shared, runtime-agnostic core for svelte-vitals (types, rule engine, scorer, reporter).",
5
5
  "type": "module",
6
6
  "license": "MIT",