Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python script for minifying CSS? [closed]

I'm looking for a simple Python script that can minify CSS as part of a web-site deployment process. (Python is the only scripting language supported on the server and full-blown parsers like CSS Utils are overkill for this project).

Basically I'd like jsmin.py for CSS. A single script with no dependencies.

Any ideas?

like image 386
Will Moffat Avatar asked Oct 21 '08 16:10

Will Moffat


People also ask

Can Python be minified?

Sure, you could uglify it, but given the fact that python relies on indentation for syntax, you couldn't do the equivalent minification (which in JS relies largely upon removing all whitespace). Beside the point, but JS is minified to make it download faster, not obfuscate it.

Should I Minify CSS files?

By stripping unnecessary data from the CSS code, minification helps the browser download and process these files faster, increasing page performance and improving user experience.


6 Answers

This seemed like a good task for me to get into python, which has been pending for a while. I hereby present my first ever python script:

import sys, re

with open( sys.argv[1] , 'r' ) as f:
    css = f.read()

# remove comments - this will break a lot of hacks :-P
css = re.sub( r'\s*/\*\s*\*/', "$$HACK1$$", css ) # preserve IE<6 comment hack
css = re.sub( r'/\*[\s\S]*?\*/', "", css )
css = css.replace( "$$HACK1$$", '/**/' ) # preserve IE<6 comment hack

# url() doesn't need quotes
css = re.sub( r'url\((["\'])([^)]*)\1\)', r'url(\2)', css )

# spaces may be safely collapsed as generated content will collapse them anyway
css = re.sub( r'\s+', ' ', css )

# shorten collapsable colors: #aabbcc to #abc
css = re.sub( r'#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)', r'#\1\2\3\4', css )

# fragment values can loose zeros
css = re.sub( r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css )

for rule in re.findall( r'([^{]+){([^}]*)}', css ):

    # we don't need spaces around operators
    selectors = [re.sub( r'(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])', r'', selector.strip() ) for selector in rule[0].split( ',' )]

    # order is important, but we still want to discard repetitions
    properties = {}
    porder = []
    for prop in re.findall( '(.*?):(.*?)(;|$)', rule[1] ):
        key = prop[0].strip().lower()
        if key not in porder: porder.append( key )
        properties[ key ] = prop[1].strip()

    # output rule if it contains any declarations
    if properties:
        print "%s{%s}" % ( ','.join( selectors ), ''.join(['%s:%s;' % (key, properties[key]) for key in porder])[:-1] ) 

I believe this to work, and output it tests fine on recent Safari, Opera, and Firefox. It will break CSS hacks other than the underscore & /**/ hacks! Do not use a minifier if you have a lot of hacks going on (or put them in a separate file).

Any tips on my python appreciated. Please be gentle though, it's my first time. :-)

like image 155
Borgar Avatar answered Sep 30 '22 14:09

Borgar


There is a port of YUI's CSS compressor available for python.

Here is its project page on PyPi: http://pypi.python.org/pypi/cssmin/0.1.1

like image 44
Gregor Müllegger Avatar answered Sep 30 '22 12:09

Gregor Müllegger


There is a nice online tool cssminifier which has also an API which is pretty simple and easy to use. I made a small python script that posts the CSS file content to that tool's API, returns the minifed CSS and saves it into a file "style.min.css". I like it because it is a small code that may be nicely integrated in an automated deployment script:

import requests
f = open("style.css", "r")
css_text = f.read()
f.close()
r = requests.post("http://cssminifier.com/raw", data={"input":css_text})
css_minified = r.text
f2 = open("style.min.css", "w")
f2.write(css_minified)
f2.close()
like image 36
Yahya Yahyaoui Avatar answered Sep 30 '22 14:09

Yahya Yahyaoui


In case someone landed on this question and is using Django, there is a commonly used package for this matter called Django Compressor:

Compresses linked and inline JavaScript or CSS into a single cached file.

  • JS/CSS belong in the templates

  • Flexibility

  • It doesn’t get in the way

  • Full test suite

like image 34
Wtower Avatar answered Sep 30 '22 12:09

Wtower


I don't know of any ready made python css minifiers, but like you said css utils has the option. After checking and verifying that the license allows for it, you could go through the source code and snip out the portions that do the minifying yourself. Then stick this in a single script and voila! There you go.

As a head start, the csscombine function in .../trunk/src/cssutils/script.py seems to do the work of minifying somewhere around line 361 (I checked out revision 1499). Note the boolean function argument called "minify".

like image 26
Jeffrey Martinez Avatar answered Sep 30 '22 12:09

Jeffrey Martinez


In the webassets docs you can find links to multiple compressors and compilers. From that list I have chosen pyScss, which also minifies the resulting CSS.

If you need just a CSS compressor you can try csscompressor:

Almost exact port of YUI CSS Compressor. Passes all original unittests.

A more generic tool is css-html-prettify:

StandAlone Async single-file cross-platform Unicode-ready Python3 Prettifier Beautifier for the Web.

like image 22
alexandrul Avatar answered Sep 30 '22 13:09

alexandrul