haml-edge 2.3.245 → 2.3.246

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.245
1
+ 2.3.246
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.245
1
+ 2.3.246
data/lib/haml/util.rb CHANGED
@@ -199,22 +199,16 @@ module Haml
199
199
  #
200
200
  # @param x [Array]
201
201
  # @param y [Array]
202
+ # @yield [a, b] An optional block to use in place of a check for equality
203
+ # between elements of `x` and `y`.
204
+ # @yieldreturn [Object, nil] If the two values register as equal,
205
+ # this will return the value to use in the LCS array.
202
206
  # @return [Array] The LCS
203
- def lcs(x, y)
207
+ def lcs(x, y, &block)
204
208
  x = [nil, *x]
205
209
  y = [nil, *y]
206
- lcs_backtrace(lcs_table(x, y), x, y, x.size-1, y.size-1)
207
- end
208
-
209
- # Computes all single longest common subsequences for `x` and `y`.
210
- #
211
- # @param x [Array]
212
- # @param y [Array]
213
- # @return [Set<Array>] The LCSes
214
- def lcs_all(x, y)
215
- x = [nil, *x]
216
- y = [nil, *y]
217
- lcs_backtrace_all(lcs_table(x, y), x, y, x.size-1, y.size-1)
210
+ block ||= proc {|a, b| a == b && a}
211
+ lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
218
212
  end
219
213
 
220
214
  # Returns information about the caller of the previous method.
@@ -600,7 +594,7 @@ METHOD
600
594
  (1...x.size).each do |i|
601
595
  (1...y.size).each do |j|
602
596
  c[i][j] =
603
- if x[i] == y[j]
597
+ if yield x[i], y[j]
604
598
  c[i-1][j-1] + 1
605
599
  else
606
600
  [c[i][j-1], c[i-1][j]].max
@@ -612,22 +606,14 @@ METHOD
612
606
 
613
607
  # Computes a single longest common subsequence for arrays x and y.
614
608
  # Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
615
- def lcs_backtrace(c, x, y, i, j)
609
+ def lcs_backtrace(c, x, y, i, j, &block)
616
610
  return [] if i == 0 || j == 0
617
- return lcs_backtrace(c, x, y, i-1, j-1) << x[i] if x[i] == y[j]
618
- return lcs_backtrace(c, x, y, i, j-1) if c[i][j-1] > c[i-1][j]
619
- return lcs_backtrace(c, x, y, i-1, j)
620
- end
621
-
622
- # Computes all longest common subsequences for arrays x and y.
623
- # Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_all_LCSs)
624
- def lcs_backtrace_all(c, x, y, i, j)
625
- return Set[[]] if i == 0 || j == 0
626
- return lcs_backtrace_all(c, x, y, i-1, j-1).map {|z| z << x[i]}.to_set if x[i] == y[j]
627
- r = Set.new
628
- r.merge(lcs_backtrace_all(c, x, y, i, j-1)) if c[i][j-1] >= c[i-1][j]
629
- r.merge(lcs_backtrace_all(c, x, y, i-1, j)) if c[i-1][j] >= c[i][j-1]
630
- r
611
+ if v = yield(x[i], y[j])
612
+ return lcs_backtrace(c, x, y, i-1, j-1, &block) << v
613
+ end
614
+
615
+ return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
616
+ return lcs_backtrace(c, x, y, i-1, j, &block)
631
617
  end
632
618
  end
633
619
  end
@@ -411,7 +411,18 @@ module Sass
411
411
  (tok(/\*/) && Selector::Universal.new(nil))
412
412
  res << v
413
413
  end
414
- expected('"{"') if tok?(/&/)
414
+
415
+ if tok?(/&/)
416
+ begin
417
+ expected('"{"')
418
+ rescue Sass::SyntaxError => e
419
+ e.message << "\n\n" << <<MESSAGE
420
+ In Sass 3, the parent selector & can only be used where element names are valid,
421
+ since it could potentially be replaced by an element name.
422
+ MESSAGE
423
+ raise e
424
+ end
425
+ end
415
426
 
416
427
  Selector::SimpleSequence.new(res)
417
428
  end
@@ -163,11 +163,16 @@ module Sass
163
163
 
164
164
  seq1 = group_selectors(seq1)
165
165
  seq2 = group_selectors(seq2)
166
- lcs = Haml::Util.lcs(seq2, seq1)
166
+ lcs = Haml::Util.lcs(seq2, seq1) do |s1, s2|
167
+ next s1 if s1 == s2
168
+ next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
169
+ next s2 if subweave_superselector?(s1, s2)
170
+ next s1 if subweave_superselector?(s2, s1)
171
+ end
167
172
 
168
173
  diff = []
169
174
  until lcs.empty?
