Skip to content

Commit 0863d46

Browse files
committed
perf: modify styles in-place
1 parent baea2c1 commit 0863d46

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

css-inline/src/lib.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mod html;
3030
mod parser;
3131

3232
pub use error::InlineError;
33+
use html5ever::tendril::StrTendril;
3334
use indexmap::IndexMap;
3435
use smallvec::{smallvec, SmallVec};
3536
use std::{
@@ -257,7 +258,7 @@ impl<'a> CSSInliner<'a> {
257258
let attributes = &mut element.attributes;
258259
if let Some(existing_style) = attributes.get_style_mut() {
259260
styles.sort_unstable_by(|_, (a, _), _, (b, _)| a.cmp(b));
260-
*existing_style = merge_styles(existing_style, &styles)?.into();
261+
merge_styles(existing_style, styles)?;
261262
} else {
262263
let mut final_styles = String::with_capacity(128);
263264
let mut styles = styles.iter().collect::<Vec<_>>();
@@ -409,9 +410,9 @@ pub fn inline_to<W: Write>(html: &str, target: &mut W) -> Result<()> {
409410
}
410411

411412
fn merge_styles(
412-
existing_style: &str,
413+
existing_style: &mut StrTendril,
413414
new_styles: &IndexMap<String, (Specificity, String)>,
414-
) -> Result<String> {
415+
) -> Result<()> {
415416
// Parse existing declarations in the "style" attribute
416417
let mut input = cssparser::ParserInput::new(existing_style);
417418
let mut parser = cssparser::Parser::new(&mut input);
@@ -423,7 +424,8 @@ fn merge_styles(
423424
for declaration in declarations {
424425
let (name, value) = declaration?;
425426
// Allocate enough space for the new style
426-
let mut style = String::with_capacity(name.len() + value.len() + 2);
427+
let mut style =
428+
String::with_capacity(name.len().saturating_add(value.len()).saturating_add(2));
427429
style.push_str(&name);
428430
style.push_str(": ");
429431
replace_double_quotes!(style, name, value.trim());
@@ -456,5 +458,16 @@ fn merge_styles(
456458
(None, Some(_)) => {}
457459
}
458460
}
459-
Ok(final_styles.join(";"))
461+
drop(input);
462+
existing_style.clear();
463+
let mut first = true;
464+
for style in &final_styles {
465+
if first {
466+
first = false
467+
} else {
468+
existing_style.push_char(';');
469+
}
470+
existing_style.push_slice(style);
471+
}
472+
Ok(())
460473
}

0 commit comments

Comments
 (0)