oreorenasass 3.4.4 → 3.4.5

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 (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