From 744c01f66f1d536ad82e2dfacead2593177d37fb Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sat, 24 Oct 2026 14:35:42 +0000 Subject: [PATCH] Match style as a whole attribute name in HTML paste Found while testing crates/engine/src/cmd/richclip.rs:230-242 (attr, used by tag_style) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/richclip.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/richclip.rs b/crates/engine/src/cmd/richclip.rs index 280d6746..134e62eb 100644 --- a/crates/engine/src/cmd/richclip.rs +++ b/crates/engine/src/cmd/richclip.rs @@ -231,7 +231,11 @@ fn weight_bold(style: &str) -> Option { fn attr<'a>(tag: &'a str, key: &str) -> Option<&'a str> { let lower = tag.to_ascii_lowercase(); - let at = lower.find(key)?; + let at = lower.match_indices(key).find_map(|(at, _)| { + let named = lower[..at].ends_with(|c: char| c.is_ascii_whitespace()); + let eq = tag.get(at + key.len()..)?.trim_start().starts_with('='); + (named && eq).then_some(at) + })?; let after = tag.get(at + key.len()..)?.trim_start(); let after = after.strip_prefix('=')?.trim_start(); let quote = after.chars().next()?; @@ -382,6 +386,20 @@ mod tests { assert_eq!(heavy.paragraphs[0].runs[0].props.bold, Some(true)); } + #[test] + fn style_attribute_is_found_after_attributes_containing_style() { + for tag in [ + "x", + "x", + "x", + ] { + let body = html_to_body(tag).unwrap(); + assert_eq!(body.paragraphs[0].runs[0].props.bold, Some(true), "{tag}"); + } + let none = html_to_body("x").unwrap(); + assert_eq!(none.paragraphs[0].runs[0].props.bold, None); + } + #[test] fn bold_italic_and_underline_round_trip() { let mut body = TextBody::from_text("Hi there");