@drskillissue/ganko 0.2.1 → 0.2.6

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.
@@ -96,7 +96,8 @@ var ServerSettingsSchema = z.object({
96
96
  useESLintConfig: z.boolean().default(true),
97
97
  eslintConfigPath: z.string().optional(),
98
98
  accessibilityPolicy: AccessibilityPolicySchema.default("wcag-aa"),
99
- exclude: z.array(z.string()).default([])
99
+ exclude: z.array(z.string()).default([]),
100
+ enableTypeScriptDiagnostics: z.boolean().default(false)
100
101
  });
101
102
  var isBun = typeof globalThis.Bun !== "undefined";
102
103
  var CHAR_FOLD_BIT = 32;
@@ -21868,10 +21869,17 @@ function wireJSXHierarchy(graph) {
21868
21869
  }
21869
21870
  function findParentJSXNode(node) {
21870
21871
  let current = node.parent;
21872
+ let crossedFunctionBoundary = false;
21871
21873
  while (current) {
21872
21874
  if (ts119.isJsxElement(current) || ts119.isJsxFragment(current)) {
21873
21875
  return current;
21874
21876
  }
21877
+ if (ts119.isArrowFunction(current) || ts119.isFunctionExpression(current)) {
21878
+ crossedFunctionBoundary = true;
21879
+ }
21880
+ if (crossedFunctionBoundary && ts119.isJsxAttribute(current)) {
21881
+ return null;
21882
+ }
21875
21883
  current = current.parent;
21876
21884
  }
21877
21885
  return null;
@@ -30787,6 +30795,7 @@ function findNodeModulesPackage(importerFile, packageName) {
30787
30795
  }
30788
30796
 
30789
30797
  // src/cross-file/layout/scope.ts
30798
+ var CSS_COLOCATED_EXTENSIONS = [".css"];
30790
30799
  function collectCSSScopeBySolidFile(solids, css, moduleResolver) {
30791
30800
  const resolver = moduleResolver ?? createLayoutModuleResolver(solids, css);
30792
30801
  const cssFilesByNormalizedPath = buildCSSFileIndex(css);
@@ -30797,6 +30806,20 @@ function collectCSSScopeBySolidFile(solids, css, moduleResolver) {
30797
30806
  const solid = solids[i];
30798
30807
  if (!solid) continue;
30799
30808
  const scope = /* @__PURE__ */ new Set();
30809
+ const colocatedCssPath = resolveColocatedCss(solid.file, cssFilesByNormalizedPath);
30810
+ if (colocatedCssPath !== null) {
30811
+ const colocatedScope = getOrCollectTransitiveScope(
30812
+ colocatedCssPath,
30813
+ resolver,
30814
+ cssFilesByNormalizedPath,
30815
+ transitiveScopeByEntryPath
30816
+ );
30817
+ for (let k = 0; k < colocatedScope.length; k++) {
30818
+ const cs = colocatedScope[k];
30819
+ if (!cs) continue;
30820
+ scope.add(cs);
30821
+ }
30822
+ }
30800
30823
  for (let j = 0; j < solid.imports.length; j++) {
30801
30824
  const imp = solid.imports[j];
30802
30825
  if (!imp) continue;
@@ -30839,6 +30862,18 @@ function collectCSSScopeBySolidFile(solids, css, moduleResolver) {
30839
30862
  }
30840
30863
  return out;
30841
30864
  }
30865
+ function resolveColocatedCss(solidFilePath, cssFilesByNormalizedPath) {
30866
+ const dotIndex = solidFilePath.lastIndexOf(".");
30867
+ if (dotIndex === -1) return null;
30868
+ const stem = solidFilePath.slice(0, dotIndex);
30869
+ for (let i = 0; i < CSS_COLOCATED_EXTENSIONS.length; i++) {
30870
+ const ext = CSS_COLOCATED_EXTENSIONS[i];
30871
+ if (!ext) continue;
30872
+ const candidate = canonicalPath(stem + ext);
30873
+ if (cssFilesByNormalizedPath.has(candidate)) return candidate;
30874
+ }
30875
+ return null;
30876
+ }
30842
30877
  function buildCSSFileIndex(css) {
30843
30878
  const out = /* @__PURE__ */ new Map();
30844
30879
  for (let i = 0; i < css.files.length; i++) {
@@ -30929,7 +30964,8 @@ var layoutSignalNames = [
30929
30964
  "inset-block-start",
30930
30965
  "inset-block-end",
30931
30966
  "writing-mode",
30932
- "direction"
30967
+ "direction",
30968
+ "contain"
30933
30969
  ];
30934
30970
 
30935
30971
  // src/cross-file/layout/util.ts
@@ -32769,73 +32805,108 @@ function compoundGroupNeedsAttributes(groups) {
32769
32805
  }
32770
32806
  function selectorMatchesLayoutElement(matcher, node, perf, fileRootElements = null, logger = noopLogger) {
32771
32807
  const firstCompound = matcher.compoundsRightToLeft[0];
32772
- if (firstCompound === void 0) return false;
32773
- if (!matchesCompound(node, firstCompound)) return false;
32774
- if (matcher.compoundsRightToLeft.length === 1) return true;
32775
- return matchesChain(matcher, node, 0, perf, fileRootElements, logger);
32808
+ if (firstCompound === void 0) return "no-match";
32809
+ const subjectResult = matchesCompound(node, firstCompound);
32810
+ if (subjectResult === "no-match") return "no-match";
32811
+ if (matcher.compoundsRightToLeft.length === 1) return subjectResult;
32812
+ const chainResult = matchesChain(matcher, node, 0, perf, fileRootElements, logger);
32813
+ if (chainResult === "no-match") return "no-match";
32814
+ if (subjectResult === "conditional" || chainResult === "conditional") return "conditional";
32815
+ return "match";
32776
32816
  }
32777
32817
  function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
32778
32818
  const combinator = matcher.combinatorsRightToLeft[index];
32779
- if (combinator === void 0) return false;
32819
+ if (combinator === void 0) return "no-match";
32780
32820
  const nextIndex = index + 1;
32781
32821
  const targetCompound = matcher.compoundsRightToLeft[nextIndex];
32782
- if (targetCompound === void 0) return false;
32822
+ if (targetCompound === void 0) return "no-match";
32783
32823
  const isFinal = nextIndex === matcher.compoundsRightToLeft.length - 1;
32784
32824
  if (combinator === "child") {
32785
32825
  const parent = node.parentElementNode;
32786
- if (parent === null) return false;
32826
+ if (parent === null) return "no-match";
32787
32827
  perf.ancestryChecks++;
32788
- if (!matchesCompound(parent, targetCompound)) return false;
32789
- if (isFinal) return true;
32790
- return matchesChain(matcher, parent, nextIndex, perf, fileRootElements, logger);
32828
+ const compoundResult = matchesCompound(parent, targetCompound);
32829
+ if (compoundResult === "no-match") return "no-match";
32830
+ if (isFinal) return compoundResult;
32831
+ const chainResult = matchesChain(matcher, parent, nextIndex, perf, fileRootElements, logger);
32832
+ return mergeMatchResults(compoundResult, chainResult);
32791
32833
  }
32792
32834
  if (combinator === "adjacent") {
32793
32835
  const sibling = node.previousSiblingNode;
32794
- if (sibling === null) return false;
32836
+ if (sibling === null) return "no-match";
32795
32837
  perf.ancestryChecks++;
32796
- if (!matchesCompound(sibling, targetCompound)) return false;
32797
- if (isFinal) return true;
32798
- return matchesChain(matcher, sibling, nextIndex, perf, fileRootElements, logger);
32838
+ const compoundResult = matchesCompound(sibling, targetCompound);
32839
+ if (compoundResult === "no-match") return "no-match";
32840
+ if (isFinal) return compoundResult;
32841
+ const chainResult = matchesChain(matcher, sibling, nextIndex, perf, fileRootElements, logger);
32842
+ return mergeMatchResults(compoundResult, chainResult);
32799
32843
  }
32800
32844
  if (combinator === "sibling") {
32801
32845
  let sibling = node.previousSiblingNode;
32802
32846
  while (sibling !== null) {
32803
32847
  perf.ancestryChecks++;
32804
- if (matchesCompound(sibling, targetCompound)) {
32805
- if (isFinal) return true;
32806
- if (matchesChain(matcher, sibling, nextIndex, perf, fileRootElements, logger)) return true;
32848
+ const compoundResult = matchesCompound(sibling, targetCompound);
32849
+ if (compoundResult !== "no-match") {
32850
+ if (isFinal) return compoundResult;
32851
+ const chainResult = matchesChain(matcher, sibling, nextIndex, perf, fileRootElements, logger);
32852
+ if (chainResult !== "no-match") return mergeMatchResults(compoundResult, chainResult);
32807
32853
  }
32808
32854
  sibling = sibling.previousSiblingNode;
32809
32855
  }
32810
- return false;
32856
+ return "no-match";
32811
32857
  }
32858
+ let bestResult = "no-match";
32812
32859
  let ancestor = node.parentElementNode;
32813
32860
  while (ancestor !== null) {
32814
32861
  perf.ancestryChecks++;
32815
- if (matchesCompound(ancestor, targetCompound)) {
32816
- if (isFinal) return true;
32817
- if (matchesChain(matcher, ancestor, nextIndex, perf, fileRootElements, logger)) return true;
32862
+ const compoundResult = matchesCompound(ancestor, targetCompound);
32863
+ if (compoundResult !== "no-match") {
32864
+ if (isFinal) return compoundResult;
32865
+ const chainResult = matchesChain(matcher, ancestor, nextIndex, perf, fileRootElements, logger);
32866
+ if (chainResult !== "no-match") {
32867
+ const merged = mergeMatchResults(compoundResult, chainResult);
32868
+ if (merged === "match") return "match";
32869
+ bestResult = merged;
32870
+ }
32818
32871
  }
32819
32872
  ancestor = ancestor.parentElementNode;
32820
32873
  }
32821
32874
  if (fileRootElements !== null) {
32875
+ if (logger.enabled) {
32876
+ const compoundDesc = describeCompound(targetCompound);
32877
+ logger.trace(`[selector-match] fallback: node=${node.key} tag=${node.tagName} checking ${fileRootElements.length} roots for compound=${compoundDesc}`);
32878
+ }
32822
32879
  for (let r = 0; r < fileRootElements.length; r++) {
32823
32880
  const root = fileRootElements[r];
32824
32881
  if (root === void 0) continue;
32825
32882
  if (root === node) continue;
32826
32883
  if (root.solidFile !== node.solidFile) continue;
32827
32884
  perf.ancestryChecks++;
32828
- if (matchesCompound(root, targetCompound)) {
32885
+ const compoundResult = matchesCompound(root, targetCompound);
32886
+ if (logger.enabled && compoundResult === "no-match") {
32887
+ logger.trace(`[selector-match] fallback MISS: root=${root.key} tag=${root.tagName} attrs=[${[...root.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}]`);
32888
+ }
32889
+ if (compoundResult !== "no-match") {
32829
32890
  if (logger.enabled) {
32830
32891
  const compoundDesc = describeCompound(targetCompound);
32831
32892
  logger.debug(`[selector-match] fallback HIT: node=${node.key} tag=${node.tagName} matched root=${root.key} tag=${root.tagName} compound=${compoundDesc} isFinal=${isFinal}`);
32832
32893
  }
32833
- if (isFinal) return true;
32834
- if (matchesChain(matcher, root, nextIndex, perf, fileRootElements, logger)) return true;
32894
+ if (isFinal) return compoundResult;
32895
+ const chainResult = matchesChain(matcher, root, nextIndex, perf, fileRootElements, logger);
32896
+ if (chainResult !== "no-match") {
32897
+ const merged = mergeMatchResults(compoundResult, chainResult);
32898
+ if (merged === "match") return "match";
32899
+ bestResult = merged;
32900
+ }
32835
32901
  }
32836
32902
  }
32837
32903
  }
32838
- return false;
32904
+ return bestResult;
32905
+ }
32906
+ function mergeMatchResults(a, b) {
32907
+ if (a === "no-match" || b === "no-match") return "no-match";
32908
+ if (a === "conditional" || b === "conditional") return "conditional";
32909
+ return "match";
32839
32910
  }
32840
32911
  function describeCompound(compound) {
32841
32912
  const parts = [];
@@ -32855,15 +32926,16 @@ function describeCompound(compound) {
32855
32926
  return parts.join("") || "*";
32856
32927
  }
32857
32928
  function matchesCompound(node, compound) {
32858
- if (compound.tagName !== null && node.tagName !== compound.tagName) return false;
32929
+ if (compound.tagName !== null && node.tagName !== compound.tagName) return "no-match";
32859
32930
  if (compound.idValue !== null) {
32860
32931
  const id = node.attributes.get("id");
32861
- if (id !== compound.idValue) return false;
32932
+ if (id !== compound.idValue) return "no-match";
32862
32933
  }
32863
- if (!matchesRequiredClasses(compound.classes, node.classTokenSet)) return false;
32864
- if (!matchesRequiredAttributes(compound.attributes, node.attributes)) return false;
32865
- if (!matchesPseudoConstraints(node, compound.pseudo)) return false;
32866
- return true;
32934
+ if (!matchesRequiredClasses(compound.classes, node.classTokenSet)) return "no-match";
32935
+ const attrResult = matchesRequiredAttributes(compound.attributes, node.attributes);
32936
+ if (attrResult === "no-match") return "no-match";
32937
+ if (!matchesPseudoConstraints(node, compound.pseudo)) return "no-match";
32938
+ return attrResult;
32867
32939
  }
32868
32940
  function matchesPseudoConstraints(node, pseudo) {
32869
32941
  if (pseudo.firstChild && node.siblingIndex !== 1) return false;
@@ -32888,7 +32960,7 @@ function matchesPseudoConstraints(node, pseudo) {
32888
32960
  for (let j = 0; j < group.length; j++) {
32889
32961
  const compound = group[j];
32890
32962
  if (compound === void 0) continue;
32891
- if (!matchesCompound(node, compound)) continue;
32963
+ if (matchesCompound(node, compound) === "no-match") continue;
32892
32964
  matched = true;
32893
32965
  break;
32894
32966
  }
@@ -32900,7 +32972,7 @@ function matchesPseudoConstraints(node, pseudo) {
32900
32972
  for (let j = 0; j < group.length; j++) {
32901
32973
  const compound = group[j];
32902
32974
  if (compound === void 0) continue;
32903
- if (!matchesCompound(node, compound)) continue;
32975
+ if (matchesCompound(node, compound) === "no-match") continue;
32904
32976
  return false;
32905
32977
  }
32906
32978
  }
@@ -33545,19 +33617,24 @@ function matchesRequiredClasses(required, actual) {
33545
33617
  return true;
33546
33618
  }
33547
33619
  function matchesRequiredAttributes(required, actual) {
33548
- if (required.length === 0) return true;
33620
+ if (required.length === 0) return "match";
33621
+ let hasConditional = false;
33549
33622
  for (let i = 0; i < required.length; i++) {
33550
33623
  const constraint = required[i];
33551
33624
  if (constraint === void 0) continue;
33552
- if (!actual.has(constraint.name)) return false;
33625
+ if (!actual.has(constraint.name)) return "no-match";
33553
33626
  if (constraint.operator === "exists") continue;
33554
33627
  const actualValue = actual.get(constraint.name);
33555
- if (actualValue === null || actualValue === void 0) return false;
33556
- if (constraint.value === null) return false;
33628
+ if (actualValue === void 0) return "no-match";
33629
+ if (actualValue === null) {
33630
+ hasConditional = true;
33631
+ continue;
33632
+ }
33633
+ if (constraint.value === null) return "no-match";
33557
33634
  if (matchesAttributeValue(actualValue, constraint)) continue;
33558
- return false;
33635
+ return "no-match";
33559
33636
  }
33560
- return true;
33637
+ return hasConditional ? "conditional" : "match";
33561
33638
  }
33562
33639
  function matchesAttributeValue(actualValue, constraint) {
33563
33640
  const expectedValue = constraint.value;
@@ -36542,6 +36619,11 @@ function compareCascadePositions(posA, posB) {
36542
36619
  }
36543
36620
 
36544
36621
  // src/cross-file/layout/cascade-builder.ts
36622
+ var DYNAMIC_ATTRIBUTE_GUARD = {
36623
+ kind: 1 /* Conditional */,
36624
+ conditions: [{ kind: "dynamic-attribute", query: null, key: "dynamic-attribute:*" }],
36625
+ key: "dynamic-attribute:*"
36626
+ };
36545
36627
  var SCROLLABLE_VALUES = /* @__PURE__ */ new Set(["auto", "scroll"]);
36546
36628
  var EMPTY_EXPANSION_RESULT = [];
36547
36629
  function collectMonitoredDeclarations(selector, layerOrder, guard) {
@@ -36616,14 +36698,21 @@ function appendMatchingEdgesFromSelectorIds(ctx, selectorIds, node, applies, app
36616
36698
  if (!selector) {
36617
36699
  throw new Error(`missing selector ${selectorId}`);
36618
36700
  }
36619
- if (!selectorMatchesLayoutElement(metadata.matcher, node, ctx.perf, fileRoots, ctx.logger)) continue;
36701
+ const matchResult = selectorMatchesLayoutElement(metadata.matcher, node, ctx.perf, fileRoots, ctx.logger);
36702
+ if (matchResult === "no-match") continue;
36620
36703
  const edge = {
36621
36704
  selectorId: selector.id,
36622
36705
  specificityScore: selector.specificityScore,
36623
- sourceOrder: selector.rule.sourceOrder
36706
+ sourceOrder: selector.rule.sourceOrder,
36707
+ conditionalMatch: matchResult === "conditional"
36624
36708
  };
36625
36709
  applies.push(edge);
36626
36710
  ctx.perf.matchEdgesCreated++;
36711
+ if (ctx.logger.enabled) {
36712
+ ctx.logger.trace(
36713
+ `[cascade] edge node=${node.key} selector=${selector.id} match=${matchResult} conditional=${edge.conditionalMatch} selector-raw=${selector.raw.slice(0, 80)}`
36714
+ );
36715
+ }
36627
36716
  const existing = appliesByElementNodeMutable.get(node);
36628
36717
  if (existing) {
36629
36718
  existing.push(edge);
@@ -36684,10 +36773,11 @@ function buildCascadeMapForElement(node, edges, monitoredDeclarationsBySelectorI
36684
36773
  const declaration = declarations[j];
36685
36774
  if (!declaration) continue;
36686
36775
  const property = declaration.property;
36776
+ const guardProvenance = edge.conditionalMatch && declaration.guardProvenance.kind === 0 /* Unconditional */ ? DYNAMIC_ATTRIBUTE_GUARD : declaration.guardProvenance;
36687
36777
  const newDeclaration = {
36688
36778
  value: declaration.value,
36689
36779
  source: 0 /* Selector */,
36690
- guardProvenance: declaration.guardProvenance
36780
+ guardProvenance
36691
36781
  };
36692
36782
  const existingPosition = positions.get(property);
36693
36783
  if (existingPosition === void 0) {
@@ -36769,7 +36859,7 @@ function resolveRuleLayerOrder(rule, css) {
36769
36859
  if (!name) return 0;
36770
36860
  return css.layerOrder.get(name) ?? 0;
36771
36861
  }
36772
- function buildConditionalDeltaIndex(elements, appliesByNode, monitoredDeclarationsBySelectorId) {
36862
+ function buildConditionalDeltaIndex(elements, appliesByNode, monitoredDeclarationsBySelectorId, selectorsById) {
36773
36863
  const conditionalSignalDeltaFactsByNode = /* @__PURE__ */ new Map();
36774
36864
  const elementsWithConditionalDeltaBySignal = /* @__PURE__ */ new Map();
36775
36865
  const baselineOffsetFactsByNode = /* @__PURE__ */ new Map();
@@ -36780,11 +36870,16 @@ function buildConditionalDeltaIndex(elements, appliesByNode, monitoredDeclaratio
36780
36870
  let factByProperty = null;
36781
36871
  if (edges !== void 0 && edges.length > 0) {
36782
36872
  const byProperty = /* @__PURE__ */ new Map();
36873
+ let conditionalAttributeDispatch = null;
36783
36874
  for (let j = 0; j < edges.length; j++) {
36784
36875
  const currentEdge = edges[j];
36785
36876
  if (!currentEdge) continue;
36786
36877
  const declarations = monitoredDeclarationsBySelectorId.get(currentEdge.selectorId);
36787
36878
  if (!declarations) continue;
36879
+ let conditionalAttributeName = null;
36880
+ if (currentEdge.conditionalMatch) {
36881
+ conditionalAttributeName = identifyConditionalAttribute(currentEdge.selectorId, node, selectorsById);
36882
+ }
36788
36883
  for (let k = 0; k < declarations.length; k++) {
36789
36884
  const declaration = declarations[k];
36790
36885
  if (!declaration) continue;
@@ -36801,8 +36896,17 @@ function buildConditionalDeltaIndex(elements, appliesByNode, monitoredDeclaratio
36801
36896
  };
36802
36897
  byProperty.set(property, bucket);
36803
36898
  }
36804
- if (declaration.guardProvenance.kind === 1 /* Conditional */) {
36899
+ if (declaration.guardProvenance.kind === 1 /* Conditional */ || currentEdge.conditionalMatch) {
36805
36900
  bucket.conditional.add(expandedEntry.value);
36901
+ if (conditionalAttributeName !== null && declaration.guardProvenance.kind !== 1 /* Conditional */) {
36902
+ if (conditionalAttributeDispatch === null) conditionalAttributeDispatch = /* @__PURE__ */ new Map();
36903
+ let dispatchMap = conditionalAttributeDispatch.get(property);
36904
+ if (!dispatchMap) {
36905
+ dispatchMap = /* @__PURE__ */ new Map();
36906
+ conditionalAttributeDispatch.set(property, dispatchMap);
36907
+ }
36908
+ dispatchMap.set(expandedEntry.value, conditionalAttributeName);
36909
+ }
36806
36910
  continue;
36807
36911
  }
36808
36912
  bucket.unconditional.add(expandedEntry.value);
@@ -36827,6 +36931,24 @@ function buildConditionalDeltaIndex(elements, appliesByNode, monitoredDeclaratio
36827
36931
  }
36828
36932
  }
36829
36933
  }
36934
+ if (hasDelta && conditionalAttributeDispatch !== null) {
36935
+ const dispatchMap = conditionalAttributeDispatch.get(property);
36936
+ if (dispatchMap !== void 0 && dispatchMap.size === conditionalValues.length) {
36937
+ let singleAttribute = null;
36938
+ let allSameAttribute = true;
36939
+ for (const attrName of dispatchMap.values()) {
36940
+ if (singleAttribute === null) {
36941
+ singleAttribute = attrName;
36942
+ } else if (singleAttribute !== attrName) {
36943
+ allSameAttribute = false;
36944
+ break;
36945
+ }
36946
+ }
36947
+ if (allSameAttribute && singleAttribute !== null) {
36948
+ hasDelta = false;
36949
+ }
36950
+ }
36951
+ }
36830
36952
  const scrollProfile = buildScrollValueProfile(property, conditionalValues, unconditionalValues);
36831
36953
  facts.set(property, {
36832
36954
  hasConditional,
@@ -36912,6 +37034,25 @@ function buildConditionalDeltaSignalGroupElements(elementsWithConditionalDeltaBy
36912
37034
  }
36913
37035
  return out;
36914
37036
  }
37037
+ function identifyConditionalAttribute(selectorId, node, selectorsById) {
37038
+ const selector = selectorsById.get(selectorId);
37039
+ if (!selector) return null;
37040
+ const constraints = selector.anchor.attributes;
37041
+ let dynamicAttributeName = null;
37042
+ for (let i = 0; i < constraints.length; i++) {
37043
+ const constraint = constraints[i];
37044
+ if (!constraint) continue;
37045
+ if (constraint.operator !== "equals") continue;
37046
+ if (constraint.value === null) continue;
37047
+ const elementValue = node.attributes.get(constraint.name);
37048
+ if (elementValue !== null) continue;
37049
+ if (dynamicAttributeName !== null && dynamicAttributeName !== constraint.name) {
37050
+ return null;
37051
+ }
37052
+ dynamicAttributeName = constraint.name;
37053
+ }
37054
+ return dynamicAttributeName;
37055
+ }
36915
37056
  function buildScrollValueProfile(property, conditionalValues, unconditionalValues) {
36916
37057
  if (property !== "overflow" && property !== "overflow-y") {
36917
37058
  return {
@@ -37293,6 +37434,23 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37293
37434
  const moduleResolver = createLayoutModuleResolver(solids, css);
37294
37435
  const componentHostResolver = createLayoutComponentHostResolver(solids, moduleResolver, logger);
37295
37436
  const cssScopeBySolidFile = collectCSSScopeBySolidFile(solids, css, moduleResolver);
37437
+ if (logger.enabled) {
37438
+ for (const [solidFile, scopePaths] of cssScopeBySolidFile) {
37439
+ if (scopePaths.length > 0) {
37440
+ let names = "";
37441
+ for (let k = 0; k < scopePaths.length; k++) {
37442
+ const p = scopePaths[k];
37443
+ if (!p) continue;
37444
+ if (names.length > 0) names += ", ";
37445
+ const slash = p.lastIndexOf("/");
37446
+ names += slash === -1 ? p : p.slice(slash + 1);
37447
+ }
37448
+ logger.trace(`[scope] ${solidFile} \u2192 ${scopePaths.length} CSS files: ${names}`);
37449
+ } else {
37450
+ logger.trace(`[scope] ${solidFile} \u2192 EMPTY (no CSS in scope)`);
37451
+ }
37452
+ }
37453
+ }
37296
37454
  const selectorIndexStartedAt = performance.now();
37297
37455
  const scopedSelectorsBySolidFile = buildScopedSelectorIndexBySolidFile(
37298
37456
  cssScopeBySolidFile,
@@ -37435,13 +37593,30 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37435
37593
  appliesByNode.set(node, edges);
37436
37594
  }
37437
37595
  perf.cascadeBuildMs = performance.now() - cascadeStartedAt;
37596
+ if (logger.enabled) {
37597
+ for (let i = 0; i < elements.length; i++) {
37598
+ const node = elements[i];
37599
+ if (!node) continue;
37600
+ const cascade = cascadeByElementNode.get(node);
37601
+ if (!cascade || cascade.size === 0) continue;
37602
+ const displayDecl = cascade.get("display");
37603
+ const flexDirDecl = cascade.get("flex-direction");
37604
+ if (!displayDecl && !flexDirDecl) continue;
37605
+ const displayGuard = displayDecl?.guardProvenance.kind === 1 /* Conditional */ ? "conditional" : "unconditional";
37606
+ const flexDirGuard = flexDirDecl?.guardProvenance.kind === 1 /* Conditional */ ? "conditional" : "unconditional";
37607
+ logger.trace(
37608
+ `[cascade] node=${node.key} tag=${node.tagName ?? "null"} display=${displayDecl ? `${displayDecl.value}(${displayGuard})` : "absent"} flex-direction=${flexDirDecl ? `${flexDirDecl.value}(${flexDirGuard})` : "absent"} edges=${(appliesByNode.get(node) ?? []).length} attrs=[${[...node.attributes.keys()].join(",")}]`
37609
+ );
37610
+ }
37611
+ }
37438
37612
  const snapshotByElementNode = buildSignalSnapshotIndex(elements, cascadeByElementNode, perf);
37439
37613
  const measurementNodeByRootKey = buildMeasurementNodeIndex(elements, childrenByParentNodeMutable, snapshotByElementNode);
37440
37614
  const factIndex = buildElementFactIndex(elements, snapshotByElementNode);
37441
37615
  const conditionalDeltaIndex = buildConditionalDeltaIndex(
37442
37616
  elements,
37443
37617
  appliesByNode,
37444
- monitoredDeclarationsBySelectorId
37618
+ monitoredDeclarationsBySelectorId,
37619
+ selectorsById
37445
37620
  );
37446
37621
  const elementsWithConditionalOverflowDelta = buildConditionalDeltaSignalGroupElements(
37447
37622
  conditionalDeltaIndex.elementsWithConditionalDeltaBySignal,
@@ -37452,7 +37627,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37452
37627
  layoutOffsetSignals
37453
37628
  );
37454
37629
  const statefulRuleIndexes = buildStatefulRuleIndexes(css.rules);
37455
- const contextByParentNode = buildContextIndex(childrenByParentNodeMutable, snapshotByElementNode, perf);
37630
+ const contextByParentNode = buildContextIndex(childrenByParentNodeMutable, snapshotByElementNode, perf, logger);
37456
37631
  const cohortIndex = buildCohortIndex({
37457
37632
  childrenByParentNode: childrenByParentNodeMutable,
37458
37633
  contextByParentNode,
@@ -37872,16 +38047,27 @@ function computeFlowParticipationFact(snapshot) {
37872
38047
  hasUnconditionalOutOfFlow: signal.guard.kind === 0 /* Unconditional */ && outOfFlow
37873
38048
  };
37874
38049
  }
37875
- function buildContextIndex(childrenByParentNode, snapshotByElementNode, perf) {
38050
+ function buildContextIndex(childrenByParentNode, snapshotByElementNode, perf, logger) {
37876
38051
  const out = /* @__PURE__ */ new Map();
38052
+ const trace = logger.enabled;
37877
38053
  for (const [parent, children] of childrenByParentNode) {
37878
38054
  if (children.length < 2) continue;
37879
38055
  const snapshot = snapshotByElementNode.get(parent);
37880
38056
  if (!snapshot) {
37881
38057
  throw new Error(`missing parent snapshot for context classification ${parent.key}`);
37882
38058
  }
37883
- out.set(parent, createAlignmentContextForParent(parent, snapshot));
38059
+ const ctx = createAlignmentContextForParent(parent, snapshot);
38060
+ out.set(parent, ctx);
37884
38061
  perf.contextsClassified++;
38062
+ if (trace) {
38063
+ const displaySignal = snapshot.signals.get("display");
38064
+ const flexDirSignal = snapshot.signals.get("flex-direction");
38065
+ const displayDesc = displaySignal ? `${displaySignal.kind}:${displaySignal.kind === "known" ? displaySignal.normalized : "?"}(guard=${displaySignal.guard.kind === 1 /* Conditional */ ? "conditional" : "unconditional"})` : "absent";
38066
+ const flexDirDesc = flexDirSignal ? `${flexDirSignal.kind}:${flexDirSignal.kind === "known" ? flexDirSignal.normalized : "?"}(guard=${flexDirSignal.guard.kind === 1 /* Conditional */ ? "conditional" : "unconditional"})` : "absent";
38067
+ logger.trace(
38068
+ `[context] parent=${parent.key} tag=${parent.tagName ?? "null"} children=${children.length} display=${displayDesc} flex-direction=${flexDirDesc} \u2192 kind=${ctx.kind} certainty=${ctx.certainty} crossAxisIsBlockAxis=${ctx.crossAxisIsBlockAxis} baseline=${ctx.baselineRelevance}`
38069
+ );
38070
+ }
37885
38071
  }
37886
38072
  return out;
37887
38073
  }
@@ -39508,7 +39694,13 @@ var MIN_OFFSET_PX_THRESHOLD = 2;
39508
39694
  var siblingAlignmentDetector = {
39509
39695
  id: "sibling-alignment-outlier",
39510
39696
  collect: collectAlignmentCases,
39511
- evaluate(input) {
39697
+ evaluate(input, context) {
39698
+ if (context.logger.enabled) {
39699
+ const ctx = input.context;
39700
+ context.logger.trace(
39701
+ `[sibling-alignment] evaluate subject=${input.subject.elementKey} tag=${input.subject.tag} parent=${ctx.parentElementKey} parentTag=${ctx.parentTag} context.kind=${ctx.kind} certainty=${ctx.certainty} display=${ctx.parentDisplay} alignItems=${ctx.parentAlignItems} crossAxisIsBlockAxis=${ctx.crossAxisIsBlockAxis} crossAxisCertainty=${ctx.crossAxisIsBlockAxisCertainty} baseline=${ctx.baselineRelevance}`
39702
+ );
39703
+ }
39512
39704
  const decision = evaluateAlignmentCase(input);
39513
39705
  if (decision.kind === "reject") {
39514
39706
  return {
@@ -40626,8 +40818,16 @@ function isExemptFromCLS(layout, solidFile, element, property) {
40626
40818
  if (POSITIONED_OFFSET_PROPERTIES.has(property) && flowFact.position !== null && flowFact.position !== "static") {
40627
40819
  return true;
40628
40820
  }
40821
+ if (hasLayoutContainment(node) || node.parentElementNode !== null && hasLayoutContainment(node.parentElementNode)) {
40822
+ return true;
40823
+ }
40629
40824
  return false;
40630
40825
  }
40826
+ function hasLayoutContainment(node) {
40827
+ const contain = node.inlineStyleValues.get("contain");
40828
+ if (contain === void 0) return false;
40829
+ return contain === "layout" || contain === "strict" || contain === "content" || contain.includes("layout");
40830
+ }
40631
40831
  function hasUnstableLayoutDelta(property, node) {
40632
40832
  const unwrapped = unwrapTypeWrapper(node);
40633
40833
  if (isStaticComparable(property, unwrapped)) return false;
@@ -41074,4 +41274,4 @@ export {
41074
41274
  rules3,
41075
41275
  runCrossFileRules
41076
41276
  };
41077
- //# sourceMappingURL=chunk-CAKVXEYV.js.map
41277
+ //# sourceMappingURL=chunk-FTIRRRQY.js.map