class Roadie::Inliner
@api private The Inliner inlines stylesheets to the elements of the DOM.
Inlining means that {StyleBlock}s and a DOM tree are combined:
a { color: red; } # StyleBlock <a href="/"></a> # DOM
becomes
<a href="/" style="color:red"></a>
Attributes
dom[R]
stylesheets[R]
Public Class Methods
new(stylesheets, dom)
click to toggle source
@param [Array<Stylesheet>] stylesheets the stylesheets to use in the inlining @param [Nokogiri::HTML::Document] dom
# File lib/roadie/inliner.rb, line 20 def initialize(stylesheets, dom) @stylesheets = stylesheets @dom = dom end
Public Instance Methods
inline(keep_extra_blocks = true)
click to toggle source
Start the inlining, mutating the DOM tree.
@param [true, false] keep_extra_blocks @return [nil]
# File lib/roadie/inliner.rb, line 29 def inline(keep_extra_blocks = true) style_map, extra_blocks = consume_stylesheets apply_style_map(style_map) add_styles_to_head(extra_blocks) if keep_extra_blocks nil end
Private Instance Methods
add_styles_to_head(blocks)
click to toggle source
# File lib/roadie/inliner.rb, line 92 def add_styles_to_head(blocks) unless blocks.empty? create_style_element(blocks, find_head) end end
apply_element_style(element, builder)
click to toggle source
# File lib/roadie/inliner.rb, line 73 def apply_element_style(element, builder) element["style"] = [builder.attribute_string, element["style"]].compact.join(";") end
apply_style_map(style_map)
click to toggle source
# File lib/roadie/inliner.rb, line 69 def apply_style_map(style_map) style_map.each_element { |element, builder| apply_element_style(element, builder) } end
consume_stylesheets()
click to toggle source
# File lib/roadie/inliner.rb, line 42 def consume_stylesheets style_map = StyleMap.new extra_blocks = [] each_style_block do |stylesheet, block| if (elements = selector_elements(stylesheet, block)) style_map.add elements, block.properties else extra_blocks << block end end [style_map, extra_blocks] end
create_style_element(style_blocks, head)
click to toggle source
# File lib/roadie/inliner.rb, line 102 def create_style_element(style_blocks, head) return unless head element = Nokogiri::XML::Node.new("style", head.document) element.content = style_blocks.join("\n") head.add_child(element) end
each_style_block() { |stylesheet, block| ... }
click to toggle source
# File lib/roadie/inliner.rb, line 57 def each_style_block stylesheets.each do |stylesheet| stylesheet.blocks.each do |block| yield stylesheet, block end end end
elements_matching_selector(stylesheet, selector)
click to toggle source
# File lib/roadie/inliner.rb, line 77 def elements_matching_selector(stylesheet, selector) dom.css(selector.to_s) # There's no way to get a list of supported pseudo selectors, so we're left # with having to rescue errors. # Pseudo selectors that are known to be bad are skipped automatically but # this will catch the rest. rescue Nokogiri::XML::XPath::SyntaxError, Nokogiri::CSS::SyntaxError => error Utils.warn "Cannot inline #{selector.inspect} from \"#{stylesheet.name}\" stylesheet. If this is valid CSS, please report a bug." nil rescue => error Utils.warn "Got error when looking for #{selector.inspect} (from \"#{stylesheet.name}\" stylesheet): #{error}" raise unless error.message.include?('XPath') nil end
find_head()
click to toggle source
# File lib/roadie/inliner.rb, line 98 def find_head dom.at_xpath('html/head') end
selector_elements(stylesheet, block)
click to toggle source
# File lib/roadie/inliner.rb, line 65 def selector_elements(stylesheet, block) block.inlinable? && elements_matching_selector(stylesheet, block.selector) end