From 8b0cc87023e752e91fb8a71bc63a2dd85cf0f96b Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Mon, 14 Sep 2026 18:36:05 -0700 Subject: [PATCH] Fix stripe-child edge and token matching AI-assisted changes requested by pbakaus. Preserve winning auto inset longhands and require complete Tailwind cue tokens. Added regressions that fail before the fixes; focused tests, cargo test --workspace, release build, and the full rebuilt-engine Bun/Node suite pass. --- crates/detect/src/regex_matchers.rs | 17 ++++++++++++++++- crates/html/src/adapters.rs | 25 ++++--------------------- crates/html/tests/stripe_child.rs | 11 +++++++++++ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/crates/detect/src/regex_matchers.rs b/crates/detect/src/regex_matchers.rs index fdbb80a29..f429d2a3e 100644 --- a/crates/detect/src/regex_matchers.rs +++ b/crates/detect/src/regex_matchers.rs @@ -942,7 +942,10 @@ pub static REGEX_MATCHERS: Lazy> = Lazy::new(|| { let scope = containing_markup_tag(line)(m.index); find_solid_chromatic_bg(&scope).is_some() && stripe_child_markup_empty(line, m.index) - && STRIPE_CHILD_CUE_RE.is_match(&scope) + && STRIPE_CHILD_CUE_RE.find_iter(&scope).any(|cue| { + hyphen_safe_prefix(&scope, cue.start()) + && hyphen_safe_suffix(&scope, cue.end()) + }) && !scope_has_fixed_height(&scope) && !STRIPE_CHILD_ROUNDED_FULL_RE.is_match(&scope) && !STRIPE_CHILD_ARIA_RE.is_match(&scope) @@ -1522,6 +1525,18 @@ mod tests { ); } + #[test] + fn stripe_child_cues_require_complete_class_tokens() { + for cue in ["left-0.5", "right-0.5", "inset-y-0.5", "-left-0", "left-0/2", "shrink-0.5"] { + let source = format!(r#"
"#); + assert!(run("side-tab", &source).is_empty(), "{cue}"); + } + for cue in ["left-0", "right-0", "inset-y-0", "shrink-0", "rounded-l-lg"] { + let source = format!(r#"
"#); + assert_eq!(run("side-tab", &source).len(), 1, "{cue}"); + } + } + #[test] fn stripe_child_tailwind() { let s = |line: &str| run("side-tab", line); diff --git a/crates/html/src/adapters.rs b/crates/html/src/adapters.rs index 4cf5afbbd..c68b4a646 100644 --- a/crates/html/src/adapters.rs +++ b/crates/html/src/adapters.rs @@ -9,7 +9,7 @@ use crate::background::{ a_ge, a_gt, read_own_background_color, resolve_background, resolve_background_info, resolve_border_radius_px, resolve_gradient_stops, sv, sv_opt, CustomPropMap, }; -use crate::cascade::{expand_static_box_values, split_css_tokens, StyleValues}; +use crate::cascade::StyleValues; use crate::dom::{StaticDocument, StaticElement}; use crate::quality::{collapse_ws, pf0, resolve_font_size_px}; use impeccable_core::checks::css_scan::css_length_to_px; @@ -469,25 +469,6 @@ fn static_edge_hugs(value: &str) -> bool { n.is_finite() && n.abs() <= 2.0 } -fn static_resolved_inset(style: &StyleValues) -> [String; 4] { - let mut out = [ - sv(style, "top").to_string(), - sv(style, "right").to_string(), - sv(style, "bottom").to_string(), - sv(style, "left").to_string(), - ]; - let inset = sv(style, "inset"); - if !inset.is_empty() { - let expanded = expand_static_box_values(&split_css_tokens(inset)); - for (i, val) in expanded.into_iter().enumerate() { - if out[i].is_empty() || out[i] == "auto" { - out[i] = val; - } - } - } - out -} - /// JS: checks.mjs#checkElementStripeChild(el, style) pub fn check_element_stripe_child(el: &StaticElement<'_>, style: &StyleValues) -> Vec { let tag = el.tag_lower(); @@ -518,7 +499,9 @@ pub fn check_element_stripe_child(el: &StaticElement<'_>, style: &StyleValues) - let host_style = host.style(); let edge = if position == "absolute" || position == "fixed" { let height_raw = sv(style, "height"); - let inset = static_resolved_inset(style); + // The cascade already expands inset; a winning `auto` longhand + // must not be overwritten by the earlier shorthand. + let inset = ["top", "right", "bottom", "left"].map(|prop| sv(style, prop)); let height_stretches = height_raw == "100%" || (static_edge_hugs(&inset[0]) && static_edge_hugs(&inset[2])); if !height_stretches { diff --git a/crates/html/tests/stripe_child.rs b/crates/html/tests/stripe_child.rs index 6c154e68c..cae36ffa3 100644 --- a/crates/html/tests/stripe_child.rs +++ b/crates/html/tests/stripe_child.rs @@ -13,6 +13,17 @@ fn side_tab_snippets(html: &str) -> Vec { .collect() } +#[test] +fn winning_auto_longhand_is_not_replaced_by_inset() { + let html = r#"
+
+
"#; + let hits = side_tab_snippets(html); + assert_eq!(hits.len(), 1); + assert!(hits[0].contains("stripe child (right)"), "{hits:?}"); + assert!(side_tab_snippets(&html.replace("left:auto", "left:auto;right:auto")).is_empty()); +} + #[test] fn flex_row_first_child_flags() { let html = r#"