def test_combine_files_includes_filename(self): """Combining files should include their relative filename at the top.""" test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("yui", "yui-min.js"), "** yui-min **"), self.makeSampleFile( test_dir, os.path.join("oop", "oop-min.js"), "** oop-min **"), self.makeSampleFile( test_dir, os.path.join("event-custom", "event-custom-min.js"), "** event-custom-min **"), ] expected = "\n".join(("// yui/yui-min.js", "** yui-min **", "// oop/oop-min.js", "** oop-min **", "// event-custom/event-custom-min.js", "** event-custom-min **")) self.assertEquals( "".join(combine_files(["yui/yui-min.js", "oop/oop-min.js", "event-custom/event-custom-min.js"], root=test_dir)).strip(), expected)
def test_missing_file_is_ignored(self): """If a missing file is requested we should still combine the others.""" test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("yui", "yui-min.js"), "** yui-min **"), self.makeSampleFile( test_dir, os.path.join("event-custom", "event-custom-min.js"), "** event-custom-min **"), ] expected = "\n".join(("// yui/yui-min.js", "** yui-min **", "// oop/oop-min.js", "// [missing]", "// event-custom/event-custom-min.js", "** event-custom-min **")) self.assertEquals( "".join(combine_files(["yui/yui-min.js", "oop/oop-min.js", "event-custom/event-custom-min.js"], root=test_dir)).strip(), expected)
def main(): icing = os.path.join(config.root, 'lib/canonical/launchpad/icing') target = os.path.join(icing, 'combo.css') # Get all the component css files so we don't have to edit this file # every time a new component is added. component_dir = 'css/components' component_path = os.path.abspath(os.path.join(icing, component_dir)) for root, dirs, files in scandir.walk(component_path): for file in files: if file.endswith('.css'): names.append('%s/%s' % (component_dir, file)) absolute_names = [] for name in names: full_path_name = os.path.abspath(os.path.join(icing, name)) absolute_names.append(full_path_name) combo = ComboFile(absolute_names, target) if combo.needs_update(): result = '' for content in combine_files(names, icing): result += content with open(target, 'w') as f: f.write(result)
def test_no_absolute_path_hack(self): """If someone tries to fetch an absolute file, they'll get nothing.""" test_dir = self.makeDir() hack = "/etc/passwd" self.assertTrue(os.path.exists("/etc/passwd")) expected = "" self.assertEqual("".join(combine_files([hack], root=test_dir)).strip(), expected)
def test_no_absolute_path_hack(self): """If someone tries to fetch an absolute file, he'll get nothing.""" test_dir = self.makeDir() hack = "/etc/passwd" self.assertTrue(os.path.exists("/etc/passwd")) expected = "" self.assertEquals( "".join(combine_files([hack], root=test_dir)).strip(), expected)
def test_rewrite_url_normalizes_parent_references(self): """URL references in CSS files get normalized for parent dirs.""" test_dir = self.makeDir() files = [ self.makeSampleFile(test_dir, os.path.join("yui", "base", "base.css"), ".foo{background-image:url(../../img.png)}"), ] expected = "\n".join( ("/* yui/base/base.css */", ".foo{background-image:url(img.png)}")) self.assertEqual("".join(combine_files(files, root=test_dir)).strip(), expected)
def test_rewrite_url_normalizes_parent_references(self): """URL references in CSS files get normalized for parent dirs.""" test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("yui", "base", "base.css"), ".foo{background-image:url(../../img.png)}"), ] expected = "\n".join(("/* yui/base/base.css */", ".foo{background-image:url(img.png)}")) self.assertEquals( "".join(combine_files(files, root=test_dir)).strip(), expected)
def test_no_parent_hack(self): """If someone tries to hack going up the root, they'll get a miss.""" test_dir = self.makeDir() self.makeSampleFile(test_dir, os.path.join("oop", "oop-min.js"), "** oop-min **") root = os.path.join(test_dir, "root", "lazr") os.makedirs(root) hack = "../../oop/oop-min.js" self.assertTrue(os.path.exists(os.path.join(root, hack))) expected = "\n".join(("// ../../oop/oop-min.js", "// [missing]")) self.assertEqual("".join(combine_files([hack], root=root)).strip(), expected)
def test_combine_css_disable_rewrite_url_and_minify(self): """ It is possible to disable both the rewriting of urls in the CSS file and minification, in which case the files are returned unchanged. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), "\n".join( ('/* widget skin */', '.yui-widget {', ' background: url("img/bg.png");', '}')) ), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), "\n".join(('/* editor skin */', '.yui-editor {', ' background: url("img/bg.png");', '}')) ), ] expected = "\n".join( ('/* widget/assets/skins/sam/widget.css */', '/* widget skin */', '.yui-widget {', ' background: url("img/bg.png");', '}', '/* editor/assets/skins/sam/editor.css */', '/* editor skin */', '.yui-editor {', ' background: url("img/bg.png");', '}', )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir, minify_css=False, rewrite_urls=False)).strip(), expected)
def test_combine_css_disable_minify(self): """ It is possible to disable CSS minification altogether, while keeping the URL rewriting behavior. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), "\n".join( ('/* widget skin */', '.yui-widget {', ' background: url("img/bg.png");', '}')) ), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), "\n".join(('/* editor skin */', '.yui-editor {', ' background: url("img/bg.png");', '}')) ), ] expected = "\n".join( ("/* widget/assets/skins/sam/widget.css */", "/* widget skin */", ".yui-widget {", " background: url(widget/assets/skins/sam/img/bg.png);", "}", "/* editor/assets/skins/sam/editor.css */", "/* editor skin */", ".yui-editor {", " background: url(editor/assets/skins/sam/img/bg.png);", "}", )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir, minify_css=False)).strip(), expected)
def test_combine_css_adds_custom_prefix(self): """ Combining CSS files minifies and makes URLs in CSS declarations relative to the target path. It's also possible to specify an additional prefix for the rewritten URLs. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), """\ /* widget skin */ .yui-widget { background: url("img/bg.png"); } """), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), """\ /* editor skin */ .yui-editor { background: url("img/bg.png"); } """), ] expected = "\n".join( ("/* widget/assets/skins/sam/widget.css */", ".yui-widget{background:url(" + "/static/widget/assets/skins/sam/img/bg.png)}", "/* editor/assets/skins/sam/editor.css */", ".yui-editor{background:url(" + "/static/editor/assets/skins/sam/img/bg.png)}", )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir, resource_prefix="/static/")).strip(), expected)
def test_combine_css_handles_relative_links_from_top_level(self): """ Combining CSS files handles making URLs relative even from the top level (alongside combo.css). """ test_dir = self.makeDir() self.makeSampleFile( test_dir, "ubuntu-webfonts.css", """\ @font-face { src: url('fonts/Ubuntu.woff'); } """) expected = "\n".join(( "/* ubuntu-webfonts.css */", "@font-face{src:url(fonts/Ubuntu.woff)}", )) self.assertEqual( "".join(combine_files(["ubuntu-webfonts.css"], root=test_dir)).strip(), expected)
def test_no_parent_hack(self): """If someone tries to hack going up the root, he'll get a miss.""" test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("oop", "oop-min.js"), "** oop-min **"), ] root = os.path.join(test_dir, "root", "lazr") os.makedirs(root) hack = "../../oop/oop-min.js" self.assertTrue(os.path.exists(os.path.join(root, hack))) expected = "\n".join(("// ../../oop/oop-min.js", "// [missing]")) self.assertEquals( "".join(combine_files([hack], root=root)).strip(), expected)
def test_combine_css_disable_rewrite_url(self): """ It is possible to disable the rewriting of urls in the CSS file. """ test_dir = self.makeDir() self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), """\ /* widget skin */ .yui-widget { background: url("img/bg.png"); } """) self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), """\ /* editor skin */ .yui-editor { background: url("img/bg.png"); } """) expected = "\n".join(( "/* widget/assets/skins/sam/widget.css */", ".yui-widget{background:url(img/bg.png)}", "/* editor/assets/skins/sam/editor.css */", ".yui-editor{background:url(img/bg.png)}", )) self.assertEqual( "".join( combine_files([ "widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css" ], root=test_dir, rewrite_urls=False)).strip(), expected)
def test_combine_css_minifies_and_makes_relative(self): """ Combining CSS files minifies and makes URLs in CSS declarations relative to the target path. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), """\ /* widget skin */ .yui-widget { background: url("img/bg.png"); } """), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), """\ /* editor skin */ .yui-editor { background: url("img/bg.png"); } """), ] expected = "\n".join( ("/* widget/assets/skins/sam/widget.css */", ".yui-widget{background:url(widget/assets/skins/sam/img/bg.png)}", "/* editor/assets/skins/sam/editor.css */", ".yui-editor{background:url(editor/assets/skins/sam/img/bg.png)}", )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir)).strip(), expected)
def test_combine_css_leaves_absolute_urls_untouched(self): """ Combining CSS files does not touch absolute URLs in declarations. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), """\ /* widget skin */ .yui-widget { background: url("/static/img/bg.png"); } """), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), """\ /* editor skin */ .yui-editor { background: url("http://foo/static/img/bg.png"); } """), ] expected = "\n".join( ("/* widget/assets/skins/sam/widget.css */", ".yui-widget{background:url(/static/img/bg.png)}", "/* editor/assets/skins/sam/editor.css */", ".yui-editor{background:url(http://foo/static/img/bg.png)}", )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir)).strip(), expected)
def test_combine_css_leaves_data_uris_untouched(self): """ Combining CSS files does not touch data uris in declarations. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), """\ /* widget skin */ .yui-widget { background: url("data:image/gif;base64,base64-data"); } """), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), """\ /* editor skin */ .yui-editor { background: url(data:image/gif;base64,base64-data); } """), ] expected = "\n".join( ('/* widget/assets/skins/sam/widget.css */', '.yui-widget{background:url("data:image/gif;base64,base64-data")}', '/* editor/assets/skins/sam/editor.css */', '.yui-editor{background:url("data:image/gif;base64,base64-data")}', )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir)).strip(), expected)
def test_combine_css_disable_rewrite_url(self): """ It is possible to disable the rewriting of urls in the CSS file. """ test_dir = self.makeDir() files = [ self.makeSampleFile( test_dir, os.path.join("widget", "assets", "skins", "sam", "widget.css"), """\ /* widget skin */ .yui-widget { background: url("img/bg.png"); } """), self.makeSampleFile( test_dir, os.path.join("editor", "assets", "skins", "sam", "editor.css"), """\ /* editor skin */ .yui-editor { background: url("img/bg.png"); } """), ] expected = "\n".join( ("/* widget/assets/skins/sam/widget.css */", ".yui-widget{background:url(img/bg.png)}", "/* editor/assets/skins/sam/editor.css */", ".yui-editor{background:url(img/bg.png)}", )) self.assertEquals( "".join(combine_files(["widget/assets/skins/sam/widget.css", "editor/assets/skins/sam/editor.css"], root=test_dir, rewrite_urls=False)).strip(), expected)