corrade-nucleus-nucleons – Blame information for rev 20
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
20 | office | 1 | #!/usr/bin/env python |
2 | # -*- coding: utf-8 -*- |
||
3 | |||
4 | ''' |
||
5 | {{&header_text}} |
||
6 | |||
7 | The MIT License (MIT) |
||
8 | |||
9 | Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors. |
||
10 | |||
11 | Permission is hereby granted, free of charge, to any person |
||
12 | obtaining a copy of this software and associated documentation files |
||
13 | (the "Software"), to deal in the Software without restriction, |
||
14 | including without limitation the rights to use, copy, modify, merge, |
||
15 | publish, distribute, sublicense, and/or sell copies of the Software, |
||
16 | and to permit persons to whom the Software is furnished to do so, |
||
17 | subject to the following conditions: |
||
18 | |||
19 | The above copyright notice and this permission notice shall be |
||
20 | included in all copies or substantial portions of the Software. |
||
21 | |||
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||
25 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
||
26 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
||
27 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||
28 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
29 | SOFTWARE. |
||
30 | ''' |
||
31 | |||
32 | import unittest |
||
33 | import cssbeautifier |
||
34 | import copy |
||
35 | |||
36 | class CSSBeautifierTest(unittest.TestCase): |
||
37 | |||
38 | options = None |
||
39 | |||
40 | @classmethod |
||
41 | def setUpClass(cls): |
||
42 | false = False |
||
43 | true = True |
||
44 | |||
45 | default_options = cssbeautifier.default_options() |
||
46 | default_options.indent_size = 1 |
||
47 | default_options.indent_char = '\t' |
||
48 | default_options.selector_separator_newline = true |
||
49 | default_options.end_with_newline = false |
||
50 | default_options.newline_between_rules = false |
||
51 | |||
52 | {{#default_options}} default_options.{{name}} = {{&value}} |
||
53 | {{/default_options}} |
||
54 | |||
55 | cls.default_options = default_options |
||
56 | |||
57 | def reset_options(self): |
||
58 | self.options = copy.copy(self.default_options) |
||
59 | |||
60 | def testGenerated(self): |
||
61 | self.reset_options() |
||
62 | test_fragment = self.decodesto |
||
63 | t = self.decodesto |
||
64 | |||
65 | false = False |
||
66 | true = True |
||
67 | |||
68 | {{#groups}}{{#set_mustache_tags}}.{{/set_mustache_tags}} |
||
69 | #============================================================ |
||
70 | {{^matrix}} |
||
71 | # {{&name}} |
||
72 | self.reset_options(); |
||
73 | {{#options}} |
||
74 | self.options.{{name}} = {{&value}} |
||
75 | {{/options}} |
||
76 | {{#tests}} |
||
77 | {{#test_line}}.{{/test_line}} |
||
78 | {{/tests}} |
||
79 | |||
80 | {{/matrix}} |
||
81 | {{#matrix}} |
||
82 | # {{&name}} - ({{#matrix_context_string}}.{{/matrix_context_string}}) |
||
83 | self.reset_options(); |
||
84 | {{#options}} |
||
85 | self.options.{{name}} = {{&value}} |
||
86 | {{/options}} |
||
87 | {{#tests}} |
||
88 | {{#test_line}}.{{/test_line}} |
||
89 | {{/tests}} |
||
90 | |||
91 | {{/matrix}} |
||
92 | {{#unset_mustache_tags}}.{{/unset_mustache_tags}}{{/groups}} |
||
93 | |||
94 | def testNewline(self): |
||
95 | self.reset_options() |
||
96 | t = self.decodesto |
||
97 | |||
98 | self.options.end_with_newline = True |
||
99 | t("", "\n") |
||
100 | t("\n", "\n") |
||
101 | t(".tabs{}\n", ".tabs {}\n") |
||
102 | t(".tabs{}", ".tabs {}\n") |
||
103 | |||
104 | def testBasics(self): |
||
105 | self.reset_options() |
||
106 | t = self.decodesto |
||
107 | |||
108 | t("", "") |
||
109 | t("\n", "") |
||
110 | t(".tabs{}\n", ".tabs {}") |
||
111 | t(".tabs{}", ".tabs {}") |
||
112 | t(".tabs{color:red}", ".tabs {\n\tcolor: red\n}") |
||
113 | t(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}") |
||
114 | t(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}") |
||
115 | t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}") |
||
116 | t("@media print {.tab{}}", "@media print {\n\t.tab {}\n}") |
||
117 | 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}") |
||
118 | |||
119 | t("a:before {\n" + |
||
120 | "\tcontent: 'a{color:black;}\"\"\\'\\'\"\\n\\n\\na{color:black}\';\n" + |
||
121 | "}"); |
||
122 | |||
123 | # may not eat the space before "[" |
||
124 | t('html.js [data-custom="123"] {\n\topacity: 1.00;\n}') |
||
125 | t('html.js *[data-custom="123"] {\n\topacity: 1.00;\n}') |
||
126 | |||
127 | # lead-in whitespace determines base-indent. |
||
128 | # lead-in newlines are stripped. |
||
129 | t("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}") |
||
130 | t(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }") |
||
131 | t(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }") |
||
132 | t("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}") |
||
133 | |||
134 | def testSeperateSelectors(self): |
||
135 | self.reset_options() |
||
136 | t = self.decodesto |
||
137 | |||
138 | t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}") |
||
139 | t("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}") |
||
140 | |||
141 | |||
142 | def testBlockNesting(self): |
||
143 | self.reset_options() |
||
144 | t = self.decodesto |
||
145 | |||
146 | 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}") |
||
147 | 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}") |
||
148 | |||
149 | # @font-face { |
||
150 | # font-family: 'Bitstream Vera Serif Bold'; |
||
151 | # src: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf'); |
||
152 | # } |
||
153 | # @media screen { |
||
154 | # #foo:hover { |
||
155 | # background-image: url(foo.png); |
||
156 | # } |
||
157 | # @media screen and (min-device-pixel-ratio: 2) { |
||
158 | # @font-face { |
||
159 | # font-family: 'Helvetica Neue' |
||
160 | # } |
||
161 | # #foo:hover { |
||
162 | # background-image: url(foo@2x.png); |
||
163 | # } |
||
164 | # } |
||
165 | # } |
||
166 | 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}") |
||
167 | |||
168 | |||
169 | def testOptions(self): |
||
170 | self.reset_options() |
||
171 | self.options.indent_size = 2 |
||
172 | self.options.indent_char = ' ' |
||
173 | self.options.selector_separator_newline = False |
||
174 | t = self.decodesto |
||
175 | |||
176 | # pseudo-classes and pseudo-elements |
||
177 | t("#foo:hover {\n background-image: url(foo@2x.png)\n}") |
||
178 | t("#foo *:hover {\n color: purple\n}") |
||
179 | t("::selection {\n color: #ff0000;\n}") |
||
180 | |||
181 | # TODO: don't break nested pseduo-classes |
||
182 | t("@media screen {.tab,.bat:hover {color:red}}", "@media screen {\n .tab, .bat:hover {\n color: red\n }\n}") |
||
183 | |||
184 | # particular edge case with braces and semicolons inside tags that allows custom text |
||
185 | t( "a:not(\"foobar\\\";{}omg\"){\ncontent: 'example\\';{} text';\ncontent: \"example\\\";{} text\";}", |
||
186 | "a:not(\"foobar\\\";{}omg\") {\n content: 'example\\';{} text';\n content: \"example\\\";{} text\";\n}") |
||
187 | |||
188 | def testLessCss(self): |
||
189 | self.reset_options() |
||
190 | t = self.decodesto |
||
191 | |||
192 | t('.well{ \n @well-bg:@bg-color;@well-fg:@fg-color;}','.well {\n\t@well-bg: @bg-color;\n\t@well-fg: @fg-color;\n}') |
||
193 | t('.well {&.active {\nbox-shadow: 0 1px 1px @border-color, 1px 0 1px @border-color;}}', |
||
194 | '.well {\n' + |
||
195 | '\t&.active {\n' + |
||
196 | '\t\tbox-shadow: 0 1px 1px @border-color, 1px 0 1px @border-color;\n' + |
||
197 | '\t}\n' + |
||
198 | '}') |
||
199 | t('a {\n' + |
||
200 | '\tcolor: blue;\n' + |
||
201 | '\t&:hover {\n' + |
||
202 | '\t\tcolor: green;\n' + |
||
203 | '\t}\n' + |
||
204 | '\t& & &&&.active {\n' + |
||
205 | '\t\tcolor: green;\n' + |
||
206 | '\t}\n' + |
||
207 | '}') |
||
208 | |||
209 | # Not sure if this is sensible |
||
210 | # but I believe it is correct to not remove the space in "&: hover". |
||
211 | t('a {\n' + |
||
212 | '\t&: hover {\n' + |
||
213 | '\t\tcolor: green;\n' + |
||
214 | '\t}\n' + |
||
215 | '}'); |
||
216 | |||
217 | # import |
||
218 | t('@import "test";'); |
||
219 | |||
220 | # don't break nested pseudo-classes |
||
221 | t("a:first-child{color:red;div:first-child{color:black;}}", |
||
222 | "a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}"); |
||
223 | |||
224 | # handle SASS/LESS parent reference |
||
225 | t("div{&:first-letter {text-transform: uppercase;}}", |
||
226 | "div {\n\t&:first-letter {\n\t\ttext-transform: uppercase;\n\t}\n}"); |
||
227 | |||
228 | # nested modifiers (&:hover etc) |
||
229 | t(".tabs{&:hover{width:10px;}}", ".tabs {\n\t&:hover {\n\t\twidth: 10px;\n\t}\n}") |
||
230 | t(".tabs{&.big{width:10px;}}", ".tabs {\n\t&.big {\n\t\twidth: 10px;\n\t}\n}") |
||
231 | t(".tabs{&>big{width:10px;}}", ".tabs {\n\t&>big {\n\t\twidth: 10px;\n\t}\n}") |
||
232 | t(".tabs{&+.big{width:10px;}}", ".tabs {\n\t&+.big {\n\t\twidth: 10px;\n\t}\n}") |
||
233 | |||
234 | # nested rules |
||
235 | t(".tabs{.child{width:10px;}}", ".tabs {\n\t.child {\n\t\twidth: 10px;\n\t}\n}") |
||
236 | |||
237 | # variables |
||
238 | t("@myvar:10px;.tabs{width:10px;}", "@myvar: 10px;\n.tabs {\n\twidth: 10px;\n}") |
||
239 | t("@myvar:10px; .tabs{width:10px;}", "@myvar: 10px;\n.tabs {\n\twidth: 10px;\n}") |
||
240 | |||
241 | def decodesto(self, input, expectation=None): |
||
242 | if expectation == None: |
||
243 | expectation = input |
||
244 | |||
245 | self.assertMultiLineEqual( |
||
246 | cssbeautifier.beautify(input, self.options), expectation) |
||
247 | |||
248 | # if the expected is different from input, run it again |
||
249 | # expected output should be unchanged when run twice. |
||
250 | if not expectation != input: |
||
251 | self.assertMultiLineEqual( |
||
252 | cssbeautifier.beautify(expectation, self.options), expectation) |
||
253 | |||
254 | # Everywhere we do newlines, they should be replaced with opts.eol |
||
255 | self.options.eol = '\r\\n'; |
||
256 | expectation = expectation.replace('\n', '\r\n') |
||
257 | self.assertMultiLineEqual( |
||
258 | cssbeautifier.beautify(input, self.options), expectation) |
||
259 | if input.find('\n') != -1: |
||
260 | input = input.replace('\n', '\r\n') |
||
261 | self.assertMultiLineEqual( |
||
262 | cssbeautifier.beautify(input, self.options), expectation) |
||
263 | # Ensure support for auto eol detection |
||
264 | self.options.eol = 'auto' |
||
265 | self.assertMultiLineEqual( |
||
266 | cssbeautifier.beautify(input, self.options), expectation) |
||
267 | self.options.eol = '\n' |
||
268 | |||
269 | if __name__ == '__main__': |
||
270 | unittest.main() |