Module: Habaki::Shorthand
- Included in:
- Declarations
- Defined in:
- lib/habaki/declarations.rb
Overview
partially adapted from css_parser github.com/premailer/css_parser/blob/master/lib/css_parser/rule_set.rb
Constant Summary collapse
- BORDER_PROPERTIES =
%w[border border-left border-right border-top border-bottom].freeze
- DIMENSIONS =
[ ['margin', %w[margin-top margin-right margin-bottom margin-left]], ['padding', %w[padding-top padding-right padding-bottom padding-left]], ['border-color', %w[border-top-color border-right-color border-bottom-color border-left-color]], ['border-style', %w[border-top-style border-right-style border-bottom-style border-left-style]], ['border-width', %w[border-top-width border-right-width border-bottom-width border-left-width]] ].freeze
- PRECOMPUTED_SHORTHAND_PROPS =
{ "background" => shorthand_properties("background"), "font" => shorthand_properties("font"), "list-style" => shorthand_properties("list-style"), "border" => shorthand_properties("border"), "border-top" => shorthand_properties("border-top"), "border-bottom" => shorthand_properties("border-bottom"), "border-left" => shorthand_properties("border-left"), "border-right" => shorthand_properties("border-right"), "border-width" => shorthand_properties("border-width"), "border-style" => shorthand_properties("border-style"), "border-color" => shorthand_properties("border-color"), }
Class Method Summary collapse
Instance Method Summary collapse
- #compute_dimensions_shorthand(values) ⇒ Object
-
#create_background_shorthand! ⇒ Object
Looks for long format CSS background properties (e.g.
background-color) and converts them into a shorthand CSSbackgroundproperty. -
#create_border_shorthand! ⇒ Object
Combine border-color, border-style and border-width into border Should be run after create_dimensions_shorthand!.
-
#create_dimensions_shorthand! ⇒ Object
Looks for long format CSS dimensional properties (margin, padding, border-color, border-style and border-width) and converts them into shorthand CSS properties.
-
#create_font_shorthand! ⇒ Object
Looks for long format CSS font properties (e.g.
font-weight) and tries to convert them into a shorthand CSSfontproperty. -
#create_list_style_shorthand! ⇒ Object
Looks for long format CSS list-style properties (e.g.
list-style-type) and converts them into a shorthand CSSlist-styleproperty. -
#create_shorthand! ⇒ Object
Create shorthand declarations (e.g.
marginorfont) whenever possible. -
#create_shorthand_properties!(shorthand_property, need_all = false) ⇒ Object
Combine several properties into a shorthand one.
-
#expand_background_shorthand! ⇒ Object
Convert shorthand background declarations (e.g.
background: url("chess.png") gray 50% repeat fixed;) into their constituent parts. -
#expand_border_shorthand! ⇒ Object
Split shorthand border declarations (e.g.
border: 1px red;) Additional splitting happens in expand_dimensions_shorthand!. -
#expand_dimensions_shorthand! ⇒ Object
Split shorthand dimensional declarations (e.g.
margin: 0px auto;) into their constituent parts. -
#expand_font_shorthand! ⇒ Object
Convert shorthand font declarations (e.g.
font: 300 italic 11px/14px verdana, helvetica, sans-serif;) into their constituent parts. -
#expand_list_style_shorthand! ⇒ Object
Convert shorthand list-style declarations (e.g.
list-style: lower-alpha outside;) into their constituent parts. -
#expand_shorthand! ⇒ Object
Split shorthand declarations (e.g.
marginorfont) into their constituent parts. - #expand_shorthand_properties!(property) ⇒ Object
Class Method Details
.shorthand_properties(shorthand_property) ⇒ Object
163 164 165 166 167 168 169 |
# File 'lib/habaki/declarations.rb', line 163 def self.shorthand_properties(shorthand_property) nodes = [] FormalSyntax::Tree.tree.property("--shorthand-"+shorthand_property).traverse do |node| nodes << {type: node.type, value: node.value, next_value: node.parent&.children&.last&.value} if [:ref, :token].include?(node.type) end nodes end |
Instance Method Details
#compute_dimensions_shorthand(values) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/habaki/declarations.rb', line 245 def compute_dimensions_shorthand(values) # All four sides are equal, returning single value return [:top] if values.values.uniq.count == 1 # `/* top | right | bottom | left */` return [:top, :right, :bottom, :left] if values[:left] != values[:right] # Vertical are the same & horizontal are the same, `/* vertical | horizontal */` return [:top, :left] if values[:top] == values[:bottom] [:top, :left, :bottom] end |
#create_background_shorthand! ⇒ Object
Looks for long format CSS background properties (e.g. background-color) and converts them into a shorthand CSS background property.
Leaves properties declared !important alone.
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/habaki/declarations.rb', line 136 def create_background_shorthand! # :nodoc: # When we have a background-size property we must separate it and distinguish it from # background-position by preceding it with a backslash. In this case we also need to # have a background-position property, so we set it if it's missing. # http://www.w3schools.com/cssref/css3_pr_background.asp if (declaration = find_by_property('background-size')) && !declaration.important add_by_property('background-position', Values.new([Percentage.new(0), Percentage.new(0)])) end create_shorthand_properties! 'background' end |
#create_border_shorthand! ⇒ Object
Combine border-color, border-style and border-width into border Should be run after create_dimensions_shorthand!
122 123 124 125 126 127 128 129 130 |
# File 'lib/habaki/declarations.rb', line 122 def create_border_shorthand! # :nodoc: border_style_properties = %w[border-width border-style border-color] border_style_properties.each do |prop| create_shorthand_properties! prop unless has_property?(prop) end create_shorthand_properties! 'border' if border_style_properties.map{|prop| has_property?(prop)}.all? end |
#create_dimensions_shorthand! ⇒ Object
Looks for long format CSS dimensional properties (margin, padding, border-color, border-style and border-width) and converts them into shorthand CSS properties.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/habaki/declarations.rb', line 219 def create_dimensions_shorthand! # :nodoc: return if length < 4 DIMENSIONS.each do |property, dimensions| values = [:top, :right, :bottom, :left].each_with_index.with_object({}) do |(side, index), result| next unless (declaration = find_by_property(dimensions[index])) result[side] = declaration.value end # All four dimensions must be present next if values.length != dimensions.length new_values = Values.new(values.values_at(*compute_dimensions_shorthand(values))) unless new_values.empty? first_position = find_by_property(dimensions.first)&.position decl = add_by_property(property, new_values) decl.position = first_position end # Delete the longhand values dimensions.each do |prop| remove_by_property(prop) end end end |
#create_font_shorthand! ⇒ Object
Looks for long format CSS font properties (e.g. font-weight) and tries to convert them into a shorthand CSS font property. All font properties must be present in order to create a shorthand declaration.
151 152 153 |
# File 'lib/habaki/declarations.rb', line 151 def create_font_shorthand! # :nodoc: create_shorthand_properties!("font", true) end |
#create_list_style_shorthand! ⇒ Object
Looks for long format CSS list-style properties (e.g. list-style-type) and converts them into a shorthand CSS list-style property.
Leaves properties declared !important alone.
159 160 161 |
# File 'lib/habaki/declarations.rb', line 159 def create_list_style_shorthand! # :nodoc: create_shorthand_properties! 'list-style' end |
#create_shorthand! ⇒ Object
Create shorthand declarations (e.g. margin or font) whenever possible.
111 112 113 114 115 116 117 118 |
# File 'lib/habaki/declarations.rb', line 111 def create_shorthand! create_background_shorthand! create_dimensions_shorthand! # border must be shortened after dimensions create_border_shorthand! create_font_shorthand! create_list_style_shorthand! end |
#create_shorthand_properties!(shorthand_property, need_all = false) ⇒ Object
Combine several properties into a shorthand one
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/habaki/declarations.rb', line 186 def create_shorthand_properties!(shorthand_property, need_all = false) properties_to_delete = [] new_values = [] PRECOMPUTED_SHORTHAND_PROPS[shorthand_property].each do |node| case node[:type] when :ref decl = find_by_property(node[:value]) if decl properties_to_delete << decl.property new_values += decl.values else return if need_all end when :token # only if next node property is present (line-height, background-size) new_values << Operator.new(node[:value]) if node[:next_value] && has_property?(node[:next_value]) end end return if new_values.empty? first_position = find_by_property(properties_to_delete.first)&.position properties_to_delete.each do |property| remove_by_property(property) end new_decl = add_by_property(shorthand_property, new_values) new_decl.position = first_position end |
#expand_background_shorthand! ⇒ Object
Convert shorthand background declarations (e.g. background: url("chess.png") gray 50% repeat fixed;) into their constituent parts.
69 70 71 |
# File 'lib/habaki/declarations.rb', line 69 def # :nodoc: ("background") end |
#expand_border_shorthand! ⇒ Object
Split shorthand border declarations (e.g. border: 1px red;) Additional splitting happens in expand_dimensions_shorthand!
26 27 28 29 30 |
# File 'lib/habaki/declarations.rb', line 26 def # :nodoc: BORDER_PROPERTIES.each do |k| (k) end end |
#expand_dimensions_shorthand! ⇒ Object
Split shorthand dimensional declarations (e.g. margin: 0px auto;) into their constituent parts. Handles margin, padding, border-color, border-style and border-width.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/habaki/declarations.rb', line 34 def # :nodoc: DIMENSIONS.each do |property, (top, right, bottom, left)| next unless (declaration = find_by_property(property)) case declaration.values.length when 1 values = declaration.values * 4 when 2 values = declaration.values * 2 when 3 values = declaration.values values << declaration.values[1] # left = right when 4 values = declaration.values else # "Habaki error: Cannot parse #{property}: #{declaration.values} (#{declaration.values.length} values)" next end replacement = [top, right, bottom, left].zip(values).to_h position = find_by_property(property)&.position remove_by_property(property) replacement.each do |short_prop, value| decl = add_by_property(short_prop, value) decl.position = position end end end |
#expand_font_shorthand! ⇒ Object
Convert shorthand font declarations (e.g. font: 300 italic 11px/14px verdana, helvetica, sans-serif;) into their constituent parts.
75 76 77 |
# File 'lib/habaki/declarations.rb', line 75 def # :nodoc: ("font") end |
#expand_list_style_shorthand! ⇒ Object
Convert shorthand list-style declarations (e.g. list-style: lower-alpha outside;) into their constituent parts.
83 84 85 |
# File 'lib/habaki/declarations.rb', line 83 def # :nodoc: ("list-style") end |
#expand_shorthand! ⇒ Object
Split shorthand declarations (e.g. margin or font) into their constituent parts.
15 16 17 18 19 20 21 22 |
# File 'lib/habaki/declarations.rb', line 15 def # border must be expanded before dimensions end |
#expand_shorthand_properties!(property) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/habaki/declarations.rb', line 87 def (property) return unless (declaration = find_by_property(property)) tmp_decl = Declaration.new("--shorthand-"+declaration.property, declaration.important) tmp_decl.values = declaration.values matcher = FormalSyntax::Matcher.new(tmp_decl) return unless matcher.match? props = {} matcher.matches.each do |match| next if match.value == Operator.new("/") # font-size/line-height props[match.reference] ||= Values.new props[match.reference] << match.value end props.each do |prop, values| new_decl = add_by_property(prop, values) new_decl.position = declaration.position end remove_by_property(property) end |