mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-30 04:39:03 +01:00
300 lines
8.9 KiB
Dart
300 lines
8.9 KiB
Dart
// Copyright 2018 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:test/test.dart';
|
|
|
|
import 'package:sass/sass.dart';
|
|
|
|
void main() {
|
|
group("in style rules", () {
|
|
test("removes unnecessary whitespace and semicolons", () {
|
|
expect(_compile("a {x: y}"), equals("a{x:y}"));
|
|
});
|
|
|
|
group("for selectors", () {
|
|
test("preserves whitespace where necessary", () {
|
|
expect(_compile("a b .c {x: y}"), equals("a b .c{x:y}"));
|
|
});
|
|
|
|
test("removes whitespace after commas", () {
|
|
expect(_compile("a, b, .c {x: y}"), equals("a,b,.c{x:y}"));
|
|
});
|
|
|
|
test("doesn't preserve newlines", () {
|
|
expect(_compile("a,\nb,\n.c {x: y}"), equals("a,b,.c{x:y}"));
|
|
});
|
|
|
|
test("removes whitespace around combinators", () {
|
|
expect(_compile("a > b {x: y}"), equals("a>b{x:y}"));
|
|
expect(_compile("a + b {x: y}"), equals("a+b{x:y}"));
|
|
expect(_compile("a ~ b {x: y}"), equals("a~b{x:y}"));
|
|
});
|
|
|
|
group("in prefixed pseudos", () {
|
|
test("preserves whitespace", () {
|
|
expect(_compile("a:nth-child(2n of b) {x: y}"),
|
|
equals("a:nth-child(2n of b){x:y}"));
|
|
});
|
|
|
|
test("removes whitespace after commas", () {
|
|
expect(_compile("a:nth-child(2n of b, c) {x: y}"),
|
|
equals("a:nth-child(2n of b,c){x:y}"));
|
|
});
|
|
});
|
|
|
|
group("in attribute selectors with modifiers", () {
|
|
test("removes whitespace when quotes are required", () {
|
|
expect(_compile('[a=" " b] {x: y}'), equals('[a=" "b]{x:y}'));
|
|
});
|
|
|
|
test("doesn't remove whitespace when quotes aren't required", () {
|
|
expect(_compile('[a="b"c] {x: y}'), equals('[a=b c]{x:y}'));
|
|
});
|
|
});
|
|
});
|
|
|
|
group("for declarations", () {
|
|
test("preserves semicolons when necessary", () {
|
|
expect(_compile("a {q: r; s: t}"), equals("a{q:r;s:t}"));
|
|
});
|
|
|
|
group("of custom properties", () {
|
|
test("folds whitespace for multiline properties", () {
|
|
expect(_compile("""
|
|
a {
|
|
--foo: {
|
|
q: r;
|
|
b {
|
|
s: t;
|
|
}
|
|
}
|
|
}
|
|
"""), equals("a{--foo: { q: r; b { s: t; } } }"));
|
|
});
|
|
|
|
test("folds whitespace for single-line properties", () {
|
|
expect(_compile("""
|
|
a {
|
|
--foo: a b\t\tc;
|
|
}
|
|
"""), equals("a{--foo: a b\tc}"));
|
|
});
|
|
|
|
test("preserves semicolons when necessary", () {
|
|
expect(_compile("""
|
|
a {
|
|
--foo: {
|
|
a: b;
|
|
};
|
|
--bar: x y;
|
|
--baz: q r;
|
|
}
|
|
"""), equals("a{--foo: { a: b; };--bar: x y;--baz: q r}"));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
group("values:", () {
|
|
group("numbers", () {
|
|
test("omit the leading 0", () {
|
|
expect(_compile("a {b: 0.123}"), equals("a{b:.123}"));
|
|
expect(_compile("a {b: 0.123px}"), equals("a{b:.123px}"));
|
|
});
|
|
});
|
|
|
|
group("lists", () {
|
|
test("don't include spaces after commas", () {
|
|
expect(_compile("a {b: x, y, z}"), equals("a{b:x,y,z}"));
|
|
});
|
|
|
|
test("don't include spaces around slashes", () {
|
|
expect(_compile("""
|
|
@use "sass:list";
|
|
a {b: list.slash(x, y, z)}
|
|
"""), equals("a{b:x/y/z}"));
|
|
});
|
|
|
|
test("do include spaces when space-separated", () {
|
|
expect(_compile("a {b: x y z}"), equals("a{b:x y z}"));
|
|
});
|
|
});
|
|
|
|
group("colors", () {
|
|
test("use names when they're shortest", () {
|
|
expect(_compile("a {b: #f00}"), equals("a{b:red}"));
|
|
});
|
|
|
|
test("use terse hex when it's shortest", () {
|
|
expect(_compile("a {b: white}"), equals("a{b:#fff}"));
|
|
});
|
|
|
|
test("use verbose hex when it's shortest", () {
|
|
expect(_compile("a {b: darkgoldenrod}"), equals("a{b:#b8860b}"));
|
|
});
|
|
|
|
test("use rgba() when necessary", () {
|
|
expect(_compile("a {b: rgba(255, 0, 0, 0.5)}"),
|
|
equals("a{b:rgba(255,0,0,.5)}"));
|
|
});
|
|
|
|
test("don't error when there's no name", () {
|
|
expect(_compile("a {b: #cc3232}"), equals("a{b:#cc3232}"));
|
|
});
|
|
});
|
|
|
|
group("strings", () {
|
|
group("emits private-use area characters as literal characters", () {
|
|
testCharacter(int character) {
|
|
var escape = "\\${character.toRadixString(16)}";
|
|
test(escape, () {
|
|
expect(
|
|
_compile("a {b: $escape}"),
|
|
equalsIgnoringWhitespace(
|
|
"a{b:${String.fromCharCode(character)}}"));
|
|
});
|
|
}
|
|
|
|
group("in the basic multilingual plane", () {
|
|
testCharacter(0xe000);
|
|
testCharacter(0xf000);
|
|
testCharacter(0xf8ff);
|
|
});
|
|
|
|
group("in the supplementary planes", () {
|
|
testCharacter(0xf0000);
|
|
testCharacter(0xfabcd);
|
|
testCharacter(0xffffd);
|
|
testCharacter(0x100000);
|
|
testCharacter(0x10abcd);
|
|
testCharacter(0x10fffd);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
group("the top level", () {
|
|
test("removes whitespace and semicolons between at-rules", () {
|
|
expect(_compile("@foo; @bar; @baz;"), equals("@foo;@bar;@baz"));
|
|
});
|
|
|
|
test("removes whitespace between style rules", () {
|
|
expect(_compile("a {b: c} x {y: z}"), equals("a{b:c}x{y:z}"));
|
|
});
|
|
});
|
|
|
|
group("@supports", () {
|
|
test("removes whitespace around the condition", () {
|
|
expect(_compile("@supports (display: flex) {a {b: c}}"),
|
|
equals("@supports(display: flex){a{b:c}}"));
|
|
});
|
|
|
|
test("preserves whitespace before the condition if necessary", () {
|
|
expect(_compile("@supports not (display: flex) {a {b: c}}"),
|
|
equals("@supports not (display: flex){a{b:c}}"));
|
|
});
|
|
});
|
|
|
|
group("@media", () {
|
|
test("removes whitespace around the query", () {
|
|
expect(_compile("@media (min-width: 900px) {a {b: c}}"),
|
|
equals("@media(min-width: 900px){a{b:c}}"));
|
|
});
|
|
|
|
test("preserves whitespace before the query if necessary", () {
|
|
expect(_compile("@media screen {a {b: c}}"),
|
|
equals("@media screen{a{b:c}}"));
|
|
});
|
|
|
|
// Removing whitespace after "and", "or", or "not" is forbidden because it
|
|
// would cause it to parse as a function token.
|
|
test('removes whitespace before "and" when possible', () {
|
|
expect(
|
|
_compile("""
|
|
@media screen and (min-width: 900px) and (max-width: 100px) {
|
|
a {b: c}
|
|
}
|
|
"""),
|
|
equals("@media screen and (min-width: 900px)and (max-width: 100px)"
|
|
"{a{b:c}}"));
|
|
});
|
|
|
|
test("preserves whitespace around the modifier", () {
|
|
expect(_compile("@media only screen {a {b: c}}"),
|
|
equals("@media only screen{a{b:c}}"));
|
|
});
|
|
});
|
|
|
|
group("@keyframes", () {
|
|
test("removes whitespace after the selector", () {
|
|
expect(_compile("@keyframes a {from {a: b}}"),
|
|
equals("@keyframes a{from{a:b}}"));
|
|
});
|
|
|
|
test("removes whitespace after commas", () {
|
|
expect(_compile("@keyframes a {from, to {a: b}}"),
|
|
equals("@keyframes a{from,to{a:b}}"));
|
|
});
|
|
});
|
|
|
|
group("@import", () {
|
|
test("removes whitespace before the URL", () {
|
|
expect(_compile('@import "foo.css";'), equals('@import"foo.css"'));
|
|
});
|
|
|
|
test("converts a url() to a string", () {
|
|
expect(_compile('@import url(foo.css);'), equals('@import"foo.css"'));
|
|
expect(_compile('@import url("foo.css");'), equals('@import"foo.css"'));
|
|
});
|
|
|
|
test("removes whitespace before a media query", () {
|
|
expect(_compile('@import "foo.css" screen;'),
|
|
equals('@import"foo.css"screen'));
|
|
});
|
|
|
|
test("removes whitespace before a supports condition", () {
|
|
expect(_compile('@import "foo.css" supports(display: flex);'),
|
|
equals('@import"foo.css"supports(display: flex)'));
|
|
});
|
|
});
|
|
|
|
group("comments", () {
|
|
test("are removed", () {
|
|
expect(_compile("/* foo bar */"), isEmpty);
|
|
expect(_compile("""
|
|
a {
|
|
b: c;
|
|
/* foo bar */
|
|
d: e;
|
|
}
|
|
"""), equals("a{b:c;d:e}"));
|
|
});
|
|
|
|
test("remove their parents if they're the only contents", () {
|
|
expect(_compile("a {/* foo bar */}"), isEmpty);
|
|
expect(_compile("""
|
|
a {
|
|
/* foo bar */
|
|
/* baz bang */
|
|
}
|
|
"""), isEmpty);
|
|
});
|
|
|
|
test("are preserved with /*!", () {
|
|
expect(_compile("/*! foo bar */"), equals("/*! foo bar */"));
|
|
expect(
|
|
_compile("/*! foo */\n/*! bar */"), equals("/*! foo *//*! bar */"));
|
|
expect(_compile("""
|
|
a {
|
|
/*! foo bar */
|
|
}
|
|
"""), equals("a{/*! foo bar */}"));
|
|
});
|
|
});
|
|
}
|
|
|
|
/// Like [compileString], but always produces compressed output.
|
|
String _compile(String source) =>
|
|
compileString(source, style: OutputStyle.compressed);
|