Skip to content

Commit

Permalink
Moved all property handling into property models
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtimberlake committed Jan 1, 2011
1 parent 0d075d5 commit d2833e2
Show file tree
Hide file tree
Showing 21 changed files with 1,324 additions and 761 deletions.
2 changes: 2 additions & 0 deletions lib/css.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require "numbers"
require "css/colors"
require "css/errors"
require "css/normalize"
require "css/parser"
require "css/property"
require "css/rule"
Expand Down
15 changes: 15 additions & 0 deletions lib/css/normalize.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module CSS
module Normalize
def normalize_property_name(name)
if name.to_s =~ /[A-Z]/
name.to_s.gsub(/([A-Z])/) do |match|
"-#{match.downcase}"
end
elsif name.to_s =~ /_/
name.to_s.gsub(/_/, '-')
else
name.to_s
end
end
end
end
35 changes: 12 additions & 23 deletions lib/css/properties/background_property.rb
Original file line number Diff line number Diff line change
@@ -1,47 +1,36 @@
module CSS
class BackgroundProperty < Property
DEFAULT_PROPERTIES = {
'color' => 'transparent',
'image' => 'none',
'repeat' => 'repeat',
'position' => 'top left',
'attachment' => 'scroll'
}

def initialize(*args)
@properties = DEFAULT_PROPERTIES.clone
super
end

def name
'background'
end

def value
%w(color image repeat position attachment).map { |prop| @properties[prop] != DEFAULT_PROPERTIES[prop] ? @properties[prop] : nil }.compact.join(' ')
%w(color image repeat position attachment).map { |prop| @properties[prop] != default_properties[prop] ? @properties[prop] : nil }.compact.join(' ')
end

def to_s
[name, value].join(':')
end

def method_missing(method_name, *args, &block)
if method_name.to_s[-1..-1] == '='
@properties[method_name.to_s.chop] = args[0]
else
@properties[method_name.to_s] || super
end
end

private
def init(name, value)
if name =~ /-/
@properties[name.sub(/[^-]+-(.*)/, '$1')] = value
@properties[name.sub(/[^-]+-(.*)/, '\1')] = value
else
expand_property value if value
end
end

def default_properties
{
'color' => 'transparent',
'image' => 'none',
'repeat' => 'repeat',
'position' => 'top left',
'attachment' => 'scroll'
}
end

def expand_property(value)
values = value.delete(';').split(/\s+/)
while values.size > 0
Expand Down
54 changes: 54 additions & 0 deletions lib/css/properties/border_property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module CSS
class BorderProperty < Property
def name
'border'
end

def to_s
value = %w(size style color).map { |prop| @properties[prop] != default_properties[prop] ? @properties[prop] : nil }.compact.join(' ')
if value == @properties['size']
"border-size:#{@properties['size']}"
else
[name, value].join(':')
end
end

private
def init(name, value)
if name =~ /-/
@properties[name.sub(/[^-]+-(.*)/, '\1')] = value
else
expand_property value if value
end
end

def default_properties
{
'size' => '3px',
'style' => nil,
'color' => 'black'
}
end

def expand_property(value)
values = value.delete(';').split(/\s+/)

