sass 3.2.0.alpha.74 → 3.2.0.alpha.75
Sign up to get free protection for your applications and to get access to all the features.
- data/REVISION +1 -1
- data/VERSION +1 -1
- data/lib/sass/css.rb +144 -48
- data/lib/sass/scss/parser.rb +2 -2
- data/lib/sass/selector/abstract_sequence.rb +11 -2
- data/lib/sass/selector/simple.rb +6 -0
- data/lib/sass/tree/node.rb +2 -2
- data/lib/sass/tree/visitors/check_nesting.rb +2 -2
- data/lib/sass/util.rb +9 -8
- data/test/sass/css2sass_test.rb +24 -0
- metadata +6 -6
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
b551f92303175e7651794dcf5a70f6148042bf69
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.0.alpha.
|
1
|
+
3.2.0.alpha.75
|
data/lib/sass/css.rb
CHANGED
@@ -77,14 +77,29 @@ module Sass
|
|
77
77
|
# @return [Tree::Node] The root node of the parsed tree
|
78
78
|
def build_tree
|
79
79
|
root = Sass::SCSS::CssParser.new(@template, @options[:filename]).parse
|
80
|
+
parse_selectors root
|
80
81
|
expand_commas root
|
82
|
+
nest_seqs root
|
81
83
|
parent_ref_rules root
|
82
|
-
remove_parent_refs root
|
83
84
|
flatten_rules root
|
84
85
|
fold_commas root
|
86
|
+
dump_selectors root
|
85
87
|
root
|
86
88
|
end
|
87
89
|
|
90
|
+
# Parse all the selectors in the document and assign them to
|
91
|
+
# {Sass::Tree::RuleNode#parsed_rules}.
|
92
|
+
#
|
93
|
+
# @param root [Tree::Node] The parent node
|
94
|
+
def parse_selectors(root)
|
95
|
+
root.children.each do |child|
|
96
|
+
next parse_selectors(child) if child.is_a?(Tree::DirectiveNode)
|
97
|
+
next unless child.is_a?(Tree::RuleNode)
|
98
|
+
parser = Sass::SCSS::CssParser.new(child.rule.first, child.filename, child.line)
|
99
|
+
child.parsed_rules = parser.parse_selector
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
88
103
|
# Transform
|
89
104
|
#
|
90
105
|
# foo, bar, baz
|
@@ -102,13 +117,14 @@ module Sass
|
|
102
117
|
# @param root [Tree::Node] The parent node
|
103
118
|
def expand_commas(root)
|
104
119
|
root.children.map! do |child|
|
105
|
-
|
120
|
+
# child.parsed_rules.members.size > 1 iff the rule contains a comma
|
121
|
+
unless child.is_a?(Tree::RuleNode) && child.parsed_rules.members.size > 1
|
106
122
|
expand_commas(child) if child.is_a?(Tree::DirectiveNode)
|
107
123
|
next child
|
108
124
|
end
|
109
|
-
child.
|
110
|
-
|
111
|
-
node =
|
125
|
+
child.parsed_rules.members.map do |seq|
|
126
|
+
node = Tree::RuleNode.new([])
|
127
|
+
node.parsed_rules = make_cseq(seq)
|
112
128
|
node.children = child.children
|
113
129
|
node
|
114
130
|
end
|
@@ -116,22 +132,7 @@ module Sass
|
|
116
132
|
root.children.flatten!
|
117
133
|
end
|
118
134
|
|
119
|
-
# Make rules use
|
120
|
-
#
|
121
|
-
# foo
|
122
|
-
# color: green
|
123
|
-
# foo.bar
|
124
|
-
# color: blue
|
125
|
-
#
|
126
|
-
# becomes
|
127
|
-
#
|
128
|
-
# foo
|
129
|
-
# color: green
|
130
|
-
# &.bar
|
131
|
-
# color: blue
|
132
|
-
#
|
133
|
-
# This has the side effect of nesting rules,
|
134
|
-
# so that
|
135
|
+
# Make rules use nesting so that
|
135
136
|
#
|
136
137
|
# foo
|
137
138
|
# color: green
|
@@ -144,28 +145,31 @@ module Sass
|
|
144
145
|
#
|
145
146
|
# foo
|
146
147
|
# color: green
|
147
|
-
#
|
148
|
+
# bar
|
148
149
|
# color: red
|
149
|
-
#
|
150
|
+
# baz
|
150
151
|
# color: blue
|
151
152
|
#
|
152
153
|
# @param root [Tree::Node] The parent node
|
153
|
-
def
|
154
|
+
def nest_seqs(root)
|
154
155
|
current_rule = nil
|
155
156
|
root.children.map! do |child|
|
156
157
|
unless child.is_a?(Tree::RuleNode)
|
157
|
-
|
158
|
+
nest_seqs(child) if child.is_a?(Tree::DirectiveNode)
|
158
159
|
next child
|
159
160
|
end
|
160
161
|
|
161
|
-
|
162
|
+
seq = first_seq(child)
|
163
|
+
seq.members.reject! {|sseq| sseq == "\n"}
|
164
|
+
first, rest = seq.members.first, seq.members[1..-1]
|
162
165
|
|
163
|
-
if current_rule.nil? || current_rule
|
164
|
-
current_rule = Tree::RuleNode.new([
|
166
|
+
if current_rule.nil? || first_sseq(current_rule) != first
|
167
|
+
current_rule = Tree::RuleNode.new([])
|
168
|
+
current_rule.parsed_rules = make_seq(first)
|
165
169
|
end
|
166
170
|
|
167
|
-
|
168
|
-
child.
|
171
|
+
unless rest.empty?
|
172
|
+
child.parsed_rules = make_seq(*rest)
|
169
173
|
current_rule << child
|
170
174
|
else
|
171
175
|
current_rule.children += child.children
|
@@ -176,32 +180,57 @@ module Sass
|
|
176
180
|
root.children.compact!
|
177
181
|
root.children.uniq!
|
178
182
|
|
179
|
-
root.children.each {
|
183
|
+
root.children.each {|v| nest_seqs(v)}
|
180
184
|
end
|
181
185
|
|
182
|
-
#
|
186
|
+
# Make rules use parent refs so that
|
183
187
|
#
|
184
188
|
# foo
|
185
|
-
#
|
186
|
-
#
|
189
|
+
# color: green
|
190
|
+
# foo.bar
|
191
|
+
# color: blue
|
187
192
|
#
|
188
193
|
# becomes
|
189
194
|
#
|
190
195
|
# foo
|
191
|
-
#
|
196
|
+
# color: green
|
197
|
+
# &.bar
|
192
198
|
# color: blue
|
193
199
|
#
|
194
200
|
# @param root [Tree::Node] The parent node
|
195
|
-
def
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
child
|
200
|
-
|
201
|
-
|
202
|
-
|
201
|
+
def parent_ref_rules(root)
|
202
|
+
current_rule = nil
|
203
|
+
root.children.map! do |child|
|
204
|
+
unless child.is_a?(Tree::RuleNode)
|
205
|
+
parent_ref_rules(child) if child.is_a?(Tree::DirectiveNode)
|
206
|
+
next child
|
207
|
+
end
|
208
|
+
|
209
|
+
sseq = first_sseq(child)
|
210
|
+
next child unless sseq.is_a?(Sass::Selector::SimpleSequence)
|
211
|
+
|
212
|
+
firsts, rest = [sseq.members.first], sseq.members[1..-1]
|
213
|
+
firsts.push rest.shift if firsts.first.is_a?(Sass::Selector::Parent)
|
214
|
+
|
215
|
+
if current_rule.nil? || first_sseq(current_rule).members != firsts
|
216
|
+
current_rule = Tree::RuleNode.new([])
|
217
|
+
current_rule.parsed_rules = make_sseq(*firsts)
|
218
|
+
end
|
219
|
+
|
220
|
+
unless rest.empty?
|
221
|
+
rest.unshift Sass::Selector::Parent.new
|
222
|
+
child.parsed_rules = make_sseq(*rest)
|
223
|
+
current_rule << child
|
224
|
+
else
|
225
|
+
current_rule.children += child.children
|
203
226
|
end
|
227
|
+
|
228
|
+
current_rule
|
204
229
|
end
|
230
|
+
root.children.compact!
|
231
|
+
root.children.uniq!
|
232
|
+
|
233
|
+
root.children.each {|v| parent_ref_rules(v)}
|
205
234
|
end
|
206
235
|
|
207
236
|
# Flatten rules so that
|
@@ -238,7 +267,7 @@ module Sass
|
|
238
267
|
end
|
239
268
|
end
|
240
269
|
|
241
|
-
# Flattens a single rule
|
270
|
+
# Flattens a single rule.
|
242
271
|
#
|
243
272
|
# @param rule [Tree::RuleNode] The candidate for flattening
|
244
273
|
# @see #flatten_rules
|
@@ -246,10 +275,10 @@ module Sass
|
|
246
275
|
while rule.children.size == 1 && rule.children.first.is_a?(Tree::RuleNode)
|
247
276
|
child = rule.children.first
|
248
277
|
|
249
|
-
if child.
|
250
|
-
rule.
|
278
|
+
if first_simple_sel(child).is_a?(Sass::Selector::Parent)
|
279
|
+
rule.parsed_rules = child.parsed_rules.resolve_parent_refs(rule.parsed_rules)
|
251
280
|
else
|
252
|
-
rule.
|
281
|
+
rule.parsed_rules = make_seq(first_sseq(rule), *first_seq(child).members)
|
253
282
|
end
|
254
283
|
|
255
284
|
rule.children = child.children
|
@@ -282,7 +311,7 @@ module Sass
|
|
282
311
|
end
|
283
312
|
|
284
313
|
if prev_rule && prev_rule.children == child.children
|
285
|
-
prev_rule.
|
314
|
+
prev_rule.parsed_rules.members << first_seq(child)
|
286
315
|
next nil
|
287
316
|
end
|
288
317
|
|
@@ -292,5 +321,72 @@ module Sass
|
|
292
321
|
end
|
293
322
|
root.children.compact!
|
294
323
|
end
|
324
|
+
|
325
|
+
# Dump all the parsed {Sass::Tree::RuleNode} selectors to strings.
|
326
|
+
#
|
327
|
+
# @param root [Tree::Node] The parent node
|
328
|
+
def dump_selectors(root)
|
329
|
+
root.children.each do |child|
|
330
|
+
next dump_selectors(child) if child.is_a?(Tree::DirectiveNode)
|
331
|
+
next unless child.is_a?(Tree::RuleNode)
|
332
|
+
child.rule = child.parsed_rules.to_s
|
333
|
+
dump_selectors(child)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Create a {Sass::Selector::CommaSequence}.
|
338
|
+
#
|
339
|
+
# @param seqs [Array<Sass::Selector::Sequence>]
|
340
|
+
# @return [Sass::Selector::CommaSequence]
|
341
|
+
def make_cseq(*seqs)
|
342
|
+
Sass::Selector::CommaSequence.new(seqs)
|
343
|
+
end
|
344
|
+
|
345
|
+
# Create a {Sass::Selector::CommaSequence} containing only a single
|
346
|
+
# {Sass::Selector::Sequence}.
|
347
|
+
#
|
348
|
+
# @param sseqs [Array<Sass::Selector::Sequence, String>]
|
349
|
+
# @return [Sass::Selector::CommaSequence]
|
350
|
+
def make_seq(*sseqs)
|
351
|
+
make_cseq(Sass::Selector::Sequence.new(sseqs))
|
352
|
+
end
|
353
|
+
|
354
|
+
# Create a {Sass::Selector::CommaSequence} containing only a single
|
355
|
+
# {Sass::Selector::Sequence} which in turn contains only a single
|
356
|
+
# {Sass::Selector::SimpleSequence}.
|
357
|
+
#
|
358
|
+
# @param sseqs [Array<Sass::Selector::Sequence, String>]
|
359
|
+
# @return [Sass::Selector::CommaSequence]
|
360
|
+
def make_sseq(*sseqs)
|
361
|
+
make_seq(Sass::Selector::SimpleSequence.new(sseqs))
|
362
|
+
end
|
363
|
+
|
364
|
+
# Return the first {Sass::Selector::Sequence} in a {Sass::Tree::RuleNode}.
|
365
|
+
#
|
366
|
+
# @param rule [Sass::Tree::RuleNode]
|
367
|
+
# @return [Sass::Selector::Sequence]
|
368
|
+
def first_seq(rule)
|
369
|
+
rule.parsed_rules.members.first
|
370
|
+
end
|
371
|
+
|
372
|
+
# Return the first {Sass::Selector::SimpleSequence} in a
|
373
|
+
# {Sass::Tree::RuleNode}.
|
374
|
+
#
|
375
|
+
# @param rule [Sass::Tree::RuleNode]
|
376
|
+
# @return [Sass::Selector::SimpleSequence, String]
|
377
|
+
def first_sseq(rule)
|
378
|
+
first_seq(rule).members.first
|
379
|
+
end
|
380
|
+
|
381
|
+
# Return the first {Sass::Selector::Simple} in a {Sass::Tree::RuleNode},
|
382
|
+
# unless the rule begins with a combinator.
|
383
|
+
#
|
384
|
+
# @param rule [Sass::Tree::RuleNode]
|
385
|
+
# @return [Sass::Selector::Simple?]
|
386
|
+
def first_simple_sel(rule)
|
387
|
+
sseq = first_sseq(rule)
|
388
|
+
return unless sseq.is_a?(Sass::Selector::SimpleSequence)
|
389
|
+
sseq.members.first
|
390
|
+
end
|
295
391
|
end
|
296
392
|
end
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -835,11 +835,11 @@ MESSAGE
|
|
835
835
|
@strs.pop
|
836
836
|
end
|
837
837
|
|
838
|
-
def str?
|
838
|
+
def str?
|
839
839
|
pos = @scanner.pos
|
840
840
|
line = @line
|
841
841
|
@strs.push ""
|
842
|
-
throw_error
|
842
|
+
throw_error {yield} && @strs.last
|
843
843
|
rescue Sass::SyntaxError => e
|
844
844
|
@scanner.pos = pos
|
845
845
|
@line = line
|
@@ -2,8 +2,9 @@ module Sass
|
|
2
2
|
module Selector
|
3
3
|
# The abstract parent class of the various selector sequence classes.
|
4
4
|
#
|
5
|
-
# All subclasses should implement a `members` method
|
6
|
-
#
|
5
|
+
# All subclasses should implement a `members` method that returns an array
|
6
|
+
# of object that respond to `#line=` and `#filename=`, as well as a `to_a`
|
7
|
+
# method that returns an array of strings and script nodes.
|
7
8
|
class AbstractSequence
|
8
9
|
# The line of the Sass template on which this selector was declared.
|
9
10
|
#
|
@@ -64,6 +65,14 @@ module Sass
|
|
64
65
|
@has_placeholder ||=
|
65
66
|
members.any? {|m| m.is_a?(AbstractSequence) ? m.has_placeholder? : m.is_a?(Placeholder)}
|
66
67
|
end
|
68
|
+
|
69
|
+
# Converts the selector into a string. This is the standard selector
|
70
|
+
# string, along with any SassScript interpolation that may exist.
|
71
|
+
#
|
72
|
+
# @return [String]
|
73
|
+
def to_s
|
74
|
+
to_a.map {|e| e.is_a?(Sass::Script::Node) ? "\#{#{e.to_sass}}" : e}.join
|
75
|
+
end
|
67
76
|
end
|
68
77
|
end
|
69
78
|
end
|
data/lib/sass/selector/simple.rb
CHANGED
@@ -33,6 +33,12 @@ module Sass
|
|
33
33
|
to_a.map {|e| e.is_a?(Sass::Script::Node) ? "\#{#{e.to_sass}}" : e}.join
|
34
34
|
end
|
35
35
|
|
36
|
+
# @see \{#inspect}
|
37
|
+
# @return [String]
|
38
|
+
def to_s
|
39
|
+
inspect
|
40
|
+
end
|
41
|
+
|
36
42
|
# Returns a hash code for this selector object.
|
37
43
|
#
|
38
44
|
# By default, this is based on the value of \{#to\_a},
|
data/lib/sass/tree/node.rb
CHANGED
@@ -159,9 +159,9 @@ module Sass
|
|
159
159
|
#
|
160
160
|
# @yield node
|
161
161
|
# @yieldparam node [Node] a node in the tree
|
162
|
-
def each
|
162
|
+
def each
|
163
163
|
yield self
|
164
|
-
children.each {|c| c.each
|
164
|
+
children.each {|c| c.each {|n| yield n}}
|
165
165
|
end
|
166
166
|
|
167
167
|
# Converts a node to Sass code that will generate it.
|
@@ -143,9 +143,9 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
143
143
|
return false
|
144
144
|
end
|
145
145
|
|
146
|
-
def try_send(method, *args
|
146
|
+
def try_send(method, *args)
|
147
147
|
return unless respond_to?(method)
|
148
|
-
send(method, *args
|
148
|
+
send(method, *args)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
data/lib/sass/util.rb
CHANGED
@@ -85,8 +85,9 @@ module Sass
|
|
85
85
|
# @return [Hash] The mapped hash
|
86
86
|
# @see #map_keys
|
87
87
|
# @see #map_vals
|
88
|
-
def map_hash(hash
|
89
|
-
|
88
|
+
def map_hash(hash)
|
89
|
+
# Using &block here completely hoses performance on 1.8.
|
90
|
+
to_hash(hash.map {|k, v| yield k, v})
|
90
91
|
end
|
91
92
|
|
92
93
|
# Computes the powerset of the given array.
|
@@ -211,11 +212,11 @@ module Sass
|
|
211
212
|
# @yieldreturn [Object, nil] If the two values register as equal,
|
212
213
|
# this will return the value to use in the LCS array.
|
213
214
|
# @return [Array] The LCS
|
214
|
-
def lcs(x, y
|
215
|
+
def lcs(x, y)
|
215
216
|
x = [nil, *x]
|
216
217
|
y = [nil, *y]
|
217
218
|
block ||= proc {|a, b| a == b && a}
|
218
|
-
lcs_backtrace(lcs_table(x, y,
|
219
|
+
lcs_backtrace(lcs_table(x, y) {|a, b| yield a, b}, x, y, x.size-1, y.size-1) {|a, b| yield a, b}
|
219
220
|
end
|
220
221
|
|
221
222
|
# Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
|
@@ -762,14 +763,14 @@ MSG
|
|
762
763
|
|
763
764
|
# Computes a single longest common subsequence for arrays x and y.
|
764
765
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
|
765
|
-
def lcs_backtrace(c, x, y, i, j
|
766
|
+
def lcs_backtrace(c, x, y, i, j)
|
766
767
|
return [] if i == 0 || j == 0
|
767
768
|
if v = yield(x[i], y[j])
|
768
|
-
return lcs_backtrace(c, x, y, i-1, j-1,
|
769
|
+
return lcs_backtrace(c, x, y, i-1, j-1) {|a, b| yield a, b} << v
|
769
770
|
end
|
770
771
|
|
771
|
-
return lcs_backtrace(c, x, y, i, j-1,
|
772
|
-
return lcs_backtrace(c, x, y, i-1, j,
|
772
|
+
return lcs_backtrace(c, x, y, i, j-1) {|a, b| yield a, b} if c[i][j-1] > c[i-1][j]
|
773
|
+
return lcs_backtrace(c, x, y, i-1, j) {|a, b| yield a, b}
|
773
774
|
end
|
774
775
|
end
|
775
776
|
end
|
data/test/sass/css2sass_test.rb
CHANGED
@@ -277,6 +277,30 @@ foo, , bar { a: b }
|
|
277
277
|
CSS
|
278
278
|
end
|
279
279
|
|
280
|
+
def test_selector_splitting
|
281
|
+
assert_equal(<<SASS, css2sass(<<CSS))
|
282
|
+
.foo >
|
283
|
+
.bar
|
284
|
+
a: b
|
285
|
+
.baz
|
286
|
+
c: d
|
287
|
+
SASS
|
288
|
+
.foo>.bar {a: b}
|
289
|
+
.foo>.baz {c: d}
|
290
|
+
CSS
|
291
|
+
|
292
|
+
assert_equal(<<SASS, css2sass(<<CSS))
|
293
|
+
.foo
|
294
|
+
&::bar
|
295
|
+
a: b
|
296
|
+
&::baz
|
297
|
+
c: d
|
298
|
+
SASS
|
299
|
+
.foo::bar {a: b}
|
300
|
+
.foo::baz {c: d}
|
301
|
+
CSS
|
302
|
+
end
|
303
|
+
|
280
304
|
# Error reporting
|
281
305
|
|
282
306
|
def test_error_reporting
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 592302987
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 2
|
9
9
|
- 0
|
10
10
|
- alpha
|
11
|
-
-
|
12
|
-
version: 3.2.0.alpha.
|
11
|
+
- 75
|
12
|
+
version: 3.2.0.alpha.75
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Nathan Weizenbaum
|
@@ -86,7 +86,7 @@ files:
|
|
86
86
|
- lib/sass/logger.rb
|
87
87
|
- lib/sass/logger/base.rb
|
88
88
|
- lib/sass/logger/log_level.rb
|
89
|
-
- lib/sass/
|
89
|
+
- lib/sass/util.rb
|
90
90
|
- lib/sass/plugin.rb
|
91
91
|
- lib/sass/plugin/compiler.rb
|
92
92
|
- lib/sass/plugin/configuration.rb
|
@@ -151,6 +151,7 @@ files:
|
|
151
151
|
- lib/sass/tree/root_node.rb
|
152
152
|
- lib/sass/tree/rule_node.rb
|
153
153
|
- lib/sass/tree/content_node.rb
|
154
|
+
- lib/sass/tree/trace_node.rb
|
154
155
|
- lib/sass/tree/variable_node.rb
|
155
156
|
- lib/sass/tree/visitors/base.rb
|
156
157
|
- lib/sass/tree/visitors/check_nesting.rb
|
@@ -162,8 +163,7 @@ files:
|
|
162
163
|
- lib/sass/tree/visitors/to_css.rb
|
163
164
|
- lib/sass/tree/warn_node.rb
|
164
165
|
- lib/sass/tree/while_node.rb
|
165
|
-
- lib/sass/
|
166
|
-
- lib/sass/util.rb
|
166
|
+
- lib/sass/media.rb
|
167
167
|
- lib/sass/util/multibyte_string_scanner.rb
|
168
168
|
- lib/sass/util/subset_map.rb
|
169
169
|
- lib/sass/version.rb
|