github.com/evanw/esbuild@v0.21.4/internal/css_printer/css_printer_test.go (about)

     1  package css_printer
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/evanw/esbuild/internal/ast"
     7  	"github.com/evanw/esbuild/internal/config"
     8  	"github.com/evanw/esbuild/internal/css_parser"
     9  	"github.com/evanw/esbuild/internal/logger"
    10  	"github.com/evanw/esbuild/internal/test"
    11  )
    12  
    13  func expectPrintedCommon(t *testing.T, name string, contents string, expected string, options Options) {
    14  	t.Helper()
    15  	t.Run(name, func(t *testing.T) {
    16  		t.Helper()
    17  		log := logger.NewDeferLog(logger.DeferLogNoVerboseOrDebug, nil)
    18  		tree := css_parser.Parse(log, test.SourceForTest(contents), css_parser.OptionsFromConfig(config.LoaderCSS, &config.Options{
    19  			MinifyWhitespace: options.MinifyWhitespace,
    20  		}))
    21  		msgs := log.Done()
    22  		text := ""
    23  		for _, msg := range msgs {
    24  			if msg.Kind == logger.Error {
    25  				text += msg.String(logger.OutputOptions{}, logger.TerminalInfo{})
    26  			}
    27  		}
    28  		test.AssertEqualWithDiff(t, text, "")
    29  		symbols := ast.NewSymbolMap(1)
    30  		symbols.SymbolsForSource[0] = tree.Symbols
    31  		result := Print(tree, symbols, options)
    32  		test.AssertEqualWithDiff(t, string(result.CSS), expected)
    33  	})
    34  }
    35  
    36  func expectPrinted(t *testing.T, contents string, expected string) {
    37  	t.Helper()
    38  	expectPrintedCommon(t, contents, contents, expected, Options{})
    39  }
    40  
    41  func expectPrintedMinify(t *testing.T, contents string, expected string) {
    42  	t.Helper()
    43  	expectPrintedCommon(t, contents+" [minified]", contents, expected, Options{
    44  		MinifyWhitespace: true,
    45  	})
    46  }
    47  
    48  func expectPrintedASCII(t *testing.T, contents string, expected string) {
    49  	t.Helper()
    50  	expectPrintedCommon(t, contents+" [ascii]", contents, expected, Options{
    51  		ASCIIOnly: true,
    52  	})
    53  }
    54  
    55  func expectPrintedString(t *testing.T, stringValue string, expected string) {
    56  	t.Helper()
    57  	t.Run(stringValue, func(t *testing.T) {
    58  		t.Helper()
    59  		p := printer{}
    60  		p.printQuoted(stringValue, 0)
    61  		test.AssertEqualWithDiff(t, string(p.css), expected)
    62  	})
    63  }
    64  
    65  func TestStringQuote(t *testing.T) {
    66  	expectPrintedString(t, "", "\"\"")
    67  	expectPrintedString(t, "foo", "\"foo\"")
    68  	expectPrintedString(t, "f\"o", "'f\"o'")
    69  	expectPrintedString(t, "f'\"'o", "\"f'\\\"'o\"")
    70  	expectPrintedString(t, "f\"'\"o", "'f\"\\'\"o'")
    71  	expectPrintedString(t, "f\\o", "\"f\\\\o\"")
    72  	expectPrintedString(t, "f\ro", "\"f\\do\"")
    73  	expectPrintedString(t, "f\no", "\"f\\ao\"")
    74  	expectPrintedString(t, "f\fo", "\"f\\co\"")
    75  	expectPrintedString(t, "f\r\no", "\"f\\d\\ao\"")
    76  	expectPrintedString(t, "f\r0", "\"f\\d 0\"")
    77  	expectPrintedString(t, "f\n0", "\"f\\a 0\"")
    78  	expectPrintedString(t, "f\n ", "\"f\\a  \"")
    79  	expectPrintedString(t, "f\n\t", "\"f\\a \t\"")
    80  	expectPrintedString(t, "f\nf", "\"f\\a f\"")
    81  	expectPrintedString(t, "f\nF", "\"f\\a F\"")
    82  	expectPrintedString(t, "f\ng", "\"f\\ag\"")
    83  	expectPrintedString(t, "f\nG", "\"f\\aG\"")
    84  	expectPrintedString(t, "f\x01o", "\"f\x01o\"")
    85  	expectPrintedString(t, "f\to", "\"f\to\"")
    86  
    87  	expectPrintedString(t, "</script>", "\"</script>\"")
    88  	expectPrintedString(t, "</style>", "\"<\\/style>\"")
    89  	expectPrintedString(t, "</style", "\"<\\/style\"")
    90  	expectPrintedString(t, "</STYLE", "\"<\\/STYLE\"")
    91  	expectPrintedString(t, "</StYlE", "\"<\\/StYlE\"")
    92  	expectPrintedString(t, ">/style", "\">/style\"")
    93  	expectPrintedString(t, ">/STYLE", "\">/STYLE\"")
    94  	expectPrintedString(t, ">/StYlE", "\">/StYlE\"")
    95  }
    96  
    97  func TestURLQuote(t *testing.T) {
    98  	expectPrinted(t, "* { background: url('foo') }", "* {\n  background: url(foo);\n}\n")
    99  	expectPrinted(t, "* { background: url('f o') }", "* {\n  background: url(f\\ o);\n}\n")
   100  	expectPrinted(t, "* { background: url('f  o') }", "* {\n  background: url(\"f  o\");\n}\n")
   101  	expectPrinted(t, "* { background: url('foo)') }", "* {\n  background: url(foo\\));\n}\n")
   102  	expectPrinted(t, "* { background: url('(foo') }", "* {\n  background: url(\\(foo);\n}\n")
   103  	expectPrinted(t, "* { background: url('(foo)') }", "* {\n  background: url(\"(foo)\");\n}\n")
   104  	expectPrinted(t, "* { background: url('\"foo\"') }", "* {\n  background: url('\"foo\"');\n}\n")
   105  }
   106  
   107  func TestImportant(t *testing.T) {
   108  	expectPrinted(t, "a { b: c!important }", "a {\n  b: c !important;\n}\n")
   109  	expectPrinted(t, "a { b: c!important; }", "a {\n  b: c !important;\n}\n")
   110  	expectPrinted(t, "a { b: c! important }", "a {\n  b: c !important;\n}\n")
   111  	expectPrinted(t, "a { b: c! important; }", "a {\n  b: c !important;\n}\n")
   112  	expectPrinted(t, "a { b: c ! important }", "a {\n  b: c !important;\n}\n")
   113  	expectPrinted(t, "a { b: c ! important; }", "a {\n  b: c !important;\n}\n")
   114  	expectPrinted(t, "a { b: c !IMPORTANT; }", "a {\n  b: c !important;\n}\n")
   115  	expectPrinted(t, "a { b: c !ImPoRtAnT; }", "a {\n  b: c !important;\n}\n")
   116  	expectPrintedMinify(t, "a { b: c !important }", "a{b:c!important}")
   117  }
   118  
   119  func TestSelector(t *testing.T) {
   120  	expectPrintedMinify(t, "a + b c > d ~ e{}", "a+b c>d~e{}")
   121  
   122  	expectPrinted(t, ":unknown( x (a+b), 'c' ) {}", ":unknown(x (a+b), \"c\") {\n}\n")
   123  	expectPrinted(t, ":unknown( x (a-b), 'c' ) {}", ":unknown(x (a-b), \"c\") {\n}\n")
   124  	expectPrinted(t, ":unknown( x (a,b), 'c' ) {}", ":unknown(x (a, b), \"c\") {\n}\n")
   125  	expectPrinted(t, ":unknown( x ( a + b ), 'c' ) {}", ":unknown(x (a + b), \"c\") {\n}\n")
   126  	expectPrinted(t, ":unknown( x ( a - b ), 'c' ) {}", ":unknown(x (a - b), \"c\") {\n}\n")
   127  	expectPrinted(t, ":unknown( x ( a , b ), 'c' ) {}", ":unknown(x (a, b), \"c\") {\n}\n")
   128  
   129  	expectPrintedMinify(t, ":unknown( x (a+b), 'c' ) {}", ":unknown(x (a+b),\"c\"){}")
   130  	expectPrintedMinify(t, ":unknown( x (a-b), 'c' ) {}", ":unknown(x (a-b),\"c\"){}")
   131  	expectPrintedMinify(t, ":unknown( x (a,b), 'c' ) {}", ":unknown(x (a,b),\"c\"){}")
   132  	expectPrintedMinify(t, ":unknown( x ( a + b ), 'c' ) {}", ":unknown(x (a + b),\"c\"){}")
   133  	expectPrintedMinify(t, ":unknown( x ( a - b ), 'c' ) {}", ":unknown(x (a - b),\"c\"){}")
   134  	expectPrintedMinify(t, ":unknown( x ( a , b ), 'c' ) {}", ":unknown(x (a,b),\"c\"){}")
   135  
   136  	// ":foo()" is a parse error, but should ideally still be preserved so they don't accidentally become valid
   137  	expectPrinted(t, ":is {}", ":is {\n}\n")
   138  	expectPrinted(t, ":is() {}", ":is() {\n}\n")
   139  	expectPrinted(t, ":hover {}", ":hover {\n}\n")
   140  	expectPrinted(t, ":hover() {}", ":hover() {\n}\n")
   141  	expectPrintedMinify(t, ":is {}", ":is{}")
   142  	expectPrintedMinify(t, ":is() {}", ":is(){}")
   143  	expectPrintedMinify(t, ":hover {}", ":hover{}")
   144  	expectPrintedMinify(t, ":hover() {}", ":hover(){}")
   145  }
   146  
   147  func TestNestedSelector(t *testing.T) {
   148  	expectPrintedMinify(t, "a { &b {} }", "a{&b{}}")
   149  	expectPrintedMinify(t, "a { & b {} }", "a{& b{}}")
   150  	expectPrintedMinify(t, "a { & :b {} }", "a{& :b{}}")
   151  	expectPrintedMinify(t, "& a & b & c {}", "& a & b & c{}")
   152  }
   153  
   154  func TestBadQualifiedRules(t *testing.T) {
   155  	expectPrinted(t, ";", "; {\n}\n")
   156  	expectPrinted(t, "$bad: rule;", "$bad: rule; {\n}\n")
   157  	expectPrinted(t, "a {}; b {};", "a {\n}\n; b {\n}\n; {\n}\n")
   158  	expectPrinted(t, "a { div.major { color: blue } color: red }", "a {\n  div.major {\n    color: blue;\n  }\n  color: red;\n}\n")
   159  	expectPrinted(t, "a { div:hover { color: blue } color: red }", "a {\n  div:hover {\n    color: blue;\n  }\n  color: red;\n}\n")
   160  	expectPrinted(t, "a { div:hover { color: blue }; color: red }", "a {\n  div:hover {\n    color: blue;\n  }\n  color: red;\n}\n")
   161  
   162  	expectPrinted(t, "$bad{ color: red }", "$bad {\n  color: red;\n}\n")
   163  	expectPrinted(t, "$bad { color: red }", "$bad {\n  color: red;\n}\n")
   164  	expectPrinted(t, "$bad foo{ color: red }", "$bad foo {\n  color: red;\n}\n")
   165  	expectPrinted(t, "$bad foo { color: red }", "$bad foo {\n  color: red;\n}\n")
   166  
   167  	expectPrintedMinify(t, "$bad{ color: red }", "$bad{color:red}")
   168  	expectPrintedMinify(t, "$bad { color: red }", "$bad{color:red}")
   169  	expectPrintedMinify(t, "$bad foo{ color: red }", "$bad foo{color:red}")
   170  	expectPrintedMinify(t, "$bad foo { color: red }", "$bad foo{color:red}")
   171  }
   172  
   173  func TestDeclaration(t *testing.T) {
   174  	expectPrinted(t, "* { unknown: x (a+b) }", "* {\n  unknown: x (a+b);\n}\n")
   175  	expectPrinted(t, "* { unknown: x (a-b) }", "* {\n  unknown: x (a-b);\n}\n")
   176  	expectPrinted(t, "* { unknown: x (a,b) }", "* {\n  unknown: x (a, b);\n}\n")
   177  	expectPrinted(t, "* { unknown: x ( a + b ) }", "* {\n  unknown: x (a + b);\n}\n")
   178  	expectPrinted(t, "* { unknown: x ( a - b ) }", "* {\n  unknown: x (a - b);\n}\n")
   179  	expectPrinted(t, "* { unknown: x ( a , b ) }", "* {\n  unknown: x (a, b);\n}\n")
   180  
   181  	expectPrintedMinify(t, "* { unknown: x (a+b) }", "*{unknown:x (a+b)}")
   182  	expectPrintedMinify(t, "* { unknown: x (a-b) }", "*{unknown:x (a-b)}")
   183  	expectPrintedMinify(t, "* { unknown: x (a,b) }", "*{unknown:x (a,b)}")
   184  	expectPrintedMinify(t, "* { unknown: x ( a + b ) }", "*{unknown:x (a + b)}")
   185  	expectPrintedMinify(t, "* { unknown: x ( a - b ) }", "*{unknown:x (a - b)}")
   186  	expectPrintedMinify(t, "* { unknown: x ( a , b ) }", "*{unknown:x (a,b)}")
   187  
   188  	// Pretty-print long lists in declarations
   189  	expectPrinted(t, "a { b: c, d }", "a {\n  b: c, d;\n}\n")
   190  	expectPrinted(t, "a { b: c, (d, e) }", "a {\n  b: c, (d, e);\n}\n")
   191  	expectPrinted(t, "a { b: c, d, e }", "a {\n  b:\n    c,\n    d,\n    e;\n}\n")
   192  	expectPrinted(t, "a { b: c, (d, e), f }", "a {\n  b:\n    c,\n    (d, e),\n    f;\n}\n")
   193  
   194  	expectPrintedMinify(t, "a { b: c, d }", "a{b:c,d}")
   195  	expectPrintedMinify(t, "a { b: c, (d, e) }", "a{b:c,(d,e)}")
   196  	expectPrintedMinify(t, "a { b: c, d, e }", "a{b:c,d,e}")
   197  	expectPrintedMinify(t, "a { b: c, (d, e), f }", "a{b:c,(d,e),f}")
   198  }
   199  
   200  func TestVerbatimWhitespace(t *testing.T) {
   201  	expectPrinted(t, "*{--x:}", "* {\n  --x:;\n}\n")
   202  	expectPrinted(t, "*{--x: }", "* {\n  --x: ;\n}\n")
   203  	expectPrinted(t, "* { --x:; }", "* {\n  --x:;\n}\n")
   204  	expectPrinted(t, "* { --x: ; }", "* {\n  --x: ;\n}\n")
   205  
   206  	expectPrintedMinify(t, "*{--x:}", "*{--x:}")
   207  	expectPrintedMinify(t, "*{--x: }", "*{--x: }")
   208  	expectPrintedMinify(t, "* { --x:; }", "*{--x:}")
   209  	expectPrintedMinify(t, "* { --x: ; }", "*{--x: }")
   210  
   211  	expectPrinted(t, "*{--x:!important}", "* {\n  --x:!important;\n}\n")
   212  	expectPrinted(t, "*{--x: !important}", "* {\n  --x: !important;\n}\n")
   213  	expectPrinted(t, "*{ --x:!important }", "* {\n  --x:!important;\n}\n")
   214  	expectPrinted(t, "*{ --x: !important }", "* {\n  --x: !important;\n}\n")
   215  	expectPrinted(t, "* { --x:!important; }", "* {\n  --x:!important;\n}\n")
   216  	expectPrinted(t, "* { --x: !important; }", "* {\n  --x: !important;\n}\n")
   217  	expectPrinted(t, "* { --x:! important ; }", "* {\n  --x:!important;\n}\n")
   218  	expectPrinted(t, "* { --x: ! important ; }", "* {\n  --x: !important;\n}\n")
   219  
   220  	expectPrintedMinify(t, "*{--x:!important}", "*{--x:!important}")
   221  	expectPrintedMinify(t, "*{--x: !important}", "*{--x: !important}")
   222  	expectPrintedMinify(t, "*{ --x:!important }", "*{--x:!important}")
   223  	expectPrintedMinify(t, "*{ --x: !important }", "*{--x: !important}")
   224  	expectPrintedMinify(t, "* { --x:!important; }", "*{--x:!important}")
   225  	expectPrintedMinify(t, "* { --x: !important; }", "*{--x: !important}")
   226  	expectPrintedMinify(t, "* { --x:! important ; }", "*{--x:!important}")
   227  	expectPrintedMinify(t, "* { --x: ! important ; }", "*{--x: !important}")
   228  
   229  	expectPrinted(t, "* { --x:y; }", "* {\n  --x:y;\n}\n")
   230  	expectPrinted(t, "* { --x: y; }", "* {\n  --x: y;\n}\n")
   231  	expectPrinted(t, "* { --x:y ; }", "* {\n  --x:y ;\n}\n")
   232  	expectPrinted(t, "* { --x:y, ; }", "* {\n  --x:y, ;\n}\n")
   233  	expectPrinted(t, "* { --x: var(y,); }", "* {\n  --x: var(y,);\n}\n")
   234  	expectPrinted(t, "* { --x: var(y, ); }", "* {\n  --x: var(y, );\n}\n")
   235  
   236  	expectPrintedMinify(t, "* { --x:y; }", "*{--x:y}")
   237  	expectPrintedMinify(t, "* { --x: y; }", "*{--x: y}")
   238  	expectPrintedMinify(t, "* { --x:y ; }", "*{--x:y }")
   239  	expectPrintedMinify(t, "* { --x:y, ; }", "*{--x:y, }")
   240  	expectPrintedMinify(t, "* { --x: var(y,); }", "*{--x: var(y,)}")
   241  	expectPrintedMinify(t, "* { --x: var(y, ); }", "*{--x: var(y, )}")
   242  
   243  	expectPrinted(t, "* { --x:(y); }", "* {\n  --x:(y);\n}\n")
   244  	expectPrinted(t, "* { --x:(y) ; }", "* {\n  --x:(y) ;\n}\n")
   245  	expectPrinted(t, "* { --x: (y); }", "* {\n  --x: (y);\n}\n")
   246  	expectPrinted(t, "* { --x:(y ); }", "* {\n  --x:(y );\n}\n")
   247  	expectPrinted(t, "* { --x:( y); }", "* {\n  --x:( y);\n}\n")
   248  
   249  	expectPrintedMinify(t, "* { --x:(y); }", "*{--x:(y)}")
   250  	expectPrintedMinify(t, "* { --x:(y) ; }", "*{--x:(y) }")
   251  	expectPrintedMinify(t, "* { --x: (y); }", "*{--x: (y)}")
   252  	expectPrintedMinify(t, "* { --x:(y ); }", "*{--x:(y )}")
   253  	expectPrintedMinify(t, "* { --x:( y); }", "*{--x:( y)}")
   254  
   255  	expectPrinted(t, "* { --x:f(y); }", "* {\n  --x:f(y);\n}\n")
   256  	expectPrinted(t, "* { --x:f(y) ; }", "* {\n  --x:f(y) ;\n}\n")
   257  	expectPrinted(t, "* { --x: f(y); }", "* {\n  --x: f(y);\n}\n")
   258  	expectPrinted(t, "* { --x:f(y ); }", "* {\n  --x:f(y );\n}\n")
   259  	expectPrinted(t, "* { --x:f( y); }", "* {\n  --x:f( y);\n}\n")
   260  
   261  	expectPrintedMinify(t, "* { --x:f(y); }", "*{--x:f(y)}")
   262  	expectPrintedMinify(t, "* { --x:f(y) ; }", "*{--x:f(y) }")
   263  	expectPrintedMinify(t, "* { --x: f(y); }", "*{--x: f(y)}")
   264  	expectPrintedMinify(t, "* { --x:f(y ); }", "*{--x:f(y )}")
   265  	expectPrintedMinify(t, "* { --x:f( y); }", "*{--x:f( y)}")
   266  
   267  	expectPrinted(t, "* { --x:[y]; }", "* {\n  --x:[y];\n}\n")
   268  	expectPrinted(t, "* { --x:[y] ; }", "* {\n  --x:[y] ;\n}\n")
   269  	expectPrinted(t, "* { --x: [y]; }", "* {\n  --x: [y];\n}\n")
   270  	expectPrinted(t, "* { --x:[y ]; }", "* {\n  --x:[y ];\n}\n")
   271  	expectPrinted(t, "* { --x:[ y]; }", "* {\n  --x:[ y];\n}\n")
   272  
   273  	expectPrintedMinify(t, "* { --x:[y]; }", "*{--x:[y]}")
   274  	expectPrintedMinify(t, "* { --x:[y] ; }", "*{--x:[y] }")
   275  	expectPrintedMinify(t, "* { --x: [y]; }", "*{--x: [y]}")
   276  	expectPrintedMinify(t, "* { --x:[y ]; }", "*{--x:[y ]}")
   277  	expectPrintedMinify(t, "* { --x:[ y]; }", "*{--x:[ y]}")
   278  
   279  	// Note: These cases now behave like qualified rules
   280  	expectPrinted(t, "* { --x:{y}; }", "* {\n  --x: {\n    y;\n  }\n}\n")
   281  	expectPrinted(t, "* { --x:{y} ; }", "* {\n  --x: {\n    y;\n  }\n}\n")
   282  	expectPrinted(t, "* { --x: {y}; }", "* {\n  --x: {\n    y;\n  }\n}\n")
   283  	expectPrinted(t, "* { --x:{y }; }", "* {\n  --x: {\n    y;\n  }\n}\n")
   284  	expectPrinted(t, "* { --x:{ y}; }", "* {\n  --x: {\n    y;\n  }\n}\n")
   285  
   286  	// Note: These cases now behave like qualified rules
   287  	expectPrintedMinify(t, "* { --x:{y}; }", "*{--x:{y}}")
   288  	expectPrintedMinify(t, "* { --x:{y} ; }", "*{--x:{y}}")
   289  	expectPrintedMinify(t, "* { --x: {y}; }", "*{--x:{y}}")
   290  	expectPrintedMinify(t, "* { --x:{y }; }", "*{--x:{y}}")
   291  	expectPrintedMinify(t, "* { --x:{ y}; }", "*{--x:{y}}")
   292  
   293  	expectPrintedMinify(t, "@supports ( --x : y , z ) { a { color: red; } }", "@supports ( --x : y , z ){a{color:red}}")
   294  	expectPrintedMinify(t, "@supports ( --x : ) { a { color: red; } }", "@supports ( --x : ){a{color:red}}")
   295  	expectPrintedMinify(t, "@supports (--x: ) { a { color: red; } }", "@supports (--x: ){a{color:red}}")
   296  	expectPrintedMinify(t, "@supports ( --x y , z ) { a { color: red; } }", "@supports (--x y,z){a{color:red}}")
   297  	expectPrintedMinify(t, "@supports ( --x ) { a { color: red; } }", "@supports (--x){a{color:red}}")
   298  	expectPrintedMinify(t, "@supports ( ) { a { color: red; } }", "@supports (){a{color:red}}")
   299  	expectPrintedMinify(t, "@supports ( . --x : y , z ) { a { color: red; } }", "@supports (. --x : y,z){a{color:red}}")
   300  }
   301  
   302  func TestAtRule(t *testing.T) {
   303  	expectPrintedMinify(t, "@unknown;", "@unknown;")
   304  	expectPrintedMinify(t, "@unknown x;", "@unknown x;")
   305  	expectPrintedMinify(t, "@unknown{}", "@unknown{}")
   306  	expectPrintedMinify(t, "@unknown{\na: b;\nc: d;\n}", "@unknown{a: b; c: d;}")
   307  
   308  	expectPrinted(t, "@unknown x{}", "@unknown x {}\n")
   309  	expectPrinted(t, "@unknown x {}", "@unknown x {}\n")
   310  	expectPrintedMinify(t, "@unknown x{}", "@unknown x{}")
   311  	expectPrintedMinify(t, "@unknown x {}", "@unknown x{}")
   312  
   313  	expectPrinted(t, "@unknown x ( a + b ) ;", "@unknown x (a + b);\n")
   314  	expectPrinted(t, "@unknown x ( a - b ) ;", "@unknown x (a - b);\n")
   315  	expectPrinted(t, "@unknown x ( a , b ) ;", "@unknown x (a, b);\n")
   316  	expectPrintedMinify(t, "@unknown x ( a + b ) ;", "@unknown x (a + b);")
   317  	expectPrintedMinify(t, "@unknown x ( a - b ) ;", "@unknown x (a - b);")
   318  	expectPrintedMinify(t, "@unknown x ( a , b ) ;", "@unknown x (a,b);")
   319  }
   320  
   321  func TestAtCharset(t *testing.T) {
   322  	expectPrinted(t, "@charset \"UTF-8\";", "@charset \"UTF-8\";\n")
   323  	expectPrintedMinify(t, "@charset \"UTF-8\";", "@charset \"UTF-8\";")
   324  }
   325  
   326  func TestAtImport(t *testing.T) {
   327  	expectPrinted(t, "@import\"foo.css\";", "@import \"foo.css\";\n")
   328  	expectPrinted(t, "@import \"foo.css\";", "@import \"foo.css\";\n")
   329  	expectPrinted(t, "@import url(foo.css);", "@import \"foo.css\";\n")
   330  	expectPrinted(t, "@import url(\"foo.css\");", "@import \"foo.css\";\n")
   331  	expectPrinted(t, "@import url(\"foo.css\") print;", "@import \"foo.css\" print;\n")
   332  
   333  	expectPrintedMinify(t, "@import\"foo.css\";", "@import\"foo.css\";")
   334  	expectPrintedMinify(t, "@import \"foo.css\";", "@import\"foo.css\";")
   335  	expectPrintedMinify(t, "@import url(foo.css);", "@import\"foo.css\";")
   336  	expectPrintedMinify(t, "@import url(\"foo.css\");", "@import\"foo.css\";")
   337  	expectPrintedMinify(t, "@import url(\"foo.css\") print;", "@import\"foo.css\"print;")
   338  }
   339  
   340  func TestAtKeyframes(t *testing.T) {
   341  	expectPrintedMinify(t, "@keyframes name { 0%, 50% { color: red } 25%, 75% { color: blue } }",
   342  		"@keyframes name{0%,50%{color:red}25%,75%{color:blue}}")
   343  	expectPrintedMinify(t, "@keyframes name { from { color: red } to { color: blue } }",
   344  		"@keyframes name{from{color:red}to{color:blue}}")
   345  }
   346  
   347  func TestAtMedia(t *testing.T) {
   348  	expectPrinted(t, "@media screen { div { color: red } }", "@media screen {\n  div {\n    color: red;\n  }\n}\n")
   349  	expectPrinted(t, "@media screen{div{color:red}}", "@media screen {\n  div {\n    color: red;\n  }\n}\n")
   350  	expectPrintedMinify(t, "@media screen { div { color: red } }", "@media screen{div{color:red}}")
   351  	expectPrintedMinify(t, "@media screen{div{color:red}}", "@media screen{div{color:red}}")
   352  }
   353  
   354  func TestAtFontFace(t *testing.T) {
   355  	expectPrinted(t, "@font-face { font-family: 'Open Sans'; src: url('OpenSans.woff') format('woff') }",
   356  		"@font-face {\n  font-family: \"Open Sans\";\n  src: url(OpenSans.woff) format(\"woff\");\n}\n")
   357  	expectPrintedMinify(t, "@font-face { font-family: 'Open Sans'; src: url('OpenSans.woff') format('woff') }",
   358  		"@font-face{font-family:\"Open Sans\";src:url(OpenSans.woff) format(\"woff\")}")
   359  }
   360  
   361  func TestAtPage(t *testing.T) {
   362  	expectPrinted(t, "@page { margin: 1cm }", "@page {\n  margin: 1cm;\n}\n")
   363  	expectPrinted(t, "@page :first { margin: 1cm }", "@page :first {\n  margin: 1cm;\n}\n")
   364  	expectPrintedMinify(t, "@page { margin: 1cm }", "@page{margin:1cm}")
   365  	expectPrintedMinify(t, "@page :first { margin: 1cm }", "@page :first{margin:1cm}")
   366  }
   367  
   368  func TestMsGridColumnsWhitespace(t *testing.T) {
   369  	// Must not insert a space between the "]" and the "("
   370  	expectPrinted(t, "div { -ms-grid-columns: (1fr)[3] }", "div {\n  -ms-grid-columns: (1fr)[3];\n}\n")
   371  	expectPrinted(t, "div { -ms-grid-columns: 1fr (20px 1fr)[3] }", "div {\n  -ms-grid-columns: 1fr (20px 1fr)[3];\n}\n")
   372  	expectPrintedMinify(t, "div { -ms-grid-columns: (1fr)[3] }", "div{-ms-grid-columns:(1fr)[3]}")
   373  	expectPrintedMinify(t, "div { -ms-grid-columns: 1fr (20px 1fr)[3] }", "div{-ms-grid-columns:1fr (20px 1fr)[3]}")
   374  }
   375  
   376  func TestASCII(t *testing.T) {
   377  	expectPrintedASCII(t, "* { background: url(🐈) }", "* {\n  background: url(\\1f408);\n}\n")
   378  	expectPrintedASCII(t, "* { background: url(🐈6) }", "* {\n  background: url(\\1f408 6);\n}\n")
   379  	expectPrintedASCII(t, "* { background: url('🐈') }", "* {\n  background: url(\\1f408);\n}\n")
   380  	expectPrintedASCII(t, "* { background: url('🐈6') }", "* {\n  background: url(\\1f408 6);\n}\n")
   381  	expectPrintedASCII(t, "* { background: url('(🐈)') }", "* {\n  background: url(\"(\\1f408)\");\n}\n")
   382  	expectPrintedASCII(t, "* { background: url('(🐈6)') }", "* {\n  background: url(\"(\\1f408 6)\");\n}\n")
   383  
   384  	expectPrintedASCII(t, "div { 🐈: 🐈('🐈') }", "div {\n  \\1f408: \\1f408(\"\\1f408\");\n}\n")
   385  	expectPrintedASCII(t, "div { 🐈 : 🐈 ('🐈 ') }", "div {\n  \\1f408: \\1f408  (\"\\1f408  \");\n}\n")
   386  	expectPrintedASCII(t, "div { 🐈6: 🐈6('🐈6') }", "div {\n  \\1f408 6: \\1f408 6(\"\\1f408 6\");\n}\n")
   387  
   388  	expectPrintedASCII(t, "@🐈;", "@\\1f408;\n")
   389  	expectPrintedASCII(t, "@🐈 {}", "@\\1f408 {}\n")
   390  	expectPrintedASCII(t, "@🐈 x {}", "@\\1f408  x {}\n")
   391  
   392  	expectPrintedASCII(t, "#🐈#x {}", "#\\1f408#x {\n}\n")
   393  	expectPrintedASCII(t, "#🐈 #x {}", "#\\1f408  #x {\n}\n")
   394  	expectPrintedASCII(t, "#🐈::x {}", "#\\1f408::x {\n}\n")
   395  	expectPrintedASCII(t, "#🐈 ::x {}", "#\\1f408  ::x {\n}\n")
   396  
   397  	expectPrintedASCII(t, ".🐈.x {}", ".\\1f408.x {\n}\n")
   398  	expectPrintedASCII(t, ".🐈 .x {}", ".\\1f408  .x {\n}\n")
   399  	expectPrintedASCII(t, ".🐈::x {}", ".\\1f408::x {\n}\n")
   400  	expectPrintedASCII(t, ".🐈 ::x {}", ".\\1f408  ::x {\n}\n")
   401  
   402  	expectPrintedASCII(t, "🐈|🐈.x {}", "\\1f408|\\1f408.x {\n}\n")
   403  	expectPrintedASCII(t, "🐈|🐈 .x {}", "\\1f408|\\1f408  .x {\n}\n")
   404  	expectPrintedASCII(t, "🐈|🐈::x {}", "\\1f408|\\1f408::x {\n}\n")
   405  	expectPrintedASCII(t, "🐈|🐈 ::x {}", "\\1f408|\\1f408  ::x {\n}\n")
   406  
   407  	expectPrintedASCII(t, "::🐈:x {}", "::\\1f408:x {\n}\n")
   408  	expectPrintedASCII(t, "::🐈 :x {}", "::\\1f408  :x {\n}\n")
   409  
   410  	expectPrintedASCII(t, "[🐈] {}", "[\\1f408] {\n}\n")
   411  	expectPrintedASCII(t, "[🐈=🐈] {}", "[\\1f408=\\1f408] {\n}\n")
   412  	expectPrintedASCII(t, "[🐈|🐈=🐈] {}", "[\\1f408|\\1f408=\\1f408] {\n}\n")
   413  
   414  	// A space must be consumed after an escaped code point even with six digits
   415  	expectPrintedASCII(t, ".\\10FFF abc:after { content: '\\10FFF abc' }", ".\\10fff abc:after {\n  content: \"\\10fff abc\";\n}\n")
   416  	expectPrintedASCII(t, ".\U00010FFFabc:after { content: '\U00010FFFabc' }", ".\\10fff abc:after {\n  content: \"\\10fff abc\";\n}\n")
   417  	expectPrintedASCII(t, ".\\10FFFFabc:after { content: '\\10FFFFabc' }", ".\\10ffffabc:after {\n  content: \"\\10ffffabc\";\n}\n")
   418  	expectPrintedASCII(t, ".\\10FFFF abc:after { content: '\\10FFFF abc' }", ".\\10ffffabc:after {\n  content: \"\\10ffffabc\";\n}\n")
   419  	expectPrintedASCII(t, ".\U0010FFFFabc:after { content: '\U0010FFFFabc' }", ".\\10ffffabc:after {\n  content: \"\\10ffffabc\";\n}\n")
   420  
   421  	// This character should always be escaped
   422  	expectPrinted(t, ".\\FEFF:after { content: '\uFEFF' }", ".\\feff:after {\n  content: \"\\feff\";\n}\n")
   423  }