Be explicit about string quotes in new SassString()

This commit is contained in:
Natalie Weizenbaum 2018-02-02 16:47:54 -08:00
parent a1d7e83143
commit 163e99bff2
10 changed files with 139 additions and 86 deletions

View File

@ -32,8 +32,8 @@ class SelectorList extends Selector {
SassList get asSassList {
return new SassList(components.map((complex) {
return new SassList(
complex.components
.map((component) => new SassString(component.toString())),
complex.components.map((component) =>
new SassString(component.toString(), quotes: false)),
ListSeparator.space);
}), ListSeparator.comma);
}

View File

@ -108,7 +108,8 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
if (first is SassColor) {
return new SassString(
"rgba(${first.red}, ${first.green}, ${first.blue}, "
"${arguments[1].toCssString()})");
"${arguments[1].toCssString()})",
quotes: false);
} else {
return _functionString('rgba', arguments);
}
@ -116,7 +117,8 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
var color = arguments[0].assertColor("color");
return new SassString(
"rgba(${color.red}, ${color.green}, ${color.blue}, "
"${arguments[1].toCssString()})");
"${arguments[1].toCssString()})",
quotes: false);
}
var color = arguments[0].assertColor("color");
@ -277,7 +279,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
new BuiltInCallable.overloaded("saturate", {
r"$number": (arguments) {
var number = arguments[0].assertNumber("number");
return new SassString("saturate(${number.toCssString()})");
return new SassString("saturate(${number.toCssString()})", quotes: false);
},
r"$color, $amount": (arguments) {
var color = arguments[0].assertColor("color");
@ -536,7 +538,8 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
component.toRadixString(16).padLeft(2, '0').toUpperCase();
return new SassString(
"#${hexString(fuzzyRound(color.alpha * 255))}${hexString(color.red)}"
"${hexString(color.green)}${hexString(color.blue)}");
"${hexString(color.green)}${hexString(color.blue)}",
quotes: false);
}),
// ## Strings
@ -544,7 +547,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
new BuiltInCallable("unquote", r"$string", (arguments) {
var string = arguments[0].assertString("string");
if (!string.hasQuotes) return string;
return new SassString(string.text);
return new SassString(string.text, quotes: false);
}),
new BuiltInCallable("quote", r"$string", (arguments) {
@ -789,8 +792,8 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
"list-separator",
r"$list",
(arguments) => arguments[0].separator == ListSeparator.comma
? new SassString("comma")
: new SassString("space")),
? new SassString("comma", quotes: false)
: new SassString("space", quotes: false)),
new BuiltInCallable("is-bracketed", r"$list",
(arguments) => new SassBoolean(arguments[0].hasBrackets)),
@ -841,7 +844,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
var argumentList = arguments[0];
if (argumentList is SassArgumentList) {
return new SassMap(mapMap(argumentList.keywords,
key: (String key, Value _) => new SassString(key)));
key: (String key, Value _) => new SassString(key, quotes: false)));
} else {
throw new SassScriptException(
"\$args: $argumentList is not an argument list.");
@ -927,7 +930,8 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
var selector = arguments[0].assertCompoundSelector(name: "selector");
return new SassList(
selector.components.map((simple) => new SassString(simple.toString())),
selector.components
.map((simple) => new SassString(simple.toString(), quotes: false)),
ListSeparator.comma);
}),
@ -942,20 +946,21 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
}),
new BuiltInCallable("inspect", r"$value",
(arguments) => new SassString(arguments.first.toString())),
(arguments) => new SassString(arguments.first.toString(), quotes: false)),
new BuiltInCallable("type-of", r"$value", (arguments) {
var value = arguments[0];
if (value is SassArgumentList) return new SassString("arglist");
if (value is SassBoolean) return new SassString("bool");
if (value is SassColor) return new SassString("color");
if (value is SassList) return new SassString("list");
if (value is SassMap) return new SassString("map");
if (value is SassNull) return new SassString("null");
if (value is SassNumber) return new SassString("number");
if (value is SassFunction) return new SassString("function");
if (value is SassArgumentList)
return new SassString("arglist", quotes: false);
if (value is SassBoolean) return new SassString("bool", quotes: false);
if (value is SassColor) return new SassString("color", quotes: false);
if (value is SassList) return new SassString("list", quotes: false);
if (value is SassMap) return new SassString("map", quotes: false);
if (value is SassNull) return new SassString("null", quotes: false);
if (value is SassNumber) return new SassString("number", quotes: false);
if (value is SassFunction) return new SassString("function", quotes: false);
assert(value is SassString);
return new SassString("string");
return new SassString("string", quotes: false);
}),
new BuiltInCallable("unit", r"$number", (arguments) {
@ -988,16 +993,19 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
_uniqueID += _random.nextInt(36) + 1;
if (_uniqueID > math.pow(36, 6)) _uniqueID %= math.pow(36, 6) as int;
// The leading "u" ensures that the result is a valid identifier.
return new SassString("u${_uniqueID.toRadixString(36).padLeft(6, '0')}");
return new SassString("u${_uniqueID.toRadixString(36).padLeft(6, '0')}",
quotes: false);
})
]);
/// Returns a string representation of [name] called with [arguments], as though
/// it were a plain CSS function.
SassString _functionString(String name, Iterable<Value> arguments) =>
new SassString("$name(" +
arguments.map((argument) => argument.toCssString()).join(', ') +
")");
new SassString(
"$name(" +
arguments.map((argument) => argument.toCssString()).join(', ') +
")",
quotes: false);
/// Asserts that [number] is a percentage or has no units, and normalizes the
/// value.