val = values.pop
if val =~ /^(#|rgb)/ || Colors::NAMES.include?(val.upcase)
@properties["color"] = val
else
values << val
end

val = values.pop
if val =~ /^\d/
values << val
else
@properties["style"] = val if val
end

val = values.pop
@properties["size"] = val if val
end
end
end
78 changes: 78 additions & 0 deletions lib/css/properties/font_property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
module CSS
class FontProperty < Property
def name
'font'
end

def value
%w(style variant weight size family).map do |prop|
if @properties[prop] != default_properties[prop]
if prop == 'size' && @properties['line-height']
[@properties[prop], @properties['line-height']].join('/')
else
@properties[prop]
end
else
nil
end
end.compact.join(' ')
end

def to_s
[name, value].join(':')
end

private
def init(name, value)
if name =~ /-/
@properties[name.sub(/[^-]+-(.*)/, '\1')] = value
else
expand_property value if value
end
end

def default_properties
{
'style' => 'normal',
'variant' => 'normal',
'weight' => 'normal',
'size' => 'inherit',
'family' => 'inherit',
'line-height' => nil
}
end

def expand_property(value)
font_families = value.delete(';').split(/,/)
values = font_families.shift.split(/\s+/)

font_families.unshift values.pop
if font_families[0] =~ /"\s*$/
font_families[0] = [values.pop, font_families[0]].join(' ')
end
@properties['family'] = font_families.join(',')

val = values.pop
font_size, line_height = val.split(/\//)
@properties['size'] = font_size
@properties['line-height'] = line_height if line_height

val = values.shift
if val =~ /(inherit|italic|oblique)/
@properties['style'] = val
else
values << val
end

val = values.shift
if val =~ /(inherit|small-caps)/
@properties['variant'] = val
else
values << val
end

val = values.shift
@properties['weight'] = val if val
end
end
end
51 changes: 51 additions & 0 deletions lib/css/properties/list_style_property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module CSS
class ListStyleProperty < Property
def initialize(*args)
@properties = default_properties.clone
super
end

def name
'list-style'
end

def to_s
%w(type position image).map { |prop| @properties[prop] }.join(' ')
end

def type
default_properties['type'] == @properties['type'] ? nil : @properties['type']
end

def type=(val)
@properties['type'] = val
end

private
def init(name, value)
expand_property value if value
end

def default_properties
{
'type' => 'disc',
'position' => 'outside',
'image' => 'none'
}
end

def expand_property(value)
values = value.delete(';').split(/\s+/)
while values.size > 0
val = values.shift
if val =~ /^url/
@properties['image'] = val
elsif val =~ /^(inside|outside)/
@properties['position'] = val
else
@properties['type'] = val
end
end
end
end
end
79 changes: 79 additions & 0 deletions lib/css/properties/margin_property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module CSS
class MarginProperty < Property
def name
'margin'
end

def to_s
top = @properties['top']
right = @properties['right']
bottom = @properties['bottom']
left = @properties['left']

if top && right && bottom && left
value = if [top, right, bottom, left] == Array.new(4) { top }
top
elsif [top, bottom] == Array.new(2) { top } && [left, right] == Array.new(2) { left }
[top, left].join(' ')
elsif [top, bottom] != Array.new(2) { top } && [left, right] == Array.new(2) { left }
[top, left, bottom].join(' ')
else
[top, right, bottom, left].join(' ')
end
[name, value].join(':')
else
default_properties.keys.map { |prop| @properties[prop] ? ["#{name}-#{prop}", @properties[prop]].join(':') : nil }.compact.join(';')
end
end

private
def init(name, value)
if name =~ /-/
@properties[name.sub(/[^-]+-(.*)/, '\1')] = value
else
expand_property value if value
end
end

def default_properties
{
'top' => nil,
'right' => nil,
'bottom' => nil,
'left' => nil
}
end

def expand_property(value)
values = value.delete(';').split(/\s+/)

top, right, bottom, left = 0, 0, 0, 0
if values.size == 1
top = values[0]
right = values[0]
bottom = values[0]
left = values[0]
elsif values.size == 2
top = values[0]
bottom = values[0]
left = values[1]
right = values[1]
elsif values.size == 3
top = values[0]
bottom = values[2]
left = values[1]
right = values[1]
else
top = values[0]
right = values[1]
bottom = values[2]
left = values[3]
end

@properties['top'] = top
@properties['right'] = right
@properties['bottom'] = bottom
@properties['left'] = left
end
end
end
7 changes: 7 additions & 0 deletions lib/css/properties/outline_property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module CSS
class OutlineProperty < BorderProperty
def name
'outline'
end
end
end
7 changes: 7 additions & 0 deletions lib/css/properties/padding_property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module CSS
class PaddingProperty < MarginProperty
def name
'padding'
end
end
end
Loading

0 comments on commit d2833e2

Please sign in to comment.