@svelte-vitals/core 0.55.1 → 0.55.3

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.
@@ -46,6 +46,15 @@ interface EachBlockFact {
46
46
  line: number;
47
47
  /** Set when the block's key expression is its index binding or a trivial coercion of it — `(i)`, `(String(i))`, `(Number(i))`, `` (`${i}`) ``, `(i.toString())`, `(i + '')` — correctness/each-index-key. */
48
48
  indexKey?: boolean;
49
+ /**
50
+ * The import the block iterates, set on an unkeyed or index-keyed block over an imported binding
51
+ * (`xs`, or `ns.xs` of `import * as ns`) the component only reads. Core cannot see the module
52
+ * behind it; a collector that can drops the block when that export is a constant list.
53
+ */
54
+ importedList?: {
55
+ source: string;
56
+ imported: string;
57
+ };
49
58
  }
50
59
  /** An `$effect(...)` / `$effect.pre(...)` call in a component's instance script. */
51
60
  interface EffectFact {
@@ -172,6 +181,8 @@ interface AriaElementFact {
172
181
  /** Set when the element also carries a spread attribute — its full attribute set is
173
182
  * unknowable, so required-prop presence checks must treat it as satisfied (a11y/required-aria-props). */
174
183
  hasSpread?: true;
184
+ /** Set when the element carries a `use:` action, which may set `role` at runtime (svelte-dnd-action's handles do). */
185
+ hasAction?: true;
175
186
  }
176
187
  /**
177
188
  * Every element in a component with its literal attribute names — the input for the rules that
@@ -238,12 +249,15 @@ interface ComponentFacts {
238
249
  * architecture/route-component-import). `type` marks a declaration that contributes **no runtime
239
250
  * value binding** — either `import type …`, or one whose every specifier is inline-typed
240
251
  * (`import { type A } from …`). A specifier-less side-effect import is not marked: it still loads
241
- * the module. Optional, so existing external constructors of `ComponentFacts` are unaffected.
252
+ * the module. `named` marks a value declaration binding only named exports — no default,
253
+ * `default as`, or namespace — so it cannot render an imported component. Both optional, so
254
+ * existing external constructors of `ComponentFacts` are unaffected.
242
255
  */
243
256
  importSpans: {
244
257
  source: string;
245
258
  line: number;
246
259
  type?: true;
260
+ named?: true;
247
261
  }[];
248
262
  /** Value `import * as X from '<bare pkg>'` namespace imports (type-only excluded) — performance/namespace-import. */
249
263
  namespaceImports: {
@@ -374,6 +388,71 @@ declare function emptyComponentFacts(file: string): ComponentFacts;
374
388
  */
375
389
  declare function collectComponentFacts(rt: Runtime, cwd: string): Promise<ComponentFacts[]>;
376
390
  //#endregion
391
+ //#region src/head.d.ts
392
+ /**
393
+ * A normalized head tag. The mode-independent boundary (design §8): the static
394
+ * SourceHeadProvider (CLI, via the runtime-abstracted `HeadProvider` below) and
395
+ * the rendered collector (`@svelte-vitals/vite`, build-time Node) both emit
396
+ * these, so rules never need to know which mode produced them.
397
+ */
398
+ interface HeadTag {
399
+ kind: 'title' | 'meta' | 'link' | 'jsonld' | 'script';
400
+ /** <meta name="...">. */
401
+ name?: string;
402
+ /** <meta property="..."> (e.g. og:image). */
403
+ property?: string;
404
+ /** <link rel="...">. */
405
+ rel?: string;
406
+ /** <link as="..."> keyword (e.g. 'font') when statically literal; undefined when absent or dynamically bound. */
407
+ as?: string;
408
+ /** True when a <link> has an `as` attribute at all (literal or dynamic). Distinguishes "no as" from "dynamic as". */
409
+ hasAs?: boolean;
410
+ /** True when a <link> has a `crossorigin` attribute (presence only; value is irrelevant to the checks). */
411
+ hasCrossorigin?: boolean;
412
+ /** True when a <meta name="robots"> literal content contains `noindex`/`none`. Undefined when dynamic or absent. */
413
+ noindex?: boolean;
414
+ /** Literal `<script type="application/ld+json">` content, set only when the script is static. Undefined when dynamic. */
415
+ jsonld?: string;
416
+ /** Literal visible text of a static <title> or <meta name="description"> content, set only when static. Undefined when dynamic. */
417
+ text?: string;
418
+ /** Literal `hreflang` of a `<link rel="alternate">` (e.g. 'en', 'en-US', 'x-default'). Undefined when dynamic/absent. */
419
+ hreflang?: string;
420
+ /** Literal href (link) / src (script) URL when static — used for third-party origin analysis (performance/preconnect). */
421
+ href?: string;
422
+ /** True for a render-blocking `<script src>` in <head> (no defer/async/module) (performance/render-blocking-script). */
423
+ blocking?: boolean;
424
+ /** Rendered only in the browser, by a component loaded with `import()` (static mode): absent from a server-rendered route's HTML. */
425
+ clientOnly?: true;
426
+ /** Where this tag was set relative to the route. Never 'none' (absence = no tag). */
427
+ presence: Exclude<Presence, 'none'>;
428
+ /** Whether the tag's value is static/dynamic/absent (design §4). */
429
+ value: Value;
430
+ /** Source file the tag came from (static mode); unset on a rendered head. */
431
+ file?: string;
432
+ }
433
+ /** Whether a `<link>`'s `rel` holds `token`: `rel` is a set of space-separated keywords (`dns-prefetch preconnect`). */
434
+ declare function hasRel(tag: {
435
+ rel?: string;
436
+ }, token: string): boolean;
437
+ /** Resolved effective head for a single route (design §8). */
438
+ interface ResolvedHead {
439
+ /** Route path, e.g. '/blog/[slug]'. */
440
+ route: string;
441
+ /** Which provider produced this. */
442
+ source: 'static' | 'rendered';
443
+ /** Effective head tags after layout-chain composition. */
444
+ tags: HeadTag[];
445
+ /** Representative source file for the route (used for issue locations). */
446
+ file: string;
447
+ }
448
+ /**
449
+ * Whether a `type` attribute (undefined = absent) makes a `<script>` a classic,
450
+ * render-blocking-capable script. Per the HTML spec, absent and the literal empty string are
451
+ * classic; any other value is ASCII-whitespace-stripped and must match a JavaScript MIME type —
452
+ * so a whitespace-only `type` is a data block, not a classic script.
453
+ */
454
+ declare function isClassicScriptType(type: string | undefined): boolean;
455
+ //#endregion
377
456
  //#region src/types.d.ts
378
457
  type Severity = 'critical' | 'warning' | 'info';
379
458
  /** Where a head tag is set, relative to the route being evaluated (design §4). */
@@ -414,6 +493,13 @@ interface KitAlias {
414
493
  * is how Kit stops the plain key from swallowing the nested specifiers.
415
494
  */
416
495
  match: 'prefix' | 'contents' | 'exact';
496
+ /** Appended after the matched rest of a `contents` specifier: the text after `*` in an exports pattern target (`./src/*.js`). */
497
+ suffix?: string;
498
+ /**
499
+ * The directory the entry's targets belong to, when it is wider than `replacement`: a workspace
500
+ * package's directory, so relative imports between its files resolve above the project root.
501
+ */
502
+ root?: string;
417
503
  }
418
504
  /** Project-wide facts precomputed by the runtime layer for project-scope rules (design §10). */
419
505
  interface Project {
@@ -447,6 +533,8 @@ interface Project {
447
533
  value?: string;
448
534
  file: string;
449
535
  };
536
+ /** `kit.router.type: 'hash'` in `svelte.config.{js,ts}`: SvelteKit then never server-renders or prerenders a page. */
537
+ kitHashRouter?: true;
450
538
  /**
451
539
  * The project's compiled SvelteKit alias entries, in Kit's own order (`$lib` first), read from
452
540
  * `svelte.config.{js,ts}`. Absent means no config was read — resolution then falls back to
@@ -454,6 +542,18 @@ interface Project {
454
542
  * list is never empty: `$lib` is always prepended.
455
543
  */
456
544
  kitAliases?: KitAlias[];
545
+ /**
546
+ * `kitAliases` plus the workspace packages the app's package.json declares, which component
547
+ * resolution (a route's composition, and each-key's imported lists) follows. Absent when the app
548
+ * declares none. Rules that resolve imports read `kitAliases`.
549
+ */
550
+ componentAliases?: KitAlias[];
551
+ /**
552
+ * `componentAliases` (else `kitAliases`) plus the Svelte packages installed in `node_modules` that
553
+ * the app declares. Only the `<head>`/heading walk reads it, so the a11y composition and each-key
554
+ * stay on `componentAliases`. Absent when no such package is installed.
555
+ */
556
+ headAliases?: KitAlias[];
457
557
  /**
458
558
  * Whether `src/app.html` opens with `<!doctype html>` (a11y/doctype). Set from the same read
459
559
  * as `htmlLang`; absent when the file wasn't read (missing or unreadable) — the rule stays
@@ -467,6 +567,13 @@ interface Project {
467
567
  }[];
468
568
  /** Distinct lowercased tag names inside `app.html`'s `<body>` (a11y/required-element's presence set; static mode). */
469
569
  appHtmlBodyTags?: string[];
570
+ /**
571
+ * The shell's own literal `<title>`, `<meta name|property>` (except charset/viewport) and
572
+ * `<link rel="canonical">`, rendered on every route beside `%sveltekit.head%` (static mode).
573
+ */
574
+ appHtmlHeadTags?: Omit<HeadTag, 'presence' | 'file'>[];
575
+ /** HTML comments inside the shell's `<head>` (`<!--seo-head-->`), which a `transformPageChunk` hook may replace with tags. */
576
+ appHtmlHeadComments?: string[];
470
577
  }
471
578
  declare const defaultProject: Project;
472
579
  /** A concrete, agent-actionable remediation for a finding (design §10, issue #18). */
@@ -601,65 +708,6 @@ declare function formatMarkdownReport(results: Result[], config: Config, meta: {
601
708
  version: string;
602
709
  }): string;
603
710
  //#endregion
604
- //#region src/head.d.ts
605
- /**
606
- * A normalized head tag. The mode-independent boundary (design §8): the static
607
- * SourceHeadProvider (CLI, via the runtime-abstracted `HeadProvider` below) and
608
- * the rendered collector (`@svelte-vitals/vite`, build-time Node) both emit
609
- * these, so rules never need to know which mode produced them.
610
- */
611
- interface HeadTag {
612
- kind: 'title' | 'meta' | 'link' | 'jsonld' | 'script';
613
- /** <meta name="...">. */
614
- name?: string;
615
- /** <meta property="..."> (e.g. og:image). */
616
- property?: string;
617
- /** <link rel="...">. */
618
- rel?: string;
619
- /** <link as="..."> keyword (e.g. 'font') when statically literal; undefined when absent or dynamically bound. */
620
- as?: string;
621
- /** True when a <link> has an `as` attribute at all (literal or dynamic). Distinguishes "no as" from "dynamic as". */
622
- hasAs?: boolean;
623
- /** True when a <link> has a `crossorigin` attribute (presence only; value is irrelevant to the checks). */
624
- hasCrossorigin?: boolean;
625
- /** True when a <meta name="robots"> literal content contains `noindex`/`none`. Undefined when dynamic or absent. */
626
- noindex?: boolean;
627
- /** Literal `<script type="application/ld+json">` content, set only when the script is static. Undefined when dynamic. */
628
- jsonld?: string;
629
- /** Literal visible text of a static <title> or <meta name="description"> content, set only when static. Undefined when dynamic. */
630
- text?: string;
631
- /** Literal `hreflang` of a `<link rel="alternate">` (e.g. 'en', 'en-US', 'x-default'). Undefined when dynamic/absent. */
632
- hreflang?: string;
633
- /** Literal href (link) / src (script) URL when static — used for third-party origin analysis (performance/preconnect). */
634
- href?: string;
635
- /** True for a render-blocking `<script src>` in <head> (no defer/async/module) (performance/render-blocking-script). */
636
- blocking?: boolean;
637
- /** Where this tag was set relative to the route. Never 'none' (absence = no tag). */
638
- presence: Exclude<Presence, 'none'>;
639
- /** Whether the tag's value is static/dynamic/absent (design §4). */
640
- value: Value;
641
- /** Source file the tag came from (static mode); unset on a rendered head. */
642
- file?: string;
643
- }
644
- /** Resolved effective head for a single route (design §8). */
645
- interface ResolvedHead {
646
- /** Route path, e.g. '/blog/[slug]'. */
647
- route: string;
648
- /** Which provider produced this. */
649
- source: 'static' | 'rendered';
650
- /** Effective head tags after layout-chain composition. */
651
- tags: HeadTag[];
652
- /** Representative source file for the route (used for issue locations). */
653
- file: string;
654
- }
655
- /**
656
- * Whether a `type` attribute (undefined = absent) makes a `<script>` a classic,
657
- * render-blocking-capable script. Per the HTML spec, absent and the literal empty string are
658
- * classic; any other value is ASCII-whitespace-stripped and must match a JavaScript MIME type —
659
- * so a whitespace-only `type` is a data block, not a classic script.
660
- */
661
- declare function isClassicScriptType(type: string | undefined): boolean;
662
- //#endregion
663
711
  //#region src/images.d.ts
664
712
  /**
665
713
  * A normalized <img> occurrence — the mode-independent boundary for Performance
@@ -674,52 +722,23 @@ interface ImageInfo {
674
722
  hasAlt: boolean;
675
723
  /** True when the <img> has a literal `loading="lazy"` (performance/lcp-image). Dynamic/spread → false. */
676
724
  lazy: boolean;
677
- /** True when the <img> has a `srcset` attribute (performance/responsive-image). */
725
+ /** True when the <img>, or a `<source>` of its `<picture>`, has a `srcset` attribute (performance/responsive-image). */
678
726
  hasSrcset: boolean;
727
+ /** True when the <img>'s src is known to be an SVG (`isSvgSrc`; performance/responsive-image). */
728
+ svg?: boolean;
679
729
  /** 1-based source line, or 0 if unknown. */
680
730
  line: number;
681
731
  /** Source file the <img> came from. */
682
732
  file: string;
683
733
  }
734
+ /** A `.svg` path (query and fragment ignored) or an inline `data:image/svg+xml` URI. */
735
+ declare function isSvgSrc(src: string): boolean;
684
736
  /** Resolved <img> elements for a single route (page + layout chain). */
685
737
  interface ResolvedImages {
686
738
  route: string;
687
739
  images: ImageInfo[];
688
740
  }
689
741
  //#endregion
690
- //#region src/headings.d.ts
691
- /**
692
- * A normalized page-body heading occurrence — the mode-independent boundary for
693
- * the heading-hierarchy rule (mirrors images.ts). Both providers collect these
694
- * so seo/single-h1 never needs to know which mode produced them.
695
- */
696
- interface HeadingInfo {
697
- /** Heading level 1–6 (the `n` in <hn>). */
698
- level: number;
699
- /** 1-based source line, or 0 if unknown (rendered mode does not track lines). */
700
- line: number;
701
- /** Source file the heading came from. */
702
- file: string;
703
- }
704
- /** Resolved page-body headings for a single route (page + layout chain). */
705
- interface ResolvedHeadings {
706
- route: string;
707
- headings: HeadingInfo[];
708
- /**
709
- * Headings found in child components rendered (transitively) by this route's
710
- * chain files — source mode only; absent in rendered mode. Kept separate from
711
- * `headings` because their position in document order is unknown: safe for
712
- * counting (seo/single-h1), unusable for outline order (seo/heading-level-skip).
713
- */
714
- componentHeadings?: HeadingInfo[];
715
- /**
716
- * This route renders a `<svelte:element>` that may be a heading whose level is not
717
- * statically determinable (`this={`h${n}`}`, an identifier, …) — source mode only.
718
- * Counting stays as-is; only the "no <h1> anywhere" claim becomes unsafe to make.
719
- */
720
- dynamicHeading?: boolean;
721
- }
722
- //#endregion
723
742
  //#region src/a11y.d.ts
724
743
  /** One step of a template branch address: which exclusive block, and which arm of it. */
725
744
  interface BranchStep {
@@ -727,6 +746,10 @@ interface BranchStep {
727
746
  group: number;
728
747
  /** branch index within the group (if: 0..n consequent→else; await: 0=pending,1=then,2=catch) */
729
748
  branch: number;
749
+ /** A heading renders here whichever arm is taken: every arm of the block has one, a prop the use passes decides the arm, or the place's own conditions select it. */
750
+ always?: true;
751
+ /** The body of an `{#each}` (headings only): it may render any number of times, or none. */
752
+ repeat?: true;
730
753
  }
731
754
  /** Where a folded occurrence sits, for the finding location. */
732
755
  interface A11yOccurrenceInfo {
@@ -871,6 +894,56 @@ declare function isTopFragment(id: string): boolean;
871
894
  */
872
895
  declare function stripTextDirective(fragment: string): string;
873
896
  //#endregion
897
+ //#region src/headings.d.ts
898
+ /**
899
+ * A normalized page-body heading occurrence — the mode-independent boundary for
900
+ * the heading-hierarchy rule (mirrors images.ts). Both providers collect these
901
+ * so seo/single-h1 never needs to know which mode produced them.
902
+ */
903
+ interface HeadingInfo {
904
+ /** Heading level: 1–6 (the `n` in <hn>), an ARIA heading's `aria-level`, or 0 when the source does not determine it (source mode). */
905
+ level: number;
906
+ /** 1-based source line, or 0 if unknown (rendered mode does not track lines). */
907
+ line: number;
908
+ /** Source file the heading came from. */
909
+ file: string;
910
+ /**
911
+ * The `{#if}`/`{#await}`/`<svelte:boundary>` arms it sits in (source mode; absent when
912
+ * unconditional), including those of the component usages and layout `{@render children()}`
913
+ * above it. Group numbers are route-wide: each file instance has its own range.
914
+ */
915
+ path?: BranchStep[];
916
+ /**
917
+ * Its place in document order (source mode): the source offset of each placement from the route's
918
+ * outermost file down — a layout's `{@render children()}`, a component's tag, a snippet's
919
+ * `{@render}` — and last its own. Compared element by element (`documentOrder`); rendered-mode
920
+ * headings carry none and arrive in order.
921
+ */
922
+ order?: number[];
923
+ /** A `role="heading"` element: it holds its outline level for seo/heading-level-skip, but is not an `<h1>` for seo/single-h1. */
924
+ aria?: true;
925
+ }
926
+ /** Resolved page-body headings for a single route (page + layout chain). */
927
+ interface ResolvedHeadings {
928
+ route: string;
929
+ headings: HeadingInfo[];
930
+ /**
931
+ * Headings found in child components rendered (transitively) by this route's
932
+ * chain files — source mode only; absent in rendered mode. Their `order` places
933
+ * them among `headings`.
934
+ */
935
+ componentHeadings?: HeadingInfo[];
936
+ /**
937
+ * This route may render a heading whose level is not statically determinable: a
938
+ * `<svelte:element>` (`this={`h${n}`}`, an identifier, …), or a component that cannot be
939
+ * followed but is given a literal `h1` element prop (`<Heading tag="h1">`) — source mode only.
940
+ * Counting stays as-is; only the "no <h1> anywhere" claim becomes unsafe to make.
941
+ */
942
+ dynamicHeading?: boolean;
943
+ /** `dynamicHeading`, but from a component loaded with `import()` — source-mode collection folds it in only on routes never server-rendered. */
944
+ clientOnlyHeading?: boolean;
945
+ }
946
+ //#endregion
874
947
  //#region src/kit-module.d.ts
875
948
  /**
876
949
  * Facts parsed from one SvelteKit route/hooks file for the SSR shared-state rules
@@ -912,6 +985,13 @@ interface KitModuleFacts {
912
985
  resolved: string;
913
986
  line: number;
914
987
  }[];
988
+ /** The targets of the `.set()`/`.update()` writes recorded in `importedStateWrites` from a handler, for the collector to drop those that reach a persistence client. */
989
+ storeWriteTargets?: {
990
+ name: string;
991
+ imported: string;
992
+ resolved: string;
993
+ line: number;
994
+ }[];
915
995
  /** Value imports whose specifier resolves to a repo-local `.svelte.ts`/`.svelte.js` runes module (security/shared-state-import). */
916
996
  runesModuleImports: {
917
997
  source: string;
@@ -925,7 +1005,7 @@ interface KitModuleFacts {
925
1005
  line: number;
926
1006
  inHandler: boolean;
927
1007
  }[];
928
- /** Browser-global reads in server-executed positions — top level, handler bodies, the `init` hook (correctness/server-browser-global). Empty when the file itself exports `ssr = false`. */
1008
+ /** Browser-global reads in server-executed positions — top level, handler bodies, the `init` hook (correctness/server-browser-global). Empty when the file itself exports a literal `ssr = false`. */
929
1009
  browserGlobalRefs: {
930
1010
  name: string;
931
1011
  line: number;
@@ -933,14 +1013,46 @@ interface KitModuleFacts {
933
1013
  }[];
934
1014
  /** Root-relative `redirect()` literals in this Kit module (correctness/base-path-navigation). */
935
1015
  basePathLinks: BasePathLinkFact[];
936
- /** Set when this file disables SSR via `export const ssr = false` (inline or same-file alias export) — the declaration's line (seo/ssr-disabled). */
1016
+ /** Set when this file disables SSR via `export const ssr = false` or `= dev` (inline or same-file alias export) — the declaration's line (seo/ssr-disabled). */
937
1017
  ssrDisabled?: {
938
1018
  line: number;
939
1019
  };
1020
+ /** Set when this file exports `ssr` as anything but a literal `false` (`true`, a computed value, a re-export) — it may turn SSR back on under a layout's `ssr = false` (see `appSsrDisabled`, `routeNeverSsr`). */
1021
+ ssrEnabled?: true;
1022
+ /** Set when this file exports `ssr` as the literal `true` (inline or same-file alias export); implies `ssrEnabled`. */
1023
+ ssrTrue?: true;
940
1024
  /** Set when this file disables client-side rendering via `export const csr = false` (inline or same-file alias export). With no client runtime, a universal load only runs during SSR — performance/load-waterfall's browser-waterfall premise doesn't hold. */
941
1025
  csrDisabled?: {
942
1026
  line: number;
943
1027
  };
1028
+ /** Set when this file exports `csr` as anything but `false` — it may turn CSR back on under a layout's `csr = false` (see `universalNeverCsr`). */
1029
+ csrEnabled?: true;
1030
+ /** Set when the exported `load` redirects or throws `error()` on every call — every path through its body reaches a `redirect()`/`error()` before any `return`, directly or through a same-file top-level function that always does (see `loadNeverRenders` in kit-module-parse.ts). A `+page` module carrying it means the route never renders its own page. */
1031
+ loadNeverRenders?: true;
1032
+ /** Set when the exported `load` redirects or errors on every call once `if (building)` (from `$app/environment`) is read false, as on every request; the page renders only if its route is prerendered (see `prerenderExported`). */
1033
+ loadNeverRendersOutsideBuild?: true;
1034
+ /** The module exports `prerender`, in any form. */
1035
+ prerenderExported?: true;
1036
+ /** The request paths the exported `handle` of a hooks file answers before calling `resolve` (see `handleAnsweredPaths` in kit-module-parse.ts): a route they cover never renders. */
1037
+ answeredPaths?: {
1038
+ op: 'eq' | 'starts';
1039
+ v: string;
1040
+ }[];
1041
+ /** The string literals a `transformPageChunk` the exported `handle` passes to `resolve` replaces in the page HTML (`html.replace('<!--seo-head-->', …)`). */
1042
+ pageChunkTokens?: string[];
1043
+ /** The imported flag a load's leading guard reads (`if (!FLAG) redirect(…)`): `collectKitModuleFacts` sets `loadNeverRenders` when that export is the literal `false`. */
1044
+ pendingFlagGuard?: {
1045
+ resolved: string;
1046
+ name: string;
1047
+ member?: string;
1048
+ };
1049
+ /** The imported factory `export const load = factory(…)` calls: `collectKitModuleFacts` sets `loadNeverRenders` when the function it returns redirects or errors on every call. */
1050
+ pendingLoadFactory?: {
1051
+ resolved: string;
1052
+ name: string;
1053
+ };
1054
+ /** Set when the exported `load` sends a request without a session away before rendering (see `loadGatesOnLocals` in kit-module-parse.ts); every route under a `+layout` carrying it is behind a login. */
1055
+ loadGated?: true;
944
1056
  /** Sequential-await analysis of the exported `load` function (performance/load-waterfall, performance/sequential-awaits): 1-based lines of await sites that depend on an earlier await's result, and of sites independent of all earlier awaits. Set only when at least one list is non-empty. */
945
1057
  loadWaterfalls?: {
946
1058
  dependentLines: number[];
@@ -953,6 +1065,25 @@ interface KitModuleFacts {
953
1065
  /** Set when the file could not be READ — an environment problem, not a malformed module. */
954
1066
  readFailed?: true;
955
1067
  }
1068
+ /** The rule-context fields the per-route SSR resolution reads. */
1069
+ type SsrScope = Pick<RuleContext, 'kitModules' | 'components' | 'sourceFiles'> & {
1070
+ project?: Pick<Project, 'kitHashRouter'>;
1071
+ };
1072
+ /**
1073
+ * Whether a `+page` file's route never renders because a layout above it redirects or errors in its
1074
+ * `load` on every call (`loadNeverRenders`). Not the root layout: one that sent every request away
1075
+ * would leave the app nothing to serve, so that reading is more likely wrong than the app, and acting
1076
+ * on it would silence every route.
1077
+ */
1078
+ declare function layoutNeverRenders(file: string, scope: SsrScope): boolean;
1079
+ /**
1080
+ * Whether a `+page` file's route never renders because its own `load` redirects or errors on every
1081
+ * request, a build-time `if (building)` aside (`loadNeverRendersOutsideBuild`), and nothing on its chain
1082
+ * exports `prerender`, so the build never renders it either.
1083
+ */
1084
+ declare function pageRendersOnlyWhenBuilding(file: string, scope: SsrScope): boolean;
1085
+ /** Whether a `+page`/`+layout` file (module or component) belongs to a route that is never server-rendered. */
1086
+ declare function routeNeverSsr(file: string, scope: SsrScope): boolean;
956
1087
  //#endregion
957
1088
  //#region src/config-apply.d.ts
958
1089
  /** The severity a setting selects: `'off'`, an explicit severity, or undefined (leave the built-in). */
@@ -1282,8 +1413,13 @@ declare function buildJsonReport(results: Result[], config: Config, meta: {
1282
1413
  version: string;
1283
1414
  }, ruleIds?: readonly string[], examined?: Record<string, Record<string, number>>, skipped?: JsonReport['skipped']): JsonReport;
1284
1415
  /** Render results as the documented JSON report string (design §7). */
1285
- declare function formatJsonReport(results: Result[], config: Config, meta: {
1416
+ declare function formatJsonReport(...args: Parameters<typeof formatJsonReportChunks>): string;
1417
+ /**
1418
+ * `formatJsonReport`'s text in pieces, one route at a time: a large prerendered site's report is
1419
+ * longer than the longest string V8 can hold.
1420
+ */
1421
+ declare function formatJsonReportChunks(results: Result[], config: Config, meta: {
1286
1422
  version: string;
1287
- }, ruleIds?: readonly string[], examined?: Record<string, Record<string, number>>, skipped?: JsonReport['skipped']): string;
1423
+ }, ruleIds?: readonly string[], examined?: Record<string, Record<string, number>>, skipped?: JsonReport['skipped']): Generator<string>;
1288
1424
  //#endregion
1289
- export { formatMarkdownReport as $, A11yOccurrenceInfo as A, OrphanEffectFact as At, decodeFragmentId as B, compileOverrides as C, Value as Ct, withFailedRulesOff as D, ComponentFacts as Dt, settingSeverity as E, defineConfig as Et, IDREF_ATTRS as F, skippedFileWarnings as Ft, stripTextDirective as G, isTopFragment as H, LandmarkInput as I, Runtime as It, ImageInfo as J, HeadingInfo as K, NAMING_ATTRS as L, withReadLimit as Lt, ANCESTRY_DEPENDENT_TAGS as M, SuppressionDirective as Mt, ASIDE_DEMOTING_TAGS as N, collectComponentFacts as Nt, withIndexableOff as O, EachBlockFact as Ot, BranchStep as P, emptyComponentFacts as Pt, isClassicScriptType as Q, ResolvedA11y as R, SEARCH_RESULT_RULES as S, TreatDynamicAs as St, selectRules as T, defaultProject as Tt, resolveLandmark as U, foldOccurrences as V, splitTokens as W, HeadTag as X, ResolvedImages as Y, ResolvedHead as Z, isPlainObject as _, RuleOverride as _t, HealthResult as a, hasFailureAtOrAbove as at, validateRuleSetting as b, Scope as bt, ScoreResult as c, Category as ct, Rule as d, Fix as dt, formatGithubReport as et, RuleContext as f, KitAlias as ft, RuleOptionsSpec as g, RuleOptions as gt, RuleOptionSpec as h, Result as ht, formatJsonReport as i, effectiveSeverity as it, A11ySkipCause as j, SourceSpan as jt, KitModuleFacts as k, EffectFact as kt, computeHealth as l, Config as lt, isPenalized as m, Project as mt, RuleEvidence as n, Summary as nt, ScoreModel as o, summarize as ot, docsUrlFor as p, Presence as pt, ResolvedHeadings as q, buildJsonReport as r, classify as rt, ScoreOptions as s, CATEGORIES as st, JsonReport as t, Classification as tt, computeScore as u, Detection as ut, resolveRuleOptions as v, RuleSetting as vt, formatFailedRuleWarning as w, defaultConfig as wt, CompiledOverride as x, Severity as xt, shouldSkipRangeCheck as y, RuleSettingObject as yt, SECTIONING_TAGS as z };
1425
+ export { ResolvedImages as $, KitModuleFacts as A, ResolvedHead as At, BranchStep as B, emptyComponentFacts as Bt, SEARCH_RESULT_RULES as C, Severity as Ct, settingSeverity as D, defaultProject as Dt, selectRules as E, defaultConfig as Et, ResolvedHeadings as F, EffectFact as Ft, SECTIONING_TAGS as G, LandmarkInput as H, Runtime as Ht, A11yOccurrenceInfo as I, OrphanEffectFact as It, isTopFragment as J, decodeFragmentId as K, A11ySkipCause as L, SourceSpan as Lt, pageRendersOnlyWhenBuilding as M, isClassicScriptType as Mt, routeNeverSsr as N, ComponentFacts as Nt, withFailedRulesOff as O, defineConfig as Ot, HeadingInfo as P, EachBlockFact as Pt, ImageInfo as Q, ANCESTRY_DEPENDENT_TAGS as R, SuppressionDirective as Rt, CompiledOverride as S, Scope as St, formatFailedRuleWarning as T, Value as Tt, NAMING_ATTRS as U, withReadLimit as Ut, IDREF_ATTRS as V, skippedFileWarnings as Vt, ResolvedA11y as W, splitTokens as X, resolveLandmark as Y, stripTextDirective as Z, RuleOptionsSpec as _, Result as _t, formatJsonReportChunks as a, classify as at, shouldSkipRangeCheck as b, RuleSetting as bt, ScoreOptions as c, summarize as ct, computeScore as d, Config as dt, isSvgSrc as et, Rule as f, Detection as ft, RuleOptionSpec as g, Project as gt, isPenalized as h, Presence as ht, formatJsonReport as i, Summary as it, layoutNeverRenders as j, hasRel as jt, withIndexableOff as k, HeadTag as kt, ScoreResult as l, CATEGORIES as lt, docsUrlFor as m, KitAlias as mt, RuleEvidence as n, formatGithubReport as nt, HealthResult as o, effectiveSeverity as ot, RuleContext as p, Fix as pt, foldOccurrences as q, buildJsonReport as r, Classification as rt, ScoreModel as s, hasFailureAtOrAbove as st, JsonReport as t, formatMarkdownReport as tt, computeHealth as u, Category as ut, isPlainObject as v, RuleOptions as vt, compileOverrides as w, TreatDynamicAs as wt, validateRuleSetting as x, RuleSettingObject as xt, resolveRuleOptions as y, RuleOverride as yt, ASIDE_DEMOTING_TAGS as z, collectComponentFacts as zt };