You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
7.8 KiB
244 lines
7.8 KiB
define(['require', './normalize'], function(req, normalize) {
|
|
var cssAPI = {};
|
|
|
|
var isWindows = !!process.platform.match(/^win/);
|
|
|
|
function compress(css) {
|
|
if (config.optimizeCss == 'none') {
|
|
return css;
|
|
}
|
|
|
|
if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
|
|
try {
|
|
var csso = require.nodeRequire('csso');
|
|
}
|
|
catch(e) {
|
|
console.log('Compression module not installed. Use "npm install csso -g" to enable.');
|
|
return css;
|
|
}
|
|
var csslen = css.length;
|
|
try {
|
|
if (typeof csso.minify === 'function') {
|
|
var minifyResult = csso.minify(css);
|
|
if (typeof minifyResult === 'string'){ // for csso < 2.0.0
|
|
css = minifyResult;
|
|
} else if (typeof minifyResult === 'object'){ // for csso >= 2.0.0
|
|
css = minifyResult.css;
|
|
}
|
|
} else { // justDoIt() was always. minify() appeared in csso 1.4.0.
|
|
css = csso.justDoIt(css);
|
|
}
|
|
}
|
|
catch(e) {
|
|
console.log('Compression failed due to a CSS syntax error.');
|
|
return css;
|
|
}
|
|
console.log('Compressed CSS output to ' + Math.round(css.length / csslen * 100) + '%.');
|
|
return css;
|
|
}
|
|
console.log('Compression not supported outside of nodejs environments.');
|
|
return css;
|
|
}
|
|
|
|
//load file code - stolen from text plugin
|
|
function loadFile(path) {
|
|
if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
|
|
var fs = require.nodeRequire('fs');
|
|
var file = fs.readFileSync(path, 'utf8');
|
|
if (file.indexOf('\uFEFF') === 0)
|
|
return file.substring(1);
|
|
return file;
|
|
}
|
|
else {
|
|
var file = new java.io.File(path),
|
|
lineSeparator = java.lang.System.getProperty("line.separator"),
|
|
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), 'utf-8')),
|
|
stringBuffer, line;
|
|
try {
|
|
stringBuffer = new java.lang.StringBuffer();
|
|
line = input.readLine();
|
|
if (line && line.length() && line.charAt(0) === 0xfeff)
|
|
line = line.substring(1);
|
|
stringBuffer.append(line);
|
|
while ((line = input.readLine()) !== null) {
|
|
stringBuffer.append(lineSeparator).append(line);
|
|
}
|
|
return String(stringBuffer.toString());
|
|
}
|
|
finally {
|
|
input.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function saveFile(path, data) {
|
|
if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
|
|
var fs = require.nodeRequire('fs');
|
|
fs.writeFileSync(path, data, 'utf8');
|
|
}
|
|
else {
|
|
var content = new java.lang.String(data);
|
|
var output = new java.io.BufferedWriter(new java.io.OutputStreamWriter(new java.io.FileOutputStream(path), 'utf-8'));
|
|
|
|
try {
|
|
output.write(content, 0, content.length());
|
|
output.flush();
|
|
}
|
|
finally {
|
|
output.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
//when adding to the link buffer, paths are normalised to the baseUrl
|
|
//when removing from the link buffer, paths are normalised to the output file path
|
|
function escape(content) {
|
|
return content.replace(/(["'\\])/g, '\\$1')
|
|
.replace(/[\f]/g, "\\f")
|
|
.replace(/[\b]/g, "\\b")
|
|
.replace(/[\n]/g, "\\n")
|
|
.replace(/[\t]/g, "\\t")
|
|
.replace(/[\r]/g, "\\r");
|
|
}
|
|
|
|
// NB add @media query support for media imports
|
|
var importRegEx = /@import\s*(url)?\s*(('([^']*)'|"([^"]*)")|\(('([^']*)'|"([^"]*)"|([^\)]*))\))\s*;?/g;
|
|
var absUrlRegEx = /^([^\:\/]+:\/)?\//;
|
|
|
|
// Write Css module definition
|
|
var writeCSSDefinition = "define('@writecss', function() {return function writeCss(c) {var d=document,a='appendChild',i='styleSheet',s=d.createElement('style');s.type='text/css';d.getElementsByTagName('head')[0][a](s);s[i]?s[i].cssText=c:s[a](d.createTextNode(c));};});";
|
|
|
|
var siteRoot;
|
|
|
|
var baseParts = req.toUrl('base_url').split('/');
|
|
baseParts[baseParts.length - 1] = '';
|
|
var baseUrl = baseParts.join('/');
|
|
|
|
var curModule = 0;
|
|
var config;
|
|
|
|
var writeCSSForLayer = true;
|
|
var layerBuffer = [];
|
|
var cssBuffer = {};
|
|
|
|
cssAPI.load = function(name, req, load, _config) {
|
|
//store config
|
|
config = config || _config;
|
|
|
|
if (!siteRoot) {
|
|
siteRoot = path.resolve(config.dir || path.dirname(config.out.toString()), config.siteRoot || '.') + '/';
|
|
if (isWindows)
|
|
siteRoot = siteRoot.replace(/\\/g, '/');
|
|
}
|
|
|
|
//external URLS don't get added (just like JS requires)
|
|
if (name.match(absUrlRegEx))
|
|
return load();
|
|
|
|
var fileUrl = req.toUrl(name + '.css');
|
|
if (isWindows)
|
|
fileUrl = fileUrl.replace(/\\/g, '/');
|
|
|
|
// rebase to the output directory if based on the source directory;
|
|
// baseUrl points always to the output directory, fileUrl only if
|
|
// it is not prefixed by a computed path (relative too)
|
|
var fileSiteUrl = fileUrl;
|
|
if (fileSiteUrl.indexOf(baseUrl) < 0) {
|
|
var appRoot = req.toUrl(config.appDir);
|
|
if (isWindows)
|
|
appRoot = appRoot.replace(/\\/g, '/');
|
|
if (fileSiteUrl.indexOf(appRoot) == 0)
|
|
fileSiteUrl = siteRoot + fileSiteUrl.substring(appRoot.length);
|
|
}
|
|
|
|
//add to the buffer
|
|
cssBuffer[name] = normalize(loadFile(fileUrl), fileSiteUrl, siteRoot);
|
|
|
|
load();
|
|
}
|
|
|
|
cssAPI.normalize = function(name, normalize) {
|
|
if (name.substr(name.length - 4, 4) == '.css')
|
|
name = name.substr(0, name.length - 4);
|
|
return normalize(name);
|
|
}
|
|
|
|
cssAPI.write = function(pluginName, moduleName, write, parse) {
|
|
var cssModule;
|
|
|
|
//external URLS don't get added (just like JS requires)
|
|
if (moduleName.match(absUrlRegEx))
|
|
return;
|
|
|
|
layerBuffer.push(cssBuffer[moduleName]);
|
|
|
|
if (!global._requirejsCssData) {
|
|
global._requirejsCssData = {
|
|
usedBy: {css: true},
|
|
css: ''
|
|
}
|
|
} else {
|
|
global._requirejsCssData.usedBy.css = true;
|
|
}
|
|
|
|
if (config.buildCSS != false) {
|
|
var style = cssBuffer[moduleName];
|
|
|
|
if (config.writeCSSModule && style) {
|
|
if (writeCSSForLayer) {
|
|
writeCSSForLayer = false;
|
|
write(writeCSSDefinition);
|
|
}
|
|
|
|
cssModule = 'define(["@writecss"], function(writeCss){\n writeCss("'+ escape(compress(style)) +'");\n})';
|
|
}
|
|
else {
|
|
cssModule = 'define(function(){})';
|
|
}
|
|
|
|
write.asModule(pluginName + '!' + moduleName, cssModule);
|
|
}
|
|
}
|
|
|
|
cssAPI.onLayerEnd = function(write, data) {
|
|
if (config.separateCSS && config.IESelectorLimit)
|
|
throw 'RequireCSS: separateCSS option is not compatible with ensuring the IE selector limit';
|
|
|
|
if (config.separateCSS) {
|
|
var outPath = data.path.replace(/(\.js)?$/, '.css');
|
|
console.log('Writing CSS! file: ' + outPath + '\n');
|
|
|
|
var css = layerBuffer.join('');
|
|
|
|
process.nextTick(function() {
|
|
if (global._requirejsCssData) {
|
|
css = global._requirejsCssData.css = css + global._requirejsCssData.css;
|
|
delete global._requirejsCssData.usedBy.css;
|
|
if (Object.keys(global._requirejsCssData.usedBy).length === 0) {
|
|
delete global._requirejsCssData;
|
|
}
|
|
}
|
|
|
|
saveFile(outPath, compress(css));
|
|
});
|
|
|
|
}
|
|
else if (config.buildCSS != false && config.writeCSSModule != true) {
|
|
var styles = config.IESelectorLimit ? layerBuffer : [layerBuffer.join('')];
|
|
for (var i = 0; i < styles.length; i++) {
|
|
if (styles[i] == '')
|
|
return;
|
|
write(
|
|
"(function(c){var d=document,a='appendChild',i='styleSheet',s=d.createElement('style');s.type='text/css';d.getElementsByTagName('head')[0][a](s);s[i]?s[i].cssText=c:s[a](d.createTextNode(c));})\n"
|
|
+ "('" + escape(compress(styles[i])) + "');\n"
|
|
);
|
|
}
|
|
}
|
|
//clear layer buffer for next layer
|
|
layerBuffer = [];
|
|
writeCSSForLayer = true;
|
|
}
|
|
|
|
return cssAPI;
|
|
}); |