Complete HTML+JS+CSS minification solution

How to minify JavaScript, CSS and HTML, including the <script> and <style> blocks?


 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
minify.py#!/usr/bin/env python3
import subprocess

import htmlmin
import csscompressor


def minify_css(inp):
    "Minify CSS that is in the Unicode string `inp`"
    return csscompressor.compress(inp)

def minify_js(inp):
    "Minify JavaScript that is in the Unicode string `inp`"
    return subprocess.check_output(
        'uglifyjs --compress --mangle --comments'.split(),
        input=inp.encode('utf-8')
    ).decode('utf-8')

def _handle_pre(tag, data):
    if tag == 'style':
        return '\n'+minify_css(data)+'\n'
    if tag == 'script':
        return '\n'+minify_js(data)+'\n'
    return data
def minify_html(inp):
    """Minify HTML that is in the Unicode string `inp`,
    including the <script> and <style> blocks inside it"""
    return htmlmin.minify(inp, remove_comments=True, handle_pre=_handle_pre)

def compile_ls(inp):
    "Compile LiveScript that is in the Unicode string `inp` to JavaScript"
    return subprocess.check_output(
        'lsc --compile --stdin --print'.split(),
        input=inp.encode('utf-8')
    ).decode('utf-8')


def minify(filename, inp=None):
    """Minify HTML or JS or CSS (depending on `filename`) that is in the
    bytestring `inp`. If `inp` is absent, the content is read from `filename`.
    Return a tuple of the new filename and a bytestring of the minified
    content, or None if the file type was not recognized."""
    if inp is None:
        with open(filename, 'rb') as f:
            inp = f.read()
    result = None
    if filename.endswith('.css'):
        result = minify_css(inp.decode('utf-8'))
    elif filename.endswith('.js'):
        if max(map(len, inp.splitlines()) <= 200: # maybe it's already minified
            result = minify_js(inp.decode('utf-8'))
    elif filename.endswith('.ls'):
        filename = filename[:-3]+'.js'
        result = minify_js(compile_ls(inp.decode('utf-8')))
    elif filename.endswith('.html'):
        result = minify_html(inp.decode('utf-8'))
    if result is not None:
        return filename, result.encode('utf-8')

Want to see what this code actually does? Press Ctrl+U!

Things used here:

Created
Comments powered by Disqus