oreorenasass 3.4.4 → 3.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +50 -70
  4. data/Rakefile +5 -26
  5. data/VERSION +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 +12 -19
  10. data/lib/sass/cache_stores/base.rb +2 -2
  11. data/lib/sass/cache_stores/chain.rb +1 -2
  12. data/lib/sass/cache_stores/filesystem.rb +5 -1
  13. data/lib/sass/cache_stores/memory.rb +1 -1
  14. data/lib/sass/cache_stores/null.rb +2 -2
  15. data/lib/sass/callbacks.rb +0 -1
  16. data/lib/sass/css.rb +13 -11
  17. data/lib/sass/engine.rb +173 -424
  18. data/lib/sass/environment.rb +58 -148
  19. data/lib/sass/error.rb +14 -11
  20. data/lib/sass/exec.rb +703 -5
  21. data/lib/sass/importers/base.rb +6 -49
  22. data/lib/sass/importers/filesystem.rb +19 -44
  23. data/lib/sass/logger.rb +4 -1
  24. data/lib/sass/logger/base.rb +4 -2
  25. data/lib/sass/logger/log_level.rb +7 -3
  26. data/lib/sass/media.rb +23 -20
  27. data/lib/sass/plugin.rb +7 -7
  28. data/lib/sass/plugin/compiler.rb +145 -304
  29. data/lib/sass/plugin/configuration.rb +23 -18
  30. data/lib/sass/plugin/merb.rb +1 -1
  31. data/lib/sass/plugin/staleness_checker.rb +3 -3
  32. data/lib/sass/repl.rb +3 -3
  33. data/lib/sass/script.rb +8 -35
  34. data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
  35. data/lib/sass/script/bool.rb +18 -0
  36. data/lib/sass/script/color.rb +606 -0
  37. data/lib/sass/script/css_lexer.rb +4 -8
  38. data/lib/sass/script/css_parser.rb +2 -5
  39. data/lib/sass/script/funcall.rb +245 -0
  40. data/lib/sass/script/functions.rb +408 -1491
  41. data/lib/sass/script/interpolation.rb +79 -0
  42. data/lib/sass/script/lexer.rb +68 -172
  43. data/lib/sass/script/list.rb +85 -0
  44. data/lib/sass/script/literal.rb +221 -0
  45. data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
  46. data/lib/sass/script/{value/null.rb → null.rb} +7 -14
  47. data/lib/sass/script/{value/number.rb → number.rb} +75 -152
  48. data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
  49. data/lib/sass/script/parser.rb +110 -245
  50. data/lib/sass/script/string.rb +51 -0
  51. data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
  52. data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
  53. data/lib/sass/script/variable.rb +58 -0
  54. data/lib/sass/scss/css_parser.rb +3 -9
  55. data/lib/sass/scss/parser.rb +421 -450
  56. data/lib/sass/scss/rx.rb +11 -19
  57. data/lib/sass/scss/static_parser.rb +7 -321
  58. data/lib/sass/selector.rb +194 -68
  59. data/lib/sass/selector/abstract_sequence.rb +14 -29
  60. data/lib/sass/selector/comma_sequence.rb +25 -108
  61. data/lib/sass/selector/sequence.rb +66 -159
  62. data/lib/sass/selector/simple.rb +25 -23
  63. data/lib/sass/selector/simple_sequence.rb +63 -173
  64. data/lib/sass/shared.rb +1 -1
  65. data/lib/sass/supports.rb +15 -13
  66. data/lib/sass/tree/charset_node.rb +1 -1
  67. data/lib/sass/tree/comment_node.rb +3 -3
  68. data/lib/sass/tree/css_import_node.rb +11 -11
  69. data/lib/sass/tree/debug_node.rb +2 -2
  70. data/lib/sass/tree/directive_node.rb +4 -21
  71. data/lib/sass/tree/each_node.rb +8 -8
  72. data/lib/sass/tree/extend_node.rb +7 -14
  73. data/lib/sass/tree/for_node.rb +4 -4
  74. data/lib/sass/tree/function_node.rb +4 -9
  75. data/lib/sass/tree/if_node.rb +1 -1
  76. data/lib/sass/tree/import_node.rb +5 -4
  77. data/lib/sass/tree/media_node.rb +14 -4
  78. data/lib/sass/tree/mixin_def_node.rb +4 -4
  79. data/lib/sass/tree/mixin_node.rb +8 -21
  80. data/lib/sass/tree/node.rb +12 -54
  81. data/lib/sass/tree/prop_node.rb +20 -39
  82. data/lib/sass/tree/return_node.rb +2 -3
  83. data/lib/sass/tree/root_node.rb +3 -19
  84. data/lib/sass/tree/rule_node.rb +22 -35
  85. data/lib/sass/tree/supports_node.rb +13 -0
  86. data/lib/sass/tree/trace_node.rb +1 -2
  87. data/lib/sass/tree/variable_node.rb +3 -9
  88. data/lib/sass/tree/visitors/base.rb +8 -5
  89. data/lib/sass/tree/visitors/check_nesting.rb +19 -49
  90. data/lib/sass/tree/visitors/convert.rb +56 -74
  91. data/lib/sass/tree/visitors/cssize.rb +74 -202
  92. data/lib/sass/tree/visitors/deep_copy.rb +5 -10
  93. data/lib/sass/tree/visitors/extend.rb +7 -7
  94. data/lib/sass/tree/visitors/perform.rb +185 -278
  95. data/lib/sass/tree/visitors/set_options.rb +6 -20
  96. data/lib/sass/tree/visitors/to_css.rb +81 -234
  97. data/lib/sass/tree/warn_node.rb +2 -2
  98. data/lib/sass/tree/while_node.rb +2 -2
  99. data/lib/sass/util.rb +152 -522
  100. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  101. data/lib/sass/util/subset_map.rb +3 -4
  102. data/lib/sass/util/test.rb +1 -0
  103. data/lib/sass/version.rb +22 -20
  104. data/test/Gemfile +3 -0
  105. data/test/Gemfile.lock +10 -0
  106. data/test/sass/cache_test.rb +20 -62
  107. data/test/sass/callbacks_test.rb +1 -1
  108. data/test/sass/conversion_test.rb +2 -296
  109. data/test/sass/css2sass_test.rb +4 -23
  110. data/test/sass/engine_test.rb +354 -411
  111. data/test/sass/exec_test.rb +2 -2
  112. data/test/sass/extend_test.rb +145 -324
  113. data/test/sass/functions_test.rb +86 -873
  114. data/test/sass/importer_test.rb +21 -241
  115. data/test/sass/logger_test.rb +1 -1
  116. data/test/sass/more_results/more_import.css +1 -1
  117. data/test/sass/plugin_test.rb +26 -16
  118. data/test/sass/results/compact.css +1 -1
  119. data/test/sass/results/complex.css +4 -4
  120. data/test/sass/results/expanded.css +1 -1
  121. data/test/sass/results/import.css +1 -1
  122. data/test/sass/results/import_charset_ibm866.css +2 -2
  123. data/test/sass/results/mixins.css +17 -17
  124. data/test/sass/results/nested.css +1 -1
  125. data/test/sass/results/parent_ref.css +2 -2
  126. data/test/sass/results/script.css +3 -3
  127. data/test/sass/results/scss_import.css +1 -1
  128. data/test/sass/script_conversion_test.rb +7 -36
  129. data/test/sass/script_test.rb +53 -485
  130. data/test/sass/scss/css_test.rb +28 -143
  131. data/test/sass/scss/rx_test.rb +4 -4
  132. data/test/sass/scss/scss_test.rb +325 -2119
  133. data/test/sass/templates/scss_import.scss +1 -2
  134. data/test/sass/test_helper.rb +1 -1
  135. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  136. data/test/sass/util/subset_map_test.rb +2 -2
  137. data/test/sass/util_test.rb +1 -86
  138. data/test/test_helper.rb +8 -37
  139. metadata +19 -66
  140. data/lib/sass/exec/base.rb +0 -187
  141. data/lib/sass/exec/sass_convert.rb +0 -264
  142. data/lib/sass/exec/sass_scss.rb +0 -424
  143. data/lib/sass/features.rb +0 -47
  144. data/lib/sass/script/tree.rb +0 -16
  145. data/lib/sass/script/tree/funcall.rb +0 -306
  146. data/lib/sass/script/tree/interpolation.rb +0 -118
  147. data/lib/sass/script/tree/list_literal.rb +0 -77
  148. data/lib/sass/script/tree/literal.rb +0 -45
  149. data/lib/sass/script/tree/map_literal.rb +0 -64
  150. data/lib/sass/script/tree/selector.rb +0 -26
  151. data/lib/sass/script/tree/variable.rb +0 -57
  152. data/lib/sass/script/value.rb +0 -11
  153. data/lib/sass/script/value/base.rb +0 -240
  154. data/lib/sass/script/value/bool.rb +0 -35
  155. data/lib/sass/script/value/color.rb +0 -680
  156. data/lib/sass/script/value/helpers.rb +0 -262
  157. data/lib/sass/script/value/list.rb +0 -113
  158. data/lib/sass/script/value/map.rb +0 -70
  159. data/lib/sass/script/value/string.rb +0 -97
  160. data/lib/sass/selector/pseudo.rb +0 -256
  161. data/lib/sass/source/map.rb +0 -210
  162. data/lib/sass/source/position.rb +0 -39
  163. data/lib/sass/source/range.rb +0 -41
  164. data/lib/sass/stack.rb +0 -120
  165. data/lib/sass/tree/at_root_node.rb +0 -83
  166. data/lib/sass/tree/error_node.rb +0 -18
  167. data/lib/sass/tree/keyframe_rule_node.rb +0 -15
  168. data/lib/sass/util/cross_platform_random.rb +0 -19
  169. data/lib/sass/util/normalized_map.rb +0 -130
  170. data/lib/sass/util/ordered_hash.rb +0 -192
  171. data/test/sass/compiler_test.rb +0 -232
  172. data/test/sass/encoding_test.rb +0 -219
  173. data/test/sass/source_map_test.rb +0 -977
  174. data/test/sass/superselector_test.rb +0 -191
  175. data/test/sass/util/normalized_map_test.rb +0 -51
  176. data/test/sass/value_helpers_test.rb +0 -179
