css 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/css.rb +2 -2
- data/lib/css/helpers/normalize.rb +16 -0
- data/lib/css/helpers/orientation.rb +19 -0
- data/lib/css/properties/background_property.rb +17 -19
- data/lib/css/properties/border_orientation_property.rb +53 -0
- data/lib/css/properties/border_property.rb +86 -18
- data/lib/css/properties/border_unit_property.rb +16 -0
- data/lib/css/properties/font_property.rb +16 -31
- data/lib/css/properties/list_style_property.rb +16 -13
- data/lib/css/properties/margin_property.rb +23 -27
- data/lib/css/property.rb +55 -14
- data/lib/css/rule.rb +44 -28
- data/lib/css/rule_set.rb +3 -9
- data/lib/monkey_patches.rb +15 -0
- metadata +8 -4
- data/lib/css/normalize.rb +0 -15
data/lib/css.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require "numbers"
|
2
|
+
require "monkey_patches"
|
2
3
|
require "css/colors"
|
3
4
|
require "css/errors"
|
4
|
-
require "css/normalize"
|
5
5
|
require "css/parser"
|
6
6
|
require "css/property"
|
7
7
|
require "css/rule"
|
8
8
|
require "css/rule_set"
|
9
9
|
|
10
10
|
module CSS
|
11
|
-
VERSION = "0.0.
|
11
|
+
VERSION = "0.0.4"
|
12
12
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CSS
|
2
|
+
module Normalize
|
3
|
+
def normalize_property_name(name)
|
4
|
+
name = name.to_s.strip
|
5
|
+
if name =~ /[A-Z]/
|
6
|
+
name.gsub(/([A-Z])/) do |match|
|
7
|
+
"-#{match.downcase}"
|
8
|
+
end
|
9
|
+
elsif name =~ /_/
|
10
|
+
name.gsub(/_/, '-')
|
11
|
+
else
|
12
|
+
name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CSS
|
2
|
+
module Orientation
|
3
|
+
NESW = %w(top right bottom left)
|
4
|
+
|
5
|
+
def compact_orientation(top, right, bottom, left)
|
6
|
+
if top && right && bottom && left
|
7
|
+
if [top, right, bottom, left] == Array.new(4) { top }
|
8
|
+
top.value
|
9
|
+
elsif [top, bottom] == Array.new(2) { top } && [left, right] == Array.new(2) { left }
|
10
|
+
[top, left].map { |s| s.value }.join(' ')
|
11
|
+
elsif [top, bottom] != Array.new(2) { top } && [left, right] == Array.new(2) { left }
|
12
|
+
[top, left, bottom].map { |s| s.value }.join(' ')
|
13
|
+
else
|
14
|
+
[top, right, bottom, left].map { |s| s.value }.join(' ')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -4,19 +4,17 @@ module CSS
|
|
4
4
|
'background'
|
5
5
|
end
|
6
6
|
|
7
|
-
def to_s
|
8
|
-
%w(color image repeat position attachment).map { |prop| @properties[prop] && @properties[prop] != default_properties[prop] ? @properties[prop].value : nil }.compact.join(' ')
|
9
|
-
end
|
10
|
-
|
11
7
|
def to_style
|
12
|
-
[
|
8
|
+
values = %w(color image repeat position attachment).map { |prop| @properties[prop] && @properties[prop] != default_properties[prop] ? @properties[prop].value : nil }.compact.join(' ')
|
9
|
+
[name, values].join(':')
|
13
10
|
end
|
14
11
|
|
15
12
|
private
|
16
|
-
def init(name, value)
|
13
|
+
def init(parent, name, value)
|
14
|
+
@parent = parent
|
17
15
|
if name =~ /-/
|
18
16
|
property_name = name.sub(/[^-]+-(.*)/, '\1')
|
19
|
-
@properties[property_name] = Property.new(
|
17
|
+
@properties[property_name] = Property.new(self, property_name, value)
|
20
18
|
else
|
21
19
|
expand_property value if value
|
22
20
|
end
|
@@ -24,11 +22,11 @@ module CSS
|
|
24
22
|
|
25
23
|
def default_properties
|
26
24
|
@@default_properties ||= {
|
27
|
-
'color' => Property.
|
28
|
-
'image' => Property.
|
29
|
-
'repeat' => Property.
|
30
|
-
'position' => Property.
|
31
|
-
'attachment' => Property.
|
25
|
+
'color' => Property.new(self, 'color', 'transparent'),
|
26
|
+
'image' => Property.new(self, 'image', 'none'),
|
27
|
+
'repeat' => Property.new(self, 'repeat', 'repeat'),
|
28
|
+
'position' => Property.new(self, 'position', 'top left'),
|
29
|
+
'attachment' => Property.new(self, 'attachment', 'scroll')
|
32
30
|
}
|
33
31
|
end
|
34
32
|
|
@@ -37,22 +35,22 @@ module CSS
|
|
37
35
|
while values.size > 0
|
38
36
|
val = values.shift
|
39
37
|
if val =~ /^(#|rgb)/ || val == 'transparent' || Colors::NAMES.keys.include?(val.to_s.upcase)
|
40
|
-
@properties['color'] = Property.
|
38
|
+
@properties['color'] = Property.new(self, 'color', val)
|
41
39
|
elsif val =~ /^url/
|
42
|
-
@properties['image'] = Property.
|
40
|
+
@properties['image'] = Property.new(self, 'image', val)
|
43
41
|
elsif val =~ /repeat/
|
44
|
-
@properties['repeat'] = Property.
|
42
|
+
@properties['repeat'] = Property.new(self, 'repeat', val)
|
45
43
|
elsif val =~ /^(\d|top|bottom|center)/
|
46
44
|
val2 = values.shift
|
47
|
-
@properties['position'] = Property.
|
45
|
+
@properties['position'] = Property.new(self, 'position', [val, val2].join(' '))
|
48
46
|
elsif val =~ /inherit/
|
49
47
|
if values.size == 0
|
50
|
-
@properties['attachment'] = Property.
|
48
|
+
@properties['attachment'] = Property.new(self, 'attachment', val)
|
51
49
|
else
|
52
|
-
@properties['repeat'] = Property.
|
50
|
+
@properties['repeat'] = Property.new(self, 'repeat', val)
|
53
51
|
end
|
54
52
|
elsif values.size == 0
|
55
|
-
@properties['attachment'] = Property.
|
53
|
+
@properties['attachment'] = Property.new(self, 'attachment', val)
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module CSS
|
2
|
+
class BorderOrientationProperty < Property
|
3
|
+
def to_style
|
4
|
+
value = %w(size style color).map { |prop| @properties[prop] && @properties[prop] != default_properties[prop] ? @properties[prop].value : nil }.compact.join(' ')
|
5
|
+
if @properties['color'].nil? && @properties['style'].nil?
|
6
|
+
"border-size:#{@properties['size']}"
|
7
|
+
else
|
8
|
+
[name, value].join(':')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def init(parent, name, value)
|
14
|
+
@parent = parent
|
15
|
+
@name = name
|
16
|
+
if name =~ /-/
|
17
|
+
property_name = name.sub(/[^-]+-(.*)/, '\1')
|
18
|
+
@properties[property_name] = Property.new(self, property_name, value)
|
19
|
+
else
|
20
|
+
expand_property value if value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_properties
|
25
|
+
@@default_properties ||= {
|
26
|
+
'size' => Property.new(self, 'size', '3px'),
|
27
|
+
'style' => nil,
|
28
|
+
'color' => Property.new(self, 'color', 'black')
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def expand_property(value)
|
33
|
+
values = value.delete(';').split(/\s+/)
|
34
|
+
|
35
|
+
val = values.pop
|
36
|
+
if val =~ /^(#|rgb)/ || Colors::NAMES.include?(val.upcase)
|
37
|
+
@properties["color"] = Property.new(self, 'color', val)
|
38
|
+
else
|
39
|
+
values << val
|
40
|
+
end
|
41
|
+
|
42
|
+
val = values.pop
|
43
|
+
if val =~ /^\d/
|
44
|
+
values << val
|
45
|
+
else
|
46
|
+
@properties["style"] = Property.new(self, 'style', val) if val
|
47
|
+
end
|
48
|
+
|
49
|
+
val = values.pop
|
50
|
+
@properties["size"] = Property.new(self, 'size', val) if val
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,32 +1,89 @@
|
|
1
|
+
require 'css/helpers/orientation'
|
2
|
+
|
1
3
|
module CSS
|
2
4
|
class BorderProperty < Property
|
5
|
+
include Orientation
|
6
|
+
|
3
7
|
def name
|
4
8
|
'border'
|
5
9
|
end
|
6
10
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
def to_style
|
12
|
+
sides = NESW.map { |o| @properties[o] }
|
13
|
+
value = nil
|
14
|
+
if %w(size style color).all? { |p| sides.all? { |side| @properties['top'].try(p) == side.try(p) && !side.try(p).nil? } }
|
15
|
+
value = %w(size style color).map { |p| top.send(p).value }.join(' ')
|
16
|
+
elsif %w(style color).all? { |p| sides.all? { |side| @properties['top'].try(p) == side.try(p) && !side.try(p).nil? } }
|
17
|
+
value = %w(style color).map { |p| top.send(p).value }.join(' ')
|
18
|
+
elsif %w(size style).all? { |p| sides.all? { |side| @properties['top'].try(p) == side.try(p) && !side.try(p).nil? } }
|
19
|
+
value = %w(size style).map { |p| top.send(p).value }.join(' ')
|
20
|
+
end
|
21
|
+
if value
|
22
|
+
[name, value].join(':')
|
11
23
|
else
|
12
|
-
|
24
|
+
if %w(style color).all? { |p| sides.all? { |side| side.try(p).nil? } } && sides.all? { |side| @properties['top'].try('size') == side.try('size') && !side.try('size').nil? }
|
25
|
+
"border-size:#{top.size.value}"
|
26
|
+
else
|
27
|
+
sides.map { |side| side.empty? ? nil : side.to_style }.compact.join(';')
|
28
|
+
end
|
13
29
|
end
|
14
30
|
end
|
15
31
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
32
|
+
def size
|
33
|
+
method_missing(:size)
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(method_name, *args)
|
37
|
+
if method_name.to_s[-1..-1] == '='
|
38
|
+
property_name = normalize_property_name(method_name.to_s.chop)
|
39
|
+
if %w(size style color).include?(property_name)
|
40
|
+
NESW.each do |o|
|
41
|
+
@properties[o].send(method_name, *args)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
20
46
|
else
|
21
|
-
|
47
|
+
if %w(color size style).include?(method_name.to_s)
|
48
|
+
property = BorderUnitProperty.new(self, method_name.to_s)
|
49
|
+
is_nil = true
|
50
|
+
NESW.each do |o|
|
51
|
+
prop = @properties[o].send(method_name).try(:value)
|
52
|
+
if prop
|
53
|
+
property.send("#{o}=", prop)
|
54
|
+
is_nil = false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
is_nil ? nil :property
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
22
61
|
end
|
23
62
|
end
|
24
63
|
|
64
|
+
def respond_to?(method_name, include_private = false)
|
65
|
+
property_name = normalize_property_name(method_name.to_s[-1..-1] == '=' ? method_name.to_s.chop : method_name)
|
66
|
+
%w(size style color).include?(property_name) || super
|
67
|
+
end
|
68
|
+
|
25
69
|
private
|
26
|
-
def init(name, value)
|
70
|
+
def init(parent, name, value)
|
71
|
+
@parent = parent
|
72
|
+
|
73
|
+
#Allocate new orientation properties
|
74
|
+
NESW.each do |o|
|
75
|
+
@properties[o] = BorderOrientationProperty.new(self, o)
|
76
|
+
end
|
77
|
+
|
27
78
|
if name =~ /-/
|
28
79
|
property_name = name.sub(/[^-]+-(.*)/, '\1')
|
29
|
-
|
80
|
+
if NESW.include?(property_name)
|
81
|
+
@properties[property_name] = BorderOrientationProperty.new(self, property_name, value)
|
82
|
+
else
|
83
|
+
NESW.each do |orientation|
|
84
|
+
@properties[orientation].send("#{property_name}=", value)
|
85
|
+
end
|
86
|
+
end
|
30
87
|
else
|
31
88
|
expand_property value if value
|
32
89
|
end
|
@@ -34,9 +91,10 @@ module CSS
|
|
34
91
|
|
35
92
|
def default_properties
|
36
93
|
@@default_properties ||= {
|
37
|
-
'
|
38
|
-
'
|
39
|
-
'
|
94
|
+
'top' => BorderOrientationProperty.new(self, 'top'),
|
95
|
+
'right' => BorderOrientationProperty.new(self, 'right'),
|
96
|
+
'bottom' => BorderOrientationProperty.new(self, 'bottom'),
|
97
|
+
'left' => BorderOrientationProperty.new(self, 'left')
|
40
98
|
}
|
41
99
|
end
|
42
100
|
|
@@ -45,7 +103,9 @@ module CSS
|
|
45
103
|
|
46
104
|
val = values.pop
|
47
105
|
if val =~ /^(#|rgb)/ || Colors::NAMES.include?(val.upcase)
|
48
|
-
|
106
|
+
NESW.each do |o|
|
107
|
+
@properties[o].send('color=', val)
|
108
|
+
end
|
49
109
|
else
|
50
110
|
values << val
|
51
111
|
end
|
@@ -54,11 +114,19 @@ module CSS
|
|
54
114
|
if val =~ /^\d/
|
55
115
|
values << val
|
56
116
|
else
|
57
|
-
|
117
|
+
if val
|
118
|
+
NESW.each do |o|
|
119
|
+
@properties[o].send('style=', val)
|
120
|
+
end
|
121
|
+
end
|
58
122
|
end
|
59
123
|
|
60
124
|
val = values.pop
|
61
|
-
|
125
|
+
if val
|
126
|
+
NESW.each do |o|
|
127
|
+
@properties[o].send('size=', val)
|
128
|
+
end
|
129
|
+
end
|
62
130
|
end
|
63
131
|
end
|
64
132
|
end
|
@@ -4,30 +4,14 @@ module CSS
|
|
4
4
|
'font'
|
5
5
|
end
|
6
6
|
|
7
|
-
def to_s
|
8
|
-
if size && family
|
9
|
-
%w(style variant weight size family).map do |prop|
|
10
|
-
if @properties[prop] != default_properties[prop]
|
11
|
-
if prop == 'size' && get('size') != nil && @properties['line-height']
|
12
|
-
[@properties[prop], @properties['line-height']].join('/')
|
13
|
-
else
|
14
|
-
@properties[prop]
|
15
|
-
end
|
16
|
-
else
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
end.compact.join(' ')
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
7
|
def to_style
|
24
8
|
if size && family
|
25
9
|
values = %w(style variant weight size family).map do |prop|
|
26
10
|
if @properties[prop] != default_properties[prop]
|
27
11
|
if prop == 'size' && get('size') != nil && @properties['line-height']
|
28
|
-
[@properties[prop], @properties['line-height']].join('/')
|
12
|
+
[@properties[prop].value, @properties['line-height'].value].join('/')
|
29
13
|
else
|
30
|
-
@properties[prop]
|
14
|
+
@properties[prop].try(:value)
|
31
15
|
end
|
32
16
|
else
|
33
17
|
nil
|
@@ -35,17 +19,18 @@ module CSS
|
|
35
19
|
end.compact.join(' ')
|
36
20
|
[name, values].join(':')
|
37
21
|
else
|
38
|
-
@properties.map { |
|
22
|
+
@properties.map { |property_name, property| "#{property_name == 'line-height' ? '' : 'font-'}#{property_name}:#{property.value}" }.join(';')
|
39
23
|
end
|
40
24
|
end
|
41
25
|
|
42
26
|
private
|
43
|
-
def init(name, value)
|
27
|
+
def init(parent, name, value)
|
28
|
+
@parent = parent
|
44
29
|
if name == 'line-height'
|
45
30
|
@properties['line-height'] = Property.new(:p, 'line-height', value)
|
46
31
|
elsif name =~ /-/
|
47
32
|
property_name = name.sub(/[^-]+-(.*)/, '\1')
|
48
|
-
@properties[property_name] = Property.new(
|
33
|
+
@properties[property_name] = Property.new(self, property_name, value)
|
49
34
|
else
|
50
35
|
expand_property value if value
|
51
36
|
end
|
@@ -53,11 +38,11 @@ module CSS
|
|
53
38
|
|
54
39
|
def default_properties
|
55
40
|
@@default_properties ||= {
|
56
|
-
'style' => Property.new(
|
57
|
-
'variant' => Property.new(
|
58
|
-
'weight' => Property.new(
|
59
|
-
'size' => Property.new(
|
60
|
-
'family' => Property.new(
|
41
|
+
'style' => Property.new(self, 'style', 'normal'),
|
42
|
+
'variant' => Property.new(self, 'variant', 'normal'),
|
43
|
+
'weight' => Property.new(self, 'weight', 'normal'),
|
44
|
+
'size' => Property.new(self, 'size', 'inherit'),
|
45
|
+
'family' => Property.new(self, 'family', 'inherit'),
|
61
46
|
'line-height' => nil
|
62
47
|
}
|
63
48
|
end
|
@@ -70,29 +55,29 @@ module CSS
|
|
70
55
|
if font_families[0] =~ /"\s*$/
|
71
56
|
font_families[0] = [values.pop, font_families[0]].join(' ')
|
72
57
|
end
|
73
|
-
@properties['family'] = Property.new(
|
58
|
+
@properties['family'] = Property.new(self, 'family', font_families.join(','))
|
74
59
|
|
75
60
|
val = values.pop
|
76
61
|
font_size, line_height = val.split(/\//)
|
77
|
-
@properties['size'] = Property.new(
|
62
|
+
@properties['size'] = Property.new(self, 'size', font_size)
|
78
63
|
@properties['line-height'] = Property.new(:p, 'line-height', line_height) if line_height
|
79
64
|
|
80
65
|
val = values.shift
|
81
66
|
if val =~ /(inherit|italic|oblique)/
|
82
|
-
@properties['style'] = Property.new(
|
67
|
+
@properties['style'] = Property.new(self, 'style', val)
|
83
68
|
else
|
84
69
|
values << val
|
85
70
|
end
|
86
71
|
|
87
72
|
val = values.shift
|
88
73
|
if val =~ /(inherit|small-caps)/
|
89
|
-
@properties['variant'] = Property.new(
|
74
|
+
@properties['variant'] = Property.new(self, 'variant', val)
|
90
75
|
else
|
91
76
|
values << val
|
92
77
|
end
|
93
78
|
|
94
79
|
val = values.shift
|
95
|
-
@properties['weight'] = Property.new(
|
80
|
+
@properties['weight'] = Property.new(self, 'weight', val) if val
|
96
81
|
end
|
97
82
|
end
|
98
83
|
end
|
@@ -5,16 +5,17 @@ module CSS
|
|
5
5
|
super
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def get(property_name)
|
9
|
+
@properties[property_name]
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
12
|
+
def name
|
13
|
+
'list-style'
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_style
|
17
|
-
[
|
17
|
+
value = %w(type position image).map { |prop| @properties[prop].try(:value) }.join(' ')
|
18
|
+
[name, value].join(':')
|
18
19
|
end
|
19
20
|
|
20
21
|
def type
|
@@ -22,19 +23,21 @@ module CSS
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def type=(val)
|
25
|
-
@properties['type'] = val
|
26
|
+
@properties['type'] = Property.new(self, 'type', val)
|
26
27
|
end
|
27
28
|
|
28
29
|
private
|
29
|
-
def init(name, value)
|
30
|
+
def init(parent, name, value)
|
31
|
+
@parent = parent
|
32
|
+
@properties['image'] = Property.new(self, 'image', 'none')
|
30
33
|
expand_property value if value
|
31
34
|
end
|
32
35
|
|
33
36
|
def default_properties
|
34
37
|
@@default_properties ||= {
|
35
|
-
'type' => Property.new(
|
36
|
-
'position' => Property.new(
|
37
|
-
'image' => Property.new(
|
38
|
+
'type' => Property.new(self, 'type', 'disc'),
|
39
|
+
'position' => Property.new(self, 'position', 'outside'),
|
40
|
+
'image' => Property.new(self, 'image', 'none')
|
38
41
|
}
|
39
42
|
end
|
40
43
|
|
@@ -43,11 +46,11 @@ module CSS
|
|
43
46
|
while values.size > 0
|
44
47
|
val = values.shift
|
45
48
|
if val =~ /^url/
|
46
|
-
@properties['image'] = Property.new(
|
49
|
+
@properties['image'] = Property.new(self, 'image', val)
|
47
50
|
elsif val =~ /^(inside|outside)/
|
48
|
-
@properties['position'] = Property.new(
|
51
|
+
@properties['position'] = Property.new(self, 'position', val)
|
49
52
|
else
|
50
|
-
@properties['type'] = Property.new(
|
53
|
+
@properties['type'] = Property.new(self, 'type', val)
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
@@ -1,25 +1,28 @@
|
|
1
|
+
require 'css/helpers/orientation'
|
2
|
+
|
1
3
|
module CSS
|
2
4
|
class MarginProperty < Property
|
5
|
+
include Orientation
|
6
|
+
|
3
7
|
def name
|
4
8
|
'margin'
|
5
9
|
end
|
6
10
|
|
7
|
-
def
|
11
|
+
def ==(val)
|
12
|
+
if val.is_a?(Property)
|
13
|
+
super
|
14
|
+
else
|
15
|
+
value == val
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def value
|
8
20
|
top = @properties['top']
|
9
21
|
right = @properties['right']
|
10
22
|
bottom = @properties['bottom']
|
11
23
|
left = @properties['left']
|
12
|
-
|
13
24
|
if top && right && bottom && left
|
14
|
-
|
15
|
-
top
|
16
|
-
elsif [top, bottom] == Array.new(2) { top } && [left, right] == Array.new(2) { left }
|
17
|
-
[top, left].join(' ')
|
18
|
-
elsif [top, bottom] != Array.new(2) { top } && [left, right] == Array.new(2) { left }
|
19
|
-
[top, left, bottom].join(' ')
|
20
|
-
else
|
21
|
-
[top, right, bottom, left].join(' ')
|
22
|
-
end
|
25
|
+
compact_orientation(top, right, bottom, left)
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -30,26 +33,19 @@ module CSS
|
|
30
33
|
left = @properties['left']
|
31
34
|
|
32
35
|
if top && right && bottom && left
|
33
|
-
value =
|
34
|
-
top
|
35
|
-
elsif [top, bottom] == Array.new(2) { top } && [left, right] == Array.new(2) { left }
|
36
|
-
[top, left].join(' ')
|
37
|
-
elsif [top, bottom] != Array.new(2) { top } && [left, right] == Array.new(2) { left }
|
38
|
-
[top, left, bottom].join(' ')
|
39
|
-
else
|
40
|
-
[top, right, bottom, left].join(' ')
|
41
|
-
end
|
36
|
+
value = compact_orientation(top, right, bottom, left)
|
42
37
|
[name, value].join(':')
|
43
38
|
else
|
44
|
-
default_properties.keys.map { |prop| @properties[prop] ? ["#{name}-#{prop}", @properties[prop]].join(':') : nil }.compact.join(';')
|
39
|
+
default_properties.keys.map { |prop| @properties[prop] ? ["#{name}-#{prop}", @properties[prop].value].join(':') : nil }.compact.join(';')
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
48
43
|
private
|
49
|
-
def init(name, value)
|
44
|
+
def init(parent, name, value)
|
45
|
+
@parent = parent
|
50
46
|
if name =~ /-/
|
51
47
|
property_name = name.sub(/[^-]+-(.*)/, '\1')
|
52
|
-
@properties[property_name] = Property.new(
|
48
|
+
@properties[property_name] = Property.new(self, property_name, value)
|
53
49
|
else
|
54
50
|
expand_property value if value
|
55
51
|
end
|
@@ -90,10 +86,10 @@ module CSS
|
|
90
86
|
left = values[3]
|
91
87
|
end
|
92
88
|
|
93
|
-
@properties['top'] = Property.new(
|
94
|
-
@properties['right'] = Property.new(
|
95
|
-
@properties['bottom'] = Property.new(
|
96
|
-
@properties['left'] = Property.new(
|
89
|
+
@properties['top'] = Property.new(self, 'top', top)
|
90
|
+
@properties['right'] = Property.new(self, 'right', right)
|
91
|
+
@properties['bottom'] = Property.new(self, 'bottom', bottom)
|
92
|
+
@properties['left'] = Property.new(self, 'left', left)
|
97
93
|
end
|
98
94
|
end
|
99
95
|
end
|
data/lib/css/property.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
|
+
require 'css/helpers/normalize'
|
2
|
+
|
1
3
|
module CSS
|
2
4
|
class Property
|
3
5
|
include Normalize
|
4
6
|
|
5
|
-
attr_reader :
|
7
|
+
attr_reader :value
|
6
8
|
|
7
9
|
def initialize(*args)
|
8
|
-
raise "Please use Property.create instead of Property.new" unless args[0] == :p
|
9
|
-
@properties
|
10
|
-
|
10
|
+
raise "Please use Property.create instead of Property.new" unless args[0] == :p || args[0].is_a?(Property)
|
11
|
+
@properties = {}
|
12
|
+
name = args[1]
|
13
|
+
value = clean_value(args[2])
|
14
|
+
init(args[0].is_a?(Property) ? args[0] : nil, name, value)
|
11
15
|
end
|
12
16
|
|
13
17
|
def self.create(name, value = nil)
|
14
|
-
klass = case name
|
18
|
+
klass = case name.to_s
|
15
19
|
when /^background/
|
16
20
|
BackgroundProperty
|
17
21
|
when /^(font|line-height)/
|
@@ -37,30 +41,46 @@ module CSS
|
|
37
41
|
@properties.keys.include?(normalize_property_name(property_name))
|
38
42
|
end
|
39
43
|
|
40
|
-
def
|
41
|
-
@
|
44
|
+
def name
|
45
|
+
[@parent.try(:name), @name].compact.join('-')
|
46
|
+
end
|
47
|
+
|
48
|
+
def value=(val)
|
49
|
+
if @properties.size > 0
|
50
|
+
expand_property val
|
51
|
+
else
|
52
|
+
@value = val
|
53
|
+
end
|
42
54
|
end
|
43
55
|
|
44
|
-
def
|
45
|
-
|
56
|
+
def to_s
|
57
|
+
@value || to_style
|
46
58
|
end
|
47
59
|
|
48
60
|
def inspect
|
49
|
-
|
61
|
+
"#<Property #{to_style}>"
|
50
62
|
end
|
51
63
|
|
52
64
|
def to_style
|
53
|
-
[
|
65
|
+
[name, @value].join(':')
|
54
66
|
end
|
55
67
|
|
56
68
|
def ==(val)
|
57
69
|
if val.is_a?(Property)
|
58
|
-
@value == val.value
|
70
|
+
@value == val.instance_variable_get(:@value) && @properties == val.instance_variable_get(:@properties)
|
59
71
|
else
|
60
72
|
@value == val
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
76
|
+
def eql?(property)
|
77
|
+
property.is_a?(Property) && self == property
|
78
|
+
end
|
79
|
+
|
80
|
+
def hash
|
81
|
+
to_style.hash
|
82
|
+
end
|
83
|
+
|
64
84
|
def <<(val)
|
65
85
|
@value = val
|
66
86
|
end
|
@@ -97,8 +117,18 @@ module CSS
|
|
97
117
|
end
|
98
118
|
end
|
99
119
|
|
120
|
+
def respond_to?(method_name, include_private = false)
|
121
|
+
property_name = normalize_property_name(method_name.to_s[-1..-1] == '=' ? method_name.to_s.chop : method_name)
|
122
|
+
default_properties.keys.include?(property_name) || super
|
123
|
+
end
|
124
|
+
|
125
|
+
def empty?
|
126
|
+
@value.nil? && @properties.all? { |p| p.empty? }
|
127
|
+
end
|
128
|
+
|
100
129
|
private
|
101
|
-
def init(name, value)
|
130
|
+
def init(parent, name, value)
|
131
|
+
@parent = parent
|
102
132
|
@name = name
|
103
133
|
@value = value
|
104
134
|
end
|
@@ -106,13 +136,24 @@ module CSS
|
|
106
136
|
def default_properties
|
107
137
|
{}
|
108
138
|
end
|
139
|
+
|
140
|
+
def clean_value(value)
|
141
|
+
return if value.nil?
|
142
|
+
|
143
|
+
value = value.
|
144
|
+
to_s.
|
145
|
+
strip.
|
146
|
+
gsub(/rgba?\([^)]+\)/) { |match| match.delete(' ') }
|
147
|
+
end
|
109
148
|
end
|
110
149
|
end
|
111
150
|
|
151
|
+
require "css/properties/margin_property.rb"
|
112
152
|
require "css/properties/background_property.rb"
|
113
153
|
require "css/properties/font_property.rb"
|
114
154
|
require "css/properties/border_property.rb"
|
155
|
+
require "css/properties/border_orientation_property.rb"
|
156
|
+
require "css/properties/border_unit_property.rb"
|
115
157
|
require "css/properties/outline_property.rb"
|
116
|
-
require "css/properties/margin_property.rb"
|
117
158
|
require "css/properties/padding_property.rb"
|
118
159
|
require "css/properties/list_style_property.rb"
|
data/lib/css/rule.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Shorthand conversions based on guide by Dustin Diaz - http://www.dustindiaz.com/css-shorthand/
|
2
2
|
require 'set'
|
3
|
+
require 'css/helpers/normalize'
|
3
4
|
|
4
5
|
module CSS
|
5
6
|
class Rule
|
@@ -28,13 +29,49 @@ module CSS
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def get(property_name)
|
31
|
-
|
32
|
+
property_name = normalize_property_name(property_name)
|
33
|
+
if property_name =~ /-/
|
34
|
+
property_name_parts = property_name.split('-')
|
35
|
+
pname = property_name_parts.shift
|
36
|
+
property = nil
|
37
|
+
while property_name_parts.size > 0
|
38
|
+
property = @rules[normalize_property_name(pname)]
|
39
|
+
break unless property.nil?
|
40
|
+
pname = [pname, property_name_parts.shift].join('-')
|
41
|
+
end
|
42
|
+
property = @rules[normalize_property_name(pname)] unless property
|
43
|
+
if property && property_name_parts.size == 0
|
44
|
+
property
|
45
|
+
else
|
46
|
+
while property_name_parts.size > 0
|
47
|
+
next_property_name = property_name_parts.shift
|
48
|
+
property = property[next_property_name] if property
|
49
|
+
end
|
50
|
+
property
|
51
|
+
end
|
52
|
+
else
|
53
|
+
@rules[normalize_property_name(property_name)]
|
54
|
+
end
|
32
55
|
end
|
33
56
|
|
34
57
|
def [](property_name)
|
35
58
|
get property_name
|
36
59
|
end
|
37
60
|
|
61
|
+
def []=(property_name, value)
|
62
|
+
property = get(property_name)
|
63
|
+
unless property
|
64
|
+
property = Property.create(property_name, value)
|
65
|
+
if @rules[property.name]
|
66
|
+
@rules[property.name] << property
|
67
|
+
else
|
68
|
+
@properties << property.name
|
69
|
+
@rules[property.name] = property
|
70
|
+
end
|
71
|
+
end
|
72
|
+
property.value = value
|
73
|
+
end
|
74
|
+
|
38
75
|
def to_s
|
39
76
|
properties.map { |prop| get(prop).to_style }.join ';'
|
40
77
|
end
|
@@ -48,43 +85,22 @@ module CSS
|
|
48
85
|
end
|
49
86
|
|
50
87
|
def has_property?(property_name)
|
51
|
-
|
52
|
-
if property_name =~ /-/
|
53
|
-
property_name_parts = property_name.split('-')
|
54
|
-
pname = property_name_parts.shift
|
55
|
-
property = nil
|
56
|
-
while property_name_parts.size > 0
|
57
|
-
property = get(pname)
|
58
|
-
break unless property.nil?
|
59
|
-
pname = [pname, property_name_parts.shift].join('-')
|
60
|
-
end
|
61
|
-
property.has_property?(property_name_parts.shift)
|
62
|
-
else
|
63
|
-
properties.include?(property_name)
|
64
|
-
end
|
88
|
+
!get(property_name).empty?
|
65
89
|
end
|
66
90
|
|
67
91
|
def method_missing(method_name, *args)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
pname = property_name_parts.shift
|
72
|
-
property = nil
|
73
|
-
while property_name_parts.size > 0
|
74
|
-
property = get(pname)
|
75
|
-
break unless property.nil?
|
76
|
-
pname = [pname, property_name_parts.shift].join('-')
|
77
|
-
end
|
78
|
-
property[property_name_parts.shift]
|
92
|
+
if method_name.to_s[-1..-1] == '='
|
93
|
+
property_name = method_name.to_s.chop
|
94
|
+
self[property_name] = args[0]
|
79
95
|
else
|
80
|
-
get(
|
96
|
+
get(method_name) || super
|
81
97
|
end
|
82
98
|
end
|
83
99
|
|
84
100
|
private
|
85
101
|
def parse_rules(properties, rules, rule_text)
|
86
102
|
rule_text.split(/;/).inject([properties, rules]) do |properties, rule|
|
87
|
-
property = rule.split(/:/)
|
103
|
+
property = rule.split(/:/)
|
88
104
|
name = normalize_property_name(property[0])
|
89
105
|
value = property[1]
|
90
106
|
|
data/lib/css/rule_set.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
1
|
module CSS
|
4
2
|
class RuleSet
|
5
3
|
def initialize
|
6
|
-
@selectors =
|
4
|
+
@selectors = []
|
7
5
|
@rules = {}
|
8
6
|
end
|
9
7
|
|
@@ -25,15 +23,11 @@ module CSS
|
|
25
23
|
end
|
26
24
|
|
27
25
|
def rules
|
28
|
-
selectors.map { |
|
26
|
+
selectors.map { |s| @rules[s] }
|
29
27
|
end
|
30
28
|
|
31
29
|
def to_style
|
32
|
-
rules
|
33
|
-
selectors.each do |selector|
|
34
|
-
rules << @rules[selector].to_style
|
35
|
-
end
|
36
|
-
rules.join("\n")
|
30
|
+
rules.map { |rule| rule.to_style }.join("\n")
|
37
31
|
end
|
38
32
|
end
|
39
33
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
unless Object.methods.include?('try')
|
2
|
+
class Object
|
3
|
+
def try(method_name, *args)
|
4
|
+
send(method_name, *args) if respond_to?(method_name, true)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
unless NilClass.methods.include?('empty?')
|
10
|
+
class NilClass
|
11
|
+
def empty?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: css
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andrew Timberlake
|
@@ -46,10 +46,13 @@ files:
|
|
46
46
|
- LICENSE
|
47
47
|
- lib/css/colors.rb
|
48
48
|
- lib/css/errors.rb
|
49
|
-
- lib/css/normalize.rb
|
49
|
+
- lib/css/helpers/normalize.rb
|
50
|
+
- lib/css/helpers/orientation.rb
|
50
51
|
- lib/css/parser.rb
|
51
52
|
- lib/css/properties/background_property.rb
|
53
|
+
- lib/css/properties/border_orientation_property.rb
|
52
54
|
- lib/css/properties/border_property.rb
|
55
|
+
- lib/css/properties/border_unit_property.rb
|
53
56
|
- lib/css/properties/font_property.rb
|
54
57
|
- lib/css/properties/list_style_property.rb
|
55
58
|
- lib/css/properties/margin_property.rb
|
@@ -59,6 +62,7 @@ files:
|
|
59
62
|
- lib/css/rule.rb
|
60
63
|
- lib/css/rule_set.rb
|
61
64
|
- lib/css.rb
|
65
|
+
- lib/monkey_patches.rb
|
62
66
|
- lib/numbers.rb
|
63
67
|
- README.rdoc
|
64
68
|
has_rdoc: true
|
data/lib/css/normalize.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
module CSS
|
2
|
-
module Normalize
|
3
|
-
def normalize_property_name(name)
|
4
|
-
if name.to_s =~ /[A-Z]/
|
5
|
-
name.to_s.gsub(/([A-Z])/) do |match|
|
6
|
-
"-#{match.downcase}"
|
7
|
-
end
|
8
|
-
elsif name.to_s =~ /_/
|
9
|
-
name.to_s.gsub(/_/, '-')
|
10
|
-
else
|
11
|
-
name.to_s
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|