137 lines
3.7 KiB
JavaScript
137 lines
3.7 KiB
JavaScript
|
'use strict';
|
||
|
var PluginError = require('plugin-error');
|
||
|
var Vinyl = require('vinyl');
|
||
|
var path = require('path');
|
||
|
var rework = require('rework');
|
||
|
var reworkImport = require('rework-import');
|
||
|
var through = require('through2');
|
||
|
var parseImport = require('parse-import');
|
||
|
var reworkUrl = require('rework-plugin-url');
|
||
|
var defaults = require('lodash.defaults');
|
||
|
|
||
|
module.exports = function(destFile, options) {
|
||
|
var buffer = [];
|
||
|
var firstFile, commonBase;
|
||
|
var destDir = path.dirname(destFile);
|
||
|
var urlImportRules = [];
|
||
|
options = defaults({}, options, {
|
||
|
inlineImports: true,
|
||
|
rebaseUrls: true,
|
||
|
includePaths: [],
|
||
|
commonBase: null
|
||
|
});
|
||
|
|
||
|
return through.obj(function(file, enc, cb) {
|
||
|
var processedCss;
|
||
|
|
||
|
if (file.isStream()) {
|
||
|
this.emit('error', new PluginError('gulp-concat-css', 'Streaming not supported'));
|
||
|
return cb();
|
||
|
}
|
||
|
|
||
|
if(!firstFile) {
|
||
|
firstFile = file;
|
||
|
commonBase = options.commonBase || file.base;
|
||
|
}
|
||
|
|
||
|
function urlPlugin(file) {
|
||
|
return reworkUrl(function(url) {
|
||
|
if(isUrl(url) || isDataURI(url) || path.extname(url) === '.css' || path.resolve(url) === url) {
|
||
|
return url;
|
||
|
}
|
||
|
|
||
|
var resourceAbsUrl = path.relative(commonBase, path.resolve(path.dirname(file), url));
|
||
|
resourceAbsUrl = path.relative(destDir, resourceAbsUrl);
|
||
|
//not all systems use forward slash as path separator
|
||
|
//this is required by urls.
|
||
|
if(path.sep === '\\'){
|
||
|
//replace with forward slash
|
||
|
resourceAbsUrl = resourceAbsUrl.replace(/\\/g, '/');
|
||
|
}
|
||
|
return resourceAbsUrl;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
|
||
|
function collectImportUrls(styles) {
|
||
|
var outRules = [];
|
||
|
styles.rules.forEach(function(rule) {
|
||
|
if(rule.type !== 'import') {
|
||
|
return outRules.push(rule);
|
||
|
}
|
||
|
|
||
|
var importData = parseImport('@import ' + rule.import + ';');
|
||
|
var importPath = importData && importData[0].path;
|
||
|
if(isUrl(importPath) || !options.inlineImports) {
|
||
|
return urlImportRules.push(rule);
|
||
|
}
|
||
|
return outRules.push(rule);
|
||
|
});
|
||
|
styles.rules = outRules;
|
||
|
}
|
||
|
|
||
|
|
||
|
function processNestedImport(contents) {
|
||
|
var rew = rework(contents,{source:this.source});//find the css file has syntax errors
|
||
|
if(options.rebaseUrls) {
|
||
|
rew = rew.use(urlPlugin(this.source));
|
||
|
}
|
||
|
rew = rew.use(collectImportUrls);
|
||
|
return rew.toString();
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
processedCss = rework(String(file.contents||""),{source:file.path});//find the css file has syntax errors
|
||
|
if(options.rebaseUrls) {
|
||
|
processedCss = processedCss.use(urlPlugin(file.path));
|
||
|
}
|
||
|
|
||
|
processedCss = processedCss.use(collectImportUrls);
|
||
|
|
||
|
if(options.inlineImports) {
|
||
|
processedCss = processedCss.use(reworkImport({
|
||
|
path: [
|
||
|
'.',
|
||
|
path.dirname(file.path)
|
||
|
].concat(options.includePaths),
|
||
|
transform: processNestedImport
|
||
|
}))
|
||
|
.toString();
|
||
|
}
|
||
|
|
||
|
processedCss = processedCss.toString();
|
||
|
} catch(err) {
|
||
|
this.emit('error', new PluginError('gulp-concat-css', err));
|
||
|
return cb();
|
||
|
}
|
||
|
|
||
|
buffer.push(processedCss);
|
||
|
cb();
|
||
|
}, function(cb) {
|
||
|
if(!firstFile) {
|
||
|
return cb();
|
||
|
}
|
||
|
|
||
|
var contents = urlImportRules.map(function(rule) {
|
||
|
return '@import ' + rule.import + ';';
|
||
|
}).concat(buffer).join('\n');
|
||
|
|
||
|
var concatenatedFile = new Vinyl({
|
||
|
base: firstFile.base,
|
||
|
cwd: firstFile.cwd,
|
||
|
path: path.join(firstFile.base, destFile),
|
||
|
contents: new Buffer(contents)
|
||
|
});
|
||
|
this.push(concatenatedFile);
|
||
|
cb();
|
||
|
});
|
||
|
};
|
||
|
|
||
|
function isUrl(url) {
|
||
|
return (/^([\w]+:)?\/\/./).test(url);
|
||
|
}
|
||
|
|
||
|
function isDataURI(url) {
|
||
|
return url && url.indexOf('data:') === 0;
|
||
|
}
|