sass 3.3.14 → 3.4.0.rc.1

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.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +5 -5
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +0 -5
  10. data/lib/sass/css.rb +1 -3
  11. data/lib/sass/engine.rb +28 -39
  12. data/lib/sass/environment.rb +13 -17
  13. data/lib/sass/error.rb +6 -9
  14. data/lib/sass/exec.rb +5 -771
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +419 -0
  18. data/lib/sass/features.rb +6 -0
  19. data/lib/sass/importers.rb +0 -1
  20. data/lib/sass/importers/base.rb +5 -1
  21. data/lib/sass/importers/filesystem.rb +4 -21
  22. data/lib/sass/media.rb +1 -4
  23. data/lib/sass/plugin/compiler.rb +32 -136
  24. data/lib/sass/script/css_lexer.rb +1 -1
  25. data/lib/sass/script/functions.rb +363 -39
  26. data/lib/sass/script/lexer.rb +68 -50
  27. data/lib/sass/script/parser.rb +29 -14
  28. data/lib/sass/script/tree.rb +1 -0
  29. data/lib/sass/script/tree/funcall.rb +1 -1
  30. data/lib/sass/script/tree/interpolation.rb +19 -1
  31. data/lib/sass/script/tree/selector.rb +26 -0
  32. data/lib/sass/script/value.rb +0 -1
  33. data/lib/sass/script/value/bool.rb +0 -5
  34. data/lib/sass/script/value/color.rb +32 -12
  35. data/lib/sass/script/value/helpers.rb +107 -0
  36. data/lib/sass/script/value/list.rb +0 -15
  37. data/lib/sass/script/value/null.rb +0 -5
  38. data/lib/sass/script/value/number.rb +60 -14
  39. data/lib/sass/script/value/string.rb +53 -9
  40. data/lib/sass/scss/css_parser.rb +8 -2
  41. data/lib/sass/scss/parser.rb +175 -319
  42. data/lib/sass/scss/rx.rb +14 -5
  43. data/lib/sass/scss/static_parser.rb +298 -1
  44. data/lib/sass/selector.rb +56 -193
  45. data/lib/sass/selector/abstract_sequence.rb +28 -13
  46. data/lib/sass/selector/comma_sequence.rb +91 -12
  47. data/lib/sass/selector/pseudo.rb +256 -0
  48. data/lib/sass/selector/sequence.rb +99 -31
  49. data/lib/sass/selector/simple.rb +14 -25
  50. data/lib/sass/selector/simple_sequence.rb +101 -37
  51. data/lib/sass/shared.rb +1 -1
  52. data/lib/sass/source/map.rb +23 -9
  53. data/lib/sass/stack.rb +0 -6
  54. data/lib/sass/supports.rb +1 -1
  55. data/lib/sass/tree/at_root_node.rb +1 -0
  56. data/lib/sass/tree/directive_node.rb +7 -1
  57. data/lib/sass/tree/error_node.rb +18 -0
  58. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  59. data/lib/sass/tree/prop_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -6
  61. data/lib/sass/tree/visitors/check_nesting.rb +3 -4
  62. data/lib/sass/tree/visitors/convert.rb +8 -17
  63. data/lib/sass/tree/visitors/cssize.rb +12 -24
  64. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  65. data/lib/sass/tree/visitors/perform.rb +43 -28
  66. data/lib/sass/tree/visitors/set_options.rb +5 -0
  67. data/lib/sass/tree/visitors/to_css.rb +14 -13
  68. data/lib/sass/util.rb +94 -90
  69. data/test/sass/cache_test.rb +1 -1
  70. data/test/sass/callbacks_test.rb +1 -1
  71. data/test/sass/compiler_test.rb +5 -14
  72. data/test/sass/conversion_test.rb +47 -1
  73. data/test/sass/css2sass_test.rb +3 -3
  74. data/test/sass/encoding_test.rb +219 -0
  75. data/test/sass/engine_test.rb +128 -191
  76. data/test/sass/exec_test.rb +2 -2
  77. data/test/sass/extend_test.rb +234 -17
  78. data/test/sass/functions_test.rb +268 -213
  79. data/test/sass/importer_test.rb +31 -21
  80. data/test/sass/logger_test.rb +1 -1
  81. data/test/sass/more_results/more_import.css +1 -1
  82. data/test/sass/plugin_test.rb +12 -11
  83. data/test/sass/results/compact.css +1 -1
  84. data/test/sass/results/complex.css +4 -4
  85. data/test/sass/results/expanded.css +1 -1
  86. data/test/sass/results/import.css +1 -1
  87. data/test/sass/results/import_charset_ibm866.css +2 -2
  88. data/test/sass/results/mixins.css +17 -17
  89. data/test/sass/results/nested.css +1 -1
  90. data/test/sass/results/parent_ref.css +2 -2
  91. data/test/sass/results/script.css +3 -3
  92. data/test/sass/results/scss_import.css +1 -1
  93. data/test/sass/script_conversion_test.rb +7 -4
  94. data/test/sass/script_test.rb +202 -79
  95. data/test/sass/scss/css_test.rb +95 -25
  96. data/test/sass/scss/rx_test.rb +4 -4
  97. data/test/sass/scss/scss_test.rb +363 -19
  98. data/test/sass/source_map_test.rb +48 -41
  99. data/test/sass/superselector_test.rb +191 -0
  100. data/test/sass/templates/scss_import.scss +2 -1
  101. data/test/sass/test_helper.rb +1 -1
  102. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  103. data/test/sass/util/normalized_map_test.rb +1 -1
  104. data/test/sass/util/subset_map_test.rb +2 -2
  105. data/test/sass/util_test.rb +1 -1
  106. data/test/sass/value_helpers_test.rb +3 -3
  107. data/test/test_helper.rb +2 -2
  108. metadata +30 -7
  109. data/lib/sass/importers/deprecated_path.rb +0 -51
  110. data/lib/sass/script/value/deprecated_false.rb +0 -55
