Add rgb().

This commit is contained in:
Natalie Weizenbaum 2016-09-20 14:59:53 -07:00 committed by Natalie Weizenbaum
parent dd8a0efd66
commit 5cc5bf1914
8 changed files with 77 additions and 2 deletions

View File

@ -5,11 +5,41 @@
import 'ast/sass.dart';
import 'callable.dart';
import 'environment.dart';
import 'exception.dart';
import 'value.dart';
void defineCoreFunctions(Environment environment) {
environment.setFunction(new BuiltInCallable(
"rgb",
new ArgumentDeclaration(
[new Argument("red"), new Argument("green"), new Argument("blue")]),
(arguments) {
var red = arguments[0].assertNumber("red");
var green = arguments[1].assertNumber("green");
var blue = arguments[2].assertNumber("blue");
return new SassColor.rgb(
_percentageOrUnitless(red, 255, "red"),
_percentageOrUnitless(green, 255, "green"),
_percentageOrUnitless(blue, 255, "blue"));
}));
environment.setFunction(new BuiltInCallable(
"inspect",
new ArgumentDeclaration([new Argument("value")]),
(arguments) => new SassString(arguments.single.toString())));
}
int _percentageOrUnitless(SassNumber number, int max, String name) {
num value;
if (!number.hasUnits) {
value = number.value;
} else if (number.hasUnit("%")) {
value = max * number.value / 100;
} else {
throw new InternalException(
'\$$name: Expected $number to have no units or "%".');
}
return value.clamp(0, max).round();
}

View File

@ -4,6 +4,9 @@
import 'exception.dart';
import 'value/boolean.dart';
import 'value/color.dart';
import 'value/map.dart';
import 'value/number.dart';
import 'value/string.dart';
import 'visitor/interface/value.dart';
import 'visitor/serialize.dart';
@ -31,6 +34,31 @@ abstract class Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor);
SassBoolean assertBoolean([String name]) {
if (name == null) throw new InternalException("$this is not a boolean.");
throw new InternalException("\$$name: $this is not a boolean.");
}
SassColor assertColor([String name]) {
if (name == null) throw new InternalException("$this is not a color.");
throw new InternalException("\$$name: $this is not a color.");
}
SassMap assertMap([String name]) {
if (name == null) throw new InternalException("$this is not a map.");
throw new InternalException("\$$name: $this is not a map.");
}
SassNumber assertNumber([String name]) {
if (name == null) throw new InternalException("$this is not a number.");
throw new InternalException("\$$name: $this is not a number.");
}
SassString assertString([String name]) {
if (name == null) throw new InternalException("$this is not a string.");
throw new InternalException("\$$name: $this is not a string.");
}
Value or(Value other) => this;
Value and(Value other) => other;

View File

@ -20,6 +20,8 @@ class SassBoolean extends Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) =>
visitor.visitBoolean(this);
SassBoolean assertBoolean([String name]) => this;
Value or(Value other) => value ? this : other;
Value and(Value other) => value ? other : this;

View File

@ -17,6 +17,8 @@ class SassColor extends Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) => visitor.visitColor(this);
SassColor assertColor([String name]) => this;
Value plus(Value other) {
if (other is! SassNumber && other is! SassColor) return super.plus(other);
throw new InternalException('Undefined operation "$this + $other".');

View File

@ -23,6 +23,8 @@ class SassMap extends Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) => visitor.visitMap(this);
SassMap assertMap([String name]) => this;
bool operator ==(other) =>
other is SassMap && const MapEquality().equals(other.contents, contents);

View File

@ -145,7 +145,7 @@ class SassNumber extends Value {
final List<String> denominatorUnits;
bool get hasUnits => numeratorUnits.isEmpty && denominatorUnits.isEmpty;
bool get hasUnits => numeratorUnits.isNotEmpty || denominatorUnits.isNotEmpty;
bool get isInt => value is int || almostEquals(value % 1, 0.0);
@ -171,6 +171,14 @@ class SassNumber extends Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) =>
visitor.visitNumber(this);
SassNumber assertNumber([String name]) => this;
/// Returns whether [this] has [unit] as its only unit (and as a numerator).
bool hasUnit(String unit) =>
numeratorUnits.length == 1 &&
denominatorUnits.isEmpty &&
numeratorUnits.first == unit;
num valueInUnits(List<String> newNumerators, List<String> newDenominators) {
if ((newNumerators.isEmpty && newDenominators.isEmpty) ||
(numeratorUnits.isEmpty && denominatorUnits.isEmpty) ||

View File

@ -16,6 +16,8 @@ class SassString extends Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) =>
visitor.visitString(this);
SassString assertString([String name]) => this;
Value plus(Value other) {
if (other is SassString) {
return new SassString(text + other.text,

View File

@ -789,7 +789,8 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
positional.add(argumentList);
}
var result = callable.callback(positional);
var result =
_addExceptionSpan(() => callable.callback(positional), invocation.span);
if (argumentList == null) return result;
if (named.isEmpty) return result;