node-css.mustache 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. {{#default_options}} opts.{{name}} = {{&value}};
  57. {{/default_options}}
  58. {{#groups}}
  59. {{^matrix}}
  60. // {{&name}}
  61. {{#options}}
  62. opts.{{name}} = {{&value}};
  63. {{/options}}
  64. {{#tests}}
  65. {{#test_line}}.{{/test_line}};
  66. {{/tests}}
  67. {{/matrix}}
  68. {{#matrix}}
  69. // {{&name}} - ({{#matrix_context_string}}.{{/matrix_context_string}})
  70. {{#options}}
  71. opts.{{name}} = {{&value}};
  72. {{/options}}
  73. {{#tests}}
  74. {{#test_line}}.{{/test_line}};
  75. {{/tests}}
  76. {{/matrix}}
  77. {{/groups}}
  78. // test basic css beautifier
  79. t(".tabs {}");
  80. t(".tabs{color:red;}", ".tabs {\n\tcolor: red;\n}");
  81. t(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}");
  82. t(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}");
  83. t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}");
  84. t("@media print {.tab{}}", "@media print {\n\t.tab {}\n}");
  85. 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}");
  86. t("a:before {\n" +
  87. "\tcontent: 'a{color:black;}\"\"\\'\\'\"\\n\\n\\na{color:black}\';\n" +
  88. "}");
  89. //lead-in whitespace determines base-indent.
  90. // lead-in newlines are stripped.
  91. t("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
  92. t(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }");
  93. t(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }");
  94. t("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
  95. // separate selectors
  96. t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}");
  97. t("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
  98. // block nesting
  99. 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}");
  100. 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}");
  101. /*
  102. @font-face {
  103. font-family: 'Bitstream Vera Serif Bold';
  104. src: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');
  105. }
  106. @media screen {
  107. #foo:hover {
  108. background-image: url(foo.png);
  109. }
  110. @media screen and (min-device-pixel-ratio: 2) {
  111. @font-face {
  112. font-family: 'Helvetica Neue'
  113. }
  114. #foo:hover {
  115. background-image: url(foo@2x.png);
  116. }
  117. }
  118. }
  119. */
  120. 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}");
  121. // less-css cases
  122. t('.well{@well-bg:@bg-color;@well-fg:@fg-color;}','.well {\n\t@well-bg: @bg-color;\n\t@well-fg: @fg-color;\n}');
  123. t('.well {&.active {\nbox-shadow: 0 1px 1px @border-color, 1px 0 1px @border-color;}}',
  124. '.well {\n' +
  125. '\t&.active {\n' +
  126. '\t\tbox-shadow: 0 1px 1px @border-color, 1px 0 1px @border-color;\n' +
  127. '\t}\n' +
  128. '}');
  129. t('a {\n' +
  130. '\tcolor: blue;\n' +
  131. '\t&:hover {\n' +
  132. '\t\tcolor: green;\n' +
  133. '\t}\n' +
  134. '\t& & &&&.active {\n' +
  135. '\t\tcolor: green;\n' +
  136. '\t}\n' +
  137. '}');
  138. // Not sure if this is sensible
  139. // but I believe it is correct to not remove the space in "&: hover".
  140. t('a {\n' +
  141. '\t&: hover {\n' +
  142. '\t\tcolor: green;\n' +
  143. '\t}\n' +
  144. '}');
  145. // import
  146. t('@import "test";');
  147. // don't break nested pseudo-classes
  148. t("a:first-child{color:red;div:first-child{color:black;}}",
  149. "a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}");
  150. // handle SASS/LESS parent reference
  151. t("div{&:first-letter {text-transform: uppercase;}}",
  152. "div {\n\t&:first-letter {\n\t\ttext-transform: uppercase;\n\t}\n}");
  153. //nested modifiers (&:hover etc)
  154. t(".tabs{&:hover{width:10px;}}", ".tabs {\n\t&:hover {\n\t\twidth: 10px;\n\t}\n}");
  155. t(".tabs{&.big{width:10px;}}", ".tabs {\n\t&.big {\n\t\twidth: 10px;\n\t}\n}");
  156. t(".tabs{&>big{width:10px;}}", ".tabs {\n\t&>big {\n\t\twidth: 10px;\n\t}\n}");
  157. t(".tabs{&+.big{width:10px;}}", ".tabs {\n\t&+.big {\n\t\twidth: 10px;\n\t}\n}");
  158. //nested rules
  159. t(".tabs{.child{width:10px;}}", ".tabs {\n\t.child {\n\t\twidth: 10px;\n\t}\n}");
  160. //variables
  161. t("@myvar:10px;.tabs{width:10px;}", "@myvar: 10px;\n.tabs {\n\twidth: 10px;\n}");
  162. t("@myvar:10px; .tabs{width:10px;}", "@myvar: 10px;\n.tabs {\n\twidth: 10px;\n}");
  163. // test options
  164. opts.indent_size = 2;
  165. opts.indent_char = ' ';
  166. opts.selector_separator_newline = false;
  167. // pseudo-classes and pseudo-elements
  168. t("#foo:hover {\n background-image: url(foo@2x.png)\n}");
  169. t("#foo *:hover {\n color: purple\n}");
  170. t("::selection {\n color: #ff0000;\n}");
  171. // TODO: don't break nested pseduo-classes
  172. t("@media screen {.tab,.bat:hover {color:red}}", "@media screen {\n .tab, .bat:hover {\n color: red\n }\n}");
  173. // particular edge case with braces and semicolons inside tags that allows custom text
  174. t("a:not(\"foobar\\\";{}omg\"){\ncontent: 'example\\';{} text';\ncontent: \"example\\\";{} text\";}",
  175. "a:not(\"foobar\\\";{}omg\") {\n content: 'example\\';{} text';\n content: \"example\\\";{} text\";\n}");
  176. // may not eat the space before "["
  177. t('html.js [data-custom="123"] {\n opacity: 1.00;\n}');
  178. t('html.js *[data-custom="123"] {\n opacity: 1.00;\n}');
  179. }
  180. beautifier_tests();
  181. }
  182. if (typeof exports !== "undefined") {
  183. exports.run_css_tests = run_css_tests;
  184. }