@@ -14,28 +14,18 @@ module Sass
14
14
  # @return [String, nil]
15
15
  attr_accessor :filename
16
16
 
17
- # Returns a representation of the node as an array of strings and
18
- # potentially {Sass::Script::Tree::Node}s (if there's interpolation in the
19
- # selector). When the interpolation is resolved and the strings are joined
20
- # together, this will be the string representation of this node.
21
- #
22
- # @return [Array<String, Sass::Script::Tree::Node>]
23
- def to_a
24
- Sass::Util.abstract(self)
25
- end
26
-
27
- # Returns a string representation of the node.
28
- # This is basically the selector string.
17
+ # @see #to_s
29
18
  #
30
19
  # @return [String]
31
20
  def inspect
32
- to_a.map {|e| e.is_a?(Sass::Script::Tree::Node) ? "\#{#{e.to_sass}}" : e}.join
21
+ to_s
33
22
  end
34
23
 
35
- # @see \{#inspect}
24
+ # Returns the selector string.
25
+ #
36
26
  # @return [String]
37
27
  def to_s
38
- inspect
28
+ Sass::Util.abstract(self)
39
29
  end
40
30
 
41
31
  # Returns a hash code for this selector object.
@@ -58,7 +48,7 @@ module Sass
58
48
  # @param other [Object] The object to test equality against
59
49
  # @return [Boolean] Whether or not this is equal to `other`
60
50
  def eql?(other)
61
- other.class == self.class && other.hash == hash && other.equality_key.eql?(equality_key)
51
+ other.class == self.class && other.hash == hash && other.equality_key == equality_key
62
52
  end
63
53
  alias_method :==, :eql?
64
54
 
@@ -83,10 +73,10 @@ module Sass
83
73
  return sels if sels.any? {|sel2| eql?(sel2)}
84
74
  sels_with_ix = Sass::Util.enum_with_index(sels)
85
75
  _, i =
86
- if is_a?(Pseudo) || is_a?(SelectorPseudoClass)
76
+ if is_a?(Pseudo)
87
77
  sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && (sels.last.type == :element)}
88
78
  else
89
- sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)}
79
+ sels_with_ix.find {|sel, _| sel.is_a?(Pseudo)}
90
80
  end
91
81
  return sels + [self] unless i
92
82
  sels[0...i] + [self] + sels[i..-1]
@@ -96,12 +86,11 @@ module Sass
96
86
 
97
87
  # Returns the key used for testing whether selectors are equal.
98
88
  #
99
- # This is based on \{#to\_a}, with adjacent strings merged so that
100
- # selectors constructed in different ways are considered equivalent.
89
+ # This is a cached version of \{#to\_s}.
101
90
  #
102
- # @return [Array<String, Sass::Script::Tree::Node>]
91
+ # @return [String]
103
92
  def equality_key
104
- @equality_key ||= Sass::Util.merge_adjacent_strings(to_a)
93
+ @equality_key ||= to_s
105
94
  end
