123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- define(['require', './normalize'], function(req, normalize) {
- var nodePrint = function() {};
- if (requirejs.tools)
- requirejs.tools.useLib(function(req) {
- req(['node/print'], function(_nodePrint) {
- nodePrint = _nodePrint;
- }, function(){});
- });
-
- var cssAPI = {};
-
- function compress(css) {
- if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
- try {
- var csso = require.nodeRequire('csso');
- var csslen = css.length;
- css = csso.justDoIt(css);
- nodePrint('Compressed CSS output to ' + Math.round(css.length / csslen * 100) + '%.');
- return css;
- }
- catch(e) {
- nodePrint('Compression module not installed. Use "npm install csso -g" to enable.');
- return css;
- }
- }
- nodePrint('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 loadCSSFile = function(fileUrl) {
- var css = loadFile(fileUrl);
- // normalize the css (except import statements)
- css = normalize(css, fileUrl, baseUrl, cssBase);
- // detect all import statements in the css and normalize
- var importUrls = [];
- var importIndex = [];
- var importLength = [];
- var match;
- while (match = importRegEx.exec(css)) {
- var importUrl = match[4] || match[5] || match[7] || match[8] || match[9];
- // normalize import url
- if (importUrl.substr(importUrl.length - 5, 5) != '.less' && importUrl.substr(importUrl.length - 4, 4) != '.css')
- importUrl += '.css';
- // contains a protocol
- if (importUrl.match(/:\/\//))
- continue;
- // relative to css base
- if (importUrl.substr(0, 1) == '/' && cssBase)
- importUrl = cssBase + importUrl;
- else
- importUrl = baseUrl + importUrl;
- importUrls.push(importUrl);
- importIndex.push(importRegEx.lastIndex - match[0].length);
- importLength.push(match[0].length);
- }
- // load the import stylesheets and substitute into the css
- for (var i = 0; i < importUrls.length; i++)
- (function(i) {
- var importCSS = loadCSSFile(importUrls[i]);
- css = css.substr(0, importIndex[i]) + importCSS + css.substr(importIndex[i] + importLength[i]);
- var lenDiff = importCSS.length - importLength[i];
- for (var j = i + 1; j < importUrls.length; j++)
- importIndex[j] += lenDiff;
- })(i);
- return css;
- }
-
- var baseUrl;
- var cssBase;
- var curModule;
- cssAPI.load = function(name, req, load, config, parse) {
- if (!baseUrl)
- baseUrl = config.baseUrl;
-
- if (!cssBase)
- cssBase = config.cssBase;
- if (config.modules) {
- //run through the module list - the first one without a layer set is the current layer we are in
- //allows to track the current layer number for layer-specific config
- for (var i = 0; i < config.modules.length; i++)
- if (config.modules[i].layer === undefined) {
- curModule = i;
- break;
- }
- }
-
- //store config
- cssAPI.config = cssAPI.config || config;
- name += !parse ? '.css' : '.less';
- var fileUrl = req.toUrl(name);
- //external URLS don't get added (just like JS requires)
- if (fileUrl.substr(0, 7) == 'http://' || fileUrl.substr(0, 8) == 'https://')
- return;
- //add to the buffer
- _cssBuffer[name] = loadCSSFile(fileUrl);
- // parse if necessary
- if (parse)
- _cssBuffer[name] = parse(_cssBuffer[name]);
- load();
- }
-
- cssAPI.normalize = function(name, normalize) {
- if (name.substr(name.length - 4, 4) == '.css')
- name = name.substr(0, name.length - 4);
- return normalize(name);
- }
-
- //list of cssIds included in this layer
- var _layerBuffer = [];
- var _cssBuffer = [];
- cssAPI.write = function(pluginName, moduleName, write, parse) {
- //external URLS don't get added (just like JS requires)
- if (moduleName.substr(0, 7) == 'http://' || moduleName.substr(0, 8) == 'https://')
- return;
-
- var resourceName = moduleName + (!parse ? '.css' : '.less');
- _layerBuffer.push(_cssBuffer[resourceName]);
- var separateCSS = false;
- if (cssAPI.config.separateCSS)
- separateCSS = true;
- if (typeof curModule == 'number' && cssAPI.config.modules[curModule].separateCSS !== undefined)
- separateCSS = cssAPI.config.modules[curModule].separateCSS;
- if (separateCSS)
- write.asModule(pluginName + '!' + moduleName, 'define(function(){})');
- else
- write("requirejs.s.contexts._.nextTick = function(f){f()}; require(['css'], function(css) { css.addBuffer('" + resourceName + "'); }); requirejs.s.contexts._.nextTick = requirejs.nextTick;");
- }
-
- cssAPI.onLayerEnd = function(write, data, parser) {
- firstWrite = true;
- //separateCSS parameter set either globally or as a layer setting
- var separateCSS = false;
- if (cssAPI.config.separateCSS)
- separateCSS = true;
- if (typeof curModule == 'number' && cssAPI.config.modules[curModule].separateCSS !== undefined)
- separateCSS = cssAPI.config.modules[curModule].separateCSS;
- curModule = null;
-
- //calculate layer css
- var css = _layerBuffer.join('');
-
- if (separateCSS) {
- nodePrint('Writing CSS! file: ' + data.name + '\n');
-
- //calculate the css output path for this layer
- var path = this.config.appDir ? this.config.baseUrl + data.name + '.css' : cssAPI.config.out.replace(/\.js$/, '.css');
-
- //renormalize the css to the output path
- var output = compress(normalize(css, baseUrl, path));
-
- saveFile(path, output);
- }
- else {
- if (css == '')
- return;
- //write the injection and layer index into the layer
- //prepare the css
- css = escape(compress(css));
-
- //the code below overrides async require functionality to ensure instant buffer injection
- write("requirejs.s.contexts._.nextTick = function(f){f()}; require(['css'], function(css) { css.setBuffer('" + css + (parser ? "', true" : "'") + "); }); requirejs.s.contexts._.nextTick = requirejs.nextTick; ");
- }
-
- //clear layer buffer for next layer
- _layerBuffer = [];
- }
-
- return cssAPI;
- });
|