Files
esbuild/internal/css_parser/css_parser_test.go
2020-09-30 00:09:39 -07:00

503 lines
27 KiB
Go

package css_parser
import (
"testing"
"github.com/evanw/esbuild/internal/config"
"github.com/evanw/esbuild/internal/css_printer"
"github.com/evanw/esbuild/internal/logger"
"github.com/evanw/esbuild/internal/test"
)
func assertEqual(t *testing.T, a interface{}, b interface{}) {
t.Helper()
if a != b {
t.Fatalf("%s != %s", a, b)
}
}
func expectParseError(t *testing.T, contents string, expected string) {
t.Helper()
t.Run(contents, func(t *testing.T) {
t.Helper()
log := logger.NewDeferLog()
Parse(log, test.SourceForTest(contents), config.Options{})
msgs := log.Done()
text := ""
for _, msg := range msgs {
text += msg.String(logger.StderrOptions{}, logger.TerminalInfo{})
}
test.AssertEqual(t, text, expected)
})
}
func expectPrintedCommon(t *testing.T, name string, contents string, expected string, options config.Options) {
t.Helper()
t.Run(name, func(t *testing.T) {
t.Helper()
log := logger.NewDeferLog()
tree := Parse(log, test.SourceForTest(contents), options)
msgs := log.Done()
text := ""
for _, msg := range msgs {
if msg.Kind == logger.Error {
text += msg.String(logger.StderrOptions{}, logger.TerminalInfo{})
}
}
assertEqual(t, text, "")
css := css_printer.Print(tree, css_printer.Options{})
assertEqual(t, string(css), expected)
})
}
func expectPrinted(t *testing.T, contents string, expected string) {
t.Helper()
expectPrintedCommon(t, contents, contents, expected, config.Options{})
}
func expectPrintedMangle(t *testing.T, contents string, expected string) {
t.Helper()
expectPrintedCommon(t, contents+" [mangle]", contents, expected, config.Options{
MangleSyntax: true,
})
}
func TestString(t *testing.T) {
expectPrinted(t, "a:after { content: 'a\\\rb' }", "a:after {\n content: \"ab\";\n}\n")
expectPrinted(t, "a:after { content: 'a\\\nb' }", "a:after {\n content: \"ab\";\n}\n")
expectPrinted(t, "a:after { content: 'a\\\fb' }", "a:after {\n content: \"ab\";\n}\n")
expectPrinted(t, "a:after { content: 'a\\\r\nb' }", "a:after {\n content: \"ab\";\n}\n")
expectPrinted(t, "a:after { content: 'a\\62 c' }", "a:after {\n content: \"abc\";\n}\n")
expectParseError(t, "a:after { content: '\r' }",
`<stdin>: error: Unterminated string token
<stdin>: error: Unterminated string token
<stdin>: warning: Expected "}" but found end of file
`)
expectParseError(t, "a:after { content: '\n' }",
`<stdin>: error: Unterminated string token
<stdin>: error: Unterminated string token
<stdin>: warning: Expected "}" but found end of file
`)
expectParseError(t, "a:after { content: '\f' }",
`<stdin>: error: Unterminated string token
<stdin>: error: Unterminated string token
<stdin>: warning: Expected "}" but found end of file
`)
expectParseError(t, "a:after { content: '\r\n' }",
`<stdin>: error: Unterminated string token
<stdin>: error: Unterminated string token
<stdin>: warning: Expected "}" but found end of file
`)
expectPrinted(t, "a:after { content: '\\1010101' }", "a:after {\n content: \"\U001010101\";\n}\n")
expectPrinted(t, "a:after { content: '\\invalid' }", "a:after {\n content: \"invalid\";\n}\n")
}
func TestNumber(t *testing.T) {
for _, ext := range []string{"", "%", "px+"} {
expectPrinted(t, "a { width: 0."+ext+"; }", "a {\n width: 0."+ext+";\n}\n")
expectPrinted(t, "a { width: 0.1"+ext+"; }", "a {\n width: 0.1"+ext+";\n}\n")
expectPrinted(t, "a { width: +0."+ext+"; }", "a {\n width: +0."+ext+";\n}\n")
expectPrinted(t, "a { width: +0.1"+ext+"; }", "a {\n width: +0.1"+ext+";\n}\n")
expectPrinted(t, "a { width: -0."+ext+"; }", "a {\n width: -0."+ext+";\n}\n")
expectPrinted(t, "a { width: -0.1"+ext+"; }", "a {\n width: -0.1"+ext+";\n}\n")
expectPrintedMangle(t, "a { width: 0."+ext+"; }", "a {\n width: 0"+ext+";\n}\n")
expectPrintedMangle(t, "a { width: 0.1"+ext+"; }", "a {\n width: .1"+ext+";\n}\n")
expectPrintedMangle(t, "a { width: +0."+ext+"; }", "a {\n width: +0"+ext+";\n}\n")
expectPrintedMangle(t, "a { width: +0.1"+ext+"; }", "a {\n width: +.1"+ext+";\n}\n")
expectPrintedMangle(t, "a { width: -0."+ext+"; }", "a {\n width: -0"+ext+";\n}\n")
expectPrintedMangle(t, "a { width: -0.1"+ext+"; }", "a {\n width: -.1"+ext+";\n}\n")
}
}
func TestHexColor(t *testing.T) {
// "#RGBA"
expectPrinted(t, "a { color: #1234 }", "a {\n color: #1234;\n}\n")
expectPrinted(t, "a { color: #123f }", "a {\n color: #123f;\n}\n")
expectPrinted(t, "a { color: #abcd }", "a {\n color: #abcd;\n}\n")
expectPrinted(t, "a { color: #abcf }", "a {\n color: #abcf;\n}\n")
expectPrinted(t, "a { color: #ABCD }", "a {\n color: #ABCD;\n}\n")
expectPrinted(t, "a { color: #ABCF }", "a {\n color: #ABCF;\n}\n")
expectPrintedMangle(t, "a { color: #1234 }", "a {\n color: #1234;\n}\n")
expectPrintedMangle(t, "a { color: #123f }", "a {\n color: #123;\n}\n")
expectPrintedMangle(t, "a { color: #abcd }", "a {\n color: #abcd;\n}\n")
expectPrintedMangle(t, "a { color: #abcf }", "a {\n color: #abc;\n}\n")
expectPrintedMangle(t, "a { color: #ABCD }", "a {\n color: #ABCD;\n}\n")
expectPrintedMangle(t, "a { color: #ABCF }", "a {\n color: #abc;\n}\n")
// "#RRGGBB"
expectPrinted(t, "a { color: #112233 }", "a {\n color: #112233;\n}\n")
expectPrinted(t, "a { color: #122233 }", "a {\n color: #122233;\n}\n")
expectPrinted(t, "a { color: #112333 }", "a {\n color: #112333;\n}\n")
expectPrinted(t, "a { color: #112234 }", "a {\n color: #112234;\n}\n")
expectPrintedMangle(t, "a { color: #112233 }", "a {\n color: #123;\n}\n")
expectPrintedMangle(t, "a { color: #122233 }", "a {\n color: #122233;\n}\n")
expectPrintedMangle(t, "a { color: #112333 }", "a {\n color: #112333;\n}\n")
expectPrintedMangle(t, "a { color: #112234 }", "a {\n color: #112234;\n}\n")
expectPrinted(t, "a { color: #aabbcc }", "a {\n color: #aabbcc;\n}\n")
expectPrinted(t, "a { color: #abbbcc }", "a {\n color: #abbbcc;\n}\n")
expectPrinted(t, "a { color: #aabccc }", "a {\n color: #aabccc;\n}\n")
expectPrinted(t, "a { color: #aabbcd }", "a {\n color: #aabbcd;\n}\n")
expectPrintedMangle(t, "a { color: #aabbcc }", "a {\n color: #abc;\n}\n")
expectPrintedMangle(t, "a { color: #abbbcc }", "a {\n color: #abbbcc;\n}\n")
expectPrintedMangle(t, "a { color: #aabccc }", "a {\n color: #aabccc;\n}\n")
expectPrintedMangle(t, "a { color: #aabbcd }", "a {\n color: #aabbcd;\n}\n")
expectPrinted(t, "a { color: #AABBCC }", "a {\n color: #AABBCC;\n}\n")
expectPrinted(t, "a { color: #ABBBCC }", "a {\n color: #ABBBCC;\n}\n")
expectPrinted(t, "a { color: #AABCCC }", "a {\n color: #AABCCC;\n}\n")
expectPrinted(t, "a { color: #AABBCD }", "a {\n color: #AABBCD;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCC }", "a {\n color: #abc;\n}\n")
expectPrintedMangle(t, "a { color: #ABBBCC }", "a {\n color: #ABBBCC;\n}\n")
expectPrintedMangle(t, "a { color: #AABCCC }", "a {\n color: #AABCCC;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCD }", "a {\n color: #AABBCD;\n}\n")
// "#RRGGBBAA"
expectPrinted(t, "a { color: #11223344 }", "a {\n color: #11223344;\n}\n")
expectPrinted(t, "a { color: #12223344 }", "a {\n color: #12223344;\n}\n")
expectPrinted(t, "a { color: #11233344 }", "a {\n color: #11233344;\n}\n")
expectPrinted(t, "a { color: #11223444 }", "a {\n color: #11223444;\n}\n")
expectPrinted(t, "a { color: #11223345 }", "a {\n color: #11223345;\n}\n")
expectPrintedMangle(t, "a { color: #11223344 }", "a {\n color: #1234;\n}\n")
expectPrintedMangle(t, "a { color: #12223344 }", "a {\n color: #12223344;\n}\n")
expectPrintedMangle(t, "a { color: #11233344 }", "a {\n color: #11233344;\n}\n")
expectPrintedMangle(t, "a { color: #11223444 }", "a {\n color: #11223444;\n}\n")
expectPrintedMangle(t, "a { color: #11223345 }", "a {\n color: #11223345;\n}\n")
expectPrinted(t, "a { color: #aabbccdd }", "a {\n color: #aabbccdd;\n}\n")
expectPrinted(t, "a { color: #abbbccdd }", "a {\n color: #abbbccdd;\n}\n")
expectPrinted(t, "a { color: #aabcccdd }", "a {\n color: #aabcccdd;\n}\n")
expectPrinted(t, "a { color: #aabbcddd }", "a {\n color: #aabbcddd;\n}\n")
expectPrinted(t, "a { color: #aabbccde }", "a {\n color: #aabbccde;\n}\n")
expectPrintedMangle(t, "a { color: #aabbccdd }", "a {\n color: #abcd;\n}\n")
expectPrintedMangle(t, "a { color: #abbbccdd }", "a {\n color: #abbbccdd;\n}\n")
expectPrintedMangle(t, "a { color: #aabcccdd }", "a {\n color: #aabcccdd;\n}\n")
expectPrintedMangle(t, "a { color: #aabbcddd }", "a {\n color: #aabbcddd;\n}\n")
expectPrintedMangle(t, "a { color: #aabbccde }", "a {\n color: #aabbccde;\n}\n")
expectPrinted(t, "a { color: #AABBCCDD }", "a {\n color: #AABBCCDD;\n}\n")
expectPrinted(t, "a { color: #ABBBCCDD }", "a {\n color: #ABBBCCDD;\n}\n")
expectPrinted(t, "a { color: #AABCCCDD }", "a {\n color: #AABCCCDD;\n}\n")
expectPrinted(t, "a { color: #AABBCDDD }", "a {\n color: #AABBCDDD;\n}\n")
expectPrinted(t, "a { color: #AABBCCDE }", "a {\n color: #AABBCCDE;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCCDD }", "a {\n color: #abcd;\n}\n")
expectPrintedMangle(t, "a { color: #ABBBCCDD }", "a {\n color: #ABBBCCDD;\n}\n")
expectPrintedMangle(t, "a { color: #AABCCCDD }", "a {\n color: #AABCCCDD;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCDDD }", "a {\n color: #AABBCDDD;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCCDE }", "a {\n color: #AABBCCDE;\n}\n")
// "#RRGGBBFF"
expectPrinted(t, "a { color: #112233ff }", "a {\n color: #112233ff;\n}\n")
expectPrinted(t, "a { color: #122233ff }", "a {\n color: #122233ff;\n}\n")
expectPrinted(t, "a { color: #112333ff }", "a {\n color: #112333ff;\n}\n")
expectPrinted(t, "a { color: #112234ff }", "a {\n color: #112234ff;\n}\n")
expectPrinted(t, "a { color: #112233ef }", "a {\n color: #112233ef;\n}\n")
expectPrintedMangle(t, "a { color: #112233ff }", "a {\n color: #123;\n}\n")
expectPrintedMangle(t, "a { color: #122233ff }", "a {\n color: #122233;\n}\n")
expectPrintedMangle(t, "a { color: #112333ff }", "a {\n color: #112333;\n}\n")
expectPrintedMangle(t, "a { color: #112234ff }", "a {\n color: #112234;\n}\n")
expectPrintedMangle(t, "a { color: #112233ef }", "a {\n color: #112233ef;\n}\n")
expectPrinted(t, "a { color: #aabbccff }", "a {\n color: #aabbccff;\n}\n")
expectPrinted(t, "a { color: #abbbccff }", "a {\n color: #abbbccff;\n}\n")
expectPrinted(t, "a { color: #aabcccff }", "a {\n color: #aabcccff;\n}\n")
expectPrinted(t, "a { color: #aabbcdff }", "a {\n color: #aabbcdff;\n}\n")
expectPrinted(t, "a { color: #aabbccef }", "a {\n color: #aabbccef;\n}\n")
expectPrintedMangle(t, "a { color: #aabbccff }", "a {\n color: #abc;\n}\n")
expectPrintedMangle(t, "a { color: #abbbccff }", "a {\n color: #abbbcc;\n}\n")
expectPrintedMangle(t, "a { color: #aabcccff }", "a {\n color: #aabccc;\n}\n")
expectPrintedMangle(t, "a { color: #aabbcdff }", "a {\n color: #aabbcd;\n}\n")
expectPrintedMangle(t, "a { color: #aabbccef }", "a {\n color: #aabbccef;\n}\n")
expectPrinted(t, "a { color: #AABBCCFF }", "a {\n color: #AABBCCFF;\n}\n")
expectPrinted(t, "a { color: #ABBBCCFF }", "a {\n color: #ABBBCCFF;\n}\n")
expectPrinted(t, "a { color: #AABCCCFF }", "a {\n color: #AABCCCFF;\n}\n")
expectPrinted(t, "a { color: #AABBCDFF }", "a {\n color: #AABBCDFF;\n}\n")
expectPrinted(t, "a { color: #AABBCCEF }", "a {\n color: #AABBCCEF;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCCFF }", "a {\n color: #abc;\n}\n")
expectPrintedMangle(t, "a { color: #ABBBCCFF }", "a {\n color: #abbbcc;\n}\n")
expectPrintedMangle(t, "a { color: #AABCCCFF }", "a {\n color: #aabccc;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCDFF }", "a {\n color: #aabbcd;\n}\n")
expectPrintedMangle(t, "a { color: #AABBCCEF }", "a {\n color: #AABBCCEF;\n}\n")
}
func TestColorNames(t *testing.T) {
expectPrinted(t, "a { color: #f00 }", "a {\n color: #f00;\n}\n")
expectPrinted(t, "a { color: #f00f }", "a {\n color: #f00f;\n}\n")
expectPrinted(t, "a { color: #ff0000 }", "a {\n color: #ff0000;\n}\n")
expectPrinted(t, "a { color: #ff0000ff }", "a {\n color: #ff0000ff;\n}\n")
expectPrintedMangle(t, "a { color: #f00 }", "a {\n color: red;\n}\n")
expectPrintedMangle(t, "a { color: #f00e }", "a {\n color: #f00e;\n}\n")
expectPrintedMangle(t, "a { color: #f00f }", "a {\n color: red;\n}\n")
expectPrintedMangle(t, "a { color: #ff0000 }", "a {\n color: red;\n}\n")
expectPrintedMangle(t, "a { color: #ff0000ef }", "a {\n color: #ff0000ef;\n}\n")
expectPrintedMangle(t, "a { color: #ff0000ff }", "a {\n color: red;\n}\n")
expectPrintedMangle(t, "a { color: #ffc0cb }", "a {\n color: pink;\n}\n")
expectPrintedMangle(t, "a { color: #ffc0cbef }", "a {\n color: #ffc0cbef;\n}\n")
expectPrintedMangle(t, "a { color: #ffc0cbff }", "a {\n color: pink;\n}\n")
expectPrinted(t, "a { color: white }", "a {\n color: white;\n}\n")
expectPrinted(t, "a { color: tUrQuOiSe }", "a {\n color: tUrQuOiSe;\n}\n")
expectPrintedMangle(t, "a { color: white }", "a {\n color: #fff;\n}\n")
expectPrintedMangle(t, "a { color: tUrQuOiSe }", "a {\n color: #40e0d0;\n}\n")
}
func TestDeclaration(t *testing.T) {
expectPrinted(t, ".decl {}", ".decl {\n}\n")
expectPrinted(t, ".decl { a: b }", ".decl {\n a: b;\n}\n")
expectPrinted(t, ".decl { a: b; }", ".decl {\n a: b;\n}\n")
expectPrinted(t, ".decl { a: b; c: d }", ".decl {\n a: b;\n c: d;\n}\n")
expectPrinted(t, ".decl { a: b; c: d; }", ".decl {\n a: b;\n c: d;\n}\n")
expectParseError(t, ".decl { a { b: c; } }", "<stdin>: warning: Expected \":\" but found \"{\"\n")
expectPrinted(t, ".decl { & a { b: c; } }", ".decl {\n & a {\n b: c;\n }\n}\n")
}
func TestSelector(t *testing.T) {
expectPrinted(t, "a{}", "a {\n}\n")
expectPrinted(t, "a {}", "a {\n}\n")
expectPrinted(t, "a b {}", "a b {\n}\n")
expectPrinted(t, "[b]{}", "[b] {\n}\n")
expectPrinted(t, "[b] {}", "[b] {\n}\n")
expectPrinted(t, "a[b] {}", "a[b] {\n}\n")
expectPrinted(t, "a [b] {}", "a [b] {\n}\n")
expectParseError(t, "[] {}", "<stdin>: warning: Expected identifier but found \"]\"\n")
expectParseError(t, "[b {}", "<stdin>: warning: Expected \"]\" but found \"{\"\n")
expectParseError(t, "[b]] {}", "<stdin>: warning: Unexpected \"]\"\n")
expectParseError(t, "a[b {}", "<stdin>: warning: Expected \"]\" but found \"{\"\n")
expectParseError(t, "a[b]] {}", "<stdin>: warning: Unexpected \"]\"\n")
expectPrinted(t, "[|b]{}", "[b] {\n}\n") // "[|b]" is equivalent to "[b]"
expectPrinted(t, "[*|b]{}", "[*|b] {\n}\n")
expectPrinted(t, "[a|b]{}", "[a|b] {\n}\n")
expectPrinted(t, "[a|b|=\"c\"]{}", "[a|b|=\"c\"] {\n}\n")
expectPrinted(t, "[a|b |= \"c\"]{}", "[a|b|=\"c\"] {\n}\n")
expectParseError(t, "[a||b] {}", "<stdin>: warning: Expected identifier but found \"|\"\n")
expectParseError(t, "[* | b] {}", "<stdin>: warning: Expected \"|\" but found whitespace\n")
expectParseError(t, "[a | b] {}", "<stdin>: warning: Expected \"=\" but found whitespace\n")
expectPrinted(t, "[b=\"c\"] {}", "[b=\"c\"] {\n}\n")
expectPrinted(t, "[b~=\"c\"] {}", "[b~=\"c\"] {\n}\n")
expectPrinted(t, "[b^=\"c\"] {}", "[b^=\"c\"] {\n}\n")
expectPrinted(t, "[b$=\"c\"] {}", "[b$=\"c\"] {\n}\n")
expectPrinted(t, "[b*=\"c\"] {}", "[b*=\"c\"] {\n}\n")
expectPrinted(t, "[b|=\"c\"] {}", "[b|=\"c\"] {\n}\n")
expectParseError(t, "[b?=\"c\"] {}", "<stdin>: warning: Expected \"]\" but found \"?\"\n")
expectPrinted(t, "[b = \"c\"] {}", "[b=\"c\"] {\n}\n")
expectPrinted(t, "[b ~= \"c\"] {}", "[b~=\"c\"] {\n}\n")
expectPrinted(t, "[b ^= \"c\"] {}", "[b^=\"c\"] {\n}\n")
expectPrinted(t, "[b $= \"c\"] {}", "[b$=\"c\"] {\n}\n")
expectPrinted(t, "[b *= \"c\"] {}", "[b*=\"c\"] {\n}\n")
expectPrinted(t, "[b |= \"c\"] {}", "[b|=\"c\"] {\n}\n")
expectParseError(t, "[b ?= \"c\"] {}", "<stdin>: warning: Expected \"]\" but found \"?\"\n")
expectPrinted(t, "[b = \"c\" i] {}", "[b=\"c\" i] {\n}\n")
expectPrinted(t, "[b = \"c\" I] {}", "[b=\"c\" I] {\n}\n")
expectParseError(t, "[b i] {}", "<stdin>: warning: Expected \"]\" but found \"i\"\n<stdin>: warning: Unexpected \"]\"\n")
expectParseError(t, "[b I] {}", "<stdin>: warning: Expected \"]\" but found \"I\"\n<stdin>: warning: Unexpected \"]\"\n")
expectPrinted(t, "|b {}", "|b {\n}\n")
expectPrinted(t, "|* {}", "|* {\n}\n")
expectPrinted(t, "a|b {}", "a|b {\n}\n")
expectPrinted(t, "a|* {}", "a|* {\n}\n")
expectPrinted(t, "*|b {}", "*|b {\n}\n")
expectPrinted(t, "*|* {}", "*|* {\n}\n")
expectParseError(t, "a||b {}", "<stdin>: warning: Expected identifier but found \"|\"\n")
expectPrinted(t, "a+b {}", "a + b {\n}\n")
expectPrinted(t, "a>b {}", "a > b {\n}\n")
expectPrinted(t, "a+b {}", "a + b {\n}\n")
expectPrinted(t, "a~b {}", "a ~ b {\n}\n")
expectPrinted(t, "a + b {}", "a + b {\n}\n")
expectPrinted(t, "a > b {}", "a > b {\n}\n")
expectPrinted(t, "a + b {}", "a + b {\n}\n")
expectPrinted(t, "a ~ b {}", "a ~ b {\n}\n")
expectPrinted(t, "::b {}", "::b {\n}\n")
expectPrinted(t, "*::b {}", "*::b {\n}\n")
expectPrinted(t, "a::b {}", "a::b {\n}\n")
expectPrinted(t, "::b(c) {}", "::b(c) {\n}\n")
expectPrinted(t, "*::b(c) {}", "*::b(c) {\n}\n")
expectPrinted(t, "a::b(c) {}", "a::b(c) {\n}\n")
expectPrinted(t, "a:b:c {}", "a:b:c {\n}\n")
expectPrinted(t, "a:b(:c) {}", "a:b(:c) {\n}\n")
}
func TestNestedSelector(t *testing.T) {
expectPrinted(t, "& {}", "& {\n}\n")
expectPrinted(t, "& b {}", "& b {\n}\n")
expectPrinted(t, "&:b {}", "&:b {\n}\n")
expectPrinted(t, "&* {}", "&* {\n}\n")
expectPrinted(t, "&|b {}", "&|b {\n}\n")
expectPrinted(t, "&*|b {}", "&*|b {\n}\n")
expectPrinted(t, "&a|b {}", "&a|b {\n}\n")
expectPrinted(t, "&[a] {}", "&[a] {\n}\n")
expectPrinted(t, "a { & {} }", "a {\n & {\n }\n}\n")
expectPrinted(t, "a { & b {} }", "a {\n & b {\n }\n}\n")
expectPrinted(t, "a { &:b {} }", "a {\n &:b {\n }\n}\n")
expectPrinted(t, "a { &* {} }", "a {\n &* {\n }\n}\n")
expectPrinted(t, "a { &|b {} }", "a {\n &|b {\n }\n}\n")
expectPrinted(t, "a { &*|b {} }", "a {\n &*|b {\n }\n}\n")
expectPrinted(t, "a { &a|b {} }", "a {\n &a|b {\n }\n}\n")
expectPrinted(t, "a { &[b] {} }", "a {\n &[b] {\n }\n}\n")
}
func TestBadQualifiedRules(t *testing.T) {
expectParseError(t, "$bad: rule;", "<stdin>: warning: Unexpected \"$\"\n")
expectParseError(t, "$bad { color: red }", "<stdin>: warning: Unexpected \"$\"\n")
expectParseError(t, "a { div.major { color: blue } color: red }", "<stdin>: warning: Expected \":\" but found \".\"\n")
expectParseError(t, "a { div:hover { color: blue } color: red }", "<stdin>: warning: Expected \";\"\n")
expectParseError(t, "a { div:hover { color: blue }; color: red }", "")
expectParseError(t, "a { div:hover { color: blue } ; color: red }", "")
}
func TestAtRule(t *testing.T) {
expectPrinted(t, "@unknown;", "@unknown;\n")
expectPrinted(t, "@unknown{}", "@unknown {}\n")
expectPrinted(t, "@unknown x;", "@unknown x;\n")
expectPrinted(t, "@unknown{\na: b;\nc: d;\n}", "@unknown { a: b; c: d; }\n")
expectParseError(t, "@unknown", "<stdin>: warning: \"@unknown\" is not a known rule name\n<stdin>: warning: Expected \"{\" but found end of file\n")
expectParseError(t, "@", "<stdin>: warning: Unexpected \"@\"\n")
expectParseError(t, "@;", "<stdin>: warning: Unexpected \"@\"\n")
expectParseError(t, "@{}", "<stdin>: warning: Unexpected \"@\"\n")
}
func TestAtCharset(t *testing.T) {
expectPrinted(t, "@charset \"UTF-8\";", "@charset \"UTF-8\";\n")
expectPrinted(t, "@charset 'UTF-8';", "@charset \"UTF-8\";\n")
expectParseError(t, "@charset \"US-ASCII\";", "<stdin>: warning: \"UTF-8\" will be used instead of unsupported charset \"US-ASCII\"\n")
expectParseError(t, "@charset;", "<stdin>: warning: Expected whitespace but found \";\"\n")
expectParseError(t, "@charset ;", "<stdin>: warning: Expected string token but found \";\"\n")
expectParseError(t, "@charset\"UTF-8\";", "<stdin>: warning: Expected whitespace but found \"\\\"UTF-8\\\"\"\n")
expectParseError(t, "@charset \"UTF-8\"", "<stdin>: warning: Expected \";\" but found end of file\n")
expectParseError(t, "@charset url(UTF-8);", "<stdin>: warning: Expected string token but found \"url(UTF-8)\"\n")
expectParseError(t, "@charset url(\"UTF-8\");", "<stdin>: warning: Expected string token but found \"url(\"\n")
expectParseError(t, "@charset \"UTF-8\" ", "<stdin>: warning: Expected \";\" but found whitespace\n")
expectParseError(t, "@charset \"UTF-8\"{}", "<stdin>: warning: Expected \";\" but found \"{\"\n")
}
func TestAtNamespace(t *testing.T) {
expectPrinted(t, "@namespace\"http://www.com\";", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace \"http://www.com\";", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace \"http://www.com\" ;", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace url();", "@namespace \"\";\n")
expectPrinted(t, "@namespace url(http://www.com);", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace url(http://www.com) ;", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace url(\"http://www.com\");", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace url(\"http://www.com\") ;", "@namespace \"http://www.com\";\n")
expectPrinted(t, "@namespace ns\"http://www.com\";", "@namespace ns \"http://www.com\";\n")
expectPrinted(t, "@namespace ns \"http://www.com\";", "@namespace ns \"http://www.com\";\n")
expectPrinted(t, "@namespace ns \"http://www.com\" ;", "@namespace ns \"http://www.com\";\n")
expectPrinted(t, "@namespace ns url();", "@namespace ns \"\";\n")
expectPrinted(t, "@namespace ns url(http://www.com);", "@namespace ns \"http://www.com\";\n")
expectPrinted(t, "@namespace ns url(http://www.com) ;", "@namespace ns \"http://www.com\";\n")
expectPrinted(t, "@namespace ns url(\"http://www.com\");", "@namespace ns \"http://www.com\";\n")
expectPrinted(t, "@namespace ns url(\"http://www.com\") ;", "@namespace ns \"http://www.com\";\n")
expectParseError(t, "@namespace;", "<stdin>: warning: Expected URL token but found \";\"\n")
expectParseError(t, "@namespace \"http://www.com\"", "<stdin>: warning: Expected \";\" but found end of file\n")
expectParseError(t, "@namespace url(\"http://www.com\";", "<stdin>: warning: Expected \")\" but found \";\"\n")
expectParseError(t, "@namespace noturl(\"http://www.com\");", "<stdin>: warning: Expected URL token but found \"noturl(\"\n")
expectParseError(t, "@namespace url(", `<stdin>: warning: Expected URL token but found bad URL token
<stdin>: error: Expected ")" to end URL token
<stdin>: warning: Expected ";" but found end of file
`)
expectParseError(t, "@namespace ns;", "<stdin>: warning: Expected URL token but found \";\"\n")
expectParseError(t, "@namespace ns \"http://www.com\"", "<stdin>: warning: Expected \";\" but found end of file\n")
expectParseError(t, "@namespace ns url(\"http://www.com\";", "<stdin>: warning: Expected \")\" but found \";\"\n")
expectParseError(t, "@namespace ns noturl(\"http://www.com\");", "<stdin>: warning: Expected URL token but found \"noturl(\"\n")
expectParseError(t, "@namespace ns url(", `<stdin>: warning: Expected URL token but found bad URL token
<stdin>: error: Expected ")" to end URL token
<stdin>: warning: Expected ";" but found end of file
`)
expectParseError(t, "@namespace \"http://www.com\" {}", `<stdin>: warning: Expected ";"
<stdin>: warning: Unexpected "{"
`)
}
func TestAtImport(t *testing.T) {
expectPrinted(t, "@import\"foo.css\";", "@import \"foo.css\";\n")
expectPrinted(t, "@import \"foo.css\";", "@import \"foo.css\";\n")
expectPrinted(t, "@import \"foo.css\" ;", "@import \"foo.css\";\n")
expectPrinted(t, "@import url();", "@import \"\";\n")
expectPrinted(t, "@import url(foo.css);", "@import \"foo.css\";\n")
expectPrinted(t, "@import url(foo.css) ;", "@import \"foo.css\";\n")
expectPrinted(t, "@import url(\"foo.css\");", "@import \"foo.css\";\n")
expectPrinted(t, "@import url(\"foo.css\") ;", "@import \"foo.css\";\n")
expectParseError(t, "@import;", "<stdin>: warning: Expected URL token but found \";\"\n")
expectParseError(t, "@import ;", "<stdin>: warning: Expected URL token but found \";\"\n")
expectParseError(t, "@import \"foo.css\"", "<stdin>: warning: Expected \";\" but found end of file\n")
expectParseError(t, "@import url(\"foo.css\";", "<stdin>: warning: Expected \")\" but found \";\"\n")
expectParseError(t, "@import noturl(\"foo.css\");", "<stdin>: warning: Expected URL token but found \"noturl(\"\n")
expectParseError(t, "@import url(", `<stdin>: warning: Expected URL token but found bad URL token
<stdin>: error: Expected ")" to end URL token
<stdin>: warning: Expected ";" but found end of file
`)
expectParseError(t, "@import \"foo.css\" {}", `<stdin>: warning: Expected ";"
<stdin>: warning: Unexpected "{"
`)
}
func TestAtKeyframes(t *testing.T) {
expectPrinted(t, "@keyframes name{}", "@keyframes name {\n}\n")
expectPrinted(t, "@keyframes name {}", "@keyframes name {\n}\n")
expectPrinted(t, "@keyframes name{0%,50%{color:red}25%,75%{color:blue}}",
"@keyframes name {\n 0%, 50% {\n color: red;\n }\n 25%, 75% {\n color: blue;\n }\n}\n")
expectPrinted(t, "@keyframes name { 0%, 50% { color: red } 25%, 75% { color: blue } }",
"@keyframes name {\n 0%, 50% {\n color: red;\n }\n 25%, 75% {\n color: blue;\n }\n}\n")
expectPrinted(t, "@keyframes name{from{color:red}to{color:blue}}",
"@keyframes name {\n from {\n color: red;\n }\n to {\n color: blue;\n }\n}\n")
expectPrinted(t, "@keyframes name { from { color: red } to { color: blue } }",
"@keyframes name {\n from {\n color: red;\n }\n to {\n color: blue;\n }\n}\n")
expectPrinted(t, "@keyframes name { from { color: red } }", "@keyframes name {\n from {\n color: red;\n }\n}\n")
expectPrinted(t, "@keyframes name { 100% { color: red } }", "@keyframes name {\n 100% {\n color: red;\n }\n}\n")
expectPrintedMangle(t, "@keyframes name { from { color: red } }", "@keyframes name {\n 0% {\n color: red;\n }\n}\n")
expectPrintedMangle(t, "@keyframes name { 100% { color: red } }", "@keyframes name {\n to {\n color: red;\n }\n}\n")
expectPrinted(t, "@-webkit-keyframes name {}", "@-webkit-keyframes name {\n}\n")
expectPrinted(t, "@-moz-keyframes name {}", "@-moz-keyframes name {\n}\n")
expectPrinted(t, "@-ms-keyframes name {}", "@-ms-keyframes name {\n}\n")
expectPrinted(t, "@-o-keyframes name {}", "@-o-keyframes name {\n}\n")
expectParseError(t, "@keyframes {}", "<stdin>: warning: Expected identifier but found \"{\"\n")
expectParseError(t, "@keyframes 'name' {}", "<stdin>: warning: Expected identifier but found \"'name'\"\n")
expectParseError(t, "@keyframes name { 0% 100% {} }", "<stdin>: warning: Expected \",\" but found \"100%\"\n")
expectParseError(t, "@keyframes name { {} 0% {} }", "<stdin>: warning: Expected percentage but found \"{\"\n")
expectParseError(t, "@keyframes name { 100 {} }", "<stdin>: warning: Expected percentage but found \"100\"\n")
expectParseError(t, "@keyframes name { into {} }", "<stdin>: warning: Expected percentage but found \"into\"\n")
expectParseError(t, "@keyframes name { 1,2 {} }", "<stdin>: warning: Expected percentage but found \"1\"\n<stdin>: warning: Expected percentage but found \"2\"\n")
expectParseError(t, "@keyframes name { 1, 2 {} }", "<stdin>: warning: Expected percentage but found \"1\"\n<stdin>: warning: Expected percentage but found \"2\"\n")
expectParseError(t, "@keyframes name { 1 ,2 {} }", "<stdin>: warning: Expected percentage but found \"1\"\n<stdin>: warning: Expected percentage but found \"2\"\n")
expectParseError(t, "@keyframes name { 1%,,2% {} }", "<stdin>: warning: Expected percentage but found \",\"\n")
}