106
95
 
107
96
  # Unifies two namespaces,
@@ -118,9 +107,9 @@ module Sass
118
107
  # could be found at all.
119
108
  # If the second value is `false`, the first should be ignored.
120
109
  def unify_namespaces(ns1, ns2)
121
- return nil, false unless ns1 == ns2 || ns1.nil? || ns1 == ['*'] || ns2.nil? || ns2 == ['*']
122
- return ns2, true if ns1 == ['*']
123
- return ns1, true if ns2 == ['*']
110
+ return nil, false unless ns1 == ns2 || ns1.nil? || ns1 == '*' || ns2.nil? || ns2 == '*'
111
+ return ns2, true if ns1 == '*'
112
+ return ns1, true if ns2 == '*'
124
113
  [ns1 || ns2, true]
125
114
  end
126
115
  end
@@ -43,11 +43,16 @@ module Sass
43
43
  end
44
44
 
45
45
  def pseudo_elements
46
- @pseudo_elements ||= (members - [base]).
47
- select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
46
+ @pseudo_elements ||= members.select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
48
47
  end
49
48
 
50
- # Returns the non-base, non-pseudo-class selectors in this sequence.
49
+ def selector_pseudo_classes
50
+ @selector_pseudo_classes ||= members.
51
+ select {|sel| sel.is_a?(Pseudo) && sel.type == :class && sel.selector}.
52
+ group_by {|sel| sel.normalized_name}
53
+ end
54
+
55
+ # Returns the non-base, non-pseudo-element selectors in this sequence.
51
56
  #
52
57
  # @return [Set<Simple>]
53
58
  def rest
@@ -86,18 +91,18 @@ module Sass
86
91
  return CommaSequence.new([Sequence.new([self])])
87
92
  end
88
93
 
89
- return super_cseq if @members.size == 1 && parent.suffix.empty?
94
+ return super_cseq if @members.size == 1 && parent.suffix.nil?
90
95
 
91
96
  CommaSequence.new(super_cseq.members.map do |super_seq|
92
97
  members = super_seq.members.dup
93
98
  newline = members.pop if members.last == "\n"
94
99
  unless members.last.is_a?(SimpleSequence)
95
100
  raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
96
- super_seq.to_a.join + '"')
101
+ super_seq.to_s + '"')
97
102
  end
98
103
 
99
104
  parent_sub = members.last.members
100
- unless parent.suffix.empty?
105
+ unless parent.suffix.nil?
101
106
  parent_sub = parent_sub.dup
102
107
  parent_sub[-1] = parent_sub.last.dup
103
108
  case parent_sub.last
@@ -108,17 +113,17 @@ module Sass
108
113
  parent_sub.last.name + parent.suffix,
109
114
  parent_sub.last.namespace)
110
115
  when Sass::Selector::Pseudo
111
- if parent_sub.last.arg
116
+ if parent_sub.last.arg || parent_sub.last.selector
112
117
  raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
113
- super_seq.to_a.join + '"')
118
+ super_seq.to_s + '"')
114
119
  end
115
- parent_sub[-1] = parent_sub.last.class.new(
120
+ parent_sub[-1] = Sass::Selector::Pseudo.new(
116
121
  parent_sub.last.type,
117
122
  parent_sub.last.name + parent.suffix,
118
- nil)
123
+ nil, nil)
119
124
  else
120
125
  raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
121
- super_seq.to_a.join + '"')
126
+ super_seq.to_s + '"')
122
127
  end
123
128
  end
124
129
 
@@ -131,16 +136,35 @@ module Sass
131
136
  # Non-destructively extends this selector with the extensions specified in a hash
132
137
  # (which should come from {Sass::Tree::Visitors::Cssize}).
133
138
  #
134
- # @overload do_extend(extends, parent_directives)
135
- # @param extends [{Selector::Simple =>
136
- # Sass::Tree::Visitors::Cssize::Extend}]
137
- # The extensions to perform on this selector
138
- # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
139
- # The directives containing this selector.
139
+ # @param extends [{Selector::Simple =>
140
+ # Sass::Tree::Visitors::Cssize::Extend}]
141
+ # The extensions to perform on this selector
142
+ # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
143
+ # The directives containing this selector.
144
+ # @param seen [Set<Array<Selector::Simple>>]
145
+ # The set of simple sequences that are currently being replaced.
146
+ # @param original [Boolean]
147
+ # Whether this is the original selector being extended, as opposed to
148
+ # the result of a previous extension that's being re-extended.
140
149
  # @return [Array<Sequence>] A list of selectors generated