170
- diff << chunks(seq1, seq2) {|s| s.first == lcs.first} << [lcs.shift]
175
+ diff << chunks(seq1, seq2) {|s| subweave_superselector?(s.first, lcs.first)} << [lcs.shift]
171
176
  seq1.shift
172
177
  seq2.shift
173
178
  end
@@ -201,10 +206,23 @@ module Sass
201
206
  return newseq
202
207
  end
203
208
 
204
- def unify_heads(sseq1, sseq2)
205
- return unless sseq2.size == 1 # Can't unify ".foo > .bar" and ".baz > .bang"
206
- unified = sseq1.last.unify(sseq2.last.members) unless sseq1.last.is_a?(String) || sseq2.last.is_a?(String)
207
- sseq1[0...-1] << unified if unified
209
+ def subweave_superselector?(sseq1, sseq2)
210
+ if sseq1.size > 1
211
+ # More complex selectors are never superselectors of less complex ones
212
+ return unless sseq2.size > 1
213
+ # .foo ~ .bar is a superselector of .foo + .bar
214
+ return unless sseq1[1] == "~" ? sseq2[1] != ">" : sseq2[1] == sseq1[1]
215
+ return unless sseq1.first.superselector?(sseq2.first)
216
+ return true if sseq1.size == 2
217
+ return false if sseq2.size == 2
218
+ return subweave_superselector?(sseq1[2..-1], sseq2[2..-1])
219
+ elsif sseq2.size > 1
220
+ return true if sseq2[1] == ">" && sseq1.first.superselector?(sseq2.first)
221
+ return false if sseq2.size == 2
222
+ return subweave_superselector?(sseq1, sseq2[2..-1])
223
+ else
224
+ sseq1.first.superselector?(sseq2.first)
225
+ end
208
226
  end
209
227
 
210
228
  def _hash
@@ -110,14 +110,11 @@ class UtilTest < Test::Unit::TestCase
110
110
  assert_equal([1, 2], lcs([1, 2, 3, 4], [3, 4, 1, 2]))
111
111
  end
112
112
 
113
- def test_lcs_all
114
- assert_equal(Set[[1, 2, 3]], lcs_all([1, 2, 3], [1, 2, 3]))
115
- assert_equal(Set[[]], lcs_all([], [1, 2, 3]))
116
- assert_equal(Set[[]], lcs_all([1, 2, 3], []))
117
- assert_equal(Set[[1, 2, 3]], lcs_all([5, 1, 4, 2, 3, 17], [0, 0, 1, 2, 6, 3]))
118
-
119
- assert_equal(Set[[1], [2], [3], [4]], lcs_all([1, 2, 3, 4], [4, 3, 2, 1]))
120
- assert_equal(Set[[1, 2], [3, 4]], lcs_all([1, 2, 3, 4], [3, 4, 1, 2]))
113
+ def test_lcs_with_block
114
+ assert_equal(["1", "2", "3"],
115
+ lcs([1, 4, 2, 5, 3], [1, 2, 3]) {|a, b| a == b && a.to_s})
116
+ assert_equal([-4, 2, 8],
117
+ lcs([-5, 3, 2, 8], [-4, 1, 8]) {|a, b| (a - b).abs <= 1 && [a, b].max})
121
118
  end
122
119
 
123
120
  def test_silence_warnings
@@ -1024,6 +1024,26 @@ CSS
1024
1024
  SCSS
1025
1025
  end
1026
1026
 
1027
+ def test_nested_extender_counts_extended_subselectors
1028
+ assert_equal <<CSS, render(<<SCSS)
1029
+ .a .bip.bop .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar {
1030
+ a: b; }
1031
+ CSS
1032
+ .a .bip.bop .foo {a: b}
1033
+ .b .bip .bar {@extend .foo}
1034
+ SCSS
1035
+ end
1036
+
1037
+ def test_nested_extender_counts_extended_superselectors
1038
+ assert_equal <<CSS, render(<<SCSS)
1039
+ .a .bip .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar {
1040
+ a: b; }
1041
+ CSS
1042
+ .a .bip .foo {a: b}
1043
+ .b .bip.bop .bar {@extend .foo}
1044
+ SCSS
1045
+ end
1046
+
1027
1047
  def test_nested_extender_with_child_selector
1028
1048
  assert_equal <<CSS, render(<<SCSS)
