Permalink
Browse files

add python based js/css minimization tool

  • Loading branch information...
Justine Tunney
Justine Tunney committed Jan 26, 2012
1 parent 0b7b31a commit ff575179fc4fa296fea7b3e3926a49ab9d410853
Showing with 124 additions and 1 deletion.
  1. +122 −0 occupywallst/management/commands/minify.py
  2. +2 −1 setup.py
@@ -0,0 +1,122 @@
+r"""
+
+ tranarchy.management.commands.minify
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Minifies JS/CSS/PNG media files.
+
+ Usage: tranarchy minify APP ...
+
+ You specify a list of Django apps as arguments. This program finds the
+ files by searching $MEDIA_DIR/$APP_NAME/{js,css,img}/. The
+ .min.js file extension is used for minified files. No new files need
+ to be created to optimize PNG.
+
+ Minification is done using:
+
+ - Javascript: slimit_
+ - CSS: cssmin_
+ - PNG: optipng_ (if available)
+
+ Please don't put third party libraries like jQuery in your app's media
+ folder because we shouldn't be minimizing them. Put vendor libraries in
+ $MEDIA_DIR/{js,css,img}/.
+
+ .. _slimit: http://pypi.python.org/pypi/slimit
+ .. _cssmin: http://pypi.python.org/pypi/cssmin
+ .. _optipng: http://optipng.sourceforge.net/
+
+"""
+
+import os
+import sys
+from glob import glob
+from subprocess import call
+from optparse import make_option
+
+
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+
+
+class Command(BaseCommand):
+ args = 'APP ...'
+ help = __doc__
+ option_list = BaseCommand.option_list + (
+ make_option(
+ '--no-mangle', action='store_false', dest='mangle',
+ default=True, help="Don't mangle javascript variables"),
+ make_option(
+ '--copyright', action='store_true', dest='copyright',
+ default=False, help=("Preserve first comment in file about "
+ "imaginary property")),
+ )
+
+ def handle(self, *args, **options):
+ mroot = settings.MEDIA_ROOT
+ mangle = options['mangle']
+ copyright = options['copyright']
+ toto_before = 0
+ toto_after = 0
+
+ if not args:
+ raise CommandError('Please specify an app name!')
+
+ try:
+ from slimit import minify
+ except ImportError:
+ raise CommandError('Please run: pip install slimit')
+
+ try:
+ from cssmin import cssmin
+ except ImportError:
+ raise CommandError('Please run: pip install cssmin')
+
+ for app in args:
+ for ext, funk in (('js', lambda s: minify(s, mangle=mangle)),
+ ('css', lambda s: cssmin(s))):
+ noms = glob('%s/%s/%s/*.%s' % (mroot, app, ext, ext))
+ for nom in [nom for nom in noms if '.min.' not in nom]:
+ before = os.stat(nom).st_size
+ toto_before += before
+ sys.stdout.write('minifying %s...' % (nom))
+ try:
+ with open(nom) as fin:
+ data = fin.read()
+ res = funk(data)
+ if copyright and data.startswith('/*'):
+ res = data[:data.index('*/') + 2] + res
+ except Exception, exc:
+ sys.stdout.write('%r\n' % (exc))
+ else:
+ after = len(res)
+ toto_after += after
+ with open(nom[:-len(ext)] + 'min.' + ext, 'w') as fout:
+ fout.write(res)
+ pct = int(float(after) / before * 100)
+ sys.stdout.write('OK (%d%% orig size)\n' % (pct))
+
+ sys.stdout.write(
+ 'total js/css reduction: %dkB -> %dkB (%d%% orig size)\n' % (
+ int(float(toto_before) / 1024),
+ int(float(toto_after) / 1024),
+ int(float(toto_after) / toto_before * 100)))
+
+ pngs = []
+ for app in args:
+ pngs += glob('%s/%s/img/*.png' % (mroot, app))
+ pngs += glob('%s/%s/img/*/*.png' % (mroot, app))
+ pngs += glob('%s/%s/img/*/*/*.png' % (mroot, app))
+ if pngs:
+ sys.stdout.write('optimizing all your png files...')
+ try:
+ if call(['optipng', '-quiet'] + pngs) != 0:
+ sys.stdout.write('FAIL\n')
+ except Exception, exc:
+ if isinstance(exc, OSError) and exc.errno == 2:
+ sys.stdout.write('optipng not installed!\n'
+ 'sudo apt-get install optipng\n')
+ else:
+ sys.stdout.write('%r\n' % (exc))
+ else:
+ sys.stdout.write('OK\n')
View
@@ -25,7 +25,8 @@ def read(fname):
install_requires = ['Django==1.3.1', 'python-memcached>=1.40', 'pytz',
'markdown', 'twilio', 'django-debug-toolbar',
'recaptcha-client', 'gunicorn', 'django-rosetta',
- 'django-imagekit', 'south', 'Whoosh', 'redis'],
+ 'django-imagekit', 'south', 'Whoosh', 'redis',
+ 'slimit', 'cssmin'],
packages = find_packages(),
include_package_data = True,
zip_safe = False,

0 comments on commit ff57517

Please sign in to comment.