fix(formats): support case-insensitive and spaced !important in HTML CSS

This commit is contained in:
Divyanshu Gupta
2026-10-16 03:21:50 +05:30
parent 86adfd34eb
commit 07ecf526a6
+31 -1
View File
@@ -506,12 +506,23 @@ fn css_len_pt(v: &str) -> Option<f32> {
}
}
fn strip_important(v: &str) -> &str {
let s = v.trim();
if let Some(pos) = s.rfind('!') {
let after = s[pos + 1..].trim();
if after.eq_ignore_ascii_case("important") {
return s[..pos].trim();
}
}
s
}
/// Apply a `style` attribute to formatting / block properties.
fn apply_style(css: &str, f: &mut Fmt, align: &mut Option<Align>, preserve: &mut bool, page_break: &mut bool) {
for decl in css.split(';').take(64) {
let Some((k, v)) = decl.split_once(':') else { continue };
let k = k.trim().to_ascii_lowercase();
let v = v.trim().trim_end_matches("!important").trim();
let v = strip_important(v);
let lv = v.to_ascii_lowercase();
match k.as_str() {
"font-weight" => f.bold = lv.starts_with("bold") || lv.parse::<u32>().is_ok_and(|w| w >= 600),
@@ -1785,4 +1796,23 @@ mod tests {
fn entities() {
assert_eq!(unescape("a &lt;b&gt; &#65;&#x42; &bogus; &"), "a <b> AB &bogus; &");
}
#[test]
fn css_important_casing_and_spacing() {
let f = parse("<p style='color: #ff0000 !IMPORTANT; font-size: 16pt ! important; font-weight: 700 !Important; text-align: center !IMPORTANT'>Styled</p>");
assert_eq!(f.blocks.len(), 1);
let p = match &f.blocks[0] {
FBlock::Para(p) => p,
b => panic!("expected para, got {b:?}"),
};
assert_eq!(p.align, Some(Align::Center));
match &p.inlines[0] {
Inline::Text(_, fmt) => {
assert_eq!(fmt.color, Some(wordcraft_doc::props::Rgb(0xFF, 0x00, 0x00)));
assert_eq!(fmt.size, Some(16.0));
assert!(fmt.bold);
}
i => panic!("expected text inline, got {i:?}"),
}
}
}