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
644 lines
12 KiB
Dart
644 lines
12 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 nested_test;
|
|
|
|
import 'package:unittest/unittest.dart';
|
|
import 'testing.dart';
|
|
|
|
List optionsCss = ['--no-colors', 'memory'];
|
|
|
|
compileAndValidate(String input, String generated) {
|
|
var errors = [];
|
|
var stylesheet = compileCss(input, errors: errors, opts: optionsCss);
|
|
expect(stylesheet != null, true);
|
|
expect(errors.isEmpty, true, reason: errors.toString());
|
|
expect(prettyPrint(stylesheet), generated);
|
|
}
|
|
|
|
selectorVariations() {
|
|
final input1 = r'''html { color: red; }''';
|
|
final generated1 = r'''html {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input1, generated1);
|
|
|
|
final input2 = r'''button { span { height: 200 } }''';
|
|
final generated2 = r'''button {
|
|
}
|
|
button span {
|
|
height: 200;
|
|
}''';
|
|
compileAndValidate(input2, generated2);
|
|
|
|
final input3 = r'''div { color: red; } button { span { height: 200 } }''';
|
|
final generated3 = r'''div {
|
|
color: #f00;
|
|
}
|
|
button {
|
|
}
|
|
button span {
|
|
height: 200;
|
|
}''';
|
|
compileAndValidate(input3, generated3);
|
|
|
|
final input4 = r'''#header { color: red; h1 { font-size: 26px; } }''';
|
|
final generated4 = r'''#header {
|
|
color: #f00;
|
|
}
|
|
#header h1 {
|
|
font-size: 26px;
|
|
}''';
|
|
compileAndValidate(input4, generated4);
|
|
|
|
final input5 = r'''
|
|
#header {
|
|
color: red;
|
|
h1 { font-size: 26px; }
|
|
background-color: blue;
|
|
}''';
|
|
final generated5 = r'''#header {
|
|
color: #f00;
|
|
background-color: #00f;
|
|
}
|
|
#header h1 {
|
|
font-size: 26px;
|
|
}''';
|
|
compileAndValidate(input5, generated5);
|
|
|
|
final input6 = r'''html { body {color: red; }}''';
|
|
final generated6 = r'''html {
|
|
}
|
|
html body {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input6, generated6);
|
|
|
|
final input7 = r'''html body {color: red; }''';
|
|
final generated7 = r'''html body {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input7, generated7);
|
|
|
|
final input8 = r'''
|
|
html, body { color: red; }
|
|
button { height: 200 }
|
|
body { width: 300px; }''';
|
|
final generated8 = r'''html, body {
|
|
color: #f00;
|
|
}
|
|
button {
|
|
height: 200;
|
|
}
|
|
body {
|
|
width: 300px;
|
|
}''';
|
|
compileAndValidate(input8, generated8);
|
|
|
|
final input9 = '''
|
|
html, body {
|
|
color: red;
|
|
button { height: 200 }
|
|
div { width: 300px; }
|
|
}''';
|
|
final generated9 = r'''html, body {
|
|
color: #f00;
|
|
}
|
|
html button, body button {
|
|
height: 200;
|
|
}
|
|
html div, body div {
|
|
width: 300px;
|
|
}''';
|
|
compileAndValidate(input9, generated9);
|
|
|
|
final input10 = '''
|
|
html {
|
|
color: red;
|
|
button, div { height: 200 }
|
|
body { width: 300px; }
|
|
}''';
|
|
final generated10 = r'''html {
|
|
color: #f00;
|
|
}
|
|
html button, html div {
|
|
height: 200;
|
|
}
|
|
html body {
|
|
width: 300px;
|
|
}''';
|
|
compileAndValidate(input10, generated10);
|
|
|
|
final input11 = '''
|
|
html, body {
|
|
color: red;
|
|
button, div { height: 200 }
|
|
table { width: 300px; }
|
|
}''';
|
|
final generated11 = r'''html, body {
|
|
color: #f00;
|
|
}
|
|
html button, body button, html div, body div {
|
|
height: 200;
|
|
}
|
|
html table, body table {
|
|
width: 300px;
|
|
}''';
|
|
compileAndValidate(input11, generated11);
|
|
|
|
final input12 = '''
|
|
html, body {
|
|
color: red;
|
|
button, div {
|
|
span, a, ul { height: 200 }
|
|
}
|
|
table { width: 300px; }
|
|
}''';
|
|
final generated12 = r'''html, body {
|
|
color: #f00;
|
|
}
|
|
'''
|
|
'html button span, body button span, html div span, body div span, '
|
|
'html button a, body button a, html div a, body div a, html button ul, '
|
|
r'''body button ul, html div ul, body div ul {
|
|
height: 200;
|
|
}
|
|
html table, body table {
|
|
width: 300px;
|
|
}''';
|
|
compileAndValidate(input12, generated12);
|
|
|
|
final input13 = r'''
|
|
#header {
|
|
div {
|
|
width: 100px;
|
|
a { height: 200px; }
|
|
}
|
|
color: blue;
|
|
}
|
|
span { color: #1f1f1f; }
|
|
''';
|
|
final generated13 = r'''#header {
|
|
color: #00f;
|
|
}
|
|
#header div {
|
|
width: 100px;
|
|
}
|
|
#header div a {
|
|
height: 200px;
|
|
}
|
|
span {
|
|
color: #1f1f1f;
|
|
}''';
|
|
compileAndValidate(input13, generated13);
|
|
}
|
|
|
|
void simpleNest() {
|
|
final errors = [];
|
|
final input = '''
|
|
div span { color: green; }
|
|
#header {
|
|
color: red;
|
|
h1 {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
}
|
|
p {
|
|
font-size: 12px;
|
|
a {
|
|
text-decoration: none;
|
|
}
|
|
}
|
|
background-color: blue;
|
|
}
|
|
div > span[attr="foo"] { color: yellow; }
|
|
''';
|
|
|
|
final generated =
|
|
r'''div span {
|
|
color: #008000;
|
|
}
|
|
#header {
|
|
color: #f00;
|
|
background-color: #00f;
|
|
}
|
|
#header h1 {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
}
|
|
#header p {
|
|
font-size: 12px;
|
|
}
|
|
#header p a {
|
|
text-decoration: none;
|
|
}
|
|
div > span[attr="foo"] {
|
|
color: #ff0;
|
|
}''';
|
|
compileAndValidate(input, generated);
|
|
}
|
|
|
|
void complexNest() {
|
|
final errors = [];
|
|
final input = '''
|
|
@font-face { font-family: arial; }
|
|
div { color: #f0f0f0; }
|
|
#header + div {
|
|
color: url(abc.png);
|
|
*[attr="bar"] {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
}
|
|
p~ul {
|
|
font-size: 12px;
|
|
:not(p) {
|
|
text-decoration: none;
|
|
div > span[attr="foo"] { color: yellow; }
|
|
}
|
|
}
|
|
background-color: blue;
|
|
span {
|
|
color: red;
|
|
.one { color: blue; }
|
|
.two { color: green; }
|
|
.three { color: yellow; }
|
|
.four {
|
|
.four-1 { background-color: #00000f; }
|
|
.four-2 { background-color: #0000ff; }
|
|
.four-3 { background-color: #000fff; }
|
|
.four-4 {
|
|
height: 44px;
|
|
.four-4-1 { height: 10px; }
|
|
.four-4-2 { height: 20px; }
|
|
.four-4-3 { height: 30px; }
|
|
width: 44px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
span { color: #1f1f2f; }
|
|
''';
|
|
|
|
final generated = r'''@font-face {
|
|
font-family: arial;
|
|
}
|
|
div {
|
|
color: #f0f0f0;
|
|
}
|
|
#header + div {
|
|
color: url("abc.png");
|
|
background-color: #00f;
|
|
}
|
|
#header + div *[attr="bar"] {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
}
|
|
#header + div p ~ ul {
|
|
font-size: 12px;
|
|
}
|
|
#header + div p ~ ul :not(p) {
|
|
text-decoration: none;
|
|
}
|
|
#header + div p ~ ul :not(p) div > span[attr="foo"] {
|
|
color: #ff0;
|
|
}
|
|
#header + div span {
|
|
color: #f00;
|
|
}
|
|
#header + div span .one {
|
|
color: #00f;
|
|
}
|
|
#header + div span .two {
|
|
color: #008000;
|
|
}
|
|
#header + div span .three {
|
|
color: #ff0;
|
|
}
|
|
#header + div span .four .four-1 {
|
|
background-color: #00000f;
|
|
}
|
|
#header + div span .four .four-2 {
|
|
background-color: #00f;
|
|
}
|
|
#header + div span .four .four-3 {
|
|
background-color: #000fff;
|
|
}
|
|
#header + div span .four .four-4 {
|
|
height: 44px;
|
|
width: 44px;
|
|
}
|
|
#header + div span .four .four-4 .four-4-1 {
|
|
height: 10px;
|
|
}
|
|
#header + div span .four .four-4 .four-4-2 {
|
|
height: 20px;
|
|
}
|
|
#header + div span .four .four-4 .four-4-3 {
|
|
height: 30px;
|
|
}
|
|
span {
|
|
color: #1f1f2f;
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
}
|
|
|
|
void mediaNesting() {
|
|
var errors = [];
|
|
|
|
final input = r'''
|
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
|
#toggle-all {
|
|
image: url(test.jpb);
|
|
div, table {
|
|
background: none;
|
|
a { width: 100px; }
|
|
}
|
|
color: red;
|
|
}
|
|
}
|
|
''';
|
|
final generated = r'''@media screen AND (-webkit-min-device-pixel-ratio:0) {
|
|
#toggle-all {
|
|
image: url("test.jpb");
|
|
color: #f00;
|
|
}
|
|
#toggle-all div, #toggle-all table {
|
|
background: none;
|
|
}
|
|
#toggle-all div a, #toggle-all table a {
|
|
width: 100px;
|
|
}
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
}
|
|
|
|
void simpleThis() {
|
|
final errors = [];
|
|
final input = '''#header {
|
|
h1 {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
}
|
|
p { font-size: 12px;
|
|
a { text-decoration: none;
|
|
&:hover { border-width: 1px }
|
|
}
|
|
}
|
|
}
|
|
''';
|
|
|
|
final generated = r'''#header {
|
|
}
|
|
#header h1 {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
}
|
|
#header p {
|
|
font-size: 12px;
|
|
}
|
|
#header p a {
|
|
text-decoration: none;
|
|
}
|
|
#header p a:hover {
|
|
border-width: 1px;
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
}
|
|
|
|
void complexThis() {
|
|
var errors = [];
|
|
|
|
final input1 = r'''
|
|
.light {
|
|
.leftCol {
|
|
.textLink {
|
|
color: fooL1;
|
|
&:hover { color: barL1;}
|
|
}
|
|
.picLink {
|
|
background-image: url(/fooL1.jpg);
|
|
&:hover { background-image: url(/barL1.jpg);}
|
|
}
|
|
.textWithIconLink {
|
|
color: fooL2;
|
|
background-image: url(/fooL2.jpg);
|
|
&:hover { color: barL2; background-image: url(/barL2.jpg);}
|
|
}
|
|
}
|
|
}''';
|
|
|
|
final generated1 = r'''.light {
|
|
}
|
|
.light .leftCol .textLink {
|
|
color: fooL1;
|
|
}
|
|
.light .leftCol .textLink:hover {
|
|
color: barL1;
|
|
}
|
|
.light .leftCol .picLink {
|
|
background-image: url("/fooL1.jpg");
|
|
}
|
|
.light .leftCol .picLink:hover {
|
|
background-image: url("/barL1.jpg");
|
|
}
|
|
.light .leftCol .textWithIconLink {
|
|
color: fooL2;
|
|
background-image: url("/fooL2.jpg");
|
|
}
|
|
.light .leftCol .textWithIconLink:hover {
|
|
color: barL2;
|
|
background-image: url("/barL2.jpg");
|
|
}''';
|
|
|
|
compileAndValidate(input1, generated1);
|
|
|
|
final input2 = r'''
|
|
.textLink {
|
|
.light .leftCol & {
|
|
color: fooL1;
|
|
&:hover { color: barL1; }
|
|
}
|
|
.light .rightCol & {
|
|
color: fooL3;
|
|
&:hover { color: barL3; }
|
|
}
|
|
}''';
|
|
|
|
final generated2 = r'''
|
|
.textLink {
|
|
}
|
|
.light .leftCol .textLink {
|
|
color: fooL1;
|
|
}
|
|
.light .leftCol .textLink:hover {
|
|
color: barL1;
|
|
}
|
|
.light .rightCol .textLink {
|
|
color: fooL3;
|
|
}
|
|
.light .rightCol .textLink:hover {
|
|
color: barL3;
|
|
}''';
|
|
|
|
compileAndValidate(input2, generated2);
|
|
}
|
|
|
|
variationsThis() {
|
|
var errors = [];
|
|
|
|
final input1 = r'''
|
|
.textLink {
|
|
a {
|
|
light .leftCol & {
|
|
color: red;
|
|
}
|
|
}
|
|
}''';
|
|
final generated1 = r'''.textLink {
|
|
}
|
|
light .leftCol .textLink a {
|
|
color: #f00;
|
|
}''';
|
|
|
|
compileAndValidate(input1, generated1);
|
|
|
|
final input2 = r'''.textLink {
|
|
a {
|
|
& light .leftCol & {
|
|
color: red;
|
|
}
|
|
}
|
|
}''';
|
|
final generated2 = r'''.textLink {
|
|
}
|
|
.textLink a light .leftCol .textLink a {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input2, generated2);
|
|
|
|
final input3 = r'''
|
|
.textLink {
|
|
a {
|
|
& light .leftCol { color: red; }
|
|
}
|
|
}''';
|
|
final generated3 = r'''.textLink {
|
|
}
|
|
.textLink a light .leftCol {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input3, generated3);
|
|
|
|
final input4 = r'''
|
|
.textLink {
|
|
a {
|
|
& light .leftCol { color: red; }
|
|
&:hover { width: 100px; }
|
|
}
|
|
}''';
|
|
final generated4 = r'''.textLink {
|
|
}
|
|
.textLink a light .leftCol {
|
|
color: #f00;
|
|
}
|
|
.textLink a:hover {
|
|
width: 100px;
|
|
}''';
|
|
compileAndValidate(input4, generated4);
|
|
|
|
final input5 = r'''.textLink { a { &:hover { color: red; } } }''';
|
|
final generated5 = r'''.textLink {
|
|
}
|
|
.textLink a:hover {
|
|
color: #f00;
|
|
}''';
|
|
|
|
compileAndValidate(input5, generated5);
|
|
|
|
final input6 = r'''.textLink { &:hover { color: red; } }''';
|
|
final generated6 = r'''.textLink {
|
|
}
|
|
.textLink:hover {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input6, generated6);
|
|
|
|
final input7 = r'''.textLink { a { & + & { color: red; } } }''';
|
|
final generated7 = r'''.textLink {
|
|
}
|
|
.textLink a + .textLink a {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input7, generated7);
|
|
|
|
final input8 = r'''.textLink { a { & { color: red; } } }''';
|
|
final generated8 = r'''.textLink {
|
|
}
|
|
.textLink a {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input8, generated8);
|
|
|
|
final input9 = r'''.textLink { a { & ~ & { color: red; } } }''';
|
|
final generated9 = r'''.textLink {
|
|
}
|
|
.textLink a ~ .textLink a {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input9, generated9);
|
|
|
|
final input10 = r'''.textLink { a { & & { color: red; } } }''';
|
|
final generated10 = r'''.textLink {
|
|
}
|
|
.textLink a .textLink a {
|
|
color: #f00;
|
|
}''';
|
|
compileAndValidate(input10, generated10);
|
|
}
|
|
|
|
thisCombinator() {
|
|
var errors = [];
|
|
var input = r'''
|
|
.btn {
|
|
color: red;
|
|
}
|
|
.btn + .btn {
|
|
margin-left: 5px;
|
|
}
|
|
input.second {
|
|
& + label {
|
|
color: blue;
|
|
}
|
|
}
|
|
''';
|
|
|
|
var generated = r'''.btn {
|
|
color: #f00;
|
|
}
|
|
.btn + .btn {
|
|
margin-left: 5px;
|
|
}
|
|
input.second {
|
|
}
|
|
input.second + label {
|
|
color: #00f;
|
|
}''';
|
|
|
|
compileAndValidate(input, generated);
|
|
}
|
|
|
|
main() {
|
|
test('Selector and Nested Variations', selectorVariations);
|
|
test('Simple nesting', simpleNest);
|
|
test('Complex nesting', complexNest);
|
|
test('@media nesting', mediaNesting);
|
|
test('Simple &', simpleThis);
|
|
test("Variations &", variationsThis);
|
|
test('Complex &', complexThis);
|
|
test('& with + selector', thisCombinator);
|
|
}
|