@@ -15,28 +15,18 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
15
15
  super
16
16
  end
17
17
 
18
- def visit_comment(node)
19
- node.value.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
20
- yield
21
- end
22
-
23
18
  def visit_debug(node)
24
19
  node.expr.options = @options
25
20
  yield
26
21
  end
27
22
 
28
- def visit_error(node)
29
- node.expr.options = @options
30
- yield
31
- end
32
-
33
23
  def visit_each(node)
34
24
  node.list.options = @options
35
25
  yield
36
26
  end
37
27
 
38
28
  def visit_extend(node)
39
- node.selector.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
29
+ node.selector.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
40
30
  yield
41
31
  end
42
32
 
@@ -51,7 +41,6 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
51
41
  k.options = @options
52
42
  v.options = @options if v
53
43
  end
54
- node.splat.options = @options if node.splat
55
44
  yield
56
45
  end
57
46
 
@@ -74,20 +63,17 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
74
63
  k.options = @options
75
64
  v.options = @options if v
76
65
  end
77
- node.splat.options = @options if node.splat
78
66
  yield
79
67
  end
80
68
 
81
69
  def visit_mixin(node)
82
70
  node.args.each {|a| a.options = @options}
83
71
  node.keywords.each {|k, v| v.options = @options}
84
- node.splat.options = @options if node.splat
85
- node.kwarg_splat.options = @options if node.kwarg_splat
86
72
  yield