View File

@ -22,7 +22,7 @@ Object newNodeSassString(SassString value) =>
/// The JS constructor for the `sass.types.String` class.
final Function stringConstructor = createClass(
(_NodeSassString thisArg, String value, [SassString dartValue]) {
thisArg.dartValue = dartValue ?? new SassString(value);
thisArg.dartValue = dartValue ?? new SassString(value, quotes: false);
}, {
'getValue': (_NodeSassString thisArg) => thisArg.dartValue.text,
'setValue': (_NodeSassString thisArg, String value) {

View File

@ -226,7 +226,7 @@ abstract class Value implements ext.Value {
/// **Note:** this function should not be called outside the `sass` package.
/// It's not guaranteed to be stable across versions.
Value singleEquals(Value other) =>
new SassString("${toCssString()}=${other.toCssString()}");
new SassString("${toCssString()}=${other.toCssString()}", quotes: false);
/// The SassScript `>` operation.
///
@ -279,7 +279,7 @@ abstract class Value implements ext.Value {
return new SassString(toCssString() + other.text,
quotes: other.hasQuotes);
} else {
return new SassString(toCssString() + other.toCssString());
return new SassString(toCssString() + other.toCssString(), quotes: false);
}
}
@ -288,32 +288,32 @@ abstract class Value implements ext.Value {
/// **Note:** this function should not be called outside the `sass` package.
/// It's not guaranteed to be stable across versions.
Value minus(Value other) =>
new SassString("${toCssString()}-${other.toCssString()}");
new SassString("${toCssString()}-${other.toCssString()}", quotes: false);
/// The SassScript `/` operation.
///
/// **Note:** this function should not be called outside the `sass` package.
/// It's not guaranteed to be stable across versions.
Value dividedBy(Value other) =>
new SassString("${toCssString()}/${other.toCssString()}");
new SassString("${toCssString()}/${other.toCssString()}", quotes: false);
/// The SassScript unary `+` operation.
///
/// **Note:** this function should not be called outside the `sass` package.
/// It's not guaranteed to be stable across versions.
Value unaryPlus() => new SassString("+${toCssString()}");
Value unaryPlus() => new SassString("+${toCssString()}", quotes: false);
/// The SassScript unary `-` operation.
///
/// **Note:** this function should not be called outside the `sass` package.
/// It's not guaranteed to be stable across versions.
Value unaryMinus() => new SassString("-${toCssString()}");
Value unaryMinus() => new SassString("-${toCssString()}", quotes: false);
/// The SassScript unary `/` operation.
///
/// **Note:** this function should not be called outside the `sass` package.
/// It's not guaranteed to be stable across versions.
Value unaryDivide() => new SassString("/${toCssString()}");
Value unaryDivide() => new SassString("/${toCssString()}", quotes: false);
/// The SassScript unary `not` operation.
///

View File

@ -225,7 +225,8 @@ class _EvaluateVisitor
? null
: new ValueExpression(
new SassMap(mapMap(args.keywords,
key: (String key, Value _) => new SassString(key),
key: (String key, Value _) =>
new SassString(key, quotes: false),
value: (String _, Value value) => value)),
_callableSpan));
@ -1343,7 +1344,7 @@ class _EvaluateVisitor
}
buffer.writeCharCode($rparen);
return new SassString(buffer.toString());
return new SassString(buffer.toString(), quotes: false);
} else {
return null;
}

View File

@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/synchronize.dart for details.
//
// Checksum: d4ffc2a9cc2c3e8e202705c44e03c7acb7822356
// Checksum: 0d20d8293daaad022a0a20115cc88b80704e2ad7
import 'dart:math' as math;
@ -227,7 +227,8 @@ class _EvaluateVisitor
? null
: new ValueExpression(
new SassMap(mapMap(args.keywords,
key: (String key, Value _) => new SassString(key),
key: (String key, Value _) =>
new SassString(key, quotes: false),
value: (String _, Value value) => value)),
_callableSpan));
@ -1321,7 +1322,7 @@ class _EvaluateVisitor
}
buffer.writeCharCode($rparen);
return new SassString(buffer.toString());
return new SassString(buffer.toString(), quotes: false);
} else {
return null;
}

