mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
[Sass] Change the behavior of Sass strings.
This still has a few ConversionTest failures.
This commit is contained in:
parent
e814ff6608
commit
397cd62c5f
14 changed files with 92 additions and 68 deletions
|
@ -407,11 +407,14 @@ WARNING
|
|||
raise SyntaxError.new("Invalid property: \"#{line.text}\".",
|
||||
:line => @line) if name.nil? || value.nil?
|
||||
|
||||
expr = if (eq.strip[0] == SCRIPT_CHAR)
|
||||
[parse_script(value, :offset => line.offset + line.text.index(value))]
|
||||
else
|
||||
parse_interp(value)
|
||||
end
|
||||
expr =
|
||||
if (eq.strip[0] == SCRIPT_CHAR)
|
||||
e = parse_script(value, :offset => line.offset + line.text.index(value))
|
||||
e.context = :equals
|
||||
[e]
|
||||
else
|
||||
parse_interp(value)
|
||||
end
|
||||
Tree::PropNode.new(
|
||||
parse_interp(name), expr,
|
||||
property_regx == PROPERTY_OLD ? :old : :new)
|
||||
|
@ -425,7 +428,9 @@ WARNING
|
|||
:line => @line) unless name && value
|
||||
Script.var_warning(name, @line, line.offset + 1, @options[:filename]) if line.text[0] == ?!
|
||||
|
||||
Tree::VariableNode.new(name, parse_script(value, :offset => line.offset + line.text.index(value)), op == '||=')
|
||||
expr = parse_script(value, :offset => line.offset + line.text.index(value))
|
||||
expr.context = :equals
|
||||
Tree::VariableNode.new(name, expr, op == '||=')
|
||||
end
|
||||
|
||||
def parse_comment(line)
|
||||
|
|
|
@ -22,6 +22,7 @@ module Sass
|
|||
def initialize(name, args)
|
||||
@name = name
|
||||
@args = args
|
||||
super()
|
||||
end
|
||||
|
||||
# @return [String] A string representation of the function call
|
||||
|
|
|
@ -677,6 +677,11 @@ module Sass::Script
|
|||
numeric_transformation(value) {|n| n.abs}
|
||||
end
|
||||
|
||||
def unquote(value)
|
||||
assert_type value, :String
|
||||
Sass::Script::String.new(value.value)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This method implements the pattern of transforming a numeric value into
|
||||
|
|
|
@ -21,6 +21,7 @@ module Sass::Script
|
|||
# @param value [Object] The object for \{#value}
|
||||
def initialize(value = nil)
|
||||
@value = value
|
||||
super()
|
||||
end
|
||||
|
||||
# Returns an empty array.
|
||||
|
@ -125,6 +126,9 @@ MSG
|
|||
# @return [Script::String] A string containing both literals
|
||||
# without any separation
|
||||
def plus(other)
|
||||
if other.is_a?(Sass::Script::String)
|
||||
return Sass::Script::String.new(self.to_s + other.value, other.type)
|
||||
end
|
||||
Sass::Script::String.new(self.to_s + other.to_s)
|
||||
end
|
||||
|
||||
|
|
|
@ -8,6 +8,18 @@ module Sass::Script
|
|||
# @return [{Symbol => Object}]
|
||||
attr_reader :options
|
||||
|
||||
# The context in which this node was parsed,
|
||||
# which determines how some operations are performed.
|
||||
#
|
||||
# Can be `:equals`, which means it's part of a `$var = val` or `prop = val` assignment,
|
||||
# or `:default`, which means it's anywhere else
|
||||
# (including `$var: val` and `prop: val` assignments,
|
||||
# `#{}`-interpolations,
|
||||
# and other script contexts such as `@if` conditions).
|
||||
#
|
||||
# @return [Symbol]
|
||||
attr_reader :context
|
||||
|
||||
# The line of the document on which this node appeared.
|
||||
#
|
||||
# @return [Fixnum]
|
||||
|
@ -23,6 +35,21 @@ module Sass::Script
|
|||
children.each {|c| c.options = options}
|
||||
end
|
||||
|
||||
# Sets the options hash for this node,
|
||||
# as well as for all child nodes.
|
||||
#
|
||||
# @param context [Symbol]
|
||||
# @see #context
|
||||
def context=(context)
|
||||
@context = context
|
||||
children.each {|c| c.context = context}
|
||||
end
|
||||
|
||||
# Creates a new script node.
|
||||
def initialize
|
||||
@context = :default
|
||||
end
|
||||
|
||||
# Evaluates the node.
|
||||
#
|
||||
# \{#perform} shouldn't be overridden directly;
|
||||
|
|
|
@ -21,6 +21,7 @@ module Sass::Script
|
|||
@operand1 = operand1
|
||||
@operand2 = operand2
|
||||
@operator = operator
|
||||
super()
|
||||
end
|
||||
|
||||
# @return [String] A human-readable s-expression representation of the operation
|
||||
|
|
|
@ -35,6 +35,7 @@ module Sass
|
|||
expr = assert_expr :expr
|
||||
assert_tok :end_interpolation
|
||||
expr.options = @options
|
||||
expr.context = :interpolated
|
||||
expr
|
||||
rescue Sass::SyntaxError => e
|
||||
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
||||
|
@ -213,14 +214,6 @@ RUBY
|
|||
if color = Color::HTML4_COLORS[name.value]
|
||||
return node(Color.new(color))
|
||||
end
|
||||
|
||||
filename = @options[:filename]
|
||||
warn(<<END)
|
||||
DEPRECATION WARNING:
|
||||
On line #{name.line}, character #{name.offset}#{" of '#{filename}'" if filename}
|
||||
Implicit strings have been deprecated and will be removed in version 3.0.
|
||||
'#{name.value}' was not quoted. Please add double quotes (e.g. "#{name.value}").
|
||||
END
|
||||
node(Script::String.new(name.value, :identifier))
|
||||
else
|
||||
args = arglist || []
|
||||
|
|
|
@ -7,7 +7,6 @@ module Sass::Script
|
|||
#
|
||||
# @return [String]
|
||||
attr_reader :value
|
||||
alias_method :to_s, :value
|
||||
|
||||
# Whether this is a CSS string or a CSS identifier.
|
||||
# The difference is that strings are written with double-quotes,
|
||||
|
@ -16,6 +15,11 @@ module Sass::Script
|
|||
# @return [Symbol] `:string` or `:identifier`
|
||||
attr_reader :type
|
||||
|
||||
def context=(context)
|
||||
super
|
||||
@type = :identifier if context == :equals
|
||||
end
|
||||
|
||||
# Creates a new string.
|
||||
#
|
||||
# @param value [String] See \{#value}
|
||||
|
@ -25,8 +29,20 @@ module Sass::Script
|
|||
@type = type
|
||||
end
|
||||
|
||||
def plus(other)
|
||||
other_str = other.is_a?(Sass::Script::String) ? other.value : other.to_s
|
||||
Sass::Script::String.new(self.value + other_str, self.type)
|
||||
end
|
||||
|
||||
# @see Node#to_s
|
||||
def to_s
|
||||
to_sass
|
||||
end
|
||||
|
||||
# @param type [Symbol] The type of string to render this as.
|
||||
# `:string`s have double quotes, `:identifier`s do not.
|
||||
# @see Node#to_sass
|
||||
def to_sass
|
||||
def to_sass(type = self.type)
|
||||
return self.value if type == :identifier
|
||||
|
||||
# Replace single backslashes with double. Really.
|
||||
|
|
|
@ -10,6 +10,7 @@ module Sass::Script
|
|||
def initialize(operand, operator)
|
||||
@operand = operand
|
||||
@operator = operator
|
||||
super()
|
||||
end
|
||||
|
||||
# @return [String] A human-readable s-expression representation of the operation
|
||||
|
|
|
@ -10,6 +10,7 @@ module Sass
|
|||
# @param name [String] See \{#name}
|
||||
def initialize(name)
|
||||
@name = name
|
||||
super()
|
||||
end
|
||||
|
||||
# @return [String] A string representation of the variable
|
||||
|
|
|
@ -253,6 +253,7 @@ module Sass
|
|||
tok!(/=/)
|
||||
ss
|
||||
expr = sass_script(:parse)
|
||||
expr.context = :equals
|
||||
|
||||
node(Sass::Tree::VariableNode.new(name, expr, guarded))
|
||||
end
|
||||
|
@ -496,8 +497,10 @@ module Sass
|
|||
def script_value
|
||||
return unless tok(/=/)
|
||||
@use_property_exception = true
|
||||
expr = sass_script(:parse)
|
||||
expr.context = :equals
|
||||
# expression, space, value
|
||||
return true, true, [sass_script(:parse)]
|
||||
return true, true, [expr]
|
||||
end
|
||||
|
||||
def plain_value
|
||||
|
|
|
@ -22,6 +22,7 @@ module Sass
|
|||
# variable and mixin values
|
||||
def _perform(environment)
|
||||
res = @expr.perform(environment)
|
||||
res = res.value if res.is_a?(Sass::Script::String)
|
||||
if filename
|
||||
$stderr.puts "#{filename}:#{line} DEBUG: #{res}"
|
||||
else
|
||||
|
|
|
@ -304,7 +304,10 @@ module Sass
|
|||
def run_interp(text, environment)
|
||||
text.map do |r|
|
||||
next r if r.is_a?(String)
|
||||
r.perform(environment).to_s
|
||||
val = r.perform(environment)
|
||||
# Interpolated strings should never render with quotes
|
||||
next val.value if val.is_a?(Sass::Script::String)
|
||||
val.to_s
|
||||
end.join.strip
|
||||
end
|
||||
|
||||
|
|
|
@ -92,11 +92,9 @@ class SassScriptTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_implicit_strings
|
||||
silence_warnings do
|
||||
assert_equal Sass::Script::String.new("foo"), eval("foo")
|
||||
assert_equal Sass::Script::String.new("foo bar"), eval("foo bar")
|
||||
assert_equal Sass::Script::String.new("foo/bar"), eval("foo/bar")
|
||||
end
|
||||
assert_equal Sass::Script::String.new("foo"), eval("foo")
|
||||
assert_equal Sass::Script::String.new("foo bar"), eval("foo bar")
|
||||
assert_equal Sass::Script::String.new("foo/bar"), eval("foo/bar")
|
||||
end
|
||||
|
||||
def test_interpolation
|
||||
|
@ -130,50 +128,14 @@ foo \#{"\\\#{" + "baz"} bang
|
|||
SASS
|
||||
end
|
||||
|
||||
def test_implicit_string_warning
|
||||
assert_warning(<<WARN) {eval("foo")}
|
||||
DEPRECATION WARNING:
|
||||
On line 1, character 1 of 'test_implicit_string_warning_inline.sass'
|
||||
Implicit strings have been deprecated and will be removed in version 3.0.
|
||||
'foo' was not quoted. Please add double quotes (e.g. "foo").
|
||||
WARN
|
||||
assert_warning(<<WARN) {eval("1 + foo")}
|
||||
DEPRECATION WARNING:
|
||||
On line 1, character 5 of 'test_implicit_string_warning_inline.sass'
|
||||
Implicit strings have been deprecated and will be removed in version 3.0.
|
||||
'foo' was not quoted. Please add double quotes (e.g. "foo").
|
||||
WARN
|
||||
assert_warning(<<WARN) {render("@if 1 + foo")}
|
||||
DEPRECATION WARNING:
|
||||
On line 1, character 9 of 'test_implicit_string_warning_inline.sass'
|
||||
Implicit strings have been deprecated and will be removed in version 3.0.
|
||||
'foo' was not quoted. Please add double quotes (e.g. "foo").
|
||||
WARN
|
||||
|
||||
# Regression
|
||||
assert_warning(<<WARN) {render("@if if")}
|
||||
DEPRECATION WARNING:
|
||||
On line 1, character 5 of 'test_implicit_string_warning_inline.sass'
|
||||
Implicit strings have been deprecated and will be removed in version 3.0.
|
||||
'if' was not quoted. Please add double quotes (e.g. "if").
|
||||
WARN
|
||||
end
|
||||
|
||||
def test_inaccessible_functions
|
||||
assert_warning <<WARN do
|
||||
DEPRECATION WARNING:
|
||||
On line 2, character 6 of 'test_inaccessible_functions_inline.sass'
|
||||
Implicit strings have been deprecated and will be removed in version 3.0.
|
||||
'to_s' was not quoted. Please add double quotes (e.g. "to_s").
|
||||
WARN
|
||||
assert_equal "send(to_s)", resolve("send(to_s)", :line => 2)
|
||||
end
|
||||
assert_equal "send(to_s)", resolve("send(to_s)", :line => 2)
|
||||
assert_equal "public_instance_methods()", resolve("public_instance_methods()")
|
||||
end
|
||||
|
||||
def test_default_functions
|
||||
assert_equal "url(12)", resolve("url(12)")
|
||||
assert_equal 'blam(foo)', resolve('blam("foo")')
|
||||
assert_equal 'blam("foo")', resolve('blam("foo")')
|
||||
end
|
||||
|
||||
def test_function_results_have_options
|
||||
|
@ -227,20 +189,20 @@ WARN
|
|||
end
|
||||
|
||||
def test_string_ops
|
||||
assert_equal "foo bar", resolve('"foo" "bar"')
|
||||
assert_equal '"foo" "bar"', resolve('"foo" "bar"')
|
||||
assert_equal "true 1", resolve('true 1')
|
||||
assert_equal "foo, bar", resolve("'foo' , 'bar'")
|
||||
assert_equal '"foo", "bar"', resolve("'foo' , 'bar'")
|
||||
assert_equal "true, 1", resolve('true , 1')
|
||||
assert_equal "foobar", resolve('"foo" + "bar"')
|
||||
assert_equal "true1", resolve('true + 1')
|
||||
assert_equal "foo-bar", resolve("'foo' - 'bar'")
|
||||
assert_equal '"foo"-"bar"', resolve("'foo' - 'bar'")
|
||||
assert_equal "true-1", resolve('true - 1')
|
||||
assert_equal "foo/bar", resolve('"foo" / "bar"')
|
||||
assert_equal '"foo"/"bar"', resolve('"foo" / "bar"')
|
||||
assert_equal "true/1", resolve('true / 1')
|
||||
|
||||
assert_equal "-bar", resolve("- 'bar'")
|
||||
assert_equal '-"bar"', resolve("- 'bar'")
|
||||
assert_equal "-true", resolve('- true')
|
||||
assert_equal "/bar", resolve('/ "bar"')
|
||||
assert_equal '/"bar"', resolve('/ "bar"')
|
||||
assert_equal "/true", resolve('/ true')
|
||||
end
|
||||
|
||||
|
@ -312,7 +274,8 @@ WARN
|
|||
|
||||
def resolve(str, opts = {}, environment = env)
|
||||
munge_filename opts
|
||||
eval(str, opts, environment).to_s
|
||||
val = eval(str, opts, environment)
|
||||
val.is_a?(Sass::Script::String) ? val.value : val.to_s
|
||||
end
|
||||
|
||||
def eval(str, opts = {}, environment = env)
|
||||
|
|
Loading…
Add table
Reference in a new issue