Skip to content

Commit 914d9d6

Browse files
committed
fix: Invalid handling of double-quoted property values like in font-family: "Open Sans"
Ref: #129
1 parent bc80bcd commit 914d9d6

6 files changed

Lines changed: 42 additions & 3 deletions

File tree

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+
- Invalid handling of double-quoted property values like in `font-family: "Open Sans"`. [#129](https://github.com/Stranger6667/css-inline/issues/129)
8+
59
### Performance
610

711
- Use `std::fs::read_to_string` in CLI to avoid over/under allocating of the input buffer.

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+
- Invalid handling of double-quoted property values like in `font-family: "Open Sans"`. [#129](https://github.com/Stranger6667/css-inline/issues/129)
8+
59
## [0.7.7] - 2022-01-07
610

711
### Added

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+
- Invalid handling of double-quoted property values like in `font-family: "Open Sans"`. [#129](https://github.com/Stranger6667/css-inline/issues/129)
8+
59
## [0.7.5] - 2021-07-24
610

711
### Fixed

css-inline/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ cli = ["pico-args", "rayon"]
2121
[dependencies]
2222
cssparser = "0.29"
2323
kuchiki = "0.8"
24+
memchr = "2.4"
2425
attohttpc = { version = "0", default-features = false, features = ["compress", "tls-rustls"] }
2526
url = "2"
2627
smallvec = "1"

css-inline/src/lib.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,21 @@ use smallvec::{smallvec, SmallVec};
118118
use std::{borrow::Cow, collections::hash_map::Entry, fs, io::Write};
119119
pub use url::{ParseError, Url};
120120

121+
/// Replace double quotes in property values.
122+
///
123+
/// This implementation is deliberately simplistic and covers only `font-family`, but escaping
124+
/// might be needed in other properties that accept strings.
125+
macro_rules! replace_double_quotes {
126+
($target:expr, $name:expr, $value:expr) => {
127+
// Avoid allocation if there is no double quote in the input string
128+
if $name.starts_with("font-family") && memchr::memchr(b'"', $value.as_bytes()).is_some() {
129+
$target.push_str(&$value.replace('"', "\'"))
130+
} else {
131+
$target.push_str($value)
132+
};
133+
};
134+
}
135+
121136
/// Configuration options for CSS inlining process.
122137
#[derive(Debug)]
123138
pub struct InlineOptions<'a> {
@@ -352,7 +367,7 @@ impl<'a> CSSInliner<'a> {
352367
for (name, (_, value)) in styles {
353368
final_styles.push_str(name.as_str());
354369
final_styles.push(':');
355-
final_styles.push_str(value.as_str());
370+
replace_double_quotes!(final_styles, name, &value);
356371
final_styles.push(';');
357372
}
358373
attributes.insert("style", final_styles);
@@ -472,7 +487,7 @@ fn merge_styles(
472487
let (name, value) = declaration?;
473488
final_styles.push_str(&name);
474489
final_styles.push(':');
475-
final_styles.push_str(value);
490+
replace_double_quotes!(final_styles, name, value);
476491
final_styles.push(';');
477492
// This property won't be taken from new styles
478493
buffer.push(name.to_string())
@@ -481,7 +496,7 @@ fn merge_styles(
481496
if !buffer.contains(property) {
482497
final_styles.push_str(property);
483498
final_styles.push(':');
484-
final_styles.push_str(value);
499+
replace_double_quotes!(final_styles, property, value);
485500
final_styles.push(';');
486501
}
487502
}

css-inline/tests/test_inlining.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ fn overloaded_styles() {
6868
)
6969
}
7070

71+
#[test]
72+
fn font_family_quoted() {
73+
// When property value contains double quotes
74+
assert_inlined!(
75+
style = r#"h1 { font-family: "Open Sans", sans-serif; }"#,
76+
body = r#"<h1>Hello world!</h1>"#,
77+
// Then it should be replaced with single quotes
78+
expected = r#"<h1 style="font-family: 'Open Sans', sans-serif;">Hello world!</h1>"#
79+
)
80+
}
81+
7182
#[test]
7283
fn existing_styles() {
7384
// When there is a `style` attribute on a tag that contains a rule

0 commit comments

Comments
 (0)