class SpreadsheetBuilder::CssParser
Attributes
cache[R]
load_paths[RW]
rules[R]
Public Class Methods
new(load_paths = [])
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 28 def initialize(load_paths = []) @load_paths = load_paths reset end
pt_from_input(val, base = :width)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 21 def self.pt_from_input(val, base = :width) px_from_input(val, base) * 12 / 16 end
px_from_input(val, base = :width)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 4 def self.px_from_input(val, base = :width) case val when /%$/ val.to_f / 100 * { width: 1024, height: 16 }[base] when /px$/ val.to_f when /cm$/ val.to_f * 37.795275591 when /em$/ val.to_f * 16 when /pt$/ val.to_f * 16 / 12 else nil end end
Public Instance Methods
format_from_node(node)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 40 def format_from_node(node) formats = [] formats << format_from_klass_tree(klass_tree_from_node(node), node) if node.attributes["style"] declarations = node.attributes["style"].value.split(';').map { |line| k, v = line.split(':') [k, { value: v }] } formats << format_from_declarations(declarations, node) end formats.inject(&:merge) end
reset(level = :parser)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 34 def reset(level = :parser) method = "reset_#{level}" __send__(method) end
Private Instance Methods
accepted_keys()
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 56 def accepted_keys # TODO Keep these in a config keys = %w{ color background-color font-size font-weight vertical-align text-align border border-width border-style border-color height width } dirs = %w{ top bottom left right } types = %w{ width style color } dirs.each do |dir| keys << "border-#{dir}" types.each { |type| keys << "border-#{dir}-#{type}" } end keys end
declarations_from_klass_tree(klass)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 152 def declarations_from_klass_tree(klass) rules = find_rules(klass).sort_by { |specificity,_| specificity } declarations = rules.map { |_,rules| rules.inject({}) { |dec, r| dec.merge(r.declarations) } }.inject({},&:merge) end
find_rules(tree)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 110 def find_rules(tree) @rules.each_with_object(Hash.new {|h,k| h[k] = []}) do |rule,rules_found| found = rule.find_selector(tree) rules_found[found.length] << rule if found end end
format_from_declarations(declarations, node)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 138 def format_from_declarations(declarations, node) denied = Hash.new { |h,k| h[k] = [] }.merge( "table" => %w{ width height }, "tr" => %w{ width } ) declarations.delete_if { |k,v| v.nil? || v.empty? || denied[node.name].include?(k) } declarations.each_with_object({}) { |(k,v), format| format.merge!(translate_declaration(k,v[:value])) } end
format_from_klass_tree(klass, node)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 73 def format_from_klass_tree(klass, node) # klass is uniq to each node (because of first-child, nth-child, etc) # so caching with the class is useless # TODO find a better way to cache that works if @cache[klass] format = @cache[klass] else declarations = declarations_from_klass_tree(klass) format = format_from_declarations(declarations, node) @cache[klass] = format end format || {} end
klass_node_from_node(node)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 88 def klass_node_from_node(node) name = node.name root = node.ancestors.last siblings = node.parent.element_children index = siblings.index(node) + 1 first_of_kind = root.css(name).first == node last_of_kind = root.css(name).last == node klasses = node.attributes["class"] && node.attributes["class"].value klasses = klasses.to_s.split(/ /).map { |k| "." + k } klasses << name klasses << "#{name}:nth-child(#{index})" klasses << "#{name}:nth-child(odd)" if index.odd? klasses << "#{name}:nth-child(even)" if index.even? klasses << "#{name}:first-child)" if index == 1 klasses << "#{name}:last-child)" if index == siblings.length klasses << "#{name}:first-of-kind)" if first_of_kind klasses << "#{name}:last-of-kind)" if last_of_kind klasses end
klass_tree_from_node(base)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 68 def klass_tree_from_node(base) tree = (base.ancestors.reverse.drop(1) << base) tree.map { |n, t| klass_node_from_node(n) } end
reset_cache()
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 159 def reset_cache @cache = {} end
reset_none()
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 117 def reset_none end
reset_parser()
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 163 def reset_parser parser = CssParser::Parser.new @load_paths.each do |uri| begin parser.load_uri!(uri) rescue CssParser::RemoteFileError => error error.message = "Failed to load #{uri}" raise error end end # Explicity reset rules to avoid infinite loop or bad data reset_rules(parser) reset_cache @parser = parser end
reset_rules(parser = @parser)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 120 def reset_rules(parser = @parser) @rules = [] parser.each_rule_set(:all) { |r| @rules << SpreadsheetBuilder::CssRule.new(r) } @rules.delete_if { |rule| rule.each_declaration do |key,_| rule.remove_declaration!(key) unless accepted_keys.include?(key) end rule.declarations.empty? } end
translate_declaration(key, val)
click to toggle source
# File lib/spreadsheet_builder/css_parser.rb, line 133 def translate_declaration(key, val) f = TRANSLATIONS[key].call(val) if key && val f || {} end