blob: 2c3b8aeb1ef4086e3eee1739d75fcb4f77253392 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import re
import sys
class CSSMinimizer(object):
INITIAL = 0
MAYBE_COMMENT_START = 1
INSIDE_COMMENT = 2
MAYBE_COMMENT_END = 3
INSIDE_SINGLE_QUOTE = 4
INSIDE_SINGLE_QUOTE_ESCAPE = 5
INSIDE_DOUBLE_QUOTE = 6
INSIDE_DOUBLE_QUOTE_ESCAPE = 7
def __init__(self):
self._output = ''
self._codeblock = ''
def flush_codeblock(self):
stripped = re.sub(r"\s+", ' ', self._codeblock)
stripped = re.sub(r";?\s*(?P<op>[{};])\s*", r'\g<op>', stripped)
self._output += stripped
self._codeblock = ''
def parse(self, content):
state = self.INITIAL
for char in content:
if state == self.INITIAL:
if char == '/':
state = self.MAYBE_COMMENT_START
elif char == "'":
self.flush_codeblock()
self._output += char
state = self.INSIDE_SINGLE_QUOTE
elif char == '"':
self.flush_codeblock()
self._output += char
state = self.INSIDE_DOUBLE_QUOTE
else:
self._codeblock += char
elif state == self.MAYBE_COMMENT_START:
if char == '*':
self.flush_codeblock()
state = self.INSIDE_COMMENT
else:
self._codeblock += '/' + char
state = self.INITIAL
elif state == self.INSIDE_COMMENT:
if char == '*':
state = self.MAYBE_COMMENT_END
else:
pass
elif state == self.MAYBE_COMMENT_END:
if char == '/':
state = self.INITIAL
else:
state = self.INSIDE_COMMENT
elif state == self.INSIDE_SINGLE_QUOTE:
if char == '\\':
self._output += char
state = self.INSIDE_SINGLE_QUOTE_ESCAPE
elif char == "'":
self._output += char
state = self.INITIAL
else:
self._output += char
elif state == self.INSIDE_SINGLE_QUOTE_ESCAPE:
self._output += char
state = self.INSIDE_SINGLE_QUOTE
elif state == self.INSIDE_DOUBLE_QUOTE:
if char == '\\':
self._output += char
state = self.INSIDE_DOUBLE_QUOTE_ESCAPE
elif char == '"':
self._output += char
state = self.INITIAL
else:
self._output += char
elif state == self.INSIDE_DOUBLE_QUOTE_ESCAPE:
self._output += char
state = self.INSIDE_DOUBLE_QUOTE
self.flush_codeblock()
self._output = self._output.strip()
return self._output
@classmethod
def minimize_css(cls, content):
minimizer = CSSMinimizer()
return minimizer.parse(content)
def main():
result = ''
try:
result = CSSMinimizer.minimize_css(sys.stdin.read())
finally:
print(result)
if __name__ == '__main__':
main()