Add Value.toCssString().

This commit is contained in:
Natalie Weizenbaum 2016-10-16 19:01:23 -07:00
parent 604fa597e5
commit 7f6c70f821
4 changed files with 40 additions and 35 deletions

View File

@ -14,7 +14,6 @@ import 'extend/extender.dart';
import 'util/number.dart';
import 'utils.dart';
import 'value.dart';
import 'visitor/serialize.dart';
/// A regular expression matching the beginning of a proprietary Microsoft
/// filter declaration.
@ -42,9 +41,7 @@ void defineCoreFunctions(Environment environment) {
environment.defineFunction("rgb", r"$red, $green, $blue", (arguments) {
if (arguments[0].isCalc || arguments[1].isCalc || arguments[2].isCalc) {
return new SassString(
"rgb(${valueToCss(arguments[0])}, ${valueToCss(arguments[0])}, "
"${valueToCss(arguments[0])})");
return _functionString('rgb', arguments);
}
var red = arguments[0].assertNumber("red");
@ -66,9 +63,7 @@ void defineCoreFunctions(Environment environment) {
arguments[1].isCalc ||
arguments[2].isCalc ||
arguments[3].isCalc) {
return new SassString(
"rgba(${valueToCss(arguments[0])}, ${valueToCss(arguments[1])}, "
"${valueToCss(arguments[2])}, ${valueToCss(arguments[3])})");
return _functionString('rgba', arguments);
}
var red = arguments[0].assertNumber("red");
@ -88,7 +83,7 @@ void defineCoreFunctions(Environment environment) {
if (arguments[1].isCalc) {
return new SassString(
"rgba(${color.red}, ${color.green}, ${color.blue}, "
"${valueToCss(arguments[1])})");
"${arguments[1].toCssString()})");
}
var alpha = arguments[0].assertNumber("alpha");
@ -121,9 +116,7 @@ void defineCoreFunctions(Environment environment) {
environment.defineFunction("hsl", r"$hue, $saturation, $lightness",
(arguments) {
if (arguments[0].isCalc || arguments[1].isCalc || arguments[2].isCalc) {
return new SassString(
"rgb(${valueToCss(arguments[0])}, ${valueToCss(arguments[0])}, "
"${valueToCss(arguments[0])})");
return _functionString("hsl", arguments);
}
var hue = arguments[0].assertNumber("hue");
@ -139,9 +132,7 @@ void defineCoreFunctions(Environment environment) {
arguments[1].isCalc ||
arguments[2].isCalc ||
arguments[3].isCalc) {
return new SassString(
"rgba(${valueToCss(arguments[0])}, ${valueToCss(arguments[1])}, "
"${valueToCss(arguments[2])}, ${valueToCss(arguments[3])})");
return _functionString("hsla", arguments);
}
var hue = arguments[0].assertNumber("hue");
@ -207,7 +198,7 @@ void defineCoreFunctions(Environment environment) {
environment.defineFunction("grayscale", r"$color", (arguments) {
if (arguments[0] is SassNumber) {
return new SassString("grayscale(${valueToCss(arguments[0])})");
return _functionString('grayscale', arguments);
}
var color = arguments[0].assertColor("color");
@ -223,7 +214,7 @@ void defineCoreFunctions(Environment environment) {
if (arguments[0] is SassNumber) {
// TODO: find some way of ensuring this is stringified using the right
// options. We may need to resort to zones.
return new SassString("invert(${valueToCss(arguments[0])})");
return _functionString("invert", arguments);
}
var color = arguments[0].assertColor("color");
@ -247,7 +238,7 @@ void defineCoreFunctions(Environment environment) {
!argument.hasQuotes &&
argument.text.contains(_microsoftFilterStart)) {
// Suport the proprietary Microsoft alpha() function.
return new SassString("alpha(${valueToCss(argument)})");
return _functionString("alpha", arguments);
}
var color = argument.assertColor("color");
@ -259,7 +250,7 @@ void defineCoreFunctions(Environment environment) {
!argument.hasQuotes &&
argument.text.contains(_microsoftFilterStart))) {
// Suport the proprietary Microsoft alpha() function.
return new SassString("alpha(${arguments.map(valueToCss).join(', ')})");
return _functionString("alpha", arguments);
}
assert(arguments.length != 1);
@ -270,7 +261,7 @@ void defineCoreFunctions(Environment environment) {
environment.defineFunction("opacity", r"$color", (arguments) {
if (arguments[0] is SassNumber) {
return new SassString("opacity(${valueToCss(arguments[0])})");
return _functionString("opacity", arguments);
}
var color = arguments[0].assertColor("color");
@ -894,6 +885,13 @@ void defineCoreFunctions(Environment environment) {
});
}
/// Returns a string representation of [name] called with [arguments], as though
/// it were a plain CSS function.
SassString _functionString(String name, List<Value> arguments) =>
new SassString("$name(" +
arguments.map((argument) => argument.toCssString()).join(', ') +
")");
/// Asserts that [number] is a percentage or has no units, and normalizes the
/// value.
///

View File

@ -254,37 +254,44 @@ abstract class Value {
/// The SassScript `+` operation.
Value plus(Value other) {
if (other is SassString) {
return new SassString(valueToCss(this) + other.text,
return new SassString(toCssString() + other.text,
quotes: other.hasQuotes);
} else {
return new SassString(valueToCss(this) + valueToCss(other));
return new SassString(toCssString() + other.toCssString());
}
}
/// The SassScript `-` operation.
Value minus(Value other) =>
new SassString("${valueToCss(this)}-${valueToCss(other)}");
new SassString("${toCssString()}-${other.toCssString()}");
/// The SassScript `/` operation.
Value dividedBy(Value other) =>
new SassString("${valueToCss(this)}/${valueToCss(other)}");
new SassString("${toCssString()}/${other.toCssString()}");
/// The SassScript unary `+` operation.
Value unaryPlus() => new SassString("+${valueToCss(this)}");
Value unaryPlus() => new SassString("+${toCssString()}");
/// The SassScript unary `-` operation.
Value unaryMinus() => new SassString("-${valueToCss(this)}");
Value unaryMinus() => new SassString("-${toCssString()}");
/// The SassScript unary `/` operation.
Value unaryDivide() => new SassString("/${valueToCss(this)}");
Value unaryDivide() => new SassString("/${toCssString()}");
/// The SassScript unary `not` operation.
Value unaryNot() => sassFalse;
/// Returns a valid CSS representation of [this].
///
/// Throws a [SassScriptException] if [this] can't be represented in plain
/// CSS. Use [toString] instead to get a string representation even if this
/// isn't valid CSS.
String toCssString() => valueToCss(this);
/// Returns a string representation of [this].
///
/// Note that this is equivalent to calling `inspect()` on the value, and thus
/// won't reflect the user's output settings. [valueToCss] should be used
/// won't reflect the user's output settings. [toCssString] should be used
/// instead to convert [this] to CSS.
String toString() => valueToCss(this, inspect: true);

View File

@ -5,7 +5,6 @@
import 'package:charcode/charcode.dart';
import '../visitor/interface/value.dart';
import '../visitor/serialize.dart';
import '../value.dart';
/// A SassScript string.
@ -44,7 +43,7 @@ class SassString extends Value {
return new SassString(text + other.text,
quotes: hasQuotes || other.hasQuotes);
} else {
return new SassString(text + valueToCss(other), quotes: hasQuotes);
return new SassString(text + other.toCssString(), quotes: hasQuotes);
}
}

View File

@ -21,7 +21,6 @@ import '../utils.dart';
import '../value.dart';
import 'interface/statement.dart';
import 'interface/expression.dart';
import 'serialize.dart';
/// A function that takes a callback with no arguments.
typedef _ScopeCallback(callback());
@ -597,10 +596,10 @@ class _PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
} else if (condition is SupportsNegation) {
return "not ${_parenthesize(condition.condition)}";
} else if (condition is SupportsInterpolation) {
return valueToCss(condition.expression.accept(this));
return condition.expression.accept(this).toCssString();
} else if (condition is SupportsDeclaration) {
return "(${valueToCss(condition.name.accept(this))}: "
"${valueToCss(condition.value.accept(this))})";
return "(${condition.name.accept(this).toCssString()}: "
"${condition.value.accept(this).toCssString()})";
} else {
return null;
}
@ -631,7 +630,7 @@ class _PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
_addExceptionSpan(
node.span,
() => stderr
.writeln("WARNING: ${valueToCss(node.expression.accept(this))}"));
.writeln("WARNING: ${node.expression.accept(this).toCssString()}"));
for (var line in _stackTrace(node.span).toString().split("\n")) {
stderr.writeln(" $line");
}
@ -789,7 +788,9 @@ class _PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
// TODO: if rest is an arglist that has keywords, error out.
var rest = node.arguments.rest?.accept(this);
if (rest != null) arguments.add(rest);
return new SassString("$name(${arguments.map(valueToCss).join(', ')})");
return new SassString("$name(" +
arguments.map((argument) => argument.toCssString()).join(', ') +
")");
}
/// Evaluates the arguments in [invocation] as applied to [callable], and