141
150
  # by extending this selector with `extends`.
142
151
  # @see CommaSequence#do_extend
143
- def do_extend(extends, parent_directives, seen = Set.new)
152
+ def do_extend(extends, parent_directives, replace, seen)
153
+ seen_with_pseudo_selectors = seen.dup
154
+
155
+ modified_original = false
156
+ members = Sass::Util.enum_with_index(self.members).map do |sel, i|
157
+ next sel unless sel.is_a?(Pseudo) && sel.selector
158
+ next sel if seen.include?([sel])
159
+ extended = sel.selector.do_extend(extends, parent_directives, replace, seen, !:original)
160
+ next sel if extended == sel.selector
161
+ extended.members.reject! {|seq| seq.has_placeholder?}
162
+ modified_original = true
163
+ result = sel.with_selector(extended)
164
+ seen_with_pseudo_selectors << [result]
165
+ result
166
+ end
167
+
144
168
  groups = Sass::Util.group_by_to_a(extends[members.to_set]) {|ex| ex.extender}
145
169
  groups.map! do |seq, group|
146
170
  sels = group.map {|e| e.target}.flatten
@@ -149,7 +173,7 @@ module Sass
149
173
 
150
174
  self_without_sel = Sass::Util.array_minus(members, sels)
151
175
  group.each {|e| e.result = :failed_to_unify unless e.result == :succeeded}
152
- unified = seq.members.last.unify(self_without_sel, subject?)
176
+ unified = seq.members.last.unify(SimpleSequence.new(self_without_sel, subject?))
153
177
  next unless unified
154
178
  group.each {|e| e.result = :succeeded}
155
179
  group.each {|e| check_directives_match!(e, parent_directives)}
@@ -159,19 +183,30 @@ module Sass
159
183
  end
160
184
  groups.compact!
161
185
  groups.map! do |sels, seq|
162
- seen.include?(sels) ? [] : seq.do_extend(extends, parent_directives, seen + [sels])
186
+ next [] if seen.include?(sels)
187
+ seq.do_extend(
188
+ extends, parent_directives, !:replace, seen_with_pseudo_selectors + [sels], !:original)
163
189
  end
164
190
  groups.flatten!
191
+
192
+ if modified_original || !replace || groups.empty?
193
+ # First Law of Extend: the result of extending a selector should
194
+ # (almost) always contain the base selector.
195
+ #
196
+ # See https://github.com/nex3/sass/issues/324.
197
+ original = Sequence.new([SimpleSequence.new(members, @subject, source_range)])
198
+ original.add_sources! sources
199
+ groups.unshift original
200
+ end
165
201
  groups.uniq!
166
202
  groups
167
203
  end
168
204
 
169
- # Unifies this selector with another {SimpleSequence}'s
170
- # {SimpleSequence#members members array}, returning another `SimpleSequence`
171
- # that matches both this selector and the input selector.
205
+ # Unifies this selector with another {SimpleSequence}, returning
206
+ # another `SimpleSequence` that is a subselector of both input
207
+ # selectors.
172
208
  #
173
- # @param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array}
174
- # @param other_subject [Boolean] Whether the other {SimpleSequence} being merged is a subject.
209
+ # @param other [SimpleSequence]
175
210
  # @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector,
176
211
  # or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
177
212
  # @raise [Sass::SyntaxError] If this selector cannot be unified.
@@ -180,13 +215,13 @@ module Sass
180
215
  # Since these selectors should be resolved
181
216
  # by the time extension and unification happen,
182
217
  # this exception will only ever be raised as a result of programmer error
183
- def unify(sels, other_subject)
184
- sseq = members.inject(sels) do |member, sel|
218
+ def unify(other)
219
+ sseq = members.inject(other.members) do |member, sel|
185
220
  return unless member
186
221
  sel.unify(member)
187
222
  end
188
223
  return unless sseq
189
- SimpleSequence.new(sseq, other_subject || subject?)
224
+ SimpleSequence.new(sseq, other.subject? || subject?)
190
225
  end
191
226
 
192
227
  # Returns whether or not this selector matches all elements
@@ -195,17 +230,44 @@ module Sass
195
230
  # @example
196
231
  # (.foo).superselector?(.foo.bar) #=> true
197
232
  # (.foo).superselector?(.bar) #=> false
