summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--compressor/filters/cssmin/__init__.py3
-rwxr-xr-xcompressor/filters/cssmin/rcssmin.py374
-rw-r--r--compressor/filters/jsmin/__init__.py3
-rwxr-xr-xcompressor/filters/jsmin/rjsmin.py514
-rw-r--r--docs/settings.txt4
-rw-r--r--requirements/tests.txt2
-rw-r--r--setup.py2
-rw-r--r--tox.ini8
9 files changed, 19 insertions, 893 deletions
diff --git a/Makefile b/Makefile
index c342825..6d4b2bf 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ runtests:
coverage run --branch --source=compressor `which django-admin.py` test --settings=compressor.test_settings compressor
coveragereport:
- coverage report --omit=compressor/test*,compressor/filters/jsmin/rjsmin*,compressor/filters/cssmin/cssmin*
+ coverage report --omit=compressor/test*
test: flake8 runtests coveragereport
diff --git a/compressor/filters/cssmin/__init__.py b/compressor/filters/cssmin/__init__.py
index 01a916d..3b127a9 100644
--- a/compressor/filters/cssmin/__init__.py
+++ b/compressor/filters/cssmin/__init__.py
@@ -11,7 +11,8 @@ class CSSCompressorFilter(CallbackOutputFilter):
class rCSSMinFilter(CallbackOutputFilter):
- callback = "compressor.filters.cssmin.rcssmin.cssmin"
+ callback = "rcssmin.cssmin"
+ dependencies = ["rcssmin"]
kwargs = {
"keep_bang_comments": True
}
diff --git a/compressor/filters/cssmin/rcssmin.py b/compressor/filters/cssmin/rcssmin.py
deleted file mode 100755
index 5f590bc..0000000
--- a/compressor/filters/cssmin/rcssmin.py
+++ /dev/null
@@ -1,374 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: ascii -*-
-r"""
-==============
- CSS Minifier
-==============
-
-CSS Minifier.
-
-The minifier is based on the semantics of the `YUI compressor`_\\, which
-itself is based on `the rule list by Isaac Schlueter`_\\.
-
-:Copyright:
-
- Copyright 2011 - 2015
- Andr\xe9 Malo or his licensors, as applicable
-
-:License:
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-This module is a re-implementation aiming for speed instead of maximum
-compression, so it can be used at runtime (rather than during a preprocessing
-step). RCSSmin does syntactical compression only (removing spaces, comments
-and possibly semicolons). It does not provide semantic compression (like
-removing empty blocks, collapsing redundant properties etc). It does, however,
-support various CSS hacks (by keeping them working as intended).
-
-Here's a feature list:
-
-- Strings are kept, except that escaped newlines are stripped
-- Space/Comments before the very end or before various characters are
- stripped: ``:{});=>],!`` (The colon (``:``) is a special case, a single
- space is kept if it's outside a ruleset.)
-- Space/Comments at the very beginning or after various characters are
- stripped: ``{}(=:>[,!``
-- Optional space after unicode escapes is kept, resp. replaced by a simple
- space
-- whitespaces inside ``url()`` definitions are stripped
-- Comments starting with an exclamation mark (``!``) can be kept optionally.
-- All other comments and/or whitespace characters are replaced by a single
- space.
-- Multiple consecutive semicolons are reduced to one
-- The last semicolon within a ruleset is stripped
-- CSS Hacks supported:
-
- - IE7 hack (``>/**/``)
- - Mac-IE5 hack (``/*\\*/.../**/``)
- - The boxmodelhack is supported naturally because it relies on valid CSS2
- strings
- - Between ``:first-line`` and the following comma or curly brace a space is
- inserted. (apparently it's needed for IE6)
- - Same for ``:first-letter``
-
-rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
-factor 100 or so (depending on the input). docs/BENCHMARKS in the source
-distribution contains the details.
-
-Both python 2 (>= 2.4) and python 3 are supported.
-
-.. _YUI compressor: https://github.com/yui/yuicompressor/
-
-.. _the rule list by Isaac Schlueter: https://github.com/isaacs/cssmin/
-"""
-if __doc__:
- # pylint: disable = W0622
- __doc__ = __doc__.encode('ascii').decode('unicode_escape')
-__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
-__docformat__ = "restructuredtext en"
-__license__ = "Apache License, Version 2.0"
-__version__ = '1.0.6'
-__all__ = ['cssmin']
-
-import re as _re
-
-
-def _make_cssmin(python_only=False):
- """
- Generate CSS minifier.
-
- :Parameters:
- `python_only` : ``bool``
- Use only the python variant. If true, the c extension is not even
- tried to be loaded.
-
- :Return: Minifier
- :Rtype: ``callable``
- """
- # pylint: disable = R0912, R0914, W0612
-
- if not python_only:
- try:
- import _rcssmin
- except ImportError:
- pass
- else:
- return _rcssmin.cssmin
-
- nl = r'(?:[\n\f]|\r\n?)' # pylint: disable = C0103
- spacechar = r'[\r\n\f\040\t]'
-
- unicoded = r'[0-9a-fA-F]{1,6}(?:[\040\n\t\f]|\r\n?)?'
- escaped = r'[^\n\r\f0-9a-fA-F]'
- escape = r'(?:\\(?:%(unicoded)s|%(escaped)s))' % locals()
-
- nmchar = r'[^\000-\054\056\057\072-\100\133-\136\140\173-\177]'
- # nmstart = r'[^\000-\100\133-\136\140\173-\177]'
- # ident = (r'(?:'
- # r'-?(?:%(nmstart)s|%(escape)s)%(nmchar)s*(?:%(escape)s%(nmchar)s*)*'
- # r')') % locals()
-
- comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
-
- # only for specific purposes. The bang is grouped:
- _bang_comment = r'(?:/\*(!?)[^*]*\*+(?:[^/*][^*]*\*+)*/)'
-
- string1 = \
- r'(?:\047[^\047\\\r\n\f]*(?:\\[^\r\n\f][^\047\\\r\n\f]*)*\047)'
- string2 = r'(?:"[^"\\\r\n\f]*(?:\\[^\r\n\f][^"\\\r\n\f]*)*")'
- strings = r'(?:%s|%s)' % (string1, string2)
-
- nl_string1 = \
- r'(?:\047[^\047\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^\047\\\r\n\f]*)*\047)'
- nl_string2 = r'(?:"[^"\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^"\\\r\n\f]*)*")'
- nl_strings = r'(?:%s|%s)' % (nl_string1, nl_string2)
-
- uri_nl_string1 = r'(?:\047[^\047\\]*(?:\\(?:[^\r]|\r\n?)[^\047\\]*)*\047)'
- uri_nl_string2 = r'(?:"[^"\\]*(?:\\(?:[^\r]|\r\n?)[^"\\]*)*")'
- uri_nl_strings = r'(?:%s|%s)' % (uri_nl_string1, uri_nl_string2)
-
- nl_escaped = r'(?:\\%(nl)s)' % locals()
-
- space = r'(?:%(spacechar)s|%(comment)s)' % locals()
-
- ie7hack = r'(?:>/\*\*/)'
-
- uri = (r'(?:'
- # noqa pylint: disable = C0330
- r'(?:[^\000-\040"\047()\\\177]*'
- r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*)'
- r'(?:'
- r'(?:%(spacechar)s+|%(nl_escaped)s+)'
- r'(?:'
- r'(?:[^\000-\040"\047()\\\177]|%(escape)s|%(nl_escaped)s)'
- r'[^\000-\040"\047()\\\177]*'
- r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*'
- r')+'
- r')*'
- r')') % locals()
-
- nl_unesc_sub = _re.compile(nl_escaped).sub
-
- uri_space_sub = _re.compile((
- r'(%(escape)s+)|%(spacechar)s+|%(nl_escaped)s+'
- ) % locals()).sub
- uri_space_subber = lambda m: m.groups()[0] or ''
-
- space_sub_simple = _re.compile((
- r'[\r\n\f\040\t;]+|(%(comment)s+)'
- ) % locals()).sub
- space_sub_banged = _re.compile((
- r'[\r\n\f\040\t;]+|(%(_bang_comment)s+)'
- ) % locals()).sub
-
- post_esc_sub = _re.compile(r'[\r\n\f\t]+').sub
-
- main_sub = _re.compile((
- # noqa pylint: disable = C0330
- r'([^\\"\047u>@\r\n\f\040\t/;:{}+]+)' # 1
- r'|(?<=[{}(=:>[,!])(%(space)s+)' # 2
- r'|^(%(space)s+)' # 3
- r'|(%(space)s+)(?=(([:{});=>\],!])|$)?)' # 4, 5, 6
- r'|;(%(space)s*(?:;%(space)s*)*)(?=(\})?)' # 7, 8
- r'|(\{)' # 9
- r'|(\})' # 10
- r'|(%(strings)s)' # 11
- r'|(?<!%(nmchar)s)url\(%(spacechar)s*(' # 12
- r'%(uri_nl_strings)s'
- r'|%(uri)s'
- r')%(spacechar)s*\)'
- r'|(@(?:' # 13
- r'[mM][eE][dD][iI][aA]'
- r'|[sS][uU][pP][pP][oO][rR][tT][sS]'
- r'|[dD][oO][cC][uU][mM][eE][nN][tT]'
- r'|(?:-(?:'
- r'[wW][eE][bB][kK][iI][tT]|[mM][oO][zZ]|[oO]|[mM][sS]'
- r')-)?'
- r'[kK][eE][yY][fF][rR][aA][mM][eE][sS]'
- r'))(?!%(nmchar)s)'
- r'|(%(ie7hack)s)(%(space)s*)' # 14, 15
- r'|(:[fF][iI][rR][sS][tT]-[lL]' # 16
- r'(?:[iI][nN][eE]|[eE][tT][tT][eE][rR]))'
- r'(%(space)s*)(?=[{,])' # 17
- r'|(%(nl_strings)s)' # 18
- r'|(%(escape)s[^\\"\047u>@\r\n\f\040\t/;:{}+]*)' # 19
- ) % locals()).sub
-
- # print main_sub.__self__.pattern
-
- def main_subber(keep_bang_comments):
- """ Make main subber """
- in_macie5, in_rule, at_group = [0], [0], [0]
-
- if keep_bang_comments:
- space_sub = space_sub_banged
-
- def space_subber(match):
- """ Space|Comment subber """
- if match.lastindex:
- group1, group2 = match.group(1, 2)
- if group2:
- if group1.endswith(r'\*/'):
- in_macie5[0] = 1
- else:
- in_macie5[0] = 0
- return group1
- elif group1:
- if group1.endswith(r'\*/'):
- if in_macie5[0]:
- return ''
- in_macie5[0] = 1
- return r'/*\*/'
- elif in_macie5[0]:
- in_macie5[0] = 0
- return '/**/'
- return ''
- else:
- space_sub = space_sub_simple
-
- def space_subber(match):
- """ Space|Comment subber """
- if match.lastindex:
- if match.group(1).endswith(r'\*/'):
- if in_macie5[0]:
- return ''
- in_macie5[0] = 1
- return r'/*\*/'
- elif in_macie5[0]:
- in_macie5[0] = 0
- return '/**/'
- return ''
-
- def fn_space_post(group):
- """ space with token after """
- if group(5) is None or (
- group(6) == ':' and not in_rule[0] and not at_group[0]):
- return ' ' + space_sub(space_subber, group(4))
- return space_sub(space_subber, group(4))
-
- def fn_semicolon(group):
- """ ; handler """
- return ';' + space_sub(space_subber, group(7))
-
- def fn_semicolon2(group):
- """ ; handler """
- if in_rule[0]:
- return space_sub(space_subber, group(7))
- return ';' + space_sub(space_subber, group(7))
-
- def fn_open(_):
- """ { handler """
- if at_group[0]:
- at_group[0] -= 1
- else:
- in_rule[0] = 1
- return '{'
-
- def fn_close(_):
- """ } handler """
- in_rule[0] = 0
- return '}'
-
- def fn_at_group(group):
- """ @xxx group handler """
- at_group[0] += 1
- return group(13)
-
- def fn_ie7hack(group):
- """ IE7 Hack handler """
- if not in_rule[0] and not at_group[0]:
- in_macie5[0] = 0
- return group(14) + space_sub(space_subber, group(15))
- return '>' + space_sub(space_subber, group(15))
-
- table = (
- # noqa pylint: disable = C0330
- None,
- None,
- None,
- None,
- fn_space_post, # space with token after
- fn_space_post, # space with token after
- fn_space_post, # space with token after
- fn_semicolon, # semicolon
- fn_semicolon2, # semicolon
- fn_open, # {
- fn_close, # }
- lambda g: g(11), # string
- lambda g: 'url(%s)' % uri_space_sub(uri_space_subber, g(12)),
- # url(...)
- fn_at_group, # @xxx expecting {...}
- None,
- fn_ie7hack, # ie7hack
- None,
- lambda g: g(16) + ' ' + space_sub(space_subber, g(17)),
- # :first-line|letter followed
- # by [{,] (apparently space
- # needed for IE6)
- lambda g: nl_unesc_sub('', g(18)), # nl_string
- lambda g: post_esc_sub(' ', g(19)), # escape
- )
-
- def func(match):
- """ Main subber """
- idx, group = match.lastindex, match.group
- if idx > 3:
- return table[idx](group)
-
- # shortcuts for frequent operations below:
- elif idx == 1: # not interesting
- return group(1)
- # else: # space with token before or at the beginning
- return space_sub(space_subber, group(idx))
-
- return func
-
- def cssmin(style, keep_bang_comments=False): # pylint: disable = W0621
- """
- Minify CSS.
-
- :Parameters:
- `style` : ``str``
- CSS to minify
-
- `keep_bang_comments` : ``bool``
- Keep comments starting with an exclamation mark? (``/*!...*/``)
-
- :Return: Minified style
- :Rtype: ``str``
- """
- return main_sub(main_subber(keep_bang_comments), style)
-
- return cssmin
-
-cssmin = _make_cssmin()
-
-
-if __name__ == '__main__':
- def main():
- """ Main """
- import sys as _sys
- keep_bang_comments = (
- '-b' in _sys.argv[1:]
- or '-bp' in _sys.argv[1:]
- or '-pb' in _sys.argv[1:]
- )
- if '-p' in _sys.argv[1:] or '-bp' in _sys.argv[1:] \
- or '-pb' in _sys.argv[1:]:
- global cssmin # pylint: disable = W0603
- cssmin = _make_cssmin(python_only=True)
- _sys.stdout.write(cssmin(
- _sys.stdin.read(), keep_bang_comments=keep_bang_comments
- ))
- main()
diff --git a/compressor/filters/jsmin/__init__.py b/compressor/filters/jsmin/__init__.py
index f8fbbdf..ceca6ac 100644
--- a/compressor/filters/jsmin/__init__.py
+++ b/compressor/filters/jsmin/__init__.py
@@ -4,7 +4,8 @@ from compressor.filters.jsmin.slimit import SlimItFilter # noqa
class rJSMinFilter(CallbackOutputFilter):
- callback = "compressor.filters.jsmin.rjsmin.jsmin"
+ callback = "rjsmin.jsmin"
+ dependencies = ["rjsmin"]
kwargs = {
"keep_bang_comments": True
}
diff --git a/compressor/filters/jsmin/rjsmin.py b/compressor/filters/jsmin/rjsmin.py
deleted file mode 100755
index 4d24b46..0000000
--- a/compressor/filters/jsmin/rjsmin.py
+++ /dev/null
@@ -1,514 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: ascii -*-
-r"""
-=====================
- Javascript Minifier
-=====================
-
-rJSmin is a javascript minifier written in python.
-
-The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\\.
-
-:Copyright:
-
- Copyright 2011 - 2015
- Andr\xe9 Malo or his licensors, as applicable
-
-:License:
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-The module is a re-implementation aiming for speed, so it can be used at
-runtime (rather than during a preprocessing step). Usually it produces the
-same results as the original ``jsmin.c``. It differs in the following ways:
-
-- there is no error detection: unterminated string, regex and comment
- literals are treated as regular javascript code and minified as such.
-- Control characters inside string and regex literals are left untouched; they
- are not converted to spaces (nor to \\n)
-- Newline characters are not allowed inside string and regex literals, except
- for line continuations in string literals (ECMA-5).
-- "return /regex/" is recognized correctly.
-- Line terminators after regex literals are handled more sensibly
-- "+ +" and "- -" sequences are not collapsed to '++' or '--'
-- Newlines before ! operators are removed more sensibly
-- Comments starting with an exclamation mark (``!``) can be kept optionally
-- rJSmin does not handle streams, but only complete strings. (However, the
- module provides a "streamy" interface).
-
-Since most parts of the logic are handled by the regex engine it's way faster
-than the original python port of ``jsmin.c`` by Baruch Even. The speed factor
-varies between about 6 and 55 depending on input and python version (it gets
-faster the more compressed the input already is). Compared to the
-speed-refactored python port by Dave St.Germain the performance gain is less
-dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS
-file for details.
-
-rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
-
-Both python 2 and python 3 are supported.
-
-.. _jsmin.c by Douglas Crockford:
- http://www.crockford.com/javascript/jsmin.c
-"""
-if __doc__:
- # pylint: disable = redefined-builtin
- __doc__ = __doc__.encode('ascii').decode('unicode_escape')
-__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
-__docformat__ = "restructuredtext en"
-__license__ = "Apache License, Version 2.0"
-__version__ = '1.0.12'
-__all__ = ['jsmin']
-
-import re as _re
-
-
-def _make_jsmin(python_only=False):
- """
- Generate JS minifier based on `jsmin.c by Douglas Crockford`_
-
- .. _jsmin.c by Douglas Crockford:
- http://www.crockford.com/javascript/jsmin.c
-
- :Parameters:
- `python_only` : ``bool``
- Use only the python variant. If true, the c extension is not even
- tried to be loaded.
-
- :Return: Minifier
- :Rtype: ``callable``
- """
- # pylint: disable = unused-variable
- # pylint: disable = too-many-locals
-
- if not python_only:
- try:
- import _rjsmin
- except ImportError:
- pass
- else:
- return _rjsmin.jsmin
- try:
- xrange
- except NameError:
- xrange = range # pylint: disable = redefined-builtin
-
- space_chars = r'[\000-\011\013\014\016-\040]'
-
- line_comment = r'(?://[^\r\n]*)'
- space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
- space_comment_nobang = r'(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*\*+)*/)'
- bang_comment = r'(?:/\*![^*]*\*+(?:[^/*][^*]*\*+)*/)'
-
- string1 = \
- r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
- string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
- strings = r'(?:%s|%s)' % (string1, string2)
-
- charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
- nospecial = r'[^/\\\[\r\n]'
- regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
- nospecial, charclass, nospecial
- )
- space = r'(?:%s|%s)' % (space_chars, space_comment)
- newline = r'(?:%s?[\r\n])' % line_comment
-
- def fix_charclass(result):
- """ Fixup string of chars to fit into a regex char class """
- pos = result.find('-')
- if pos >= 0:
- result = r'%s%s-' % (result[:pos], result[pos + 1:])
-
- def sequentize(string):
- """
- Notate consecutive characters as sequence
-
- (1-4 instead of 1234)
- """
- first, last, result = None, None, []
- for char in map(ord, string):
- if last is None:
- first = last = char
- elif last + 1 == char:
- last = char
- else:
- result.append((first, last))
- first = last = char
- if last is not None:
- result.append((first, last))
- return ''.join(['%s%s%s' % (
- chr(first),
- last > first + 1 and '-' or '',
- last != first and chr(last) or ''
- ) for first, last in result]) # noqa
-
- return _re.sub(
- r'([\000-\040\047])', # \047 for better portability
- lambda m: '\\%03o' % ord(m.group(1)), (
- sequentize(result)
- .replace('\\', '\\\\')
- .replace('[', '\\[')
- .replace(']', '\\]')
- )
- )
-
- def id_literal_(what):
- """ Make id_literal like char class """
- match = _re.compile(what).match
- result = ''.join([
- chr(c) for c in xrange(127) if not match(chr(c))
- ])
- return '[^%s]' % fix_charclass(result)
-
- def not_id_literal_(keep):
- """ Make negated id_literal like char class """
- match = _re.compile(id_literal_(keep)).match
- result = ''.join([
- chr(c) for c in xrange(127) if not match(chr(c))
- ])
- return r'[%s]' % fix_charclass(result)
-
- not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
- preregex1 = r'[(,=:\[!&|?{};\r\n]'
- preregex2 = r'%(not_id_literal)sreturn' % locals()
-
- id_literal = id_literal_(r'[a-zA-Z0-9_$]')
- id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
- id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
- post_regex_off = id_literal_(r'[^\000-\040}\])?:|,;.&=+-]')
-
- dull = r'[^\047"/\000-\040]'
-
- space_sub_simple = _re.compile((
- # noqa pylint: disable = bad-continuation
-
- r'(%(dull)s+)' # 0
- r'|(%(strings)s%(dull)s*)' # 1
- r'|(?<=%(preregex1)s)'
- r'%(space)s*(?:%(newline)s%(space)s*)*'
- r'(%(regex)s)' # 2
- r'(%(space)s*(?:%(newline)s%(space)s*)+' # 3
- r'(?=%(post_regex_off)s))?'
- r'|(?<=%(preregex2)s)'
- r'%(space)s*(?:(%(newline)s)%(space)s*)*' # 4
- r'(%(regex)s)' # 5
- r'(%(space)s*(?:%(newline)s%(space)s*)+' # 6
- r'(?=%(post_regex_off)s))?'
- r'|(?<=%(id_literal_close)s)'
- r'%(space)s*(?:(%(newline)s)%(space)s*)+' # 7
- r'(?=%(id_literal_open)s)'
- r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)' # 8
- r'|(?<=\+)(%(space)s)+(?=\+)' # 9
- r'|(?<=-)(%(space)s)+(?=-)' # 10
- r'|%(space)s+'
- r'|(?:%(newline)s%(space)s*)+'
- ) % locals()).sub
-
- # print space_sub_simple.__self__.pattern
-
- def space_subber_simple(match):
- """ Substitution callback """
- # pylint: disable = too-many-return-statements
-
- groups = match.groups()
- if groups[0]:
- return groups[0]
- elif groups[1]:
- return groups[1]
- elif groups[2]:
- if groups[3]:
- return groups[2] + '\n'
- return groups[2]
- elif groups[5]:
- return "%s%s%s" % (
- groups[4] and '\n' or '',
- groups[5],
- groups[6] and '\n' or '',
- )
- elif groups[7]:
- return '\n'
- elif groups[8] or groups[9] or groups[10]:
- return ' '
- else:
- return ''
-
- space_sub_banged = _re.compile((
- # noqa pylint: disable = bad-continuation
-
- r'(%(dull)s+)' # 0
- r'|(%(strings)s%(dull)s*)' # 1
- r'|(?<=%(preregex1)s)'
- r'(%(space)s*(?:%(newline)s%(space)s*)*)' # 2
- r'(%(regex)s)' # 3
- r'(%(space)s*(?:%(newline)s%(space)s*)+' # 4
- r'(?=%(post_regex_off)s))?'
- r'|(?<=%(preregex2)s)'
- r'(%(space)s*(?:(%(newline)s)%(space)s*)*)' # 5, 6
- r'(%(regex)s)' # 7
- r'(%(space)s*(?:%(newline)s%(space)s*)+' # 8
- r'(?=%(post_regex_off)s))?'
- r'|(?<=%(id_literal_close)s)'
- r'(%(space)s*(?:%(newline)s%(space)s*)+)' # 9
- r'(?=%(id_literal_open)s)'
- r'|(?<=%(id_literal)s)(%(space)s+)(?=%(id_literal)s)' # 10
- r'|(?<=\+)(%(space)s+)(?=\+)' # 11
- r'|(?<=-)(%(space)s+)(?=-)' # 12
- r'|(%(space)s+)' # 13
- r'|((?:%(newline)s%(space)s*)+)' # 14
- ) % locals()).sub
-
- # print space_sub_banged.__self__.pattern
-
- keep = _re.compile((
- r'%(space_chars)s+|%(space_comment_nobang)s+|%(newline)s+'
- r'|(%(bang_comment)s+)'
- ) % locals()).sub
- keeper = lambda m: m.groups()[0] or ''
-
- # print keep.__self__.pattern
-
- def space_subber_banged(match):
- """ Substitution callback """
- # pylint: disable = too-many-return-statements
-
- groups = match.groups()
- if groups[0]:
- return groups[0]
- elif groups[1]:
- return groups[1]
- elif groups[3]:
- return "%s%s%s%s" % (
- keep(keeper, groups[2]),
- groups[3],
- keep(keeper, groups[4] or ''),
- groups[4] and '\n' or '',
- )
- elif groups[7]:
- return "%s%s%s%s%s" % (
- keep(keeper, groups[5]),
- groups[6] and '\n' or '',
- groups[7],
- keep(keeper, groups[8] or ''),
- groups[8] and '\n' or '',
- )
- elif groups[9]:
- return keep(keeper, groups[9]) + '\n'
- elif groups[10] or groups[11] or groups[12]:
- return keep(keeper, groups[10] or groups[11] or groups[12]) or ' '
- else:
- return keep(keeper, groups[13] or groups[14])
-
- def jsmin(script, keep_bang_comments=False):
- r"""
- Minify javascript based on `jsmin.c by Douglas Crockford`_\.
-
- Instead of parsing the stream char by char, it uses a regular
- expression approach which minifies the whole script with one big
- substitution regex.
-
- .. _jsmin.c by Douglas Crockford:
- http://www.crockford.com/javascript/jsmin.c
-
- :Parameters:
- `script` : ``str``
- Script to minify
-
- `keep_bang_comments` : ``bool``
- Keep comments starting with an exclamation mark? (``/*!...*/``)
-
- :Return: Minified script
- :Rtype: ``str``
- """
- # pylint: disable = redefined-outer-name
-
- if keep_bang_comments:
- return space_sub_banged(
- space_subber_banged, '\n%s\n' % script
- ).strip()
- else:
- return space_sub_simple(
- space_subber_simple, '\n%s\n' % script
- ).strip()
-
- return jsmin
-
-jsmin = _make_jsmin()
-
-
-def jsmin_for_posers(script, keep_bang_comments=False):
- r"""
- Minify javascript based on `jsmin.c by Douglas Crockford`_\.
-
- Instead of parsing the stream char by char, it uses a regular
- expression approach which minifies the whole script with one big
- substitution regex.
-
- .. _jsmin.c by Douglas Crockford:
- http://www.crockford.com/javascript/jsmin.c
-
- :Warning: This function is the digest of a _make_jsmin() call. It just
- utilizes the resulting regexes. It's here for fun and may
- vanish any time. Use the `jsmin` function instead.
-
- :Parameters:
- `script` : ``str``
- Script to minify
-
- `keep_bang_comments` : ``bool``
- Keep comments starting with an exclamation mark? (``/*!...*/``)
-
- :Return: Minified script
- :Rtype: ``str``
- """
- if not keep_bang_comments:
- rex = (
- r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'
- r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'
- r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?'
- r'{};\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*'
- r'][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\0'
- r'14\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r'
- r'\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r'
- r'\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\014'
- r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^\r'
- r'\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:'
- r'[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;=?\]|}-]))?|(?<=[\00'
- r'0-#%-,./:-@\[-^`{-~-]return)(?:[\000-\011\013\014\016-\040]|(?'
- r':/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?[\r\n]'
- r'))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'
- r'\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\['
- r'[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))(('
- r'?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'
- r'*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\04'
- r'0]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;'
- r'=?\]|}-]))?|(?<=[^\000-!#%&(*,./:-@\[\\^`{|~])(?:[\000-\011\01'
- r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?:'
- r'//[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]'
- r'*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./:-@\\-^'
- r'`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\014\0'
- r'16-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./'
- r':-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*['
- r'^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013'
- r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:['
- r'\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
- r')+|(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]'
- r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+'
- )
-
- def subber(match):
- """ Substitution callback """
- groups = match.groups()
- return (
- groups[0] or
- groups[1] or
- (groups[3] and (groups[2] + '\n')) or
- groups[2] or
- (groups[5] and "%s%s%s" % (
- groups[4] and '\n' or '',
- groups[5],
- groups[6] and '\n' or '',
- )) or
- (groups[7] and '\n') or
- (groups[8] and ' ') or
- (groups[9] and ' ') or
- (groups[10] and ' ') or
- ''
- )
- else:
- rex = (
- r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'
- r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'
- r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?'
- r'{};\r\n])((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/'
- r'*][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013'
- r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*)((?:/(?!'
- r'[\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^'
- r'\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\01'
- r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^'
- r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+('
- r'?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;=?\]|}-]))?|(?<=['
- r'\000-#%-,./:-@\[-^`{-~-]return)((?:[\000-\011\013\014\016-\040'
- r']|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?['
- r'\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*]['
- r'^*]*\*+)*/))*)*)((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|'
- r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*'
- r'/))((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]'
- r'*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\01'
- r'6-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)'
- r'+,.:;=?\]|}-]))?|(?<=[^\000-!#%&(*,./:-@\[\\^`{|~])((?:[\000-'
- r'\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:'
- r'(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/'
- r'\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)(?=[^\000-\040"#%-\047)*,./'
- r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\01'
- r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=[^\000'
- r'-#%-,./:-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|'
- r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=\+)|(?<=-)((?:[\000-\0'
- r'11\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=-'
- r')|((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'
- r'\*+)*/))+)|((?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014'
- r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)'
- )
-
- keep = _re.compile((
- r'[\000-\011\013\014\016-\040]+|(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*'
- r'\*+)*/)+|(?:(?://[^\r\n]*)?[\r\n])+|((?:/\*![^*]*\*+(?:[^/*][^'
- r'*]*\*+)*/)+)'
- ) % locals()).sub
- keeper = lambda m: m.groups()[0] or ''
-
- def subber(match):
- """ Substitution callback """
- groups = match.groups()
- return (
- groups[0] or
- groups[1] or
- (groups[3] and "%s%s%s%s" % (
- keep(keeper, groups[2]),
- groups[3],
- keep(keeper, groups[4] or ''),
- groups[4] and '\n' or '',
- )) or
- (groups[7] and "%s%s%s%s%s" % (
- keep(keeper, groups[5]),
- groups[6] and '\n' or '',
- groups[7],
- keep(keeper, groups[8] or ''),
- groups[8] and '\n' or '',
- )) or
- (groups[9] and keep(keeper, groups[9] + '\n')) or
- (groups[10] and keep(keeper, groups[10]) or ' ') or
- (groups[11] and keep(keeper, groups[11]) or ' ') or
- (groups[12] and keep(keeper, groups[12]) or ' ') or
- keep(keeper, groups[13] or groups[14])
- )
-
- return _re.sub(rex, subber, '\n%s\n' % script).strip()
-
-
-if __name__ == '__main__':
- def main():
- """ Main """
- import sys as _sys
-
- argv = _sys.argv[1:]
- keep_bang_comments = '-b' in argv or '-bp' in argv or '-pb' in argv
- if '-p' in argv or '-bp' in argv or '-pb' in argv:
- xjsmin = _make_jsmin(python_only=True)
- else:
- xjsmin = jsmin
-
- _sys.stdout.write(xjsmin(
- _sys.stdin.read(), keep_bang_comments=keep_bang_comments
- ))
-
- main()
diff --git a/docs/settings.txt b/docs/settings.txt
index 34995d5..b175bff 100644
--- a/docs/settings.txt
+++ b/docs/settings.txt
@@ -130,7 +130,7 @@ Backend settings
- ``compressor.filters.cssmin.rCSSMinFilter``
A filter that uses the cssmin implementation rCSSmin_ to compress CSS
- (included, no external dependencies).
+ (installed by default).
- ``compressor.filters.cleancss.CleanCSSFilter``
@@ -173,7 +173,7 @@ Backend settings
- ``compressor.filters.jsmin.JSMinFilter``
A filter that uses the jsmin implementation rJSmin_ to compress
- JavaScript code (included, no external dependencies).
+ JavaScript code (installed by default).
.. _slimit_filter:
diff --git a/requirements/tests.txt b/requirements/tests.txt
index 3d42158..1c6a3ff 100644
--- a/requirements/tests.txt
+++ b/requirements/tests.txt
@@ -11,3 +11,5 @@ jingo==0.7
django-sekizai==0.8.2
django-overextends==0.4.0
csscompressor==0.9.4
+rcssmin==1.0.6
+rjsmin==1.0.12
diff --git a/setup.py b/setup.py
index 5271a00..49f9dc2 100644
--- a/setup.py
+++ b/setup.py
@@ -142,5 +142,7 @@ setup(
zip_safe=False,
install_requires=[
'django-appconf >= 0.4',
+ 'rcssmin == 1.0.6',
+ 'rjsmin == 1.0.12',
],
)
diff --git a/tox.ini b/tox.ini
index 478adf0..8767697 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,6 +13,8 @@ two =
django-sekizai==0.8.2
django-overextends==0.4.0
csscompressor==0.9.4
+ rcssmin==1.0.6
+ rjsmin==1.0.12
two_six =
flake8==2.4.0
coverage==3.7.1
@@ -27,6 +29,8 @@ two_six =
django-sekizai==0.8.2
django-overextends==0.4.0
csscompressor==0.9.4
+ rcssmin==1.0.6
+ rjsmin==1.0.12
three =
flake8==2.4.0
coverage==3.7.1
@@ -40,6 +44,8 @@ three =
django-sekizai==0.8.2
django-overextends==0.4.0
csscompressor==0.9.4
+ rcssmin==1.0.6
+ rjsmin==1.0.12
three_two =
flake8==2.4.0
coverage==3.7.1
@@ -53,6 +59,8 @@ three_two =
django-sekizai==0.8.2
django-overextends==0.4.0
csscompressor==0.9.4
+ rcssmin==1.0.6
+ rjsmin==1.0.12
[tox]
envlist =
{py26,py27}-1.4.X,