define([ "../buildControl", "../fileUtils", "dojo/_base/lang" ], function(bc, fileUtils, lang) { // note: this transform originated from the v1.6 build system. In 1.8 it has been enhanced to handle // relative paths for imports when the src and destination tree structures are not predictable. // // The cssImportIgnore logic remains although it is of questionable value because it depends on naming a file // exactly as it is named in an import directive. Instead, the tag "importIgnore" can be used to prevent expanding // a CSS file and the tag "noOptimize" can be used to prevent optimizing a CSS file. The tag system gives a // much more general method to handle this problem. Of course cssImportIgnore can be disabled by simply setting // it to falsy. var cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g, cssUrlRegExp = /url\(\s*([^\)]+)\s*\)?/g, checkSlashes = function(name){ return name.replace(/\\/g, "/"); }, cssImportIgnore = (bc.cssImportIgnore ? // trim any spaces off of all items; add a trailing comma for fast lookups bc.cssImportIgnore.split(",").map(function(item){return lang.trim(item);}).join(",") + "," : ""), cleanCssUrlQuotes = function(url){ // If an URL from a CSS url value contains start/end quotes, remove them. // This is not done in the regexp, since the CSS spec allows for ' and " in the URL // which makes the regex overly complicated if they are backslash escaped. url = lang.trim(url); if(url.charAt(0) == "'" || url.charAt(0) == '"'){ url = url.substring(1, url.length - 1); } return url; }, removeComments = function(text, filename){ var originalText = text, startIndex = -1, endIndex; while((startIndex = text.indexOf("/*")) != -1){ endIndex = text.indexOf("*/", startIndex + 2); if(endIndex == -1){ bc.log("cssOptimizeImproperComment", ["CSS file", filename]); return originalText; } text = text.substring(0, startIndex) + text.substring(endIndex + 2, text.length); } return text; }, isRelative = function(url){ var colonIndex = url.indexOf(":"); return url.charAt(0) != "/" && (colonIndex == -1 || colonIndex > url.indexOf("/")); }, getDestRelativeFilename = function(dest, relativeResource){ var referenceSegments = dest.split("/"), relativeSegments = relativeResource.dest.split("/"); referenceSegments.pop(); while(referenceSegments.length && relativeSegments.length && referenceSegments[0]==relativeSegments[0]){ referenceSegments.shift(); relativeSegments.shift(); } for(var i = 0; i 0){ queryString = fixedUrl.slice(queryStart); fixedUrl = fixedUrl.slice(0, queryStart); } if(isRelative(fixedUrl)){ var fullDestFilename = fileUtils.compactPath(fileUtils.catPath(importResourceDestPath, fixedUrl)), relativeResource = bc.resourcesByDest[fullDestFilename]; if(!relativeResource){ bc.log("cssOptimizeUnableToResolveURL", ["CSS file", src, "import", importResource.src, "relative URL", fullMatch]); }else{ return 'url("' + getDestRelativeFilename(resource.dest, relativeResource) + queryString + '")'; } } // right or wrong, this is our only choice at this point return fullMatch; }); }); //Hoist imports to maintain valid CSS text = text.replace(cssImportRegExp, function(fullMatch){ imports.push(fullMatch); return ""; }); if(imports.length) { text = imports.join("\n") + "\n" + text; } if(/keepLines/i.test(bc.cssOptimize)){ // remove multiple empty lines. text = text.replace(/(\r\n)+/g, "\r\n").replace(/\n+/g, "\n"); }else{ // remove newlines and extra spaces text = text.replace(/[\r\n]/g, "").replace(/\s+/g, " ").replace(/\{\s/g, "{").replace(/\s\}/g, "}"); } resource.optimizedText = text; if(!resource.tag.noOptimize){ resource.rawText = resource.text; resource.text = text; } }; return function(resource, callback) { try{ if(bc.cssOptimize && !resource.tag.noOptimize){ flattenCss(resource); bc.log("cssOptimize", ["file", resource.src]); } }catch(e){ bc.log("cssOptimizeFailed", ["file", resource.src, "error", e]); } }; });