1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00

[Sass] Add support for single-quoted strings.

This commit is contained in:
Nathan Weizenbaum 2009-11-20 03:40:42 -08:00
parent 14d32b9265
commit 4d7b19506b
4 changed files with 49 additions and 9 deletions

View file

@ -29,6 +29,13 @@ For example:
!prettiest-color = #542FA9
### Single-Quoted Strings
SassScript now supports single-quoted strings.
They behave identically to double-quoted strings,
except that single quotes need to be backslash-escaped
and double quotes do not.
### Error Backtraces
Numerous bugs were fixed with the backtraces given for Sass errors,

View file

@ -691,7 +691,7 @@ available in that context.
SassScript supports four data types:
* numbers (e.g. `1.2`, `13`, `10px`)
* strings of text (e.g. `"foo"`, `"bar"`)
* strings of text (e.g. `"foo"`, `"bar"`, `'baz'`)
* colors (e.g. `blue`, `#04a3f9`, `rgba(255, 0, 0, 0.5)`)
* booleans (e.g. `true`, `false`)

View file

@ -54,13 +54,32 @@ module Sass
:whitespace => /\s*/,
:variable => /!([\w-]+)/,
:ident => /(\\.|[^\s\\+*\/%(),=!])+/,
:string_end => /((?:\\.|\#(?!\{)|[^"\\#])*)(?:"|(?=#\{))/,
:number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
:color => /\##{"([0-9a-fA-F]{1,2})" * 3}|(#{Color::HTML4_COLORS.keys.join("|")})(?!\()/,
:bool => /(true|false)\b/,
:op => %r{(#{Regexp.union(*OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + (s =~ /\w$/ ? '(?:\b|$)' : ''))})})}
}
class << self
private
def string_re(open, close)
/#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|(?=#\{))/
end
end
# A hash of regular expressions that are used for tokenizing strings.
#
# The key is a [Symbol, Boolean] pair.
# The symbol represents which style of quotation to use,
# while the boolean represents whether or not the string
# is following an interpolated segment.
STRING_REGULAR_EXPRESSIONS = {
[:double, false] => string_re('"', '"'),
[:single, false] => string_re("'", "'"),
[:double, true] => string_re('', '"'),
[:single, true] => string_re('', "'"),
}
# @param str [String, StringScanner] The source text to lex
# @param line [Fixnum] The line on which the SassScript appears.
# Used for error reporting
@ -71,6 +90,7 @@ module Sass
@line = line
@offset = offset
@filename = filename
@interpolation_stack = []
@prev = nil
end
@ -114,8 +134,8 @@ module Sass
end
def token
return string('') if after_interpolation?
variable || string || number || color || bool || op || ident
return string(@interpolation_stack.pop, true) if after_interpolation?
variable || string(:double, false) || string(:single, false) || number || color || bool || op || ident
end
def variable
@ -128,8 +148,9 @@ module Sass
[:ident, s.gsub(/\\(.)/, '\1')]
end
def string(start_char = '"')
return unless @scanner.scan(/#{start_char}#{REGULAR_EXPRESSIONS[:string_end]}/)
def string(re, open)
return unless @scanner.scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
@interpolation_stack << re if @scanner[2].empty? # Started an interpolated section
[:string, Script::String.new(@scanner[1].gsub(/\\([^0-9a-f])/, '\1').gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1"))]
end

View file

@ -16,9 +16,21 @@ class SassScriptTest < Test::Unit::TestCase
end
def test_string_escapes
assert_equal "'", resolve("\"'\"")
assert_equal '"', resolve("\"\\\"\"")
assert_equal "\\", resolve("\"\\\\\"")
assert_equal "\\02fa", resolve("\"\\02fa\"")
assert_equal "'", resolve("'\\''")
assert_equal '"', resolve("'\"'")
assert_equal "\\", resolve("'\\\\'")
assert_equal "\\02fa", resolve("'\\02fa'")
end
def test_string_interpolation
assert_equal "foo2bar", resolve('\'foo#{1 + 1}bar\'')
assert_equal "foo2bar", resolve('"foo#{1 + 1}bar"')
assert_equal "foo1bar5baz4bang", resolve('\'foo#{1 + "bar#{2 + 3}baz" + 4}bang\'')
end
def test_color_names
@ -188,16 +200,16 @@ WARN
def test_string_ops
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 "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 "/true", resolve('/ true')