@svelte-vitals/core 0.55.2 → 0.55.4

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/internal.js CHANGED
@@ -1,44 +1,10 @@
1
- import { $ as performanceMinifyDisabled, $n as applyRuleSeverities, $t as correctnessOrphanLifecycle, A as a11yAbbrTitle, An as seoImageAlt, Ar as defaultProject, At as walkEstree, B as a11yUseList, Bn as seoSitemapInRobots, Bt as parseSvelte, C as a11yDisallowedElement, Cn as foldOccurrences, Cr as effectiveSeverity, Ct as collectSvelteLifecycleImports, D as a11yDeprecatedElement, Dn as stripTextDirective, Dr as isPenalized, Dt as scopeIntroducedNames, E as a11yDeprecatedAttr, En as splitTokens, Er as docsUrlFor, Et as rootObjectName, F as isInteractiveContainer, Fn as seoJsonLdPlaceholder, Ft as attrTextOf, G as a11yInvalidAriaValue, Gn as seoIndexability, Gt as securitySharedStateImport, H as a11yAccessibleName, Hn as seoOgUrl, Ht as valueFromNodes, I as isInteractiveElement, In as seoJsonLdDateFormat, It as attrValue, J as a11yInvalidRole, Jn as resolveRuleOptions, Jt as securityJavascriptUrl, K as a11yRequiredAriaProps, Kn as performancePreconnect, Kt as securityServerModuleState, L as literalTabindexValue, Ln as seoJsonLdRelativeUrl, Lt as attrValueOf, M as a11yNoAutofocus, Mn as seoDescriptionLength, Mt as walkScoped, N as a11yNoAccesskey, Nn as seoTitleLength, Nt as CHILD_NODE_KEYS, O as HTML_SPEC, On as resolveRole, Ot as unwrapExport, P as a11yPositiveTabindex, Pn as seoJsonLdRequiredProps, Pt as attrText, Q as performanceLoadWaterfall, Qn as applyOverrides, Qt as correctnessBasePathNavigation, R as a11yRequireDatetime, Rn as seoJsonLdDeprecatedType, Rt as findAttr, S as a11yPermittedContents, Sn as decodeFragmentId, Sr as classify, St as collectSuppressions, T as a11yDisallowedAriaProps, Tn as resolveLandmark, Tr as summarize, Tt as parseModuleProgram, U as a11yAriaHiddenFocus, Un as seoOgDescription, Ut as architecturePropCount, V as a11yLabelHasControl, Vn as seoViewport, Vt as textFromNodes, W as a11yInteractiveNesting, Wn as seoTwitterCard, Wt as architectureComponentSize, X as performanceStateRaw, Xn as validateRuleSetting, Xt as correctnessInstanceBrowserGlobal, Y as performanceIframeLoading, Yn as shouldSkipRangeCheck, Yt as securityRawHtml, Z as performanceSequentialAwaits, Zn as SEARCH_RESULT_RULES, Zt as correctnessServerBrowserGlobal, _ as a11yIdDuplication, _n as ANCESTRY_DEPENDENT_TAGS, _r as seoOgTitle, _t as collectBrowserGlobalRefs, a as formatJsonReport, an as correctnessPropMutation, ar as withIndexableOff, at as architectureReservedDirectoryNames, b as a11yDoctype, bn as NAMING_ATTRS, br as seoDescriptionPresence, bt as collectNamedImportAliases, c as formatGithubReport, cn as correctnessEffectAsDerived, cr as performanceFontPreloadCrossorigin, ct as architecturePrivateScopeImport, d as ruleMetaById, dn as seoSsrDisabled, dr as performanceImageLoadingHint, dt as parseInMemoryExports, en as correctnessOrphanEffect, er as compileOverrides, et as performanceNamespaceImport, f as severityToSarifLevel, fn as routeNeverSsr, fr as performanceImageDimensions, ft as parseKitModuleFacts, g as a11yNoMissingIdRef, gn as seoSingleH1, gr as seoJsonLd, gt as addBoundNames, h as a11yUnverifiedIdRef, hn as seoDuplicateTitle, hr as seoRobotsTxt, ht as WALK_IGNORED_KEYS, i as buildJsonReport, in as correctnessStalePropDerivation, ir as withFailedRulesOff, it as architectureReservedNamePlacement, j as a11yNoDuplicateDt, jn as seoCharset, jt as walkEvalScope, k as a11yPatternTitle, kn as seoHreflang, kr as defaultConfig, kt as unwrapTs, l as SEVERITY_RANK, ln as correctnessEachIndexKey, lr as performancePreloadMissingAs, lt as DEFAULT_KIT_ALIASES, m as explainRule, mn as seoDuplicateDescription, mr as seoSitemapXml, mt as isRootRelativePath, n as mdEscape, nn as correctnessCheckableBindValue, nr as selectRules, nt as architectureDocLinkTarget, o as computeHealth, on as correctnessUnmutatedState, or as performanceRenderBlockingScript, ot as architectureDirectoryNaming, p as allRules, pn as seoHeadingLevelSkip, pr as seoHtmlLang, pt as resolveRepoLocalPath, q as a11yUnknownAriaAttribute, qn as isPlainObject, qt as securityHandlerStateWrite, r as terminalSafe, rn as correctnessNonreactiveBuiltinState, rr as settingSeverity, rt as architectureRouteComponentImport, s as computeScore, sn as correctnessEffectAsOnMount, sr as performanceLcpImage, st as architectureUnitEntryFile, t as formatMarkdownReport, tn as correctnessAutoplayMuted, tr as formatFailedRuleWarning, tt as performanceHeavyImport, u as messageText, un as correctnessEachKey, ur as performanceResponsiveImage, ut as collectTopLevelBindings, v as a11yTopLevelLandmark, vn as ASIDE_DEMOTING_TAGS, vr as seoOgImage, vt as collectBrowserGuardImports, w as a11yDeprecatedAria, wn as isTopFragment, wr as hasFailureAtOrAbove, wt as matchLifecycleCall, x as a11yRequiredElement, xn as SECTIONING_TAGS, xr as seoTitlePresence, xt as collectProgramBindings, y as a11yDuplicateLandmark, yn as IDREF_ATTRS, yr as seoCanonicalUrl, yt as collectDerivedGuardBindings, z as a11yPlaceholderLabelOption, zn as seoJsonLdValidity, zt as lineOf } from "./markdown-DgHBAvYl.js";
2
- //#region src/head.ts
3
- const JS_MIME_TYPES = /* @__PURE__ */ new Set([
4
- "application/ecmascript",
5
- "application/javascript",
6
- "application/x-ecmascript",
7
- "application/x-javascript",
8
- "text/ecmascript",
9
- "text/javascript",
10
- "text/javascript1.0",
11
- "text/javascript1.1",
12
- "text/javascript1.2",
13
- "text/javascript1.3",
14
- "text/javascript1.4",
15
- "text/javascript1.5",
16
- "text/jscript",
17
- "text/livescript",
18
- "text/x-ecmascript",
19
- "text/x-javascript"
20
- ]);
21
- /** HTML strips only ASCII whitespace from a `type` before matching — `trim()` would also strip
22
- * U+00A0 etc. and misread a data block as a classic script. */
23
- const ASCII_WHITESPACE_EDGES = /^[\t\n\f\r ]+|[\t\n\f\r ]+$/g;
24
- /**
25
- * Whether a `type` attribute (undefined = absent) makes a `<script>` a classic,
26
- * render-blocking-capable script. Per the HTML spec, absent and the literal empty string are
27
- * classic; any other value is ASCII-whitespace-stripped and must match a JavaScript MIME type —
28
- * so a whitespace-only `type` is a data block, not a classic script.
29
- */
30
- function isClassicScriptType(type) {
31
- if (type === void 0 || type === "") return true;
32
- return JS_MIME_TYPES.has(type.replace(ASCII_WHITESPACE_EDGES, "").toLowerCase());
33
- }
34
- //#endregion
35
- //#region src/images.ts
1
+ import { $ as performanceLoadWaterfall, $n as shouldSkipRangeCheck, $t as securityJavascriptUrl, A as a11yPatternTitle, An as splitTokens, Ar as seoTitlePresence, At as parseModuleProgram, B as a11yPlaceholderLabelOption, Bn as seoJsonLdDateFormat, Bt as attrTextOf, C as a11yPermittedContents, Cn as IDREF_ATTRS, Cr as seoCanonicalUrl, Ct as collectBrowserGuardImports, D as a11yDeprecatedAttr, Dn as foldOccurrences, Dr as layoutNeverRenders, Dt as collectSuppressions, E as a11yDisallowedAriaProps, En as decodeFragmentId, Er as seoDescriptionPresence, Et as collectProgramBindings, F as a11yPositiveTabindex, Fn as seoCharset, Fr as docsUrlFor, Ft as walkEstree, G as a11yInteractiveNesting, Gn as seoViewport, Gt as parseSvelte, H as a11yLabelHasControl, Hn as seoJsonLdDeprecatedType, Ht as attrValueOf, I as isInteractiveContainer, In as seoDescriptionLength, Ir as isPenalized, It as walkEvalScope, J as a11yUnknownAriaAttribute, Jn as seoTwitterCard, Jt as architecturePropCount, K as a11yInvalidAriaValue, Kn as seoOgUrl, Kt as textFromNodes, L as isInteractiveElement, Ln as seoTitleLength, Lt as walkScoped, M as a11yNoDuplicateDt, Mn as resolveRole, Mr as effectiveSeverity, Mt as scopeIntroducedNames, N as a11yNoAutofocus, Nn as seoHreflang, Nr as hasFailureAtOrAbove, Nt as unwrapExport, O as a11yDeprecatedElement, On as isTopFragment, Or as pageRendersOnlyWhenBuilding, Ot as collectSvelteLifecycleImports, P as a11yNoAccesskey, Pn as seoImageAlt, Pr as summarize, Pt as unwrapTs, Q as performanceSequentialAwaits, Qn as resolveRuleOptions, Qt as securityHandlerStateWrite, R as literalTabindexValue, Rn as seoJsonLdRequiredProps, Rr as defaultConfig, Rt as CHILD_NODE_KEYS, S as a11yRequiredElement, Sn as ASIDE_DEMOTING_TAGS, Sr as seoOgImage, St as collectBrowserGlobalRefs, T as a11yDeprecatedAria, Tn as SECTIONING_TAGS, Tr as isClassicScriptType, Tt as collectNamedImportAliases, U as a11yAccessibleName, Un as seoJsonLdValidity, Ut as findAttr, V as a11yUseList, Vn as seoJsonLdRelativeUrl, Vt as attrValue, W as a11yAriaHiddenFocus, Wn as seoSitemapInRobots, Wt as lineOf, X as performanceIframeLoading, Xn as performancePreconnect, Xt as securitySharedStateImport, Y as a11yInvalidRole, Yn as seoIndexability, Yt as architectureComponentSize, Z as performanceStateRaw, Zn as isPlainObject, Zt as securityServerModuleState, _ as a11yNoMissingIdRef, _n as seoHeadingLevelSkip, _r as seoHtmlLang, _t as parseKitModuleFacts, a as formatJsonReport, an as correctnessOrphanEffect, ar as formatFailedRuleWarning, at as architectureReservedNamePlacement, b as a11yDuplicateLandmark, bn as seoSingleH1, br as seoJsonLd, bt as WALK_IGNORED_KEYS, c as computeScore, cn as correctnessNonreactiveBuiltinState, cr as withFailedRulesOff, ct as architectureUnitEntryFile, d as messageText, dn as correctnessUnmutatedState, dr as performanceLcpImage, dt as collectFalseExports, en as securityRawHtml, er as validateRuleSetting, et as performanceMinifyDisabled, f as ruleMetaById, fn as correctnessEffectAsOnMount, fr as performanceFontPreloadCrossorigin, ft as collectTopLevelBindings, g as a11yUnverifiedIdRef, gn as seoSsrDisabled, gr as performanceImageDimensions, gt as parseInMemoryExports, h as explainRule, hn as correctnessEachKey, hr as performanceImageLoadingHint, ht as parseFalseExports, i as buildJsonReport, in as correctnessOrphanLifecycle, ir as compileOverrides, it as architectureRouteComponentImport, j as a11yAbbrTitle, jn as stripTextDirective, jr as classify, jt as rootObjectName, k as HTML_SPEC, kn as resolveLandmark, kr as routeNeverSsr, kt as matchLifecycleCall, l as formatGithubReport, ln as correctnessStalePropDerivation, lr as withIndexableOff, lt as architecturePrivateScopeImport, m as allRules, mn as correctnessEachIndexKey, mr as performanceResponsiveImage, mt as parseExitFactoryExports, n as mdEscape, nn as correctnessServerBrowserGlobal, nr as applyOverrides, nt as performanceHeavyImport, o as formatJsonReportChunks, on as correctnessAutoplayMuted, or as selectRules, ot as architectureReservedDirectoryNames, p as severityToSarifLevel, pn as correctnessEffectAsDerived, pr as performancePreloadMissingAs, pt as parseClientExports, q as a11yRequiredAriaProps, qn as seoOgDescription, qt as valueFromNodes, r as terminalSafe, rn as correctnessBasePathNavigation, rr as applyRuleSeverities, rt as architectureDocLinkTarget, s as computeHealth, sn as correctnessCheckableBindValue, sr as settingSeverity, st as architectureDirectoryNaming, t as formatMarkdownReport, tn as correctnessInstanceBrowserGlobal, tr as SEARCH_RESULT_RULES, tt as performanceNamespaceImport, u as SEVERITY_RANK, un as correctnessPropMutation, ur as performanceRenderBlockingScript, ut as DEFAULT_KIT_ALIASES, v as a11yIdDuplication, vn as seoDuplicateDescription, vr as seoSitemapXml, vt as resolveRepoLocalPath, w as a11yDisallowedElement, wn as NAMING_ATTRS, wr as hasRel, wt as collectDerivedGuardBindings, x as a11yDoctype, xn as ANCESTRY_DEPENDENT_TAGS, xr as seoOgTitle, xt as addBoundNames, y as a11yTopLevelLandmark, yn as seoDuplicateTitle, yr as seoRobotsTxt, yt as isRootRelativePath, z as a11yRequireDatetime, zn as seoJsonLdPlaceholder, zr as defaultProject, zt as attrText } from "./markdown-YuU0EwLR.js";
2
+ // src/images.ts
36
3
  /** A `.svg` path (query and fragment ignored) or an inline `data:image/svg+xml` URI. */