198
- # @param sseq [SimpleSequence]
233
+ # @param their_sseq [SimpleSequence]
234
+ # @param parents [Array<SimpleSequence, String>] The parent selectors of `their_sseq`, if any.
199
235
  # @return [Boolean]
200
- def superselector?(sseq)
201
- (base.nil? || base.eql?(sseq.base)) &&
202
- pseudo_elements.eql?(sseq.pseudo_elements) &&
203
- rest.subset?(sseq.rest)
236
+ def superselector?(their_sseq, parents = [])
237
+ return false unless base.nil? || base.eql?(their_sseq.base)
238
+ return false unless pseudo_elements.eql?(their_sseq.pseudo_elements)
239
+ our_spcs = selector_pseudo_classes
240
+ their_spcs = their_sseq.selector_pseudo_classes
241
+
242
+ # Some psuedo-selectors can be subselectors of non-pseudo selectors.
243
+ # Pull those out here so we can efficiently check against them below.
244
+ their_subselector_pseudos = %w[matches any nth-child nth-last-child].
245
+ map {|name| their_spcs[name] || []}.flatten
246
+
247
+ # If `self`'s non-pseudo simple selectors aren't a subset of `their_sseq`'s,
248
+ # it's definitely not a superselector. This also considers being matched
249
+ # by `:matches` or `:any`.
250
+ return false unless rest.all? do |our_sel|
251
+ next true if our_sel.is_a?(Pseudo) && our_sel.selector
252
+ next true if their_sseq.rest.include?(our_sel)
253
+ their_subselector_pseudos.any? do |their_pseudo|
254
+ their_pseudo.selector.members.all? do |their_seq|
255
+ next false unless their_seq.members.length == 1
256
+ their_sseq = their_seq.members.first
257
+ next false unless their_sseq.is_a?(SimpleSequence)
258
+ their_sseq.rest.include?(our_sel)
259
+ end
260
+ end
261
+ end
262
+
263
+ our_spcs.all? do |name, pseudos|
264
+ pseudos.all? {|pseudo| pseudo.superselector?(their_sseq, parents)}
265
+ end
204
266
  end
205
267
 
206
- # @see Simple#to_a
207
- def to_a
208
- res = @members.map {|sel| sel.to_a}.flatten
268
+ # @see Simple#to_s
269
+ def to_s
270
+ res = @members.join
209
271
  res << '!' if subject?
210
272
  res
211
273
  end
@@ -215,7 +277,9 @@ module Sass
215
277
  #
216
278
  # @return [String]
217
279
  def inspect
218
- members.map {|m| m.inspect}.join
280
+ res = members.map {|m| m.inspect}.join
281
+ res << '!' if subject?
282
+ res
219
283
  end
220
284
 
221
285
  # Return a copy of this simple sequence with `sources` merged into the
@@ -44,7 +44,7 @@ module Sass
44
44
  str << scanner.matched
45
45
  count += 1 if scanner.matched[-1] == start
46
46
  count -= 1 if scanner.matched[-1] == finish
47
- return [str, scanner.rest] if count == 0
47
+ return [str.strip, scanner.rest] if count == 0
48
48
  end
49
49
  end
50
50
 
@@ -68,12 +68,6 @@ module Sass::Source
68
68
  # it will be inferred from `:css_path` and `:sourcemap_path` using the
69
69
  # assumption that the local file system has the same layout as the server.
70
70
  #
71
- # If any source stylesheets use the default filesystem importer, sourcemap
72
- # generation will fail unless the `:sourcemap_path` option is specified.
73
- # The layout of the local file system is assumed to be the same as the
74
- # layout of the server for the purposes of linking to source stylesheets
75
- # that use the filesystem importer.
76
- #
77
71
  # Regardless of which options are passed to this method, source stylesheets
78
72
  # that are imported using a non-default importer will only be linked to in
79
73
  # the source map if their importers implement
@@ -85,6 +79,8 @@ module Sass::Source
85
79
  # The local path of the CSS output file.
86
80
  # @option options :sourcemap_path [String]
87
81
  # The (eventual) local path of the sourcemap file.
82
+ # @option options :type [Symbol]
83
+ # `:auto` (default), `:file`, or `:inline`.
88
84
  # @return [String] The JSON string.
89
85
  # @raise [ArgumentError] If neither `:css_uri` nor `:css_path` and
90
86
  # `:sourcemap_path` are specified.
