csscom.py 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/env python
  2. from argparse import ArgumentParser
  3. from parse import parse_groups
  4. from generate import generate_group
  5. def compress_css(css, compress_blocks=True, compress_whitespace=True,
  6. compress_color=True, compress_font=True,
  7. compress_dimension=True, sort_properties=True):
  8. groups = parse_groups(css)
  9. options = dict(compress_blocks=compress_blocks,
  10. compress_whitespace=compress_whitespace,
  11. compress_color=compress_color,
  12. compress_font=compress_font,
  13. compress_dimension=compress_dimension,
  14. sort_properties=sort_properties)
  15. compressed_groups = [generate_group(selectors, blocks, **options)
  16. for selectors, blocks in groups]
  17. newlines = '' if compress_whitespace else '\n\n'
  18. return newlines.join(compressed_groups)
  19. def parse_options():
  20. parser = ArgumentParser(description='Just another CSS compressor.')
  21. parser.add_argument('files', metavar='FILE', nargs='+',
  22. help='list of CSS files to compress')
  23. parser.add_argument('-cw', '--compress-whitespace', action='store_true',
  24. help='omit unnecessary whitespaces and semicolons')
  25. parser.add_argument('-cc', '--compress-color', action='store_true',
  26. help='replace color codes/names with shorter synonyms')
  27. parser.add_argument('-cf', '--compress-font', action='store_true',
  28. help='replace separate font statements with shortcut '
  29. 'font statement where possible')
  30. parser.add_argument('-cd', '--compress-dimension', action='store_true',
  31. help='replace separate margin/padding statements with '
  32. 'shortcut statements where possible')
  33. parser.add_argument('-cb', '--compress-blocks', action='store_true',
  34. help='combine or split blocks into blocks with '
  35. 'comma-separated selectors if it results in less '
  36. 'css code')
  37. parser.add_argument('-nc', '--no-compression', action='store_true',
  38. help='don\'t apply any compression, just generate CSS')
  39. parser.add_argument('-ns', '--no-sort', action='store_false',
  40. dest='sort_properties', help='sort property names')
  41. parser.add_argument('-o', '--output', help='filename for compressed '
  42. 'output (default is stdout)')
  43. args = parser.parse_args()
  44. # Enable all compression options if none are explicitely enabled
  45. if not any([args.compress_whitespace, args.compress_color,
  46. args.compress_font, args.compress_dimension,
  47. args.compress_blocks]) and not args.no_compression:
  48. args.compress_whitespace = args.compress_color = args.compress_font = \
  49. args.compress_dimension = args.compress_blocks = True
  50. return args
  51. def _content(filename):
  52. handle = open(filename, 'r')
  53. content = '\n' + handle.read()
  54. handle.close()
  55. return content
  56. if __name__ == '__main__': # pragma: nocover
  57. args = parse_options()
  58. options = dict(args._get_kwargs())
  59. files = options.pop('files')
  60. output_file = options.pop('output')
  61. del options['no_compression']
  62. try:
  63. css = '\n'.join(_content(filename) for filename in files)
  64. compressed = compress_css(css, **options)
  65. if output_file:
  66. open(output_file, 'w').write(compressed)
  67. else:
  68. print compressed,
  69. except IOError as e:
  70. print e