@drskillissue/ganko 0.1.19 → 0.1.20

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.
@@ -30006,6 +30006,7 @@ function readStatefulBaseValueIndex(graph) {
30006
30006
  }
30007
30007
 
30008
30008
  // src/cross-file/layout/context-classification.ts
30009
+ var WHITESPACE_RE3 = /\s+/;
30009
30010
  var TABLE_SEMANTIC_TAGS = /* @__PURE__ */ new Set(["table", "thead", "tbody", "tfoot", "tr", "td", "th"]);
30010
30011
  var TABLE_DISPLAY_VALUES = /* @__PURE__ */ new Set([
30011
30012
  "table",
@@ -30044,6 +30045,7 @@ function createAlignmentContextForParent(parent, snapshot) {
30044
30045
  const classified = classifyKind(evidence);
30045
30046
  const contextCertainty = combineCertainty(classified.certainty, axis.certainty);
30046
30047
  const certainty = combineCertainty(contextCertainty, inlineDirection.certainty);
30048
+ const baselineRelevance = computeBaselineRelevance(classified.kind, parentAlignItems, parentPlaceItems);
30047
30049
  const out = {
30048
30050
  kind: classified.kind,
30049
30051
  certainty,
@@ -30059,6 +30061,7 @@ function createAlignmentContextForParent(parent, snapshot) {
30059
30061
  parentAlignItems,
30060
30062
  parentPlaceItems,
30061
30063
  hasPositionedOffset: positionedOffset.hasPositionedOffset,
30064
+ baselineRelevance,
30062
30065
  evidence
30063
30066
  };
30064
30067
  return out;
@@ -30279,6 +30282,63 @@ function combineCertainty(left, right) {
30279
30282
  if (left === "conditional" || right === "conditional") return "conditional";
30280
30283
  return "resolved";
30281
30284
  }
30285
+ var FLEX_GRID_GEOMETRIC_ALIGN_ITEMS = /* @__PURE__ */ new Set([
30286
+ "center",
30287
+ "flex-start",
30288
+ "flex-end",
30289
+ "start",
30290
+ "end",
30291
+ "stretch",
30292
+ "self-start",
30293
+ "self-end",
30294
+ "normal"
30295
+ ]);
30296
+ function computeBaselineRelevance(kind, parentAlignItems, parentPlaceItems) {
30297
+ if (kind === "flex-cross-axis" || kind === "grid-cross-axis") {
30298
+ const effective = resolveEffectiveAlignItems(parentAlignItems, parentPlaceItems);
30299
+ if (effective === null) return "relevant";
30300
+ return FLEX_GRID_GEOMETRIC_ALIGN_ITEMS.has(effective) ? "irrelevant" : "relevant";
30301
+ }
30302
+ return "relevant";
30303
+ }
30304
+ function resolveEffectiveAlignItems(alignItems, placeItems) {
30305
+ if (alignItems !== null) return alignItems;
30306
+ if (placeItems === null) return null;
30307
+ const firstToken2 = placeItems.split(WHITESPACE_RE3)[0];
30308
+ return firstToken2 ?? null;
30309
+ }
30310
+ var TABLE_CELL_GEOMETRIC_VERTICAL_ALIGN = /* @__PURE__ */ new Set([
30311
+ "middle",
30312
+ "top",
30313
+ "bottom"
30314
+ ]);
30315
+ function finalizeTableCellBaselineRelevance(contextByParentNode, cohortVerticalAlignConsensus) {
30316
+ for (const [parent, consensusValue] of cohortVerticalAlignConsensus) {
30317
+ const context = contextByParentNode.get(parent);
30318
+ if (!context) continue;
30319
+ if (context.kind !== "table-cell") continue;
30320
+ if (consensusValue === null) continue;
30321
+ if (!TABLE_CELL_GEOMETRIC_VERTICAL_ALIGN.has(consensusValue)) continue;
30322
+ contextByParentNode.set(parent, {
30323
+ kind: context.kind,
30324
+ certainty: context.certainty,
30325
+ parentSolidFile: context.parentSolidFile,
30326
+ parentElementId: context.parentElementId,
30327
+ parentElementKey: context.parentElementKey,
30328
+ parentTag: context.parentTag,
30329
+ axis: context.axis,
30330
+ axisCertainty: context.axisCertainty,
30331
+ inlineDirection: context.inlineDirection,
30332
+ inlineDirectionCertainty: context.inlineDirectionCertainty,
30333
+ parentDisplay: context.parentDisplay,
30334
+ parentAlignItems: context.parentAlignItems,
30335
+ parentPlaceItems: context.parentPlaceItems,
30336
+ hasPositionedOffset: context.hasPositionedOffset,
30337
+ baselineRelevance: "irrelevant",
30338
+ evidence: context.evidence
30339
+ });
30340
+ }
30341
+ }
30282
30342
 
30283
30343
  // src/cross-file/layout/diagnostics.ts
30284
30344
  var FINDING_WEIGHT_BY_KIND = /* @__PURE__ */ new Map([
@@ -32974,7 +33034,7 @@ var UNCONDITIONAL_GUARD = {
32974
33034
  conditions: [],
32975
33035
  key: "always"
32976
33036
  };
32977
- var WHITESPACE_RE3 = /\s+/g;
33037
+ var WHITESPACE_RE4 = /\s+/g;
32978
33038
  function resolveRuleGuard(rule) {
32979
33039
  const conditions = collectRuleConditions(rule);
32980
33040
  if (conditions.length === 0) return UNCONDITIONAL_GUARD;
@@ -33033,7 +33093,7 @@ function buildCondition(kind, query) {
33033
33093
  }
33034
33094
  function normalizeQuery(query) {
33035
33095
  if (query === null) return null;
33036
- const normalized = query.trim().toLowerCase().replace(WHITESPACE_RE3, " ");
33096
+ const normalized = query.trim().toLowerCase().replace(WHITESPACE_RE4, " ");
33037
33097
  if (normalized.length === 0) return null;
33038
33098
  return normalized;
33039
33099
  }
@@ -33655,12 +33715,7 @@ function resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints
33655
33715
  return alignmentStrengthCalibration.compositionMixedOutlierAmongReplacedStrength;
33656
33716
  }
33657
33717
  function hasSharedBaselineAlignment(context) {
33658
- if (context.kind === "inline-formatting" || context.kind === "table-cell") return true;
33659
- if (context.kind === "flex-cross-axis" || context.kind === "grid-cross-axis") {
33660
- const alignItems = context.parentAlignItems;
33661
- return alignItems === null || alignItems === "baseline";
33662
- }
33663
- return false;
33718
+ return context.baselineRelevance === "relevant";
33664
33719
  }
33665
33720
  function resolveMajorityClassification(allFingerprints) {
33666
33721
  const countByClassification = /* @__PURE__ */ new Map();
@@ -33814,6 +33869,7 @@ function estimateBlockOffsetWithDeclaredFromSources(axis, position, readNumeric)
33814
33869
  // src/cross-file/layout/cohort-index.ts
33815
33870
  function buildCohortIndex(input) {
33816
33871
  const statsByParentNode = /* @__PURE__ */ new Map();
33872
+ const verticalAlignConsensusByParent = /* @__PURE__ */ new Map();
33817
33873
  const profileBuffers = createCohortProfileBuffers();
33818
33874
  let conditionalSignals = 0;
33819
33875
  let totalSignals = 0;
@@ -33888,12 +33944,14 @@ function buildCohortIndex(input) {
33888
33944
  subjectsByElementKey,
33889
33945
  excludedElementKeys: cohortMetricsResult.excludedElementKeys
33890
33946
  });
33947
+ verticalAlignConsensusByParent.set(parent, resolveVerticalAlignConsensus(signalIndex.verticalAlign));
33891
33948
  conditionalSignals += counts.conditional;
33892
33949
  totalSignals += counts.total;
33893
33950
  if (!profile.unimodal) unimodalFalseCount++;
33894
33951
  }
33895
33952
  return {
33896
33953
  statsByParentNode,
33954
+ verticalAlignConsensusByParent,
33897
33955
  conditionalSignals,
33898
33956
  totalSignals,
33899
33957
  unimodalFalseCount,
@@ -34716,6 +34774,13 @@ function swap(values, left, right) {
34716
34774
  values[left] = rightValue;
34717
34775
  values[right] = leftValue;
34718
34776
  }
34777
+ function resolveVerticalAlignConsensus(aggregate) {
34778
+ if (aggregate.comparableCount === 0) return null;
34779
+ if (aggregate.countsByValue.size !== 1) return null;
34780
+ const firstEntry = aggregate.countsByValue.entries().next();
34781
+ if (firstEntry.done) return null;
34782
+ return firstEntry.value[0];
34783
+ }
34719
34784
 
34720
34785
  // src/cross-file/layout/measurement-node.ts
34721
34786
  var EMPTY_NODE_LIST = [];
@@ -36318,6 +36383,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
36318
36383
  snapshotByElementNode,
36319
36384
  snapshotHotSignalsByElementKey: factIndex.snapshotHotSignalsByElementKey
36320
36385
  });
36386
+ finalizeTableCellBaselineRelevance(contextByParentNode, cohortIndex.verticalAlignConsensusByParent);
36321
36387
  perf.conditionalSignals = cohortIndex.conditionalSignals;
36322
36388
  perf.totalSignals = cohortIndex.totalSignals;
36323
36389
  perf.cohortUnimodalFalse = cohortIndex.unimodalFalseCount;
@@ -36658,6 +36724,12 @@ function collectAlignmentCases(context) {
36658
36724
  if (!subjectStats) {
36659
36725
  throw new Error(`missing subject cohort stats for ${measurementNode.key}`);
36660
36726
  }
36727
+ const effectiveAlignmentContext = resolveEffectiveAlignmentContext(
36728
+ alignmentContext,
36729
+ child,
36730
+ measurementNode,
36731
+ context.layout.contextByParentNode
36732
+ );
36661
36733
  const subjectDeclaredOffsetDeviation = computeDeviation(
36662
36734
  subjectStats.declaredOffset,
36663
36735
  subjectStats.baselineProfile.medianDeclaredOffsetPx
@@ -36673,7 +36745,7 @@ function collectAlignmentCases(context) {
36673
36745
  out.push(
36674
36746
  buildAlignmentCase(
36675
36747
  parent,
36676
- alignmentContext,
36748
+ effectiveAlignmentContext,
36677
36749
  cohortStats.profile,
36678
36750
  subjectStats.signals,
36679
36751
  subjectStats.identifiability,
@@ -36822,6 +36894,31 @@ function collectCohortContentCompositions(cohortStats, children, measurementNode
36822
36894
  }
36823
36895
  return out;
36824
36896
  }
36897
+ function resolveEffectiveAlignmentContext(parentContext, child, measurementNode, contextByParentNode) {
36898
+ if (child === measurementNode) return parentContext;
36899
+ if (parentContext.baselineRelevance === "irrelevant") return parentContext;
36900
+ const childContext = contextByParentNode.get(child);
36901
+ if (!childContext) return parentContext;
36902
+ if (childContext.baselineRelevance !== "irrelevant") return parentContext;
36903
+ return {
36904
+ kind: parentContext.kind,
36905
+ certainty: parentContext.certainty,
36906
+ parentSolidFile: parentContext.parentSolidFile,
36907
+ parentElementId: parentContext.parentElementId,
36908
+ parentElementKey: parentContext.parentElementKey,
36909
+ parentTag: parentContext.parentTag,
36910
+ axis: parentContext.axis,
36911
+ axisCertainty: parentContext.axisCertainty,
36912
+ inlineDirection: parentContext.inlineDirection,
36913
+ inlineDirectionCertainty: parentContext.inlineDirectionCertainty,
36914
+ parentDisplay: parentContext.parentDisplay,
36915
+ parentAlignItems: parentContext.parentAlignItems,
36916
+ parentPlaceItems: parentContext.parentPlaceItems,
36917
+ hasPositionedOffset: parentContext.hasPositionedOffset,
36918
+ baselineRelevance: "irrelevant",
36919
+ evidence: parentContext.evidence
36920
+ };
36921
+ }
36825
36922
  function compareAlignmentCaseOrder(left, right) {
36826
36923
  if (left.subject.solidFile < right.subject.solidFile) return -1;
36827
36924
  if (left.subject.solidFile > right.subject.solidFile) return 1;
@@ -36854,10 +36951,11 @@ function buildConsistencyEvidence(input) {
36854
36951
  input.cohortProfile.lineHeightDispersionPx,
36855
36952
  input.cohortProfile.medianLineHeightPx
36856
36953
  );
36857
- const baselineStrength = resolveBaselineStrength(input, lineHeight);
36858
- const contextStrength = resolveContextStrength(input, lineHeight);
36859
- const replacedStrength = resolveReplacedControlStrength(input, lineHeight);
36860
- const compositionStrength = resolveContentCompositionStrength(input);
36954
+ const baselinesIrrelevant = input.context.baselineRelevance === "irrelevant";
36955
+ const baselineStrength = baselinesIrrelevant ? ZERO_STRENGTH : resolveBaselineStrength(input, lineHeight);
36956
+ const contextStrength = baselinesIrrelevant ? ZERO_STRENGTH : resolveContextStrength(input, lineHeight);
36957
+ const replacedStrength = baselinesIrrelevant ? ZERO_STRENGTH : resolveReplacedControlStrength(input, lineHeight);
36958
+ const compositionStrength = baselinesIrrelevant ? ZERO_STRENGTH : resolveContentCompositionStrength(input);
36861
36959
  const contextCertaintyPenalty = resolveContextCertaintyPenalty(input);
36862
36960
  const provenance = input.cohortProvenance;
36863
36961
  const atoms = buildEvidenceAtoms(
@@ -37153,6 +37251,7 @@ function toNegativeContribution(strength, maxPenalty, valueKind) {
37153
37251
  max: 0
37154
37252
  };
37155
37253
  }
37254
+ var ZERO_STRENGTH = { strength: 0, kind: "exact" };
37156
37255
 
37157
37256
  // src/cross-file/layout/consistency-policy.ts
37158
37257
  function applyConsistencyPolicy(input) {
@@ -37372,6 +37471,7 @@ function runLayoutDetector(context, detector) {
37372
37471
  const cases = detector.collect(context);
37373
37472
  const startedAt = performance.now();
37374
37473
  const out = [];
37474
+ const log = context.logger;
37375
37475
  for (let i = 0; i < cases.length; i++) {
37376
37476
  const current = cases[i];
37377
37477
  if (!current) continue;
@@ -37384,10 +37484,20 @@ function runLayoutDetector(context, detector) {
37384
37484
  result.evidence.posteriorLower,
37385
37485
  result.evidence.posteriorUpper
37386
37486
  );
37487
+ if (log.enabled) {
37488
+ log.debug(
37489
+ `[${detector.id}] accept case=${i} severity=${result.evidence.severity.toFixed(2)} confidence=${result.evidence.confidence.toFixed(2)} posterior=[${result.evidence.posteriorLower.toFixed(3)},${result.evidence.posteriorUpper.toFixed(3)}] evidenceMass=${result.evidence.evidenceMass.toFixed(3)} context=${result.evidence.contextKind} offset=${result.evidence.estimatedOffsetPx?.toFixed(2) ?? "null"} topFactors=[${result.evidence.topFactors.join(",")}] causes=[${result.evidence.causes.join("; ")}]`
37490
+ );
37491
+ }
37387
37492
  out.push({ caseData: current, evidence: result.evidence });
37388
37493
  continue;
37389
37494
  }
37390
37495
  recordPolicyMetrics(context, result.evidenceMass, result.posteriorLower, result.posteriorUpper);
37496
+ if (log.enabled) {
37497
+ log.debug(
37498
+ `[${detector.id}] reject case=${i} reason=${result.reason} detail=${result.detail ?? "none"} posterior=[${result.posteriorLower.toFixed(3)},${result.posteriorUpper.toFixed(3)}] evidenceMass=${result.evidenceMass.toFixed(3)}`
37499
+ );
37500
+ }
37391
37501
  if (result.reason === "low-evidence") {
37392
37502
  context.layout.perf.casesRejectedLowEvidence++;
37393
37503
  continue;
@@ -38168,33 +38278,73 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
38168
38278
  category: "css-layout"
38169
38279
  },
38170
38280
  check(context, emit) {
38281
+ const log = context.logger;
38171
38282
  const detections = runLayoutDetector(context, siblingAlignmentDetector);
38172
38283
  const uniqueDetections = dedupeDetectionsBySubject(detections);
38284
+ if (log.enabled) {
38285
+ log.debug(
38286
+ `[sibling-alignment] raw=${detections.length} deduped=${uniqueDetections.length}`
38287
+ );
38288
+ }
38173
38289
  for (let i = 0; i < uniqueDetections.length; i++) {
38174
38290
  const detection = uniqueDetections[i];
38175
38291
  if (!detection) continue;
38176
- if (detection.evidence.confidence < MIN_CONFIDENCE_THRESHOLD) continue;
38292
+ const subjectTag = detection.caseData.subject.tag ?? "element";
38293
+ const parentTag = detection.caseData.cohort.parentTag ?? "container";
38294
+ const subjectFile = detection.caseData.subject.solidFile;
38295
+ const subjectId = detection.caseData.subject.elementId;
38296
+ const logPrefix = `[sibling-alignment] <${subjectTag}> in <${parentTag}> (${subjectFile}#${subjectId})`;
38297
+ if (detection.evidence.confidence < MIN_CONFIDENCE_THRESHOLD) {
38298
+ if (log.enabled) {
38299
+ log.debug(
38300
+ `${logPrefix} SKIP: confidence=${detection.evidence.confidence.toFixed(2)} < threshold=${MIN_CONFIDENCE_THRESHOLD}`
38301
+ );
38302
+ }
38303
+ continue;
38304
+ }
38177
38305
  const estimatedOffset = detection.evidence.estimatedOffsetPx;
38178
- if (estimatedOffset !== null && Math.abs(estimatedOffset) < MIN_OFFSET_PX_THRESHOLD && !hasNonOffsetPrimaryEvidence(detection.evidence.topFactors)) continue;
38306
+ if (estimatedOffset !== null && Math.abs(estimatedOffset) < MIN_OFFSET_PX_THRESHOLD && !hasNonOffsetPrimaryEvidence(detection.evidence.topFactors)) {
38307
+ if (log.enabled) {
38308
+ log.debug(
38309
+ `${logPrefix} SKIP: offset=${estimatedOffset.toFixed(2)}px < ${MIN_OFFSET_PX_THRESHOLD}px (no non-offset primary evidence, topFactors=[${detection.evidence.topFactors.join(",")}])`
38310
+ );
38311
+ }
38312
+ continue;
38313
+ }
38179
38314
  if (isInsideOutOfFlowAncestor(
38180
38315
  context.layout,
38181
38316
  detection.caseData.cohort.parentElementKey,
38182
38317
  detection.caseData.subject.solidFile
38183
- )) continue;
38318
+ )) {
38319
+ if (log.enabled) {
38320
+ log.debug(`${logPrefix} SKIP: out-of-flow ancestor`);
38321
+ }
38322
+ continue;
38323
+ }
38184
38324
  const subjectRef = readNodeRefById(
38185
38325
  context.layout,
38186
38326
  detection.caseData.subject.solidFile,
38187
38327
  detection.caseData.subject.elementId
38188
38328
  );
38189
- if (!subjectRef) continue;
38190
- const subject = detection.caseData.subject.tag ?? "element";
38191
- const parent = detection.caseData.cohort.parentTag ?? "container";
38329
+ if (!subjectRef) {
38330
+ if (log.enabled) {
38331
+ log.debug(`${logPrefix} SKIP: no node ref`);
38332
+ }
38333
+ continue;
38334
+ }
38335
+ const subject = subjectTag;
38336
+ const parent = parentTag;
38192
38337
  const severity = formatFixed(detection.evidence.severity);
38193
38338
  const confidence = formatFixed(detection.evidence.confidence);
38194
38339
  const offset = detection.evidence.estimatedOffsetPx;
38195
38340
  const hasOffset = offset !== null && Math.abs(offset) > 0.25;
38196
38341
  const offsetClause = hasOffset ? `, estimated offset ${formatFixed(offset)}px` : "";
38197
38342
  const causes = detection.evidence.causes.length === 0 ? "alignment signals indicate an outlier" : detection.evidence.causes.join("; ");
38343
+ if (log.enabled) {
38344
+ log.debug(
38345
+ `${logPrefix} EMIT: severity=${severity} confidence=${confidence} offset=${offset?.toFixed(2) ?? "null"} posterior=[${detection.evidence.posteriorLower.toFixed(3)},${detection.evidence.posteriorUpper.toFixed(3)}] evidenceMass=${detection.evidence.evidenceMass.toFixed(3)} topFactors=[${detection.evidence.topFactors.join(",")}] causes=[${causes}]`
38346
+ );
38347
+ }
38198
38348
  emit(
38199
38349
  createDiagnostic(
38200
38350
  subjectRef.solid.file,
@@ -39732,7 +39882,8 @@ var CrossFilePlugin = {
39732
39882
  const context = {
39733
39883
  solids: solidGraphs,
39734
39884
  css: cssGraph,
39735
- layout: buildLayoutGraph(solidGraphs, cssGraph)
39885
+ layout: buildLayoutGraph(solidGraphs, cssGraph),
39886
+ logger: noopLogger
39736
39887
  };
39737
39888
  runCrossFileRules(context, emit);
39738
39889
  }
@@ -39771,7 +39922,8 @@ function buildCrossContext(context) {
39771
39922
  return {
39772
39923
  solids: [solidGraph],
39773
39924
  css: cssGraph,
39774
- layout: buildLayoutGraph([solidGraph], cssGraph)
39925
+ layout: buildLayoutGraph([solidGraph], cssGraph),
39926
+ logger: noopLogger
39775
39927
  };
39776
39928
  }
39777
39929
  var { eslintRules: eslintRules3 } = createBatchPluginAdapter(