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:
parent
14d32b9265
commit
4d7b19506b
4 changed files with 49 additions and 9 deletions
|
@ -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,
|
||||
|
|
|
@ -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`)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Add table
Reference in a new issue