def test_resolveImports(self): "cssutils.resolveImports(sheet)" if mock: self._tempSer() cssutils.ser.prefs.useMinified() a = u'@charset "iso-8859-1";@import"b.css";ä{color:green}'.encode( 'iso-8859-1') b = u'@charset "ascii";\E4 {color:red}'.encode('ascii') # normal mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() self.assertEqual(a, s.cssText) self.assertEqual(b, s.cssRules[1].styleSheet.cssText) c = cssutils.resolveImports(s) self.assertEqual('\xc3\xa4{color:red}\xc3\xa4{color:green}', c.cssText) c.encoding = 'ascii' self.assertEqual( r'@charset "ascii";\E4 {color:red}\E4 {color:green}', c.cssText) # b cannot be found mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, None)) s = cssutils.parseString(a) restore() self.assertEqual(a, s.cssText) self.assertEqual(None, s.cssRules[1].styleSheet) c = cssutils.resolveImports(s) self.assertEqual('@import"b.css";\xc3\xa4{color:green}', c.cssText) # @import with media a = u'@import"b.css";@import"b.css" print, tv ;@import"b.css" all;' b = u'a {color: red}' mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() c = cssutils.resolveImports(s) self.assertEqual( 'a{color:red}@media print,tv{a{color:red}}a{color:red}', c.cssText) # cannot resolve with media => keep original a = u'@import"b.css"print;' b = u'@namespace "http://example.com";' mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() c = cssutils.resolveImports(s) self.assertEqual(a, c.cssText) else: self.assertEqual(False, u'Minimock needed for this test')
def test_resolveImports(self): "cssutils.resolveImports(sheet)" if mock: self._tempSer() cssutils.ser.prefs.useMinified() a = u'@charset "iso-8859-1";@import"b.css";ä{color:green}'.encode('iso-8859-1') b = u'@charset "ascii";\E4 {color:red}'.encode('ascii') # normal mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() self.assertEqual(a, s.cssText) self.assertEqual(b, s.cssRules[1].styleSheet.cssText) c = cssutils.resolveImports(s) self.assertEqual('\xc3\xa4{color:red}\xc3\xa4{color:green}', c.cssText) c.encoding = 'ascii' self.assertEqual(r'@charset "ascii";\E4 {color:red}\E4 {color:green}', c.cssText) # b cannot be found mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, None)) s = cssutils.parseString(a) restore() self.assertEqual(a, s.cssText) self.assertEqual(None, s.cssRules[1].styleSheet) c = cssutils.resolveImports(s) self.assertEqual('@import"b.css";\xc3\xa4{color:green}', c.cssText) # @import with media a = u'@import"b.css";@import"b.css" print, tv ;@import"b.css" all;' b = u'a {color: red}' mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() c = cssutils.resolveImports(s) self.assertEqual('a{color:red}@media print,tv{a{color:red}}a{color:red}', c.cssText) # cannot resolve with media => keep original a = u'@import"b.css"print;' b = u'@namespace "http://example.com";' mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() c = cssutils.resolveImports(s) self.assertEqual(a, c.cssText) else: self.assertEqual(False, u'Minimock needed for this test')
def process(self, files): for f in files: if not f['resource_path'].endswith('.css') or f['type'] != 'file': yield f continue self._counter += 1 fs_rpath = f['filesystem_path'] sheet = cssutils.parseFile(fs_rpath) sheet.setSerializer(self.serializer) for url in cssutils.getUrls(sheet): u = urlparse(url) if u.scheme or u.netloc or not u.path.startswith('./'): logging.warning('non-relative URL used in CSS: %s' % url) if self.resolve_imports: sheet = cssutils.resolveImports(sheet) target = os.path.join( self._tmpdir, str(self._counter) + '-' + os.path.basename(fs_rpath)) out_f = open(target, 'wb') try: out_f.write(sheet.cssText) finally: out_f.close() f['filesystem_path'] = target yield f
def csscombine( path=None, url=None, cssText=None, href=None, sourceencoding=None, targetencoding=None, minify=True, resolveVariables=True, ): """Combine sheets referred to by @import rules in given CSS proxy sheet into a single new sheet. :returns: combined cssText, normal or minified :Parameters: `path` or `url` or `cssText` + `href` path or URL to a CSSStyleSheet or a cssText of a sheet which imports other sheets which are then combined into one sheet. `cssText` normally needs `href` to be able to resolve relative imports. `sourceencoding` = 'utf-8' explicit encoding of the source proxysheet `targetencoding` encoding of the combined stylesheet `minify` = True defines if the combined sheet should be minified, in this case comments are not parsed at all! `resolveVariables` = True defines if variables in combined sheet should be resolved """ cssutils.log.info('Combining files from %r' % url, neverraise=True) if sourceencoding is not None: cssutils.log.info('Using source encoding %r' % sourceencoding, neverraise=True) parser = cssutils.CSSParser(parseComments=not minify) if path and not cssText: src = parser.parseFile(path, encoding=sourceencoding) elif url: src = parser.parseUrl(url, encoding=sourceencoding) elif cssText: src = parser.parseString(cssText, href=href, encoding=sourceencoding) else: sys.exit('Path or URL must be given') result = cssutils.resolveImports(src) result.encoding = targetencoding cssutils.log.info('Using target encoding: %r' % targetencoding, neverraise=True) oldser = cssutils.ser cssutils.setSerializer(cssutils.serialize.CSSSerializer()) if minify: cssutils.ser.prefs.useMinified() cssutils.ser.prefs.resolveVariables = resolveVariables cssText = result.cssText cssutils.setSerializer(oldser) return cssText
def process_file(source): sheet = cssutils.resolveImports(cssutils.parseFile(source)).cssText hash = hashlib.md5() hash.update(sheet) filename = OUT_PREFIX + hash.hexdigest() + FILENAME_POSTFIX with open(filename, "w") as out: out.write(sheet) return source, filename
def csscombine( path=None, url=None, cssText=None, href=None, sourceencoding=None, targetencoding=None, minify=True, resolveVariables=True, ): """Combine sheets referred to by @import rules in given CSS proxy sheet into a single new sheet. :returns: combined cssText, normal or minified :Parameters: `path` or `url` or `cssText` + `href` path or URL to a CSSStyleSheet or a cssText of a sheet which imports other sheets which are then combined into one sheet. `cssText` normally needs `href` to be able to resolve relative imports. `sourceencoding` = 'utf-8' explicit encoding of the source proxysheet `targetencoding` encoding of the combined stylesheet `minify` = True defines if the combined sheet should be minified, in this case comments are not parsed at all! `resolveVariables` = True defines if variables in combined sheet should be resolved """ cssutils.log.info(u"Combining files from %r" % url, neverraise=True) if sourceencoding is not None: cssutils.log.info(u"Using source encoding %r" % sourceencoding, neverraise=True) parser = cssutils.CSSParser(parseComments=not minify) if path and not cssText: src = parser.parseFile(path, encoding=sourceencoding) elif url: src = parser.parseUrl(url, encoding=sourceencoding) elif cssText: src = parser.parseString(cssText, href=href, encoding=sourceencoding) else: sys.exit("Path or URL must be given") result = cssutils.resolveImports(src) result.encoding = targetencoding cssutils.log.info(u"Using target encoding: %r" % targetencoding, neverraise=True) oldser = cssutils.ser cssutils.setSerializer(cssutils.serialize.CSSSerializer()) if minify: cssutils.ser.prefs.useMinified() cssutils.ser.prefs.resolveVariables = resolveVariables cssText = result.cssText cssutils.setSerializer(oldser) return cssText
def csscombine(path=None, url=None, sourceencoding=None, targetencoding=None, minify=True): """Combine sheets referred to by @import rules in given CSS proxy sheet into a single new sheet. :returns: combined cssText, normal or minified :Parameters: `path` or `url` path or URL to a CSSStyleSheet which imports other sheets which are then combined into one sheet `targetencoding` encoding of the combined stylesheet, default 'utf-8' `minify` defines if the combined sheet should be minified, default True """ cssutils.log.info(u'Combining files from %r' % url, neverraise=True) if sourceencoding is not None: cssutils.log.info(u'Using source encoding %r' % sourceencoding, neverraise=True) if path: src = cssutils.parseFile(path, encoding=sourceencoding) elif url: src = cssutils.parseUrl(url, encoding=sourceencoding) else: sys.exit('Path or URL must be given') result = cssutils.resolveImports(src) result.encoding = targetencoding cssutils.log.info(u'Using target encoding: %r' % targetencoding, neverraise=True) if minify: # save old setting and use own serializer oldser = cssutils.ser cssutils.setSerializer(cssutils.serialize.CSSSerializer()) cssutils.ser.prefs.useMinified() cssText = result.cssText cssutils.setSerializer(oldser) else: cssText = result.cssText return cssText
def minify(source, output, **options): '''Minifies CSS from a file and outputs it to a different file. :type source: :class:`django.core.files.File` :type output: :class:`django.core.files.File` ''' ser.prefs.useMinified() base_path = getattr(source, 'path', source.name) stylesheet = parseString(source.read(), href='file://%s' % pathname2url(base_path)) css_files = get_recursive_imports(stylesheet, base=base_path) # concatenate the stylesheets minified = resolveImports(stylesheet) # replace static asset references with the "live" URLs replaceUrls(minified, replace_static_refs, ignoreImportRules=True) # generate minified CSS css = minified.cssText output.write(css) output.seek(0)
def getCssRules(self, uri): """Given the URI of a CSS file, return the list of all CSS rules, including all the imports.""" IMPORT_FLAG = False stylesheet = "" # requests is more robust for encoding errors headers = {'User-Agent': UAREF} r = requests.get(uri, headers=headers) stylesheet = cssutils.parseString(r.text) for cssrule in stylesheet: if cssrule.type == 3: IMPORT_FLAG = True # ResolveImports only if there is a rule if IMPORT_FLAG: stylesheet2 = cssutils.resolveImports(stylesheet) else: stylesheet2 = stylesheet return stylesheet2
def stylesheet(static_file): stylesheets_dir = os.path.join( settings.DATA_DIR, 'cssminify', 'stylesheets' ) imports = [ '@import "{stylesheet}";'.format(stylesheet=stylesheet) for stylesheet in os.listdir(stylesheets_dir) ] proxy_stylesheet = cssutils.parseString( '\n'.join(imports), href='file://{path}'.format( path=os.path.join( stylesheets_dir, '{uuid}.css'.format(uuid=uuid.uuid4()) ) ) ) stylesheet = cssutils.resolveImports(proxy_stylesheet) static_file.content = stylesheet.cssText
def csscombine(path=None, url=None, sourceencoding=None, targetencoding=None, minify=True): """Combine sheets referred to by @import rules in given CSS proxy sheet into a single new sheet. :returns: combined cssText, normal or minified :Parameters: `path` or `url` path or URL to a CSSStyleSheet which imports other sheets which are then combined into one sheet `targetencoding` encoding of the combined stylesheet, default 'utf-8' `minify` defines if the combined sheet should be minified, default True """ cssutils.log.info(u"Combining files from %r" % url, neverraise=True) if sourceencoding is not None: cssutils.log.info(u"Using source encoding %r" % sourceencoding, neverraise=True) if path: src = cssutils.parseFile(path, encoding=sourceencoding) elif url: src = cssutils.parseUrl(url, encoding=sourceencoding) else: sys.exit("Path or URL must be given") result = cssutils.resolveImports(src) result.encoding = targetencoding cssutils.log.info(u"Using target encoding: %r" % targetencoding, neverraise=True) if minify: # save old setting and use own serializer oldser = cssutils.ser cssutils.setSerializer(cssutils.serialize.CSSSerializer()) cssutils.ser.prefs.useMinified() cssText = result.cssText cssutils.setSerializer(oldser) else: cssText = result.cssText return cssText
def test_resolveImports(self): "cssutils.resolveImports(sheet)" if mock: self._tempSer() cssutils.ser.prefs.useMinified() a = '@charset "iso-8859-1";@import"b.css";\xe4{color:green}'.encode('iso-8859-1') b = '@charset "ascii";\\E4 {color:red}'.encode('ascii') # normal m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, b) s = cssutils.parseString(a) # py3 TODO self.assertEqual(a, s.cssText) self.assertEqual(b, s.cssRules[1].styleSheet.cssText) c = cssutils.resolveImports(s) # py3 TODO self.assertEqual('\xc3\xa4{color:red}\xc3\xa4{color:green}'.encode('iso-8859-1'), c.cssText) c.encoding = 'ascii' self.assertEqual(r'@charset "ascii";\E4 {color:red}\E4 {color:green}'.encode(), c.cssText) # b cannot be found m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, None) s = cssutils.parseString(a) # py3 TODO self.assertEqual(a, s.cssText) self.assertEqual(cssutils.css.CSSStyleSheet, type(s.cssRules[1].styleSheet)) c = cssutils.resolveImports(s) # py3 TODO self.assertEqual('@import"b.css";\xc3\xa4{color:green}'.encode('iso-8859-1'), c.cssText) # @import with media a = '@import"b.css";@import"b.css" print, tv ;@import"b.css" all;' b = 'a {color: red}' m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, b) s = cssutils.parseString(a) c = cssutils.resolveImports(s) self.assertEqual('a{color:red}@media print,tv{a{color:red}}a{color:red}'.encode(), c.cssText) # cannot resolve with media => keep original a = '@import"b.css"print;' b = '@namespace "http://example.com";' m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, b) s = cssutils.parseString(a) c = cssutils.resolveImports(s) self.assertEqual(a.encode(), c.cssText) # urls are adjusted too, layout: # a.css # c.css # img/img.gif # b/ # b.css # subimg/subimg.gif a = ''' @import"b/b.css"; a { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif); }''' def fetcher(url): c = { 'b.css': ''' @import"../c.css"; b { x: url(/img/abs.gif); y: url(../img/img.gif); z: url(subimg/subimg.gif); }''', 'c.css': ''' c { x: url(/img/abs.gif); y: url(./img/img.gif); z: url(./b/subimg/subimg.gif); }''' } return 'utf-8', c[os.path.split(url)[1]] @mock.patch.object(cssutils.util, '_defaultFetcher', new=fetcher) def do(): s = cssutils.parseString(a) r = cssutils.resolveImports(s) return s, r s, r = do() cssutils.ser.prefs.useDefaults() cssutils.ser.prefs.keepComments = False self.assertEqual('''c { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) } b { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) } a { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) }'''.encode(), r.cssText) cssutils.ser.prefs.useDefaults() else: self.assertEqual(False, 'Mock needed for this test')
over3-0: var(over3-0); over2-1: var(over2-1); over3-1: var(over3-1); over3-2: var(over3-2); over2-1-0: var(over2-1-0); over3-2-0: var(over3-2-0); over3-2-1: var(over3-2-1); over3-2-1-0: var(over3-2-1-0); } ''' cssutils.ser.prefs.resolveVariables = False p = cssutils.CSSParser(fetcher=fetcher) s = p.parseString(css) #print s.cssText print() s = cssutils.resolveImports(s) print(sorted(s.variables.keys())) sys.exit(0) if 1: print(cssutils.ser.prefs.keepUnkownAtRules) cssutils.ser.prefs.keepUnkownAtRules = 1 sys.exit(1) def fetcher(url): if url == "/1/2.css": return None, '''@variables { color: red; }''' else:
def do(): s = cssutils.parseString(a) r = cssutils.resolveImports(s) return s, r
def test_resolveImports(self): "cssutils.resolveImports(sheet)" if mock: self._tempSer() cssutils.ser.prefs.useMinified() a = u'@charset "iso-8859-1";@import"b.css";\xe4{color:green}'.encode( 'iso-8859-1') b = u'@charset "ascii";\\E4 {color:red}'.encode('ascii') # normal m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, b) s = cssutils.parseString(a) # py3 TODO self.assertEqual(a, s.cssText) self.assertEqual(b, s.cssRules[1].styleSheet.cssText) c = cssutils.resolveImports(s) # py3 TODO self.assertEqual( u'\xc3\xa4{color:red}\xc3\xa4{color:green}'.encode( 'iso-8859-1'), c.cssText) c.encoding = 'ascii' self.assertEqual( ur'@charset "ascii";\E4 {color:red}\E4 {color:green}'. encode(), c.cssText) # b cannot be found m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, None) s = cssutils.parseString(a) # py3 TODO self.assertEqual(a, s.cssText) self.assertEqual(cssutils.css.CSSStyleSheet, type(s.cssRules[1].styleSheet)) c = cssutils.resolveImports(s) # py3 TODO self.assertEqual( u'@import"b.css";\xc3\xa4{color:green}'.encode( 'iso-8859-1'), c.cssText) # @import with media a = u'@import"b.css";@import"b.css" print, tv ;@import"b.css" all;' b = u'a {color: red}' m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, b) s = cssutils.parseString(a) c = cssutils.resolveImports(s) self.assertEqual( 'a{color:red}@media print,tv{a{color:red}}a{color:red}'. encode(), c.cssText) # cannot resolve with media => keep original a = u'@import"b.css"print;' b = u'@namespace "http://example.com";' m = mock.Mock() with mock.patch('cssutils.util._defaultFetcher', m): m.return_value = (None, b) s = cssutils.parseString(a) c = cssutils.resolveImports(s) self.assertEqual(a.encode(), c.cssText) # urls are adjusted too, layout: # a.css # c.css # img/img.gif # b/ # b.css # subimg/subimg.gif a = u''' @import"b/b.css"; a { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif); }''' def fetcher(url): c = { 'b.css': u''' @import"../c.css"; b { x: url(/img/abs.gif); y: url(../img/img.gif); z: url(subimg/subimg.gif); }''', 'c.css': u''' c { x: url(/img/abs.gif); y: url(./img/img.gif); z: url(./b/subimg/subimg.gif); }''' } return 'utf-8', c[os.path.split(url)[1]] @mock.patch.object(cssutils.util, '_defaultFetcher', new=fetcher) def do(): s = cssutils.parseString(a) r = cssutils.resolveImports(s) return s, r s, r = do() cssutils.ser.prefs.useDefaults() cssutils.ser.prefs.keepComments = False self.assertEqual( u'''c { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) } b { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) } a { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) }'''.encode(), r.cssText) cssutils.ser.prefs.useDefaults() else: self.assertEqual(False, u'Mock needed for this test')
over3-0: var(over3-0); over2-1: var(over2-1); over3-1: var(over3-1); over3-2: var(over3-2); over2-1-0: var(over2-1-0); over3-2-0: var(over3-2-0); over3-2-1: var(over3-2-1); over3-2-1-0: var(over3-2-1-0); } ''' cssutils.ser.prefs.resolveVariables = False p = cssutils.CSSParser(fetcher=fetcher) s = p.parseString(css) #print s.cssText print s = cssutils.resolveImports(s) print sorted(s.variables.keys()) sys.exit(0) if 1: print cssutils.ser.prefs.keepUnkownAtRules cssutils.ser.prefs.keepUnkownAtRules = 1 sys.exit(1) def fetcher(url): if url == "/1/2.css": return None, '''@variables {
def test_imports(self): "CSSVariables imports" def fetcher(url): url = url.replace('\\', '/') url = url[url.rfind('/') + 1:] return (None, { '3.css': ''' @variables { over3-2-1-0: 3; over3-2-1: 3; over3-2: 3; over3-2-0: 3; over3-1: 3; over3-1-0: 3; over3-0: 3; local3: 3; } ''', '2.css': ''' @variables { over3-2-1-0: 2; over3-2-1: 2; over3-2-0: 2; over3-2: 2; over2-1: 2; over2-1-0: 2; over2-0: 2; local2: 2; } ''', '1.css': ''' @import "3.css"; @import "2.css"; @variables { over3-2-1-0: 1; over3-2-1: 1; over3-1: 1; over3-1-0: 1; over2-1: 1; over2-1-0: 1; over1-0: 1; local1: 1; } ''' }[url]) css = ''' @import "1.css"; @variables { over3-2-1-0: 0; over3-2-0: 0; over3-1-0: 0; over2-1-0: 0; over3-0: 0; over2-0: 0; over1-0: 0; local0: 0; } a { local0: var(local0); local1: var(local1); local2: var(local2); local3: var(local3); over1-0: var(over1-0); over2-0: var(over2-0); over3-0: var(over3-0); over2-1: var(over2-1); over3-1: var(over3-1); over3-2: var(over3-2); over2-1-0: var(over2-1-0); over3-2-0: var(over3-2-0); over3-2-1: var(over3-2-1); over3-2-1-0: var(over3-2-1-0); } ''' p = cssutils.CSSParser(fetcher=fetcher) s = p.parseString(css) # only these in rule of this sheet self.assertEqual(s.cssRules[1].variables.length, 8) # but all vars in s available! self.assertEqual(s.variables.length, 15) self.assertEqual([ u'local0', u'local1', u'local2', u'local3', u'over1-0', u'over2-0', u'over2-1', u'over2-1-0', u'over3-0', u'over3-1', u'over3-1-0', u'over3-2', u'over3-2-0', u'over3-2-1', u'over3-2-1-0' ], sorted(s.variables.keys())) # test with variables rule cssutils.ser.prefs.resolveVariables = False self.assertEqual( s.cssText, '''@import "1.css"; @variables { over3-2-1-0: 0; over3-2-0: 0; over3-1-0: 0; over2-1-0: 0; over3-0: 0; over2-0: 0; over1-0: 0; local0: 0 } a { local0: var(local0); local1: var(local1); local2: var(local2); local3: var(local3); over1-0: var(over1-0); over2-0: var(over2-0); over3-0: var(over3-0); over2-1: var(over2-1); over3-1: var(over3-1); over3-2: var(over3-2); over2-1-0: var(over2-1-0); over3-2-0: var(over3-2-0); over3-2-1: var(over3-2-1); over3-2-1-0: var(over3-2-1-0) }'''.encode()) # test with resolved vars cssutils.ser.prefs.resolveVariables = True self.assertEqual( s.cssText, '''@import "1.css"; a { local0: 0; local1: 1; local2: 2; local3: 3; over1-0: 0; over2-0: 0; over3-0: 0; over2-1: 1; over3-1: 1; over3-2: 2; over2-1-0: 0; over3-2-0: 0; over3-2-1: 1; over3-2-1-0: 0 }'''.encode()) s = cssutils.resolveImports(s) self.assertEqual( s.cssText, '''/* START @import "1.css" */ /* START @import "3.css" */ /* START @import "2.css" */ a { local0: 0; local1: 1; local2: 2; local3: 3; over1-0: 0; over2-0: 0; over3-0: 0; over2-1: 1; over3-1: 1; over3-2: 2; over2-1-0: 0; over3-2-0: 0; over3-2-1: 1; over3-2-1-0: 0 }'''.encode())
def test_resolveImports(self): "cssutils.resolveImports(sheet)" if mock: self._tempSer() cssutils.ser.prefs.useMinified() a = u'@charset "iso-8859-1";@import"b.css";ä{color:green}'.encode('iso-8859-1') b = u'@charset "ascii";\E4 {color:red}'.encode('ascii') # normal mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() self.assertEqual(a, s.cssText) self.assertEqual(b, s.cssRules[1].styleSheet.cssText) c = cssutils.resolveImports(s) self.assertEqual('\xc3\xa4{color:red}\xc3\xa4{color:green}', c.cssText) c.encoding = 'ascii' self.assertEqual(r'@charset "ascii";\E4 {color:red}\E4 {color:green}', c.cssText) # b cannot be found mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, None)) s = cssutils.parseString(a) restore() self.assertEqual(a, s.cssText) self.assertEqual(cssutils.css.CSSStyleSheet, type(s.cssRules[1].styleSheet)) c = cssutils.resolveImports(s) self.assertEqual('@import"b.css";\xc3\xa4{color:green}', c.cssText) # @import with media a = u'@import"b.css";@import"b.css" print, tv ;@import"b.css" all;' b = u'a {color: red}' mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() c = cssutils.resolveImports(s) self.assertEqual('a{color:red}@media print,tv{a{color:red}}a{color:red}', c.cssText) # cannot resolve with media => keep original a = u'@import"b.css"print;' b = u'@namespace "http://example.com";' mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, b)) s = cssutils.parseString(a) restore() c = cssutils.resolveImports(s) self.assertEqual(a, c.cssText) # urls are adjusted too, layout: # a.css # c.css # img/img.gif # b/ # b.css # subimg/subimg.gif a = u''' @import"b/b.css"; a { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif); }''' def fetcher(url): c = { 'b.css': u''' @import"../c.css"; b { x: url(/img/abs.gif); y: url(../img/img.gif); z: url(subimg/subimg.gif); }''', 'c.css': u''' c { x: url(/img/abs.gif); y: url(./img/img.gif); z: url(./b/subimg/subimg.gif); }''' } return 'utf-8', c[os.path.split(url)[1]] mock("cssutils.util._defaultFetcher", mock_obj=fetcher) s = cssutils.parseString(a) r = cssutils.resolveImports(s) restore() cssutils.ser.prefs.useDefaults() cssutils.ser.prefs.keepComments = False self.assertEqual(u'''c { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) } b { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) } a { x: url(/img/abs.gif); y: url(img/img.gif); z: url(b/subimg/subimg.gif) }''', r.cssText) else: self.assertEqual(False, u'Minimock needed for this test')
def _minified(): href = self.base_url if self.base_url != '' else None sheet = cssutils.parseString(css, href=href) sheet = cssutils.resolveImports(sheet) cssutils.ser.prefs.useMinified() return sheet.cssText
#!/usr/bin/env python import sys,cssutils proxysheet = cssutils.parseFile(sys.argv[1]) combinedsheet = cssutils.resolveImports(proxysheet) cssutils.ser.prefs.useMinified() print combinedsheet.cssText
def test_imports(self): "CSSVariables imports" def fetcher(url): url = url.replace('\\', '/') url = url[url.rfind('/')+1:] return (None, { '3.css': ''' @variables { over3-2-1-0: 3; over3-2-1: 3; over3-2: 3; over3-2-0: 3; over3-1: 3; over3-1-0: 3; over3-0: 3; local3: 3; } ''', '2.css': ''' @variables { over3-2-1-0: 2; over3-2-1: 2; over3-2-0: 2; over3-2: 2; over2-1: 2; over2-1-0: 2; over2-0: 2; local2: 2; } ''', '1.css': ''' @import "3.css"; @import "2.css"; @variables { over3-2-1-0: 1; over3-2-1: 1; over3-1: 1; over3-1-0: 1; over2-1: 1; over2-1-0: 1; over1-0: 1; local1: 1; } ''' }[url]) css = ''' @import "1.css"; @variables { over3-2-1-0: 0; over3-2-0: 0; over3-1-0: 0; over2-1-0: 0; over3-0: 0; over2-0: 0; over1-0: 0; local0: 0; } a { local0: var(local0); local1: var(local1); local2: var(local2); local3: var(local3); over1-0: var(over1-0); over2-0: var(over2-0); over3-0: var(over3-0); over2-1: var(over2-1); over3-1: var(over3-1); over3-2: var(over3-2); over2-1-0: var(over2-1-0); over3-2-0: var(over3-2-0); over3-2-1: var(over3-2-1); over3-2-1-0: var(over3-2-1-0); } ''' p = cssutils.CSSParser(fetcher=fetcher) s = p.parseString(css) # only these in rule of this sheet self.assertEqual(s.cssRules[1].variables.length, 8) # but all vars in s available! self.assertEqual(s.variables.length, 15) self.assertEqual([u'local0', u'local1', u'local2', u'local3', u'over1-0', u'over2-0', u'over2-1', u'over2-1-0', u'over3-0', u'over3-1', u'over3-1-0', u'over3-2', u'over3-2-0', u'over3-2-1', u'over3-2-1-0'], sorted(s.variables.keys())) # test with variables rule cssutils.ser.prefs.resolveVariables = False self.assertEqual(s.cssText, '''@import "1.css"; @variables { over3-2-1-0: 0; over3-2-0: 0; over3-1-0: 0; over2-1-0: 0; over3-0: 0; over2-0: 0; over1-0: 0; local0: 0 } a { local0: var(local0); local1: var(local1); local2: var(local2); local3: var(local3); over1-0: var(over1-0); over2-0: var(over2-0); over3-0: var(over3-0); over2-1: var(over2-1); over3-1: var(over3-1); over3-2: var(over3-2); over2-1-0: var(over2-1-0); over3-2-0: var(over3-2-0); over3-2-1: var(over3-2-1); over3-2-1-0: var(over3-2-1-0) }'''.encode()) # test with resolved vars cssutils.ser.prefs.resolveVariables = True self.assertEqual(s.cssText, '''@import "1.css"; a { local0: 0; local1: 1; local2: 2; local3: 3; over1-0: 0; over2-0: 0; over3-0: 0; over2-1: 1; over3-1: 1; over3-2: 2; over2-1-0: 0; over3-2-0: 0; over3-2-1: 1; over3-2-1-0: 0 }'''.encode()) s = cssutils.resolveImports(s) self.assertEqual(s.cssText, '''/* START @import "1.css" */ /* START @import "3.css" */ /* START @import "2.css" */ a { local0: 0; local1: 1; local2: 2; local3: 3; over1-0: 0; over2-0: 0; over3-0: 0; over2-1: 1; over3-1: 1; over3-2: 2; over2-1-0: 0; over3-2-0: 0; over3-2-1: 1; over3-2-1-0: 0 }'''.encode())