class Prawn::SVG::CSS::Stylesheets
Attributes
css_parser[R]
media[R]
root[R]
Public Class Methods
new(css_parser, root, media = :all)
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 5 def initialize(css_parser, root, media = :all) @css_parser = css_parser @root = root @media = media end
Public Instance Methods
load()
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 11 def load load_style_elements xpath_styles = gather_xpath_styles associate_xpath_styles_with_elements(xpath_styles) end
Private Instance Methods
associate_xpath_styles_with_elements(xpath_styles)
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 48 def associate_xpath_styles_with_elements(xpath_styles) element_styles = {} xpath_styles.each do |xpath, declarations, _| REXML::XPath.match(root, xpath).each do |element| (element_styles[element] ||= []).concat declarations end end element_styles end
calculate_specificity(selector)
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 115 def calculate_specificity(selector) selector.reduce([0, 0, 0]) do |(a, b, c), element| [ a + (element[:id] || []).length, b + (element[:class] || []).length + (element[:attribute] || []).length + (element[:pseudo_class] || []).length, c + (element[:name] && element[:name] != "*" ? 1 : 0) ] end end
css_selector_to_xpath(selector)
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 64 def css_selector_to_xpath(selector) selector.map do |element| pseudo_classes = Set.new(element[:pseudo_class]) result = case element[:combinator] when :child '/' when :adjacent pseudo_classes << 'first-child' '/following-sibling::' when :siblings '/following-sibling::' else '//' end result << element[:name] if element[:name] result << ((element[:class] || []).map { |name| "[contains(concat(' ',@class,' '), ' #{name} ')]" }.join) result << ((element[:id] || []).map { |name| "[@id='#{name}']" }.join) (element[:attribute] || []).each do |key, operator, value| case operator when nil result << "[@#{key}]" when "=" result << "[@#{key}=#{xpath_quote value}]" when "^=" result << "[starts-with(@#{key}, #{xpath_quote value})]" when "$=" result << "[substring(@#{key}, string-length(@#{key}) - #{value.length - 1}) = #{xpath_quote value})]" when "*=" result << "[contains(@#{key}, #{xpath_quote value})]" when "~=" result << "[contains(concat(' ',@#{key},' '), #{xpath_quote " #{value} "})]" when "|=" result << "[contains(concat('-',@#{key},'-'), #{xpath_quote "-#{value}-"})]" end end pseudo_classes.each do |pc| case pc when "first-child" then result << "[1]" when "last-child" then result << "[last()]" when /^nth-child\((\d+)\)$/ then result << "[#{$1}]" end end result end.join end
gather_xpath_styles()
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 26 def gather_xpath_styles xpath_styles = [] order = 0 css_parser.each_rule_set(media) do |rule_set, _| declarations = [] rule_set.each_declaration { |*data| declarations << data } rule_set.selectors.each do |selector_text| selector = Prawn::SVG::CSS::SelectorParser.parse(selector_text) xpath = css_selector_to_xpath(selector) specificity = calculate_specificity(selector) specificity << order order += 1 xpath_styles << [xpath, declarations, specificity] end end xpath_styles.sort_by(&:last) end
load_style_elements()
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 19 def load_style_elements REXML::XPath.match(root, '//style').each do |source| data = source.texts.map(&:value).join css_parser.add_block!(data) end end
xpath_quote(value)
click to toggle source
# File lib/prawn/svg/css/stylesheets.rb, line 60 def xpath_quote(value) %{"#{value.gsub('\\', '\\\\').gsub('"', '\\"')}"} if value end