예제 #1
0
 def test_concatenate_and_rewrite(self):
     compressor = Compressor()
     css = compressor.concatenate_and_rewrite([
         os.path.join(settings.PIPELINE_ROOT, 'css/first.css'),
         os.path.join(settings.PIPELINE_ROOT, 'css/second.css')
     ])
     self.assertEquals(""".concat {\n  display: none;\n}\n.concatenate {\n  display: block;\n}""", css)
예제 #2
0
 def test_concatenate(self):
     compressor = Compressor()
     js = compressor.concatenate([
         os.path.join(settings.PIPELINE_ROOT, 'js/first.js'),
         os.path.join(settings.PIPELINE_ROOT, 'js/second.js')
     ])
     self.assertEquals("""(function() { function concat() {\n  console.log(arguments);\n}\nfunction cat() {\n  console.log("hello world");\n} }).call(this);""", js)
예제 #3
0
    def test_url_rewrite(self):
        compressor = Compressor()
        output = compressor.concatenate_and_rewrite([
            os.path.join(settings.PIPELINE_ROOT, 'css/urls.css'),
        ])
        self.assertEquals(""".relative-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)
예제 #4
0
class Packager(object):
    def __init__(self, storage=default_storage, verbose=False, css_packages=None, js_packages=None):
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(verbose=verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {"css": self.create_packages(css_packages), "js": self.create_packages(js_packages)}

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound("No corresponding package for %s package name : %s" % (kind, package_name))

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(
            package,
            self.compressor.compress_css,
            css_compressed,
            output_filename=package.output_filename,
            variant=package.variant,
            **kwargs
        )

    def compile(self, paths):
        return self.compiler.compile(paths)

    def pack(self, package, compress, signal, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print "Saving: %s" % output_filename
        paths = self.compile(package.paths)
        content = compress(paths, **kwargs)
        self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_js, js_compressed, templates=package.templates, **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_str(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #5
0
 def __init__(self, force=False, verbose=False):
     self.force = force
     self.verbose = verbose
     self.compressor = Compressor(verbose)
     self.versioning = Versioning(verbose)
     self.compiler = Compiler(verbose)
     self.packages = {
         'css': self.create_packages(settings.PIPELINE_CSS),
         'js': self.create_packages(settings.PIPELINE_JS),
     }
예제 #6
0
 def __init__(self, storage=default_storage, verbose=False, css_packages=None, js_packages=None):
     self.storage = storage
     self.verbose = verbose
     self.compressor = Compressor(storage=storage, verbose=verbose)
     self.compiler = Compiler(verbose=verbose)
     if css_packages is None:
         css_packages = settings.PIPELINE_CSS
     if js_packages is None:
         js_packages = settings.PIPELINE_JS
     self.packages = {"css": self.create_packages(css_packages), "js": self.create_packages(js_packages)}
예제 #7
0
 def __init__(self, verbose=False, css_packages=None, js_packages=None):
     self.verbose = verbose
     self.compressor = Compressor(verbose)
     self.versioning = Versioning(verbose)
     self.compiler = Compiler(verbose)
     if css_packages is None:
         css_packages = settings.PIPELINE_CSS
     if js_packages is None:
         js_packages = settings.PIPELINE_JS
     self.packages = {
         'css': self.create_packages(css_packages),
         'js': self.create_packages(js_packages),
     }
예제 #8
0
 def __init__(self, storage=None, verbose=False, css_packages=None, js_packages=None):
     if storage is None:
         storage = staticfiles_storage
     self.storage = storage
     self.verbose = verbose
     self.compressor = Compressor(storage=storage, verbose=verbose)
     self.compiler = Compiler(storage=storage, verbose=verbose)
     if css_packages is None:
         css_packages = settings.STYLESHEETS
     if js_packages is None:
         js_packages = settings.JAVASCRIPT
     self.packages = {
         'css': self.create_packages(css_packages),
         'js': self.create_packages(js_packages),
     }
예제 #9
0
 def setUp(self):
     self.compressor = Compressor()
예제 #10
0
 def setUp(self):
     self.maxDiff = None
     self.compressor = Compressor()
예제 #11
0
class CompressorImplementationTest(TestCase):

    maxDiff = None

    def setUp(self):
        self.compressor = Compressor()
        default_collector.collect(RequestFactory().get('/'))

    def tearDown(self):
        default_collector.clear()

    def _test_compressor(self, compressor_cls, compress_type, expected_file):
        override_settings = {
            ("%s_COMPRESSOR" % compress_type.upper()): compressor_cls,
        }
        with pipeline_settings(**override_settings):
            if compress_type == 'js':
                result = self.compressor.compress_js(
                    [_('pipeline/js/first.js'), _('pipeline/js/second.js')])
            else:
                result = self.compressor.compress_css(
                    [_('pipeline/css/first.css'), _('pipeline/css/second.css')],
                    os.path.join('pipeline', 'css', os.path.basename(expected_file)))
        with self.compressor.storage.open(expected_file, 'r') as f:
            expected = f.read()
        self.assertEqual(result, expected)

    def test_jsmin(self):
        self._test_compressor('pipeline.compressors.jsmin.JSMinCompressor',
            'js', 'pipeline/compressors/jsmin.js')

    def test_slimit(self):
        self._test_compressor('pipeline.compressors.slimit.SlimItCompressor',
            'js', 'pipeline/compressors/slimit.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_uglifyjs(self):
        self._test_compressor('pipeline.compressors.uglifyjs.UglifyJSCompressor',
            'js', 'pipeline/compressors/uglifyjs.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_yuglify_js(self):
        self._test_compressor('pipeline.compressors.yuglify.YuglifyCompressor',
            'js', 'pipeline/compressors/yuglify.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_yuglify_css(self):
        self._test_compressor('pipeline.compressors.yuglify.YuglifyCompressor',
            'css', 'pipeline/compressors/yuglify.css')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_cssmin(self):
        self._test_compressor('pipeline.compressors.cssmin.CSSMinCompressor',
            'css', 'pipeline/compressors/cssmin.css')

    @skipUnless(settings.HAS_NODE, "requires node")
    @skipUnless(settings.HAS_JAVA, "requires java")
    def test_closure(self):
        self._test_compressor('pipeline.compressors.closure.ClosureCompressor',
            'js', 'pipeline/compressors/closure.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    @skipUnless(settings.HAS_JAVA, "requires java")
    def test_yui_js(self):
        self._test_compressor('pipeline.compressors.yui.YUICompressor',
            'js', 'pipeline/compressors/yui.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    @skipUnless(settings.HAS_JAVA, "requires java")
    def test_yui_css(self):
        self._test_compressor('pipeline.compressors.yui.YUICompressor',
            'css', 'pipeline/compressors/yui.css')

    @skipUnless(settings.HAS_CSSTIDY, "requires csstidy")
    def test_csstidy(self):
        self._test_compressor('pipeline.compressors.csstidy.CSSTidyCompressor',
            'css', 'pipeline/compressors/csstidy.css')
예제 #12
0
class Packager(object):
    def __init__(self,
                 storage=None,
                 verbose=False,
                 css_packages=None,
                 js_packages=None):
        if storage is None:
            storage = staticfiles_storage
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(storage=storage, verbose=verbose)
        if css_packages is None:
            css_packages = settings.STYLESHEETS
        if js_packages is None:
            js_packages = settings.JAVASCRIPT
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" %
                (kind, package_name))

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(package,
                         self.compressor.compress_css,
                         css_compressed,
                         output_filename=package.output_filename,
                         variant=package.variant,
                         **kwargs)

    def compile(self, paths, compiler_options={}, force=False):
        return self.compiler.compile(
            paths,
            compiler_options=compiler_options,
            force=force,
        )

    def pack(self, package, compress, signal, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print("Saving: %s" % output_filename)
        paths = self.compile(
            package.paths,
            compiler_options=package.compiler_options,
            force=True,
        )
        output_path = self.storage.path(output_filename)
        output_mtime = self.storage.get_modified_time(output_path)
        if any([
                self.storage.get_modified_time(self.storage.path(path)) >=
                output_mtime for path in paths
        ]):
            content = compress(paths, **kwargs)
            self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package,
                         self.compressor.compress_js,
                         js_compressed,
                         templates=package.templates,
                         **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_bytes(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #13
0
 def setUp(self):
     self.maxDiff = None
     self.compressor = Compressor()
예제 #14
0
class CompressorTest(TestCase):
    def setUp(self):
        self.maxDiff = None
        self.compressor = Compressor()

    def test_js_compressor_class(self):
        self.assertEqual(self.compressor.js_compressor, YuglifyCompressor)

    def test_css_compressor_class(self):
        self.assertEqual(self.compressor.css_compressor, YuglifyCompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite(
            [_('pipeline/css/first.css'),
             _('pipeline/css/second.css')], 'css/screen.css')
        self.assertEqual(
            """.concat {\n  display: none;\n}\n\n.concatenate {\n  display: block;\n}\n""",
            css)

    def test_concatenate(self):
        js = self.compressor.concatenate(
            [_('pipeline/js/first.js'),
             _('pipeline/js/second.js')])
        self.assertEqual(
            """function concat() {\n  console.log(arguments);\n}\n\nfunction cat() {\n  console.log("hello world");\n}\n""",
            js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertFalse(mock.called)

    def test_relative_path(self):
        relative_path = self.compressor.relative_path("images/sprite.png",
                                                      'css/screen.css')
        self.assertEqual(relative_path, '../images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path(
            [_('js/templates/form.jst'),
             _('js/templates/field.jst')])
        self.assertEqual(base_path, _('js/templates'))

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path(
            '../../images/sprite.png', 'css/plugins/')
        self.assertEqual(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
                                                      'css/plugins/')
        self.assertEqual(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
                                             'templates/')
        self.assertEqual(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
                                             'templates\\')
        self.assertEqual(name, 'photo_detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates(
            [_('pipeline/templates/photo/list.jst')])
        self.assertEqual(
            templates,
            """window.JST = window.JST || {};\n%s\nwindow.JST[\'list\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%>\\n </div>\\n</div>\');\n"""
            % TEMPLATE_FUNC)
        templates = self.compressor.compile_templates([
            _('pipeline/templates/video/detail.jst'),
            _('pipeline/templates/photo/detail.jst')
        ])
        self.assertEqual(
            templates,
            """window.JST = window.JST || {};\n%s\nwindow.JST[\'video_detail\'] = template(\'<div class="video">\\n <video src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= description %%>\\n </div>\\n</div>\');\nwindow.JST[\'photo_detail\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%> by <%%= author %%>\\n </div>\\n</div>\');\n"""
            % TEMPLATE_FUNC)

    def test_embeddable(self):
        self.assertFalse(
            self.compressor.embeddable(_('pipeline/images/sprite.png'), None))
        self.assertFalse(
            self.compressor.embeddable(_('pipeline/images/arrow.png'),
                                       'datauri'))
        self.assertTrue(
            self.compressor.embeddable(_('pipeline/images/embed/arrow.png'),
                                       'datauri'))
        self.assertFalse(
            self.compressor.embeddable(_('pipeline/images/arrow.dat'),
                                       'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path(
            "../../images/sprite.png", "css/plugins/gallery.css",
            "css/gallery.css")
        self.assertEqual(asset_path, "../images/sprite.png")
        asset_path = self.compressor.construct_asset_path(
            "/images/sprite.png", "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/urls.css'),
        ], 'css/screen.css')
        self.assertEqual(
            """@font-face {
  font-family: 'Pipeline';
  src: url(../pipeline/fonts/pipeline.eot);
  src: url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(../pipeline/fonts/pipeline.woff) format('woff'), url(../pipeline/fonts/pipeline.ttf) format('truetype'), url(../pipeline/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(../pipeline/images/sprite-buttons.png);
}
.relative-url-querystring {
  background-image: url(../pipeline/images/sprite-buttons.png?v=1.0#foo=bar);
}
.absolute-url {
  background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)

    def test_compressor_subprocess_unicode(self):
        tests_path = os.path.dirname(os.path.dirname(__file__))
        output = SubProcessCompressor(False).execute_command(
            '/usr/bin/env cat',
            open(tests_path + '/assets/css/unicode.css').read())
        self.assertEqual(
            """.some_class {
  // Some unicode
  content: "áéíóú";
}
""", output)
예제 #15
0
 def setUp(self):
     self.compressor = Compressor()
     self.old_pipeline_url = settings.PIPELINE_URL
     self.old_pipeline_root = settings.PIPELINE_ROOT
     settings.PIPELINE_URL = 'http://localhost/static/'
예제 #16
0
class CompressorTest(TestCase):
    def setUp(self):
        self.compressor = Compressor()
        self.old_pipeline_url = settings.PIPELINE_URL
        self.old_pipeline_root = settings.PIPELINE_ROOT
        settings.PIPELINE_URL = 'http://localhost/static/'

    def test_js_compressor_class(self):
        self.assertEquals(self.compressor.js_compressor, YUICompressor)

    def test_css_compressor_class(self):
        self.assertEquals(self.compressor.css_compressor, YUICompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            'css/first.css',
            'css/second.css'
        ])
        self.assertEquals(""".concat {\n  display: none;\n}\n.concatenate {\n  display: block;\n}""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            'js/first.js',
            'js/second.js'
        ])
        self.assertEquals("""function concat() {\n  console.log(arguments);\n}\nfunction cat() {\n  console.log("hello world");\n}""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content('images/arrow.png')
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content('images/arrow.png')
        self.assertFalse(mock.called)

    def test_relative_path(self):
        settings.PIPELINE_ROOT = '/var/www/static/'
        relative_path = self.compressor.relative_path('/var/www/static/images/sprite.png')
        self.assertEquals(relative_path, '/images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path([
            'js/templates/form.jst', 'js/templates/field.jst'
        ])
        self.assertEquals(base_path, 'js/templates')

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path('../../images/sprite.png',
            'css/plugins/')
        self.assertEquals(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
            'css/plugins/')
        self.assertEquals(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEquals(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEquals(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
            'templates\\')
        self.assertEquals(name, 'photo_detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates(['templates/photo/list.jst'])
        self.assertEquals(templates, """window.JST = window.JST || {};\nwindow.JST['list'] = _.template('<div class="photo"> <img src="<%= src %>" /> <div class="caption">  <%= caption %> </div></div>');\n""")
        templates = self.compressor.compile_templates([
            'templates/video/detail.jst',
            'templates/photo/detail.jst'
        ])
        self.assertEqual(templates, """window.JST = window.JST || {};\nwindow.JST['video_detail'] = _.template('<div class="video"> <video src="<%= src %>" /> <div class="caption">  <%= description %> </div></div>');\nwindow.JST[\'photo_detail\'] = _.template(\'<div class="photo"> <img src="<%= src %>" /> <div class="caption">  <%= caption %> by <%= author %> </div></div>\');\n""")

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable('images/sprite.png', None))
        self.assertFalse(self.compressor.embeddable('images/arrow.png', 'datauri'))
        self.assertTrue(self.compressor.embeddable('images/embed/arrow.png', 'datauri'))
        self.assertFalse(self.compressor.embeddable('images/arrow.dat', 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
    
    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_construct_asset_path_windows(self):
        asset_path = self.compressor.construct_asset_path("\image\sprite.png",
            "css\plugins\gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")

    def test_construct_asset_path_relative(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css",
            absolute_asset_paths=False)
        self.assertEquals(asset_path, "../../images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css",
            absolute_asset_paths=False)
        self.assertEquals(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        self.maxDiff = None
        output = self.compressor.concatenate_and_rewrite([
            'css/urls.css',
        ])
        self.assertMultiLineEqual("""@font-face {
  font-family: 'Pipeline';
  src: url(http://localhost/static/fonts/pipeline.eot);
  src: url(http://localhost/static/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(http://localhost/static/fonts/pipeline.woff) format('woff'), url(http://localhost/static/fonts/pipeline.ttf) format('truetype'), url(http://localhost/static/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)

    def tearDown(self):
        settings.PIPELINE_URL = self.old_pipeline_url
        settings.PIPELINE_ROOT = self.old_pipeline_root
예제 #17
0
class CompressorTest(TestCase):
    def setUp(self):
        self.compressor = Compressor()
        self.old_pipeline_url = settings.PIPELINE_URL
        self.old_pipeline_root = settings.PIPELINE_ROOT
        settings.PIPELINE_URL = 'http://localhost/static/'

    def test_js_compressor_class(self):
        self.assertEquals(self.compressor.js_compressor, YUICompressor)

    def test_css_compressor_class(self):
        self.assertEquals(self.compressor.css_compressor, YUICompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            'css/first.css',
            'css/second.css'
        ])
        self.assertEquals(""".concat {\n  display: none;\n}\n.concatenate {\n  display: block;\n}""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            'js/first.js',
            'js/second.js'
        ])
        self.assertEquals("""function concat() {\n  console.log(arguments);\n}\nfunction cat() {\n  console.log("hello world");\n}""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content('images/arrow.png')
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content('images/arrow.png')
        self.assertFalse(mock.called)

    def test_relative_path(self):
        settings.PIPELINE_ROOT = '/var/www/static/'
        relative_path = self.compressor.relative_path('/var/www/static/images/sprite.png')
        self.assertEquals(relative_path, '/images/sprite.png')

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path('../../images/sprite.png',
            'css/plugins/gallery.css')
        self.assertEquals(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
            'css/plugins/gallery.css')
        self.assertEquals(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEquals(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEquals(name, 'photo_edit')

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable('images/sprite.png', None))
        self.assertFalse(self.compressor.embeddable('images/arrow.png', 'datauri'))
        self.assertTrue(self.compressor.embeddable('images/embed/arrow.png', 'datauri'))
        self.assertFalse(self.compressor.embeddable('images/arrow.dat', 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")

    def test_url_rewrite(self):
        self.maxDiff = None
        output = self.compressor.concatenate_and_rewrite([
            'css/urls.css',
        ])
        self.assertMultiLineEqual("""@font-face {
  font-family: 'Pipeline';
  src: url(http://localhost/static/fonts/pipeline.eot);
  src: url(http://localhost/static/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(http://localhost/static/fonts/pipeline.woff) format('woff'), url(http://localhost/static/fonts/pipeline.ttf) format('truetype'), url(http://localhost/static/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)

    def tearDown(self):
        settings.PIPELINE_URL = self.old_pipeline_url
        settings.PIPELINE_ROOT = self.old_pipeline_root
class CompressorTest(TestCase):
    def setUp(self):
        self.maxDiff = None
        self.compressor = Compressor()

    def test_js_compressor_class(self):
        self.assertEqual(self.compressor.js_compressor, YuglifyCompressor)

    def test_css_compressor_class(self):
        self.assertEqual(self.compressor.css_compressor, YuglifyCompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/first.css'),
            _('pipeline/css/second.css')
        ], 'css/screen.css')
        self.assertEqual(""".concat {\n  display: none;\n}\n\n.concatenate {\n  display: block;\n}\n""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            _('pipeline/js/first.js'),
            _('pipeline/js/second.js')
        ])
        self.assertEqual("""function concat() {\n  console.log(arguments);\n}\n\nfunction cat() {\n  console.log("hello world");\n}\n""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertFalse(mock.called)

    def test_relative_path(self):
        relative_path = self.compressor.relative_path("images/sprite.png", 'css/screen.css')
        self.assertEqual(relative_path, '../images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path([
            _('js/templates/form.jst'), _('js/templates/field.jst')
        ])
        self.assertEqual(base_path, _('js/templates'))

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path('../../images/sprite.png',
            'css/plugins/')
        self.assertEqual(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
            'css/plugins/')
        self.assertEqual(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEqual(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
            'templates\\')
        self.assertEqual(name, 'photo_detail')

    @override_settings(PIPELINE_TEMPLATE_SEPARATOR='/')
    def test_template_name_separator(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEqual(name, 'photo/detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
            'templates\\')
        self.assertEqual(name, 'photo/detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates([_('pipeline/templates/photo/list.jst')])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'list\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)
        templates = self.compressor.compile_templates([
            _('pipeline/templates/video/detail.jst'),
            _('pipeline/templates/photo/detail.jst')
        ])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'video_detail\'] = template(\'<div class="video">\\n <video src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= description %%>\\n </div>\\n</div>\');\nwindow.JST[\'photo_detail\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%> by <%%= author %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/sprite.png'), None))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.png'), 'datauri'))
        self.assertTrue(self.compressor.embeddable(_('pipeline/images/embed/arrow.png'), 'datauri'))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.dat'), 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "../images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/urls.css'),
        ], 'css/screen.css')
        self.assertEqual("""@font-face {
  font-family: 'Pipeline';
  src: url(../pipeline/fonts/pipeline.eot);
  src: url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(../pipeline/fonts/pipeline.woff) format('woff'), url(../pipeline/fonts/pipeline.ttf) format('truetype'), url(../pipeline/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(../pipeline/images/sprite-buttons.png);
}
.relative-url-querystring {
  background-image: url(../pipeline/images/sprite-buttons.png?v=1.0#foo=bar);
}
.absolute-url {
  background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}
""", output)

    def test_url_rewrite_data_uri(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/nested/nested.css'),
        ], 'pipeline/screen.css')
        self.assertEqual(""".data-url {
  background-image: url(data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E);
}
""", output)

    def test_compressor_subprocess_unicode(self):
        tests_path = os.path.dirname(os.path.dirname(__file__))
        output = SubProcessCompressor(False).execute_command(
            '/usr/bin/env cat',
            open(tests_path + '/assets/css/unicode.css').read())
        self.assertEqual(""".some_class {
  // Some unicode
  content: "áéíóú";
}
""", output)
예제 #19
0
 def setUp(self):
     self.compressor = Compressor()
예제 #20
0
class CompressorTest(TestCase):
    def setUp(self):
        self.maxDiff = None
        self.compressor = Compressor()

    def test_js_compressor_class(self):
        self.assertEqual(self.compressor.js_compressor, YuglifyCompressor)

    def test_css_compressor_class(self):
        self.assertEqual(self.compressor.css_compressor, YuglifyCompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/first.css'),
            _('pipeline/css/second.css')
        ], 'css/screen.css')
        self.assertEqual(""".concat {\n  display: none;\n}\n\n.concatenate {\n  display: block;\n}\n""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            _('pipeline/js/first.js'),
            _('pipeline/js/second.js')
        ])
        self.assertEqual("""function concat() {\n  console.log(arguments);\n}\n\nfunction cat() {\n  console.log("hello world");\n}\n""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertFalse(mock.called)

    def test_relative_path(self):
        relative_path = self.compressor.relative_path("images/sprite.png", 'css/screen.css')
        self.assertEqual(relative_path, '../images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path([
            _('js/templates/form.jst'), _('js/templates/field.jst')
        ])
        self.assertEqual(base_path, _('js/templates'))

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path('../../images/sprite.png',
            'css/plugins/')
        self.assertEqual(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
            'css/plugins/')
        self.assertEqual(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEqual(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
            'templates\\')
        self.assertEqual(name, 'photo_detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates([_('pipeline/templates/photo/list.jst')])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'list\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)
        templates = self.compressor.compile_templates([
            _('pipeline/templates/video/detail.jst'),
            _('pipeline/templates/photo/detail.jst')
        ])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'video_detail\'] = template(\'<div class="video">\\n <video src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= description %%>\\n </div>\\n</div>\');\nwindow.JST[\'photo_detail\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%> by <%%= author %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/sprite.png'), None))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.png'), 'datauri'))
        self.assertTrue(self.compressor.embeddable(_('pipeline/images/embed/arrow.png'), 'datauri'))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.dat'), 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "../images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "/images/sprite.png")

    def test_compress_js(self):
        with patch.object(self.compressor.js_compressor, 'compress_js') as mock_method:
            paths = []
            mock_method.return_value = 'asdf'
            (js, source_map) = self.compressor.compress_js(paths)
            self.assertEqual(js, 'asdf')
            self.assertEqual(source_map, '')
            mock_method.assert_called_with(u'(function() {  }).call(this);')

    @patch('pipeline.compressors.yuglify.YuglifyCompressor')
    def test_compress_js_with_source_map(self, mock_constructor):
        mock_js_compressor = MagicMock()
        mock_constructor.return_value = mock_js_compressor
        mock_js_compressor.compress_js_with_source_map.return_value = ['code', 'map']

        paths = [
            _('pipeline/js/first.js'),
            _('pipeline/js/second.js')
        ]
        (js, source_map) = self.compressor.compress_js(paths, source_map_filename='map.js')
        self.assertEqual(js, 'code')
        self.assertEqual(source_map, 'map')
        call = mock_js_compressor.compress_js_with_source_map.call_args_list[0]
        call_args = call[0]
        self.assertRegexpMatches(call_args[0][0], 'first.js')
        self.assertRegexpMatches(call_args[0][1], 'second.js')
        self.assertEquals(call_args[1], 'map.js')
        self.assertEquals(call_args[2], '/static/')
        self.assertEquals(call_args[3], 'tests/static/')

    # Uncomment if you need a fully working version
    # May also need to tweak pipeline/conf/settings.py to point to real uglify binary
    # @patch('pipeline.compressors.yuglify.YuglifyCompressor')
    # def test_compress_js_with_source_map_real(self, mock_constructor):
    #     mock_constructor.return_value = UglifyJSCompressor(False)

    #     paths = [
    #         _('pipeline/js/first.js'),
    #         _('pipeline/js/second.js')
    #     ]
    #     (js, source_map) = self.compressor.compress_js(paths, source_map_filename='wakawaka.js')
    #     self.assertRegexpMatches(js, 'function concat.*function cat')
    #     self.assertRegexpMatches(js, '@ sourceMappingURL=/static/wakawaka.js') # Bunch of newlines..easier to do 2 asserts
    #     self.assertTrue(len(source_map) > 0)

    @patch('pipeline.compressors.yuglify.YuglifyCompressor')
    def test_compress_js_with_source_map_on_non_compatible_compressor(self, mock_constructor):
        mock_js_compressor = MagicMock()
        mock_constructor.return_value = mock_js_compressor
        del mock_js_compressor.compress_js_with_source_map

        with self.assertRaisesRegexp(CompressorError, 'cannot make source maps'):
            self.compressor.compress_js([], source_map_filename='map.js')

    @patch('pipeline.compressors.yuglify.YuglifyCompressor')
    def test_compress_js_with_source_map_and_templates(self, mock_constructor):
        mock_js_compressor = MagicMock()
        mock_constructor.return_value = mock_js_compressor

        with self.assertRaisesRegexp(CompressorError, 'Templates cannot be part of a group'):
            self.compressor.compress_js([], source_map_filename='map.js', templates=['foo.jst'])

    def test_url_rewrite(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/urls.css'),
        ], 'css/screen.css')
        self.assertEqual("""@font-face {
  font-family: 'Pipeline';
  src: url(../pipeline/fonts/pipeline.eot);
  src: url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(../pipeline/fonts/pipeline.woff) format('woff'), url(../pipeline/fonts/pipeline.ttf) format('truetype'), url(../pipeline/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(../pipeline/images/sprite-buttons.png);
}
.relative-url-querystring {
  background-image: url(../pipeline/images/sprite-buttons.png?v=1.0#foo=bar);
}
.absolute-url {
  background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)
예제 #21
0
class Packager(object):
    def __init__(self,
                 storage=default_storage,
                 verbose=False,
                 css_packages=None,
                 js_packages=None):
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(verbose=verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" %
                (kind, package_name))

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(package,
                         self.compressor.compress_css,
                         css_compressed,
                         output_filename=package.output_filename,
                         variant=package.variant,
                         **kwargs)

    def compile(self, paths, force=False):
        return self.compiler.compile(paths, force=force)

    def pack(self, package, compress, signal, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print("Saving: %s" % output_filename)
        paths = self.compile(package.paths, force=True)
        content = compress(paths, **kwargs)
        self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package,
                         self.compressor.compress_js,
                         js_compressed,
                         templates=package.templates,
                         **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_str(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #22
0
class Packager(object):
    def __init__(self, storage=None, verbose=False, css_packages=None, js_packages=None):
        if storage is None:
            storage = staticfiles_storage
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(storage=storage, verbose=verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" % (
                    kind, package_name
                )
            )

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_css, css_compressed,
                         output_filename=package.output_filename,
                         variant=package.variant, **kwargs)

    def compile(self, paths, force=False):
        paths = self.compiler.compile(paths, force=force)
        for path in paths:
            if not self.storage.exists(path):
                if self.verbose:
                    print("Compiled file '%s' cannot be found with packager's storage. Locating it." % path)

                source_storage = self.find_source_storage(path)
                if source_storage is not None:
                    with source_storage.open(path) as source_file:
                        if self.verbose:
                            print("Saving: %s" % path)
                        self.storage.save(path, source_file)
                else:
                    raise IOError("File does not exist: %s" % path)
        return paths

    def pack(self, package, compress, signal, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print("Saving: %s" % output_filename)
        paths = self.compile(package.paths, force=True)
        content = compress(paths, **kwargs)
        self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_js, js_compressed, templates=package.templates, **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_bytes(content)))

    def find_source_storage(self, path):
        for finder in get_finders():
            for short_path, storage in finder.list(''):
                if short_path == path:
                    if self.verbose:
                        print("Found storage: %s" % str(self.storage))
                    return storage
        return None

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #23
0
class Packager(object):
    def __init__(self, verbose=False, css_packages=None, js_packages=None):
        self.verbose = verbose
        self.compressor = Compressor(verbose)
        self.versioning = Versioning(verbose)
        self.compiler = Compiler(verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name].copy()
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" %
                (kind, package_name))

    def individual_url(self, filename):
        relative_path = self.compressor.relative_path(filename)[1:]
        return urlparse.urljoin(settings.PIPELINE_URL,
                                filepath_to_uri(relative_path))

    def pack_stylesheets(self, package, **kwargs):
        variant = package.get('variant', None)
        absolute_asset_paths = package.get('absolute_asset_paths', True)
        return self.pack(package,
                         self.compressor.compress_css,
                         css_compressed,
                         variant=variant,
                         absolute_asset_paths=absolute_asset_paths,
                         **kwargs)

    def compile(self, paths):
        return self.compiler.compile(paths)

    def pack(self,
             package,
             compress,
             signal,
             sync=False,
             force=False,
             **kwargs):
        if settings.PIPELINE_AUTO or (force and sync):
            need_update, version = self.versioning.need_update(
                package['output'], package['paths'])
            if need_update or force:
                output_filename = self.versioning.output_filename(
                    package['output'], version)
                self.versioning.cleanup(package['output'])
                if self.verbose:
                    print "Version: %s" % version
                    print "Saving: %s" % output_filename
                paths = self.compile(package['paths'])
                content = compress(
                    paths,
                    asset_url=self.individual_url(output_filename),
                    **kwargs)
                self.save_file(output_filename, content)
        else:
            filename_base, filename = os.path.split(package['output'])
            version = self.versioning.version_from_file(filename_base,
                                                        filename,
                                                        force=force)
        signal.send(sender=self, package=package, version=version, **kwargs)
        return self.versioning.output_filename(package['output'], version)

    def pack_javascripts(self, package, **kwargs):
        if 'externals' in package:
            return
        return self.pack(package,
                         self.compressor.compress_js,
                         js_compressed,
                         templates=package['templates'],
                         **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package['templates'])

    def save_file(self, path, content):
        return storage.save(path, ContentFile(smart_str(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = {}
            if 'external_urls' in config[name]:
                packages[name]['externals'] = config[name]['external_urls']
                continue
            paths = []
            for pattern in config[name]['source_filenames']:
                for path in glob(pattern):
                    if not path in paths:
                        paths.append(str(path))
            packages[name]['paths'] = [
                path for path in paths
                if not path.endswith(settings.PIPELINE_TEMPLATE_EXT)
            ]
            packages[name]['templates'] = [
                path for path in paths
                if path.endswith(settings.PIPELINE_TEMPLATE_EXT)
            ]
            packages[name]['output'] = config[name]['output_filename']
            packages[name]['context'] = {}
            packages[name]['manifest'] = True
            if 'absolute_asset_paths' in config[name]:
                packages[name]['absolute_asset_paths'] = \
                    config[name]['absolute_asset_paths']
            if 'extra_context' in config[name]:
                packages[name]['context'] = config[name]['extra_context']
            if 'template_name' in config[name]:
                packages[name]['template'] = config[name]['template_name']
            if 'variant' in config[name]:
                packages[name]['variant'] = config[name]['variant']
            if 'manifest' in config[name]:
                packages[name]['manifest'] = config[name]['manifest']
        return packages
예제 #24
0
class CompressorTest(TestCase):
    def setUp(self):
        self.maxDiff = None
        self.compressor = Compressor()

    def test_js_compressor_class(self):
        self.assertEqual(self.compressor.js_compressor, YuglifyCompressor)

    def test_css_compressor_class(self):
        self.assertEqual(self.compressor.css_compressor, YuglifyCompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/first.css'),
            _('pipeline/css/second.css')
        ], 'css/screen.css')
        self.assertEqual(""".concat {\n  display: none;\n}\n\n.concatenate {\n  display: block;\n}\n""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            _('pipeline/js/first.js'),
            _('pipeline/js/second.js')
        ])
        self.assertEqual("""function concat() {\n  console.log(arguments);\n}\n\nfunction cat() {\n  console.log("hello world");\n}\n""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertFalse(mock.called)

    def test_relative_path(self):
        relative_path = self.compressor.relative_path("images/sprite.png", 'css/screen.css')
        self.assertEqual(relative_path, '../images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path([
            _('js/templates/form.jst'), _('js/templates/field.jst')
        ])
        self.assertEqual(base_path, _('js/templates'))

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path('../../images/sprite.png',
            'css/plugins/')
        self.assertEqual(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
            'css/plugins/')
        self.assertEqual(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEqual(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
            'templates\\')
        self.assertEqual(name, 'photo_detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates([_('pipeline/templates/photo/list.jst')])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'list\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)
        templates = self.compressor.compile_templates([
            _('pipeline/templates/video/detail.jst'),
            _('pipeline/templates/photo/detail.jst')
        ])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'video_detail\'] = template(\'<div class="video">\\n <video src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= description %%>\\n </div>\\n</div>\');\nwindow.JST[\'photo_detail\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%> by <%%= author %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/sprite.png'), None))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.png'), 'datauri'))
        self.assertTrue(self.compressor.embeddable(_('pipeline/images/embed/arrow.png'), 'datauri'))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.dat'), 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "../images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/urls.css'),
        ], 'css/screen.css')
        self.assertEqual("""@font-face {
  font-family: 'Pipeline';
  src: url(../pipeline/fonts/pipeline.eot);
  src: url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(../pipeline/fonts/pipeline.woff) format('woff'), url(../pipeline/fonts/pipeline.ttf) format('truetype'), url(../pipeline/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(../pipeline/images/sprite-buttons.png);
}
.relative-url-querystring {
  background-image: url(../pipeline/images/sprite-buttons.png?v=1.0#foo=bar);
}
.absolute-url {
  background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)
예제 #25
0
class CompressorTest(TestCase):
    def setUp(self):
        self.compressor = Compressor()
        self.old_pipeline_url = settings.PIPELINE_URL
        self.old_pipeline_root = settings.PIPELINE_ROOT
        settings.PIPELINE_URL = 'http://localhost/static/'

    def test_js_compressor_class(self):
        self.assertEquals(self.compressor.js_compressor, YUICompressor)

    def test_css_compressor_class(self):
        self.assertEquals(self.compressor.css_compressor, YUICompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            'css/first.css',
            'css/second.css'
        ])
        self.assertEquals(""".concat {\n  display: none;\n}\n.concatenate {\n  display: block;\n}""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            'js/first.js',
            'js/second.js'
        ])
        self.assertEquals("""function concat() {\n  console.log(arguments);\n}\nfunction cat() {\n  console.log("hello world");\n}""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.encoded_content('images/arrow.png')
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content('images/arrow.png')
        self.assertFalse(mock.called)

    def test_relative_path(self):
        settings.PIPELINE_ROOT = '/var/www/static/'
        relative_path = self.compressor.relative_path('/var/www/static/images/sprite.png')
        self.assertEquals(relative_path, '/images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path([
            'js/templates/form.jst', 'js/templates/field.jst'
        ])
        self.assertEquals(base_path, 'js/templates')

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path('../../images/sprite.png',
            'css/plugins/')
        self.assertEquals(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
            'css/plugins/')
        self.assertEquals(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
            'templates/')
        self.assertEquals(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEquals(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
            'templates\\')
        self.assertEquals(name, 'photo_detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates(['templates/photo/list.jst'])
        self.assertEquals(templates, """window.JST = window.JST || {};\nwindow.JST['list'] = _.template('<div class="photo"> <img src="<%= src %>" /> <div class="caption">  <%= caption %> </div></div>');\n""")
        templates = self.compressor.compile_templates([
            'templates/video/detail.jst',
            'templates/photo/detail.jst'
        ])
        self.assertEqual(templates, """window.JST = window.JST || {};\nwindow.JST['video_detail'] = _.template('<div class="video"> <video src="<%= src %>" /> <div class="caption">  <%= description %> </div></div>');\nwindow.JST[\'photo_detail\'] = _.template(\'<div class="photo"> <img src="<%= src %>" /> <div class="caption">  <%= caption %> by <%= author %> </div></div>\');\n""")

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable('images/sprite.png', None))
        self.assertFalse(self.compressor.embeddable('images/arrow.png', 'datauri'))
        self.assertTrue(self.compressor.embeddable('images/embed/arrow.png', 'datauri'))
        self.assertFalse(self.compressor.embeddable('images/arrow.dat', 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
    
    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_construct_asset_path_windows(self):
        asset_path = self.compressor.construct_asset_path("\image\sprite.png",
            "css\plugins\gallery.css")
        self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")

    def test_construct_asset_path_relative(self):
        asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
            "css/plugins/gallery.css",
            absolute_asset_paths=False)
        self.assertEquals(asset_path, "../../images/sprite.png")
        asset_path = self.compressor.construct_asset_path("/images/sprite.png",
            "css/plugins/gallery.css",
            absolute_asset_paths=False)
        self.assertEquals(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        self.maxDiff = None
        output = self.compressor.concatenate_and_rewrite([
            'css/urls.css',
        ])
        self.assertMultiLineEqual("""@font-face {
  font-family: 'Pipeline';
  src: url(http://localhost/static/fonts/pipeline.eot);
  src: url(http://localhost/static/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(http://localhost/static/fonts/pipeline.woff) format('woff'), url(http://localhost/static/fonts/pipeline.ttf) format('truetype'), url(http://localhost/static/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-url {
  background-image: url(http://localhost/static/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}""", output)

    def tearDown(self):
        settings.PIPELINE_URL = self.old_pipeline_url
        settings.PIPELINE_ROOT = self.old_pipeline_root
예제 #26
0
class Packager(object):
    def __init__(self, storage=None, verbose=False, css_packages=None, js_packages=None):
        if storage is None:
            storage = staticfiles_storage
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(storage=storage, verbose=verbose)
        if css_packages is None:
            css_packages = settings.STYLESHEETS
        if js_packages is None:
            js_packages = settings.JAVASCRIPT
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" % (
                    kind, package_name
                )
            )

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_css, css_compressed,
                         output_filename=package.output_filename,
                         variant=package.variant, **kwargs)

    def compile(self, paths, compiler_options={}, force=False):
        return self.compiler.compile(
            paths,
            compiler_options=compiler_options,
            force=force,
        )

    def pack(self, package, compress, signal, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print("Saving: %s" % output_filename)
        paths = self.compile(
            package.paths,
            compiler_options=package.compiler_options,
            force=True,
        )
        output_path = self.storage.path(output_filename)
        output_mtime = self.storage.get_modified_time(output_path)
        if any([self.storage.get_modified_time(self.storage.path(path)) >=
                output_mtime for path in paths]):
            content = compress(paths, **kwargs)
            self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_js, js_compressed, templates=package.templates, **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_bytes(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #27
0
class CompressorImplementationTest(TestCase):

    maxDiff = None

    def setUp(self):
        self.compressor = Compressor()
        default_collector.collect(RequestFactory().get('/'))

    def tearDown(self):
        default_collector.clear()

    def _test_compressor(self, compressor_cls, compress_type, expected_file):
        override_settings = {
            ("%s_COMPRESSOR" % compress_type.upper()): compressor_cls,
        }
        with pipeline_settings(**override_settings):
            if compress_type == 'js':
                result = self.compressor.compress_js(
                    [_('pipeline/js/first.js'), _('pipeline/js/second.js')])
            else:
                result = self.compressor.compress_css(
                    [_('pipeline/css/first.css'), _('pipeline/css/second.css')],
                    os.path.join('pipeline', 'css', os.path.basename(expected_file)))
        with self.compressor.storage.open(expected_file) as f:
            expected = f.read()
        self.assertEqual(smart_bytes(result), expected)

    def test_jsmin(self):
        self._test_compressor('pipeline.compressors.jsmin.JSMinCompressor',
            'js', 'pipeline/compressors/jsmin.js')

    def test_slimit(self):
        self._test_compressor('pipeline.compressors.slimit.SlimItCompressor',
            'js', 'pipeline/compressors/slimit.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_uglifyjs(self):
        self._test_compressor('pipeline.compressors.uglifyjs.UglifyJSCompressor',
            'js', 'pipeline/compressors/uglifyjs.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_yuglify_js(self):
        self._test_compressor('pipeline.compressors.yuglify.YuglifyCompressor',
            'js', 'pipeline/compressors/yuglify.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_yuglify_css(self):
        self._test_compressor('pipeline.compressors.yuglify.YuglifyCompressor',
            'css', 'pipeline/compressors/yuglify.css')

    @skipUnless(settings.HAS_NODE, "requires node")
    def test_cssmin(self):
        self._test_compressor('pipeline.compressors.cssmin.CSSMinCompressor',
            'css', 'pipeline/compressors/cssmin.css')

    @skipUnless(settings.HAS_NODE, "requires node")
    @skipUnless(settings.HAS_JAVA, "requires java")
    def test_closure(self):
        self._test_compressor('pipeline.compressors.closure.ClosureCompressor',
            'js', 'pipeline/compressors/closure.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    @skipUnless(settings.HAS_JAVA, "requires java")
    def test_yui_js(self):
        self._test_compressor('pipeline.compressors.yui.YUICompressor',
            'js', 'pipeline/compressors/yui.js')

    @skipUnless(settings.HAS_NODE, "requires node")
    @skipUnless(settings.HAS_JAVA, "requires java")
    def test_yui_css(self):
        self._test_compressor('pipeline.compressors.yui.YUICompressor',
            'css', 'pipeline/compressors/yui.css')

    @skipUnless(settings.HAS_CSSTIDY, "requires csstidy")
    def test_csstidy(self):
        self._test_compressor('pipeline.compressors.csstidy.CSSTidyCompressor',
            'css', 'pipeline/compressors/csstidy.css')
예제 #28
0
class Packager(object):
    def __init__(self, verbose=False, css_packages=None, js_packages=None):
        self.verbose = verbose
        self.compressor = Compressor(verbose)
        self.versioning = Versioning(verbose)
        self.compiler = Compiler(verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name].copy()
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" % (
                    kind, package_name
                )
            )

    def individual_url(self, filename):
        relative_path = self.compressor.relative_path(filename)[1:]
        return urlparse.urljoin(settings.PIPELINE_URL,
            filepath_to_uri(relative_path))

    def pack_stylesheets(self, package, **kwargs):
        variant = package.get('variant', None)
        absolute_asset_paths = package.get('absolute_asset_paths', True)
        return self.pack(package, self.compressor.compress_css, css_compressed,
            variant=variant, absolute_asset_paths=absolute_asset_paths,
            **kwargs)

    def compile(self, paths):
        return self.compiler.compile(paths)

    def pack(self, package, compress, signal, sync=False, force=False, **kwargs):
        if settings.PIPELINE_AUTO or (force and sync):
            need_update, version = self.versioning.need_update(
                package['output'], package['paths'])
            if need_update or force:
                output_filename = self.versioning.output_filename(
                    package['output'],
                    version
                )
                self.versioning.cleanup(package['output'])
                if self.verbose:
                    print "Version: %s" % version
                    print "Saving: %s" % output_filename
                paths = self.compile(package['paths'])
                content = compress(paths,
                    asset_url=self.individual_url(output_filename), **kwargs)
                self.save_file(output_filename, content)
        else:
            filename_base, filename = os.path.split(package['output'])
            version = self.versioning.version_from_file(filename_base, filename, force=force)
        signal.send(sender=self, package=package, version=version, **kwargs)
        return self.versioning.output_filename(package['output'], version)

    def pack_javascripts(self, package, **kwargs):
        if 'externals' in package:
            return
        return self.pack(package, self.compressor.compress_js, js_compressed, templates=package['templates'], **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package['templates'])

    def save_file(self, path, content):
        return storage.save(path, ContentFile(smart_str(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = {}
            if 'external_urls' in config[name]:
                packages[name]['externals'] = config[name]['external_urls']
                continue
            paths = []
            for pattern in config[name]['source_filenames']:
                for path in glob(pattern):
                    if not path in paths:
                        paths.append(str(path))
            packages[name]['paths'] = [path for path in paths if not path.endswith(settings.PIPELINE_TEMPLATE_EXT)]
            packages[name]['templates'] = [path for path in paths if path.endswith(settings.PIPELINE_TEMPLATE_EXT)]
            packages[name]['output'] = config[name]['output_filename']
            packages[name]['context'] = {}
            packages[name]['manifest'] = True
            if 'absolute_asset_paths' in config[name]:
                packages[name]['absolute_asset_paths'] = \
                    config[name]['absolute_asset_paths']
            if 'extra_context' in config[name]:
                packages[name]['context'] = config[name]['extra_context']
            if 'template_name' in config[name]:
                packages[name]['template'] = config[name]['template_name']
            if 'variant' in config[name]:
                packages[name]['variant'] = config[name]['variant']
            if 'manifest' in config[name]:
                packages[name]['manifest'] = config[name]['manifest']
        return packages
예제 #29
0
class CompressorTest(TestCase):
    def setUp(self):
        self.maxDiff = None
        self.compressor = Compressor()
        default_collector.collect()

    def test_js_compressor_class(self):
        self.assertEqual(self.compressor.js_compressor, YuglifyCompressor)

    def test_css_compressor_class(self):
        self.assertEqual(self.compressor.css_compressor, YuglifyCompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/first.css'),
            _('pipeline/css/second.css')
        ], 'css/screen.css')
        self.assertEqual(""".concat {\n  display: none;\n}\n\n.concatenate {\n  display: block;\n}\n""", css)

    def test_concatenate(self):
        js = self.compressor.concatenate([
            _('pipeline/js/first.js'),
            _('pipeline/js/second.js')
        ])
        self.assertEqual("""(function() {\n  window.concat = function() {\n    console.log(arguments);\n  }\n}()) // No semicolon\n\n;(function() {\n  window.cat = function() {\n    console.log("hello world");\n  }\n}());\n""", js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.asset_contents.clear()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertFalse(mock.called)

    def test_encoded_content_output(self):
        self.compressor.asset_contents.clear()
        encoded = self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        expected = ('iVBORw0KGgoAAAANSUhEUgAAAAkAAAAGCAYAAAARx7TFAAAAMk'
                    'lEQVR42oXKwQkAMAxC0Q7rEk5voSEepCHC9/SOpLV3JPULgArV'
                    'RtDIMEEiQ4NECRNdciCfK3K3wvEAAAAASUVORK5CYII=')
        self.assertEqual(encoded, expected)

    def test_relative_path(self):
        relative_path = self.compressor.relative_path("images/sprite.png", 'css/screen.css')
        self.assertEqual(relative_path, '../images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path([
            _('js/templates/form.jst'), _('js/templates/field.jst')
        ])
        self.assertEqual(base_path, _('js/templates'))

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path(
            '../../images/sprite.png', 'css/plugins/')
        self.assertEqual(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path(
            '/images/sprite.png', 'css/plugins/')
        self.assertEqual(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name(
            'templates/photo/detail.jst', 'templates/')
        self.assertEqual(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name(
            'templates\photo\detail.jst', 'templates\\')
        self.assertEqual(name, 'photo_detail')

    @pipeline_settings(TEMPLATE_SEPARATOR='/')
    def test_template_name_separator(self):
        name = self.compressor.template_name(
            'templates/photo/detail.jst', 'templates/')
        self.assertEqual(name, 'photo/detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name(
            'templates\photo\detail.jst', 'templates\\')
        self.assertEqual(name, 'photo/detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates([_('pipeline/templates/photo/list.jst')])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'list\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)
        templates = self.compressor.compile_templates([
            _('pipeline/templates/video/detail.jst'),
            _('pipeline/templates/photo/detail.jst')
        ])
        self.assertEqual(templates, """window.JST = window.JST || {};\n%s\nwindow.JST[\'video_detail\'] = template(\'<div class="video">\\n <video src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= description %%>\\n </div>\\n</div>\');\nwindow.JST[\'photo_detail\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%> by <%%= author %%>\\n </div>\\n</div>\');\n""" % TEMPLATE_FUNC)

    def test_embeddable(self):
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/sprite.png'), None))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.png'), 'datauri'))
        self.assertTrue(self.compressor.embeddable(_('pipeline/images/embed/arrow.png'), 'datauri'))
        self.assertFalse(self.compressor.embeddable(_('pipeline/images/arrow.dat'), 'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path(
            "../../images/sprite.png", "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "../images/sprite.png")
        asset_path = self.compressor.construct_asset_path(
            "/images/sprite.png", "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/urls.css'),
        ], 'css/screen.css')
        self.assertEqual(""".embedded-url-svg {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath      stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%     3C/svg%3E");
}
@font-face {
  font-family: 'Pipeline';
  src: url(../pipeline/fonts/pipeline.eot);
  src: url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(../pipeline/fonts/pipeline.woff) format('woff'), url(../pipeline/fonts/pipeline.ttf) format('truetype'), url(../pipeline/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(../pipeline/images/sprite-buttons.png);
}
.relative-url-querystring {
  background-image: url(../pipeline/images/sprite-buttons.png?v=1.0#foo=bar);
}
.absolute-url {
  background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}
.anchor-tag-url {
  background-image: url(#image-gradient);
}
@font-face{src:url(../pipeline/fonts/pipeline.eot);src:url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype'),url(../pipeline/fonts/pipeline.woff) format('woff'),url(../pipeline/fonts/pipeline.ttf) format('truetype');}
""", output)

    def test_url_rewrite_data_uri(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/nested/nested.css'),
        ], 'pipeline/screen.css')
        self.assertEqual(""".data-url {
  background-image: url(data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E);
}
.data-url-quoted {
  background-image: url('data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E');
}
""", output)

    @skipIf(sys.platform.startswith("win"), "requires posix platform")
    def test_compressor_subprocess_unicode(self):
        path = os.path.dirname(os.path.dirname(__file__))
        content = io.open(path + '/assets/css/unicode.css', encoding="utf-8").read()
        output = SubProcessCompressor(False).execute_command(('cat',), content)
        self.assertEqual(""".some_class {
  // Some unicode
  content: "áéíóú";
}
""", output)

    def tearDown(self):
        default_collector.clear()
예제 #30
0
class Packager(object):
    def __init__(self, storage=default_storage, verbose=False, css_packages=None, js_packages=None):
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(verbose=verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" % (
                    kind, package_name
                )
            )

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_css, css_compressed,
                         '/*# sourceMappingURL={} */',
                         output_filename=package.output_filename,
                         variant=package.variant, **kwargs)

    def compile(self, paths, force=False):
        return self.compiler.compile(paths, force=force)

    def pack(self, package, compress, signal, source_mapping_template, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print("Saving: %s" % output_filename)
        paths = self.compile(package.paths, force=True)
        content, source_map = compress(paths, **kwargs)
        if source_map is not None:
            source_map_output_filename = output_filename + '.map'
            self.save_file(source_map_output_filename, source_map)
            content = content + '\n' + source_mapping_template.format(
                os.path.basename(source_map_output_filename))
        self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_js, js_compressed,
                         '//# sourceMappingURL={}',
                         templates=package.templates, **kwargs)

    def pack_templates(self, package):
        return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_str(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #31
0
class Packager(object):
    def __init__(self, storage=default_storage, verbose=False, css_packages=None, js_packages=None):
        self.storage = storage
        self.verbose = verbose
        self.compressor = Compressor(storage=storage, verbose=verbose)
        self.compiler = Compiler(verbose=verbose)
        if css_packages is None:
            css_packages = settings.PIPELINE_CSS
        if js_packages is None:
            js_packages = settings.PIPELINE_JS
        self.packages = {
            'css': self.create_packages(css_packages),
            'js': self.create_packages(js_packages),
        }

    def package_for(self, kind, package_name):
        try:
            return self.packages[kind][package_name]
        except KeyError:
            raise PackageNotFound(
                "No corresponding package for %s package name : %s" % (
                    kind, package_name
                )
            )

    def individual_url(self, filename):
        return self.storage.url(filename)

    def pack_stylesheets(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_css, css_compressed,
            output_filename=package.output_filename,
            variant=package.variant, **kwargs)

    def compile(self, paths, force=False):
        return self.compiler.compile(paths, force=force)

    def pack(self, package, compress, signal, **kwargs):
        output_filename = package.output_filename
        if self.verbose:
            print "Saving: %s" % output_filename
        paths = self.compile(package.paths, force=True)
        content = compress(paths, **kwargs)
        self.save_file(output_filename, content)
        signal.send(sender=self, package=package, **kwargs)
        return output_filename

    def pack_javascripts(self, package, **kwargs):
        return self.pack(package, self.compressor.compress_js, js_compressed, templates=package.templates, **kwargs)

    def pack_templates(self, package):
        if settings.PIPELINE_TEMPLATE_USE_CACHE and package.templates:
            key_partial = hashlib.md5()
            key_partial.update(str(package.templates))
            cache_key = "%s_%s"%(key_partial.hexdigest(), translation.get_language())
            default_cache = cache.get_cache('default')
            cached_package = default_cache.get(cache_key)
            if not cached_package:
                cached_package = self.compressor.compile_templates(package.templates)
                default_cache.set(cache_key, cached_package)
            return cached_package
        else:
            if self.verbose:
                print "Generating templates without using cache .."
            return self.compressor.compile_templates(package.templates)

    def save_file(self, path, content):
        return self.storage.save(path, ContentFile(smart_str(content)))

    def create_packages(self, config):
        packages = {}
        if not config:
            return packages
        for name in config:
            packages[name] = Package(config[name])
        return packages
예제 #32
0
 def setUp(self):
     self.compressor = Compressor()
     self.old_pipeline_url = settings.PIPELINE_URL
     self.old_pipeline_root = settings.PIPELINE_ROOT
     settings.PIPELINE_URL = 'http://localhost/static/'
예제 #33
0
 def setUp(self):
     self.compressor = Compressor()
     default_collector.collect(RequestFactory().get('/'))
예제 #34
0
 def setUp(self):
     self.compressor = Compressor()
     default_collector.collect(RequestFactory().get('/'))
예제 #35
0
class CompressorTest(TestCase):
    def setUp(self):
        self.maxDiff = None
        self.compressor = Compressor()
        default_collector.collect()

    def test_js_compressor_class(self):
        self.assertEqual(self.compressor.js_compressor, YuglifyCompressor)

    def test_css_compressor_class(self):
        self.assertEqual(self.compressor.css_compressor, YuglifyCompressor)

    def test_concatenate_and_rewrite(self):
        css = self.compressor.concatenate_and_rewrite(
            [_('pipeline/css/first.css'),
             _('pipeline/css/second.css')], 'css/screen.css')
        self.assertEqual(
            """.concat {\n  display: none;\n}\n\n.concatenate {\n  display: block;\n}\n""",
            css)

    def test_concatenate(self):
        js = self.compressor.concatenate(
            [_('pipeline/js/first.js'),
             _('pipeline/js/second.js')])
        self.assertEqual(
            """(function() {\n  window.concat = function() {\n    console.log(arguments);\n  }\n}()) // No semicolon\n\n;(function() {\n  window.cat = function() {\n    console.log("hello world");\n  }\n}());\n""",
            js)

    @patch.object(base64, 'b64encode')
    def test_encoded_content(self, mock):
        self.compressor.asset_contents.clear()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertTrue(mock.called)
        mock.reset_mock()
        self.compressor.encoded_content(_('pipeline/images/arrow.png'))
        self.assertFalse(mock.called)

    def test_encoded_content_output(self):
        self.compressor.asset_contents.clear()
        encoded = self.compressor.encoded_content(
            _('pipeline/images/arrow.png'))
        expected = ('iVBORw0KGgoAAAANSUhEUgAAAAkAAAAGCAYAAAARx7TFAAAAMk'
                    'lEQVR42oXKwQkAMAxC0Q7rEk5voSEepCHC9/SOpLV3JPULgArV'
                    'RtDIMEEiQ4NECRNdciCfK3K3wvEAAAAASUVORK5CYII=')
        self.assertEqual(encoded, expected)

    def test_relative_path(self):
        relative_path = self.compressor.relative_path("images/sprite.png",
                                                      'css/screen.css')
        self.assertEqual(relative_path, '../images/sprite.png')

    def test_base_path(self):
        base_path = self.compressor.base_path(
            [_('js/templates/form.jst'),
             _('js/templates/field.jst')])
        self.assertEqual(base_path, _('js/templates'))

    def test_absolute_path(self):
        absolute_path = self.compressor.absolute_path(
            '../../images/sprite.png', 'css/plugins/')
        self.assertEqual(absolute_path, 'images/sprite.png')
        absolute_path = self.compressor.absolute_path('/images/sprite.png',
                                                      'css/plugins/')
        self.assertEqual(absolute_path, '/images/sprite.png')

    def test_template_name(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
                                             'templates/')
        self.assertEqual(name, 'photo_detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
                                             'templates\\')
        self.assertEqual(name, 'photo_detail')

    @pipeline_settings(TEMPLATE_SEPARATOR='/')
    def test_template_name_separator(self):
        name = self.compressor.template_name('templates/photo/detail.jst',
                                             'templates/')
        self.assertEqual(name, 'photo/detail')
        name = self.compressor.template_name('templates/photo_edit.jst', '')
        self.assertEqual(name, 'photo_edit')
        name = self.compressor.template_name('templates\photo\detail.jst',
                                             'templates\\')
        self.assertEqual(name, 'photo/detail')

    def test_compile_templates(self):
        templates = self.compressor.compile_templates(
            [_('pipeline/templates/photo/list.jst')])
        self.assertEqual(
            templates,
            """window.JST = window.JST || {};\n%s\nwindow.JST[\'list\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%>\\n </div>\\n</div>\');\n"""
            % TEMPLATE_FUNC)
        templates = self.compressor.compile_templates([
            _('pipeline/templates/video/detail.jst'),
            _('pipeline/templates/photo/detail.jst')
        ])
        self.assertEqual(
            templates,
            """window.JST = window.JST || {};\n%s\nwindow.JST[\'video_detail\'] = template(\'<div class="video">\\n <video src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= description %%>\\n </div>\\n</div>\');\nwindow.JST[\'photo_detail\'] = template(\'<div class="photo">\\n <img src="<%%= src %%>" />\\n <div class="caption">\\n  <%%= caption %%> by <%%= author %%>\\n </div>\\n</div>\');\n"""
            % TEMPLATE_FUNC)

    def test_embeddable(self):
        self.assertFalse(
            self.compressor.embeddable(_('pipeline/images/sprite.png'), None))
        self.assertFalse(
            self.compressor.embeddable(_('pipeline/images/arrow.png'),
                                       'datauri'))
        self.assertTrue(
            self.compressor.embeddable(_('pipeline/images/embed/arrow.png'),
                                       'datauri'))
        self.assertFalse(
            self.compressor.embeddable(_('pipeline/images/arrow.dat'),
                                       'datauri'))

    def test_construct_asset_path(self):
        asset_path = self.compressor.construct_asset_path(
            "../../images/sprite.png", "css/plugins/gallery.css",
            "css/gallery.css")
        self.assertEqual(asset_path, "../images/sprite.png")
        asset_path = self.compressor.construct_asset_path(
            "/images/sprite.png", "css/plugins/gallery.css", "css/gallery.css")
        self.assertEqual(asset_path, "/images/sprite.png")

    def test_url_rewrite(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/urls.css'),
        ], 'css/screen.css')
        self.assertEqual(
            """@font-face {
  font-family: 'Pipeline';
  src: url(../pipeline/fonts/pipeline.eot);
  src: url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype');
  src: local('☺'), url(../pipeline/fonts/pipeline.woff) format('woff'), url(../pipeline/fonts/pipeline.ttf) format('truetype'), url(../pipeline/fonts/pipeline.svg#IyfZbseF) format('svg');
  font-weight: normal;
  font-style: normal;
}
.relative-url {
  background-image: url(../pipeline/images/sprite-buttons.png);
}
.relative-url-querystring {
  background-image: url(../pipeline/images/sprite-buttons.png?v=1.0#foo=bar);
}
.absolute-url {
  background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
  background-image: url(http://localhost/images/sprite-buttons.png);
}
.no-protocol-url {
  background-image: url(//images/sprite-buttons.png);
}
.anchor-tag-url {
  background-image: url(#image-gradient);
}
@font-face{src:url(../pipeline/fonts/pipeline.eot);src:url(../pipeline/fonts/pipeline.eot?#iefix) format('embedded-opentype'),url(../pipeline/fonts/pipeline.woff) format('woff'),url(../pipeline/fonts/pipeline.ttf) format('truetype');}
""", output)

    def test_url_rewrite_data_uri(self):
        output = self.compressor.concatenate_and_rewrite([
            _('pipeline/css/nested/nested.css'),
        ], 'pipeline/screen.css')
        self.assertEqual(
            """.data-url {
  background-image: url(data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E);
}
.data-url-quoted {
  background-image: url('data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E');
}
""", output)

    @skipIf(sys.platform.startswith("win"), "requires posix platform")
    def test_compressor_subprocess_unicode(self):
        path = os.path.dirname(os.path.dirname(__file__))
        content = io.open(path + '/assets/css/unicode.css',
                          encoding="utf-8").read()
        output = SubProcessCompressor(False).execute_command(('cat', ),
                                                             content)
        self.assertEqual(
            """.some_class {
  // Some unicode
  content: "áéíóú";
}
""", output)

    def tearDown(self):
        default_collector.clear()
예제 #36
0
 def setUp(self):
     self.maxDiff = None
     self.compressor = Compressor()
     default_collector.collect()
예제 #37
0
 def setUp(self):
     self.maxDiff = None
     self.compressor = Compressor()
     default_collector.collect()