1
0
Fork 0
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:
Nathan Weizenbaum 2010-03-25 17:19:50 -07:00
parent e814ff6608
commit 397cd62c5f
14 changed files with 92 additions and 68 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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 || []

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)