1029
1049
  .baz .foo, .baz foo > bar {
@@ -1034,6 +1054,76 @@ foo > bar {@extend .foo}
1034
1054
  SCSS
1035
1055
  end
1036
1056
 
1057
+ def test_nested_extender_finds_common_selectors_around_child_selector
1058
+ assert_equal <<CSS, render(<<SCSS)
1059
+ a > b c .c1, a > b c .c2 {
1060
+ a: b; }
1061
+ CSS
1062
+ a > b c .c1 {a: b}
1063
+ a c .c2 {@extend .c1}
1064
+ SCSS
1065
+
1066
+ assert_equal <<CSS, render(<<SCSS)
1067
+ a > b c .c1, a > b c .c2 {
1068
+ a: b; }
1069
+ CSS
1070
+ a > b c .c1 {a: b}
1071
+ b c .c2 {@extend .c1}
1072
+ SCSS
1073
+ end
1074
+
1075
+ def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector
1076
+ assert_equal <<CSS, render(<<SCSS)
1077
+ a + b c .c1, a + b a c .c2, a a + b c .c2 {
1078
+ a: b; }
1079
+ CSS
1080
+ a + b c .c1 {a: b}
1081
+ a c .c2 {@extend .c1}
1082
+ SCSS
1083
+
1084
+ assert_equal <<CSS, render(<<SCSS)
1085
+ a + b c .c1, a a + b c .c2 {
1086
+ a: b; }
1087
+ CSS
1088
+ a + b c .c1 {a: b}
1089
+ a b .c2 {@extend .c1}
1090
+ SCSS
1091
+
1092
+ assert_equal <<CSS, render(<<SCSS)
1093
+ a + b c .c1, a + b c .c2 {
1094
+ a: b; }
1095
+ CSS
1096
+ a + b c .c1 {a: b}
1097
+ b c .c2 {@extend .c1}
1098
+ SCSS
1099
+ end
1100
+
1101
+ def test_nested_extender_doesnt_find_common_selectors_around_sibling_selector
1102
+ assert_equal <<CSS, render(<<SCSS)
1103
+ a ~ b c .c1, a ~ b a c .c2, a a ~ b c .c2 {
1104
+ a: b; }
1105
+ CSS
1106
+ a ~ b c .c1 {a: b}
1107
+ a c .c2 {@extend .c1}
1108
+ SCSS
1109
+
1110
+ assert_equal <<CSS, render(<<SCSS)
1111
+ a ~ b c .c1, a a ~ b c .c2 {
1112
+ a: b; }
1113
+ CSS
1114
+ a ~ b c .c1 {a: b}
1115
+ a b .c2 {@extend .c1}
1116
+ SCSS
1117
+
1118
+ assert_equal <<CSS, render(<<SCSS)
1119
+ a ~ b c .c1, a ~ b c .c2 {
1120
+ a: b; }
1121
+ CSS
1122
+ a ~ b c .c1 {a: b}
1123
+ b c .c2 {@extend .c1}
1124
+ SCSS
1125
+ end
1126
+
1037
1127
  def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
1038
1128
  assert_equal <<CSS, render(<<SCSS)
1039
1129
  .bip > .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar {
@@ -950,7 +950,12 @@ SCSS
950
950
  end
951
951
 
952
952
  def test_parent_in_mid_selector_error
953
- assert_raise(Sass::SyntaxError, 'Invalid CSS after ".foo": expected "{", was "&.bar"') {render <<SCSS}
953
+ assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
954
+ Invalid CSS after ".foo": expected "{", was "&.bar"
955
+
956
+ In Sass 3, the parent selector & can only be used where element names are valid,
957
+ since it could potentially be replaced by an element name.
958
+ MESSAGE
954
959
  flim {
955
960
  .foo&.bar {a: b}
956
961
  }
@@ -958,7 +963,12 @@ SCSS
958
963
  end
959
964
 
960
965
  def test_parent_in_mid_selector_error
961
- assert_raise(Sass::SyntaxError, 'Invalid CSS after ".foo.bar": expected "{", was "&"') {render <<SCSS}
966
+ assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
967
+ Invalid CSS after ".foo.bar": expected "{", was "&"
968
+
969
+ In Sass 3, the parent selector & can only be used where element names are valid,
970
+ since it could potentially be replaced by an element name.
971
+ MESSAGE
962
972
  flim {
963
973
  .foo.bar& {a: b}
964
974
  }
@@ -966,7 +976,12 @@ SCSS
966
976
  end
967
977
 
968
978
  def test_double_parent_selector_error
969
- assert_raise(Sass::SyntaxError, 'Invalid CSS after "&": expected "{", was "&"') {render <<SCSS}
979
+ assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
980
+ Invalid CSS after "&": expected "{", was "&"
981
+
982
+ In Sass 3, the parent selector & can only be used where element names are valid,
983
+ since it could potentially be replaced by an element name.
984
+ MESSAGE
970
985
  flim {
971
986
  && {a: b}
972
987
  }
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.245
4
+ version: 2.3.246
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-05-07 00:00:00 -04:00
13
+ date: 2010-05-08 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency