beautify-css-tests.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*global js_beautify: true */
  2. function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_beautify)
  3. {
  4. var opts = {
  5. indent_size: 4,
  6. indent_char: ' ',
  7. preserve_newlines: true,
  8. jslint_happy: false,
  9. keep_array_indentation: false,
  10. brace_style: 'collapse',
  11. space_before_conditional: true,
  12. break_chained_methods: false,
  13. selector_separator: '\n',
  14. end_with_newline: false,
  15. newline_between_rules: true
  16. };
  17. function test_css_beautifier(input)
  18. {
  19. return css_beautify(input, opts);
  20. }
  21. var sanitytest;
  22. // test the input on beautifier with the current flag settings
  23. // does not check the indentation / surroundings as bt() does
  24. function test_fragment(input, expected)
  25. {
  26. expected = expected || expected === '' ? expected : input;
  27. sanitytest.expect(input, expected);
  28. // if the expected is different from input, run it again
  29. // expected output should be unchanged when run twice.
  30. if (expected !== input) {
  31. sanitytest.expect(expected, expected);
  32. }
  33. // Everywhere we do newlines, they should be replaced with opts.eol
  34. opts.eol = '\r\\n';
  35. expected = expected.replace(/[\n]/g, '\r\n');
  36. sanitytest.expect(input, expected);
  37. input = input.replace(/[\n]/g, '\r\n');
  38. sanitytest.expect(input, expected);
  39. opts.eol = '\n';
  40. }
  41. // test css
  42. function t(input, expectation)
  43. {
  44. var wrapped_input, wrapped_expectation;
  45. expectation = expectation || expectation === '' ? expectation : input;
  46. sanitytest.test_function(test_css_beautifier, 'css_beautify');
  47. test_fragment(input, expectation);
  48. }
  49. function unicode_char(value) {
  50. return String.fromCharCode(value)
  51. }
  52. function beautifier_tests()
  53. {
  54. sanitytest = test_obj;
  55. t(".tabs {}");
  56. opts.indent_size = 1;
  57. opts.indent_char = '\t';
  58. opts.selector_separator_newline = true;
  59. opts.end_with_newline = false;
  60. opts.newline_between_rules = false;
  61. // End With Newline - (eof = "\n")
  62. opts.end_with_newline = true;
  63. test_fragment('', '\n');
  64. test_fragment(' .tabs{}', ' .tabs {}\n');
  65. test_fragment(' \n\n.tabs{}\n\n\n\n', ' .tabs {}\n');
  66. test_fragment('\n');
  67. // End With Newline - (eof = "")
  68. opts.end_with_newline = false;
  69. test_fragment('');
  70. test_fragment(' .tabs{}', ' .tabs {}');
  71. test_fragment(' \n\n.tabs{}\n\n\n\n', ' .tabs {}');
  72. test_fragment('\n', '');
  73. // Empty braces
  74. t('.tabs{}', '.tabs {}');
  75. t('.tabs { }', '.tabs {}');
  76. t('.tabs { }', '.tabs {}');
  77. t('.tabs \n{\n \n }', '.tabs {}');
  78. //
  79. t('#cboxOverlay {\n\tbackground: url(images/overlay.png) repeat 0 0;\n\topacity: 0.9;\n\tfilter: alpha(opacity = 90);\n}', '#cboxOverlay {\n\tbackground: url(images/overlay.png) repeat 0 0;\n\topacity: 0.9;\n\tfilter: alpha(opacity=90);\n}');
  80. // Selector Separator - (separator = " ", separator1 = " ")
  81. opts.selector_separator_newline = false;
  82. opts.selector_separator = " ";
  83. t('#bla, #foo{color:green}', '#bla, #foo {\n\tcolor: green\n}');
  84. t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
  85. t('@media print {.tab,.bat{}}', '@media print {\n\t.tab, .bat {}\n}');
  86. t('#bla, #foo{color:black}', '#bla, #foo {\n\tcolor: black\n}');
  87. t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child, a:first-child {\n\tcolor: red;\n\tdiv:first-child, div:hover {\n\t\tcolor: black;\n\t}\n}');
  88. // Selector Separator - (separator = " ", separator1 = " ")
  89. opts.selector_separator_newline = false;
  90. opts.selector_separator = " ";
  91. t('#bla, #foo{color:green}', '#bla, #foo {\n\tcolor: green\n}');
  92. t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
  93. t('@media print {.tab,.bat{}}', '@media print {\n\t.tab, .bat {}\n}');
  94. t('#bla, #foo{color:black}', '#bla, #foo {\n\tcolor: black\n}');
  95. t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child, a:first-child {\n\tcolor: red;\n\tdiv:first-child, div:hover {\n\t\tcolor: black;\n\t}\n}');
  96. // Selector Separator - (separator = "\n", separator1 = "\n\t")
  97. opts.selector_separator_newline = true;
  98. opts.selector_separator = " ";
  99. t('#bla, #foo{color:green}', '#bla,\n#foo {\n\tcolor: green\n}');
  100. t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
  101. t('@media print {.tab,.bat{}}', '@media print {\n\t.tab,\n\t.bat {}\n}');
  102. t('#bla, #foo{color:black}', '#bla,\n#foo {\n\tcolor: black\n}');
  103. t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child,\na:first-child {\n\tcolor: red;\n\tdiv:first-child,\n\tdiv:hover {\n\t\tcolor: black;\n\t}\n}');
  104. // Selector Separator - (separator = "\n", separator1 = "\n\t")
  105. opts.selector_separator_newline = true;
  106. opts.selector_separator = " ";
  107. t('#bla, #foo{color:green}', '#bla,\n#foo {\n\tcolor: green\n}');
  108. t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
  109. t('@media print {.tab,.bat{}}', '@media print {\n\t.tab,\n\t.bat {}\n}');
  110. t('#bla, #foo{color:black}', '#bla,\n#foo {\n\tcolor: black\n}');
  111. t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child,\na:first-child {\n\tcolor: red;\n\tdiv:first-child,\n\tdiv:hover {\n\t\tcolor: black;\n\t}\n}');
  112. // Newline Between Rules - (separator = "\n")
  113. opts.newline_between_rules = true;
  114. t('.div {}\n.span {}', '.div {}\n\n.span {}');
  115. t('.div{}\n \n.span{}', '.div {}\n\n.span {}');
  116. t('.div {} \n \n.span { } \n', '.div {}\n\n.span {}');
  117. t('.div {\n \n} \n .span {\n } ', '.div {}\n\n.span {}');
  118. t('.selector1 {\n\tmargin: 0; /* This is a comment including an url http://domain.com/path/to/file.ext */\n}\n.div{height:15px;}', '.selector1 {\n\tmargin: 0;\n\t/* This is a comment including an url http://domain.com/path/to/file.ext */\n}\n\n.div {\n\theight: 15px;\n}');
  119. t('.tabs{width:10px;//end of line comment\nheight:10px;//another\n}\n.div{height:15px;}', '.tabs {\n\twidth: 10px; //end of line comment\n\theight: 10px; //another\n}\n\n.div {\n\theight: 15px;\n}');
  120. t('#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div{height:15px;}', '#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
  121. t('@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div{height:15px;}', '@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
  122. t('@font-face {\n\tfont-family: "Bitstream Vera Serif Bold";\n\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: "Helvetica Neue"\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}', '@font-face {\n\tfont-family: "Bitstream Vera Serif Bold";\n\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n}\n\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: "Helvetica Neue"\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}');
  123. t('a:first-child{color:red;div:first-child{color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
  124. t('a:first-child{color:red;div:not(.peq){color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:not(.peq) {\n\t\tcolor: black;\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
  125. // Newline Between Rules - (separator = "")
  126. opts.newline_between_rules = false;
  127. t('.div {}\n.span {}');
  128. t('.div{}\n \n.span{}', '.div {}\n.span {}');
  129. t('.div {} \n \n.span { } \n', '.div {}\n.span {}');
  130. t('.div {\n \n} \n .span {\n } ', '.div {}\n.span {}');
  131. t('.selector1 {\n\tmargin: 0; /* This is a comment including an url http://domain.com/path/to/file.ext */\n}\n.div{height:15px;}', '.selector1 {\n\tmargin: 0;\n\t/* This is a comment including an url http://domain.com/path/to/file.ext */\n}\n.div {\n\theight: 15px;\n}');
  132. t('.tabs{width:10px;//end of line comment\nheight:10px;//another\n}\n.div{height:15px;}', '.tabs {\n\twidth: 10px; //end of line comment\n\theight: 10px; //another\n}\n.div {\n\theight: 15px;\n}');
  133. t('#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div{height:15px;}', '#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div {\n\theight: 15px;\n}');
  134. t('@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div{height:15px;}', '@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div {\n\theight: 15px;\n}');
  135. t('@font-face {\n\tfont-family: "Bitstream Vera Serif Bold";\n\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: "Helvetica Neue"\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}');
  136. t('a:first-child{color:red;div:first-child{color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}\n.div {\n\theight: 15px;\n}');
  137. t('a:first-child{color:red;div:not(.peq){color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:not(.peq) {\n\t\tcolor: black;\n\t}\n}\n.div {\n\theight: 15px;\n}');
  138. // Functions braces
  139. t('.tabs(){}', '.tabs() {}');
  140. t('.tabs (){}', '.tabs () {}');
  141. t('.tabs (pa, pa(1,2)), .cols { }', '.tabs (pa, pa(1, 2)),\n.cols {}');
  142. t('.tabs(pa, pa(1,2)), .cols { }', '.tabs(pa, pa(1, 2)),\n.cols {}');
  143. t('.tabs ( ) { }', '.tabs () {}');
  144. t('.tabs( ) { }', '.tabs() {}');
  145. t('.tabs (t, t2) \n{\n key: val(p1 ,p2); \n }', '.tabs (t, t2) {\n\tkey: val(p1, p2);\n}');
  146. t('.box-shadow(@shadow: 0 1px 3px rgba(0, 0, 0, .25)) {\n\t-webkit-box-shadow: @shadow;\n\t-moz-box-shadow: @shadow;\n\tbox-shadow: @shadow;\n}');
  147. // Comments
  148. t('/* test */');
  149. t('.tabs{/* test */}', '.tabs {\n\t/* test */\n}');
  150. t('.tabs{/* test */}', '.tabs {\n\t/* test */\n}');
  151. t('/* header */.tabs {}', '/* header */\n\n.tabs {}');
  152. t('.tabs {\n/* non-header */\nwidth:10px;}', '.tabs {\n\t/* non-header */\n\twidth: 10px;\n}');
  153. t('/* header');
  154. t('// comment');
  155. t('.selector1 {\n\tmargin: 0; /* This is a comment including an url http://domain.com/path/to/file.ext */\n}', '.selector1 {\n\tmargin: 0;\n\t/* This is a comment including an url http://domain.com/path/to/file.ext */\n}');
  156. // single line comment support (less/sass)
  157. t('.tabs{\n// comment\nwidth:10px;\n}', '.tabs {\n\t// comment\n\twidth: 10px;\n}');
  158. t('.tabs{// comment\nwidth:10px;\n}', '.tabs {\n\t// comment\n\twidth: 10px;\n}');
  159. t('//comment\n.tabs{width:10px;}', '//comment\n.tabs {\n\twidth: 10px;\n}');
  160. t('.tabs{//comment\n//2nd single line comment\nwidth:10px;}', '.tabs {\n\t//comment\n\t//2nd single line comment\n\twidth: 10px;\n}');
  161. t('.tabs{width:10px;//end of line comment\n}', '.tabs {\n\twidth: 10px; //end of line comment\n}');
  162. t('.tabs{width:10px;//end of line comment\nheight:10px;}', '.tabs {\n\twidth: 10px; //end of line comment\n\theight: 10px;\n}');
  163. t('.tabs{width:10px;//end of line comment\nheight:10px;//another\n}', '.tabs {\n\twidth: 10px; //end of line comment\n\theight: 10px; //another\n}');
  164. // Psuedo-classes vs Variables
  165. t('@page :first {}');
  166. // Assume the colon goes with the @name. If we're in LESS, this is required regardless of the at-string.
  167. t('@page:first {}', '@page: first {}');
  168. t('@page: first {}');
  169. // SASS/SCSS
  170. // Basic Interpolation
  171. t('p {\n\t$font-size: 12px;\n\t$line-height: 30px;\n\tfont: #{$font-size}/#{$line-height};\n}');
  172. t('p.#{$name} {}');
  173. t(
  174. '@mixin itemPropertiesCoverItem($items, $margin) {\n' +
  175. '\twidth: calc((100% - ((#{$items} - 1) * #{$margin}rem)) / #{$items});\n' +
  176. '\tmargin: 1.6rem #{$margin}rem 1.6rem 0;\n' +
  177. '}');
  178. //
  179. // test basic css beautifier
  180. t(".tabs {}");
  181. t(".tabs{color:red;}", ".tabs {\n\tcolor: red;\n}");
  182. t(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}");
  183. t(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}");
  184. t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}");
  185. t("@media print {.tab{}}", "@media print {\n\t.tab {}\n}");
  186. t("@media print {.tab{background-image:url(foo@2x.png)}}", "@media print {\n\t.tab {\n\t\tbackground-image: url(foo@2x.png)\n\t}\n}");
  187. t("a:before {\n" +
  188. "\tcontent: 'a{color:black;}\"\"\\'\\'\"\\n\\n\\na{color:black}\';\n" +
  189. "}");
  190. //lead-in whitespace determines base-indent.
  191. // lead-in newlines are stripped.
  192. t("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
  193. t(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }");
  194. t(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }");
  195. t("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
  196. // separate selectors
  197. t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}");
  198. t("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
  199. // block nesting
  200. t("#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: 'Bitstream Vera Serif Bold';\n\t\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n\t}\n}");
  201. t("@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: 'Bitstream Vera Serif Bold';\n\t\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n\t}\n}");
  202. /*
  203. @font-face {
  204. font-family: 'Bitstream Vera Serif Bold';
  205. src: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');
  206. }
  207. @media screen {
  208. #foo:hover {
  209. background-image: url(foo.png);
  210. }
  211. @media screen and (min-device-pixel-ratio: 2) {
  212. @font-face {
  213. font-family: 'Helvetica Neue'
  214. }
  215. #foo:hover {
  216. background-image: url(foo@2x.png);
  217. }
  218. }
  219. }
  220. */
  221. t("@font-face {\n\tfont-family: 'Bitstream Vera Serif Bold';\n\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: 'Helvetica Neue'\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}");
  222. // less-css cases
  223. t('.well{@well-bg:@bg-color;@well-fg:@fg-color;}','.well {\n\t@well-bg: @bg-color;\n\t@well-fg: @fg-color;\n}');
  224. t('.well {&.active {\nbox-shadow: 0 1px 1px @border-color, 1px 0 1px @border-color;}}',
  225. '.well {\n' +
  226. '\t&.active {\n' +
  227. '\t\tbox-shadow: 0 1px 1px @border-color, 1px 0 1px @border-color;\n' +
  228. '\t}\n' +
  229. '}');
  230. t('a {\n' +
  231. '\tcolor: blue;\n' +
  232. '\t&:hover {\n' +
  233. '\t\tcolor: green;\n' +
  234. '\t}\n' +
  235. '\t& & &&&.active {\n' +
  236. '\t\tcolor: green;\n' +
  237. '\t}\n' +
  238. '}');
  239. // Not sure if this is sensible
  240. // but I believe it is correct to not remove the space in "&: hover".
  241. t('a {\n' +
  242. '\t&: hover {\n' +
  243. '\t\tcolor: green;\n' +
  244. '\t}\n' +
  245. '}');
  246. // import
  247. t('@import "test";');
  248. // don't break nested pseudo-classes
  249. t("a:first-child{color:red;div:first-child{color:black;}}",
  250. "a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}");
  251. // handle SASS/LESS parent reference
  252. t("div{&:first-letter {text-transform: uppercase;}}",
  253. "div {\n\t&:first-letter {\n\t\ttext-transform: uppercase;\n\t}\n}");
  254. //nested modifiers (&:hover etc)
  255. t(".tabs{&:hover{width:10px;}}", ".tabs {\n\t&:hover {\n\t\twidth: 10px;\n\t}\n}");
  256. t(".tabs{&.big{width:10px;}}", ".tabs {\n\t&.big {\n\t\twidth: 10px;\n\t}\n}");
  257. t(".tabs{&>big{width:10px;}}", ".tabs {\n\t&>big {\n\t\twidth: 10px;\n\t}\n}");
  258. t(".tabs{&+.big{width:10px;}}", ".tabs {\n\t&+.big {\n\t\twidth: 10px;\n\t}\n}");
  259. //nested rules
  260. t(".tabs{.child{width:10px;}}", ".tabs {\n\t.child {\n\t\twidth: 10px;\n\t}\n}");
  261. //variables
  262. t("@myvar:10px;.tabs{width:10px;}", "@myvar: 10px;\n.tabs {\n\twidth: 10px;\n}");
  263. t("@myvar:10px; .tabs{width:10px;}", "@myvar: 10px;\n.tabs {\n\twidth: 10px;\n}");
  264. // test options
  265. opts.indent_size = 2;
  266. opts.indent_char = ' ';
  267. opts.selector_separator_newline = false;
  268. // pseudo-classes and pseudo-elements
  269. t("#foo:hover {\n background-image: url(foo@2x.png)\n}");
  270. t("#foo *:hover {\n color: purple\n}");
  271. t("::selection {\n color: #ff0000;\n}");
  272. // TODO: don't break nested pseduo-classes
  273. t("@media screen {.tab,.bat:hover {color:red}}", "@media screen {\n .tab, .bat:hover {\n color: red\n }\n}");
  274. // particular edge case with braces and semicolons inside tags that allows custom text
  275. t("a:not(\"foobar\\\";{}omg\"){\ncontent: 'example\\';{} text';\ncontent: \"example\\\";{} text\";}",
  276. "a:not(\"foobar\\\";{}omg\") {\n content: 'example\\';{} text';\n content: \"example\\\";{} text\";\n}");
  277. // may not eat the space before "["
  278. t('html.js [data-custom="123"] {\n opacity: 1.00;\n}');
  279. t('html.js *[data-custom="123"] {\n opacity: 1.00;\n}');
  280. }
  281. beautifier_tests();
  282. }
  283. if (typeof exports !== "undefined") {
  284. exports.run_css_tests = run_css_tests;
  285. }