@@ -106,6 +102,7 @@ module Sass::Source
106
102
 
107
103
  source_uri_to_id = {}
108
104
  id_to_source_uri = {}
105
+ id_to_contents = {} if options[:type] == :inline
109
106
  next_source_id = 0
110
107
  line_data = []
111
108
  segment_data_for_line = []
@@ -119,9 +116,15 @@ module Sass::Source
119
116
 
120
117
  @data.each do |m|
121
118
  file, importer = m.input.file, m.input.importer
122
- source_uri = importer &&
123
- importer.public_url(file, sourcemap_path && sourcemap_path.dirname.to_s)
124
- next unless source_uri
119
+
120
+ if options[:type] == :inline
121
+ source_uri = file
122
+ else
123
+ sourcemap_dir = sourcemap_path && sourcemap_path.dirname.to_s
124
+ sourcemap_dir = nil if options[:type] == :file
125
+ source_uri = importer && importer.public_url(file, sourcemap_dir)
126
+ next unless source_uri
127
+ end
125
128
 
126
129
  current_source_id = source_uri_to_id[source_uri]
127
130
  unless current_source_id
@@ -130,6 +133,11 @@ module Sass::Source
130
133
 
131
134
  source_uri_to_id[source_uri] = current_source_id
132
135
  id_to_source_uri[current_source_id] = source_uri
136
+
137
+ if options[:type] == :inline
138
+ id_to_contents[current_source_id] =
139
+ importer.find(file, {}).instance_variable_get('@template')
140
+ end
133
141
  end
134
142
 
135
143
  [
@@ -174,6 +182,12 @@ module Sass::Source
174
182
  source_names = []
175
183
  (0...next_source_id).each {|id| source_names.push(id_to_source_uri[id].to_s)}
176
184
  write_json_field(result, "sources", source_names)
185
+
186
+ if options[:type] == :inline
187
+ write_json_field(result, "sourcesContent",
188
+ (0...next_source_id).map {|id| id_to_contents[id]})
189
+ end
190
+
177
191
  write_json_field(result, "names", [])
178
192
  write_json_field(result, "file", css_uri)
179
193
 
@@ -107,12 +107,6 @@ module Sass
107
107
  end.join("\n")
108
108
  end
109
109
 
110
- def deep_copy
111
- stack = Stack.new
112
- stack.frames.replace frames
113
- stack
114
- end
115
-
116
110
  private
117
111
 
118
112
  def with_frame(filename, line, type, name = nil)
@@ -212,7 +212,7 @@ module Sass::Supports
212
212
  end
213
213
 
214
214
  def to_src(options)
215
- "\#{#{@value.to_sass(options)}}"
215
+ @value.to_sass(options)
216
216
  end
217
217
 
218
218
  def deep_copy
@@ -70,6 +70,7 @@ module Sass
70
70
  # @return [Boolean]
71
71
  def exclude_node?(node)
72
72
  return exclude?(node.name.gsub(/^@/, '')) if node.is_a?(Sass::Tree::DirectiveNode)
73
+ return exclude?('keyframes') if node.is_a?(Sass::Tree::KeyframeRuleNode)
73
74
  exclude?('rule') && node.is_a?(Sass::Tree::RuleNode)
74
75
  end
75
76
 
@@ -43,7 +43,13 @@ module Sass::Tree
43
43
 
44
44
  # @return [String] The name of the directive, including `@`.
45
45
  def name
46
- value.first.gsub(/ .*$/, '')
46
+ @name ||= value.first.gsub(/ .*$/, '')
47
+ end
48
+
49
+ # Strips out any vendor prefixes and downcases the directive name.
50
+ # @return [String] The normalized name of the directive.
51
+ def normalized_name
52
+ @normalized_name ||= name.gsub(/^(@)(?:-[a-zA-Z0-9]+-)?/, '\1').downcase
47
53
  end
48
54
 
49
55
  def bubbles?
@@ -0,0 +1,18 @@
1
+ module Sass
2
+ module Tree
3
+ # A dynamic node representing a Sass `@error` statement.
4
+ #
5
+ # @see Sass::Tree
6
+ class ErrorNode < Node
7
+ # The expression to print.
8
+ # @return [Script::Tree::Node]
9
+ attr_accessor :expr
10
+
11
+ # @param expr [Script::Tree::Node] The expression to print
12
+ def initialize(expr)
13
+ @expr = expr
14
+ super()
15
+ end
16
+ end
17
+ end
18
+ end