View File

@ -29,7 +29,7 @@ main() {
new Callable("foo", r"$arg", expectAsync1((arguments) {
expect(arguments, hasLength(1));
expect(arguments.first.assertString().text, equals("bar"));
return new SassString("result");
return new SassString("result", quotes: false);
}))
]);
@ -42,7 +42,7 @@ main() {
expect(arguments, hasLength(1));
expect(arguments.first.assertString().text, equals("bar"));
await pumpEventQueue();
return new SassString("result");
return new SassString("result", quotes: false);
}))
]);

View File

@ -26,40 +26,49 @@ main() {
test("returns its contents as a list", () {
expect(
value.asList,
equals(
[new SassString("a"), new SassString("b"), new SassString("c")]));
equals([
new SassString("a", quotes: false),
new SassString("b", quotes: false),
new SassString("c", quotes: false)
]));
});
test("equals the same list", () {
expect(
value,
equalsWithHash(new SassList(
[new SassString("a"), new SassString("b"), new SassString("c")],
ListSeparator.comma)));
equalsWithHash(new SassList([
new SassString("a", quotes: false),
new SassString("b", quotes: false),
new SassString("c", quotes: false)
], ListSeparator.comma)));
});
test("doesn't equal a value with different metadata", () {
expect(
value,
isNot(equals(new SassList(
[new SassString("a"), new SassString("b"), new SassString("c")],
ListSeparator.space))));
isNot(equals(new SassList([
new SassString("a", quotes: false),
new SassString("b", quotes: false),
new SassString("c", quotes: false)
], ListSeparator.space))));
expect(
value,
isNot(equals(new SassList([
new SassString("a"),
new SassString("b"),
new SassString("c")
new SassString("a", quotes: false),
new SassString("b", quotes: false),
new SassString("c", quotes: false)
], ListSeparator.comma, brackets: true))));
});
test("doesn't equal a value with different contents", () {
expect(
value,
isNot(equals(new SassList(
[new SassString("a"), new SassString("x"), new SassString("c")],
ListSeparator.comma))));
isNot(equals(new SassList([
new SassString("a", quotes: false),
new SassString("x", quotes: false),
new SassString("c", quotes: false)
], ListSeparator.comma))));
});
group("sassIndexToListIndex()", () {
@ -76,7 +85,9 @@ main() {
});
test("rejects a non-number", () {
expect(() => value.sassIndexToListIndex(new SassString("foo")),
expect(
() => value
.sassIndexToListIndex(new SassString("foo", quotes: false)),
throwsSassScriptException);
});
@ -233,15 +244,17 @@ main() {
group("new SassList()", () {
test("creates a list with the given contents and metadata", () {
var list = new SassList([new SassString("a")], ListSeparator.space);
expect(list.asList, equals([new SassString("a")]));
var list = new SassList(
[new SassString("a", quotes: false)], ListSeparator.space);
expect(list.asList, equals([new SassString("a", quotes: false)]));
expect(list.separator, equals(ListSeparator.space));
expect(list.hasBrackets, isFalse);
});
test("can create a bracketed list", () {
expect(
new SassList([new SassString("a")], ListSeparator.space,
new SassList(
[new SassString("a", quotes: false)], ListSeparator.space,
brackets: true)
.hasBrackets,
isTrue);
@ -249,7 +262,8 @@ main() {
test("can create a short list with an undecided separator", () {
expect(
new SassList([new SassString("a")], ListSeparator.undecided)
new SassList(
[new SassString("a", quotes: false)], ListSeparator.undecided)
.separator,
equals(ListSeparator.undecided));
expect(new SassList([], ListSeparator.undecided).separator,
@ -258,8 +272,10 @@ main() {
test("can't create a long list with an undecided separator", () {
expect(
() => new SassList([new SassString("a"), new SassString("b")],
ListSeparator.undecided),
() => new SassList([
new SassString("a", quotes: false),
new SassString("b", quotes: false)
], ListSeparator.undecided),
throwsArgumentError);
});
});

View File

@ -23,8 +23,10 @@ main() {
expect(
value.contents,
equals({
new SassString("a"): new SassString("b"),
new SassString("c"): new SassString("d")
new SassString("a", quotes: false):
new SassString("b", quotes: false),
new SassString("c", quotes: false):
new SassString("d", quotes: false)
}));
});
@ -32,10 +34,14 @@ main() {
expect(
value.asList,
equals([
new SassList([new SassString("a"), new SassString("b")],
ListSeparator.space),
new SassList(
[new SassString("c"), new SassString("d")], ListSeparator.space)
new SassList([
new SassString("a", quotes: false),
new SassString("b", quotes: false)
], ListSeparator.space),
new SassList([
new SassString("c", quotes: false),
new SassString("d", quotes: false)
], ListSeparator.space)
]));
});
@ -64,8 +70,10 @@ main() {
expect(
value,
equalsWithHash(new SassMap({
new SassString("a"): new SassString("b"),
new SassString("c"): new SassString("d")
new SassString("a", quotes: false):
new SassString("b", quotes: false),
new SassString("c", quotes: false):
new SassString("d", quotes: false)
})));
});
@ -73,10 +81,14 @@ main() {
expect(
value,
isNot(equals(new SassList([
new SassList([new SassString("a"), new SassString("b")],
ListSeparator.space),
new SassList(
[new SassString("c"), new SassString("d")], ListSeparator.space)
new SassList([
new SassString("a", quotes: false),
new SassString("b", quotes: false)
], ListSeparator.space),
new SassList([
new SassString("c", quotes: false),
new SassString("d", quotes: false)
], ListSeparator.space)
], ListSeparator.comma))));
});
@ -85,8 +97,10 @@ main() {
expect(
value,
isNot(equals(new SassMap({
new SassString("a"): new SassString("x"),
new SassString("c"): new SassString("d")
new SassString("a", quotes: false):
new SassString("x", quotes: false),
new SassString("c", quotes: false):
new SassString("d", quotes: false)
}))));
});
@ -94,25 +108,32 @@ main() {
expect(
value,
isNot(equals(new SassMap({
new SassString("a"): new SassString("b"),
new SassString("x"): new SassString("d")
new SassString("a", quotes: false):
new SassString("b", quotes: false),
new SassString("x", quotes: false):
new SassString("d", quotes: false)
}))));
});
test("a missing pair", () {
expect(
value,
isNot(equals(
new SassMap({new SassString("a"): new SassString("b")}))));
isNot(equals(new SassMap({
new SassString("a", quotes: false):
new SassString("b", quotes: false)
}))));
});
test("an additional pair", () {
expect(
value,
isNot(equals(new SassMap({
new SassString("a"): new SassString("b"),
new SassString("c"): new SassString("d"),
new SassString("e"): new SassString("f")
new SassString("a", quotes: false):
new SassString("b", quotes: false),
new SassString("c", quotes: false):
new SassString("d", quotes: false),
new SassString("e", quotes: false):
new SassString("f", quotes: false)
}))));
});
});
@ -165,7 +186,13 @@ main() {
});
test("new SassMap() creates a map with the given contents", () {
var list = new SassMap({new SassString("a"): new SassString("b")});
expect(list.contents, equals({new SassString("a"): new SassString("b")}));
var list = new SassMap({
new SassString("a", quotes: false): new SassString("b", quotes: false)
});
expect(
list.contents,
equals({
new SassString("a", quotes: false): new SassString("b", quotes: false)
}));
});
}

View File

@ -206,7 +206,7 @@ main() {
group("new SassString.empty()", () {
test("creates an empty unquoted string", () {
var string = new SassString.empty();
var string = new SassString.empty(quotes: false);
expect(string.text, isEmpty);
expect(string.hasQuotes, isFalse);
});
@ -220,7 +220,7 @@ main() {
group("new SassString()", () {
test("creates an unquoted string with the given text", () {
var string = new SassString("a b c");
var string = new SassString("a b c", quotes: false);
expect(string.text, equals("a b c"));
expect(string.hasQuotes, isFalse);
});