index.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. 'use strict';
  2. var gutil = require('gulp-util');
  3. var path = require('path');
  4. var rework = require('rework');
  5. var reworkImport = require('rework-import');
  6. var through = require('through2');
  7. var parseImport = require('parse-import');
  8. var reworkUrl = require('rework-plugin-url');
  9. var defaults = require('lodash.defaults');
  10. module.exports = function(destFile, options) {
  11. var buffer = [];
  12. var firstFile, commonBase;
  13. var destDir = path.dirname(destFile);
  14. var urlImportRules = [];
  15. options = defaults({}, options, {
  16. inlineImports: true,
  17. rebaseUrls: true,
  18. includePaths: []
  19. });
  20. return through.obj(function(file, enc, cb) {
  21. var processedCss;
  22. if (file.isStream()) {
  23. this.emit('error', new gutil.PluginError('gulp-concat-css', 'Streaming not supported'));
  24. return cb();
  25. }
  26. if(!firstFile) {
  27. firstFile = file;
  28. commonBase = file.base;
  29. }
  30. function urlPlugin(file) {
  31. return reworkUrl(function(url) {
  32. if(isUrl(url) || isDataURI(url) || path.extname(url) === '.css' || path.resolve(url) === url) {
  33. return url;
  34. }
  35. var resourceAbsUrl = path.relative(commonBase, path.resolve(path.dirname(file), url));
  36. resourceAbsUrl = path.relative(destDir, resourceAbsUrl);
  37. //not all systems use forward slash as path separator
  38. //this is required by urls.
  39. if(path.sep === '\\'){
  40. //replace with forward slash
  41. resourceAbsUrl = resourceAbsUrl.replace(/\\/g, '/');
  42. }
  43. return resourceAbsUrl;
  44. });
  45. }
  46. function collectImportUrls(styles) {
  47. var outRules = [];
  48. styles.rules.forEach(function(rule) {
  49. if(rule.type !== 'import') {
  50. return outRules.push(rule);
  51. }
  52. var importData = parseImport('@import ' + rule.import + ';');
  53. var importPath = importData && importData[0].path;
  54. if(isUrl(importPath) || !options.inlineImports) {
  55. return urlImportRules.push(rule);
  56. }
  57. return outRules.push(rule);
  58. });
  59. styles.rules = outRules;
  60. }
  61. function processNestedImport(contents) {
  62. var rew = rework(contents,{source:this.source});//find the css file has syntax errors
  63. if(options.rebaseUrls) {
  64. rew = rew.use(urlPlugin(this.source));
  65. }
  66. rew = rew.use(collectImportUrls);
  67. return rew.toString();
  68. }
  69. try {
  70. processedCss = rework(String(file.contents||""),{source:file.path});//find the css file has syntax errors
  71. if(options.rebaseUrls) {
  72. processedCss = processedCss.use(urlPlugin(file.path));
  73. }
  74. processedCss = processedCss.use(collectImportUrls);
  75. if(options.inlineImports) {
  76. processedCss = processedCss.use(reworkImport({
  77. path: [
  78. '.',
  79. path.dirname(file.path)
  80. ].concat(options.includePaths),
  81. transform: processNestedImport
  82. }))
  83. .toString();
  84. }
  85. processedCss = processedCss.toString();
  86. } catch(err) {
  87. this.emit('error', new gutil.PluginError('gulp-concat-css', err));
  88. return cb();
  89. }
  90. buffer.push(processedCss);
  91. cb();
  92. }, function(cb) {
  93. if(!firstFile) {
  94. return cb();
  95. }
  96. var contents = urlImportRules.map(function(rule) {
  97. return '@import ' + rule.import + ';';
  98. }).concat(buffer).join(gutil.linefeed);
  99. var concatenatedFile = new gutil.File({
  100. base: firstFile.base,
  101. cwd: firstFile.cwd,
  102. path: path.join(firstFile.base, destFile),
  103. contents: new Buffer(contents)
  104. });
  105. this.push(concatenatedFile);
  106. cb();
  107. });
  108. };
  109. function isUrl(url) {
  110. return (/^([\w]+:)?\/\/./).test(url);
  111. }
  112. function isDataURI(url) {
  113. return url && url.indexOf('data:') === 0;
  114. }