Merge commit 'origin/stable' into stable
Conflicts: doc-src/HAML_CHANGELOG.md
This commit is contained in:
commit
802ffa27d4
|
@ -21,6 +21,12 @@
|
|||
but it shouldn't have too much effect and the optimizations
|
||||
will hopefully be re-enabled in version 2.4.
|
||||
|
||||
* Allow multiple ids to be used on the same element.
|
||||
They will be concatenated together with an underscore.
|
||||
For example, `%p#foo#bar` will become `<p id="foo_bar">`.
|
||||
This is consistent with the behavior of multiple ids
|
||||
when one is specified as a standard attribute.
|
||||
|
||||
## [2.2.10](http://github.com/nex3/haml/commit/2.2.10)
|
||||
|
||||
* Fixed a bug where elements with dynamic attributes and no content
|
||||
|
|
|
@ -3,6 +3,17 @@
|
|||
* Table of contents
|
||||
{:toc}
|
||||
|
||||
## 2.2.11 (Unreleased)
|
||||
|
||||
* Added a note to errors on properties that could be pseudo-classes (e.g. `:focus`)
|
||||
indicating that they should be backslash-escaped.
|
||||
|
||||
* Automatically interpret properties that could be pseudo-classes as such
|
||||
if {file:SASS_REFERENCE.md.html#property_syntax-option `:property_syntax`}
|
||||
is set to `:new`.
|
||||
|
||||
* Fixed `css2sass`'s generation of pseudo-classes so that they're backslash-escaped.
|
||||
|
||||
## [2.2.10](http://github.com/nex3/haml/commit/2.2.10)
|
||||
|
||||
* Add support for attribute selectors with spaces around the `=`.
|
||||
|
|
|
@ -479,7 +479,13 @@ END
|
|||
attributes['class'] = ""
|
||||
end
|
||||
attributes['class'] += property
|
||||
when '#'; attributes['id'] = property
|
||||
when '#'
|
||||
if attributes['id']
|
||||
attributes['id'] += "_"
|
||||
else
|
||||
attributes['id'] = ""
|
||||
end
|
||||
attributes['id'] += property
|
||||
end
|
||||
end
|
||||
attributes
|
||||
|
|
|
@ -24,7 +24,9 @@ module Sass
|
|||
class RuleNode
|
||||
# @see Node#to_sass
|
||||
def to_sass(tabs, opts = {})
|
||||
str = "\n#{' ' * tabs}#{rules.first}#{children.any? { |c| c.is_a? PropNode } ? "\n" : ''}"
|
||||
name = rules.first
|
||||
name = "\\" + name if name[0] == ?:
|
||||
str = "\n#{' ' * tabs}#{name}#{children.any? { |c| c.is_a? PropNode } ? "\n" : ''}"
|
||||
|
||||
children.each do |child|
|
||||
str << "#{child.to_sass(tabs + 1, opts)}"
|
||||
|
|
|
@ -314,12 +314,16 @@ LONG
|
|||
def parse_line(parent, line, root)
|
||||
case line.text[0]
|
||||
when PROPERTY_CHAR
|
||||
if line.text[1] != PROPERTY_CHAR
|
||||
parse_property(line, PROPERTY_OLD)
|
||||
else
|
||||
if line.text[1] == PROPERTY_CHAR ||
|
||||
(@options[:property_syntax] == :new &&
|
||||
line.text =~ PROPERTY_OLD && $3.empty?)
|
||||
# Support CSS3-style pseudo-elements,
|
||||
# which begin with ::
|
||||
# which begin with ::,
|
||||
# as well as pseudo-classes
|
||||
# if we're using the new property syntax
|
||||
Tree::RuleNode.new(line.text)
|
||||
else
|
||||
parse_property(line, PROPERTY_OLD)
|
||||
end
|
||||
when Script::VARIABLE_CHAR
|
||||
parse_variable(line)
|
||||
|
|
|
@ -123,7 +123,9 @@ module Sass
|
|||
result = String.new
|
||||
children.each do |child|
|
||||
if child.is_a? PropNode
|
||||
raise Sass::SyntaxError.new('Properties aren\'t allowed at the root of a document.', child.line)
|
||||
message = "Properties aren't allowed at the root of a document." +
|
||||
child.pseudo_class_selector_message
|
||||
raise Sass::SyntaxError.new(message, child.line)
|
||||
else
|
||||
next if child.invisible?
|
||||
child_str = child.to_s(1)
|
||||
|
|
|
@ -54,7 +54,9 @@ module Sass::Tree
|
|||
real_name = "#{parent_name}-#{real_name}" if parent_name
|
||||
|
||||
if value.empty? && children.empty?
|
||||
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value).", @line)
|
||||
message = "Invalid property: #{declaration.dump} (no value)." +
|
||||
pseudo_class_selector_message
|
||||
raise Sass::SyntaxError.new(message, @line)
|
||||
end
|
||||
|
||||
join_string = case style
|
||||
|
@ -76,6 +78,16 @@ module Sass::Tree
|
|||
(style == :compressed && parent_name) ? to_return : to_return[0...-1]
|
||||
end
|
||||
|
||||
# Returns a appropriate message indicating how to escape pseudo-class selectors.
|
||||
# This only applies for old-style properties with no value,
|
||||
# so returns the empty string if this is new-style.
|
||||
#
|
||||
# @return [String] The message
|
||||
def pseudo_class_selector_message
|
||||
return "" if @prop_syntax == :new || !value.empty?
|
||||
"\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead."
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Runs any SassScript that may be embedded in the property.
|
||||
|
@ -103,7 +115,7 @@ module Sass::Tree
|
|||
private
|
||||
|
||||
def declaration
|
||||
@prop_syntax == :new ? "#{name}: #{value}" : ":#{name} #{value}"
|
||||
(@prop_syntax == :new ? "#{name}: #{value}" : ":#{name} #{value}").strip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -278,6 +278,18 @@ RESULT
|
|||
SOURCE
|
||||
end
|
||||
|
||||
def test_multiple_ids
|
||||
assert_equal("<p id='bc_ab'></p>\n", render("%p#bc#ab"))
|
||||
assert_equal("<p id='ab_bc'></p>\n", render("%p#ab#bc"))
|
||||
assert_equal("<p id='ab'></p>\n", render("%p(id='bc' id='ab')"))
|
||||
assert_equal("<p id='bc'></p>\n", render("%p(id='ab' id='bc')"))
|
||||
assert_equal("<p id='bc_ab'></p>\n", render("%p#bc(id='ab')"))
|
||||
assert_equal("<p id='ab_bc'></p>\n", render("%p#ab(id='bc')"))
|
||||
assert_equal("<p id='bc_ab'></p>\n", render("%p#bc{:id => 'ab'}"))
|
||||
assert_equal("<p id='ab_bc'></p>\n", render("%p#ab{:id => 'bc'}"))
|
||||
assert_equal("<p id='ab_bc_cd'></p>\n", render("%p#ab{:id => 'bc'}(id='cd')"))
|
||||
end
|
||||
|
||||
# Regression tests
|
||||
|
||||
def test_whitespace_nuke_with_both_newlines
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<foo2u>11</foo2u>
|
||||
</div>
|
||||
<div class='classes'>
|
||||
<p class='foo bar' id='boom'></p>
|
||||
<p class='foo bar' id='baz_boom'></p>
|
||||
<div class='fooBar'>a</div>
|
||||
<div class='foo-bar'>b</div>
|
||||
<div class='foo_bar'>c</div>
|
||||
|
|
|
@ -230,6 +230,19 @@ SASS
|
|||
CSS
|
||||
end
|
||||
|
||||
def test_pseudo_classes_are_escaped
|
||||
assert_equal(<<SASS, css2sass(<<CSS))
|
||||
\\:focus
|
||||
a: b
|
||||
|
||||
\\:foo
|
||||
bar: baz
|
||||
SASS
|
||||
:focus {a: b;}
|
||||
:focus :foo {bar: baz;}
|
||||
CSS
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def css2sass(string, opts={})
|
||||
|
|
|
@ -18,8 +18,11 @@ class SassEngineTest < Test::Unit::TestCase
|
|||
":" => 'Invalid property: ":".',
|
||||
": a" => 'Invalid property: ": a".',
|
||||
":= a" => 'Invalid property: ":= a".',
|
||||
"a\n :b" => 'Invalid property: ":b " (no value).',
|
||||
"a\n b:" => 'Invalid property: "b: " (no value).',
|
||||
"a\n :b" => <<MSG,
|
||||
Invalid property: ":b" (no value).
|
||||
If ":b" should be a selector, use "\\:b" instead.
|
||||
MSG
|
||||
"a\n b:" => 'Invalid property: "b:" (no value).',
|
||||
"a\n :b: c" => 'Invalid property: ":b: c".',
|
||||
"a\n :b:c d" => 'Invalid property: ":b:c d".',
|
||||
"a\n :b=c d" => 'Invalid property: ":b=c d".',
|
||||
|
@ -27,7 +30,12 @@ class SassEngineTest < Test::Unit::TestCase
|
|||
"a\n b: c;" => 'Invalid property: "b: c;" (no ";" required at end-of-line).',
|
||||
"a\n b : c" => 'Invalid property: "b : c".',
|
||||
"a\n b=c: d" => 'Invalid property: "b=c: d".',
|
||||
":a" => 'Properties aren\'t allowed at the root of a document.',
|
||||
":a b" => 'Properties aren\'t allowed at the root of a document.',
|
||||
"a:" => 'Properties aren\'t allowed at the root of a document.',
|
||||
":a" => <<MSG,
|
||||
Properties aren't allowed at the root of a document.
|
||||
If ":a" should be a selector, use "\\:a" instead.
|
||||
MSG
|
||||
"!" => 'Invalid variable: "!".',
|
||||
"!a" => 'Invalid variable: "!a".',
|
||||
"! a" => 'Invalid variable: "! a".',
|
||||
|
@ -134,7 +142,7 @@ class SassEngineTest < Test::Unit::TestCase
|
|||
rescue Sass::SyntaxError => err
|
||||
value = [value] unless value.is_a?(Array)
|
||||
|
||||
assert_equal(value.first, err.message, "Line: #{key}")
|
||||
assert_equal(value.first.rstrip, err.message, "Line: #{key}")
|
||||
assert_equal(__FILE__, err.sass_filename)
|
||||
assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
|
||||
assert_match(/#{Regexp.escape(__FILE__)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
|
||||
|
@ -737,6 +745,27 @@ bang, bip, bop
|
|||
SASS
|
||||
end
|
||||
|
||||
def test_root_level_pseudo_class_with_new_properties
|
||||
assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
|
||||
:focus {
|
||||
outline: 0; }
|
||||
CSS
|
||||
:focus
|
||||
outline: 0
|
||||
SASS
|
||||
end
|
||||
|
||||
def test_pseudo_class_with_new_properties
|
||||
assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
|
||||
p :focus {
|
||||
outline: 0; }
|
||||
CSS
|
||||
p
|
||||
:focus
|
||||
outline: 0
|
||||
SASS
|
||||
end
|
||||
|
||||
# Regression tests
|
||||
|
||||
def test_parens_in_mixins
|
||||
|
|
Loading…
Reference in New Issue