87
73
  end
88
74
 
89
75
  def visit_prop(node)
90
- node.name.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
76
+ node.name.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
91
77
  node.value.options = @options
92
78
  yield
93
79
  end
@@ -98,7 +84,7 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
98
84
  end
99
85
 
100
86
  def visit_rule(node)
101
- node.rule.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
87
+ node.rule.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
102
88
  yield
103
89
  end
104
90
 
@@ -118,17 +104,17 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
118
104
  end
119
105
 
120
106
  def visit_directive(node)
121
- node.value.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
107
+ node.value.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
122
108
  yield
123
109
  end
124
110
 
125
111
  def visit_media(node)
126
- node.query.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
112
+ node.query.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
127
113
  yield
128
114
  end
129
115
 
130
116
  def visit_cssimport(node)
131
- node.query.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)} if node.query
117
+ node.query.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)} if node.query
132
118
  yield
133
119
  end
134
120
 
@@ -1,25 +1,11 @@
1
1
  # A visitor for converting a Sass tree into CSS.
2
2
  class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
3
- # The source mapping for the generated CSS file. This is only set if
4
- # `build_source_mapping` is passed to the constructor and \{Sass::Engine#render} has been
5
- # run.
6
- attr_reader :source_mapping
3
+ protected
7
4
 
8
- # @param build_source_mapping [Boolean] Whether to build a
9
- # \{Sass::Source::Map} while creating the CSS output. The mapping will
10
- # be available from \{#source\_mapping} after the visitor has completed.
11
- def initialize(build_source_mapping = false)
5
+ def initialize
12
6
  @tabs = 0
13
- @line = 1
14
- @offset = 1
15
- @result = ""
16
- @source_mapping = Sass::Source::Map.new if build_source_mapping
17
7
  end
18
8
 
19
- # Runs the visitor on `node`.
20
- #
21
- # @param node [Sass::Tree::Node] The root node of the tree to convert to CSS>
22
- # @return [String] The CSS output.
23
9
  def visit(node)
24
10
  super
25
11
  rescue Sass::SyntaxError => e
@@ -27,8 +13,6 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
27
13
  raise e
28
14
  end
29
15
 
30
- protected
31
-
32
16
  def with_tabs(tabs)
33
17
  old_tabs, @tabs = @tabs, tabs
34
18
  yield
@@ -36,203 +20,97 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
36
20
  @tabs = old_tabs
37
21
  end
38
22
 
39
- # Associate all output produced in a block with a given node. Used for source
40
- # mapping.
41
- def for_node(node, attr_prefix = nil)
42
- return yield unless @source_mapping
43
- start_pos = Sass::Source::Position.new(@line, @offset)
44
- yield
45
-
46
- range_attr = attr_prefix ? :"#{attr_prefix}_source_range" : :source_range
47
- return if node.invisible? || !node.send(range_attr)
48
- source_range = node.send(range_attr)
49
- target_end_pos = Sass::Source::Position.new(@line, @offset)
50
- target_range = Sass::Source::Range.new(start_pos, target_end_pos, nil)
51
- @source_mapping.add(source_range, target_range)
52
- end
53
-
54
- # Move the output cursor back `chars` characters.
55
- def erase!(chars)
56
- return if chars == 0
57
- str = @result.slice!(-chars..-1)
58
- newlines = str.count("\n")
59
- if newlines > 0
60
- @line -= newlines
61
- @offset = @result[@result.rindex("\n") || 0..-1].size
62
- else
63
- @offset -= chars
64
- end
65
- end
66
-
67
- # Avoid allocating lots of new strings for `#output`. This is important
68
- # because `#output` is called all the time.
69
- NEWLINE = "\n"
70
-
71
- # Add `s` to the output string and update the line and offset information
72
- # accordingly.
73
- def output(s)
74
- if @lstrip
75
- s = s.gsub(/\A\s+/, "")
76
- @lstrip = false
77
- end
78
-
79
- newlines = s.count(NEWLINE)
80
- if newlines > 0
81
- @line += newlines
82
- @offset = s[s.rindex(NEWLINE)..-1].size
83
- else
84
- @offset += s.size
85
- end
86
-
87
- @result << s
88
- end
89
-
90
- # Strip all trailing whitespace from the output string.
91
- def rstrip!
92
- erase! @result.length - 1 - (@result.rindex(/[^\s]/) || -1)
93
- end
94
-
95
- # lstrip the first output in the given block.
96
- def lstrip
97
- old_lstrip = @lstrip
98
- @lstrip = true
99
- yield
100
- ensure
101
- @lstrip = @lstrip && old_lstrip
102
- end
103
-
104
- # Prepend `prefix` to the output string.
105
- def prepend!(prefix)
106
- @result.insert 0, prefix
107
- return unless @source_mapping
108
-
109
- line_delta = prefix.count("\n")
110
- offset_delta = prefix.gsub(/.*\n/, '').size
111
- @source_mapping.shift_output_offsets(offset_delta)
112
- @source_mapping.shift_output_lines(line_delta)
113
- end
114
-
115
23
  def visit_root(node)
24
+ result = String.new
116
25
  node.children.each do |child|
117
26
  next if child.invisible?
118
- visit(child)
119
- unless node.style == :compressed
120
- output "\n"
121
- if child.is_a?(Sass::Tree::DirectiveNode) && child.has_children && !child.bubbles?
122
- output "\n"
27
+ child_str = visit(child)
28
+ result << child_str + (node.style == :compressed ? '' : "\n")
29
+ end
30
+ result.rstrip!
31
+ return "" if result.empty?
32
+ result << "\n"
33
+ unless Sass::Util.ruby1_8? || result.ascii_only?
34
+ if node.children.first.is_a?(Sass::Tree::CharsetNode)
35
+ begin
36
+ encoding = node.children.first.name
37
+ # Default to big-endian encoding, because we have to decide somehow
38
+ encoding << 'BE' if encoding =~ /\Autf-(16|32)\Z/i
39
+ result = result.encode(Encoding.find(encoding))
40
+ rescue EncodingError
123
41
  end
124
42
  end
125
- end
126
- rstrip!
127
- return "" if @result.empty?
128
43
 
129
- output "\n"
130
-
131
- unless Sass::Util.ruby1_8? || @result.ascii_only?
132
- if node.style == :compressed
133
- # A byte order mark is sufficient to tell browsers that this
134
- # file is UTF-8 encoded, and will override any other detection
135
- # methods as per http://encoding.spec.whatwg.org/#decode-and-encode.
136
- prepend! "\uFEFF"
137
- else
138
- prepend! "@charset \"UTF-8\";\n"
139
- end
44
+ result = "@charset \"#{result.encoding.name}\";#{
45
+ node.style == :compressed ? '' : "\n"
46
+ }".encode(result.encoding) + result
140
47
  end
141
-
142
- @result
48
+ result
143
49
  rescue Sass::SyntaxError => e
144
50
  e.sass_template ||= node.template
145
51
  raise e
146
52
  end
147
53
 
148
54
  def visit_charset(node)
149
- for_node(node) {output("@charset \"#{node.name}\";")}
150
- end
55
+ "@charset \"#{node.name}\";"
56
+ end
151
57
 
152
58
  def visit_comment(node)
153
59
  return if node.invisible?
154
60
  spaces = (' ' * [@tabs - node.resolved_value[/^ */].size, 0].max)
155
61
 
156
62
  content = node.resolved_value.gsub(/^/, spaces)
