Skip to content

Commit c1b71ba

Browse files
committed
fix: Ignoring selectors' specificity when applying declarations from different qualified rules
Ref: #148
1 parent 9f9fbbf commit c1b71ba

File tree

5 files changed

+42
-2
lines changed

5 files changed

+42
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44

5+
### Fixed
6+
7+
- Ignoring selectors' specificity when applying declarations from different qualified rules. [#148](https://github.com/Stranger6667/css-inline/issues/148)
8+
59
## [0.8.2] - 2022-07-21
610

711
### Added

bindings/python/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44

5+
### Fixed
6+
7+
- Ignoring selectors' specificity when applying declarations from different qualified rules. [#148](https://github.com/Stranger6667/css-inline/issues/148)
8+
59
### Changed
610

711
- Update `PyO3` to `0.17.1`.

bindings/wasm/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44

5+
### Fixed
6+
7+
- Ignoring selectors' specificity when applying declarations from different qualified rules. [#148](https://github.com/Stranger6667/css-inline/issues/148)
8+
59
### Changed
610

711
- Unpin `parking_lot_core`.

css-inline/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,12 @@ impl<'a> CSSInliner<'a> {
306306
*existing_style = merge_styles(existing_style, &styles)?;
307307
} else {
308308
let mut final_styles = String::with_capacity(128);
309+
let mut styles = styles.iter().collect::<Vec<_>>();
310+
styles.sort_unstable_by(|(_, (a, _)), (_, (b, _))| a.cmp(b));
309311
for (name, (_, value)) in styles {
310312
final_styles.push_str(name.as_str());
311313
final_styles.push(':');
312-
replace_double_quotes!(final_styles, name, &value);
314+
replace_double_quotes!(final_styles, name, value);
313315
final_styles.push(';');
314316
}
315317
attributes.insert("style", final_styles);
@@ -399,6 +401,8 @@ fn process_css(
399401
let element_styles = styles
400402
.entry(&**matching_element.as_node())
401403
.or_insert_with(|| IndexMap::with_capacity(8));
404+
// Iterate over pairs of property name & value
405+
// Example: `padding`, `0`
402406
for (name, value) in &declarations {
403407
match element_styles.entry(name.to_string()) {
404408
indexmap::map::Entry::Occupied(mut entry) => {
@@ -476,6 +480,8 @@ fn merge_styles(
476480
// This property won't be taken from new styles unless it's !important
477481
buffer.push(name.to_string());
478482
}
483+
let mut new_styles = new_styles.iter().collect::<Vec<_>>();
484+
new_styles.sort_unstable_by(|(_, (a, _)), (_, (b, _))| a.cmp(b));
479485
for (property, (_, value)) in new_styles {
480486
match (
481487
value.strip_suffix("!important"),

css-inline/tests/test_inlining.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ p.footer { font-size: 1px}"#,
2121
}
2222

2323
#[test]
24-
fn maintain_rules_order() {
24+
fn specificity_same_selector() {
2525
assert_inlined!(
2626
style = r#"
2727
.test-class {
@@ -35,6 +35,28 @@ fn maintain_rules_order() {
3535
)
3636
}
3737

38+
#[test]
39+
fn specificity_different_selectors() {
40+
assert_inlined!(
41+
style = r#"
42+
.test { padding-left: 16px; }
43+
h1 { padding: 0; }"#,
44+
body = r#"<h1 class="test"></h1>"#,
45+
expected = r#"<h1 class="test" style="padding: 0;padding-left: 16px;"></h1>"#
46+
)
47+
}
48+
49+
#[test]
50+
fn specificity_different_selectors_existing_style() {
51+
assert_inlined!(
52+
style = r#"
53+
.test { padding-left: 16px; }
54+
h1 { padding: 0; }"#,
55+
body = r#"<h1 class="test" style="color: blue;"></h1>"#,
56+
expected = r#"<h1 class="test" style="color: blue;padding: 0;padding-left: 16px"></h1>"#
57+
)
58+
}
59+
3860
#[test]
3961
fn overlap_styles() {
4062
// When two selectors match the same element

0 commit comments

Comments
 (0)