haml-edge 2.1.6 → 2.1.7

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.
data/EDGE_GEM_VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.6
1
+ 2.1.7
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.6
1
+ 2.1.7
data/lib/haml/exec.rb CHANGED
@@ -189,6 +189,12 @@ END
189
189
  opts.on('-I', '--load-path PATH', 'Add a sass import path.') do |path|
190
190
  @options[:for_engine][:load_paths] << path
191
191
  end
192
+ opts.on('--cache-location', 'The path to put cached Sass files. Defaults to .sass-cache.') do |loc|
193
+ @options[:for_engine][:cache_location] = path
194
+ end
195
+ opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
196
+ @options[:for_engine][:cache] = false
197
+ end
192
198
  end
193
199
 
194
200
  def process_result
@@ -203,21 +209,23 @@ END
203
209
  input = @options[:input]
204
210
  output = @options[:output]
205
211
 
206
- template = input.read()
207
- input.close() if input.is_a? File
212
+ tree =
213
+ if input.is_a?(File) && !@options[:check_syntax]
214
+ ::Sass::Files.tree_for(input.path, @options[:for_engine])
215
+ else
216
+ # We don't need to do any special handling of @options[:check_syntax] here,
217
+ # because the Sass syntax checking happens alongside evaluation
218
+ # and evaluation doesn't actually evaluate any code anyway.
219
+ ::Sass::Engine.new(input.read(), @options[:for_engine]).to_tree
220
+ end
208
221
 
209
- begin
210
- # We don't need to do any special handling of @options[:check_syntax] here,
211
- # because the Sass syntax checking happens alongside evaluation
212
- # and evaluation doesn't actually evaluate any code anyway.
213
- result = ::Sass::Engine.new(template, @options[:for_engine]).render
214
- rescue ::Sass::SyntaxError => e
215
- raise e if @options[:trace]
216
- raise "Syntax error on line #{get_line e}: #{e.message}"
217
- end
222
+ input.close() if input.is_a?(File)
218
223
 
219
- output.write(result)
224
+ output.write(tree.render)
220
225
  output.close() if output.is_a? File
226
+ rescue ::Sass::SyntaxError => e
227
+ raise e if @options[:trace]
228
+ raise "Syntax error on line #{get_line e}: #{e.message}"
221
229
  end
222
230
  end
223
231
 
data/lib/sass.rb CHANGED
@@ -991,6 +991,9 @@ require 'haml/version'
991
991
  # or <tt>width = !main_width</tt>.
992
992
  # By default, either syntax is valid.
993
993
  #
994
+ # [<tt>:cache</tt>] Whether parsed Sass files should be cached,
995
+ # allowing greater speed. Defaults to true.
996
+ #
994
997
  # [<tt>:never_update</tt>] Whether the CSS files should never be updated,
995
998
  # even if the template file changes.
996
999
  # Setting this to true may give small performance gains.
@@ -1035,6 +1038,11 @@ require 'haml/version'
1035
1038
  # or <tt>MERB_ROOT + "/public/stylesheets"</tt>.
1036
1039
  # Only has meaning within Ruby on Rails or Merb.
1037
1040
  #
1041
+ # [<tt>:cache_location</tt>] The path where the cached <tt>sassc</tt> files should be written to.
1042
+ # Defaults to <tt>RAILS_ROOT + "/tmp/sass-cache"</tt>,
1043
+ # or <tt>MERB_ROOT + "/tmp/sass-cache"</tt>,
1044
+ # or just <tt>"./.sass-cache"</tt>.
1045
+ #
1038
1046
  # [<tt>:filename</tt>] The filename of the file being rendered.
1039
1047
  # This is used solely for reporting errors,
1040
1048
  # and is automatically set when using Rails or Merb.
data/lib/sass/css.rb CHANGED
@@ -75,7 +75,7 @@ module Sass
75
75
  private
76
76
 
77
77
  def build_tree
78
- root = Tree::Node.new({})
78
+ root = Tree::Node.new
79
79
  whitespace
80
80
  rules root
81
81
  expand_commas root
@@ -99,7 +99,7 @@ module Sass
99
99
  directive = rule[0] == ?@
100
100
 
101
101
  if directive
102
- node = Tree::DirectiveNode.new(rule, {})
102
+ node = Tree::DirectiveNode.new(rule)
103
103
  return node if @template.scan(/;/)
104
104
 
105
105
  assert_match /\{/
@@ -110,7 +110,7 @@ module Sass
110
110
  end
111
111
 
112
112
  assert_match /\{/
113
- node = Tree::RuleNode.new(rule, {})
113
+ node = Tree::RuleNode.new(rule)
114
114
  attributes(node)
115
115
  return node
116
116
  end
@@ -128,7 +128,7 @@ module Sass
128
128
  end
129
129
 
130
130
  assert_match /(;|(?=\}))/
131
- rule << Tree::AttrNode.new(name, value, {})
131
+ rule << Tree::AttrNode.new(name, value, nil)
132
132
  end
133
133
 
134
134
  assert_match /\}/
@@ -176,7 +176,7 @@ module Sass
176
176
  root.children.map! do |child|
177
177
  next child unless Tree::RuleNode === child && child.rules.first.include?(',')
178
178
  child.rules.first.split(',').map do |rule|
179
- node = Tree::RuleNode.new(rule.strip, {})
179
+ node = Tree::RuleNode.new(rule.strip)
180
180
  node.children = child.children
181
181
  node
182
182
  end
@@ -224,7 +224,7 @@ module Sass
224
224
  first, rest = child.rules.first.scan(/^(&?(?: .|[^ ])[^.#: \[]*)([.#: \[].*)?$/).first
225
225
 
226
226
  if current_rule.nil? || current_rule.rules.first != first
227
- current_rule = Tree::RuleNode.new(first, {})
227
+ current_rule = Tree::RuleNode.new(first)
228
228
  root << current_rule
229
229
  end
230
230
 
data/lib/sass/engine.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'strscan'
2
+ require 'digest/sha1'
2
3
  require 'sass/tree/node'
3
4
  require 'sass/tree/rule_node'
4
5
  require 'sass/tree/comment_node'
@@ -15,6 +16,7 @@ require 'sass/tree/file_node'
15
16
  require 'sass/environment'
16
17
  require 'sass/script'
17
18
  require 'sass/error'
19
+ require 'sass/files'
18
20
  require 'haml/shared'
19
21
 
20
22
  module Sass
@@ -76,6 +78,14 @@ module Sass
76
78
  # attributes of the form <tt>name: attr</tt>.
77
79
  ATTRIBUTE_ALTERNATE = /^([^\s=:"]+)(\s*=|:)(?:\s+|$)(.*)/
78
80
 
81
+ # The default options for Sass::Engine.
82
+ DEFAULT_OPTIONS = {
83
+ :style => :nested,
84
+ :load_paths => ['.'],
85
+ :cache => true,
86
+ :cache_location => './.sass-cache',
87
+ }.freeze
88
+
79
89
  # Creates a new instace of Sass::Engine that will compile the given
80
90
  # template string when <tt>render</tt> is called.
81
91
  # See README.rdoc for available options.
@@ -89,36 +99,23 @@ module Sass
89
99
  #++
90
100
  #
91
101
  def initialize(template, options={})
92
- @options = {
93
- :style => :nested,
94
- :load_paths => ['.']
95
- }.merge! options
102
+ @options = DEFAULT_OPTIONS.merge(options)
96
103
  @template = template
97
- @environment = Environment.new(nil, @options)
98
- @environment.set_var("important", Script::String.new("!important"))
99
104
  end
100
105
 
101
106
  # Processes the template and returns the result as a string.
102
107
  def render
103
- begin
104
- render_to_tree.perform(@environment).to_s
105
- rescue SyntaxError => err
106
- err.sass_line = @line unless err.sass_line
107
- unless err.sass_filename
108
- err.add_backtrace_entry(@options[:filename])
109
- end
110
- raise err
111
- end
108
+ to_tree.render
112
109
  end
113
110
 
114
111
  alias_method :to_css, :render
115
112
 
116
- protected
117
-
118
- def render_to_tree
119
- root = Tree::Node.new(@options)
113
+ def to_tree
114
+ root = Tree::Node.new
120
115
  append_children(root, tree(tabulate(@template)).first, true)
116
+ root.options = @options
121
117
  root
118
+ rescue SyntaxError => e; e.add_metadata(@options[:filename], @line)
122
119
  end
123
120
 
124
121
  private
@@ -246,7 +243,7 @@ END
246
243
  else
247
244
  # Support CSS3-style pseudo-elements,
248
245
  # which begin with ::
249
- Tree::RuleNode.new(line.text, @options)
246
+ Tree::RuleNode.new(line.text)
250
247
  end
251
248
  when Script::VARIABLE_CHAR
252
249
  parse_variable(line)
@@ -255,12 +252,12 @@ END
255
252
  when DIRECTIVE_CHAR
256
253
  parse_directive(parent, line, root)
257
254
  when ESCAPE_CHAR
258
- Tree::RuleNode.new(line.text[1..-1], @options)
255
+ Tree::RuleNode.new(line.text[1..-1])
259
256
  when MIXIN_DEFINITION_CHAR
260
257
  parse_mixin_definition(line)
261
258
  when MIXIN_INCLUDE_CHAR
262
259
  if line.text[1].nil?
263
- Tree::RuleNode.new(line.text, @options)
260
+ Tree::RuleNode.new(line.text)
264
261
  else
265
262
  parse_mixin_include(line, root)
266
263
  end
@@ -268,20 +265,12 @@ END
268
265
  if line.text =~ ATTRIBUTE_ALTERNATE_MATCHER
269
266
  parse_attribute(line, ATTRIBUTE_ALTERNATE)
270
267
  else
271
- Tree::RuleNode.new(line.text, @options)
268
+ Tree::RuleNode.new(line.text)
272
269
  end
273
270
  end
274
271
  end
275
272
 
276
273
  def parse_attribute(line, attribute_regx)
277
- if @options[:attribute_syntax] == :normal &&
278
- attribute_regx == ATTRIBUTE_ALTERNATE
279
- raise SyntaxError.new("Illegal attribute syntax: can't use alternate syntax when :attribute_syntax => :normal is set.")
280
- elsif @options[:attribute_syntax] == :alternate &&
281
- attribute_regx == ATTRIBUTE
282
- raise SyntaxError.new("Illegal attribute syntax: can't use normal syntax when :attribute_syntax => :alternate is set.")
283
- end
284
-
285
274
  name, eq, value = line.text.scan(attribute_regx)[0]
286
275
 
287
276
  if name.nil? || value.nil?
@@ -292,7 +281,7 @@ END
292
281
  else
293
282
  value
294
283
  end
295
- Tree::AttrNode.new(name, expr, @options)
284
+ Tree::AttrNode.new(name, expr, attribute_regx == ATTRIBUTE ? :old : :new)
296
285
  end
297
286
 
298
287
  def parse_variable(line)
@@ -300,14 +289,14 @@ END
300
289
  raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath variable declarations.", @line + 1) unless line.children.empty?
301
290
  raise SyntaxError.new("Invalid variable: \"#{line.text}\".", @line) unless name && value
302
291
 
303
- Tree::VariableNode.new(name, parse_script(value, :offset => line.offset + line.text.index(value)), op == '||=', @options)
292
+ Tree::VariableNode.new(name, parse_script(value, :offset => line.offset + line.text.index(value)), op == '||=')
304
293
  end
305
294
 
306
295
  def parse_comment(line)
307
296
  if line[1] == CSS_COMMENT_CHAR || line[1] == SASS_COMMENT_CHAR
308
- Tree::CommentNode.new(line, @options.merge(:silent => (line[1] == SASS_COMMENT_CHAR)))
297
+ Tree::CommentNode.new(line, line[1] == SASS_COMMENT_CHAR)
309
298
  else
310
- Tree::RuleNode.new(line, @options)
299
+ Tree::RuleNode.new(line)
311
300
  end
312
301
  end
313
302
 
@@ -326,17 +315,17 @@ END
326
315
  parse_else(parent, line, value)
327
316
  elsif directive == "while"
328
317
  raise SyntaxError.new("Invalid while directive '@while': expected expression.") unless value
329
- Tree::WhileNode.new(parse_script(value, :offset => offset), @options)
318
+ Tree::WhileNode.new(parse_script(value, :offset => offset))
330
319
  elsif directive == "if"
331
320
  raise SyntaxError.new("Invalid if directive '@if': expected expression.") unless value
332
- Tree::IfNode.new(parse_script(value, :offset => offset), @options)
321
+ Tree::IfNode.new(parse_script(value, :offset => offset))
333
322
  elsif directive == "debug"
334
323
  raise SyntaxError.new("Invalid debug directive '@debug': expected expression.") unless value
335
324
  raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath debug directives.", @line + 1) unless line.children.empty?
336
325
  offset = line.offset + line.text.index(value).to_i
337
- Tree::DebugNode.new(parse_script(value, :offset => offset), @options)
326
+ Tree::DebugNode.new(parse_script(value, :offset => offset))
338
327
  else
339
- Tree::DirectiveNode.new(line.text, @options)
328
+ Tree::DirectiveNode.new(line.text)
340
329
  end
341
330
  end
342
331
 
@@ -357,7 +346,7 @@ END
357
346
 
358
347
  parsed_from = parse_script(from_expr, :offset => line.offset + line.text.index(from_expr))
359
348
  parsed_to = parse_script(to_expr, :offset => line.offset + line.text.index(to_expr))
360
- Tree::ForNode.new(var[1..-1], parsed_from, parsed_to, to_name == 'to', @options)
349
+ Tree::ForNode.new(var[1..-1], parsed_from, parsed_to, to_name == 'to')
361
350
  end
362
351
 
363
352
  def parse_else(parent, line, text)
@@ -371,7 +360,7 @@ END
371
360
  expr = parse_script($1, :offset => line.offset + line.text.index($1))
372
361
  end
373
362
 
374
- node = Tree::IfNode.new(expr, @options)
363
+ node = Tree::IfNode.new(expr)
375
364
  append_children(node, line.children, false)
376
365
  previous.add_else node
377
366
  nil
@@ -406,7 +395,7 @@ END
406
395
  default = parse_script(default, :offset => line.offset + line.text.index(default)) if default
407
396
  [arg[1..-1], default]
408
397
  end
409
- Tree::MixinDefNode.new(name, args, @options)
398
+ Tree::MixinDefNode.new(name, args)
410
399
  end
411
400
 
412
401
  def parse_mixin_include(line, root)
@@ -416,7 +405,7 @@ END
416
405
  raise SyntaxError.new("Invalid mixin include \"#{line.text}\".", @line) if name.nil? || args.nil?
417
406
  args.each {|a| raise SyntaxError.new("Mixin arguments can't be empty.", @line) if a.empty?}
418
407
 
419
- Tree::MixinNode.new(name, args.map {|s| parse_script(s, :offset => line.offset + line.text.index(s))}, @options)
408
+ Tree::MixinNode.new(name, args.map {|s| parse_script(s, :offset => line.offset + line.text.index(s))})
420
409
  end
421
410
 
422
411
  def parse_script(script, options = {})
@@ -436,60 +425,15 @@ END
436
425
  engine = nil
437
426
 
438
427
  begin
439
- filename = self.class.find_file_to_import(filename, import_paths)
428
+ filename = Sass::Files.find_file_to_import(filename, import_paths)
440
429
  rescue Exception => e
441
430
  raise SyntaxError.new(e.message, @line)
442
431
  end
443
432
 
444
- next Tree::DirectiveNode.new("@import url(#{filename})", @options) if filename =~ /\.css$/
433
+ next Tree::DirectiveNode.new("@import url(#{filename})") if filename =~ /\.css$/
445
434
 
446
- File.open(filename) do |file|
447
- new_options = @options.dup
448
- new_options[:filename] = filename
449
- engine = Sass::Engine.new(file.read, new_options)
450
- end
451
-
452
- begin
453
- root = engine.render_to_tree
454
- rescue Sass::SyntaxError => err
455
- err.add_backtrace_entry(filename)
456
- raise err
457
- end
458
- Tree::FileNode.new(filename, root.children, @options)
435
+ Tree::FileNode.new(filename)
459
436
  end.flatten
460
437
  end
461
-
462
- def self.find_file_to_import(filename, load_paths)
463
- was_sass = false
464
- original_filename = filename
465
-
466
- if filename[-5..-1] == ".sass"
467
- filename = filename[0...-5]
468
- was_sass = true
469
- elsif filename[-4..-1] == ".css"
470
- return filename
471
- end
472
-
473
- new_filename = find_full_path("#{filename}.sass", load_paths)
474
-
475
- return new_filename if new_filename
476
- return filename + '.css' unless was_sass
477
- raise SyntaxError.new("File to import not found or unreadable: #{original_filename}.", @line)
478
- end
479
-
480
- def self.find_full_path(filename, load_paths)
481
- segments = filename.split(File::SEPARATOR)
482
- segments.push "_#{segments.pop}"
483
- partial_name = segments.join(File::SEPARATOR)
484
- load_paths.each do |path|
485
- [partial_name, filename].each do |name|
486
- full_path = File.join(path, name)
487
- if File.readable?(full_path)
488
- return full_path
489
- end
490
- end
491
- end
492
- nil
493
- end
494
438
  end
495
439
  end
@@ -1,12 +1,14 @@
1
1
  module Sass
2
2
  class Environment
3
3
  attr_reader :parent
4
+ attr_writer :options
4
5
 
5
- def initialize(parent = nil, options = nil)
6
+ def initialize(parent = nil)
6
7
  @vars = {}
7
8
  @mixins = {}
8
9
  @parent = parent
9
- @options = options
10
+
11
+ set_var("important", Script::String.new("!important")) unless @parent
10
12
  end
11
13
 
12
14
  def options
data/lib/sass/error.rb CHANGED
@@ -19,6 +19,13 @@ module Sass
19
19
  @sass_line = lineno
20
20
  end
21
21
 
22
+ # Add information about the filename and line on which the error was raised.
23
+ def add_metadata(filename, line)
24
+ self.sass_line ||= line
25
+ add_backtrace_entry(filename) unless sass_filename
26
+ raise self
27
+ end
28
+
22
29
  # Adds a properly formatted entry to the exception's backtrace.
23
30
  # +filename+ should be the file in which the error occurred,
24
31
  # if applicable (defaults to "(sass)").
data/lib/sass/files.rb ADDED
@@ -0,0 +1,100 @@
1
+ require 'digest/sha1'
2
+
3
+ module Sass
4
+ # This module contains various bits of functionality
5
+ # related to finding and caching Sass files.
6
+ module Files
7
+ extend self
8
+
9
+ def tree_for(filename, options)
10
+ options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
11
+ text = File.read(filename)
12
+
13
+ if options[:cache]
14
+ compiled_filename = sassc_filename(filename, options)
15
+ sha = Digest::SHA1.hexdigest(text)
16
+
17
+ if dump = try_to_read_sassc(filename, compiled_filename, sha)
18
+ return Marshal.load(dump)
19
+ end
20
+ end
21
+
22
+ engine = Sass::Engine.new(text, options.merge(:filename => filename))
23
+
24
+ begin
25
+ root = engine.to_tree
26
+ rescue Sass::SyntaxError => err
27
+ err.add_backtrace_entry(filename)
28
+ raise err
29
+ end
30
+
31
+ try_to_write_sassc(root, compiled_filename, sha, options) if options[:cache]
32
+
33
+ root
34
+ end
35
+
36
+ def find_file_to_import(filename, load_paths)
37
+ was_sass = false
38
+ original_filename = filename
39
+
40
+ if filename[-5..-1] == ".sass"
41
+ filename = filename[0...-5]
42
+ was_sass = true
43
+ elsif filename[-4..-1] == ".css"
44
+ return filename
45
+ end
46
+
47
+ new_filename = find_full_path("#{filename}.sass", load_paths)
48
+
49
+ return new_filename if new_filename
50
+ return filename + '.css' unless was_sass
51
+ raise SyntaxError.new("File to import not found or unreadable: #{original_filename}.", @line)
52
+ end
53
+
54
+ private
55
+
56
+ def sassc_filename(filename, options)
57
+ File.join(options[:cache_location],
58
+ Digest::SHA1.hexdigest(File.dirname(File.expand_path(filename))),
59
+ File.basename(filename) + 'c')
60
+ end
61
+
62
+ def try_to_read_sassc(filename, compiled_filename, sha)
63
+ return unless File.readable?(compiled_filename)
64
+
65
+ File.open(compiled_filename) do |f|
66
+ return unless f.readline("\n").strip == Sass::VERSION
67
+ return unless f.readline("\n").strip == sha
68
+ return f.read
69
+ end
70
+ end
71
+
72
+ def try_to_write_sassc(root, compiled_filename, sha, options)
73
+ return unless File.writable?(File.dirname(options[:cache_location]))
74
+ return if File.exists?(options[:cache_location]) && !File.writable?(options[:cache_location])
75
+ return if File.exists?(File.dirname(compiled_filename)) && !File.writable?(File.dirname(compiled_filename))
76
+ return if File.exists?(compiled_filename) && !File.writable?(compiled_filename)
77
+ FileUtils.mkdir_p(File.dirname(compiled_filename))
78
+ File.open(compiled_filename, "w") do |f|
79
+ f.puts(Sass::VERSION)
80
+ f.puts(sha)
81
+ f.write(Marshal.dump(root))
82
+ end
83
+ end
84
+
85
+ def find_full_path(filename, load_paths)
86
+ segments = filename.split(File::SEPARATOR)
87
+ segments.push "_#{segments.pop}"
88
+ partial_name = segments.join(File::SEPARATOR)
89
+ load_paths.each do |path|
90
+ [partial_name, filename].each do |name|
91
+ full_path = File.join(path, name)
92
+ if File.readable?(full_path)
93
+ return full_path
94
+ end
95
+ end
96
+ end
97
+ nil
98
+ end
99
+ end
100
+ end
data/lib/sass/plugin.rb CHANGED
@@ -70,9 +70,8 @@ module Sass
70
70
  File.delete(css) if File.exists?(css)
71
71
 
72
72
  filename = template_filename(name, template_location)
73
- engine = Engine.new(File.read(filename), engine_options(:css_filename => css, :filename => filename))
74
73
  result = begin
75
- engine.render
74
+ Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).render
76
75
  rescue Exception => e
77
76
  exception_string(e)
78
77
  end
@@ -193,7 +192,7 @@ END
193
192
  def dependencies(filename)
194
193
  File.readlines(filename).grep(/^@import /).map do |line|
195
194
  line[8..-1].split(',').map do |inc|
196
- Sass::Engine.find_file_to_import(inc.strip, [File.dirname(filename)] + load_paths)
195
+ Sass::Files.find_file_to_import(inc.strip, [File.dirname(filename)] + load_paths)
197
196
  end
198
197
  end.flatten.grep(/\.sass$/)
199
198
  end
@@ -10,10 +10,11 @@ unless defined?(Sass::MERB_LOADED)
10
10
  env = Merb.environment
11
11
  end
12
12
 
13
- Sass::Plugin.options.merge!(:template_location => root + '/public/stylesheets/sass',
14
- :css_location => root + '/public/stylesheets',
15
- :always_check => env != "production",
16
- :full_exception => env != "production")
13
+ Sass::Plugin.options.merge!(:template_location => root + '/public/stylesheets/sass',
14
+ :css_location => root + '/public/stylesheets',
15
+ :cache_location => root + '/tmp/sass-cache',
16
+ :always_check => env != "production",
17
+ :full_exception => env != "production")
17
18
  config = Merb::Plugins.config[:sass] || Merb::Plugins.config["sass"] || {}
18
19
 
19
20
  if defined? config.symbolize_keys!
@@ -1,10 +1,11 @@
1
1
  unless defined?(Sass::RAILS_LOADED)
2
2
  Sass::RAILS_LOADED = true
3
3
 
4
- Sass::Plugin.options.merge!(:template_location => RAILS_ROOT + '/public/stylesheets/sass',
5
- :css_location => RAILS_ROOT + '/public/stylesheets',
6
- :always_check => RAILS_ENV != "production",
7
- :full_exception => RAILS_ENV != "production")
4
+ Sass::Plugin.options.merge!(:template_location => RAILS_ROOT + '/public/stylesheets/sass',
5
+ :css_location => RAILS_ROOT + '/public/stylesheets',
6
+ :cache_location => RAILS_ROOT + '/tmp/sass-cache',
7
+ :always_check => RAILS_ENV != "production",
8
+ :full_exception => RAILS_ENV != "production")
8
9
 
9
10
  # :stopdoc:
10
11
  module ActionController
@@ -2,10 +2,11 @@ module Sass::Tree
2
2
  class AttrNode < Node
3
3
  attr_accessor :name, :value
4
4
 
5
- def initialize(name, value, options)
5
+ def initialize(name, value, attr_syntax)
6
6
  @name = name
7
7
  @value = value
8
- super(options)
8
+ @attr_syntax = attr_syntax
9
+ super()
9
10
  end
10
11
 
11
12
  def ==(other)
@@ -13,6 +14,12 @@ module Sass::Tree
13
14
  end
14
15
 
15
16
  def to_s(tabs, parent_name = nil)
17
+ if @options[:attribute_syntax] == :normal && @attr_syntax == :new
18
+ raise Sass::SyntaxError.new("Illegal attribute syntax: can't use alternate syntax when :attribute_syntax => :normal is set.")
19
+ elsif @options[:attribute_syntax] == :alternate && @attr_syntax == :old
20
+ raise Sass::SyntaxError.new("Illegal attribute syntax: can't use normal syntax when :attribute_syntax => :alternate is set.")
21
+ end
22
+
16
23
  if value[-1] == ?;
17
24
  raise Sass::SyntaxError.new("Invalid attribute: #{declaration.dump} (This isn't CSS!).", @line)
18
25
  end
@@ -23,7 +30,7 @@ module Sass::Tree
23
30
  raise Sass::SyntaxError.new("Invalid attribute: #{declaration.dump}.", @line)
24
31
  end
25
32
 
26
- join_string = case @style
33
+ join_string = case style
27
34
  when :compact; ' '
28
35
  when :compressed; ''
29
36
  else "\n"
@@ -31,7 +38,7 @@ module Sass::Tree
31
38
  spaces = ' ' * (tabs - 1)
32
39
  to_return = ''
33
40
  if !value.empty?
34
- to_return << "#{spaces}#{real_name}:#{@style == :compressed ? '' : ' '}#{value};#{join_string}"
41
+ to_return << "#{spaces}#{real_name}:#{style == :compressed ? '' : ' '}#{value};#{join_string}"
35
42
  end
36
43
 
37
44
  children.each do |kid|
@@ -39,7 +46,7 @@ module Sass::Tree
39
46
  to_return << kid.to_s(tabs, real_name) << join_string
40
47
  end
41
48
 
42
- (@style == :compressed && parent_name) ? to_return : to_return[0...-1]
49
+ (style == :compressed && parent_name) ? to_return : to_return[0...-1]
43
50
  end
44
51
 
45
52
  protected
@@ -4,19 +4,17 @@ module Sass::Tree
4
4
  class CommentNode < Node
5
5
  attr_accessor :lines
6
6
  attr_accessor :value
7
+ attr_accessor :silent
7
8
 
8
- def initialize(value, options)
9
+ def initialize(value, silent)
9
10
  @lines = []
10
11
  @value = value[2..-1].strip
11
- super(options)
12
+ @silent = silent
13
+ super()
12
14
  end
13
15
 
14
16
  def ==(other)
15
- self.class == other.class && value == other.value && lines == other.lines
16
- end
17
-
18
- def silent?
19
- !!@options[:silent]
17
+ self.class == other.class && value == other.value && silent == other.silent && lines == other.lines
20
18
  end
21
19
 
22
20
  def to_s(tabs = 0, parent_name = nil)
@@ -24,17 +22,17 @@ module Sass::Tree
24
22
 
25
23
  spaces = ' ' * (tabs - 1)
26
24
  spaces + "/* " + ([value] + lines.map {|l| l.text}).
27
- map{|l| l.sub(%r{ ?\*/ *$},'')}.join(@style == :compact ? ' ' : "\n#{spaces} * ") + " */"
25
+ map{|l| l.sub(%r{ ?\*/ *$},'')}.join(style == :compact ? ' ' : "\n#{spaces} * ") + " */"
28
26
  end
29
27
 
30
28
  def invisible?
31
- @style == :compressed || silent?
29
+ style == :compressed || @silent
32
30
  end
33
31
 
34
32
  protected
35
33
 
36
34
  def _perform(environment)
37
- return [] if silent?
35
+ return [] if @silent
38
36
  self
39
37
  end
40
38
  end
@@ -1,9 +1,9 @@
1
1
  module Sass
2
2
  module Tree
3
3
  class DebugNode < Node
4
- def initialize(expr, options)
4
+ def initialize(expr)
5
5
  @expr = expr
6
- super(options)
6
+ super()
7
7
  end
8
8
 
9
9
  protected
@@ -2,25 +2,25 @@ module Sass::Tree
2
2
  class DirectiveNode < Node
3
3
  attr_accessor :value
4
4
 
5
- def initialize(value, options)
5
+ def initialize(value)
6
6
  @value = value
7
- super(options)
7
+ super()
8
8
  end
9
9
 
10
10
  def to_s(tabs)
11
11
  if children.empty?
12
12
  value + ";"
13
13
  else
14
- result = if @style == :compressed
14
+ result = if style == :compressed
15
15
  "#{value}{"
16
16
  else
17
- "#{' ' * (tabs - 1)}#{value} {" + (@style == :compact ? ' ' : "\n")
17
+ "#{' ' * (tabs - 1)}#{value} {" + (style == :compact ? ' ' : "\n")
18
18
  end
19
19
  was_attr = false
20
20
  first = true
21
21
  children.each do |child|
22
22
  next if child.invisible?
23
- if @style == :compact
23
+ if style == :compact
24
24
  if child.is_a?(AttrNode)
25
25
  result << "#{child.to_s(first || was_attr ? 1 : tabs + 1)} "
26
26
  else
@@ -33,17 +33,17 @@ module Sass::Tree
33
33
  end
34
34
  was_attr = child.is_a?(AttrNode)
35
35
  first = false
36
- elsif @style == :compressed
36
+ elsif style == :compressed
37
37
  result << (was_attr ? ";#{child.to_s(1)}" : child.to_s(1))
38
38
  was_attr = child.is_a?(AttrNode)
39
39
  else
40
40
  result << child.to_s(tabs + 1) + "\n"
41
41
  end
42
42
  end
43
- result.rstrip + if @style == :compressed
43
+ result.rstrip + if style == :compressed
44
44
  "}"
45
45
  else
46
- (@style == :expanded ? "\n" : " ") + "}\n"
46
+ (style == :expanded ? "\n" : " ") + "}\n"
47
47
  end
48
48
  end
49
49
  end
@@ -1,10 +1,9 @@
1
1
  module Sass
2
2
  module Tree
3
3
  class FileNode < Node
4
- def initialize(filename, children, options)
4
+ def initialize(filename)
5
5
  @filename = filename
6
- super(options)
7
- self.children = children
6
+ super()
8
7
  end
9
8
 
10
9
  def to_s(*args)
@@ -17,6 +16,7 @@ module Sass
17
16
  protected
18
17
 
19
18
  def perform!(environment)
19
+ self.children = Sass::Files.tree_for(filename, @options).children
20
20
  self.children = perform_children(environment)
21
21
  rescue Sass::SyntaxError => e
22
22
  e.add_backtrace_entry(@filename)
@@ -2,12 +2,12 @@ require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
4
  class ForNode < Node
5
- def initialize(var, from, to, exclusive, options)
5
+ def initialize(var, from, to, exclusive)
6
6
  @var = var
7
7
  @from = from
8
8
  @to = to
9
9
  @exclusive = exclusive
10
- super(options)
10
+ super()
11
11
  end
12
12
 
13
13
  protected
@@ -4,10 +4,10 @@ module Sass::Tree
4
4
  class IfNode < Node
5
5
  attr_accessor :else
6
6
 
7
- def initialize(expr, options)
7
+ def initialize(expr)
8
8
  @expr = expr
9
9
  @last_else = self
10
- super(options)
10
+ super()
11
11
  end
12
12
 
13
13
  def add_else(node)
@@ -15,6 +15,11 @@ module Sass::Tree
15
15
  @last_else = node
16
16
  end
17
17
 
18
+ def options=(options)
19
+ super
20
+ self.else.options = options if self.else
21
+ end
22
+
18
23
  protected
19
24
 
20
25
  def _perform(environment)
@@ -1,10 +1,10 @@
1
1
  module Sass
2
2
  module Tree
3
3
  class MixinDefNode < Node
4
- def initialize(name, args, options)
4
+ def initialize(name, args)
5
5
  @name = name
6
6
  @args = args
7
- super(options)
7
+ super()
8
8
  end
9
9
 
10
10
  private
@@ -2,10 +2,10 @@ require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
4
  class MixinNode < Node
5
- def initialize(name, args, options)
5
+ def initialize(name, args)
6
6
  @name = name
7
7
  @args = args
8
- super(options)
8
+ super()
9
9
  end
10
10
 
11
11
  protected
@@ -3,14 +3,22 @@ module Sass
3
3
  class Node
4
4
  attr_accessor :children
5
5
  attr_accessor :line
6
- attr_accessor :filename
6
+ attr_writer :filename
7
+ attr_reader :options
7
8
 
8
- def initialize(options)
9
- @options = options
10
- @style = options[:style]
9
+ def initialize
11
10
  @children = []
12
11
  end
13
12
 
13
+ def options=(options)
14
+ children.each {|c| c.options = options}
15
+ @options = options
16
+ end
17
+
18
+ def filename
19
+ @filename || @options[:filename]
20
+ end
21
+
14
22
  def <<(child)
15
23
  if msg = invalid_child?(child)
16
24
  raise Sass::SyntaxError.new(msg, child.line)
@@ -27,6 +35,10 @@ module Sass
27
35
  self.class == other.class && other.children == children
28
36
  end
29
37
 
38
+ def render
39
+ perform(Environment.new).to_s
40
+ end
41
+
30
42
  def invisible?; false; end
31
43
 
32
44
  def to_s
@@ -37,17 +49,21 @@ module Sass
37
49
  else
38
50
  next if child.invisible?
39
51
  child_str = child.to_s(1)
40
- result << child_str + (@style == :compressed ? '' : "\n")
52
+ result << child_str + (style == :compressed ? '' : "\n")
41
53
  end
42
54
  end
43
- @style == :compressed ? result+"\n" : result[0...-1]
55
+ style == :compressed ? result+"\n" : result[0...-1]
56
+ rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
44
57
  end
45
58
 
46
59
  def perform(environment)
60
+ environment.options = @options if self.class == Tree::Node
47
61
  _perform(environment)
48
- rescue Sass::SyntaxError => e
49
- e.sass_line ||= line
50
- raise e
62
+ rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
63
+ end
64
+
65
+ def style
66
+ @options[:style]
51
67
  end
52
68
 
53
69
  protected
@@ -7,9 +7,9 @@ module Sass::Tree
7
7
 
8
8
  attr_accessor :rules, :parsed_rules
9
9
 
10
- def initialize(rule, options)
10
+ def initialize(rule)
11
11
  @rules = [rule]
12
- super(options)
12
+ super()
13
13
  end
14
14
 
15
15
  def ==(other)
@@ -30,10 +30,10 @@ module Sass::Tree
30
30
  attributes = []
31
31
  sub_rules = []
32
32
 
33
- rule_separator = @style == :compressed ? ',' : ', '
34
- line_separator = [:nested, :expanded].include?(@style) ? ",\n" : rule_separator
33
+ rule_separator = style == :compressed ? ',' : ', '
34
+ line_separator = [:nested, :expanded].include?(style) ? ",\n" : rule_separator
35
35
  rule_indent = ' ' * (tabs - 1)
36
- per_rule_indent, total_indent = [:nested, :expanded].include?(@style) ? [rule_indent, ''] : ['', rule_indent]
36
+ per_rule_indent, total_indent = [:nested, :expanded].include?(style) ? [rule_indent, ''] : ['', rule_indent]
37
37
 
38
38
  total_rule = total_indent + resolved_rules.map do |line|
39
39
  per_rule_indent + line.join(rule_separator)
@@ -52,7 +52,7 @@ module Sass::Tree
52
52
  if !attributes.empty?
53
53
  old_spaces = ' ' * (tabs - 1)
54
54
  spaces = ' ' * tabs
55
- if @options[:line_comments] && @style != :compressed
55
+ if @options[:line_comments] && style != :compressed
56
56
  to_return << "#{old_spaces}/* line #{line}"
57
57
 
58
58
  if filename
@@ -71,20 +71,20 @@ module Sass::Tree
71
71
  to_return << " */\n"
72
72
  end
73
73
 
74
- if @style == :compact
74
+ if style == :compact
75
75
  attributes = attributes.map { |a| a.to_s(1) }.select{|a| a && a.length > 0}.join(' ')
76
76
  to_return << "#{total_rule} { #{attributes} }\n"
77
- elsif @style == :compressed
77
+ elsif style == :compressed
78
78
  attributes = attributes.map { |a| a.to_s(1) }.select{|a| a && a.length > 0}.join(';')
79
79
  to_return << "#{total_rule}{#{attributes}}"
80
80
  else
81
81
  attributes = attributes.map { |a| a.to_s(tabs + 1) }.select{|a| a && a.length > 0}.join("\n")
82
- end_attrs = (@style == :expanded ? "\n" + old_spaces : ' ')
82
+ end_attrs = (style == :expanded ? "\n" + old_spaces : ' ')
83
83
  to_return << "#{total_rule} {\n#{attributes}#{end_attrs}}\n"
84
84
  end
85
85
  end
86
86
 
87
- tabs += 1 unless attributes.empty? || @style != :nested
87
+ tabs += 1 unless attributes.empty? || style != :nested
88
88
  sub_rules.each do |sub|
89
89
  to_return << sub.to_s(tabs, resolved_rules)
90
90
  end
@@ -1,11 +1,11 @@
1
1
  module Sass
2
2
  module Tree
3
3
  class VariableNode < Node
4
- def initialize(name, expr, guarded, options)
4
+ def initialize(name, expr, guarded)
5
5
  @name = name
6
6
  @expr = expr
7
7
  @guarded = guarded
8
- super(options)
8
+ super()
9
9
  end
10
10
 
11
11
  protected
@@ -2,9 +2,9 @@ require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
4
  class WhileNode < Node
5
- def initialize(expr, options)
5
+ def initialize(expr)
6
6
  @expr = expr
7
- super(options)
7
+ super()
8
8
  end
9
9
 
10
10
  private
@@ -85,7 +85,11 @@ class SassEngineTest < Test::Unit::TestCase
85
85
  "& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
86
86
  "a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3],
87
87
  }
88
-
88
+
89
+ def teardown
90
+ clean_up_sassc
91
+ end
92
+
89
93
  def test_basic_render
90
94
  renders_correctly "basic", { :style => :compact }
91
95
  end
@@ -185,7 +189,18 @@ SASS
185
189
  end
186
190
 
187
191
  def test_sass_import
192
+ assert !File.exists?(sassc_path("importee"))
188
193
  renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] }
194
+ assert File.exists?(sassc_path("importee"))
195
+ end
196
+
197
+ def test_no_cache
198
+ assert !File.exists?(sassc_path("importee"))
199
+ renders_correctly("import", {
200
+ :style => :compact, :cache => false,
201
+ :load_paths => [File.dirname(__FILE__) + "/templates"],
202
+ })
203
+ assert !File.exists?(sassc_path("importee"))
189
204
  end
190
205
 
191
206
  def test_units
@@ -750,4 +765,9 @@ SOURCE
750
765
  def filename(name, type)
751
766
  File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
752
767
  end
768
+
769
+ def sassc_path(template)
770
+ sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
771
+ Sass::Files.send(:sassc_filename, sassc_path, Sass::Engine::DEFAULT_OPTIONS)
772
+ end
753
773
  end
@@ -17,6 +17,7 @@ class SassPluginTest < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  def teardown
20
+ clean_up_sassc
20
21
  FileUtils.rm_r tempfile_loc
21
22
  FileUtils.rm_r tempfile_loc(nil,"more_")
22
23
  end
data/test/test_helper.rb CHANGED
@@ -2,6 +2,7 @@ lib_dir = File.dirname(__FILE__) + '/../lib'
2
2
  require File.dirname(__FILE__) + '/linked_rails'
3
3
 
4
4
  require 'test/unit'
5
+ require 'fileutils'
5
6
  $:.unshift lib_dir unless $:.include?(lib_dir)
6
7
  require 'haml'
7
8
  require 'sass'
@@ -18,4 +19,9 @@ class Test::Unit::TestCase
18
19
  test_name = caller[1].gsub(/^.*`(?:\w+ )*(\w+)'.*$/, '\1')
19
20
  opts[:filename] = "#{test_name}_inline.sass"
20
21
  end
22
+
23
+ def clean_up_sassc
24
+ path = File.dirname(__FILE__) + "/../.sass-cache"
25
+ FileUtils.rm_r(path) if File.exist?(path)
26
+ end
21
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.6
4
+ version: 2.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-05-10 00:00:00 -04:00
13
+ date: 2009-05-11 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -91,6 +91,7 @@ files:
91
91
  - lib/sass/tree/rule_node.rb
92
92
  - lib/sass/tree/variable_node.rb
93
93
  - lib/sass/tree/while_node.rb
94
+ - lib/sass/files.rb
94
95
  - bin/css2sass
95
96
  - bin/haml
96
97
  - bin/html2haml