Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 import functools | |
| 7 import os.path | |
| 8 import re | |
| 9 import sys | |
| 10 | |
| 11 import in_generator | |
| 12 | |
| 13 | |
| 14 class CSSMinimizer(object): | |
| 15 | |
| 16 INITIAL = 0 | |
| 17 MAYBE_COMMENT_START = 1 | |
| 18 INSIDE_COMMENT = 2 | |
| 19 MAYBE_COMMENT_END = 3 | |
| 20 INSIDE_SINGLE_QUOTE = 4 | |
| 21 INSIDE_SINGLE_QUOTE_ESCAPE = 5 | |
| 22 INSIDE_DOUBLE_QUOTE = 6 | |
| 23 INSIDE_DOUBLE_QUOTE_ESCAPE = 7 | |
| 24 | |
| 25 def __init__(self): | |
| 26 self._output = '' | |
| 27 self._codeblock = '' | |
| 28 | |
| 29 def flush_codeblock(self): | |
| 30 stripped = re.sub(r"\s+", ' ', self._codeblock) | |
| 31 stripped = re.sub(r";?\s*(?P<op>[{};])\s*", r'\g<op>', stripped) | |
| 32 self._output += stripped | |
| 33 self._codeblock = '' | |
| 34 | |
| 35 def parse(self, content): | |
| 36 state = self.INITIAL | |
| 37 for char in content: | |
| 38 if state == self.INITIAL: | |
| 39 if char == '/': | |
| 40 state = self.MAYBE_COMMENT_START | |
| 41 elif char == "'": | |
| 42 self.flush_codeblock() | |
| 43 self._output += char | |
| 44 state = self.INSIDE_SINGLE_QUOTE | |
| 45 elif char == '"': | |
| 46 self.flush_codeblock() | |
| 47 self._output += char | |
| 48 state = self.INSIDE_DOUBLE_QUOTE | |
| 49 else: | |
| 50 self._codeblock += char | |
| 51 elif state == self.MAYBE_COMMENT_START: | |
| 52 if char == '*': | |
| 53 self.flush_codeblock() | |
| 54 state = self.INSIDE_COMMENT | |
| 55 else: | |
| 56 self._codeblock += '/' + char | |
| 57 state = self.INITIAL | |
| 58 elif state == self.INSIDE_COMMENT: | |
| 59 if char == '*': | |
| 60 state = self.MAYBE_COMMENT_END | |
| 61 else: | |
| 62 pass | |
| 63 elif state == self.MAYBE_COMMENT_END: | |
| 64 if char == '/': | |
| 65 state = self.INITIAL | |
| 66 else: | |
| 67 state = self.INSIDE_COMMENT | |
| 68 elif state == self.INSIDE_SINGLE_QUOTE: | |
| 69 if char == '\\': | |
| 70 self._output += char | |
| 71 state = self.INSIDE_SINGLE_QUOTE_ESCAPE | |
| 72 elif char == "'": | |
| 73 self._output += char | |
| 74 state = self.INITIAL | |
| 75 else: | |
| 76 self._output += char | |
| 77 elif state == self.INSIDE_SINGLE_QUOTE_ESCAPE: | |
| 78 self._output += char | |
| 79 state = self.INSIDE_SINGLE_QUOTE | |
| 80 elif state == self.INSIDE_DOUBLE_QUOTE: | |
| 81 if char == '\\': | |
| 82 self._output += char | |
| 83 state = self.INSIDE_DOUBLE_QUOTE_ESCAPE | |
| 84 elif char == '"': | |
| 85 self._output += char | |
| 86 state = self.INITIAL | |
| 87 else: | |
| 88 self._output += char | |
| 89 elif state == self.INSIDE_DOUBLE_QUOTE_ESCAPE: | |
| 90 self._output += char | |
| 91 state = self.INSIDE_DOUBLE_QUOTE | |
| 92 | |
| 93 self.flush_codeblock() | |
| 94 self._output = self._output.strip() | |
| 95 return self._output | |
| 96 | |
| 97 @property | |
| 98 def output(self): | |
|
Timothy Loh
2016/11/03 06:07:59
Why do we need this? Can we just "return CSSMinimi
kouhei (in TOK)
2016/11/06 23:06:29
Done. Removed
| |
| 99 return self._output | |
| 100 | |
| 101 @classmethod | |
| 102 def minimize_css(cls, content): | |
| 103 minimizer = CSSMinimizer() | |
| 104 minimizer.parse(content) | |
| 105 return minimizer.output | |
| 106 | |
| 107 | |
| 108 class CSSMinimizerWriter(in_generator.GenericWriter): | |
| 109 | |
| 110 def __init__(self, in_file_paths): | |
| 111 super(CSSMinimizerWriter, self).__init__(in_file_paths) | |
| 112 | |
| 113 self._outputs = {} | |
| 114 for in_file_path in in_file_paths: | |
| 115 out_path = os.path.basename(in_file_path) | |
| 116 self._outputs[out_path] = functools.partial(self.generate_implementa tion, in_file_path) | |
| 117 | |
| 118 def generate_implementation(self, in_file_path): | |
| 119 content = '' | |
| 120 with open(os.path.abspath(in_file_path)) as in_file: | |
| 121 content = in_file.read() | |
| 122 return CSSMinimizer.minimize_css(content) | |
| 123 | |
| 124 | |
| 125 if __name__ == '__main__': | |
| 126 in_generator.Maker(CSSMinimizerWriter).main(sys.argv) | |
| OLD | NEW |