157
- if node.type == :silent
158
- content.gsub!(%r{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"}
159
- end
160
- if (node.style == :compact || node.style == :compressed) && node.type != :loud
161
- content.gsub!(/\n +(\* *(?!\/))?/, ' ')
162
- end
163
- for_node(node) {output(content)}
63
+ content.gsub!(%r{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"} if node.type == :silent
64
+ content.gsub!(/\n +(\* *(?!\/))?/, ' ') if (node.style == :compact || node.style == :compressed) && node.type != :loud
65
+ content
164
66
  end
165
67
 
166
- # @comment
167
- # rubocop:disable MethodLength
168
68
  def visit_directive(node)
169
69
  was_in_directive = @in_directive
170
70
  tab_str = ' ' * @tabs
171
- if !node.has_children || node.children.empty?
172
- output(tab_str)
173
- for_node(node) {output(node.resolved_value)}
174
- output(!node.has_children ? ";" : " {}")
175
- return
176
- end
177
-
71
+ return tab_str + node.resolved_value + ";" unless node.has_children
72
+ return tab_str + node.resolved_value + " {}" if node.children.empty?
178
73
  @in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
179
- output(tab_str) if node.style != :compressed
180
- for_node(node) {output(node.resolved_value)}
181
- output(node.style == :compressed ? "{" : " {")
182
- output(node.style == :compact ? ' ' : "\n") if node.style != :compressed
183
-
74
+ result = if node.style == :compressed
75
+ "#{node.resolved_value}{"
76
+ else
77
+ "#{tab_str}#{node.resolved_value} {" + (node.style == :compact ? ' ' : "\n")
78
+ end
184
79
  was_prop = false
185
80
  first = true
186
81
  node.children.each do |child|
187
82
  next if child.invisible?
188
83
  if node.style == :compact
189
84
  if child.is_a?(Sass::Tree::PropNode)
190
- with_tabs(first || was_prop ? 0 : @tabs + 1) do
191
- visit(child)
192
- output(' ')
193
- end
85
+ with_tabs(first || was_prop ? 0 : @tabs + 1) {result << visit(child) << ' '}
194
86
  else
195
- if was_prop
196
- erase! 1
197
- output "\n"
198
- end
199
-
200
- if first
201
- lstrip {with_tabs(@tabs + 1) {visit(child)}}
202
- else
203
- with_tabs(@tabs + 1) {visit(child)}
204
- end
205
-
206
- rstrip!
207
- output "\n"
87
+ result[-1] = "\n" if was_prop
88
+ rendered = with_tabs(@tabs + 1) {visit(child).dup}
89
+ rendered = rendered.lstrip if first
90
+ result << rendered.rstrip + "\n"
208
91
  end
209
92
  was_prop = child.is_a?(Sass::Tree::PropNode)
210
93
  first = false
211
94
  elsif node.style == :compressed
212
- output(was_prop ? ";" : "")
213
- with_tabs(0) {visit(child)}
95
+ result << (was_prop ? ";" : "") << with_tabs(0) {visit(child)}
214
96
  was_prop = child.is_a?(Sass::Tree::PropNode)
215
97
  else
216
- with_tabs(@tabs + 1) {visit(child)}
217
- output "\n"
98
+ result << with_tabs(@tabs + 1) {visit(child)} + "\n"
218
99
  end
219
100
  end
220
- rstrip!
221
- if node.style == :expanded
222
- output("\n#{tab_str}")
223
- elsif node.style != :compressed
224
- output(" ")
225
- end
226
- output("}")
101
+ result.rstrip + if node.style == :compressed
102
+ "}"
103
+ else
104
+ (node.style == :expanded ? "\n" : " ") + "}\n"
105
+ end
227
106
  ensure
228
107
  @in_directive = was_in_directive
229
108
  end
230
- # @comment
231
- # rubocop:enable MethodLength
232
109
 
233
110
  def visit_media(node)
234
- with_tabs(@tabs + node.tabs) {visit_directive(node)}
235
- output("\n") if node.style != :compressed && node.group_end
111
+ str = with_tabs(@tabs + node.tabs) {visit_directive(node)}
112
+ str.gsub!(/\n\Z/, '') unless node.style == :compressed || node.group_end
113
+ str
236
114
  end
237
115
 
238
116
  def visit_supports(node)
@@ -246,39 +124,28 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
246
124
  def visit_prop(node)
247
125
  return if node.resolved_value.empty?
248
126
  tab_str = ' ' * (@tabs + node.tabs)
249
- output(tab_str)
250
- for_node(node, :name) {output(node.resolved_name)}
251
127
  if node.style == :compressed
252
- output(":")
253
- for_node(node, :value) {output(node.resolved_value)}
128
+ "#{tab_str}#{node.resolved_name}:#{node.resolved_value}"
254
129
  else
255
- output(": ")
256
- for_node(node, :value) {output(node.resolved_value)}
257
- output(";")
130
+ "#{tab_str}#{node.resolved_name}: #{node.resolved_value};"
258
131
  end
259
132
  end
260
133
 
261
- # @comment
262
- # rubocop:disable MethodLength
263
134
  def visit_rule(node)
264
135
  with_tabs(@tabs + node.tabs) do
265
136
  rule_separator = node.style == :compressed ? ',' : ', '
266
137
  line_separator =
267
138
  case node.style
268
- when :nested, :expanded; "\n"
269
- when :compressed; ""
270
- else; " "
139
+ when :nested, :expanded; "\n"
140
+ when :compressed; ""
141
+ else; " "
271
142
  end
272
143
  rule_indent = ' ' * @tabs
273
- per_rule_indent, total_indent = if [:nested, :expanded].include?(node.style)
274
- [rule_indent, '']
275
- else
276
- ['', rule_indent]
277
- end
144
+ per_rule_indent, total_indent = [:nested, :expanded].include?(node.style) ? [rule_indent, ''] : ['', rule_indent]
278
145
 
279
146
  joined_rules = node.resolved_rules.members.map do |seq|
280
147
  next if seq.has_placeholder?
281
- rule_part = seq.to_s
148
+ rule_part = seq.to_a.join
282
149
  if node.style == :compressed
283
150
  rule_part.gsub!(/([^,])\s*\n\s*/m, '\1 ')
284
151
  rule_part.gsub!(/\s*([,+>])\s*/m, '\1')
@@ -287,72 +154,54 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
287
154
  rule_part
288
155
  end.compact.join(rule_separator)
289
156
 
290
- joined_rules.lstrip!
157
+ joined_rules.sub!(/\A\s*/, per_rule_indent)
291
158
  joined_rules.gsub!(/\s*\n\s*/, "#{line_separator}#{per_rule_indent}")
159
+ total_rule = total_indent << joined_rules
292
160
 
161
+ to_return = ''
293
162
  old_spaces = ' ' * @tabs
294
163
  if node.style != :compressed
295
164
  if node.options[:debug_info] && !@in_directive
296
- visit(debug_info_rule(node.debug_info, node.options))
297
- output "\n"
165
+ to_return << visit(debug_info_rule(node.debug_info, node.options)) << "\n"
298
166
  elsif node.options[:trace_selectors]
299
- output("#{old_spaces}/* ")
300
- output(node.stack_trace.gsub("\n", "\n #{old_spaces}"))
301
- output(" */\n")
167
+ to_return << "#{old_spaces}/* "
168
+ to_return << node.stack_trace.join("\n #{old_spaces}")
169
+ to_return << " */\n"
302
170
  elsif node.options[:line_comments]
303
- output("#{old_spaces}/* line #{node.line}")
171
+ to_return << "#{old_spaces}/* line #{node.line}"
304
172
 
305
173
  if node.filename
306
- relative_filename =
307
- if node.options[:css_filename]
308
- begin
309
- Sass::Util.pathname(node.filename).relative_path_from(
310
- Sass::Util.pathname(File.dirname(node.options[:css_filename]))).to_s
311
- rescue ArgumentError
312
- nil
313
- end
174
+ relative_filename = if node.options[:css_filename]
175
+ begin
176
+ Pathname.new(node.filename).relative_path_from(
177
+ Pathname.new(File.dirname(node.options[:css_filename]))).to_s
178
+ rescue ArgumentError
179
+ nil
314
180
  end
181
+ end
315
182
  relative_filename ||= node.filename
316
- output(", #{relative_filename}")
183
+ to_return << ", #{relative_filename}"
317
184
  end
318
185
 
319
- output(" */\n")
186
+ to_return << " */\n"
320
187
  end
321
188
  end
322
189
 
323
- end_props, trailer, tabs = '', '', 0
324
190
  if node.style == :compact
325
- separator, end_props, bracket = ' ', ' ', ' { '
326
- trailer = "\n" if node.group_end
191
+ properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(' ')}
192
+ to_return << "#{total_rule} { #{properties} }#{"\n" if node.group_end}"
327
193
  elsif node.style == :compressed
328
- separator, bracket = ';', '{'
194
+ properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(';')}
195
+ to_return << "#{total_rule}{#{properties}}"
329
196
  else
330
- tabs = @tabs + 1
331
- separator, bracket = "\n", " {\n"
332
- trailer = "\n" if node.group_end
197
+ properties = with_tabs(@tabs + 1) {node.children.map {|a| visit(a)}.join("\n")}
333
198
  end_props = (node.style == :expanded ? "\n" + old_spaces : ' ')
199
+ to_return << "#{total_rule} {\n#{properties}#{end_props}}#{"\n" if node.group_end}"
334
200
  end
335
- output(total_indent + per_rule_indent)
336
- for_node(node, :selector) {output(joined_rules)}
337
- output(bracket)
338
201
 
339
- with_tabs(tabs) do
340
- node.children.each_with_index do |child, i|
341
- output(separator) if i > 0
342
- visit(child)
343
- end
344
- end
345
-
346
- output(end_props)
347
- output("}" + trailer)
202
+ to_return
348
203
  end
349
204
  end
350
- # @comment
351
- # rubocop:enable MethodLength
352
-
353
- def visit_keyframerule(node)
354
- visit_directive(node)
355
- end
356
205
 
357
206
  private
358
207
 
@@ -367,15 +216,13 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
367
216
  false)
368
217
  ])
369
218
  ])
370
- prop = Sass::Tree::PropNode.new([""], Sass::Script::Value::String.new(''), :new)
219
+ prop = Sass::Tree::PropNode.new([""], Sass::Script::String.new(''), :new)
371
220
  prop.resolved_name = "font-family"
372
221
  prop.resolved_value = Sass::SCSS::RX.escape_ident(v.to_s)
373
222
  rule << prop
374
223
  node << rule
375
224
  end
376
- node.options = options.merge(:debug_info => false,
377
- :line_comments => false,
378
- :style => :compressed)
225
+ node.options = options.merge(:debug_info => false, :line_comments => false, :style => :compressed)
379
226
  node
380
227
  end
381
228
  end