mirror of
https://github.com/danog/dart-sass.git
synced 2025-01-22 05:41:14 +01:00
Simple perform.
This commit is contained in:
parent
5543201398
commit
34b365c8c6
@ -6,9 +6,10 @@ import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:sass/src/parser.dart';
|
||||
import 'package:sass/src/visitor/statement/perform.dart';
|
||||
|
||||
void main(List<String> args) {
|
||||
var parser = new Parser(new File(args.first).readAsStringSync(),
|
||||
url: p.toUri(args.first));
|
||||
print(parser.parse());
|
||||
print(new PerformVisitor().visitStylesheet(parser.parse()));
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../value/identifier.dart';
|
||||
import '../../value.dart';
|
||||
import 'node.dart';
|
||||
import 'value.dart';
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../value/identifier.dart';
|
||||
import 'node.dart';
|
||||
import 'value.dart';
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import 'node.dart';
|
||||
import '../../value.dart';
|
||||
|
||||
class CssValue<T> implements CssNode {
|
||||
final T value;
|
||||
|
@ -2,6 +2,8 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import 'ast/node.dart';
|
||||
@ -13,3 +15,9 @@ SourceSpan spanForList(List<AstNode> nodes) {
|
||||
var last = nodes.last.span;
|
||||
return first is FileSpan && last is FileSpan ? first.expand(last) : null;
|
||||
}
|
||||
|
||||
class LinkedListValue<T> extends LinkedListEntry<LinkedListValue<T>> {
|
||||
final T value;
|
||||
|
||||
LinkedListValue(this.value);
|
||||
}
|
||||
|
35
lib/src/visitor/expression/perform.dart
Normal file
35
lib/src/visitor/expression/perform.dart
Normal file
@ -0,0 +1,35 @@
|
||||
// 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 '../../ast/sass/expression.dart';
|
||||
import '../../ast/sass/expression/identifier.dart';
|
||||
import '../../ast/sass/expression/interpolation.dart';
|
||||
import '../../ast/sass/expression/list.dart';
|
||||
import '../../ast/sass/expression/string.dart';
|
||||
import '../../value.dart';
|
||||
import '../../value/identifier.dart';
|
||||
import '../../value/list.dart';
|
||||
import '../../value/string.dart';
|
||||
import '../expression.dart';
|
||||
|
||||
class PerformExpressionVisitor extends ExpressionVisitor<Value> {
|
||||
Value visit(Expression expression) => expression.visit(this);
|
||||
|
||||
Identifier visitIdentifierExpression(IdentifierExpression node) =>
|
||||
new Identifier(visitInterpolationExpression(node.text).text);
|
||||
|
||||
SassString visitInterpolationExpression(InterpolationExpression node) {
|
||||
return new SassString(node.contents.map((value) {
|
||||
if (value is String) return value;
|
||||
return (value as Expression).visit(this);
|
||||
}).join());
|
||||
}
|
||||
|
||||
SassList visitListExpression(ListExpression node) => new SassList(
|
||||
node.contents.map((expression) => expression.visit(this)),
|
||||
node.separator);
|
||||
|
||||
SassString visitStringExpression(StringExpression node) =>
|
||||
visitInterpolationExpression(node.text);
|
||||
}
|
99
lib/src/visitor/statement/perform.dart
Normal file
99
lib/src/visitor/statement/perform.dart
Normal file
@ -0,0 +1,99 @@
|
||||
// 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 'dart:collection';
|
||||
|
||||
import '../../ast/css/comment.dart';
|
||||
import '../../ast/css/declaration.dart';
|
||||
import '../../ast/css/node.dart';
|
||||
import '../../ast/css/style_rule.dart';
|
||||
import '../../ast/css/stylesheet.dart';
|
||||
import '../../ast/css/value.dart';
|
||||
import '../../ast/sass/comment.dart';
|
||||
import '../../ast/sass/declaration.dart';
|
||||
import '../../ast/sass/expression.dart';
|
||||
import '../../ast/sass/expression/interpolation.dart';
|
||||
import '../../ast/sass/statement.dart';
|
||||
import '../../ast/sass/style_rule.dart';
|
||||
import '../../ast/sass/stylesheet.dart';
|
||||
import '../../ast/sass/variable_declaration.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../value.dart';
|
||||
import '../expression/perform.dart';
|
||||
import '../statement.dart';
|
||||
|
||||
class PerformVisitor extends StatementVisitor {
|
||||
final _expressionVisitor = new PerformExpressionVisitor();
|
||||
final _styleRules = <CssStyleRule>[];
|
||||
|
||||
/// These are linked lists so that we can efficiently insert the style rules
|
||||
/// before their nested children.
|
||||
final _children = [new LinkedList<LinkedListValue<CssNode>>()];
|
||||
|
||||
void visit(Statement node) => node.visit(this);
|
||||
|
||||
CssStylesheet visitStylesheet(Stylesheet node) {
|
||||
super.visitStylesheet(node);
|
||||
return new CssStylesheet(_children.single.map((entry) => entry.value),
|
||||
span: node.span);
|
||||
}
|
||||
|
||||
void visitComment(Comment node) {
|
||||
if (node.isSilent) return;
|
||||
_addChild(new CssComment(node.text, span: node.span));
|
||||
}
|
||||
|
||||
void visitDeclaration(Declaration node) {
|
||||
_addChild(new CssDeclaration(
|
||||
_performInterpolation(node.name),
|
||||
_performExpression(node.value),
|
||||
span: node.span));
|
||||
}
|
||||
|
||||
void visitStyleRule(StyleRule node) {
|
||||
var selector = _performInterpolation(node.selector);
|
||||
if (_styleRules.isNotEmpty) {
|
||||
selector = new CssValue(
|
||||
"${_styleRules.last.selector.value} ${selector.value}",
|
||||
span: node.selector.span);
|
||||
}
|
||||
|
||||
// This allows us to follow Ruby Sass's behavior of always putting the style
|
||||
// rule before any of its children.
|
||||
var insertionPoint = _children.first.isEmpty ? null : _children.first.last;
|
||||
|
||||
_styleRules.add(new CssStyleRule(selector, [], span: node.span));
|
||||
var children = _collectChildren(() => super.visitStyleRule(node));
|
||||
_styleRules.removeLast();
|
||||
if (children.isEmpty) return;
|
||||
|
||||
var rule = new CssStyleRule(selector, children, span: node.span);
|
||||
if (insertionPoint == null) {
|
||||
_children.first.addFirst(new LinkedListValue(rule));
|
||||
} else {
|
||||
insertionPoint.insertAfter(new LinkedListValue(rule));
|
||||
}
|
||||
}
|
||||
|
||||
void visitVariableDeclaration(VariableDeclaration node) {}
|
||||
|
||||
CssValue<String> _performInterpolation(
|
||||
InterpolationExpression interpolation) {
|
||||
return new CssValue(
|
||||
_expressionVisitor.visitInterpolationExpression(interpolation).text);
|
||||
}
|
||||
|
||||
CssValue<Value> _performExpression(Expression expression) =>
|
||||
new CssValue(expression.visit(_expressionVisitor));
|
||||
|
||||
void _addChild(CssNode node) {
|
||||
_children.last.add(new LinkedListValue(node));
|
||||
}
|
||||
|
||||
Iterable<CssNode> _collectChildren(void callback()) {
|
||||
_children.add(new LinkedList<LinkedListValue<CssNode>>());
|
||||
callback();
|
||||
return _children.removeLast().map((entry) => entry.value);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user