(
&self,
html: &str,
css: Option<&str>,
target: &mut W,
mode: InliningMode,
)
| 642 | |
| 643 | #[allow(clippy::too_many_lines)] |
| 644 | fn inline_to_impl<W: Write>( |
| 645 | &self, |
| 646 | html: &str, |
| 647 | css: Option<&str>, |
| 648 | target: &mut W, |
| 649 | mode: InliningMode, |
| 650 | ) -> Result<()> { |
| 651 | let mut document = Document::parse_with_options( |
| 652 | html.as_bytes(), |
| 653 | self.options.preallocate_node_capacity, |
| 654 | mode, |
| 655 | ); |
| 656 | // CSS rules may overlap, and the final set of rules applied to an element depend on |
| 657 | // selectors' specificity - selectors with higher specificity have more priority. |
| 658 | // Inlining happens in two major steps: |
| 659 | // 1. All available styles are mapped to respective elements together with their |
| 660 | // selector's specificity. When two rules overlap on the same declaration, then |
| 661 | // the one with higher specificity replaces another. |
| 662 | // 2. Resulting styles are merged into existing "style" tags. |
| 663 | let track_selector_cleanup = self.options.remove_inlined_selectors; |
| 664 | let mut size_estimate: usize = if self.options.inline_style_tags { |
| 665 | document |
| 666 | .styles() |
| 667 | .map(|(_, s)| { |
| 668 | // Add 1 to account for the extra `\n` char we add between styles |
| 669 | s.len().saturating_add(1) |
| 670 | }) |
| 671 | .sum() |
| 672 | } else { |
| 673 | 0 |
| 674 | }; |
| 675 | if let Some(extra_css) = &self.options.extra_css { |
| 676 | size_estimate = size_estimate.saturating_add(extra_css.len()); |
| 677 | } |
| 678 | if let Some(css) = css { |
| 679 | size_estimate = size_estimate.saturating_add(css.len()); |
| 680 | } |
| 681 | let mut css_buffer = CssBuffer::new(track_selector_cleanup); |
| 682 | css_buffer.raw.reserve(size_estimate); |
| 683 | if self.options.inline_style_tags || self.options.keep_at_rules { |
| 684 | for (node_id, style) in document.styles() { |
| 685 | let style_node = track_selector_cleanup.then_some(node_id); |
| 686 | css_buffer.push(style_node, style, true); |
| 687 | } |
| 688 | } |
| 689 | if self.options.load_remote_stylesheets { |
| 690 | let mut links = document.stylesheets().collect::<Vec<&str>>(); |
| 691 | links.sort_unstable(); |
| 692 | links.dedup(); |
| 693 | for href in &links { |
| 694 | let url = self.get_full_url(href); |
| 695 | #[cfg(feature = "stylesheet-cache")] |
| 696 | if let Some(lock) = self.options.cache.as_ref() { |
| 697 | let mut cache = lock.lock().expect("Cache lock is poisoned"); |
| 698 | if let Some(cached) = cache.get(url.as_ref()) { |
| 699 | css_buffer.push(None, cached, true); |
| 700 | continue; |
| 701 | } |
no test coverage detected