haml-edge 2.3.193 → 2.3.194

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.3.193
1
+ 2.3.194
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.193
1
+ 2.3.194
data/lib/sass/engine.rb CHANGED
@@ -6,7 +6,6 @@ require 'sass/tree/rule_node'
6
6
  require 'sass/tree/comment_node'
7
7
  require 'sass/tree/prop_node'
8
8
  require 'sass/tree/directive_node'
9
- require 'sass/tree/raw_node'
10
9
  require 'sass/tree/variable_node'
11
10
  require 'sass/tree/mixin_def_node'
12
11
  require 'sass/tree/mixin_node'
@@ -462,10 +461,13 @@ WARNING
462
461
 
463
462
  # If value begins with url( or ",
464
463
  # it's a CSS @import rule and we don't want to touch it.
465
- if directive == "import" && value !~ /^(url\(|")/
464
+ if directive == "import" && value !~ /^(url\(|["'])/
466
465
  raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
467
466
  :line => @line + 1) unless line.children.empty?
468
- value.split(/,\s*/).map {|f| Tree::ImportNode.new(f)}
467
+ value.split(/,\s*/).map do |f|
468
+ f = $1 || $2 || $3 if f =~ Sass::SCSS::RX::STRING || f =~ Sass::SCSS::RX::URI
469
+ Tree::ImportNode.new(f)
470
+ end
469
471
  elsif directive == "mixin"
470
472
  parse_mixin_definition(line)
471
473
  elsif directive == "include"
@@ -486,10 +488,6 @@ WARNING
486
488
  :line => @line + 1) unless line.children.empty?
487
489
  offset = line.offset + line.text.index(value).to_i
488
490
  Tree::DebugNode.new(parse_script(value, :offset => offset))
489
- elsif directive == "raw"
490
- raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath raw directives.",
491
- :line => @line + 1) unless line.children.empty?
492
- Tree::RawNode.new(value)
493
491
  else
494
492
  Tree::DirectiveNode.new(line.text)
495
493
  end
@@ -7,10 +7,7 @@ module Sass
7
7
 
8
8
  def string(*args)
9
9
  return unless scan(STRING)
10
- str = (@scanner[1] || @scanner[2]).
11
- gsub(/\\([^0-9a-f])/, '\1').
12
- gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1")
13
- [:string, Script::String.new(str, :string)]
10
+ [:string, Script::String.new((@scanner[1] || @scanner[2]).gsub(/\\(['"])/, '\1'), :string)]
14
11
  end
15
12
 
16
13
  def important
@@ -237,13 +237,13 @@ module Sass
237
237
 
238
238
  def ident
239
239
  return unless s = scan(REGULAR_EXPRESSIONS[:ident])
240
- [:ident, s.gsub(/\\(.)/, '\1')]
240
+ [:ident, s]
241
241
  end
242
242
 
243
243
  def string(re, open)
244
244
  return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
245
245
  @interpolation_stack << re if @scanner[2].empty? # Started an interpolated section
246
- [:string, Script::String.new(@scanner[1].gsub(/\\([^0-9a-f])/, '\1').gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1"), :string)]
246
+ [:string, Script::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string)]
247
247
  end
248
248
 
249
249
  def number
@@ -55,8 +55,6 @@ module Sass::Script
55
55
  return self.value
56
56
  end
57
57
 
58
- # Replace single backslashes with double. Really.
59
- value = self.value.gsub("\\", "\\\\\\\\")
60
58
  return "\"#{value.gsub('"', "\\\"")}\"" if opts[:quote] == %q{"}
61
59
  return "'#{value.gsub("'", "\\'")}'" if opts[:quote] == %q{'}
62
60
  return "\"#{value}\"" unless value.include?('"')
@@ -11,10 +11,31 @@ module Sass::Script
11
11
  end
12
12
 
13
13
  def to_sass(opts = {})
14
+ # We can get rid of all of this when we remove the deprecated :equals context
15
+ before_unquote, before_quote_char, before_str = parse_str(@before.to_sass(opts))
16
+ after_unquote, after_quote_char, after_str = parse_str(@after.to_sass(opts))
17
+ unquote = before_unquote || after_unquote ||
18
+ (before_quote_char && !after_quote_char && !after_str.empty?) ||
19
+ (!before_quote_char && after_quote_char && !before_str.empty?)
20
+ quote_char =
21
+ if before_quote_char && after_quote_char && before_quote_char != after_quote_char
22
+ before_str.gsub!("\\'", "'")
23
+ before_str.gsub!('"', "\\\"")
24
+ after_str.gsub!("\\'", "'")
25
+ after_str.gsub!('"', "\\\"")
26
+ '"'
27
+ else
28
+ before_quote_char || after_quote_char
29
+ end
30
+
14
31
  res = ""
15
- res << @before.to_sass(opts)[0...-1]
32
+ res << 'unquote(' if unquote
33
+ res << quote_char if quote_char
34
+ res << before_str
16
35
  res << '#{' << @mid.to_sass(opts) << '}'
17
- res << @after.to_sass(opts)[1..-1]
36
+ res << after_str
37
+ res << quote_char if quote_char
38
+ res << ')' if unquote
18
39
  res
19
40
  end
20
41
 
@@ -32,5 +53,18 @@ module Sass::Script
32
53
  res << @after.perform(environment).value
33
54
  Sass::Script::String.new(res, :string)
34
55
  end
56
+
57
+ def parse_str(str)
58
+ case str
59
+ when /^unquote\((["'])(.*)\1\)$/
60
+ return true, $1, $2
61
+ when '""'
62
+ return false, nil, ""
63
+ when /^(["'])(.*)\1$/
64
+ return false, $1, $2
65
+ else
66
+ return false, nil, str
67
+ end
68
+ end
35
69
  end
36
70
  end
@@ -276,13 +276,6 @@ module Sass
276
276
  node.has_children = true
277
277
  tok!(/\{/)
278
278
  block_contents(node, context)
279
-
280
- # Support the hack of having # after all properties.
281
- if context == :ruleset && tok(/#/)
282
- node << Sass::Tree::RawNode.new("#")
283
- ss
284
- end
285
-
286
279
  tok!(/\}/)
287
280
  node
288
281
  end
@@ -383,10 +376,8 @@ module Sass
383
376
  ['.', expr!(:interp_ident)]
384
377
  end
385
378
 
386
- # @private
387
- ID_START = /#(?=#{NMCHAR})/
388
379
  def id_selector
389
- return unless tok(ID_START)
380
+ return unless tok(/#(?!\{)/)
390
381
  @expected = "id name"
391
382
  ['#', expr!(:interp_name)]
392
383
  end
@@ -463,8 +454,8 @@ module Sass
463
454
 
464
455
  def declaration
465
456
  # This allows the "*prop: val", ":prop: val", and ".prop: val" hacks
466
- if s = tok(/[:\*\.]/)
467
- @use_property_exception = s != '.'
457
+ if s = tok(/[:\*\.]|\#(?!\{)/)
458
+ @use_property_exception = s !~ /[\.\#]/
468
459
  name = [s, str{ss}, *expr!(:interp_ident)]
469
460
  else
470
461
  return unless name = interp_ident
@@ -665,15 +656,6 @@ MESSAGE
665
656
  pos = scanner.pos
666
657
 
667
658
  after = scanner.string[0...pos]
668
- was = scanner.rest.dup
669
-
670
- # We support the foo {a: b; #} hack,
671
- # but we don't want it cluttering our errors.
672
- if after =~ /\#$/ && expected == '"}"'
673
- after.slice!(-1)
674
- was = '#' + was
675
- end
676
-
677
659
  # Get rid of whitespace between pos and the last token,
678
660
  # but only if there's a newline in there
679
661
  after.gsub!(/\s*\n\s*$/, '')
@@ -681,6 +663,7 @@ MESSAGE
681
663
  after.gsub!(/.*\n/, '')
682
664
  after = "..." + after[-15..-1] if after.size > 18
683
665
 
666
+ was = scanner.rest.dup
684
667
  # Get rid of whitespace between pos and the next token,
685
668
  # but only if there's a newline in there
686
669
  was.gsub!(/^\s*\n\s*/, '')
@@ -80,6 +80,10 @@ module Sass::Tree
80
80
 
81
81
  def to_src(tabs, opts, fmt)
82
82
  name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
83
+ if name[0] == ?:
84
+ raise Sass::SyntaxError.new("The \":#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
85
+ end
86
+
83
87
  old = opts[:old] && fmt == :sass
84
88
  initial = old ? ':' : ''
85
89
  mid = old ? '' : ':'
@@ -777,18 +777,71 @@ SCSS
777
777
  assert_sass_to_scss '$var: 12px $bar baz !default;', '$var ||= 12px $bar "baz"'
778
778
  end
779
779
 
780
- def test_hash_hack
780
+ # Hacks
781
+
782
+ def test_declaration_hacks
781
783
  assert_renders <<SASS, <<SCSS
782
784
  foo
783
- bar: baz
784
- @raw #
785
+ _name: val
786
+ *name: val
787
+ #name: val
788
+ .name: val
789
+ name: val
785
790
  SASS
786
791
  foo {
787
- bar: baz;
788
- # }
792
+ _name: val;
793
+ *name: val;
794
+ #name: val;
795
+ .name: val;
796
+ name: val; }
789
797
  SCSS
790
798
  end
791
799
 
800
+ def test_old_declaration_hacks
801
+ assert_renders <<SASS, <<SCSS, :old => true
802
+ foo
803
+ :_name val
804
+ :*name val
805
+ :#name val
806
+ :.name val
807
+ :name val
808
+ SASS
809
+ foo {
810
+ _name: val;
811
+ *name: val;
812
+ #name: val;
813
+ .name: val;
814
+ name: val; }
815
+ SCSS
816
+ end
817
+
818
+ def test_selector_hacks
819
+ assert_selector_renders = lambda do |s|
820
+ assert_renders <<SASS, <<SCSS
821
+ #{s}
822
+ a: b
823
+ SASS
824
+ #{s} {
825
+ a: b; }
826
+ SCSS
827
+ end
828
+
829
+ assert_selector_renders['> E']
830
+ assert_selector_renders['+ E']
831
+ assert_selector_renders['~ E']
832
+ assert_selector_renders['>> E']
833
+
834
+ assert_selector_renders['E*']
835
+ assert_selector_renders['E*.foo']
836
+ assert_selector_renders['E*:hover']
837
+ end
838
+
839
+ def test_disallowed_colon_hack
840
+ assert_raise(Sass::SyntaxError, '":foo: bar" is not allowed in the Sass syntax') do
841
+ to_sass("foo {:name: val;}", :syntax => :scss)
842
+ end
843
+ end
844
+
792
845
  # Sass 3 Deprecation conversions
793
846
 
794
847
  def test_simple_quoted_strings_unquoted_with_equals
@@ -56,7 +56,6 @@ MSG
56
56
  "@import foo.sass" => "File to import not found or unreadable: foo.sass.",
57
57
  "a,\n$b: 1" => ["Rules can\'t end in commas.", 1],
58
58
  "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
59
- "@raw foo {}\n a: b\n" => "Illegal nesting: Nothing may be nested beneath raw directives.",
60
59
  "@import foo.sass" => <<MSG,
61
60
  File to import not found or unreadable: foo.sass.
62
61
  Load paths:
@@ -590,20 +589,6 @@ END
590
589
  assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
591
590
  end
592
591
 
593
- def test_raw_directive
594
- assert_equal(<<CSS, render(<<SASS))
595
- foo {
596
- bar {
597
- baz: bang;
598
- # }
599
- CSS
600
- @raw foo {
601
- bar
602
- baz: bang
603
- @raw #
604
- SASS
605
- end
606
-
607
592
  def test_line_annotations
608
593
  assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
609
594
  /* line 2, test_line_annotations_inline.sass */
@@ -1906,3 +1891,4 @@ SASS
1906
1891
  Sass::Files.send(:sassc_filename, sassc_path, Sass::Engine::DEFAULT_OPTIONS)
1907
1892
  end
1908
1893
  end
1894
+
@@ -1,7 +1,7 @@
1
- #main { content: Hello!; qstr: 'Quo"ted"!'; hstr: Hyph-en!; width: 30em; background-color: black; color: #ffffaa; short-color: #112233; named-color: olive; con: "foo" bar(9 hi there "boom"); con2: "noquo" quo; }
2
- #main #sidebar { background-color: #00ff98; num-normal: 10; num-dec: 10.2; num-dec0: 99; num-neg: -10; esc: 10 +12; many: 6; order: 7; complex: #4c9db1hi16; }
1
+ #main { content: Hello\!; qstr: 'Quo"ted"!'; hstr: Hyph-en\!; width: 30em; background-color: black; color: #ffffaa; short-color: #112233; named-color: olive; con: "foo" bar(9 hi there "boom"); con2: "noquo" quo; }
2
+ #main #sidebar { background-color: #00ff98; num-normal: 10; num-dec: 10.2; num-dec0: 99; num-neg: -10; esc: 10 \+12; many: 6; order: 7; complex: #4c9db1hi16; }
3
3
 
4
- #plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: #b7b7b7; num-perc: 31%; str-str: "hi there"; str-str2: "hi there"; str-col: "14em solid #112233"; str-num: "times: 13"; col-num: #ff7b9d; col-col: #5173ff; }
4
+ #plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: #b7b7b7; num-perc: 31%; str-str: "hi\ there"; str-str2: "hi there"; str-col: "14em solid #112233"; str-num: "times: 13"; col-num: #ff7b9d; col-col: #5173ff; }
5
5
 
6
6
  #minus { num-num: 900; col-num: #f9f9f4; col-col: #000035; unary-num: -1; unary-const: 10; unary-paren: -11; unary-two: 12; unary-many: 12; unary-crazy: -15; }
7
7
 
@@ -11,6 +11,6 @@
11
11
 
12
12
  #mod { num-num: 2; col-col: #0f0e05; col-num: #020001; }
13
13
 
14
- #const { escaped-quote: $foo !bar; default: Hello! !important; }
14
+ #const { escaped-quote: \$foo \!bar; default: Hello\! !important; }
15
15
 
16
16
  #regression { a: 4; }
@@ -161,7 +161,23 @@ RUBY
161
161
  assert_renders '"foo #{$bar} #{$bang} baz"'
162
162
  assert_renders '"#{$bar}baz"'
163
163
  assert_renders '"foo#{$bar}"'
164
- assert_renders '"#{$bar}"'
164
+ assert_equal '#{$bar}', render('"#{$bar}"')
165
+
166
+ assert_equal '"foo#{$bar}baz"', render("'foo\#{$bar}baz'")
167
+ end
168
+
169
+ def test_sass2_string_interpolation
170
+ assert_equal 'foo#{$bar}baz', render('"foo#{$bar}baz"', :context => :equals)
171
+ assert_equal '#{$bar}baz', render('"#{$bar}baz"', :context => :equals)
172
+ assert_equal 'foo#{$bar}', render('"foo#{$bar}"', :context => :equals)
173
+
174
+ assert_equal 'unquote(".foo#{$bar}.bar")', render('".foo#{$bar}.bar"', :context => :equals)
175
+ assert_equal 'unquote(".foo#{$bar}")', render('".foo#{$bar}"', :context => :equals)
176
+ assert_equal 'unquote("#{$bar}.bar")', render('"#{$bar}.bar"', :context => :equals)
177
+
178
+ assert_equal "unquote(\"f'o\#{$bar}b'z\")", render("'f\\'o\#{$bar}b\\'z'", :context => :equals)
179
+ assert_equal "unquote('f\"o\#{$bar}b\"z')", render("'f\\\"o\#{$bar}b\\\"z'", :context => :equals)
180
+ assert_equal "unquote(\"f'o\#{$bar}b\\\"z\")", render("'f\\'o\#{$bar}b\\\"z'", :context => :equals)
165
181
  end
166
182
 
167
183
  private
@@ -172,6 +188,8 @@ RUBY
172
188
 
173
189
  def render(script, options = {})
174
190
  munge_filename(options)
175
- Sass::Script.parse(script, 1, 0, options).to_sass
191
+ node = Sass::Script.parse(script, 1, 0, options)
192
+ node.context = options[:context] if options[:context]
193
+ node.to_sass
176
194
  end
177
195
  end
@@ -25,12 +25,12 @@ class SassScriptTest < Test::Unit::TestCase
25
25
  def test_string_escapes
26
26
  assert_equal "'", resolve("\"'\"")
27
27
  assert_equal '"', resolve("\"\\\"\"")
28
- assert_equal "\\", resolve("\"\\\\\"")
28
+ assert_equal "\\\\", resolve("\"\\\\\"")
29
29
  assert_equal "\\02fa", resolve("\"\\02fa\"")
30
30
 
31
31
  assert_equal "'", resolve("'\\''")
32
32
  assert_equal '"', resolve("'\"'")
33
- assert_equal "\\", resolve("'\\\\'")
33
+ assert_equal "\\\\", resolve("'\\\\'")
34
34
  assert_equal "\\02fa", resolve("'\\02fa'")
35
35
  end
36
36
 
@@ -290,7 +290,7 @@ SASS
290
290
  assert_equal "teal(12)", resolve("teal(12)")
291
291
  assert_equal "tealbang(12)", resolve("tealbang(12)")
292
292
  assert_equal "teal-bang(12)", resolve("teal-bang(12)")
293
- assert_equal "teal+bang(12)", resolve("teal\\+bang(12)")
293
+ assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
294
294
  end
295
295
 
296
296
  def test_interpolation_after_hash
@@ -348,6 +348,7 @@ foo {
348
348
  *name: val;
349
349
  :name: val;
350
350
  .name: val;
351
+ #name: val;
351
352
  name: val; }
352
353
  SCSS
353
354
  end
@@ -356,8 +357,8 @@ SCSS
356
357
  assert_parses <<SCSS
357
358
  foo {
358
359
  foo: bar;
359
- baz: bang;
360
- # }
360
+ #baz: bang;
361
+ #bip: bop; }
361
362
  SCSS
362
363
  end
363
364
 
@@ -399,6 +400,28 @@ foo {
399
400
  SCSS
400
401
  end
401
402
 
403
+ def test_css_string_escapes
404
+ assert_parses <<SCSS
405
+ foo {
406
+ a: "\\foo bar";
407
+ b: "foo\\ bar";
408
+ c: "\\2022 \\0020";
409
+ d: "foo\\\\bar";
410
+ e: "foo\\"'bar"; }
411
+ SCSS
412
+ end
413
+
414
+ def test_css_ident_escapes
415
+ assert_parses <<SCSS
416
+ foo {
417
+ a: \\foo bar;
418
+ b: foo\\ bar;
419
+ c: \\2022 \\0020;
420
+ d: foo\\\\bar;
421
+ e: foo\\"\\'bar; }
422
+ SCSS
423
+ end
424
+
402
425
  ## Directives
403
426
 
404
427
  def test_charset_directive
@@ -789,7 +812,7 @@ SCSS
789
812
 
790
813
  def test_no_nested_rules
791
814
  assert_not_parses('":"', 'foo {bar <err>{a: b}}')
792
- assert_not_parses('"}"', 'foo {<err>#bar {a: b}}')
815
+ assert_not_parses('"}"', 'foo {<err>[bar=baz] {a: b}}')
793
816
  end
794
817
 
795
818
  def test_no_nested_properties
@@ -3,7 +3,7 @@ $preconst: hello
3
3
  =premixin
4
4
  pre-mixin: here
5
5
 
6
- @import importee.sass, scss_importee, basic.sass, basic.css, ../results/complex.css, partial.sass
6
+ @import importee.sass, scss_importee, "basic.sass", basic.css, ../results/complex.css, url(partial.sass)
7
7
 
8
8
  nonimported
9
9
  :myconst $preconst
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.3.193
4
+ version: 2.3.194
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: 2010-04-08 00:00:00 -04:00
13
+ date: 2010-04-09 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -118,7 +118,6 @@ files:
118
118
  - lib/sass/tree/rule_node.rb
119
119
  - lib/sass/tree/variable_node.rb
120
120
  - lib/sass/tree/while_node.rb
121
- - lib/sass/tree/raw_node.rb
122
121
  - lib/sass/tree/root_node.rb
123
122
  - lib/sass/scss/css_parser.rb
124
123
  - lib/sass/scss/parser.rb
@@ -1,33 +0,0 @@
1
- module Sass::Tree
2
- # A static node representing raw CSS.
3
- # This simply renders a string value.
4
- #
5
- # @see Sass::Tree
6
- class RawNode < Node
7
- # The text of the hack.
8
- #
9
- # @return [String]
10
- attr_accessor :value
11
-
12
- # @param value [String] See \{#value}
13
- def initialize(value)
14
- @value = value
15
- super()
16
- end
17
-
18
- protected
19
-
20
- def to_src(tabs, opts, fmt)
21
- return "#{' ' * tabs}#{value}" if fmt == :scss
22
- "#{' ' * tabs}@raw #{value}"
23
- end
24
-
25
- # Returns the value of the node.
26
- #
27
- # @param tabs [Fixnum] The level of indentation for the CSS
28
- # @return [String] The resulting CSS
29
- def _to_s(tabs)
30
- "#{' ' * (tabs - 1)}#{value}"
31
- end
32
- end
33
- end