From 7f6c70f82193ade16abac4a4f96721d645a50d6c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Sun, 16 Oct 2016 19:01:23 -0700 Subject: [PATCH] Add Value.toCssString(). --- lib/src/functions.dart | 36 +++++++++++++++++------------------- lib/src/value.dart | 23 +++++++++++++++-------- lib/src/value/string.dart | 3 +-- lib/src/visitor/perform.dart | 13 +++++++------ 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/lib/src/functions.dart b/lib/src/functions.dart index 3e6179ce..5484b430 100644 --- a/lib/src/functions.dart +++ b/lib/src/functions.dart @@ -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 arguments) => + new SassString("$name(" + + arguments.map((argument) => argument.toCssString()).join(', ') + + ")"); + /// Asserts that [number] is a percentage or has no units, and normalizes the /// value. /// diff --git a/lib/src/value.dart b/lib/src/value.dart index 9e3977d3..fe36012a 100644 --- a/lib/src/value.dart +++ b/lib/src/value.dart @@ -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); diff --git a/lib/src/value/string.dart b/lib/src/value/string.dart index 4c79be0c..e06287b5 100644 --- a/lib/src/value/string.dart +++ b/lib/src/value/string.dart @@ -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); } } diff --git a/lib/src/visitor/perform.dart b/lib/src/visitor/perform.dart index 4e6e52a4..5d5054af 100644 --- a/lib/src/visitor/perform.dart +++ b/lib/src/visitor/perform.dart @@ -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 { } 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 { _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 { // 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