import os, re
from os import path
from django.template import Library, Node, TemplateSyntaxError
from django.conf import settings
register = Library()
class JSPacker:
""" JS compressor. This commpress a javascript content
This class code is adapted from http://plone.org/products/resourceregistries """
def __init__(self):
# protect this strings:
# match a single quote
# match anything but the single quote, a backslash and a newline "[^'\\\n]"
# or match a null escape (\0 not followed by another digit) "\\0(?![0-9])"
# or match a character escape (no newline) "\\[^\n]"
self.patterns = []
self.protect(r"""('(?:[^'\\\n]|\\0(?![0-9])|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\[^\n])*?'|"""
r""""(?:[^"\\\n]|\\0(?![0-9])|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\[^\n])*?")""")
# protect regular expressions
self.protect(r"""\s+(\/[^\/\n\r\*](?:\\/|[^\n\r])*\/g?i?)""")
self.protect(r"""([^\w\$\/'"*)\?:]\/[^\/\n\r\*](?:\\/|[^\n\r])*\/g?i?)""")
# protect IE conditional compilation
self.protect(r'(/\*@.*?(?:\*/|\n|\*/(?!\n)))', re.DOTALL)
# remove multiline comments
self.sub(r'/\*.*?\*/', '', re.DOTALL)
# strip whitespace at the beginning and end of each line
self.sub(r'^[ \t\r\f\v]*(.*?)[ \t\r\f\v]*$', r'\1', re.MULTILINE)
# after an equal sign a function definition is ok
self.sub(r'=\s+(?=function)', r'=')
# whitespace before some special chars
self.sub(r'\s+([={},&|\?:\.()<>%!/\]])', r'\1')
# whitespace before plus chars if no other plus char before i
self.sub(r'(? last_mtime
def merge_js(self, jsname, jspath, fd):
""" do merging and compressing of javascript """
global jspacker
jsfile = open(jspath)
jscontent = jsfile.read()
jscontent = jspacker.pack(jscontent)
fd.write('/* -- %s -- */\n\n%s\n\n\n' % (jsname, jscontent))
def js_tag(self):
""" write js tag for merged file inclusion """
js_url = '%s%s' % (settings.MEDIA_URL, self.js_name)
return '' % js_url
def do_jsmerge(parser, token):
"""
This will merge javascript files in only one compressed javascript.
Usage::
{% load jsmerge %}
{% jsmerge jsname [jsfile1] [jsfile2] .. %}
Example::
{% load jsmerge %}
{% jsmerge jsmergefile js/file1.js js/file2.js js/file3.js %}
This will create (if not exists) a /media/jsmergefile.js with three files merged. The HTML output for this will be::
"""
tokens = token.contents.split()
if len(tokens) < 2:
raise TemplateSyntaxError(u"'%r' tag requires at least 1 arguments." % tokens[0])
js_name = tokens[1]
return JSMergeNode(js_name, tokens[2:])
register.tag('jsmerge', do_jsmerge)