8992076c3c
- Added parameter support for mixins. - Support var definition with multiple parameters as an @include parameter. - Support @extend and @extend with nested selectors. - Removed hoisting var and cycle checks - can only reference known vars. - Added bunch of tests. BUG= Review URL: https://codereview.chromium.org//23819036 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@28555 260f80e4-7a28-3924-810f-c04153c831b5
927 lines
20 KiB
Dart
927 lines
20 KiB
Dart
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library var_test;
|
|
|
|
import 'package:unittest/unittest.dart';
|
|
import 'testing.dart';
|
|
|
|
List options = ['--no-colors', '--warnings_as_errors', 'memory'];
|
|
|
|
compileAndValidate(String input, String generated) {
|
|
var errors = [];
|
|
var stylesheet = compileCss(input, errors: errors, opts: options);
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated);
|
|
}
|
|
|
|
compilePolyfillAndValidate(String input, String generated) {
|
|
var errors = [];
|
|
var stylesheet = polyFillCompileCss(input, errors: errors, opts: options);
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated);
|
|
}
|
|
|
|
void simpleVar() {
|
|
final input = ''':root {
|
|
var-color-background: red;
|
|
var-color-foreground: blue;
|
|
|
|
var-c: #00ff00;
|
|
var-b: var(c);
|
|
var-a: var(b);
|
|
}
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(color-background);
|
|
}
|
|
''';
|
|
|
|
final generated = ''':root {
|
|
var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
var-c: #0f0;
|
|
var-b: var(c);
|
|
var-a: var(b);
|
|
}
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(color-background);
|
|
}''';
|
|
|
|
final generatedPolyfill = ''':root {
|
|
}
|
|
.testIt {
|
|
color: #00f;
|
|
background: #f00;
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
compilePolyfillAndValidate(input, generatedPolyfill);
|
|
}
|
|
|
|
void expressionsVar() {
|
|
final errors = [];
|
|
final input = ''':root {
|
|
var-color-background: red;
|
|
var-color-foreground: blue;
|
|
|
|
var-c: #00ff00;
|
|
var-b: var(c);
|
|
var-a: var(b);
|
|
|
|
var-image: url(test.png);
|
|
|
|
var-b-width: 20cm;
|
|
var-m-width: 33%;
|
|
var-b-height: 30EM;
|
|
var-width: .6in;
|
|
var-length: 1.2in;
|
|
var-web-stuff: -10Px;
|
|
var-rgba: rgba(10,20,255);
|
|
var-transition: color 0.4s;
|
|
var-transform: rotate(20deg);
|
|
var-content: "✔";
|
|
var-text-shadow: 0 -1px 0 #bfbfbf;
|
|
var-font-family: Gentium;
|
|
var-src: url("http://example.com/fonts/Gentium.ttf");
|
|
var-src-1: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
|
|
var-unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
|
|
var-unicode-range-1: U+0A-FF, U+980-9FF, U+????, U+3???;
|
|
var-grid-columns: 10px ("content" 1fr 10px) [4];
|
|
}
|
|
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(c);
|
|
background-image: var(image);
|
|
|
|
border-width: var(b-width);
|
|
margin-width: var(m-width);
|
|
border-height: var(b-height);
|
|
width: var(width);
|
|
length: var(length);
|
|
-web-stuff: var(web-stuff);
|
|
background-color: var(rgba);
|
|
|
|
transition: var(transition);
|
|
transform: var(transform);
|
|
content: var(content);
|
|
text-shadow: var(text-shadow);
|
|
}
|
|
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src);
|
|
unicode-range: var(unicode-range);
|
|
}
|
|
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src-1);
|
|
unicode-range: var(unicode-range-1);
|
|
}
|
|
|
|
.foobar {
|
|
grid-columns: var(grid-columns);
|
|
}
|
|
''';
|
|
|
|
final generated = ''':root {
|
|
var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
var-c: #0f0;
|
|
var-b: var(c);
|
|
var-a: var(b);
|
|
var-image: url("test.png");
|
|
var-b-width: 20cm;
|
|
var-m-width: 33%;
|
|
var-b-height: 30em;
|
|
var-width: .6in;
|
|
var-length: 1.2in;
|
|
var-web-stuff: -10px;
|
|
var-rgba: rgba(10, 20, 255);
|
|
var-transition: color 0.4s;
|
|
var-transform: rotate(20deg);
|
|
var-content: "✔";
|
|
var-text-shadow: 0 -1px 0 #bfbfbf;
|
|
var-font-family: Gentium;
|
|
var-src: url("http://example.com/fonts/Gentium.ttf");
|
|
var-src-1: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
|
|
var-unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
|
|
var-unicode-range-1: U+0A-FF, U+980-9FF, U+????, U+3???;
|
|
var-grid-columns: 10px ("content" 1fr 10px) [4];
|
|
}
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(c);
|
|
background-image: var(image);
|
|
border-width: var(b-width);
|
|
margin-width: var(m-width);
|
|
border-height: var(b-height);
|
|
width: var(width);
|
|
length: var(length);
|
|
-web-stuff: var(web-stuff);
|
|
background-color: var(rgba);
|
|
transition: var(transition);
|
|
transform: var(transform);
|
|
content: var(content);
|
|
text-shadow: var(text-shadow);
|
|
}
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src);
|
|
unicode-range: var(unicode-range);
|
|
}
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src-1);
|
|
unicode-range: var(unicode-range-1);
|
|
}
|
|
.foobar {
|
|
grid-columns: var(grid-columns);
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
|
|
var generatedPolyfill = r''':root {
|
|
}
|
|
.testIt {
|
|
color: #00f;
|
|
background: #0f0;
|
|
background-image: url("test.png");
|
|
border-width: 20cm;
|
|
margin-width: 33%;
|
|
border-height: 30em;
|
|
width: .6in;
|
|
length: 1.2in;
|
|
-web-stuff: -10px;
|
|
background-color: rgba(10, 20, 255);
|
|
transition: color 0.4s;
|
|
transform: rotate(20deg);
|
|
content: "✔";
|
|
text-shadow: 0 -1px 0 #bfbfbf;
|
|
}
|
|
@font-face {
|
|
font-family: Gentium;
|
|
src: url("http://example.com/fonts/Gentium.ttf");
|
|
unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
|
|
}
|
|
@font-face {
|
|
font-family: Gentium;
|
|
src: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
|
|
unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???;
|
|
}
|
|
.foobar {
|
|
grid-columns: 10px ("content" 1fr 10px) [4];
|
|
}''';
|
|
|
|
compilePolyfillAndValidate(input, generatedPolyfill);
|
|
}
|
|
|
|
void defaultVar() {
|
|
final errors = [];
|
|
final input = '''
|
|
:root {
|
|
var-color-background: red;
|
|
var-color-foreground: blue;
|
|
|
|
var-a: var(b, #0a0);
|
|
var-b: var(c, #0b0);
|
|
var-c: #00ff00;
|
|
|
|
var-image: url(test.png);
|
|
|
|
var-b-width: 20cm;
|
|
var-m-width: 33%;
|
|
var-b-height: 30EM;
|
|
}
|
|
|
|
.test {
|
|
background-color: var(test, orange);
|
|
}
|
|
|
|
body {
|
|
background: var(a) var(image) no-repeat right top;
|
|
}
|
|
|
|
div {
|
|
background: var(color-background) url('img_tree.png') no-repeat right top;
|
|
}
|
|
|
|
.test-2 {
|
|
background: var(color-background) var(image-2, url('img_1.png'))
|
|
no-repeat right top;
|
|
}
|
|
|
|
.test-3 {
|
|
background: var(color-background) var(image) no-repeat right top;
|
|
}
|
|
|
|
.test-4 {
|
|
background: #ffff00 var(image) no-repeat right top;
|
|
}
|
|
|
|
.test-5 {
|
|
background: var(test-color, var(a)) var(image) no-repeat right top;
|
|
}
|
|
|
|
.test-6 {
|
|
border: red var(a-1, solid 20px);
|
|
}
|
|
''';
|
|
|
|
final generated = ''':root {
|
|
var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
var-a: var(b, #0a0);
|
|
var-b: var(c, #0b0);
|
|
var-c: #0f0;
|
|
var-image: url("test.png");
|
|
var-b-width: 20cm;
|
|
var-m-width: 33%;
|
|
var-b-height: 30em;
|
|
}
|
|
.test {
|
|
background-color: var(test, #ffa500);
|
|
}
|
|
body {
|
|
background: var(a) var(image) no-repeat right top;
|
|
}
|
|
div {
|
|
background: var(color-background) url("img_tree.png") no-repeat right top;
|
|
}
|
|
.test-2 {
|
|
background: var(color-background) var(image-2, url("img_1.png")) no-repeat right top;
|
|
}
|
|
.test-3 {
|
|
background: var(color-background) var(image) no-repeat right top;
|
|
}
|
|
.test-4 {
|
|
background: #ff0 var(image) no-repeat right top;
|
|
}
|
|
.test-5 {
|
|
background: var(test-color, var(a)) var(image) no-repeat right top;
|
|
}
|
|
.test-6 {
|
|
border: #f00 var(a-1, solid 20px);
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
|
|
var generatedPolyfill = r''':root {
|
|
}
|
|
.test {
|
|
background-color: #ffa500;
|
|
}
|
|
body {
|
|
background: #0a0 url("test.png") no-repeat right top;
|
|
}
|
|
div {
|
|
background: #f00 url("img_tree.png") no-repeat right top;
|
|
}
|
|
.test-2 {
|
|
background: #f00 url("img_1.png") no-repeat right top;
|
|
}
|
|
.test-3 {
|
|
background: #f00 url("test.png") no-repeat right top;
|
|
}
|
|
.test-4 {
|
|
background: #ff0 url("test.png") no-repeat right top;
|
|
}
|
|
.test-5 {
|
|
background: #0a0 url("test.png") no-repeat right top;
|
|
}
|
|
.test-6 {
|
|
border: #f00 solid 20px;
|
|
}''';
|
|
|
|
compilePolyfillAndValidate(input, generatedPolyfill);
|
|
}
|
|
|
|
void undefinedVars() {
|
|
final errors = [];
|
|
final input = ''':root {
|
|
var-color-background: red;
|
|
var-color-foreground: blue;
|
|
|
|
var-a: var(b);
|
|
var-b: var(c);
|
|
var-c: #00ff00;
|
|
|
|
var-one: var(two);
|
|
var-two: var(one);
|
|
|
|
var-four: var(five);
|
|
var-five: var(six);
|
|
var-six: var(four);
|
|
|
|
var-def-1: var(def-2);
|
|
var-def-2: var(def-3);
|
|
var-def-3: var(def-2);
|
|
}
|
|
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(color-background);
|
|
}
|
|
.test-1 {
|
|
color: var(c);
|
|
}
|
|
.test-2 {
|
|
color: var(one);
|
|
background: var(six);
|
|
}
|
|
''';
|
|
|
|
final generatedPolyfill = ''':root {
|
|
}
|
|
.testIt {
|
|
color: #00f;
|
|
background: #f00;
|
|
}
|
|
.test-1 {
|
|
color: #0f0;
|
|
}
|
|
.test-2 {
|
|
color: ;
|
|
background: ;
|
|
}''';
|
|
|
|
var errorStrings = [
|
|
'error :5:14: Variable is not defined.\n'
|
|
' var-a: var(b);\n'
|
|
' ^^',
|
|
'error :6:14: Variable is not defined.\n'
|
|
' var-b: var(c);\n'
|
|
' ^^',
|
|
'error :9:16: Variable is not defined.\n'
|
|
' var-one: var(two);\n'
|
|
' ^^^^',
|
|
'error :12:17: Variable is not defined.\n'
|
|
' var-four: var(five);\n'
|
|
' ^^^^^',
|
|
'error :13:17: Variable is not defined.\n'
|
|
' var-five: var(six);\n'
|
|
' ^^^^',
|
|
'error :16:18: Variable is not defined.\n'
|
|
' var-def-1: var(def-2);\n'
|
|
' ^^^^^^',
|
|
'error :17:18: Variable is not defined.\n'
|
|
' var-def-2: var(def-3);\n'
|
|
' ^^^^^^',
|
|
];
|
|
|
|
var generated = r''':root {
|
|
var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
var-a: var(b);
|
|
var-b: var(c);
|
|
var-c: #0f0;
|
|
var-one: var(two);
|
|
var-two: var(one);
|
|
var-four: var(five);
|
|
var-five: var(six);
|
|
var-six: var(four);
|
|
var-def-1: var(def-2);
|
|
var-def-2: var(def-3);
|
|
var-def-3: var(def-2);
|
|
}
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(color-background);
|
|
}
|
|
.test-1 {
|
|
color: var(c);
|
|
}
|
|
.test-2 {
|
|
color: var(one);
|
|
background: var(six);
|
|
}''';
|
|
int testBitMap = 0;
|
|
|
|
compileAndValidate(input, generated);
|
|
|
|
var stylesheet = polyFillCompileCss(input, errors: errors..clear(),
|
|
opts: options);
|
|
|
|
expect(stylesheet != null, true);
|
|
|
|
expect(errors.length, errorStrings.length, reason: errors.toString());
|
|
testBitMap = 0;
|
|
|
|
outer: for (var error in errors) {
|
|
var errorString = error.toString();
|
|
for (int i = 0; i < errorStrings.length; i++) {
|
|
if (errorString == errorStrings[i]) {
|
|
testBitMap |= 1 << i;
|
|
continue outer;
|
|
}
|
|
}
|
|
fail("Unexpected error string: $errorString");
|
|
}
|
|
expect(testBitMap, equals((1 << errorStrings.length) - 1));
|
|
expect(prettyPrint(stylesheet), generatedPolyfill);
|
|
}
|
|
|
|
parserVar() {
|
|
final input = ''':root {
|
|
var-color-background: red;
|
|
var-color-foreground: blue;
|
|
|
|
var-c: #00ff00;
|
|
var-b: var(c);
|
|
var-a: var(b);
|
|
|
|
var-image: url(test.png);
|
|
|
|
var-b-width: 20cm;
|
|
var-m-width: 33%;
|
|
var-b-height: 30EM;
|
|
var-width: .6in;
|
|
var-length: 1.2in;
|
|
var-web-stuff: -10Px;
|
|
var-rgba: rgba(10,20,255);
|
|
var-transition: color 0.4s;
|
|
var-transform: rotate(20deg);
|
|
var-content: "✔";
|
|
var-text-shadow: 0 -1px 0 #bfbfbf;
|
|
var-font-family: Gentium;
|
|
var-src: url("http://example.com/fonts/Gentium.ttf");
|
|
var-src-1: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
|
|
var-unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
|
|
var-unicode-range-1: U+0A-FF, U+980-9FF, U+????, U+3???;
|
|
var-grid-columns: 10px ("content" 1fr 10px) [4];
|
|
}
|
|
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(c);
|
|
background-image: var(image);
|
|
|
|
border-width: var(b-width);
|
|
margin-width: var(m-width);
|
|
border-height: var(b-height);
|
|
width: var(width);
|
|
length: var(length);
|
|
-web-stuff: var(web-stuff);
|
|
background-color: var(rgba);
|
|
|
|
transition: var(transition);
|
|
transform: var(transform);
|
|
content: var(content);
|
|
text-shadow: var(text-shadow);
|
|
}
|
|
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src);
|
|
unicode-range: var(unicode-range);
|
|
}
|
|
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src-1);
|
|
unicode-range: var(unicode-range-1);
|
|
}
|
|
|
|
.foobar {
|
|
grid-columns: var(grid-columns);
|
|
}
|
|
''';
|
|
|
|
final generated = ''':root {
|
|
var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
var-c: #0f0;
|
|
var-b: var(c);
|
|
var-a: var(b);
|
|
var-image: url("test.png");
|
|
var-b-width: 20cm;
|
|
var-m-width: 33%;
|
|
var-b-height: 30em;
|
|
var-width: .6in;
|
|
var-length: 1.2in;
|
|
var-web-stuff: -10px;
|
|
var-rgba: rgba(10, 20, 255);
|
|
var-transition: color 0.4s;
|
|
var-transform: rotate(20deg);
|
|
var-content: "✔";
|
|
var-text-shadow: 0 -1px 0 #bfbfbf;
|
|
var-font-family: Gentium;
|
|
var-src: url("http://example.com/fonts/Gentium.ttf");
|
|
var-src-1: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
|
|
var-unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
|
|
var-unicode-range-1: U+0A-FF, U+980-9FF, U+????, U+3???;
|
|
var-grid-columns: 10px ("content" 1fr 10px) [4];
|
|
}
|
|
.testIt {
|
|
color: var(color-foreground);
|
|
background: var(c);
|
|
background-image: var(image);
|
|
border-width: var(b-width);
|
|
margin-width: var(m-width);
|
|
border-height: var(b-height);
|
|
width: var(width);
|
|
length: var(length);
|
|
-web-stuff: var(web-stuff);
|
|
background-color: var(rgba);
|
|
transition: var(transition);
|
|
transform: var(transform);
|
|
content: var(content);
|
|
text-shadow: var(text-shadow);
|
|
}
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src);
|
|
unicode-range: var(unicode-range);
|
|
}
|
|
@font-face {
|
|
font-family: var(font-family);
|
|
src: var(src-1);
|
|
unicode-range: var(unicode-range-1);
|
|
}
|
|
.foobar {
|
|
grid-columns: var(grid-columns);
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
|
|
var generatedPolyfill = r''':root {
|
|
}
|
|
.testIt {
|
|
color: #00f;
|
|
background: #0f0;
|
|
background-image: url("test.png");
|
|
border-width: 20cm;
|
|
margin-width: 33%;
|
|
border-height: 30em;
|
|
width: .6in;
|
|
length: 1.2in;
|
|
-web-stuff: -10px;
|
|
background-color: rgba(10, 20, 255);
|
|
transition: color 0.4s;
|
|
transform: rotate(20deg);
|
|
content: "✔";
|
|
text-shadow: 0 -1px 0 #bfbfbf;
|
|
}
|
|
@font-face {
|
|
font-family: Gentium;
|
|
src: url("http://example.com/fonts/Gentium.ttf");
|
|
unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
|
|
}
|
|
@font-face {
|
|
font-family: Gentium;
|
|
src: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
|
|
unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???;
|
|
}
|
|
.foobar {
|
|
grid-columns: 10px ("content" 1fr 10px) [4];
|
|
}''';
|
|
compilePolyfillAndValidate(input, generatedPolyfill);
|
|
}
|
|
|
|
testVar() {
|
|
final errors = [];
|
|
final input = '''
|
|
@color-background: red;
|
|
@color-foreground: blue;
|
|
|
|
.test {
|
|
background-color: var(color-background);
|
|
color: var(color-foreground);
|
|
}
|
|
''';
|
|
final generated = '''
|
|
var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
|
|
.test {
|
|
background-color: var(color-background);
|
|
color: var(color-foreground);
|
|
}''';
|
|
|
|
var stylesheet = parseCss(input, errors: errors,
|
|
opts: ['--no-colors', 'memory']);
|
|
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated);
|
|
|
|
compileAndValidate(input, generated);
|
|
|
|
final input2 = '''
|
|
@color-background: red;
|
|
@color-foreground: blue;
|
|
|
|
.test {
|
|
background-color: @color-background;
|
|
color: @color-foreground;
|
|
}
|
|
''';
|
|
final generated2 = '''var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
|
|
.test {
|
|
background-color: var(color-background);
|
|
color: var(color-foreground);
|
|
}''';
|
|
|
|
stylesheet = parseCss(input, errors: errors..clear(),
|
|
opts: ['--no-colors', 'memory']);
|
|
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated2);
|
|
|
|
compileAndValidate(input2, generated2);
|
|
}
|
|
|
|
testLess() {
|
|
final errors = [];
|
|
final input = '''
|
|
@color-background: red;
|
|
@color-foreground: blue;
|
|
|
|
.test {
|
|
background-color: var(color-background);
|
|
color: var(color-foreground);
|
|
}
|
|
''';
|
|
final generated = '''var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
|
|
.test {
|
|
background-color: var(color-background);
|
|
color: var(color-foreground);
|
|
}''';
|
|
|
|
var stylesheet = parseCss(input, errors: errors,
|
|
opts: ['--no-colors', 'memory']);
|
|
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated);
|
|
|
|
compileAndValidate(input, generated);
|
|
|
|
final input2 = '''
|
|
@color-background: red;
|
|
@color-foreground: blue;
|
|
|
|
.test {
|
|
background-color: @color-background;
|
|
color: @color-foreground;
|
|
}
|
|
''';
|
|
final generated2 = '''var-color-background: #f00;
|
|
var-color-foreground: #00f;
|
|
|
|
.test {
|
|
background-color: var(color-background);
|
|
color: var(color-foreground);
|
|
}''';
|
|
|
|
stylesheet = parseCss(input, errors: errors..clear(),
|
|
opts: ['--no-colors', 'memory']);
|
|
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated2);
|
|
|
|
compileAndValidate(input2, generated2);
|
|
}
|
|
|
|
void polyfill() {
|
|
compilePolyfillAndValidate(r'''
|
|
@color-background: red;
|
|
@color-foreground: blue;
|
|
.test {
|
|
background-color: @color-background;
|
|
color: @color-foreground;
|
|
}''', r'''.test {
|
|
background-color: #f00;
|
|
color: #00f;
|
|
}''');
|
|
}
|
|
|
|
void testIndirects() {
|
|
compilePolyfillAndValidate('''
|
|
:root {
|
|
var-redef: #0f0;
|
|
|
|
var-a1: #fff;
|
|
var-a2: var(a1);
|
|
var-a3: var(a2);
|
|
|
|
var-redef: #000;
|
|
}
|
|
.test {
|
|
background-color: @a1;
|
|
color: @a2;
|
|
border-color: @a3;
|
|
}
|
|
.test-1 {
|
|
color: @redef;
|
|
}''', r''':root {
|
|
}
|
|
.test {
|
|
background-color: #fff;
|
|
color: #fff;
|
|
border-color: #fff;
|
|
}
|
|
.test-1 {
|
|
color: #000;
|
|
}''');
|
|
}
|
|
|
|
void includes() {
|
|
var errors = [];
|
|
var file1Input = r'''
|
|
:root {
|
|
var-redef: #0f0;
|
|
|
|
var-a1: #fff;
|
|
var-a2: var(a1);
|
|
var-a3: var(a2);
|
|
|
|
var-redef: #000;
|
|
}
|
|
.test-1 {
|
|
background-color: @a1;
|
|
color: @a2;
|
|
border-color: @a3;
|
|
}
|
|
.test-1a {
|
|
color: @redef;
|
|
}
|
|
''';
|
|
|
|
var file2Input = r'''
|
|
:root {
|
|
var-redef: #0b0;
|
|
var-b3: var(a3);
|
|
}
|
|
.test-2 {
|
|
color: var(b3);
|
|
background-color: var(redef);
|
|
border-color: var(a3);
|
|
}
|
|
''';
|
|
|
|
var input = r'''
|
|
:root {
|
|
var-redef: #0c0;
|
|
}
|
|
.test-main {
|
|
color: var(b3);
|
|
background-color: var(redef);
|
|
border-color: var(a3);
|
|
}
|
|
''';
|
|
|
|
var generated1 = r''':root {
|
|
var-redef: #0f0;
|
|
var-a1: #fff;
|
|
var-a2: var(a1);
|
|
var-a3: var(a2);
|
|
var-redef: #000;
|
|
}
|
|
.test-1 {
|
|
background-color: var(a1);
|
|
color: var(a2);
|
|
border-color: var(a3);
|
|
}
|
|
.test-1a {
|
|
color: var(redef);
|
|
}''';
|
|
|
|
var stylesheet1 = compileCss(file1Input, errors: errors, opts: options);
|
|
expect(stylesheet1 != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet1), generated1);
|
|
|
|
var generated2 = r''':root {
|
|
var-redef: #0b0;
|
|
var-b3: var(a3);
|
|
}
|
|
.test-2 {
|
|
color: var(b3);
|
|
background-color: var(redef);
|
|
border-color: var(a3);
|
|
}''';
|
|
|
|
var stylesheet2 = compileCss(file2Input, includes: [stylesheet1],
|
|
errors: errors..clear(), opts: options);
|
|
expect(stylesheet2 != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet2), generated2);
|
|
|
|
var generatedPolyfill1 = r''':root {
|
|
}
|
|
.test-1 {
|
|
background-color: #fff;
|
|
color: #fff;
|
|
border-color: #fff;
|
|
}
|
|
.test-1a {
|
|
color: #000;
|
|
}''';
|
|
var styleSheet1Polyfill = compileCss(file1Input, errors: errors..clear(),
|
|
polyfill: true, opts: options);
|
|
expect(styleSheet1Polyfill != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(styleSheet1Polyfill), generatedPolyfill1);
|
|
|
|
var generatedPolyfill2 = r''':root {
|
|
}
|
|
.test-2 {
|
|
color: #fff;
|
|
background-color: #0b0;
|
|
border-color: #fff;
|
|
}''';
|
|
var styleSheet2Polyfill = compileCss(file2Input, includes: [stylesheet1],
|
|
errors: errors..clear(), polyfill: true, opts: options);
|
|
expect(styleSheet2Polyfill != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(styleSheet2Polyfill), generatedPolyfill2);
|
|
|
|
// Make sure includes didn't change.
|
|
expect(prettyPrint(stylesheet1), generated1);
|
|
|
|
var generatedPolyfill = r''':root {
|
|
}
|
|
.test-main {
|
|
color: #fff;
|
|
background-color: #0c0;
|
|
border-color: #fff;
|
|
}''';
|
|
var stylesheetPolyfill = compileCss(input,
|
|
includes: [stylesheet1, stylesheet2], errors: errors..clear(),
|
|
polyfill: true, opts: options);
|
|
|
|
expect(stylesheetPolyfill != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheetPolyfill), generatedPolyfill);
|
|
|
|
// Make sure includes didn't change.
|
|
expect(prettyPrint(stylesheet1), generated1);
|
|
expect(prettyPrint(stylesheet2), generated2);
|
|
}
|
|
|
|
main() {
|
|
test('Simple var', simpleVar);
|
|
test('Expressions var', expressionsVar);
|
|
test('Default value in var()', defaultVar);
|
|
test('CSS Parser only var', parserVar);
|
|
test('Var syntax', testVar);
|
|
test('Indirects', testIndirects);
|
|
test('Forward Refs', undefinedVars);
|
|
test('Less syntax', testLess);
|
|
test('Polyfill', polyfill);
|
|
test('Multi-file', includes);
|
|
}
|