ionfish-stylish 0.1.2 → 0.1.3
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/History.txt +32 -0
- data/README.md +2 -5
- data/Rakefile +16 -5
- data/VERSION.yml +1 -1
- data/lib/stylish/background.rb +226 -0
- data/lib/stylish/color.rb +14 -20
- data/lib/stylish/core.rb +24 -159
- data/lib/stylish/generate.rb +62 -3
- data/lib/stylish/stylesheet.rb +2 -2
- data/lib/stylish/tree.rb +2 -2
- data/lib/stylish.rb +15 -9
- data/test/background_test.rb +36 -3
- data/test/color_test.rb +8 -13
- data/test/comment_test.rb +0 -3
- data/test/declaration_test.rb +0 -3
- data/test/declarations_test.rb +1 -4
- data/test/formattable_test.rb +0 -3
- data/test/generate_test.rb +0 -3
- data/test/image_test.rb +0 -3
- data/test/rule_test.rb +0 -3
- data/test/selector_test.rb +1 -4
- data/test/selectors_test.rb +0 -3
- data/test/stylesheet_test.rb +0 -3
- data/test/tree_test.rb +0 -3
- data/test/variable_test.rb +46 -0
- metadata +6 -2
data/History.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
=== Version 0.1.3 (TODO)
|
2
|
+
|
3
|
+
Variables in the DSL
|
4
|
+
* Selector and property variables
|
5
|
+
* New descope example
|
6
|
+
* Limited CSS3 background support
|
7
|
+
* Cleaned up various things
|
8
|
+
|
9
|
+
|
10
|
+
=== Version 0.1.2 (2009-04-12)
|
11
|
+
|
12
|
+
Documentation release
|
13
|
+
* Documented the stylesheet generation DSL
|
14
|
+
* Updated example code in the README
|
15
|
+
* Added an Image class to handle background images
|
16
|
+
|
17
|
+
|
18
|
+
=== Version 0.1.1 (2009-04-12)
|
19
|
+
|
20
|
+
More DSL features
|
21
|
+
* Added the ability to append comments through the stylesheet generation DSL
|
22
|
+
* Fixed some parsing and selector serialisation problems
|
23
|
+
* Updated the main example file to work with the new DSL
|
24
|
+
* Completed the documentation of the core classes
|
25
|
+
|
26
|
+
|
27
|
+
=== Version 0.1.0 (2009-04-10)
|
28
|
+
|
29
|
+
First major release
|
30
|
+
* New selector scope tree, which serialises to a valid stylesheet
|
31
|
+
* Stylesheet generation DSL based on the tree datastructure
|
32
|
+
* HSL(A) colour space support, complementing the existing RGB support
|
data/README.md
CHANGED
@@ -23,6 +23,8 @@ Calling the stylesheet's `to_s` method would produce the following
|
|
23
23
|
.content h2 {font-size:2em;}
|
24
24
|
.content p {margin:0 0 1em 0;}
|
25
25
|
|
26
|
+
A number of additional examples are available in the example/ directory.
|
27
|
+
|
26
28
|
|
27
29
|
Compatibility
|
28
30
|
-------------
|
@@ -36,11 +38,6 @@ Future considerations
|
|
36
38
|
|
37
39
|
* Add a Border class to complement Background.
|
38
40
|
* Add better support for CSS3 properties to Background.
|
39
|
-
* Add a native mapping construct to allow symbol lookup for alternate
|
40
|
-
stylesheets.
|
41
|
-
* Change stylesheet generation to a two-step process where the tree structure
|
42
|
-
is generated in the first step and symbols (for example, those employed by
|
43
|
-
a mapping construct) are evaluated the second.
|
44
41
|
* Fundamental objects like percentages need their own classes rather than
|
45
42
|
being dealt with in an ad-hoc manner by higher-level objects.
|
46
43
|
* Add a parser so CSS can be read as well as written.
|
data/Rakefile
CHANGED
@@ -11,14 +11,16 @@ begin
|
|
11
11
|
s.authors = ["Benedict Eastaugh"]
|
12
12
|
end
|
13
13
|
rescue LoadError
|
14
|
-
puts "Jeweler not available. Install it with: sudo gem install "
|
15
|
-
|
14
|
+
puts "Jeweler not available. Install it with: sudo gem install " +
|
15
|
+
"technicalpickles-jeweler -s http://gems.github.com"
|
16
16
|
end
|
17
17
|
|
18
18
|
task :default => :test
|
19
19
|
|
20
20
|
desc "Run the Stylish test suite"
|
21
21
|
task :test do
|
22
|
+
require 'test/unit'
|
23
|
+
|
22
24
|
testdir = "test"
|
23
25
|
Dir.foreach(testdir) do |f|
|
24
26
|
path = "#{testdir}/#{f}"
|
@@ -28,7 +30,16 @@ task :test do
|
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
namespace :example do
|
34
|
+
|
35
|
+
desc "An extended generator DSL example."
|
36
|
+
task :tarski do
|
37
|
+
require 'example/tarski'
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Extract base rules from a selector tree."
|
41
|
+
task :descope do
|
42
|
+
require 'example/descope'
|
43
|
+
end
|
34
44
|
end
|
45
|
+
|
data/VERSION.yml
CHANGED
@@ -0,0 +1,226 @@
|
|
1
|
+
module Stylish
|
2
|
+
|
3
|
+
# The Background class is a specialised kind of Declaration, geared towards
|
4
|
+
# dealing with the oddities of the background family of declarations, which
|
5
|
+
# can exist in both long- and shorthand forms.
|
6
|
+
#
|
7
|
+
# For example, these longhand background declarations
|
8
|
+
#
|
9
|
+
# background-color: #999;
|
10
|
+
# background-image: url('bg.png');
|
11
|
+
# background-repeat: repeat-x;
|
12
|
+
#
|
13
|
+
# could be compressed into a single shorthand declaration
|
14
|
+
#
|
15
|
+
# background: #999 url('bg.png') repeat-x;
|
16
|
+
#
|
17
|
+
# The Background class allows for easy conversion between these forms. It
|
18
|
+
# defaults to the longhand versions, allowing rules with stronger selector
|
19
|
+
# weighting to only override specific parts of other rules' background
|
20
|
+
# declarations.
|
21
|
+
class Background < Declaration
|
22
|
+
attr_reader :color,
|
23
|
+
:image,
|
24
|
+
:repeat,
|
25
|
+
:position,
|
26
|
+
:attachment,
|
27
|
+
:origin,
|
28
|
+
:break,
|
29
|
+
:compressed
|
30
|
+
|
31
|
+
PROPERTIES = [
|
32
|
+
[:color, "background-color"],
|
33
|
+
[:image, "background-image"],
|
34
|
+
[:repeat, "background-repeat"],
|
35
|
+
[:position, "background-position"],
|
36
|
+
[:attachment, "background-attachment"],
|
37
|
+
[:origin, "background-origin"],
|
38
|
+
[:break, "background-break"],
|
39
|
+
[:compressed]]
|
40
|
+
|
41
|
+
REPEAT_VALUES = ["repeat-x", "repeat-y", "repeat",
|
42
|
+
"space", "round", "no-repeat"]
|
43
|
+
ATTACHMENT_VALUES = ["scroll", "fixed", "local"]
|
44
|
+
HORIZONTAL_POSITIONS = ["left", "center", "right"]
|
45
|
+
VERTICAL_POSITIONS = ["top", "center", "bottom"]
|
46
|
+
ORIGIN_VALUES = ["border-box", "padding-box", "content-box"]
|
47
|
+
BREAK_VALUES = ["bounding-box", "each-box", "continuous"]
|
48
|
+
|
49
|
+
# Create a new Background object with the specified properties.
|
50
|
+
def initialize(options)
|
51
|
+
accept_format(/^\s*%s\s*:\s*%s;\s*$/m, "%s:%s;")
|
52
|
+
self.value = options
|
53
|
+
end
|
54
|
+
|
55
|
+
# Input validation for colours is handled by the Color class, which will
|
56
|
+
# raise an ArgumentError if the argument is an invalid colour value.
|
57
|
+
def color=(val)
|
58
|
+
@color = Color.new(val)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Set the background image(s). As of CSS3, elements may have multiple
|
62
|
+
# background images, so this method attempts to provide a backwards-
|
63
|
+
# compatible solution.
|
64
|
+
#
|
65
|
+
# background = Background.new :image => "sky.png", :compressed => true
|
66
|
+
# background.to_s # => "background:url('sky.png');"
|
67
|
+
#
|
68
|
+
# background.image = ["ball.png", "grass.png"]
|
69
|
+
# background.to_s # => "background:url('ball.png'), url('grass.png');"
|
70
|
+
#
|
71
|
+
def image=(paths)
|
72
|
+
paths = [paths] if paths.is_a?(String)
|
73
|
+
@image = paths.inject([]) {|images, path| images << Image.new(path) }
|
74
|
+
|
75
|
+
if @image.length < 2
|
76
|
+
@image = @image.first
|
77
|
+
else
|
78
|
+
def @image.to_s
|
79
|
+
join(", ")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Set the background repeat(s). As of CSS3, the background-repeat property
|
85
|
+
# may have multiple values, so this method provides a backwards-compatible
|
86
|
+
# solution.
|
87
|
+
#
|
88
|
+
# repeating = Background.new :repeat => ["repeat-x", "repeat-y"]
|
89
|
+
# repeating.to_s # => "background-repeat:repeat-x, repeat-y;"
|
90
|
+
#
|
91
|
+
def repeat=(repeats)
|
92
|
+
repeats = [repeats] if repeats.is_a? String
|
93
|
+
@repeat = repeats.find_all {|r| REPEAT_VALUES.include? r }
|
94
|
+
|
95
|
+
if @repeat.length < 2
|
96
|
+
@repeat = @repeat.first
|
97
|
+
else
|
98
|
+
def @repeat.to_s
|
99
|
+
join(", ")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Only position keywords are currently handled, not percentages or lengths.
|
105
|
+
def position=(val)
|
106
|
+
xpos, ypos = val.split(/\s+/) << "center"
|
107
|
+
if HORIZONTAL_POSITIONS.include?(xpos) && VERTICAL_POSITIONS.include?(ypos)
|
108
|
+
@position = [xpos, ypos]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# The background-attachment property takes a limited range of values, so
|
113
|
+
# only a value within that range will be accepted.
|
114
|
+
def attachment=(attachments)
|
115
|
+
attachments = [attachments] if attachments.is_a? String
|
116
|
+
@attachment = attachments.find_all {|a| ATTACHMENT_VALUES.include? a }
|
117
|
+
|
118
|
+
if @attachment.length < 2
|
119
|
+
@attachment = @attachment.first
|
120
|
+
else
|
121
|
+
def @attachment.to_s
|
122
|
+
join(", ")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# The background-origin property specifies the background positioning area.
|
128
|
+
# It is a CSS3 property which takes multiple values.
|
129
|
+
#
|
130
|
+
# original = Background.new :origin => ["padding-box", "content-box"]
|
131
|
+
# original.to_s # => background-origin:padding-box, content-box;
|
132
|
+
#
|
133
|
+
def origin=(origins)
|
134
|
+
origins = [origins] if origins.is_a? String
|
135
|
+
@origin = origins.find_all {|o| ORIGIN_VALUES.include? o }
|
136
|
+
|
137
|
+
if @origin.length < 2
|
138
|
+
@origin = @origin.first
|
139
|
+
else
|
140
|
+
def @origin.to_s
|
141
|
+
join(", ")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# The background-break property, defined in CSS3, specifies how the
|
147
|
+
# background positioning area is derived when an element is broken into
|
148
|
+
# multiple boxes.
|
149
|
+
#
|
150
|
+
# broken = Background.new :break => "bounding-box"
|
151
|
+
# broken.to_s # => "background-break:bounding-box;"
|
152
|
+
#
|
153
|
+
def break=(value)
|
154
|
+
@break = value if BREAK_VALUES.include? value
|
155
|
+
end
|
156
|
+
|
157
|
+
# Set this to true to generate a shorthand declaration, e.g.
|
158
|
+
#
|
159
|
+
# background:#ccc url('bg.png') no-repeat 0 0;
|
160
|
+
#
|
161
|
+
# As opposed to the longhand version:
|
162
|
+
#
|
163
|
+
# background-color:#ccc; background-image:url('bg.png');
|
164
|
+
# background-repeat:no-repeat; background-position:0 0;
|
165
|
+
#
|
166
|
+
def compressed=(val)
|
167
|
+
@compressed = val == true || nil
|
168
|
+
end
|
169
|
+
|
170
|
+
# Override Declaration#name, since it's not compatible with the
|
171
|
+
# internals of this class.
|
172
|
+
def name
|
173
|
+
PROPERTIES.reject {|n, p| p.nil? }.map {|n, p|
|
174
|
+
value = self.send(n)
|
175
|
+
p.to_s unless value.nil?
|
176
|
+
}.compact
|
177
|
+
end
|
178
|
+
|
179
|
+
# Override Declaration#name=, since it's not compatible with the
|
180
|
+
# internals of this class.
|
181
|
+
def name=(val)
|
182
|
+
raise NoMethodError, "name= is not defined for Background."
|
183
|
+
end
|
184
|
+
|
185
|
+
# Override Declaration#value, since it's not compatible with the internals
|
186
|
+
# of this class.
|
187
|
+
def value(name_and_value = false)
|
188
|
+
PROPERTIES.reject {|n, p| p.nil? }.map {|n, p|
|
189
|
+
value = self.send(n)
|
190
|
+
next if value.nil?
|
191
|
+
name_and_value ? [p.to_s, value] : value
|
192
|
+
}.compact
|
193
|
+
end
|
194
|
+
|
195
|
+
# Override Declaration#value=, since it's not compatible with the internals
|
196
|
+
# of this class.
|
197
|
+
def value=(options)
|
198
|
+
unless options.is_a? Hash
|
199
|
+
raise ArgumentError, "Argument must be a hash of background properties"
|
200
|
+
end
|
201
|
+
|
202
|
+
PROPERTIES.each do |name, property|
|
203
|
+
self.send(:"#{name.to_s}=", options[name]) if options[name]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Generate a string representation of a Background instance.
|
208
|
+
#
|
209
|
+
# There are two kinds of representation, each of which have slightly
|
210
|
+
# different CSS semantics. If compressed is set to true, this method will
|
211
|
+
# produce a shorthand CSS declaration such as the following:
|
212
|
+
#
|
213
|
+
# background: #fff url('bg.png') no-repeat 50% 0;
|
214
|
+
#
|
215
|
+
# Otherwise it will produce an unordered list of individual background
|
216
|
+
# declarations.
|
217
|
+
def to_s(symbols = {})
|
218
|
+
if @compressed
|
219
|
+
"background:#{self.value(true).map {|p, v| v }.compact.join(" ")};"
|
220
|
+
else
|
221
|
+
self.value(true).map {|p, v| sprintf(@format, p, v.to_s) }.join(" ")
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
data/lib/stylish/color.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'mathn'
|
2
|
-
require 'rational'
|
3
|
-
|
4
1
|
module Stylish #:nodoc:
|
5
2
|
|
6
3
|
# The Color class is intended to eventually implement the entirety of the
|
@@ -214,7 +211,7 @@ module Stylish #:nodoc:
|
|
214
211
|
[:red, :green, :blue].each do |color|
|
215
212
|
reader = color
|
216
213
|
writer = :"#{color}="
|
217
|
-
color
|
214
|
+
color = :"@#{color.to_s}"
|
218
215
|
|
219
216
|
unless self.respond_to?(reader)
|
220
217
|
self.send(:define_method, reader) do
|
@@ -246,11 +243,11 @@ module Stylish #:nodoc:
|
|
246
243
|
# Attribute writer for the color's value. Uses the ColorStringParser inner
|
247
244
|
# class to parse string values, and contains other logic to handle arrays.
|
248
245
|
def value=(value)
|
249
|
-
if value.is_a?(String)
|
246
|
+
if value.is_a?(String)
|
250
247
|
parser = ColorStringParser.new
|
251
248
|
@type, @red, @green, @blue, @opacity = parser.parse(value)
|
252
249
|
return unless @type.nil?
|
253
|
-
|
250
|
+
else
|
254
251
|
rgb = value[0..2].inject([]) do |rgb, v|
|
255
252
|
if v.is_a?(Integer) || v.is_a?(Float)
|
256
253
|
rgb << v
|
@@ -263,14 +260,12 @@ module Stylish #:nodoc:
|
|
263
260
|
rgb
|
264
261
|
end
|
265
262
|
|
266
|
-
if
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
@type = :rgba and return
|
273
|
-
end
|
263
|
+
if value.length < 4
|
264
|
+
@red, @green, @blue, @opacity = rgb << nil
|
265
|
+
@type = :rgb and return
|
266
|
+
else
|
267
|
+
@red, @green, @blue, @opacity = rgb << value[3].to_f
|
268
|
+
@type = :rgba and return
|
274
269
|
end
|
275
270
|
end
|
276
271
|
|
@@ -289,10 +284,7 @@ module Stylish #:nodoc:
|
|
289
284
|
# color.opacity # => 0.5
|
290
285
|
#
|
291
286
|
def opacity=(value)
|
292
|
-
|
293
|
-
return if value < 0 || value > 1
|
294
|
-
|
295
|
-
@opacity = value
|
287
|
+
@opacity = value unless value < 0 || value > 1
|
296
288
|
end
|
297
289
|
|
298
290
|
# Returns a color keyword string if the RGB value of the color is equal to
|
@@ -381,7 +373,7 @@ module Stylish #:nodoc:
|
|
381
373
|
# color.type = :rgb
|
382
374
|
# color.to_s # => "rgb(0, 0, 0)"
|
383
375
|
#
|
384
|
-
def to_s
|
376
|
+
def to_s(symbols = {})
|
385
377
|
return "inherit" if @type == :inherit
|
386
378
|
|
387
379
|
self.send(:"to_#{self.type.to_s}")
|
@@ -415,7 +407,9 @@ module Stylish #:nodoc:
|
|
415
407
|
huer.call(red - green, 240)
|
416
408
|
end
|
417
409
|
|
418
|
-
[hue].concat([saturation, lightness].map {|r|
|
410
|
+
[hue].concat([saturation, lightness].map {|r|
|
411
|
+
(r * 100).to_f.round.to_s + "%"
|
412
|
+
})
|
419
413
|
end
|
420
414
|
|
421
415
|
def hsla
|
data/lib/stylish/core.rb
CHANGED
@@ -73,8 +73,9 @@ module Stylish
|
|
73
73
|
end
|
74
74
|
|
75
75
|
# Serialise the rule to valid CSS code.
|
76
|
-
def to_s(scope = "")
|
77
|
-
sprintf(@format, selectors.join(scope),
|
76
|
+
def to_s(symbols = {}, scope = "")
|
77
|
+
sprintf(@format, selectors.join(symbols, scope),
|
78
|
+
@declarations.to_s(symbols))
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
@@ -150,7 +151,7 @@ module Stylish
|
|
150
151
|
# the serialisation API of those trees, and thus the #to_s method has a
|
151
152
|
# scope argument, which is in practice discarded when the serialisation of
|
152
153
|
# the comment occurs.
|
153
|
-
def to_s(scope = "")
|
154
|
+
def to_s(symbols = {}, scope = "")
|
154
155
|
if @lines.empty? && @metadata.empty?
|
155
156
|
sprintf("/**\n * %s\n */", @header)
|
156
157
|
else
|
@@ -178,8 +179,8 @@ module Stylish
|
|
178
179
|
|
179
180
|
# Selectors are immutable once created; the value of a given Selector must
|
180
181
|
# be set when the object is created.
|
181
|
-
def initialize(
|
182
|
-
@selector =
|
182
|
+
def initialize(selector)
|
183
|
+
@selector = selector
|
183
184
|
end
|
184
185
|
|
185
186
|
# Each Rule possesses one or more Selectors. Rules are often placed in
|
@@ -190,8 +191,9 @@ module Stylish
|
|
190
191
|
#
|
191
192
|
# The Selector class is also used internally by the Tree::SelectorScope
|
192
193
|
# class, to store its scope value.
|
193
|
-
def to_s(scope = "")
|
194
|
-
(scope.empty? ? "" : scope + " ") +
|
194
|
+
def to_s(symbols = {}, scope = "")
|
195
|
+
(scope.empty? ? "" : scope + " ") +
|
196
|
+
(@selector.is_a?(String) ? @selector.to_s : @selector.to_s(symbols))
|
195
197
|
end
|
196
198
|
end
|
197
199
|
|
@@ -211,15 +213,15 @@ module Stylish
|
|
211
213
|
# The join method overrides the superclass' method in order to always use a
|
212
214
|
# specific separator, and so that the scope that the selectors are being
|
213
215
|
# used in can be passed through when Rules etc. are serialised.
|
214
|
-
def join(scope = "")
|
216
|
+
def join(symbols = {}, scope = "")
|
215
217
|
self.inject("") do |ss, s|
|
216
|
-
(ss.empty? ? "" : ss + self.format) + s.to_s(scope)
|
218
|
+
(ss.empty? ? "" : ss + self.format) + s.to_s(symbols, scope)
|
217
219
|
end
|
218
220
|
end
|
219
221
|
|
220
222
|
# The to_s method alternative way of calling the join method.
|
221
|
-
def to_s(scope = "")
|
222
|
-
self.join(scope)
|
223
|
+
def to_s(symbols = {}, scope = "")
|
224
|
+
self.join(symbols, scope)
|
223
225
|
end
|
224
226
|
end
|
225
227
|
|
@@ -262,12 +264,17 @@ module Stylish
|
|
262
264
|
#
|
263
265
|
# Since the formatting can be adjusted via the #format= accessor, the exact
|
264
266
|
# spacing of the declaration can be controlled if desired.
|
265
|
-
def to_s
|
266
|
-
|
267
|
+
def to_s(symbols = {})
|
268
|
+
if @value.is_a?(Generate::Variable) || @value.is_a?(Color)
|
269
|
+
value = @value.to_s(symbols)
|
270
|
+
else
|
271
|
+
value = @value.to_s
|
272
|
+
end
|
273
|
+
|
274
|
+
sprintf(@format, @property_name.to_s, value)
|
267
275
|
end
|
268
276
|
end
|
269
277
|
|
270
|
-
|
271
278
|
# Declarations subclasses Array so that whenever #join is called, the
|
272
279
|
# instance's format attribute will be used as the join string, rather than
|
273
280
|
# the empty string.
|
@@ -292,151 +299,9 @@ module Stylish
|
|
292
299
|
# format attribute. Assuming that its contents are indeed Declaration
|
293
300
|
# objects, this will invoke their own #to_s method and generating correct
|
294
301
|
# CSS code.
|
295
|
-
def to_s
|
296
|
-
self.
|
297
|
-
|
298
|
-
end
|
299
|
-
|
300
|
-
# The Background class is a specialised kind of Declaration, geared towards
|
301
|
-
# dealing with the oddities of the background family of declarations, which
|
302
|
-
# can exist in both long- and shorthand forms.
|
303
|
-
#
|
304
|
-
# For example, these longhand background declarations
|
305
|
-
#
|
306
|
-
# background-color: #999;
|
307
|
-
# background-image: url('bg.png');
|
308
|
-
# background-repeat: repeat-x;
|
309
|
-
#
|
310
|
-
# could be compressed into a single shorthand declaration
|
311
|
-
#
|
312
|
-
# background: #999 url('bg.png') repeat-x;
|
313
|
-
#
|
314
|
-
# The Background class allows for easy conversion between these forms. It
|
315
|
-
# defaults to the longhand versions, allowing rules with stronger selector
|
316
|
-
# weighting to only override specific parts of other rules' background
|
317
|
-
# declarations.
|
318
|
-
class Background < Declaration
|
319
|
-
attr_reader :color,
|
320
|
-
:image,
|
321
|
-
:repeat,
|
322
|
-
:position,
|
323
|
-
:attachment,
|
324
|
-
:compressed
|
325
|
-
|
326
|
-
PROPERTIES = [
|
327
|
-
[:color, "background-color"],
|
328
|
-
[:image, "background-image"],
|
329
|
-
[:repeat, "background-repeat"],
|
330
|
-
[:position, "background-position"],
|
331
|
-
[:attachment, "background-attachment"],
|
332
|
-
[:compressed]]
|
333
|
-
|
334
|
-
REPEAT_VALUES = ["repeat", "repeat-x", "repeat-y", "no-repeat"]
|
335
|
-
ATTACHMENT_VALUES = ["scroll", "fixed", "inherit"]
|
336
|
-
HORIZONTAL_POSITIONS = ["left", "center", "right"]
|
337
|
-
VERTICAL_POSITIONS = ["top", "center", "bottom"]
|
338
|
-
|
339
|
-
# Create a new Background object with the specified properties.
|
340
|
-
def initialize(options)
|
341
|
-
accept_format(/^\s*%s\s*:\s*%s;\s*$/m, "%s:%s;")
|
342
|
-
self.value = options
|
343
|
-
end
|
344
|
-
|
345
|
-
# Input validation for colours is handled by the Color class, which will
|
346
|
-
# raise an ArgumentError if the argument is an invalid colour value.
|
347
|
-
def color=(val)
|
348
|
-
@color = Color.new(val)
|
349
|
-
end
|
350
|
-
|
351
|
-
# Set the background image.
|
352
|
-
def image=(path)
|
353
|
-
@image = Image.new(path) if path.is_a?(String)
|
354
|
-
end
|
355
|
-
|
356
|
-
# Set the background repeat.
|
357
|
-
def repeat=(val)
|
358
|
-
@repeat = val if REPEAT_VALUES.include?(val)
|
359
|
-
end
|
360
|
-
|
361
|
-
# Only position keywords are currently handled, not percentages or lengths.
|
362
|
-
def position=(val)
|
363
|
-
xpos, ypos = val.split(/\s+/) << "center"
|
364
|
-
if HORIZONTAL_POSITIONS.include?(xpos) && VERTICAL_POSITIONS.include?(ypos)
|
365
|
-
@position = [xpos, ypos]
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
# The background-attachment property takes a limited range of values, so
|
370
|
-
# only a value within that range will be accepted.
|
371
|
-
def attachment=(val)
|
372
|
-
@attachment = val if ATTACHMENT_VALUES.include?(val)
|
373
|
-
end
|
374
|
-
|
375
|
-
# Set this to true to generate a shorthand declaration, e.g.
|
376
|
-
#
|
377
|
-
# background:#ccc url('bg.png') no-repeat 0 0;
|
378
|
-
#
|
379
|
-
# As opposed to the longhand version:
|
380
|
-
#
|
381
|
-
# background-color:#ccc; background-image:url('bg.png');
|
382
|
-
# background-repeat:no-repeat; background-position:0 0;
|
383
|
-
#
|
384
|
-
def compressed=(val)
|
385
|
-
@compressed = val == true || nil
|
386
|
-
end
|
387
|
-
|
388
|
-
# Override Declaration#name, since it's not compatible with the
|
389
|
-
# internals of this class.
|
390
|
-
def name
|
391
|
-
PROPERTIES.reject {|n, p| p.nil? }.map {|n, p|
|
392
|
-
value = self.send(n)
|
393
|
-
p.to_s unless value.nil?
|
394
|
-
}.compact
|
395
|
-
end
|
396
|
-
|
397
|
-
# Override Declaration#name=, since it's not compatible with the
|
398
|
-
# internals of this class.
|
399
|
-
def name=(val)
|
400
|
-
raise NoMethodError, "name= is not defined for Background."
|
401
|
-
end
|
402
|
-
|
403
|
-
# Override Declaration#value, since it's not compatible with the internals
|
404
|
-
# of this class.
|
405
|
-
def value(name_and_value = false)
|
406
|
-
PROPERTIES.reject {|n, p| p.nil? }.map {|n, p|
|
407
|
-
value = self.send(n)
|
408
|
-
next if value.nil?
|
409
|
-
name_and_value ? [p.to_s, value] : value
|
410
|
-
}.compact
|
411
|
-
end
|
412
|
-
|
413
|
-
# Override Declaration#value=, since it's not compatible with the internals
|
414
|
-
# of this class.
|
415
|
-
def value=(options)
|
416
|
-
unless options.is_a? Hash
|
417
|
-
raise ArgumentError, "Argument must be a hash of background properties"
|
418
|
-
end
|
419
|
-
|
420
|
-
PROPERTIES.each do |name, property|
|
421
|
-
self.send(:"#{name.to_s}=", options[name]) if options[name]
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
# Generate a string representation of a Background instance.
|
426
|
-
#
|
427
|
-
# There are two kinds of representation, each of which have slightly
|
428
|
-
# different CSS semantics. If compressed is set to true, this method will
|
429
|
-
# produce a shorthand CSS declaration such as the following:
|
430
|
-
#
|
431
|
-
# background: #fff url('bg.png') no-repeat 50% 0;
|
432
|
-
#
|
433
|
-
# Otherwise it will produce an unordered list of individual background
|
434
|
-
# declarations.
|
435
|
-
def to_s
|
436
|
-
if @compressed
|
437
|
-
"background:#{self.value(true).map {|p, v| v }.compact.join(" ")};"
|
438
|
-
else
|
439
|
-
self.value(true).map {|p, v| sprintf(@format, p, v.to_s) }.join(" ")
|
302
|
+
def to_s(symbols = {})
|
303
|
+
self.inject("") do |a, o|
|
304
|
+
a << (a.empty? ? "" : @format) << o.to_s(symbols)
|
440
305
|
end
|
441
306
|
end
|
442
307
|
end
|
data/lib/stylish/generate.rb
CHANGED
@@ -55,10 +55,21 @@ module Stylish
|
|
55
55
|
key = key.to_s.sub("_", "-").to_sym
|
56
56
|
|
57
57
|
if key == :background
|
58
|
-
|
58
|
+
if value.any? {|k,v| v.is_a? Symbol }
|
59
|
+
declaration = Variable.new(value, Background)
|
60
|
+
else
|
61
|
+
declaration = Background.new(value)
|
62
|
+
end
|
59
63
|
elsif key == :color
|
60
|
-
|
64
|
+
if value.is_a? Symbol
|
65
|
+
value = Variable.new(value, Color)
|
66
|
+
else
|
67
|
+
value = Color.new(value)
|
68
|
+
end
|
69
|
+
|
70
|
+
declaration = Declaration.new("color", value)
|
61
71
|
else
|
72
|
+
value = Variable.new(value) if value.is_a? Symbol
|
62
73
|
declaration = Declaration.new(key, value)
|
63
74
|
end
|
64
75
|
|
@@ -66,6 +77,52 @@ module Stylish
|
|
66
77
|
end
|
67
78
|
end
|
68
79
|
|
80
|
+
# Variables are elements of a selector tree that haven't been assigned
|
81
|
+
# values yet. When a tree that includes Variable objects is serialised, it
|
82
|
+
# must be passed a symbol table so that the variables may be given values.
|
83
|
+
class Variable
|
84
|
+
|
85
|
+
# When Variable objects are initialised they may be given either a simple
|
86
|
+
# symbol, or a compound object (such as a hash) which contains symbols.
|
87
|
+
# When a compound object is given, a constructor must also be given.
|
88
|
+
#
|
89
|
+
# varbg = Variable.new({:image => :button, :color => :bright})
|
90
|
+
# varbg.to_s({:button => "button.png", :bright => "0f0"})
|
91
|
+
#
|
92
|
+
# Which would give the following:
|
93
|
+
#
|
94
|
+
# background-image:url('button.png'); background-color:#0f0;
|
95
|
+
#
|
96
|
+
# Constructors can also be given for simple values, e.g. when creating a
|
97
|
+
# Color.
|
98
|
+
#
|
99
|
+
# varc = Variable.new(:bright, Color)
|
100
|
+
# varc.to_s({:bright => "f00"}) # => "#f00"
|
101
|
+
#
|
102
|
+
def initialize(name_or_hash, constructor = nil)
|
103
|
+
@name = name_or_hash
|
104
|
+
@constructor = constructor
|
105
|
+
end
|
106
|
+
|
107
|
+
# The symbol table is given as an argument to the root element of a
|
108
|
+
# selector tree when it is serialised, and passed down to each node as
|
109
|
+
# the tree is traversed. Nodes must then serialise themselves, and if
|
110
|
+
# they contain Variables they must pass them the symbol table so that
|
111
|
+
# they can be resolved to a given value.
|
112
|
+
def to_s(symbols)
|
113
|
+
if @constructor.nil?
|
114
|
+
symbols[@name]
|
115
|
+
elsif @name.is_a? Symbol
|
116
|
+
@constructor.new(symbols[@name]).to_s
|
117
|
+
else
|
118
|
+
@constructor.new(@name.to_a.inject({}) {|a, e|
|
119
|
+
a[e.first] = symbols[e.last]
|
120
|
+
a
|
121
|
+
}).to_s
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
69
126
|
# Often the selector associated with a call to the rule method would simply
|
70
127
|
# be a single HTML element name. This has been factored out by adding
|
71
128
|
# methods to the Description DSL class corresponding to all the HTML
|
@@ -161,7 +218,9 @@ module Stylish
|
|
161
218
|
return unless declarations || block
|
162
219
|
|
163
220
|
selectors = [selectors] unless selectors.is_a?(Array)
|
164
|
-
selectors.map!
|
221
|
+
selectors.map! do |s|
|
222
|
+
Selector.new(s.is_a?(Symbol) ? Variable.new(s) : s)
|
223
|
+
end
|
165
224
|
|
166
225
|
declarations = Generate.parse_declarations(declarations)
|
167
226
|
|
data/lib/stylish/stylesheet.rb
CHANGED
@@ -16,9 +16,9 @@ module Stylish
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Recursively serialise the tree to a stylesheet.
|
19
|
-
def to_s
|
19
|
+
def to_s(symbols = {})
|
20
20
|
return "" if @nodes.empty?
|
21
|
-
@nodes.map {|node| node.to_s }.join(@format)
|
21
|
+
@nodes.map {|node| node.to_s(symbols) }.join(@format)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/lib/stylish/tree.rb
CHANGED
@@ -84,10 +84,10 @@ module Stylish
|
|
84
84
|
end
|
85
85
|
|
86
86
|
# Recursively serialise the selector tree.
|
87
|
-
def to_s(scope = "")
|
87
|
+
def to_s(symbols = {}, scope = "")
|
88
88
|
return "" if @nodes.empty?
|
89
89
|
scope = scope.empty? ? @scope.to_s : scope + " " + @scope.to_s
|
90
|
-
@nodes.map {|node| node.to_s(scope) }.join(@format)
|
90
|
+
@nodes.map {|node| node.to_s(symbols, scope) }.join(@format)
|
91
91
|
end
|
92
92
|
|
93
93
|
# Return the node's child nodes.
|
data/lib/stylish.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__)
|
2
|
-
|
3
1
|
require 'pathname'
|
2
|
+
require 'mathn'
|
3
|
+
require 'rational'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require '
|
9
|
-
require '
|
10
|
-
require '
|
11
|
-
require '
|
5
|
+
module Stylish
|
6
|
+
STYLISH_PATH = File.expand_path(File.dirname(__FILE__)) + '/stylish/'
|
7
|
+
|
8
|
+
require STYLISH_PATH + 'formattable'
|
9
|
+
require STYLISH_PATH + 'tree'
|
10
|
+
require STYLISH_PATH + 'core'
|
11
|
+
require STYLISH_PATH + 'tree'
|
12
|
+
require STYLISH_PATH + 'stylesheet'
|
13
|
+
require STYLISH_PATH + 'image'
|
14
|
+
require STYLISH_PATH + 'background'
|
15
|
+
require STYLISH_PATH + 'color'
|
16
|
+
require STYLISH_PATH + 'generate'
|
17
|
+
end
|
data/test/background_test.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require './lib/stylish'
|
3
|
-
|
4
1
|
class BackgroundTest < Test::Unit::TestCase
|
5
2
|
|
6
3
|
def setup
|
@@ -24,10 +21,26 @@ class BackgroundTest < Test::Unit::TestCase
|
|
24
21
|
Stylish::Background.new(:image => "background.jpg").image.path)
|
25
22
|
end
|
26
23
|
|
24
|
+
def test_multiple_background_images
|
25
|
+
bg = Stylish::Background.new :image =>
|
26
|
+
["flower.png", "ball.png", "grass.png"]
|
27
|
+
|
28
|
+
assert_equal(3, bg.image.length)
|
29
|
+
assert_equal("background-image:" +
|
30
|
+
"url('flower.png'), url('ball.png'), url('grass.png');", bg.to_s)
|
31
|
+
end
|
32
|
+
|
27
33
|
def test_valid_background_repeats
|
28
34
|
assert_equal('no-repeat', @composite.repeat)
|
29
35
|
end
|
30
36
|
|
37
|
+
def test_multiple_background_repeats
|
38
|
+
bg = Stylish::Background.new :repeat => ["repeat-x", "repeat-y"]
|
39
|
+
|
40
|
+
assert_equal(2, bg.repeat.length)
|
41
|
+
assert_equal("background-repeat:repeat-x, repeat-y;", bg.to_s)
|
42
|
+
end
|
43
|
+
|
31
44
|
def test_valid_background_positions
|
32
45
|
assert_equal(2, @composite.position.length)
|
33
46
|
assert_equal("left", @composite.position[0])
|
@@ -44,12 +57,32 @@ class BackgroundTest < Test::Unit::TestCase
|
|
44
57
|
Stylish::Background.new(:attachment => "fixed").attachment)
|
45
58
|
end
|
46
59
|
|
60
|
+
def test_multiple_attachments
|
61
|
+
glued = Stylish::Background.new :attachment => ["local", "fixed"]
|
62
|
+
|
63
|
+
assert_equal(2, glued.attachment.length)
|
64
|
+
assert_equal("background-attachment:local, fixed;", glued.to_s)
|
65
|
+
end
|
66
|
+
|
47
67
|
def test_invalid_background_colors
|
48
68
|
assert_raise ArgumentError do
|
49
69
|
Stylish::Background.new(:color => "sky-blue")
|
50
70
|
end
|
51
71
|
end
|
52
72
|
|
73
|
+
def test_origins
|
74
|
+
original = Stylish::Background.new :origin => ["border-box", "padding-box"]
|
75
|
+
|
76
|
+
assert_equal(2, original.origin.length)
|
77
|
+
assert_equal("background-origin:border-box, padding-box;", original.to_s)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_breaks
|
81
|
+
broken = Stylish::Background.new :break => "bounding-box"
|
82
|
+
|
83
|
+
assert_equal("background-break:bounding-box;", broken.to_s)
|
84
|
+
end
|
85
|
+
|
53
86
|
def test_invalid_image_values
|
54
87
|
assert_nil(Stylish::Background.new(:image => []).image)
|
55
88
|
assert_nil(Stylish::Background.new(:image => {}).image)
|
data/test/color_test.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require './lib/stylish'
|
3
|
-
|
4
1
|
class ColorTest < Test::Unit::TestCase
|
5
2
|
|
6
3
|
def setup
|
7
|
-
@red = Stylish::Color.new(
|
8
|
-
@green = Stylish::Color.new(
|
4
|
+
@red = Stylish::Color.new("red")
|
5
|
+
@green = Stylish::Color.new("green")
|
9
6
|
@blue = Stylish::Color.new("#0000FF")
|
10
7
|
@white = Stylish::Color.new("#FFF")
|
11
8
|
@yellow = Stylish::Color.new([255, 255, 0])
|
@@ -68,8 +65,6 @@ class ColorTest < Test::Unit::TestCase
|
|
68
65
|
end
|
69
66
|
|
70
67
|
def test_case_insensitivity_of_keywords
|
71
|
-
assert_equal([0, 128, 0, nil], Stylish::Color.new(:Green).value)
|
72
|
-
assert_equal([0, 128, 0, nil], Stylish::Color.new(:GrEeN).value)
|
73
68
|
assert_equal([0, 128, 0, nil], Stylish::Color.new("Green").value)
|
74
69
|
assert_equal([0, 128, 0, nil], Stylish::Color.new("GrEeN").value)
|
75
70
|
end
|
@@ -117,7 +112,7 @@ class ColorTest < Test::Unit::TestCase
|
|
117
112
|
|
118
113
|
def test_keyword_to_string
|
119
114
|
assert_equal("green", @green.to_s)
|
120
|
-
assert_equal("yellow", Stylish::Color.new(
|
115
|
+
assert_equal("yellow", Stylish::Color.new("yellow").to_s)
|
121
116
|
end
|
122
117
|
|
123
118
|
def test_rgb_to_string
|
@@ -148,8 +143,8 @@ class ColorTest < Test::Unit::TestCase
|
|
148
143
|
end
|
149
144
|
|
150
145
|
def test_inherit_and_transparent_to_hex
|
151
|
-
assert_nil(Stylish::Color.new(
|
152
|
-
assert_nil(Stylish::Color.new(
|
146
|
+
assert_nil(Stylish::Color.new("inherit").to_hex)
|
147
|
+
assert_nil(Stylish::Color.new("transparent").to_hex)
|
153
148
|
end
|
154
149
|
|
155
150
|
def test_hex_to_hex
|
@@ -160,8 +155,8 @@ class ColorTest < Test::Unit::TestCase
|
|
160
155
|
end
|
161
156
|
|
162
157
|
def test_keywords_to_hex
|
163
|
-
assert_equal("#808080", Stylish::Color.new(
|
164
|
-
assert_equal("#800000", Stylish::Color.new(
|
158
|
+
assert_equal("#808080", Stylish::Color.new("gray").to_hex)
|
159
|
+
assert_equal("#800000", Stylish::Color.new("maroon").to_hex)
|
165
160
|
end
|
166
161
|
|
167
162
|
def test_rgb_to_hex
|
@@ -174,7 +169,7 @@ class ColorTest < Test::Unit::TestCase
|
|
174
169
|
assert_equal("#fff", Stylish::Color.new([255, 255, 255]).to_hex)
|
175
170
|
assert_equal("#fff", Stylish::Color.new("#ffffff").to_hex)
|
176
171
|
assert_equal("#fb0", Stylish::Color.new("#ffbb00").to_hex)
|
177
|
-
assert_equal("#0ff", Stylish::Color.new(
|
172
|
+
assert_equal("#0ff", Stylish::Color.new("aqua").to_hex)
|
178
173
|
end
|
179
174
|
|
180
175
|
def test_rgb_to_hsl
|
data/test/comment_test.rb
CHANGED
data/test/declaration_test.rb
CHANGED
data/test/declarations_test.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require './lib/stylish'
|
3
|
-
|
4
1
|
class DeclarationsTest < Test::Unit::TestCase
|
5
2
|
|
6
3
|
def setup
|
7
4
|
@ds = Stylish::Declarations.new
|
8
5
|
@ds << Stylish::Declaration.new("border-color", "red")
|
9
|
-
@ds << Stylish::Background.new(:color =>
|
6
|
+
@ds << Stylish::Background.new(:color => "blue", :image => "test.png")
|
10
7
|
end
|
11
8
|
|
12
9
|
def test_join
|
data/test/formattable_test.rb
CHANGED
data/test/generate_test.rb
CHANGED
data/test/image_test.rb
CHANGED
data/test/rule_test.rb
CHANGED
data/test/selector_test.rb
CHANGED
@@ -1,13 +1,10 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require './lib/stylish'
|
3
|
-
|
4
1
|
class SelectorTest < Test::Unit::TestCase
|
5
2
|
|
6
3
|
def test_to_string
|
7
4
|
s = Stylish::Selector.new(".test")
|
8
5
|
assert_equal(".test", s.to_s)
|
9
6
|
|
10
|
-
s = Stylish::Selector.new(
|
7
|
+
s = Stylish::Selector.new("div")
|
11
8
|
assert_equal("div", s.to_s)
|
12
9
|
end
|
13
10
|
end
|
data/test/selectors_test.rb
CHANGED
data/test/stylesheet_test.rb
CHANGED
data/test/tree_test.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
class VariableTest < Test::Unit::TestCase
|
2
|
+
|
3
|
+
def setup
|
4
|
+
@style = Stylish.generate do
|
5
|
+
div :font_weight => :weighty
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_variable_inclusion
|
10
|
+
assert_instance_of(Stylish::Generate::Variable,
|
11
|
+
@style.rules.first.declarations.first.value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_variable_serialisation
|
15
|
+
assert_equal("div {font-weight:bold;}",
|
16
|
+
@style.to_s({:weighty => "bold"}))
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_selector_variables
|
20
|
+
style = Stylish.generate do
|
21
|
+
rule :some_selector, :line_height => 1.5
|
22
|
+
end
|
23
|
+
|
24
|
+
assert_equal("body p {line-height:1.5;}",
|
25
|
+
style.to_s({:some_selector => "body p"}))
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_color_variables
|
29
|
+
style = Stylish.generate do
|
30
|
+
body :color => :bright_as_a_button
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_equal("body {color:#57b5cc;}",
|
34
|
+
style.to_s({:bright_as_a_button => "57b5cc"}))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_background_variables
|
38
|
+
style = Stylish.generate do
|
39
|
+
body :background => {:color => :dark, :image => :buttonish}
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_equal(
|
43
|
+
"body {background-color:#000; background-image:url('button.png');}",
|
44
|
+
style.to_s({:dark => "000", :buttonish => "button.png"}))
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ionfish-stylish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benedict Eastaugh
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-24 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -22,10 +22,12 @@ extensions: []
|
|
22
22
|
extra_rdoc_files:
|
23
23
|
- README.md
|
24
24
|
files:
|
25
|
+
- History.txt
|
25
26
|
- README.md
|
26
27
|
- Rakefile
|
27
28
|
- VERSION.yml
|
28
29
|
- lib/stylish.rb
|
30
|
+
- lib/stylish/background.rb
|
29
31
|
- lib/stylish/color.rb
|
30
32
|
- lib/stylish/core.rb
|
31
33
|
- lib/stylish/formattable.rb
|
@@ -46,6 +48,7 @@ files:
|
|
46
48
|
- test/selectors_test.rb
|
47
49
|
- test/stylesheet_test.rb
|
48
50
|
- test/tree_test.rb
|
51
|
+
- test/variable_test.rb
|
49
52
|
has_rdoc: true
|
50
53
|
homepage: http://github.com/ionfish/stylish
|
51
54
|
post_install_message:
|
@@ -86,3 +89,4 @@ test_files:
|
|
86
89
|
- test/selectors_test.rb
|
87
90
|
- test/stylesheet_test.rb
|
88
91
|
- test/tree_test.rb
|
92
|
+
- test/variable_test.rb
|