ionfish-stylish 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/README.md +2 -7
- data/VERSION.yml +1 -1
- data/lib/stylish/color.rb +7 -6
- data/lib/stylish/core.rb +43 -26
- data/lib/stylish/{background.rb → extended.rb} +128 -75
- data/lib/stylish/formattable.rb +35 -44
- data/lib/stylish/generate.rb +44 -12
- data/lib/stylish/numeric.rb +94 -0
- data/lib/stylish/tree.rb +3 -4
- data/lib/stylish.rb +2 -4
- data/test/background_test.rb +16 -25
- data/test/formattable_test.rb +6 -25
- data/test/generate_test.rb +17 -0
- data/test/length_test.rb +20 -0
- data/test/position_test.rb +22 -0
- metadata +8 -5
- data/lib/stylish/image.rb +0 -32
- data/lib/stylish/stylesheet.rb +0 -25
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== Version 0.1.5 (2009-05-03)
|
2
|
+
|
3
|
+
Improved background support
|
4
|
+
* Length, Position and Percentage classes
|
5
|
+
* accept_format now a class method
|
6
|
+
* Improved API and internals for multiple background properties
|
7
|
+
|
8
|
+
|
1
9
|
=== Version 0.1.4 (2009-04-25)
|
2
10
|
|
3
11
|
Bug fixes
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ 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
|
26
|
+
A number of additional examples are available in the `example/` directory.
|
27
27
|
|
28
28
|
|
29
29
|
Compatibility
|
@@ -37,9 +37,6 @@ Future considerations
|
|
37
37
|
---------------------
|
38
38
|
|
39
39
|
* Add a Border class to complement Background.
|
40
|
-
* Add better support for CSS3 properties to Background.
|
41
|
-
* Fundamental objects like percentages need their own classes rather than
|
42
|
-
being dealt with in an ad-hoc manner by higher-level objects.
|
43
40
|
* Add a parser so CSS can be read as well as written.
|
44
41
|
|
45
42
|
|
@@ -59,9 +56,7 @@ Stylish treats CSS as object code--but it treats it nicely.
|
|
59
56
|
Licence
|
60
57
|
-------
|
61
58
|
|
62
|
-
Copyright (c) 2008-2009, Benedict Eastaugh
|
63
|
-
|
64
|
-
All rights reserved.
|
59
|
+
Copyright (c) 2008-2009, Benedict Eastaugh. All rights reserved.
|
65
60
|
|
66
61
|
Redistribution and use in source and binary forms, with or without
|
67
62
|
modification, are permitted provided that the following conditions are met:
|
data/VERSION.yml
CHANGED
data/lib/stylish/color.rb
CHANGED
@@ -22,14 +22,15 @@ module Stylish #:nodoc:
|
|
22
22
|
# RGB integer; a hexadecimal representation of an RGB color; a rgb()
|
23
23
|
# representation of an RGB color; and an rgba() representation of an RGBA
|
24
24
|
# color.
|
25
|
+
pct = Percentage::PCTSTR
|
25
26
|
OPACITY = /([0-1]|0\.\d+)/
|
26
27
|
RGB_INT = /(\d{1,2}|[1-2][0-5]{2})/
|
27
28
|
HSL_INT = /(\d{1,2}|[1-2]\d{2}|3([0-5]\d|60))/
|
28
29
|
HEX_COLOR = /^#?([\da-fA-F]{3}){1,2}$/
|
29
|
-
RGB_COLOR = /rgb\(\s*((#{RGB_INT}|#{
|
30
|
-
RGBA_COLOR = /rgba\(\s*((#{RGB_INT}|#{
|
31
|
-
HSL_COLOR = /hsl\(\s*((#{HSL_INT}|#{
|
32
|
-
HSLA_COLOR = /hsla\(\s*((#{HSL_INT}|#{
|
30
|
+
RGB_COLOR = /rgb\(\s*((#{RGB_INT}|#{pct}),\s*){2}(#{RGB_INT}|#{pct})\s*\)/
|
31
|
+
RGBA_COLOR = /rgba\(\s*((#{RGB_INT}|#{pct}),\s*){3}#{OPACITY}\s*\)/
|
32
|
+
HSL_COLOR = /hsl\(\s*((#{HSL_INT}|#{pct}),\s*){2}(#{HSL_INT}|#{pct})\s*\)/
|
33
|
+
HSLA_COLOR = /hsla\(\s*((#{HSL_INT}|#{pct}),\s*){3}(#{OPACITY})\s*\)/
|
33
34
|
|
34
35
|
# Colors can be of several types: keywords, hexadecimal strings, RGB and
|
35
36
|
# RGBA formats. The type of the color is set on initialisation, so that
|
@@ -253,7 +254,7 @@ module Stylish #:nodoc:
|
|
253
254
|
rgb << v
|
254
255
|
elsif v =~ /^#{RGB_INT}$/
|
255
256
|
rgb << v.to_i
|
256
|
-
elsif v
|
257
|
+
elsif Percentage.match? v
|
257
258
|
rgb << (v.chop.to_f * 256 / 100).round
|
258
259
|
end
|
259
260
|
|
@@ -503,7 +504,7 @@ module Stylish #:nodoc:
|
|
503
504
|
map do |value|
|
504
505
|
if value =~ /^#{RGB_INT}$/
|
505
506
|
value.to_i
|
506
|
-
elsif value
|
507
|
+
elsif Percentage.match? value
|
507
508
|
(value.chop.to_f * 255 / 100).round
|
508
509
|
else
|
509
510
|
value.to_f
|
data/lib/stylish/core.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
module Stylish
|
2
2
|
|
3
|
-
# Regular expressions matching a percentage, and matching only a percentage.
|
4
|
-
PCT = /-?(0\.)?\d+%/
|
5
|
-
PERCENTAGE = /^#{PCT}$/
|
6
|
-
|
7
3
|
# A list of all valid HTML5 elements. Used primarily in the stylesheet
|
8
4
|
# generation DSL as method names.
|
9
5
|
HTML_ELEMENTS = [:html, :head, :title, :base, :link, :meta, :style, :script,
|
@@ -21,6 +17,28 @@ module Stylish
|
|
21
17
|
:command, :bb, :menu, :legend, :div, :h1, :h2, :h3, :h4,
|
22
18
|
:h5, :h6]
|
23
19
|
|
20
|
+
class Stylesheet < Tree::SelectorScope
|
21
|
+
accept_format(/\s*/m, "\n")
|
22
|
+
|
23
|
+
# Stylesheets are pure aggregate objects; they can contain child nodes,
|
24
|
+
# but have no data of their own. Their initializer therefore accepts no
|
25
|
+
# arguments.
|
26
|
+
def initialize
|
27
|
+
@nodes = []
|
28
|
+
end
|
29
|
+
|
30
|
+
# Stylesheets are the roots of selector trees.
|
31
|
+
def root?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Recursively serialise the tree to a stylesheet.
|
36
|
+
def to_s(symbols = {})
|
37
|
+
return "" if @nodes.empty?
|
38
|
+
@nodes.map {|node| node.to_s(symbols) }.join(self.class.format)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
24
42
|
# Rule objects represent CSS rules, and serialise to them. They possess one
|
25
43
|
# or more selectors, and zero or more declarations. In addition to their
|
26
44
|
# importance as the major building-blocks of stylesheets, they act as the
|
@@ -45,6 +63,7 @@ module Stylish
|
|
45
63
|
include Formattable, Tree::Leaf
|
46
64
|
|
47
65
|
attr_reader :selectors, :declarations
|
66
|
+
accept_format(/^\s*%s\s*\{\s*%s\s*\}\s*$/m, "%s {%s}")
|
48
67
|
|
49
68
|
# Every Rule must have at least one selector, but may have any number of
|
50
69
|
# declarations. Empty rules are often used in stylesheets to indicate
|
@@ -61,8 +80,6 @@ module Stylish
|
|
61
80
|
# This makes Rule objects a very flexible foundation for the higher-level
|
62
81
|
# data structures and APIs in Stylish.
|
63
82
|
def initialize(selectors, declarations)
|
64
|
-
accept_format(/^\s*%s\s*\{\s*%s\s*\}\s*$/m, "%s {%s}")
|
65
|
-
|
66
83
|
@selectors = selectors.inject(Selectors.new) do |ss, s|
|
67
84
|
ss << s
|
68
85
|
end
|
@@ -74,7 +91,7 @@ module Stylish
|
|
74
91
|
|
75
92
|
# Serialise the rule to valid CSS code.
|
76
93
|
def to_s(symbols = {}, scope = "")
|
77
|
-
sprintf(
|
94
|
+
sprintf(self.class.format, selectors.join(symbols, scope),
|
78
95
|
@declarations.to_s(symbols))
|
79
96
|
end
|
80
97
|
end
|
@@ -201,20 +218,14 @@ module Stylish
|
|
201
218
|
class Selectors < Array
|
202
219
|
include Formattable
|
203
220
|
|
204
|
-
|
205
|
-
# is done in its initialiser, regardless of arguments, is to set the
|
206
|
-
# default serialisation format.
|
207
|
-
def initialize(*args)
|
208
|
-
accept_format(/^\s*,\s*$/m, ", ")
|
209
|
-
super
|
210
|
-
end
|
221
|
+
accept_format(/^\s*,\s*$/m, ", ")
|
211
222
|
|
212
223
|
# The join method overrides the superclass' method in order to always use a
|
213
224
|
# specific separator, and so that the scope that the selectors are being
|
214
225
|
# used in can be passed through when Rules etc. are serialised.
|
215
226
|
def join(symbols = {}, scope = "")
|
216
227
|
self.inject("") do |ss, s|
|
217
|
-
(ss.empty? ? "" : ss + self.format) + s.to_s(symbols, scope)
|
228
|
+
(ss.empty? ? "" : ss + self.class.format) + s.to_s(symbols, scope)
|
218
229
|
end
|
219
230
|
end
|
220
231
|
|
@@ -232,10 +243,10 @@ module Stylish
|
|
232
243
|
include Formattable
|
233
244
|
|
234
245
|
attr_accessor :value
|
246
|
+
accept_format(/^\s*%s\s*:\s*%s;\s*$/m, "%s:%s;")
|
235
247
|
|
236
248
|
# Each Declaration has a property name and a value.
|
237
249
|
def initialize(name, value)
|
238
|
-
accept_format(/^\s*%s\s*:\s*%s;\s*$/m, "%s:%s;")
|
239
250
|
self.value = value
|
240
251
|
self.name = name
|
241
252
|
end
|
@@ -270,7 +281,7 @@ module Stylish
|
|
270
281
|
value = @value.to_s
|
271
282
|
end
|
272
283
|
|
273
|
-
sprintf(
|
284
|
+
sprintf(self.class.format, @property_name.to_s, value)
|
274
285
|
end
|
275
286
|
end
|
276
287
|
|
@@ -280,18 +291,12 @@ module Stylish
|
|
280
291
|
class Declarations < Array
|
281
292
|
include Formattable
|
282
293
|
|
283
|
-
|
284
|
-
# characters, including newline. The default format string is a single
|
285
|
-
# space, which is probably the most common choice in hand-written CSS.
|
286
|
-
def initialize(*args)
|
287
|
-
accept_format(/^\s*$/m, " ")
|
288
|
-
super
|
289
|
-
end
|
294
|
+
accept_format(/^\s*$/m, " ")
|
290
295
|
|
291
296
|
# The format attribute is always used as the separator when joining the
|
292
297
|
# elements of a Declarations object.
|
293
298
|
def join
|
294
|
-
super(
|
299
|
+
super(self.class.format)
|
295
300
|
end
|
296
301
|
|
297
302
|
# Returns a string by converting each element to a string, separated by the
|
@@ -300,9 +305,21 @@ module Stylish
|
|
300
305
|
# CSS code.
|
301
306
|
def to_s(symbols = {})
|
302
307
|
self.inject("") do |a, o|
|
303
|
-
a << (a.empty? ? "" :
|
308
|
+
a << (a.empty? ? "" : self.class.format) << o.to_s(symbols)
|
304
309
|
end
|
305
310
|
end
|
306
311
|
end
|
307
312
|
|
313
|
+
# PropertyBundle objects are simple wrappers around property values with
|
314
|
+
# multiple values.
|
315
|
+
class PropertyBundle < Array
|
316
|
+
include Formattable
|
317
|
+
|
318
|
+
accept_format(/^\s*,\s*$/m, ", ")
|
319
|
+
|
320
|
+
def to_s
|
321
|
+
self.join(self.class.format)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
308
325
|
end
|
@@ -1,5 +1,34 @@
|
|
1
1
|
module Stylish
|
2
2
|
|
3
|
+
# Instances of the Image class are used to represent paths to images,
|
4
|
+
# generally background images.
|
5
|
+
class Image
|
6
|
+
include Formattable
|
7
|
+
|
8
|
+
attr_accessor :path
|
9
|
+
accept_format(/^url\(\s*('|")?%s\1\s*\)$/, "url('%s')")
|
10
|
+
|
11
|
+
# Image instances are serialised to URI values. The path to the image file
|
12
|
+
# can be surrounded by either single quotes, double quotes or neither;
|
13
|
+
# single quotes are the default in Stylish.
|
14
|
+
def initialize(path)
|
15
|
+
@path = path
|
16
|
+
end
|
17
|
+
|
18
|
+
# Serialising Image objects to a string produces the URI values seen in
|
19
|
+
# background-image declarations, e.g.
|
20
|
+
#
|
21
|
+
# image = Image.new("test.png")
|
22
|
+
# image.to_s # => "url('test.png')"
|
23
|
+
#
|
24
|
+
# background = Stylish::Background.new(:image => "test.png")
|
25
|
+
# background.to_s # => "background-image:url('test.png');"
|
26
|
+
#
|
27
|
+
def to_s
|
28
|
+
sprintf(self.class.format, path.to_s)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
3
32
|
# The Background class is a specialised kind of Declaration, geared towards
|
4
33
|
# dealing with the oddities of the background family of declarations, which
|
5
34
|
# can exist in both long- and shorthand forms.
|
@@ -19,15 +48,6 @@ module Stylish
|
|
19
48
|
# weighting to only override specific parts of other rules' background
|
20
49
|
# declarations.
|
21
50
|
class Background < Declaration
|
22
|
-
attr_reader :color,
|
23
|
-
:image,
|
24
|
-
:repeat,
|
25
|
-
:position,
|
26
|
-
:attachment,
|
27
|
-
:origin,
|
28
|
-
:break,
|
29
|
-
:compressed
|
30
|
-
|
31
51
|
PROPERTIES = [
|
32
52
|
[:color, "background-color"],
|
33
53
|
[:image, "background-image"],
|
@@ -41,105 +61,134 @@ module Stylish
|
|
41
61
|
REPEAT_VALUES = ["repeat-x", "repeat-y", "repeat",
|
42
62
|
"space", "round", "no-repeat"]
|
43
63
|
ATTACHMENT_VALUES = ["scroll", "fixed", "local"]
|
44
|
-
HORIZONTAL_POSITIONS = ["left", "center", "right"]
|
45
|
-
VERTICAL_POSITIONS = ["top", "center", "bottom"]
|
46
64
|
ORIGIN_VALUES = ["border-box", "padding-box", "content-box"]
|
47
65
|
BREAK_VALUES = ["bounding-box", "each-box", "continuous"]
|
48
66
|
|
67
|
+
PROPERTIES.each do |name, value|
|
68
|
+
attr_reader name
|
69
|
+
end
|
70
|
+
|
49
71
|
# Create a new Background object with the specified properties.
|
50
72
|
def initialize(options)
|
51
|
-
accept_format(/^\s*%s\s*:\s*%s;\s*$/m, "%s:%s;")
|
52
73
|
self.value = options
|
53
74
|
end
|
54
75
|
|
55
76
|
# Input validation for colours is handled by the Color class, which will
|
56
77
|
# raise an ArgumentError if the argument is an invalid colour value.
|
78
|
+
#
|
79
|
+
# coloured = Background.new :color => "545454"
|
80
|
+
# coloured.to_s # => "background-color:#545454;"
|
81
|
+
#
|
57
82
|
def color=(val)
|
58
83
|
@color = Color.new(val)
|
59
84
|
end
|
60
85
|
|
61
|
-
# Set the background image
|
62
|
-
# background images, so this method attempts to provide a backwards-
|
63
|
-
# compatible solution.
|
86
|
+
# Set the background image.
|
64
87
|
#
|
65
88
|
# background = Background.new :image => "sky.png", :compressed => true
|
66
89
|
# background.to_s # => "background:url('sky.png');"
|
67
90
|
#
|
68
|
-
|
91
|
+
def image=(path)
|
92
|
+
@image = Image.new(path)
|
93
|
+
end
|
94
|
+
|
95
|
+
# As of CSS3, elements may have multiple background images.
|
96
|
+
#
|
97
|
+
# background.images = ["ball.png", "grass.png"]
|
69
98
|
# background.to_s # => "background:url('ball.png'), url('grass.png');"
|
70
99
|
#
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
if @image.length < 2
|
76
|
-
@image = @image.first
|
77
|
-
else
|
78
|
-
def @image.to_s
|
79
|
-
join(", ")
|
80
|
-
end
|
100
|
+
def images=(paths)
|
101
|
+
@image = paths.inject(PropertyBundle.new) do |is, i|
|
102
|
+
is << Image.new(i)
|
81
103
|
end
|
82
104
|
end
|
83
105
|
|
84
|
-
# Set the background repeat
|
85
|
-
#
|
86
|
-
#
|
106
|
+
# Set the background repeat.
|
107
|
+
#
|
108
|
+
# nonrepeating = Background.new :repeat => "no-repeat"
|
109
|
+
# nonrepeating.to_s # => "background-repeat:no-repeat;"
|
110
|
+
#
|
111
|
+
def repeat=(repeat)
|
112
|
+
@repeat = repeat if REPEAT_VALUES.include? repeat
|
113
|
+
end
|
114
|
+
|
115
|
+
# As of CSS3, the background-repeat property may have multiple values.
|
87
116
|
#
|
88
|
-
# repeating = Background.new :
|
117
|
+
# repeating = Background.new :repeats => ["repeat-x", "repeat-y"]
|
89
118
|
# repeating.to_s # => "background-repeat:repeat-x, repeat-y;"
|
90
119
|
#
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if @repeat.length < 2
|
96
|
-
@repeat = @repeat.first
|
97
|
-
else
|
98
|
-
def @repeat.to_s
|
99
|
-
join(", ")
|
100
|
-
end
|
120
|
+
def repeats=(repeats)
|
121
|
+
@repeat = repeats.inject(PropertyBundle.new) do |rs, r|
|
122
|
+
rs << r if REPEAT_VALUES.include? r
|
123
|
+
rs
|
101
124
|
end
|
102
125
|
end
|
103
126
|
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
127
|
+
# Positions have an x and a y value, and are handled by a specialised
|
128
|
+
# Position class. They should be passed an array of two values, e.g.
|
129
|
+
#
|
130
|
+
# positioned = Background.new :position => ["100%", 0]
|
131
|
+
# positioned.to_s # => "background-position:100% 0;"
|
132
|
+
#
|
133
|
+
# See the documentation for the Position class for further details on
|
134
|
+
# permitted position types.
|
135
|
+
def position=(position)
|
136
|
+
@position = Position.new(position[0], position[1])
|
137
|
+
end
|
138
|
+
|
139
|
+
# As of CSS3, elements may have multiple background images, and
|
140
|
+
# consequently they will need to be separately positioned as well.
|
141
|
+
#
|
142
|
+
# p = Background.new :positions => [["left", "top"], ["right", "top"]]
|
143
|
+
# p.to_s # => "background-position:left top, right top;"
|
144
|
+
#
|
145
|
+
def positions=(positions)
|
146
|
+
@position = positions.inject(PropertyBundle.new) do |ps, p|
|
147
|
+
ps << Position.new(p[0], p[1])
|
109
148
|
end
|
110
149
|
end
|
111
150
|
|
112
151
|
# The background-attachment property takes a limited range of values, so
|
113
152
|
# only a value within that range will be accepted.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
153
|
+
#
|
154
|
+
# attached = Background.new :attachment => "fixed"
|
155
|
+
# attached.to_s # => "background-attachment:fixed;"
|
156
|
+
#
|
157
|
+
def attachment=(attachment)
|
158
|
+
@attachment = attachment if ATTACHMENT_VALUES.include? attachment
|
159
|
+
end
|
160
|
+
|
161
|
+
# As of CSS3 elements may have multiple background-attachment values.
|
162
|
+
#
|
163
|
+
# atts = Background.new :attachments => ["fixed", "scroll"]
|
164
|
+
# atts.to_s # => "background-attachment:fixed, scroll;"
|
165
|
+
#
|
166
|
+
def attachments=(attachments)
|
167
|
+
@attachment = attachments.inject(PropertyBundle.new) do |as, a|
|
168
|
+
as << a if ATTACHMENT_VALUES.include? a
|
169
|
+
as
|
124
170
|
end
|
125
171
|
end
|
126
172
|
|
127
173
|
# The background-origin property specifies the background positioning area.
|
128
|
-
# It is a CSS3 property which takes multiple values.
|
129
174
|
#
|
130
|
-
# original = Background.new :origin =>
|
131
|
-
# original.to_s # => background-origin:
|
175
|
+
# original = Background.new :origin => "content-box"
|
176
|
+
# original.to_s # => background-origin:content-box;
|
132
177
|
#
|
133
|
-
def origin=(
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
178
|
+
def origin=(origin)
|
179
|
+
@origin = origin if ORIGIN_VALUES.include? origin
|
180
|
+
end
|
181
|
+
|
182
|
+
# The background-origin property is a CSS3 property and can take multiple
|
183
|
+
# values.
|
184
|
+
#
|
185
|
+
# origs = Background.new :origin => ["padding-box", "content-box"]
|
186
|
+
# origs.to_s # => background-origin:padding-box, content-box;
|
187
|
+
#
|
188
|
+
def origins=(origins)
|
189
|
+
@origin = origins.inject(PropertyBundle.new) do |os, o|
|
190
|
+
os << o if ORIGIN_VALUES.include? o
|
191
|
+
os
|
143
192
|
end
|
144
193
|
end
|
145
194
|
|
@@ -164,11 +213,11 @@ module Stylish
|
|
164
213
|
# background-repeat:no-repeat; background-position:0 0;
|
165
214
|
#
|
166
215
|
def compressed=(val)
|
167
|
-
@compressed = val == true
|
216
|
+
@compressed = val == true
|
168
217
|
end
|
169
218
|
|
170
|
-
# Override Declaration#name, since it's not compatible with the
|
171
|
-
#
|
219
|
+
# Override Declaration#name, since it's not compatible with the internals
|
220
|
+
# of this class.
|
172
221
|
def name
|
173
222
|
PROPERTIES.reject {|n, p| p.nil? }.map {|n, p|
|
174
223
|
value = self.send(n)
|
@@ -176,8 +225,8 @@ module Stylish
|
|
176
225
|
}.compact
|
177
226
|
end
|
178
227
|
|
179
|
-
# Override Declaration#name=, since it's not compatible with the
|
180
|
-
#
|
228
|
+
# Override Declaration#name=, since it's not compatible with the internals
|
229
|
+
# of this class.
|
181
230
|
def name=(val)
|
182
231
|
raise NoMethodError, "name= is not defined for Background."
|
183
232
|
end
|
@@ -199,8 +248,10 @@ module Stylish
|
|
199
248
|
raise ArgumentError, "Argument must be a hash of background properties"
|
200
249
|
end
|
201
250
|
|
202
|
-
PROPERTIES.each do |name,
|
251
|
+
PROPERTIES.each do |name, value|
|
252
|
+
plural = (name.to_s + "s").to_sym
|
203
253
|
self.send(:"#{name.to_s}=", options[name]) if options[name]
|
254
|
+
self.send(:"#{name.to_s}s=", options[plural]) if options[plural]
|
204
255
|
end
|
205
256
|
end
|
206
257
|
|
@@ -218,7 +269,9 @@ module Stylish
|
|
218
269
|
if @compressed
|
219
270
|
"background:#{self.value(true).map {|p, v| v }.compact.join(" ")};"
|
220
271
|
else
|
221
|
-
self.value(true).map {|p, v|
|
272
|
+
self.value(true).map {|p, v|
|
273
|
+
sprintf(self.class.format, p, v.to_s)
|
274
|
+
}.join(" ")
|
222
275
|
end
|
223
276
|
end
|
224
277
|
end
|
data/lib/stylish/formattable.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Stylish
|
2
2
|
|
3
3
|
# The Formattable mixin gives an API for changing the output format of any of
|
4
|
-
# Stylish's core
|
5
|
-
# provided
|
6
|
-
#
|
4
|
+
# Stylish's core classes, as long as the new output format matches the regex
|
5
|
+
# provided when the class was declared. This is because in order to generate
|
6
|
+
# valid CSS, strings must be joined in the correct way.
|
7
7
|
#
|
8
8
|
# For example, a rule's selectors must be comma-separated and its
|
9
9
|
# declarations must be wrapped in curly braces, while each declaration
|
@@ -11,56 +11,47 @@ module Stylish
|
|
11
11
|
# terminating with a semicolon.
|
12
12
|
#
|
13
13
|
# In order to employ the Formattable mixin, it must be included into a class
|
14
|
-
# and the
|
15
|
-
#
|
14
|
+
# and the accept_format method must be called with the allowed format (as a
|
15
|
+
# regular expression) and the default format (a string).
|
16
16
|
#
|
17
17
|
# class Stylesheet
|
18
18
|
# include Formattable
|
19
|
-
#
|
20
|
-
# def initialize
|
21
|
-
# accept_format(/\s*/m, "\n")
|
22
|
-
# end
|
19
|
+
# accept_format(/\s*/m, "\n")
|
23
20
|
# end
|
24
21
|
#
|
25
|
-
# If one then creates a new Stylesheet object, one can modify the way it's
|
26
|
-
# formatted when serialised to CSS code.
|
27
|
-
#
|
28
|
-
# stylesheet = Stylesheet.new
|
29
|
-
# stylesheet.format # => "\n"
|
30
|
-
# stylesheet.format = "\n\n"
|
31
|
-
# stylesheet.format # => "\n\n"
|
32
|
-
#
|
33
22
|
module Formattable
|
34
|
-
attr_reader :format
|
35
23
|
|
36
|
-
|
37
|
-
|
38
|
-
# object's initialize method.
|
39
|
-
def format=(format)
|
40
|
-
if format_validates?(format)
|
41
|
-
@format = format
|
42
|
-
else
|
43
|
-
raise ArgumentError, "Not an allowed format."
|
44
|
-
end
|
24
|
+
def self.included(base)
|
25
|
+
base.extend(FormattableMethods)
|
45
26
|
end
|
46
27
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
28
|
+
module FormattableMethods
|
29
|
+
attr_reader :format
|
30
|
+
|
31
|
+
def format=(format)
|
32
|
+
if format_validates?(format)
|
33
|
+
@format = format
|
34
|
+
else
|
35
|
+
raise ArgumentError, "Not an allowed format."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def accept_format(pattern, default)
|
40
|
+
@format_pattern = pattern if pattern.is_a? Regexp
|
41
|
+
self.format = default
|
42
|
+
end
|
43
|
+
|
44
|
+
def format_validates?(format_string)
|
45
|
+
format_string =~ @format_pattern
|
46
|
+
end
|
47
|
+
|
48
|
+
def inherited(subclass)
|
49
|
+
["format", "format_pattern"].each do |attribute|
|
50
|
+
instance_var = "@#{attribute}"
|
51
|
+
subclass.instance_variable_set(instance_var,
|
52
|
+
instance_variable_get(instance_var))
|
53
|
+
end
|
54
|
+
end
|
64
55
|
end
|
65
56
|
end
|
66
57
|
|
data/lib/stylish/generate.rb
CHANGED
@@ -55,13 +55,13 @@ module Stylish
|
|
55
55
|
key = key.to_s.sub("_", "-").to_sym
|
56
56
|
|
57
57
|
if key == :background
|
58
|
-
if
|
58
|
+
if includes_symbols? value
|
59
59
|
declaration = Variable.new(value, Background)
|
60
60
|
else
|
61
61
|
declaration = Background.new(value)
|
62
62
|
end
|
63
63
|
elsif key == :color
|
64
|
-
if
|
64
|
+
if includes_symbols? value
|
65
65
|
value = Variable.new(value, Color)
|
66
66
|
else
|
67
67
|
value = Color.new(value)
|
@@ -69,7 +69,7 @@ module Stylish
|
|
69
69
|
|
70
70
|
declaration = Declaration.new("color", value)
|
71
71
|
else
|
72
|
-
value = Variable.new(value) if
|
72
|
+
value = Variable.new(value) if includes_symbols? value
|
73
73
|
declaration = Declaration.new(key, value)
|
74
74
|
end
|
75
75
|
|
@@ -77,6 +77,18 @@ module Stylish
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
def self.includes_symbols?(value)
|
81
|
+
return true if value.is_a? Symbol
|
82
|
+
|
83
|
+
if value.is_a? Array
|
84
|
+
return value.any? {|v| includes_symbols?(v) }
|
85
|
+
elsif value.is_a? Hash
|
86
|
+
return value.values.any? {|v| includes_symbols?(v) }
|
87
|
+
end
|
88
|
+
|
89
|
+
false
|
90
|
+
end
|
91
|
+
|
80
92
|
# Variables are elements of a selector tree that haven't been assigned
|
81
93
|
# values yet. When a tree that includes Variable objects is serialised, it
|
82
94
|
# must be passed a symbol table so that the variables may be given values.
|
@@ -109,16 +121,36 @@ module Stylish
|
|
109
121
|
# the tree is traversed. Nodes must then serialise themselves, and if
|
110
122
|
# they contain Variables they must pass them the symbol table so that
|
111
123
|
# they can be resolved to a given value.
|
112
|
-
def to_s(
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@constructor.new(
|
124
|
+
def to_s(symbol_table, scope = "")
|
125
|
+
evald = eval(nil, symbol_table)
|
126
|
+
|
127
|
+
unless @constructor.nil?
|
128
|
+
@constructor.new(evald).to_s(symbol_table, scope)
|
129
|
+
else
|
130
|
+
evald
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Recursively replace symbols with values. This allows for symbol lookup
|
135
|
+
# within more complex nested structures of arrays and hashes, created by
|
136
|
+
# e.g. background declarations.
|
137
|
+
def eval(name_or_hash, symbol_table)
|
138
|
+
replaceable = name_or_hash || @name
|
139
|
+
|
140
|
+
if replaceable.is_a? Symbol
|
141
|
+
symbol_table[replaceable]
|
142
|
+
elsif replaceable.is_a?(Hash) || replaceable.is_a?(Array)
|
143
|
+
replaceable.to_a.inject(replaceable.class.new) do |acc, el|
|
144
|
+
if acc.is_a? Hash
|
145
|
+
acc[el[0]] = eval(el[1], symbol_table)
|
146
|
+
else
|
147
|
+
acc << eval(el, symbol_table)
|
148
|
+
end
|
149
|
+
|
150
|
+
acc
|
151
|
+
end
|
117
152
|
else
|
118
|
-
|
119
|
-
a[e.first] = symbols[e.last]
|
120
|
-
a
|
121
|
-
}).to_s(symbols, scope)
|
153
|
+
replaceable
|
122
154
|
end
|
123
155
|
end
|
124
156
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Stylish
|
2
|
+
|
3
|
+
class Percentage
|
4
|
+
PCTSTR = /-?(0\.)?\d+%/
|
5
|
+
|
6
|
+
def initialize(value)
|
7
|
+
value = value[0..-2]
|
8
|
+
|
9
|
+
if value =~ /^\d+$/
|
10
|
+
@number = value.to_i
|
11
|
+
else
|
12
|
+
@number = value.to_f
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s(symbols = {}, scope = "")
|
17
|
+
@number.to_s + "%"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.match?(value)
|
21
|
+
value =~ /^#{PCTSTR}$/
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Length
|
26
|
+
UNITS = [
|
27
|
+
# Relative length units
|
28
|
+
"em", "ex", "px",
|
29
|
+
# Absolute length units
|
30
|
+
"in", "cm", "mm", "pt", "pc"]
|
31
|
+
|
32
|
+
attr_reader :unit, :value
|
33
|
+
|
34
|
+
def initialize(value)
|
35
|
+
self.unit = value.match(/(#{UNITS * "|"})$/)[0]
|
36
|
+
self.value = value[0..-3]
|
37
|
+
end
|
38
|
+
|
39
|
+
def value=(value)
|
40
|
+
if value.is_a? Numeric
|
41
|
+
@value = value
|
42
|
+
elsif value =~ /^\d+$/
|
43
|
+
@value = value.to_i
|
44
|
+
elsif value =~ /^\d+\.\d+$/
|
45
|
+
@value = value.to_f
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def unit=(unit)
|
50
|
+
@unit = unit if UNITS.include? unit
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s(symbols = {}, scope = "")
|
54
|
+
self.value.to_s + self.unit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Position
|
59
|
+
HORIZONTAL = ["left", "center", "right"]
|
60
|
+
VERTICAL = ["top", "center", "bottom"]
|
61
|
+
|
62
|
+
attr_reader :x, :y
|
63
|
+
|
64
|
+
def initialize(xpos, ypos)
|
65
|
+
self.x = xpos || "center"
|
66
|
+
self.y = ypos || "center"
|
67
|
+
end
|
68
|
+
|
69
|
+
def x=(xpos)
|
70
|
+
if HORIZONTAL.include?(xpos) || xpos.to_i == 0
|
71
|
+
@x = xpos
|
72
|
+
elsif Percentage.match? xpos
|
73
|
+
@x = Percentage.new(xpos)
|
74
|
+
else
|
75
|
+
@x = Length.new(xpos)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def y=(ypos)
|
80
|
+
if VERTICAL.include?(ypos) || ypos.to_i == 0
|
81
|
+
@y = ypos
|
82
|
+
elsif Percentage.match? ypos
|
83
|
+
@y = Percentage.new(ypos)
|
84
|
+
else
|
85
|
+
@y = Length.new(ypos)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s(symbols = {}, scope = "")
|
90
|
+
@x.to_s + " " + @y.to_s
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/lib/stylish/tree.rb
CHANGED
@@ -41,14 +41,13 @@ module Stylish
|
|
41
41
|
include Formattable, Node
|
42
42
|
|
43
43
|
attr_reader :nodes
|
44
|
+
accept_format(/\s*/m, "\n")
|
44
45
|
|
45
46
|
def initialize(selector)
|
46
|
-
accept_format(/\s*/m, "\n")
|
47
|
-
|
48
47
|
@nodes = []
|
49
48
|
@scope = selector
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
# Return the child node at the given index.
|
53
52
|
def [](index)
|
54
53
|
@nodes[index]
|
@@ -89,7 +88,7 @@ module Stylish
|
|
89
88
|
|
90
89
|
@nodes.map {|node|
|
91
90
|
node.to_s(symbols, @scope.to_s(symbols, scope))
|
92
|
-
}.join(
|
91
|
+
}.join(self.class.format)
|
93
92
|
end
|
94
93
|
|
95
94
|
# Return the node's child nodes.
|
data/lib/stylish.rb
CHANGED
@@ -8,10 +8,8 @@ module Stylish
|
|
8
8
|
require STYLISH_PATH + 'formattable'
|
9
9
|
require STYLISH_PATH + 'tree'
|
10
10
|
require STYLISH_PATH + 'core'
|
11
|
-
require STYLISH_PATH + '
|
12
|
-
require STYLISH_PATH + '
|
13
|
-
require STYLISH_PATH + 'image'
|
14
|
-
require STYLISH_PATH + 'background'
|
11
|
+
require STYLISH_PATH + 'numeric'
|
12
|
+
require STYLISH_PATH + 'extended'
|
15
13
|
require STYLISH_PATH + 'color'
|
16
14
|
require STYLISH_PATH + 'generate'
|
17
15
|
end
|
data/test/background_test.rb
CHANGED
@@ -3,7 +3,7 @@ class BackgroundTest < Test::Unit::TestCase
|
|
3
3
|
def setup
|
4
4
|
@composite = Stylish::Background.new(:color => "#CCC",
|
5
5
|
:image => "images/test.png", :repeat => "no-repeat",
|
6
|
-
:position => "left", :attachment => "scroll")
|
6
|
+
:position => ["left", "top"], :attachment => "scroll")
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_valid_background_colors
|
@@ -22,7 +22,7 @@ class BackgroundTest < Test::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_multiple_background_images
|
25
|
-
bg = Stylish::Background.new :
|
25
|
+
bg = Stylish::Background.new :images =>
|
26
26
|
["flower.png", "ball.png", "grass.png"]
|
27
27
|
|
28
28
|
assert_equal(3, bg.image.length)
|
@@ -35,20 +35,27 @@ class BackgroundTest < Test::Unit::TestCase
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_multiple_background_repeats
|
38
|
-
bg = Stylish::Background.new :
|
38
|
+
bg = Stylish::Background.new :repeats => ["repeat-x", "repeat-y"]
|
39
39
|
|
40
40
|
assert_equal(2, bg.repeat.length)
|
41
41
|
assert_equal("background-repeat:repeat-x, repeat-y;", bg.to_s)
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_valid_background_positions
|
45
|
-
assert_equal(
|
46
|
-
assert_equal("
|
47
|
-
assert_equal("center", @composite.position[1])
|
45
|
+
assert_equal("left", @composite.position.x)
|
46
|
+
assert_equal("top", @composite.position.y)
|
48
47
|
end
|
49
48
|
|
50
|
-
def
|
49
|
+
def test_position_serialisation
|
50
|
+
positioned = Stylish::Background.new({:position => ["100%", 0]})
|
51
|
+
assert_equal("background-position:100% 0;", positioned.to_s)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_compression
|
51
55
|
assert(Stylish::Background.new(:compressed => true))
|
56
|
+
assert_equal(false, Stylish::Background.new(:compressed => "true").compressed)
|
57
|
+
assert_equal(false, Stylish::Background.new(:compressed => "false").compressed)
|
58
|
+
assert_nil(Stylish::Background.new(:compressed => nil).compressed)
|
52
59
|
end
|
53
60
|
|
54
61
|
def test_valid_background_attachments
|
@@ -58,7 +65,7 @@ class BackgroundTest < Test::Unit::TestCase
|
|
58
65
|
end
|
59
66
|
|
60
67
|
def test_multiple_attachments
|
61
|
-
glued = Stylish::Background.new :
|
68
|
+
glued = Stylish::Background.new :attachments => ["local", "fixed"]
|
62
69
|
|
63
70
|
assert_equal(2, glued.attachment.length)
|
64
71
|
assert_equal("background-attachment:local, fixed;", glued.to_s)
|
@@ -71,7 +78,7 @@ class BackgroundTest < Test::Unit::TestCase
|
|
71
78
|
end
|
72
79
|
|
73
80
|
def test_origins
|
74
|
-
original = Stylish::Background.new :
|
81
|
+
original = Stylish::Background.new :origins => ["border-box", "padding-box"]
|
75
82
|
|
76
83
|
assert_equal(2, original.origin.length)
|
77
84
|
assert_equal("background-origin:border-box, padding-box;", original.to_s)
|
@@ -83,31 +90,15 @@ class BackgroundTest < Test::Unit::TestCase
|
|
83
90
|
assert_equal("background-break:bounding-box;", broken.to_s)
|
84
91
|
end
|
85
92
|
|
86
|
-
def test_invalid_image_values
|
87
|
-
assert_nil(Stylish::Background.new(:image => []).image)
|
88
|
-
assert_nil(Stylish::Background.new(:image => {}).image)
|
89
|
-
end
|
90
|
-
|
91
93
|
def test_invalid_background_repeats
|
92
94
|
assert_nil(Stylish::Background.new(:repeat => 'maxim-gun').repeat)
|
93
95
|
end
|
94
96
|
|
95
|
-
def test_invalid_background_positions
|
96
|
-
assert_nil(Stylish::Background.new(:position => "green ideas").position)
|
97
|
-
assert_nil(Stylish::Background.new(:position => "top").position)
|
98
|
-
end
|
99
|
-
|
100
97
|
def test_invalid_background_attachments
|
101
98
|
assert_nil(Stylish::Background.new(:attachment => "static").attachment)
|
102
99
|
assert_nil(Stylish::Background.new(:attachment => "unhooked").attachment)
|
103
100
|
end
|
104
101
|
|
105
|
-
def test_invalid_compression
|
106
|
-
assert_nil(Stylish::Background.new(:compressed => "true").compressed)
|
107
|
-
assert_nil(Stylish::Background.new(:compressed => "false").compressed)
|
108
|
-
assert_nil(Stylish::Background.new(:compressed => nil).compressed)
|
109
|
-
end
|
110
|
-
|
111
102
|
def test_declaration_property
|
112
103
|
assert_equal(["background-color", "background-repeat"],
|
113
104
|
Stylish::Background.new(:color => "red", :repeat => "no-repeat").name)
|
data/test/formattable_test.rb
CHANGED
@@ -1,40 +1,21 @@
|
|
1
1
|
class FormattableTest < Test::Unit::TestCase
|
2
2
|
|
3
|
-
def setup
|
4
|
-
@selectors = Stylish::Selectors.new
|
5
|
-
@declaration = Stylish::Declaration.new("background-color", "#000")
|
6
|
-
@background = Stylish::Background.new("color" => "red")
|
7
|
-
end
|
8
|
-
|
9
3
|
def test_reading_default_formats
|
10
|
-
assert_equal(", ",
|
11
|
-
assert_equal("%s:%s;",
|
12
|
-
assert_equal("%s:%s;",
|
4
|
+
assert_equal(", ", Stylish::Selectors.format)
|
5
|
+
assert_equal("%s:%s;", Stylish::Declaration.format)
|
6
|
+
assert_equal("%s:%s;", Stylish::Background.format)
|
13
7
|
end
|
14
8
|
|
15
9
|
def test_setting_allowed_formats
|
16
10
|
assert_nothing_raised do
|
17
|
-
|
11
|
+
Stylish::Selectors.format = ",\n"
|
12
|
+
Stylish::Selectors.format = ", "
|
18
13
|
end
|
19
14
|
end
|
20
15
|
|
21
16
|
def test_setting_disallowed_formats
|
22
17
|
assert_raise ArgumentError do
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class ConfusedAboutFormatting
|
28
|
-
include Stylish::Formattable
|
29
|
-
|
30
|
-
def initialize
|
31
|
-
accept_format(/^\s*$/, "///")
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_class_definition_with_disallowed_format
|
36
|
-
assert_raise ArgumentError do
|
37
|
-
ConfusedAboutFormatting.new
|
18
|
+
Stylish::Selectors.format = "//"
|
38
19
|
end
|
39
20
|
end
|
40
21
|
end
|
data/test/generate_test.rb
CHANGED
@@ -77,4 +77,21 @@ class GenerateTest < Test::Unit::TestCase
|
|
77
77
|
assert_equal("A glorious comment!", style.comments[0].header)
|
78
78
|
assert_equal("An additional note.", style.comments[1].lines[0])
|
79
79
|
end
|
80
|
+
|
81
|
+
def test_complex_background
|
82
|
+
style = Stylish.generate do
|
83
|
+
div :background => {
|
84
|
+
:images => ["tl.png", "tr.png", "br.png", "bl.png"],
|
85
|
+
:positions => [
|
86
|
+
["left", "top"],
|
87
|
+
["right", "top"],
|
88
|
+
["right", "bottom"],
|
89
|
+
["left", :pos]]}
|
90
|
+
end
|
91
|
+
|
92
|
+
assert_equal("div {background-image:url('tl.png'), url('tr.png'), " +
|
93
|
+
"url('br.png'), url('bl.png'); " +
|
94
|
+
"background-position:left top, right top, right bottom, left bottom;}",
|
95
|
+
style.to_s({:pos => "bottom"}))
|
96
|
+
end
|
80
97
|
end
|
data/test/length_test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class LengthTest < Test::Unit::TestCase
|
2
|
+
|
3
|
+
def test_different_units
|
4
|
+
assert_equal("px", Stylish::Length.new("10px").unit)
|
5
|
+
end
|
6
|
+
|
7
|
+
def test_serialisation
|
8
|
+
length = Stylish::Length.new("5em")
|
9
|
+
assert_equal("5em", length.to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_accessors
|
13
|
+
length = Stylish::Length.new("30mm")
|
14
|
+
length.unit = "px"
|
15
|
+
length.value = 50
|
16
|
+
|
17
|
+
assert_equal("px", length.unit)
|
18
|
+
assert_equal(50, length.value)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class PositionTest < Test::Unit::TestCase
|
2
|
+
|
3
|
+
def setup
|
4
|
+
@pos = Stylish::Position.new(0, 0)
|
5
|
+
end
|
6
|
+
|
7
|
+
def test_percentage_positions
|
8
|
+
percentage = Stylish::Position.new("5%", "10%")
|
9
|
+
assert_equal("5%", percentage.x.to_s)
|
10
|
+
assert_equal("10%", percentage.y.to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_keyword_positions
|
14
|
+
keyed = Stylish::Position.new("left", "top")
|
15
|
+
assert_equal("left", keyed.x)
|
16
|
+
assert_equal("top", keyed.y)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_serialisation
|
20
|
+
assert_equal("0 0", @pos.to_s)
|
21
|
+
end
|
22
|
+
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.5
|
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-
|
12
|
+
date: 2009-05-03 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -27,13 +27,12 @@ files:
|
|
27
27
|
- Rakefile
|
28
28
|
- VERSION.yml
|
29
29
|
- lib/stylish.rb
|
30
|
-
- lib/stylish/background.rb
|
31
30
|
- lib/stylish/color.rb
|
32
31
|
- lib/stylish/core.rb
|
32
|
+
- lib/stylish/extended.rb
|
33
33
|
- lib/stylish/formattable.rb
|
34
34
|
- lib/stylish/generate.rb
|
35
|
-
- lib/stylish/
|
36
|
-
- lib/stylish/stylesheet.rb
|
35
|
+
- lib/stylish/numeric.rb
|
37
36
|
- lib/stylish/tree.rb
|
38
37
|
- test/background_test.rb
|
39
38
|
- test/color_test.rb
|
@@ -43,6 +42,8 @@ files:
|
|
43
42
|
- test/formattable_test.rb
|
44
43
|
- test/generate_test.rb
|
45
44
|
- test/image_test.rb
|
45
|
+
- test/length_test.rb
|
46
|
+
- test/position_test.rb
|
46
47
|
- test/rule_test.rb
|
47
48
|
- test/selector_test.rb
|
48
49
|
- test/selectors_test.rb
|
@@ -84,6 +85,8 @@ test_files:
|
|
84
85
|
- test/formattable_test.rb
|
85
86
|
- test/generate_test.rb
|
86
87
|
- test/image_test.rb
|
88
|
+
- test/length_test.rb
|
89
|
+
- test/position_test.rb
|
87
90
|
- test/rule_test.rb
|
88
91
|
- test/selector_test.rb
|
89
92
|
- test/selectors_test.rb
|
data/lib/stylish/image.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
module Stylish
|
2
|
-
|
3
|
-
# Instances of the Image class are used to represent paths to images,
|
4
|
-
# generally background images.
|
5
|
-
class Image
|
6
|
-
include Formattable
|
7
|
-
|
8
|
-
attr_accessor :path
|
9
|
-
|
10
|
-
# Image instances are serialised to URI values. The path to the image file
|
11
|
-
# can be surrounded by either single quotes, double quotes or neither;
|
12
|
-
# single quotes are the default in Stylish.
|
13
|
-
def initialize(path)
|
14
|
-
accept_format(/^url\(\s*('|")?%s\1\s*\)$/, "url('%s')")
|
15
|
-
@path = path
|
16
|
-
end
|
17
|
-
|
18
|
-
# Serialising Image objects to a string produces the URI values seen in
|
19
|
-
# background-image declarations, e.g.
|
20
|
-
#
|
21
|
-
# image = Image.new("test.png")
|
22
|
-
# image.to_s # => "url('test.png')"
|
23
|
-
#
|
24
|
-
# background = Stylish::Background.new(:image => "test.png")
|
25
|
-
# background.to_s # => "background-image:url('test.png');"
|
26
|
-
#
|
27
|
-
def to_s
|
28
|
-
sprintf(@format, path.to_s)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
data/lib/stylish/stylesheet.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Stylish
|
2
|
-
|
3
|
-
class Stylesheet < Tree::SelectorScope
|
4
|
-
|
5
|
-
# Stylesheets are pure aggregate objects; they can contain child nodes,
|
6
|
-
# but have no data of their own. Their initializer therefore accepts no
|
7
|
-
# arguments.
|
8
|
-
def initialize
|
9
|
-
accept_format(/\s*/m, "\n")
|
10
|
-
@nodes = []
|
11
|
-
end
|
12
|
-
|
13
|
-
# Stylesheets are the roots of selector trees.
|
14
|
-
def root?
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
# Recursively serialise the tree to a stylesheet.
|
19
|
-
def to_s(symbols = {})
|
20
|
-
return "" if @nodes.empty?
|
21
|
-
@nodes.map {|node| node.to_s(symbols) }.join(@format)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|