Skip to content

Commit 239b0a9

Browse files
committed
perf: Reduce unneeded operations number during inlining
1 parent fe55ce0 commit 239b0a9

File tree

1 file changed

+32
-45
lines changed

1 file changed

+32
-45
lines changed

src/lib.rs

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
)]
100100
use crate::parse::Declaration;
101101
use kuchiki::traits::TendrilSink;
102-
use kuchiki::{parse_html, ElementData, NodeDataRef, Selectors};
102+
use kuchiki::{parse_html, Selectors};
103103

104104
pub mod error;
105105
mod parse;
@@ -122,57 +122,44 @@ impl Rule {
122122
}
123123
}
124124

125-
fn process_style_node(node: &NodeDataRef<ElementData>) -> Vec<Rule> {
126-
let css = node.text_contents();
127-
let mut parse_input = cssparser::ParserInput::new(css.as_str());
128-
let mut parser = parse::CSSParser::new(&mut parse_input);
129-
parser
130-
.parse()
131-
.filter_map(|r| {
132-
r.map(|(selector, declarations)| Rule::new(&selector, declarations))
133-
.ok()
134-
})
135-
.collect::<Result<Vec<_>, _>>()
136-
.map_err(|_| error::InlineError::ParseError)
137-
.expect("Parsing error") // Should return Result instead
138-
}
139-
140125
/// Inline CSS styles from <style> tags to matching elements in the HTML tree.
141126
pub fn inline(html: &str) -> Result<String, InlineError> {
142127
let document = parse_html().one(html);
143-
let rules = document
128+
for style_tag in document
144129
.select("style")
145130
.map_err(|_| error::InlineError::ParseError)?
146-
.map(|ref node| process_style_node(node))
147-
.flatten();
148-
149-
for rule in rules {
150-
let matching_elements = document
151-
.inclusive_descendants()
152-
.filter_map(|node| node.into_element_ref())
153-
.filter(|element| rule.selectors.matches(element));
154-
for matching_element in matching_elements {
155-
let mut attributes = matching_element.attributes.borrow_mut();
156-
let style = if let Some(existing_style) = attributes.get("style") {
157-
merge_styles(existing_style, &rule.declarations)?
158-
} else {
159-
rule.declarations
160-
.iter()
161-
.map(|&(ref key, ref value)| format!("{}:{};", key, value))
162-
.collect()
163-
};
164-
attributes.insert("style", style);
131+
{
132+
if let Some(first_child) = style_tag.as_node().first_child() {
133+
if let Some(css_cell) = first_child.as_text() {
134+
let css = css_cell.borrow();
135+
let mut parse_input = cssparser::ParserInput::new(css.as_str());
136+
let mut parser = parse::CSSParser::new(&mut parse_input);
137+
for parsed in parser.parse() {
138+
let (selector, declarations) = parsed?;
139+
let rule = Rule::new(&selector, declarations)
140+
.map_err(|_| error::InlineError::ParseError)?;
141+
let matching_elements = document
142+
.inclusive_descendants()
143+
.filter_map(|node| node.into_element_ref())
144+
.filter(|element| rule.selectors.matches(element));
145+
for matching_element in matching_elements {
146+
let mut attributes = matching_element.attributes.borrow_mut();
147+
let style = if let Some(existing_style) = attributes.get("style") {
148+
merge_styles(existing_style, &rule.declarations)?
149+
} else {
150+
rule.declarations
151+
.iter()
152+
.map(|&(ref key, ref value)| format!("{}:{};", key, value))
153+
.collect()
154+
};
155+
attributes.insert("style", style);
156+
}
157+
}
158+
}
165159
}
166160
}
167-
168161
let mut out = vec![];
169-
document
170-
.select("html")
171-
.map_err(|_| error::InlineError::ParseError)?
172-
.next()
173-
.expect("HTML tag should be present") // Should it?
174-
.as_node()
175-
.serialize(&mut out)?;
162+
document.serialize(&mut out)?;
176163
Ok(String::from_utf8_lossy(&out).to_string())
177164
}
178165

@@ -186,7 +173,7 @@ fn merge_styles(existing_style: &str, new_styles: &[Declaration]) -> Result<Stri
186173
let mut styles: HashMap<String, String> = HashMap::new();
187174
for declaration in declarations.into_iter() {
188175
let (property, value) = declaration?;
189-
styles.insert(property.to_string(), value.to_string());
176+
styles.insert(property, value);
190177
}
191178
for (property, value) in new_styles.iter() {
192179
styles.insert(property.to_string(), value.to_string());

0 commit comments

Comments
 (0)