37
4
  function isSvgSrc(src) {
38
5
  return /^data:image\/svg\+xml[;,]/i.test(src) || /\.svg$/i.test(src.split(/[?#]/, 1)[0]);
39
6
  }
40
- //#endregion
41
- //#region src/component-parse.ts
7
+ // src/component-parse.ts
42
8
  const KNOWN_TAGS = new Set(Object.keys(HTML_SPEC.elements).map((k) => k.replace(/^svg:/, "").toLowerCase()));
43
9
  /**
44
10
  * Whether `expr` is a length-only list constructor: `Array(n)` / `new Array(n)` (single argument =
@@ -161,21 +127,46 @@ function collectConstantLists(programs, fragment, opts = {}) {
161
127
  const stmt = opts.exported ? unwrapExport(top) : top;
162
128
  if (stmt?.type !== "VariableDeclaration" || stmt.kind !== "const") continue;
163
129
  for (const d of stmt.declarations ?? []) {
164
- const init = unwrapTs(d?.init);
130
+ const init = opts.sets ? setLiteralList(unwrapTs(d?.init)) : unwrapTs(d?.init);
165
131
  if (d?.id?.type === "Identifier" && init?.type === "ArrayExpression") {
166
132
  if (!(init.elements ?? []).some((el) => el?.type === "SpreadElement")) candidates.set(d.id.name, d.id);
167
133
  }
168
134
  }
169
135
  }
170
136
  if (candidates.size === 0) return /* @__PURE__ */ new Set();
137
+ const aliases = /* @__PURE__ */ new Map();
138
+ if (opts.exported) for (const program of programs) walkEstree(program, (n) => {
139
+ if (n.type !== "VariableDeclaration" || n.kind !== "const") return;
140
+ for (const d of n.declarations ?? []) {
141
+ const init = unwrapTs(d?.init);
142
+ const list = (init?.type === "ConditionalExpression" ? [init.consequent, init.alternate] : init?.type === "LogicalExpression" && init.operator !== "&&" ? [init.left, init.right] : [init]).map((b) => unwrapTs(b)).find((b) => b?.type === "Identifier" && candidates.has(b.name));
143
+ if (d?.id?.type !== "Identifier" || !list || candidates.has(d.id.name)) continue;
144
+ safe.add(list);
145
+ aliases.set(d.id.name, list.name);
146
+ candidates.set(d.id.name, d.id);
147
+ }
148
+ });
171
149
  for (const node of candidates.values()) safe.add(node);
172
150
  const namespaces = new Set([...opts.imports ?? []].filter(([, b]) => b.imported === "*").map(([local]) => local));
173
151
  const unsafe = /* @__PURE__ */ new Set();
174
152
  const roots = [...programs, fragment];
175
153
  const listOf = (n) => n?.type === "Identifier" && candidates.has(n.name) ? n.name : void 0;
154
+ const outerList = listOf;
176
155
  const nsMember = (n) => n?.type === "MemberExpression" && !n.computed && namespaces.has(listOf(n.object)) ? `${n.object.name}.${n.property.name}` : void 0;
156
+ const outerMember = nsMember;
177
157
  const members = /* @__PURE__ */ new Set();
178
- for (const root of roots) walkEstree(root, (n) => {
158
+ const declared = /* @__PURE__ */ new Set();
159
+ for (const program of programs) {
160
+ const imported = /* @__PURE__ */ new Set();
161
+ for (const top of program.body ?? []) if (top?.type === "ImportDeclaration") for (const s of top.specifiers ?? []) imported.add(s?.local?.name);
162
+ for (const name of collectProgramBindings(program)) if (!imported.has(name)) declared.add(name);
163
+ }
164
+ for (const root of roots) walkScoped(root, (n, shadowed) => {
165
+ const listOf = (x) => {
166
+ const name = outerList(x);
167
+ return name && !shadowed.has(name) ? name : void 0;
168
+ };
169
+ const nsMember = (x) => x?.type === "MemberExpression" && listOf(x.object) ? outerMember(x) : void 0;
179
170
  if (n.type === "EachBlock" && (listOf(n.expression) || nsMember(n.expression))) safe.add(n.expression);
180
171
  if (n.type === "ForOfStatement" && (listOf(n.right) || nsMember(n.right))) safe.add(n.right);
181
172
  if (n.type === "ArrayExpression") {
@@ -183,29 +174,46 @@ function collectConstantLists(programs, fragment, opts = {}) {
183
174
  }
184
175
  if (nsMember(n)) members.add(nsMember(n));
185
176
  if (n.type === "MemberExpression") {
186
- if (listOf(n.object) && !(n.computed && namespaces.has(n.object.name))) safe.add(n.object);
187
- if (nsMember(n.object)) safe.add(n.object);
177
+ const object = n.object ? unwrapTs(n.object) : n.object;
178
+ if (listOf(object) && !(n.computed && namespaces.has(object.name))) safe.add(object);
179
+ if (nsMember(object)) safe.add(object);
188
180
  if (!n.computed) safe.add(n.property);
189
181
  }
190
182
  const target = n.type === "AssignmentExpression" ? n.left : n.type === "UpdateExpression" ? n.argument : void 0;
191
- if (target?.type === "MemberExpression" && listOf(rootObjectNode(target))) unsafe.add(listOf(rootObjectNode(target)));
192
- const called = n.type === "CallExpression" && n.callee?.type === "MemberExpression" ? n.callee.object : void 0;
183
+ let root = target;
184
+ while (root && (root.type === "MemberExpression" || root.type.startsWith("TS"))) root = root.type === "MemberExpression" ? root.object : root.expression;
185
+ if (target?.type === "MemberExpression" && listOf(root)) unsafe.add(listOf(root));
186
+ const called = n.type === "CallExpression" && n.callee?.type === "MemberExpression" ? unwrapTs(n.callee.object) : void 0;
193
187
  const calledList = listOf(called) ?? nsMember(called);
194
188
  if (calledList) {
195
189
  const { computed, property } = n.callee;
196
190
  const method = !computed ? property?.name : property?.type === "Literal" && typeof property.value === "string" ? property.value : void 0;
197
191
  if (computed && method === void 0 || method !== void 0 && MUTATING_METHODS.has(method)) unsafe.add(calledList);
198
192
  }
193
+ const callee = n.type === "CallExpression" || n.type === "NewExpression" ? rootObjectName(n.callee) : void 0;
194
+ if (opts.exported && callee !== void 0 && !declared.has(callee) && !shadowed.has(callee)) {
195
+ for (const arg of n.arguments ?? []) if (listOf(unwrapTs(arg))) safe.add(unwrapTs(arg));
196
+ }
199
197
  if (n.type === "BindDirective" && listOf(rootObjectNode(n.expression))) unsafe.add(listOf(rootObjectNode(n.expression)));
200
198
  if (n.type === "Property" && !n.computed && !n.shorthand) safe.add(n.key);
201
199
  });
202
- for (const root of roots) walkEvalScope(root, (n) => {
200
+ for (const root of roots) walkEvalScope(root, (n, shadowed) => {
203
201
  if (n.type.startsWith("TS") && !TS_VALUE_NODES.has(n.type)) return true;
204
202
  const name = listOf(n) ?? nsMember(n);
205
- if (name && !safe.has(n)) unsafe.add(name);
203
+ if (name && !safe.has(n) && !shadowed.has(name.split(".")[0])) unsafe.add(name);
206
204
  return false;
207
205
  }, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
208
- return new Set([...candidates.keys(), ...members].filter((key) => !unsafe.has(key) && !unsafe.has(key.split(".")[0])));
206
+ for (const [alias, list] of aliases) if (unsafe.has(alias)) unsafe.add(list);
207
+ return new Set([...candidates.keys(), ...members].filter((key) => !aliases.has(key) && !unsafe.has(key) && !unsafe.has(key.split(".")[0])));
208
+ }
209
+ /** A component's script `const` lists that nothing in its scripts or template can change. */
210
+ function collectComponentConstantLists(ast, opts = {}) {
211
+ return collectConstantLists([ast.module?.content, ast.instance?.content].filter(Boolean), ast.fragment ?? ast, opts);
212
+ }
213
+ /** The array literal of `new Set([…])`, or the node itself. */
214
+ function setLiteralList(n) {
215
+ const arg = n?.type === "NewExpression" && n.callee?.type === "Identifier" && n.callee.name === "Set" ? n.arguments : void 0;
216
+ return arg?.length === 1 && unwrapTs(arg[0])?.type === "ArrayExpression" ? unwrapTs(arg[0]) : n;
209
217
  }
210
218
  /**
211
219
  * Export names of a module's constant lists — `export const X = [ … ]`, or a local one exported by
@@ -288,6 +296,14 @@ function isEffectRootCall(node) {
288
296
  * `$state.raw(...)`, or `$state.frozen(...)` — but NOT readers like
289
297
  * `$state.snapshot(...)`, which would otherwise pollute the state-name set (correctness/effect-as-derived).
290
298
  */
299
+ /** An absent argument or a literal no reader can write through: `0`, `'x'`, `null`, `-1`, `` `x` ``. */
300
+ function isPrimitiveLiteral(node) {
301
+ if (node === void 0) return true;
302
+ if (node.type === "Literal") return !("regex" in node);
303
+ if (node.type === "TemplateLiteral") return node.expressions.length === 0;
304
+ if (node.type === "UnaryExpression") return node.argument?.type === "Literal";
305
+ return node.type === "Identifier" && node.name === "undefined";
306
+ }
291
307
  function isStateDeclaration(node) {
292
308
  const c = node?.callee;
293
309
  if (c?.type === "Identifier") return c.name === "$state";
@@ -296,7 +312,18 @@ function isStateDeclaration(node) {
296
312
  }
297
313
  /** True when a function's body does nothing but assign to `$state` identifiers (correctness/effect-as-derived). */
298
314
  function bodyOnlyAssignsState(fn, stateNames) {
299
- const isStateAssign = (expr) => expr?.type === "AssignmentExpression" && expr.operator === "=" && expr.left?.type === "Identifier" && stateNames.has(expr.left.name);
315
+ const readsItself = (expr) => {
316
+ let reads = false;
317
+ const names = /* @__PURE__ */ new Set();
318
+ walkEstree(expr.right, (n) => {
319
+ if (n?.type === "MemberExpression" && !n.computed) names.add(n.property);
320
+ if (n?.type === "Property" && !n.computed && !n.shorthand) names.add(n.key);
321
+ if (n?.type === "TSTypeQuery") names.add(n.exprName);
322
+ reads ||= n?.type === "Identifier" && n.name === expr.left.name && !names.has(n);
323
+ });
324
+ return reads;
325
+ };
326
+ const isStateAssign = (expr) => expr?.type === "AssignmentExpression" && expr.operator === "=" && expr.left?.type === "Identifier" && stateNames.has(expr.left.name) && !readsItself(expr);
300
327
  const body = fn?.body;
301
328
  if (!body) return false;
302
329
  if (body.type !== "BlockStatement") return isStateAssign(body);
@@ -310,6 +337,36 @@ function isDerivedDeclaration(node) {
310
337
  if (c?.type === "MemberExpression" && c.object?.type === "Identifier" && c.object.name === "$derived") return c.property?.type === "Identifier" && c.property.name === "by";
311
338
  return false;
312
339
  }
340
+ const OBJECT_TYPES = /* @__PURE__ */ new Set([
341
+ "TSArrayType",
342
+ "TSTupleType",
343
+ "TSTypeLiteral"
344
+ ]);
345
+ const OBJECT_TYPE_NAMES = /* @__PURE__ */ new Set([
346
+ "Array",
347
+ "ReadonlyArray",
348
+ "Record",
349
+ "Map",
350
+ "Set",
351
+ "WeakMap",
352
+ "WeakSet",
353
+ "Date"
354
+ ]);
355
+ const OBJECT_VALUES = /* @__PURE__ */ new Set([
356
+ "ObjectExpression",
357
+ "ArrayExpression",
358
+ "NewExpression"
359
+ ]);
360
+ /** A `$state` call whose initial value or type argument is an object, array or class instance. */
361
+ function isObjectState(call) {
362
+ const arg = unwrapTs(call.arguments?.[0]);
363
+ if (isPrimitiveLiteral(arg)) return false;
364
+ if (OBJECT_VALUES.has(arg?.type)) return true;
365
+ if (arg?.type === "LogicalExpression" && arg.operator !== "&&" && !isPrimitiveLiteral(unwrapTs(arg.left)) && OBJECT_VALUES.has(unwrapTs(arg.right)?.type)) return true;
366
+ const type = (call.typeArguments ?? call.typeParameters)?.params?.[0];
367
+ if (type?.type === "TSTypeReference") return OBJECT_TYPE_NAMES.has(type.typeName?.name);
368
+ return OBJECT_TYPES.has(type?.type);
369
+ }
313
370
  function collectStateWrites(root, stateNames, acc, kinds, localStates = false) {
314
371
  const record = (name, kind) => {
315
372
  acc.add(name);
@@ -319,14 +376,38 @@ function collectStateWrites(root, stateNames, acc, kinds, localStates = false) {
319
376
  set.add(kind);
320
377
  }
321
378
  };
379
+ const primitiveStates = /* @__PURE__ */ new Set();
380
+ const objectStates = /* @__PURE__ */ new Set();
381
+ const heldObjects = /* @__PURE__ */ new Set();
382
+ walkEstree(root, (n) => {
383
+ const init = n?.type === "VariableDeclarator" ? unwrapTs(n.init) : void 0;
384
+ if (n?.id?.type !== "Identifier" || !isStateDeclaration(init)) return;
385
+ (isPrimitiveLiteral(init.arguments?.[0]) ? primitiveStates : objectStates).add(n.id.name);
386
+ if (localStates && isObjectState(init)) heldObjects.add(n.id.name);
387
+ });
388
+ for (const name of objectStates) primitiveStates.delete(name);
389
+ const aliasOf = /* @__PURE__ */ new Map();
390
+ const reassigned = /* @__PURE__ */ new Set();
391
+ if (localStates) walkEstree(root, (n) => {
392
+ const target = n?.type === "AssignmentExpression" ? n.left : n?.type === "UpdateExpression" ? n.argument : void 0;
393
+ if (target?.type === "Identifier") reassigned.add(target.name);
394
+ });
395
+ if (localStates) for (let pass = 0; pass < 2; pass++) walkEstree(root, (n) => {
396
+ const [id, from] = n?.type === "VariableDeclarator" && unwrapTs(n.init)?.type === "MemberExpression" ? [n.id, n.init] : n?.type === "ForOfStatement" && n.left?.type === "VariableDeclaration" ? [n.left.declarations?.[0]?.id, n.right] : [void 0, void 0];
397
+ const r = rootObjectName(unwrapTs(from));
398
+ const owner = r && (stateNames.has(r) ? r : aliasOf.get(r));
399
+ if (id?.type === "Identifier" && owner && !stateNames.has(id.name) && !reassigned.has(id.name)) aliasOf.set(id.name, owner);
400
+ });
322
401
  const visit = (stateNames) => (n, scope) => {
323
402
  const shadowed = (name) => name === void 0 || scope.has(name);
403
+ const mutated = (r) => {
404
+ if (r && stateNames.has(r) && !shadowed(r)) record(r, "mutate");
405
+ else if (r && stateNames.has(aliasOf.get(r))) record(aliasOf.get(r), "mutate");
406
+ };
324
407
  if (n?.type === "AssignmentExpression") {
325
408
  if (n.left?.type === "Identifier" && stateNames.has(n.left.name) && !shadowed(n.left.name)) record(n.left.name, "reassign");
326
- else if (n.left?.type === "MemberExpression") {
327
- const r = rootObjectName(n.left);
328
- if (r && stateNames.has(r) && !shadowed(r)) record(r, "mutate");
329
- } else if (n.left?.type === "ObjectPattern" || n.left?.type === "ArrayPattern") {
409
+ else if (n.left?.type === "MemberExpression") mutated(rootObjectName(n.left));
410
+ else if (n.left?.type === "ObjectPattern" || n.left?.type === "ArrayPattern") {
330
411
  const bound = /* @__PURE__ */ new Set();
331
412
  addBoundNames(n.left, bound);
332
413
  for (const name of bound) if (stateNames.has(name) && !shadowed(name)) record(name, "reassign");
@@ -334,24 +415,30 @@ function collectStateWrites(root, stateNames, acc, kinds, localStates = false) {
334
415
  } else if (n?.type === "UpdateExpression") {
335
416
  if (n.argument?.type === "Identifier") {
336
417
  if (stateNames.has(n.argument.name) && !shadowed(n.argument.name)) record(n.argument.name, "reassign");
337
- } else {
338
- const r = rootObjectName(n.argument);
339
- if (r && stateNames.has(r) && !shadowed(r)) record(r, "mutate");
340
- }
341
- } else if (n?.type === "UnaryExpression" && n.operator === "delete") {
342
- const r = rootObjectName(n.argument);
343
- if (r && stateNames.has(r) && !shadowed(r)) record(r, "mutate");
344
- } else if (n?.type === "CallExpression") {
345
- if (n.callee?.type === "MemberExpression") {
346
- const r = rootObjectName(n.callee);
347
- if (r && stateNames.has(r) && !shadowed(r)) record(r, "mutate");
348
- }
418
+ } else mutated(rootObjectName(n.argument));
419
+ } else if (n?.type === "UnaryExpression" && n.operator === "delete") mutated(rootObjectName(n.argument));
420
+ else if (n?.type === "CallExpression") {
421
+ if (n.callee?.type === "MemberExpression") mutated(rootObjectName(n.callee));
349
422
  for (const a of n.arguments ?? []) {
350
423
  const arg = a?.type === "SpreadElement" ? a.argument : a;
351
424
  const r = rootObjectName(arg);
352
425
  if (r && stateNames.has(r) && !shadowed(r)) record(r, "escape");
353
426
  }
354
- }
427
+ } else if (n?.type === "ReturnStatement") {
428
+ const out = unwrapTs(n.argument);
429
+ const r = out?.type === "Identifier" ? out.name : void 0;
430
+ if (r && stateNames.has(r) && !shadowed(r) && !primitiveStates.has(r)) record(r, "escape");
431
+ } else if (heldObjects.size > 0 && (n?.type === "ObjectExpression" || n?.type === "ArrayExpression")) {
432
+ const values = n.type === "ObjectExpression" ? (n.properties ?? []).map((p) => p?.value) : n.elements;
433
+ for (const v of values ?? []) {
434
+ const placed = unwrapTs(v);
435
+ const r = placed?.type === "Identifier" ? placed.name : void 0;
436
+ if (r && heldObjects.has(r) && stateNames.has(r) && !shadowed(r)) record(r, "escape");
437
+ }
438
+ } else if ((n?.type === "Property" || n?.type === "MethodDefinition") && n.kind === "get") walkEstree(n.value?.body, (m) => {
439
+ const r = m?.type === "ReturnStatement" ? rootObjectName(m.argument) : void 0;
440
+ if (r && stateNames.has(r) && !shadowed(r) && !primitiveStates.has(r)) record(r, "escape");
441
+ });
355
442
  };
356
443
  walkScoped(root, visit(stateNames));
357
444
  if (!localStates) return;
@@ -1028,12 +1115,25 @@ function selectNativeRole(attributes) {
1028
1115
  if (attrValueOf(size) !== "static") return void 0;
1029
1116
  return Number(attrTextOf(size)) > 1 ? "listbox" : "combobox";
1030
1117
  }
1031
- function collectAriaElements(node, source, acc) {
1118
+ /** svelte-dnd-action's zone actions, which set `role="listitem"` on each child element at runtime. */
1119
+ const DND_ZONE_ACTIONS = /* @__PURE__ */ new Set(["dndzone", "dragHandleZone"]);
1120
+ /** A zone action unless its options' final say on `autoAriaDisabled` is a literal `true`, which turns the item roles off. */
1121
+ function isDndZone(a) {
1122
+ if (a?.type !== "UseDirective" || !DND_ZONE_ACTIONS.has(a.name)) return false;
1123
+ const opts = unwrapTs(a.expression);
1124
+ if (opts?.type !== "ObjectExpression") return true;
1125
+ const keyOf = (p) => p.computed ? p.key?.type === "Literal" ? String(p.key.value) : void 0 : String(p.key?.name ?? p.key?.value);
1126
+ const last = opts.properties.filter((p) => p.type === "SpreadElement" || p.type === "Property" && (keyOf(p) === void 0 || keyOf(p) === "autoAriaDisabled")).at(-1);
1127
+ return !(last?.type === "Property" && keyOf(last) === "autoAriaDisabled" && last.value?.type === "Literal" && last.value.value === true);
1128
+ }
1129
+ function collectAriaElements(node, source, acc, parentIsDndZone = false) {
1032
1130
  if (Array.isArray(node)) {
1033
- for (const child of node) collectAriaElements(child, source, acc);
1131
+ for (const child of node) collectAriaElements(child, source, acc, parentIsDndZone);
1034
1132
  return;
1035
1133
  }
1036
1134
  if (!node || typeof node !== "object") return;
1135
+ let inDndZone = parentIsDndZone;
1136
+ if (typeof node.type === "string" && (node.type.endsWith("Element") || node.type === "Component" || node.type.startsWith("Svelte")) && node.type !== "SvelteBoundary") inDndZone = Array.isArray(node.attributes) && node.attributes.some(isDndZone);
1037
1137
  if (node.type === "RegularElement" && Array.isArray(node.attributes)) {
1038
1138
  const roleAttr = findAttr(node.attributes, "role");
1039
1139
  const ariaAttrs = node.attributes.filter((a) => a?.type === "Attribute" && typeof a.name === "string" && a.name.toLowerCase().startsWith("aria-"));
@@ -1043,7 +1143,7 @@ function collectAriaElements(node, source, acc) {
1043
1143
  const hasList = tag === "input" && findAttr(node.attributes, "list") !== void 0;
1044
1144
  const selectKind = tag === "select" ? selectNativeRole(node.attributes) : void 0;
1045
1145
  const hasSpread = node.attributes.some((a) => a?.type === "SpreadAttribute");
1046
- const hasAction = node.attributes.some((a) => a?.type === "UseDirective");
1146
+ const hasAction = parentIsDndZone || node.attributes.some((a) => a?.type === "UseDirective");
1047
1147
  acc.push({
1048
1148
  tag,
1049
1149
  line: lineOf(source, node.start),
@@ -1061,7 +1161,7 @@ function collectAriaElements(node, source, acc) {
1061
1161
  });
1062
1162
  }
1063
1163
  }
1064
- for (const key of CHILD_NODE_KEYS) if (key in node) collectAriaElements(node[key], source, acc);
1164
+ for (const key of CHILD_NODE_KEYS) if (key in node) collectAriaElements(node[key], source, acc, inDndZone);
1065
1165
  }
1066
1166
  /** This element's `Attribute` nodes (directives/spreads excluded) as `isInteractiveElement`'s
1067
1167
  * input shape. */
@@ -1739,6 +1839,7 @@ function isPropsCall(node) {
1739
1839
  }
1740
1840
  /** Whether a CallExpression is a `$bindable(...)` call (a destructured prop's default value). */
1741
1841
  function isBindableCall(node) {
1842
+ node = unwrapTs(node);
1742
1843
  return node?.type === "CallExpression" && node.callee?.type === "Identifier" && node.callee.name === "$bindable";
1743
1844
  }
1744
1845
  /**
@@ -1809,6 +1910,92 @@ const MUTATING_METHODS = /* @__PURE__ */ new Set([
1809
1910
  "delete",
1810
1911
  "clear"
1811
1912
  ]);
1913
+ /** Built-in types whose own methods include the mutating method names above. */
1914
+ const COLLECTION_TYPES = /* @__PURE__ */ new Set([
1915
+ "Array",
1916
+ "ReadonlyArray",
1917
+ "Set",
1918
+ "ReadonlySet",
1919
+ "Map",
1920
+ "ReadonlyMap",
1921
+ "WeakMap",
1922
+ "WeakSet",
1923
+ "SvelteSet",
1924
+ "SvelteMap",
1925
+ "URLSearchParams",
1926
+ "SvelteURLSearchParams",
1927
+ "FormData",
1928
+ "Headers",
1929
+ "Int8Array",
1930
+ "Uint8Array",
1931
+ "Uint8ClampedArray",
1932
+ "Int16Array",
1933
+ "Uint16Array",
1934
+ "Int32Array",
1935
+ "Uint32Array",
1936
+ "Float16Array",
1937
+ "Float32Array",
1938
+ "Float64Array",
1939
+ "BigInt64Array",
1940
+ "BigUint64Array"
1941
+ ]);
1942
+ const NON_COLLECTION_NODES = /* @__PURE__ */ new Set([
1943
+ "TSStringKeyword",
1944
+ "TSNumberKeyword",
1945
+ "TSBooleanKeyword",
1946
+ "TSBigIntKeyword",
1947
+ "TSNullKeyword",
1948
+ "TSUndefinedKeyword",
1949
+ "TSFunctionType",
1950
+ "TSTypeLiteral",
1951
+ "TSLiteralType"
1952
+ ]);
1953
+ /**
1954
+ * The props whose declared type, from the `$props()` annotation, is known not to be a collection: a
1955
+ * method called on one is its own API (`queryClient.clear()`), not an array, Set or Map mutation.
1956
+ * A named type counts unless it is a built-in collection or a same-file alias of one.
1957
+ */
1958
+ function nonCollectionProps(program) {
1959
+ const decls = /* @__PURE__ */ new Map();
1960
+ walkEstree(program, (n) => {
1961
+ if ((n.type === "TSInterfaceDeclaration" || n.type === "TSTypeAliasDeclaration") && n.id?.name) decls.set(n.id.name, n);
1962
+ });
1963
+ const unwrap = (t) => t?.type === "TSTypeAnnotation" ? t.typeAnnotation : t;
1964
+ const nonCollection = (t, depth) => {
1965
+ t = unwrap(t);
1966
+ if (!t || depth > 4) return false;
1967
+ if (NON_COLLECTION_NODES.has(t.type)) return true;
1968
+ if (t.type === "TSUnionType") return t.types.every((u) => nonCollection(u, depth + 1));
1969
+ if (t.type !== "TSTypeReference" || t.typeName?.type !== "Identifier") return false;
1970
+ const name = t.typeName.name;
1971
+ if (COLLECTION_TYPES.has(name)) return false;
1972
+ const decl = decls.get(name);
1973
+ if (decl?.type === "TSTypeAliasDeclaration") return nonCollection(decl.typeAnnotation, depth + 1);
1974
+ if (decl?.type === "TSInterfaceDeclaration") return !(decl.extends ?? []).some((h) => COLLECTION_TYPES.has(h.expression?.name));
1975
+ return !(t.typeArguments ?? t.typeParameters)?.params?.length;
1976
+ };
1977
+ const membersOf = (t, depth) => {
1978
+ t = unwrap(t);
1979
+ if (t?.type === "TSTypeLiteral") return t.members;
1980
+ if (t?.type !== "TSTypeReference" || depth > 4) return void 0;
1981
+ const decl = decls.get(t.typeName?.name);
1982
+ if (decl?.type === "TSInterfaceDeclaration") return decl.body?.body;
1983
+ return decl?.type === "TSTypeAliasDeclaration" ? membersOf(decl.typeAnnotation, depth + 1) : void 0;
1984
+ };
1985
+ const names = /* @__PURE__ */ new Set();
1986
+ walkEstree(program, (n) => {
1987
+ if (n.type !== "VariableDeclarator" || !n.init || !isPropsCall(unwrapTs(n.init))) return;
1988
+ if (n.id?.type !== "ObjectPattern") return;
1989
+ const types = /* @__PURE__ */ new Map();
1990
+ for (const m of membersOf(n.id.typeAnnotation, 0) ?? []) if (m.type === "TSPropertySignature" && m.key?.type === "Identifier") types.set(m.key.name, m.typeAnnotation);
1991
+ for (const p of n.id.properties ?? []) {
1992
+ if (p?.type !== "Property" || p.key?.type !== "Identifier" || !types.has(p.key.name)) continue;
1993
+ const local = p.value?.type === "AssignmentPattern" ? p.value.left : p.value;
1994
+ if (local?.type === "Identifier" && nonCollection(types.get(p.key.name), 0)) names.add(local.name);
1995
+ }
1996
+ });
1997
+ return names;
1998
+ }
1812
1999
  /**
1813
2000
  * Flag mutations of a non-`$bindable` prop (correctness/prop-mutation): a member-expression write
1814
2001
  * (`prop.x = …`, `prop.x += …`, `prop.x++`), `delete prop.x`, or a call to a mutating
@@ -1820,16 +2007,18 @@ const MUTATING_METHODS = /* @__PURE__ */ new Set([
1820
2007
  * A `legacy` (export let) prop is flagged only for `delete` and mutating method calls — the legacy
1821
2008
  * compiler turns a member write or update into an invalidating assignment (`prop(prop().x = …, true)`).
1822
2009
  */
1823
- function collectPropMutations(root, propNames, source, acc, legacy) {
2010
+ function collectPropMutations(root, propNames, source, acc, legacy, ownApi = /* @__PURE__ */ new Set()) {
1824
2011
  if (propNames.size === 0) return;
1825
2012
  const exemptCalls = /* @__PURE__ */ new Set();
2013
+ const returnedToProp = /* @__PURE__ */ new Set();
1826
2014
  if (legacy.size > 0) walkEstree(root, (fn) => {
1827
- if (!isDeferredBody(fn)) return;
2015
+ const body = isDeferredBody(fn) ? fn.body : fn.type === "LabeledStatement" && fn.label?.name === "$" ? fn.body : void 0;
2016
+ if (!body) return;
1828
2017
  const assigned = /* @__PURE__ */ new Set();
1829
- walkScoped(fn.body, (m, scope) => {
2018
+ walkScoped(body, (m, scope) => {
1830
2019
  if (m.type === "AssignmentExpression" && m.left?.type === "Identifier" && !scope.has(m.left.name)) assigned.add(m.left.name);
1831
2020
  });
1832
- walkEstree(fn.body, (m) => {
2021
+ walkEstree(body, (m) => {
1833
2022
  const r = m.type === "CallExpression" ? rootObjectName(m.callee?.object) : m.type === "UnaryExpression" && m.operator === "delete" ? rootObjectName(m.argument) : void 0;
1834
2023
  if (r && legacy.has(r) && assigned.has(r)) exemptCalls.add(m);
1835
2024
  });
@@ -1837,6 +2026,20 @@ function collectPropMutations(root, propNames, source, acc, legacy) {
1837
2026
  walkEstree(root, (m) => {
1838
2027
  const call = m.type === "AssignmentExpression" && m.left?.type === "Identifier" ? m.right : void 0;
1839
2028
  if (call?.type === "CallExpression" && rootObjectName(call.callee?.object) === m.left.name && call.arguments?.length === 1 && call.arguments[0]?.type === "ObjectExpression") exemptCalls.add(call);
2029
+ const awaited = m.type === "AwaitExpression" ? unwrapTs(m.argument) : void 0;
2030
+ if (awaited?.type === "CallExpression") exemptCalls.add(awaited);
2031
+ const chained = m.type === "CallExpression" && m.callee?.type === "MemberExpression" && !m.callee.computed && [
2032
+ "then",
2033
+ "catch",
2034
+ "finally"
2035
+ ].includes(m.callee.property?.name) ? unwrapTs(m.callee.object) : void 0;
2036
+ if (chained?.type === "CallExpression") exemptCalls.add(chained);
2037
+ if (m.type === "AssignmentExpression" && m.left?.type === "Identifier") {
2038
+ let back = unwrapTs(m.right);
2039
+ if (back?.type === "LogicalExpression") back = unwrapTs(back.left);
2040
+ if (back?.type === "ChainExpression") back = back.expression;
2041
+ if (back?.type === "CallExpression" && back.callee.type === "MemberExpression" && rootObjectName(back.callee.object) === m.left.name) returnedToProp.add(back);
2042
+ }
1840
2043
  });
1841
2044
  walkScoped(root, (n, scope) => {
1842
2045
  const flag = (r) => {
@@ -1855,6 +2058,8 @@ function collectPropMutations(root, propNames, source, acc, legacy) {
1855
2058
  } else if (n.type === "UnaryExpression" && n.operator === "delete") flag(rootObjectName(n.argument));
1856
2059
  else if (n.type === "CallExpression" && n.callee?.type === "MemberExpression") {
1857
2060
  const method = n.callee.property?.type === "Identifier" ? n.callee.property.name : void 0;
2061
+ const receiver = unwrapTs(n.callee.object);
2062
+ if (receiver?.type === "Identifier" && ownApi.has(receiver.name) && !returnedToProp.has(n)) return;
1858
2063
  if (method && MUTATING_METHODS.has(method)) flag(rootObjectName(n.callee.object));
1859
2064
  }
1860
2065
  });
@@ -1904,7 +2109,7 @@ function collectImportSources(program, source, acc) {
1904
2109
  }
1905
2110
  /** A specifier is "bare" (a node_modules package) when it is not relative/absolute/alias-local. */
1906
2111
  function isBareSpecifier(s) {
1907
- return !/^[./$#]/.test(s);
2112
+ return !/^([./$#]|@\/|~\/)/.test(s);
1908
2113
  }
1909
2114
  /**
1910
2115
  * Whether `name` is used anywhere in `roots` other than as the object of a static member access
@@ -1921,6 +2126,8 @@ function namespaceUsedDynamically(name, roots) {
1921
2126
  if (!n.computed) staticOrDeclaring.add(n.property);
1922
2127
  } else if ((n.type === "Property" && !n.shorthand || n.type === "TSPropertySignature" || n.type === "TSMethodSignature") && !n.computed) staticOrDeclaring.add(n.key);
1923
2128
  else if (n.type === "ImportNamespaceSpecifier") staticOrDeclaring.add(n.local);
2129
+ else if (n.type === "ImportSpecifier" && n.imported !== n.local) staticOrDeclaring.add(n.imported);
2130
+ else if (n.type === "ExportSpecifier" && n.exported !== n.local) staticOrDeclaring.add(n.exported);
1924
2131
  else if (n.type === "TSQualifiedName" || n.type === "TSTypeQuery") {
1925
2132
  const id = n.type === "TSQualifiedName" ? n.left : n.exprName;
1926
2133
  if (id?.type === "Identifier") staticOrDeclaring.add(id);
@@ -2312,8 +2519,9 @@ function parseComponentFacts(source, filename) {
2312
2519
  const legacyPropNames = collectLegacyPropNames(program);
2313
2520
  const nonBindableProps = /* @__PURE__ */ new Set([...collectPropNames(program, false), ...legacyPropNames]);
2314
2521
  const rawMutations = [];
2315
- collectPropMutations(program, nonBindableProps, source, rawMutations, legacyPropNames);
2316
- if (ast.fragment) collectPropMutations(ast.fragment, nonBindableProps, source, rawMutations, legacyPropNames);
2522
+ const ownApi = nonCollectionProps(program);
2523
+ collectPropMutations(program, nonBindableProps, source, rawMutations, legacyPropNames, ownApi);
2524
+ if (ast.fragment) collectPropMutations(ast.fragment, nonBindableProps, source, rawMutations, legacyPropNames, ownApi);
2317
2525
  const isLegacy = legacyPropNames.size > 0;
2318
2526
  for (const m of rawMutations) mutatedProps.push(legacyPropNames.has(m.name) ? {
2319
2527
  ...m,
@@ -2494,8 +2702,7 @@ function parseComponentFacts(source, filename) {
2494
2702
  duplicateDts
2495
2703
  };
2496
2704
  }
2497
- //#endregion
2498
- //#region src/inline-directives.ts
2705
+ // src/inline-directives.ts
2499
2706
  /**
2500
2707
  * Enter every fact-carrying file into a directive index — components, Kit modules, and the Vite
2501
2708
  * config when its minify flag was read. The one home for the union both pipelines apply, so a new
@@ -2578,8 +2785,7 @@ function unknownDirectiveIds(index, rules) {
2578
2785
  for (const [file, directives] of index) for (const d of directives) for (const id of d.ruleIds ?? []) if (!known.has(id)) seen.add(`${file}:${d.line - 1} disables unknown rule "${id}" — run \`svelte-vitals explain --list\` for the ids.`);
2579
2786
  return [...seen].sort();
2580
2787
  }
2581
- //#endregion
2582
- //#region src/component.ts
2788
+ // src/component.ts
2583
2789
  /**
2584
2790
  * Component-body facts for the Correctness category — the source-analysis boundary
2585
2791
  * (mirrors images.ts / headings.ts). Collected by the static (CLI) provider only;
@@ -2672,8 +2878,7 @@ async function collectComponentFacts(rt, cwd) {
2672
2878
  }
2673
2879
  }));
2674
2880
  }
2675
- //#endregion
2676
- //#region src/source-files.ts
2881
+ // src/source-files.ts
2677
2882
  /**
2678
2883
  * Every file under `src/`, as project-relative paths, sorted. Paths only — nothing is
2679
2884
  * read, so this is the cheaper of the two passes over `src/` (the component collector
@@ -2690,8 +2895,7 @@ async function collectComponentFacts(rt, cwd) {
2690
2895
  async function collectSourceFiles(rt, cwd) {
2691
2896
  return (await rt.glob("src/**/*", cwd)).slice().sort();
2692
2897
  }
2693
- //#endregion
2694
- //#region src/kit-module-collect.ts
2898
+ // src/kit-module-collect.ts
2695
2899
  /** Fallback facts for a Kit file that fails to read or parse (dev tooling must never throw). */
2696
2900
  function emptyKitModuleFacts(file, kind) {
2697
2901
  return {
@@ -2731,7 +2935,7 @@ async function collectKitModuleFacts(rt, cwd, aliases) {
2731
2935
  "src/hooks.server.{ts,js}"
2732
2936
  ].map((p) => rt.glob(p, cwd)));
2733
2937
  const files = [...new Set(lists.flat())];
2734
- return arbitrateServerStoreWrites(rt, cwd, await Promise.all(files.sort().map(async (rel) => {
2938
+ return decideLoadFactories(rt, cwd, await decideFlagGuards(rt, cwd, await dropClientWrites(rt, cwd, await arbitrateServerStoreWrites(rt, cwd, await Promise.all(files.sort().map(async (rel) => {
2735
2939
  const kind = kindOf(rel);
2736
2940
  let source;
2737
2941
  try {
@@ -2755,7 +2959,7 @@ async function collectKitModuleFacts(rt, cwd, aliases) {
2755
2959
  parseFailed: true
2756
2960
  };
2757
2961
  }
2758
- })));
2962
+ }))), aliases)));
2759
2963
  }
2760
2964
  /**
2761
2965
  * The files a resolved specifier may name, in resolution order. An extensionless path takes an
@@ -2773,20 +2977,58 @@ function moduleCandidates(repoPath) {
2773
2977
  `${repoPath}/index.js`
2774
2978
  ];
2775
2979
  }
2776
- /**
2777
- * Read the module a pending write targets and return the names it exports as an in-memory
2778
- * container. Returns an empty set when the file cannot be found or read: unresolvable means
2779
- * unarbitrated, which leaves the write exempt.
2780
- */
2781
- async function inMemoryExportsOf(rt, cwd, repoPath) {
2980
+ /** Read a module and parse it with `parse`; empty when it cannot be found or read. */
2981
+ async function exportsOf(rt, cwd, repoPath, parse) {
2782
2982
  for (const rel of moduleCandidates(repoPath)) try {
2783
2983
  if (!await rt.exists(rt.join(cwd, rel))) continue;
2784
- return parseInMemoryExports(await rt.readFile(rt.join(cwd, rel)), rel);
2984
+ return parse(await rt.readFile(rt.join(cwd, rel)), rel);
2785
2985
  } catch {
2786
2986
  return /* @__PURE__ */ new Set();
2787
2987
  }
2788
2988
  return /* @__PURE__ */ new Set();
2789
2989
  }
2990
+ /** Drop the handler `.set()`/`.update()` writes whose target module exports a persistence client under that name. */
2991
+ async function dropClientWrites(rt, cwd, facts, aliases) {
2992
+ const targets = [...new Set(facts.flatMap((f) => (f.storeWriteTargets ?? []).map((w) => w.resolved)))];
2993
+ if (targets.length === 0) return facts;
2994
+ const byPath = new Map(await Promise.all(targets.map(async (t) => [t, await exportsOf(rt, cwd, t, (src, file) => parseClientExports(src, file, aliases))])));
2995
+ return facts.map((f) => {
2996
+ const clients = (f.storeWriteTargets ?? []).filter((w) => byPath.get(w.resolved)?.has(w.imported));
2997
+ if (clients.length === 0) return f;
2998
+ const drop = (w) => w.via === "set-call" && clients.some((c) => c.name === w.name && c.line === w.line);
2999
+ return {
3000
+ ...f,
3001
+ importedStateWrites: f.importedStateWrites.filter((w) => !drop(w))
3002
+ };
3003
+ });
3004
+ }
3005
+ /** A `load` an imported factory builds never renders when the function the factory returns always exits. */
3006
+ async function decideLoadFactories(rt, cwd, facts) {
3007
+ const targets = [...new Set(facts.flatMap((f) => f.pendingLoadFactory ? [f.pendingLoadFactory.resolved] : []))];
3008
+ if (targets.length === 0) return facts;
3009
+ const byPath = new Map(await Promise.all(targets.map(async (t) => [t, await exportsOf(rt, cwd, t, parseExitFactoryExports)])));
3010
+ return facts.map((f) => {
3011
+ const g = f.pendingLoadFactory;
3012
+ return g && byPath.get(g.resolved)?.has(g.name) ? {
3013
+ ...f,
3014
+ loadNeverRenders: true
3015
+ } : f;
3016
+ });
3017
+ }
3018
+ /** A load whose leading guard exits on an imported flag that is the literal `false` never renders. */
3019
+ async function decideFlagGuards(rt, cwd, facts) {
3020
+ const targets = [...new Set(facts.flatMap((f) => f.pendingFlagGuard ? [f.pendingFlagGuard.resolved] : []))];
3021
+ if (targets.length === 0) return facts;
3022
+ const byPath = new Map(await Promise.all(targets.map(async (t) => [t, await exportsOf(rt, cwd, t, parseFalseExports)])));
3023
+ return facts.map((f) => {
3024
+ const g = f.pendingFlagGuard;
3025
+ const key = g && (g.member ? `${g.name}.${g.member}` : g.name);
3026
+ return g && byPath.get(g.resolved)?.has(key) ? {
3027
+ ...f,
3028
+ loadNeverRenders: true
3029
+ } : f;
3030
+ });
3031
+ }
2790
3032
  /**
2791
3033
  * Decide the `.set()`/`.update()` calls the parse could not: a call on a binding exported from
2792
3034
  * under the `$lib` server root is shared module state when that binding is an in-memory
@@ -2796,7 +3038,7 @@ async function inMemoryExportsOf(rt, cwd, repoPath) {
2796
3038
  async function arbitrateServerStoreWrites(rt, cwd, facts) {
2797
3039
  const targets = [...new Set(facts.flatMap((f) => f.pendingServerStoreWrites.map((w) => w.resolved)))];
2798
3040
  if (targets.length === 0) return facts;
2799
- const byPath = new Map(await Promise.all(targets.map(async (t) => [t, await inMemoryExportsOf(rt, cwd, t)])));
3041
+ const byPath = new Map(await Promise.all(targets.map(async (t) => [t, await exportsOf(rt, cwd, t, parseInMemoryExports)])));
2800
3042
  return facts.map((f) => {
2801
3043
  const promoted = f.pendingServerStoreWrites.filter((w) => byPath.get(w.resolved)?.has(w.imported)).map((w) => ({
2802
3044
  name: w.name,
@@ -2810,8 +3052,7 @@ async function arbitrateServerStoreWrites(rt, cwd, facts) {
2810
3052
  };
2811
3053
  });
2812
3054
  }
2813
- //#endregion
2814
- //#region src/config-object.ts
3055
+ // src/config-object.ts
2815
3056
  /**
2816
3057
  * Non-computed property of an object literal, by key name (`build` or `'build'`).
2817
3058
  * Returns the LAST matching property, honoring JavaScript object semantics where
@@ -2898,8 +3139,7 @@ function resolveConfigObject(program) {
2898
3139
  if (!exported) return void 0;
2899
3140
  return unwrapToObjectExpression(exported, collectTopLevelBindings(program));
2900
3141
  }
2901
- //#endregion
2902
- //#region src/vite-config-parse.ts
3142
+ // src/vite-config-parse.ts
2903
3143
  /**
2904
3144
  * The `build: { minify: false }` override, when present as a literal: returns the
2905
3145
  * `minify` property's 1-based line in the ORIGINAL source. Undefined for clean,
@@ -2924,30 +3164,52 @@ function findMinifyDisabled(source) {
2924
3164
  if (!minify || minifyValue?.type !== "Literal" || minifyValue.value !== false) return void 0;
2925
3165
  return { line: Math.max(0, lineOf(wrapped, minify.start) - 1) };
2926
3166
  }
2927
- //#endregion
2928
- //#region src/svelte-config-parse.ts
2929
- /** Whether every branch of a `?:` / `||` / `&&` / `??` tree is the literal `''`. */
2930
- function alwaysEmptyString(expr) {
2931
- const e = unwrapTs(expr);
2932
- if (e.type === "Literal") return e.value === "";
2933
- if (e.type === "ConditionalExpression") return alwaysEmptyString(e.consequent) && alwaysEmptyString(e.alternate);
2934
- if (e.type === "LogicalExpression") return alwaysEmptyString(e.left) && alwaysEmptyString(e.right);
3167
+ // src/svelte-config-parse.ts
3168
+ function isServedBase(value) {
3169
+ return typeof value === "string" && value.startsWith("/") && !value.endsWith("/");
3170
+ }
3171
+ /** The top-level bindings declared `const`: a `let` may be reassigned on the way to the export. */
3172
+ function constBindings(program, bindings) {
3173
+ const names = /* @__PURE__ */ new Set();
3174
+ for (const stmt of program.body) {
3175
+ const decl = stmt.type === "ExportNamedDeclaration" ? stmt.declaration : stmt;
3176
+ if (decl?.type !== "VariableDeclaration" || decl.kind !== "const") continue;
3177
+ for (const d of decl.declarations) if (d.id.type === "Identifier") names.add(d.id.name);
3178
+ }
3179
+ return new Map([...bindings].filter(([name]) => names.has(name)));
3180
+ }
3181
+ /** Whether no branch of a `?:` / `||` / `&&` / `??` tree is a literal base an app can be served under. */
3182
+ function neverABase(expr, consts) {
3183
+ const e = resolveBinding(expr, consts);
3184
+ if (e.type === "Literal") return !isServedBase(e.value);
3185
+ if (e.type === "ConditionalExpression") return neverABase(e.consequent, consts) && neverABase(e.alternate, consts);
3186
+ if (e.type === "LogicalExpression") return neverABase(e.left, consts) && neverABase(e.right, consts);
2935
3187
  return false;
2936
3188
  }
3189
+ /** `expr` with top-level `const` names followed to their initializers (`paths: { base }` naming `const base = ''`). */
3190
+ function resolveBinding(expr, consts) {
3191
+ let e = unwrapTs(expr);
3192
+ for (let i = 0; i < 4 && e.type === "Identifier"; i++) {
3193
+ const next = consts.get(e.name);
3194
+ if (!next) break;
3195
+ e = unwrapTs(next);
3196
+ }
3197
+ return e;
3198
+ }
2937
3199
  /**
2938
3200
  * `paths.base` off a resolved Kit-config object: `{ value }` for a non-empty string literal,
2939
3201
  * `{}` for any other expression (base exists, value unknowable — the `dev ? '' : '/repo'`
2940
- * deploy form), and undefined when absent or when every value it can take is the empty string.
3202
+ * deploy form), and undefined when absent or when no value it can take is a base SvelteKit serves under.
2941
3203
  */
2942
- function basePathOf(kitConfig, bindings) {
3204
+ function basePathOf(kitConfig, bindings, consts) {
2943
3205
  const paths = propOf(kitConfig, "paths");
2944
3206
  const pathsObj = paths ? unwrapToObjectExpression(paths.value, bindings) : void 0;
2945
3207
  if (!pathsObj) return void 0;
2946
3208
  const base = propOf(pathsObj, "base");
2947
3209
  if (!base) return void 0;
2948
- const value = unwrapTs(base.value);
2949
- if (value.type === "Literal") return typeof value.value === "string" && value.value !== "" ? { value: value.value } : void 0;
2950
- return alwaysEmptyString(value) ? void 0 : {};
3210
+ const value = resolveBinding(base.value, consts);
3211
+ if (value.type === "Literal") return isServedBase(value.value) ? { value: value.value } : void 0;
3212
+ return neverABase(value, consts) ? void 0 : {};
2951
3213
  }
2952
3214
  /** A property's key when it is a plain (non-computed) string or identifier key. */
2953
3215
  function keyNameOf(p) {
@@ -3173,7 +3435,33 @@ function findKitPathsBaseInSvelteConfig(source) {
3173
3435
  const bindings = collectTopLevelBindings(program);
3174
3436
  const kit = propOf(config, "kit");
3175
3437
  const kitObj = kit ? unwrapToObjectExpression(kit.value, bindings) : void 0;
3176
- return kitObj ? basePathOf(kitObj, bindings) : void 0;
3438
+ return kitObj ? basePathOf(kitObj, bindings, constBindings(program, bindings)) : void 0;
3439
+ }
3440
+ /**
3441
+ * `unwrapToObjectExpression`, but only where the literal is the value: a call passing more than one
3442
+ * argument (`mergeConfigs(a, b)`) or a spread could make it something else.
3443
+ */
3444
+ function knownObject(expr, bindings) {
3445
+ let current = expr;
3446
+ for (let i = 0; i < 4 && current; i++) {
3447
+ const e = unwrapTs(current);
3448
+ if (e.type === "ObjectExpression") return e.properties.some((p) => p.type === "SpreadElement") ? void 0 : e;
3449
+ if (e.type === "Identifier") current = bindings.get(e.name);
3450
+ else if (e.type === "CallExpression" && e.arguments.length === 1) current = e.arguments[0];
3451
+ else return void 0;
3452
+ }
3453
+ }
3454
+ /** Whether `kit.router.type` is the literal `'hash'` in a config whose value is known. */
3455
+ function findKitHashRouterInSvelteConfig(source) {
3456
+ const program = programOf(source, "svelte.config.js");
3457
+ if (!program) return false;
3458
+ const bindings = collectTopLevelBindings(program);
3459
+ const objectAt = (obj, key) => {
3460
+ const p = obj && propOf(obj, key);
3461
+ return p ? knownObject(p.value, bindings) : void 0;
3462
+ };
3463
+ const router = objectAt(objectAt(knownObject(findExportedExpression(program), bindings), "kit"), "router");
3464
+ return stringLiteralOf(router && propOf(router, "type")?.value) === "hash";
3177
3465
  }
3178
3466
  /**
3179
3467
  * Local names bound to `sveltekit` imported from '@sveltejs/kit/vite'. When no such import is
@@ -3206,7 +3494,7 @@ function findKitPathsBaseInViteConfig(source) {
3206
3494
  if (arg === void 0) return none;
3207
3495
  const kitConfig = unwrapToObjectExpression(arg, bindings);
3208
3496
  if (!kitConfig) return { kind: "unresolvable" };
3209
- const base = basePathOf(kitConfig, bindings);
3497
+ const base = basePathOf(kitConfig, bindings, constBindings(program, bindings));
3210
3498
  return base ? {
3211
3499
  kind: "resolved",
3212
3500
  base
@@ -3235,8 +3523,7 @@ function resolveKitPathsBase(viteConfig, svelteConfig) {
3235
3523
  file: svelteConfig.file
3236
3524
  } : void 0;
3237
3525
  }
3238
- //#endregion
3239
- //#region src/workspace-packages.ts
3526
+ // src/workspace-packages.ts
3240
3527
  const DEPENDENCY_FIELDS = [
3241
3528
  "dependencies",
3242
3529
  "devDependencies",
@@ -3448,8 +3735,7 @@ function withInstalledPackages(aliases, packages) {
3448
3735
  const svelte = packages.filter((p) => isSveltePackage(p.manifest));
3449
3736
  return svelte.length === 0 ? aliases : [...aliases ?? DEFAULT_KIT_ALIASES, ...svelte.flatMap(entriesOf)];
3450
3737
  }
3451
- //#endregion
3452
- //#region src/project-paths.ts
3738
+ // src/project-paths.ts
3453
3739
  /**
3454
3740
  * Source-file locations that satisfy the project-scope rules, shared by every
3455
3741
  * mode so the static (CLI) and rendered (plugin) collectors never drift. This
@@ -3468,11 +3754,17 @@ const SITEMAP_SOURCE_PATHS = [
3468
3754
  "src/routes/sitemap.xml/+server.js"
3469
3755
  ];
3470
3756
  /** The `+server` endpoints above, wherever (group) directories nest them — filter with `servesRootFile`. */
3471
- const ROOT_FILE_ENDPOINT_GLOB = "src/routes/**/{robots.txt,sitemap.xml}/+server.{ts,js}";
3472
- /** Whether a `+server` endpoint serves `/<file>`: (group) directories add no URL segment. */
3757
+ const ROOT_FILE_ENDPOINT_GLOB = "src/routes/**/{robots.txt,sitemap*.xml}/+server.{ts,js}";
3758
+ /**
3759
+ * Whether a `+server` endpoint serves `/<file>`: (group) directories add no URL segment, and an optional
3760
+ * parameter in the name (`sitemap[[page]].xml`) still answers the bare name.
3761
+ */
3473
3762
  function servesRootFile(rel, file) {
3474
3763
  const segments = rel.split("/");
3475
- return segments[0] === "src" && segments[1] === "routes" && segments.at(-2) === file && /^\+server\.(ts|js)$/.test(segments.at(-1) ?? "") && segments.slice(2, -2).every((s) => /^\(.+\)$/.test(s));
3764
+ const dot = file.lastIndexOf(".");
3765
+ const optional = new RegExp(`^${file.slice(0, dot)}\\[\\[[^\\]]+\\]\\]\\${file.slice(dot)}$`);
3766
+ const dir = segments.at(-2) ?? "";
3767
+ return segments[0] === "src" && segments[1] === "routes" && (dir === file || optional.test(dir)) && /^\+server\.(ts|js)$/.test(segments.at(-1) ?? "") && segments.slice(2, -2).every((s) => /^\(.+\)$/.test(s));
3476
3768
  }
3477
3769
  /** Vite's own config resolution order — only the first existing file is the one Vite loads. */
3478
3770
  const VITE_CONFIG_FILES = [
@@ -3485,8 +3777,7 @@ const VITE_CONFIG_FILES = [
3485
3777
  ];
3486
3778
  /** SvelteKit's config resolution order (`@sveltejs/kit` checks js before ts). */
3487
3779
  const SVELTE_CONFIG_FILES = ["svelte.config.js", "svelte.config.ts"];
3488
- //#endregion
3489
- //#region src/runtime.ts
3780
+ // src/runtime.ts
3490
3781
  /**
3491
3782
  * How many file reads may be in flight at once. Analysis reads every `.svelte` file in a project
3492
3783
  * in parallel, which on a large project opens more descriptors than the process is allowed: at
@@ -3519,8 +3810,7 @@ function withReadLimit(readFile, limit = READ_CONCURRENCY) {
3519
3810
  }
3520
3811
  };
3521
3812
  }
3522
- //#endregion
3523
- //#region src/engine.ts
3813
+ // src/engine.ts
3524
3814
  /**
3525
3815
  * Run a set of rules against a shared context and collect their findings.
3526
3816
  * Rules are independent, so they run concurrently; results are flattened in
@@ -3545,7 +3835,7 @@ async function runRules(rules, ctx) {
3545
3835
  }));
3546
3836
  const results = [];
3547
3837
  const failedRules = [];
3548
- for (const outcome of perRule) if (Array.isArray(outcome)) results.push(...outcome);
3838
+ for (const outcome of perRule) if (Array.isArray(outcome)) for (const r of outcome) results.push(r);
3549
3839
  else failedRules.push(outcome);
3550
3840
  return {
3551
3841
  results,
@@ -3573,8 +3863,7 @@ async function runAnalysis(rules, ctx, directives) {
3573
3863
  scoringConfig: withFailedRulesOff(ctx.config, failedRuleIds)
3574
3864
  };
3575
3865
  }
3576
- //#endregion
3577
- //#region src/reporter/palette.ts
3866
+ // src/reporter/palette.ts
3578
3867
  /** Default: no decoration (identity) — output is byte-identical to plain text. */
3579
3868
  const noColorPalette = {
3580
3869
  bold: (s) => s,
@@ -3590,8 +3879,7 @@ function scoreColor(p, score) {
3590
3879
  if (score >= 70) return p.yellow;
3591
3880
  return p.red;
3592
3881
  }
3593
- //#endregion
3594
- //#region src/reporter/console.ts
3882
+ // src/reporter/console.ts
3595
3883
  const RULE = "────────────────────────";
3596
3884
  const SEVERITY_TITLE = {
3597
3885
  critical: "Critical",
@@ -3717,12 +4005,11 @@ function formatConsoleReport(results, config, options = {}) {
3717
4005
  }
3718
4006
  lines.push("");
3719
4007
  }
3720
- if (options.byRoute) lines.push(...byRouteTree(p, results, config, options.verbose ?? false));
4008
+ if (options.byRoute) for (const line of byRouteTree(p, results, config, options.verbose ?? false)) lines.push(line);
3721
4009
  if (options.verbose && summary.dynamic > 0) lines.push(p.dim("↯ = set dynamically (verified at runtime)."));
3722
4010
  return lines.join("\n").replace(/\n+$/, "\n");
3723
4011
  }
3724
- //#endregion
3725
- //#region src/reporter/agent.ts
4012
+ // src/reporter/agent.ts
3726
4013
  /** Render failing findings as an agent-actionable Markdown remediation document (issue #18). */
3727
4014
  function formatAgentReport(results, config) {
3728
4015
  const failing = results.filter((r) => classify(r, config) === "fail");
@@ -3744,7 +4031,7 @@ function formatAgentReport(results, config) {
3744
4031
  if (!groups.has(key)) groups.set(key, []);
3745
4032
  groups.get(key).push(r);
3746
4033
  }
3747
- const groupSeverity = (rs) => Math.min(...rs.map((r) => SEVERITY_RANK[effectiveSeverity(r, config)]));
4034
+ const groupSeverity = (rs) => rs.reduce((min, r) => Math.min(min, SEVERITY_RANK[effectiveSeverity(r, config)]), Infinity);
3748
4035
  const orderedGroups = [...groups.entries()].sort((a, b) => groupSeverity(a[1]) - groupSeverity(b[1]) || a[0].localeCompare(b[0]));
3749
4036
  for (const [loc, rs] of orderedGroups) {
3750
4037
  rs.sort((x, y) => SEVERITY_RANK[effectiveSeverity(x, config)] - SEVERITY_RANK[effectiveSeverity(y, config)] || x.id.localeCompare(y.id));
@@ -3763,8 +4050,7 @@ function formatAgentReport(results, config) {
3763
4050
  }
3764
4051
  return lines.join("\n").replace(/\n+$/, "\n");
3765
4052
  }
3766
- //#endregion
3767
- //#region src/reporter/sarif.ts
4053
+ // src/reporter/sarif.ts
3768
4054
  /**
3769
4055
  * SARIF `artifactLocation.uri` is a URI reference: `#`, `?`, `%`, spaces and non-ASCII in a raw
3770
4056
  * path would be read as fragment/query/escape/invalid and mis-attribute (or drop) the alert in
@@ -3820,8 +4106,7 @@ function formatSarifReport(results, config, meta) {
3820
4106
  };
3821
4107
  return JSON.stringify(log, null, 2);
3822
4108
  }
3823
- //#endregion
3824
- //#region src/reporter/app-shell.ts
4109
+ // src/reporter/app-shell.ts
3825
4110
  function escapeHtml(s) {
3826
4111
  return s.replace(/[&<>"']/g, (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : c === ">" ? "&gt;" : c === "\"" ? "&quot;" : "&#39;");
3827
4112
  }
@@ -4579,5 +4864,4 @@ function buildHtmlDocument(report, meta) {
4579
4864
  function formatHtmlReport(results, config, meta) {
4580
4865
  return buildHtmlDocument(buildJsonReport(results, config, meta), meta);
4581
4866
  }
4582
- //#endregion
4583
- export { ANCESTRY_DEPENDENT_TAGS, APP_SCRIPT, ASIDE_DEMOTING_TAGS, CHILD_NODE_KEYS, IDREF_ATTRS, NAMING_ATTRS, ROBOTS_SOURCE_PATHS, ROOT_FILE_ENDPOINT_GLOB, SEARCH_RESULT_RULES, SECTIONING_TAGS, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, VITE_CONFIG_FILES, a11yAbbrTitle, a11yAccessibleName, a11yAriaHiddenFocus, a11yDeprecatedAria, a11yDeprecatedAttr, a11yDeprecatedElement, a11yDisallowedAriaProps, a11yDisallowedElement, a11yDoctype, a11yDuplicateLandmark, a11yIdDuplication, a11yInteractiveNesting, a11yInvalidAriaValue, a11yInvalidRole, a11yLabelHasControl, a11yNoAccesskey, a11yNoAutofocus, a11yNoDuplicateDt, a11yNoMissingIdRef, a11yPatternTitle, a11yPermittedContents, a11yPlaceholderLabelOption, a11yPositiveTabindex, a11yRequireDatetime, a11yRequiredAriaProps, a11yRequiredElement, a11yTopLevelLandmark, a11yUnknownAriaAttribute, a11yUnverifiedIdRef, a11yUseList, addFactsDirectives, allRules, architectureComponentSize, architectureDirectoryNaming, architectureDocLinkTarget, architecturePrivateScopeImport, architecturePropCount, architectureReservedDirectoryNames, architectureReservedNamePlacement, architectureRouteComponentImport, architectureUnitEntryFile, attrText, attrTextOf, attrValue, attrValueOf, buildHtmlDocument, buildJsonReport, classify, collectComponentFacts, collectConstantListExports, collectKitModuleFacts, collectSourceFiles, collectSuppressions, compileOverrides, computeHealth, computeScore, correctnessAutoplayMuted, correctnessBasePathNavigation, correctnessCheckableBindValue, correctnessEachIndexKey, correctnessEachKey, correctnessEffectAsDerived, correctnessEffectAsOnMount, correctnessInstanceBrowserGlobal, correctnessNonreactiveBuiltinState, correctnessOrphanEffect, correctnessOrphanLifecycle, correctnessPropMutation, correctnessServerBrowserGlobal, correctnessStalePropDerivation, correctnessUnmutatedState, declaredInstalledPackages, declaredLocalPackages, decodeFragmentId, defaultConfig, defaultProject, docsUrlFor, effectiveSeverity, emptyComponentFacts, escapeHtml, explainRule, findAttr, findMinifyDisabled, foldOccurrences, formatAgentReport, formatConsoleReport, formatFailedRuleWarning, formatGithubReport, formatHtmlReport, formatJsonReport, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, isClassicScriptType, isPenalized, isPlainObject, isSvgSrc, isTopFragment, lineOf, noColorPalette, packageJsonWorkspaceGlobs, parseComponentFacts, parseModuleProgram, parseSvelte, performanceFontPreloadCrossorigin, performanceHeavyImport, performanceIframeLoading, performanceImageDimensions, performanceImageLoadingHint, performanceLcpImage, performanceLoadWaterfall, performanceMinifyDisabled, performanceNamespaceImport, performancePreconnect, performancePreloadMissingAs, performanceRenderBlockingScript, performanceResponsiveImage, performanceSequentialAwaits, performanceStateRaw, pnpmWorkspaceGlobs, renderAppShell, resolveKitAliases, resolveKitPathsBase, resolveLandmark, resolveRepoLocalPath, resolveRuleOptions, routeNeverSsr, runAnalysis, runRules, safeHref, scoreColor, 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, servesRootFile, settingSeverity, shouldSkipRangeCheck, skippedFileWarnings, splitTokens, stripTextDirective, summarize, terminalSafe, textFromNodes, unknownDirectiveIds, validateRuleSetting, valueFromNodes, withFailedRulesOff, withIndexableOff, withInstalledPackages, withPackageImports, withReadLimit, withWorkspacePackages };
4867
+ export { ANCESTRY_DEPENDENT_TAGS, APP_SCRIPT, ASIDE_DEMOTING_TAGS, CHILD_NODE_KEYS, IDREF_ATTRS, NAMING_ATTRS, ROBOTS_SOURCE_PATHS, ROOT_FILE_ENDPOINT_GLOB, SEARCH_RESULT_RULES, SECTIONING_TAGS, SITEMAP_SOURCE_PATHS, SVELTE_CONFIG_FILES, VITE_CONFIG_FILES, a11yAbbrTitle, a11yAccessibleName, a11yAriaHiddenFocus, a11yDeprecatedAria, a11yDeprecatedAttr, a11yDeprecatedElement, a11yDisallowedAriaProps, a11yDisallowedElement, a11yDoctype, a11yDuplicateLandmark, a11yIdDuplication, a11yInteractiveNesting, a11yInvalidAriaValue, a11yInvalidRole, a11yLabelHasControl, a11yNoAccesskey, a11yNoAutofocus, a11yNoDuplicateDt, a11yNoMissingIdRef, a11yPatternTitle, a11yPermittedContents, a11yPlaceholderLabelOption, a11yPositiveTabindex, a11yRequireDatetime, a11yRequiredAriaProps, a11yRequiredElement, a11yTopLevelLandmark, a11yUnknownAriaAttribute, a11yUnverifiedIdRef, a11yUseList, addFactsDirectives, allRules, architectureComponentSize, architectureDirectoryNaming, architectureDocLinkTarget, architecturePrivateScopeImport, architecturePropCount, architectureReservedDirectoryNames, architectureReservedNamePlacement, architectureRouteComponentImport, architectureUnitEntryFile, attrText, attrTextOf, attrValue, attrValueOf, buildHtmlDocument, buildJsonReport, classify, collectComponentConstantLists, collectComponentFacts, collectConstantListExports, collectFalseExports, collectKitModuleFacts, collectSourceFiles, collectSuppressions, compileOverrides, computeHealth, computeScore, correctnessAutoplayMuted, correctnessBasePathNavigation, correctnessCheckableBindValue, correctnessEachIndexKey, correctnessEachKey, correctnessEffectAsDerived, correctnessEffectAsOnMount, correctnessInstanceBrowserGlobal, correctnessNonreactiveBuiltinState, correctnessOrphanEffect, correctnessOrphanLifecycle, correctnessPropMutation, correctnessServerBrowserGlobal, correctnessStalePropDerivation, correctnessUnmutatedState, declaredInstalledPackages, declaredLocalPackages, decodeFragmentId, defaultConfig, defaultProject, docsUrlFor, effectiveSeverity, emptyComponentFacts, escapeHtml, explainRule, findAttr, findKitHashRouterInSvelteConfig, findMinifyDisabled, foldOccurrences, formatAgentReport, formatConsoleReport, formatFailedRuleWarning, formatGithubReport, formatHtmlReport, formatJsonReport, formatJsonReportChunks, formatMarkdownReport, formatSarifReport, hasFailureAtOrAbove, hasRel, isClassicScriptType, isPenalized, isPlainObject, isSvgSrc, isTopFragment, layoutNeverRenders, lineOf, noColorPalette, packageJsonWorkspaceGlobs, pageRendersOnlyWhenBuilding, parseComponentFacts, parseModuleProgram, parseSvelte, performanceFontPreloadCrossorigin, performanceHeavyImport, performanceIframeLoading, performanceImageDimensions, performanceImageLoadingHint, performanceLcpImage, performanceLoadWaterfall, performanceMinifyDisabled, performanceNamespaceImport, performancePreconnect, performancePreloadMissingAs, performanceRenderBlockingScript, performanceResponsiveImage, performanceSequentialAwaits, performanceStateRaw, pnpmWorkspaceGlobs, renderAppShell, resolveKitAliases, resolveKitPathsBase, resolveLandmark, resolveRepoLocalPath, resolveRuleOptions, routeNeverSsr, runAnalysis, runRules, safeHref, scoreColor, 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, servesRootFile, settingSeverity, shouldSkipRangeCheck, skippedFileWarnings, splitTokens, stripTextDirective, summarize, terminalSafe, textFromNodes, unknownDirectiveIds, unwrapTs, validateRuleSetting, valueFromNodes, walkEstree, withFailedRulesOff, withIndexableOff, withInstalledPackages, withPackageImports, withReadLimit, withWorkspacePackages };