mirror of
https://github.com/danog/dart-sass.git
synced 2025-01-22 13:51:31 +01:00
Unify strings and identifiers.
The separation makes sense conceptually, but it would make string functions a lot harder to write.
This commit is contained in:
parent
9ac48fbc05
commit
bacc1c4529
@ -12,7 +12,6 @@ export 'sass/expression/binary_operation.dart';
|
||||
export 'sass/expression/boolean.dart';
|
||||
export 'sass/expression/color.dart';
|
||||
export 'sass/expression/function.dart';
|
||||
export 'sass/expression/identifier.dart';
|
||||
export 'sass/expression/list.dart';
|
||||
export 'sass/expression/map.dart';
|
||||
export 'sass/expression/null.dart';
|
||||
|
@ -1,22 +0,0 @@
|
||||
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../../visitor/interface/expression.dart';
|
||||
import '../expression.dart';
|
||||
import '../interpolation.dart';
|
||||
|
||||
class IdentifierExpression implements Expression {
|
||||
final Interpolation text;
|
||||
|
||||
FileSpan get span => text.span;
|
||||
|
||||
IdentifierExpression(this.text);
|
||||
|
||||
/*=T*/ accept/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitIdentifierExpression(this);
|
||||
|
||||
String toString() => text.toString();
|
||||
}
|
@ -19,24 +19,28 @@ class StringExpression implements Expression {
|
||||
/// included.
|
||||
final Interpolation text;
|
||||
|
||||
final bool hasQuotes;
|
||||
|
||||
FileSpan get span => text.span;
|
||||
|
||||
static String quoteText(String text) =>
|
||||
new StringExpression(new Interpolation([text], null))
|
||||
new StringExpression(new Interpolation([text], null), quotes: true)
|
||||
.asInterpolation(static: true)
|
||||
.asPlain;
|
||||
|
||||
StringExpression(this.text);
|
||||
StringExpression(this.text, {bool quotes}) : hasQuotes = quotes;
|
||||
|
||||
/*=T*/ accept/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitStringExpression(this);
|
||||
|
||||
/// Interpolation that, when evaluated, produces the syntax of the string.
|
||||
///
|
||||
/// Unlike [text], his doesn't resolve escapes and does include quotes.
|
||||
/// Unlike [text], his doesn't resolve escapes and does include quotes for
|
||||
/// quoted strings.
|
||||
Interpolation asInterpolation({bool static: false, int quote}) {
|
||||
quote ??= _bestQuote();
|
||||
var buffer = new InterpolationBuffer()..writeCharCode(quote);
|
||||
quote ??= hasQuotes ? null : _bestQuote();
|
||||
var buffer = new InterpolationBuffer();
|
||||
if (quote != null) buffer.writeCharCode(quote);
|
||||
for (var value in text.contents) {
|
||||
if (value is Interpolation) {
|
||||
buffer.addInterpolation(value);
|
||||
@ -63,7 +67,7 @@ class StringExpression implements Expression {
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.writeCharCode(quote);
|
||||
if (quote != null) buffer.writeCharCode(quote);
|
||||
|
||||
return buffer.interpolation(text.span);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class SelectorList extends Selector {
|
||||
return new SassList(components.map((complex) {
|
||||
return new SassList(
|
||||
complex.components
|
||||
.map((component) => new SassIdentifier(component.toString())),
|
||||
.map((component) => new SassString(component.toString())),
|
||||
ListSeparator.space);
|
||||
}), ListSeparator.comma);
|
||||
}
|
||||
|
@ -11,5 +11,5 @@ void defineCoreFunctions(Environment environment) {
|
||||
environment.setFunction(new BuiltInCallable(
|
||||
"inspect",
|
||||
new ArgumentDeclaration([new Argument("value")]),
|
||||
(arguments) => new SassIdentifier(arguments.single.toString())));
|
||||
(arguments) => new SassString(arguments.single.toString())));
|
||||
}
|
||||
|
@ -101,7 +101,8 @@ abstract class StylesheetParser extends Parser {
|
||||
|
||||
Expression _declarationExpression() {
|
||||
if (lookingAtChildren()) {
|
||||
return new StringExpression(new Interpolation([], scanner.emptySpan));
|
||||
return new StringExpression(new Interpolation([], scanner.emptySpan),
|
||||
quotes: true);
|
||||
}
|
||||
|
||||
return _expression();
|
||||
@ -1265,7 +1266,8 @@ abstract class StylesheetParser extends Parser {
|
||||
}
|
||||
}
|
||||
|
||||
return new StringExpression(buffer.interpolation(scanner.spanFrom(start)));
|
||||
return new StringExpression(buffer.interpolation(scanner.spanFrom(start)),
|
||||
quotes: true);
|
||||
}
|
||||
|
||||
Expression _hexColorOrID() {
|
||||
@ -1287,8 +1289,7 @@ abstract class StylesheetParser extends Parser {
|
||||
var buffer = new InterpolationBuffer();
|
||||
buffer.writeCharCode($hash);
|
||||
buffer.addInterpolation(identifier);
|
||||
return new IdentifierExpression(
|
||||
buffer.interpolation(scanner.spanFrom(start)));
|
||||
return new StringExpression(buffer.interpolation(scanner.spanFrom(start)));
|
||||
}
|
||||
|
||||
SassColor _hexColorContents() {
|
||||
@ -1342,7 +1343,7 @@ abstract class StylesheetParser extends Parser {
|
||||
|
||||
return scanner.peekChar() == $lparen
|
||||
? new FunctionExpression(identifier, _argumentInvocation())
|
||||
: new IdentifierExpression(identifier);
|
||||
: new StringExpression(identifier);
|
||||
}
|
||||
|
||||
/// Consumes tokens up to "{", "}", ";", or "!".
|
||||
@ -1420,7 +1421,7 @@ abstract class StylesheetParser extends Parser {
|
||||
return buffer.interpolation(scanner.spanFrom(start));
|
||||
}
|
||||
|
||||
IdentifierExpression _interpolatedDeclarationValue() {
|
||||
StringExpression _interpolatedDeclarationValue() {
|
||||
// NOTE: this logic is largely duplicated in Parser.declarationValue. Most
|
||||
// changes here should be mirrored there.
|
||||
|
||||
@ -1511,8 +1512,7 @@ abstract class StylesheetParser extends Parser {
|
||||
}
|
||||
|
||||
if (brackets.isNotEmpty) scanner.expectChar(brackets.last);
|
||||
return new IdentifierExpression(
|
||||
buffer.interpolation(scanner.spanFrom(start)));
|
||||
return new StringExpression(buffer.interpolation(scanner.spanFrom(start)));
|
||||
}
|
||||
|
||||
Interpolation _interpolatedIdentifier() {
|
||||
|
@ -4,14 +4,12 @@
|
||||
|
||||
import 'exception.dart';
|
||||
import 'value/boolean.dart';
|
||||
import 'value/identifier.dart';
|
||||
import 'value/string.dart';
|
||||
import 'visitor/interface/value.dart';
|
||||
import 'visitor/serialize.dart';
|
||||
|
||||
export 'value/boolean.dart';
|
||||
export 'value/color.dart';
|
||||
export 'value/identifier.dart';
|
||||
export 'value/list.dart';
|
||||
export 'value/map.dart';
|
||||
export 'value/null.dart';
|
||||
@ -56,23 +54,24 @@ abstract class Value {
|
||||
|
||||
Value plus(Value other) {
|
||||
if (other is SassString) {
|
||||
return new SassString(valueToCss(this) + other.text);
|
||||
return new SassString(valueToCss(this) + other.text,
|
||||
quotes: other.hasQuotes);
|
||||
} else {
|
||||
return new SassIdentifier(valueToCss(this) + valueToCss(other));
|
||||
return new SassString(valueToCss(this) + valueToCss(other));
|
||||
}
|
||||
}
|
||||
|
||||
Value minus(Value other) =>
|
||||
new SassIdentifier("${valueToCss(this)}-${valueToCss(other)}");
|
||||
new SassString("${valueToCss(this)}-${valueToCss(other)}");
|
||||
|
||||
Value dividedBy(Value other) =>
|
||||
new SassIdentifier("${valueToCss(this)}/${valueToCss(other)}");
|
||||
new SassString("${valueToCss(this)}/${valueToCss(other)}");
|
||||
|
||||
Value unaryPlus() => new SassIdentifier("+${valueToCss(this)}");
|
||||
Value unaryPlus() => new SassString("+${valueToCss(this)}");
|
||||
|
||||
Value unaryMinus() => new SassIdentifier("-${valueToCss(this)}");
|
||||
Value unaryMinus() => new SassString("-${valueToCss(this)}");
|
||||
|
||||
Value unaryDivide() => new SassIdentifier("/${valueToCss(this)}");
|
||||
Value unaryDivide() => new SassString("/${valueToCss(this)}");
|
||||
|
||||
Value unaryNot() => sassFalse;
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../visitor/interface/value.dart';
|
||||
import '../value.dart';
|
||||
|
||||
class SassIdentifier extends Value {
|
||||
final String text;
|
||||
|
||||
bool get isBlank => text.isEmpty;
|
||||
|
||||
SassIdentifier(this.text);
|
||||
|
||||
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitIdentifier(this);
|
||||
|
||||
bool operator ==(other) {
|
||||
if (other is SassString) return text == other.text;
|
||||
if (other is SassIdentifier) return text == other.text;
|
||||
return false;
|
||||
}
|
||||
|
||||
int get hashCode => text.hashCode;
|
||||
}
|
@ -9,19 +9,23 @@ import '../value.dart';
|
||||
class SassString extends Value {
|
||||
final String text;
|
||||
|
||||
SassString(this.text);
|
||||
final bool hasQuotes;
|
||||
|
||||
SassString(this.text, {bool quotes: false}) : hasQuotes = quotes;
|
||||
|
||||
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitString(this);
|
||||
|
||||
Value plus(Value other) => new SassString(
|
||||
text + (other is SassString ? other.text : valueToCss(other)));
|
||||
|
||||
bool operator ==(other) {
|
||||
if (other is SassString) return text == other.text;
|
||||
if (other is SassIdentifier) return text == other.text;
|
||||
return false;
|
||||
Value plus(Value other) {
|
||||
if (other is SassString) {
|
||||
return new SassString(text + other.text,
|
||||
quotes: hasQuotes || other.hasQuotes);
|
||||
} else {
|
||||
return new SassString(text + valueToCss(other), quotes: hasQuotes);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator ==(other) => other is SassString && text == other.text;
|
||||
|
||||
int get hashCode => text.hashCode;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ abstract class ExpressionVisitor<T> {
|
||||
T visitBooleanExpression(BooleanExpression node);
|
||||
T visitColorExpression(ColorExpression node);
|
||||
T visitFunctionExpression(FunctionExpression node);
|
||||
T visitIdentifierExpression(IdentifierExpression node);
|
||||
T visitListExpression(ListExpression node);
|
||||
T visitMapExpression(MapExpression node);
|
||||
T visitNullExpression(NullExpression node);
|
||||
|
@ -7,7 +7,6 @@ import '../../value.dart';
|
||||
abstract class ValueVisitor<T> {
|
||||
T visitBoolean(SassBoolean value);
|
||||
T visitColor(SassColor value);
|
||||
T visitIdentifier(SassIdentifier value);
|
||||
T visitList(SassList value);
|
||||
T visitMap(SassMap value);
|
||||
T visitNull(SassNull value);
|
||||
|
@ -629,9 +629,6 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
|
||||
}
|
||||
}
|
||||
|
||||
SassIdentifier visitIdentifierExpression(IdentifierExpression node) =>
|
||||
new SassIdentifier(_performInterpolation(node.text));
|
||||
|
||||
SassBoolean visitBooleanExpression(BooleanExpression node) =>
|
||||
new SassBoolean(node.value);
|
||||
|
||||
@ -695,7 +692,7 @@ 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 SassIdentifier("$name(${arguments.join(', ')})");
|
||||
return new SassString("$name(${arguments.join(', ')})");
|
||||
}
|
||||
|
||||
Value _runUserDefinedCallable(CallableInvocation invocation,
|
||||
@ -805,9 +802,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
|
||||
|
||||
void _addRestMap(Map<String, Value> values, SassMap map, FileSpan span) {
|
||||
map.contents.forEach((key, value) {
|
||||
if (key is SassIdentifier) {
|
||||
values[key.text] = value;
|
||||
} else if (key is SassString) {
|
||||
if (key is SassString) {
|
||||
values[key.text] = value;
|
||||
} else {
|
||||
throw _exception(
|
||||
@ -863,7 +858,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
|
||||
}
|
||||
|
||||
SassString visitStringExpression(StringExpression node) =>
|
||||
new SassString(_performInterpolation(node.text));
|
||||
new SassString(_performInterpolation(node.text), quotes: node.hasQuotes);
|
||||
|
||||
// ## Utilities
|
||||
|
||||
|
@ -161,7 +161,7 @@ class _SerializeCssVisitor
|
||||
}
|
||||
|
||||
void _writeCustomPropertyValue(CssDeclaration node) {
|
||||
var value = (node.value.value as SassIdentifier).text;
|
||||
var value = (node.value.value as SassString).text;
|
||||
|
||||
var minimumIndentation = _minimumIndentation(value);
|
||||
if (minimumIndentation == null) {
|
||||
@ -234,9 +234,6 @@ class _SerializeCssVisitor
|
||||
_buffer.writeCharCode(hexCharFor(color & 0xF));
|
||||
}
|
||||
|
||||
void visitIdentifier(SassIdentifier value) =>
|
||||
_buffer.write(value.text.replaceAll("\n", " "));
|
||||
|
||||
void visitList(SassList value) {
|
||||
if (value.isBracketed) {
|
||||
_buffer.writeCharCode($lbracket);
|
||||
@ -301,8 +298,11 @@ class _SerializeCssVisitor
|
||||
_buffer.write(value.value.toString());
|
||||
}
|
||||
|
||||
void visitString(SassString string) =>
|
||||
_buffer.write(_visitString(string.text));
|
||||
void visitString(SassString string) {
|
||||
_buffer.write(string.hasQuotes
|
||||
? _visitString(string.text)
|
||||
: string.text.replaceAll("\n", " "));
|
||||
}
|
||||
|
||||
String _visitString(String string, {bool forceDoubleQuote: false}) {
|
||||
var includesSingleQuote = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user