nouveau-theatre-de-besancon/node_modules/gulp-cssimport/gulp-cssimport.js
2024-09-20 10:32:49 +02:00

268 lines
9.5 KiB
JavaScript

"use strict";
var through = require("through2");
var path = require("path");
var deepExtend = require("deep-extend");
var fs = require("fs");
var pify = require("pify");
var Vinyl = require("vinyl");
var PluginError = require("plugin-error");
var collect = require("collect-stream");
var hh = require("http-https");
var minimatch = require("minimatch");
var applySourceMap = require("vinyl-sourcemaps-apply");
var MagicString = require("magic-string");
var lookupPath = require("lookup-path");
var PLUGIN_NAME = "gulp-cssimport";
var readFile = pify(fs.readFile);
var trim = require("lodash.trim");
var format = require("util").format;
var stripBom = require("strip-bom");
var defaults = {
skipComments: true,
extensions: null,
includePaths: [],
filter: null,
matchPattern: null,
matchOptions: {
matchBase: true
},
limit: 5000,
transform: null
};
module.exports = function cssImport(options) {
options = deepExtend({}, defaults, options || {});
if (options.extensions && !Array.isArray(options.extensions)) {
options.extensions = options.extensions.toString().split(",").map(function(x) {
return x.trim();
});
}
var stream;
var cssCount = 0;
var transform = (options.transform && typeof options.transform === 'function') ? options.transform : null;
function fileContents(vinyl, encoding, callback) {
if (!stream) {
stream = this;
}
// https://github.com/kevva/import-regex/
var regex = '(?:@import)(?:\\s)(?:url)?(?:(?:(?:\\()(["\'])?(?:[^"\')]+)\\1(?:\\))|(["\'])(?:.+)\\2)(?:[A-Z\\s])*)+(?:;)'; // eslint-disable-line
var importRe = new RegExp(regex, "gi");
var match;
var file = [];
var lastpos = 0;
var promises = [];
var contents = vinyl.contents.toString();
while ((match = importRe.exec(contents)) !== null) {
if (options.skipComments) {
var matchIndex = match.index;
// Check comment symbols 1.
var startCommentPosition = contents.lastIndexOf('/*', matchIndex);
var endCommentPosition = contents.lastIndexOf('*/', matchIndex);
if (!(endCommentPosition > startCommentPosition) && startCommentPosition !== -1) {
continue;
}
// Check comment symbols 2.
var startCommentPosition2 = contents.lastIndexOf('//', matchIndex);
var endCommentPosition2 = contents.lastIndexOf('\n', matchIndex);
if (startCommentPosition2 > endCommentPosition2 && startCommentPosition2 !== -1) {
continue;
}
}
var match2 = /@import\s+(?:url\()?(.+(?=['")]))(?:\))?.*/ig.exec(match[0]);
var importPath = trim(match2[1], "'\"");
if (transform) {
importPath = transform(importPath, { match: match[0] });
}
var isMatched = isMatch(importPath, options);
if (!isMatched) {
continue;
}
file[file.length] = contents.slice(lastpos, match.index);
var index = file.length;
file[index] = format("importing file %s from %s", importPath, vinyl.relative);
lastpos = importRe.lastIndex;
// Start resolving.
if (++cssCount > options.limit) {
stream.emit("error", new Error("Exceed limit. Recursive include?"));
return;
}
(function(index) {
var result = { index: index, importPath: importPath };
if (!isUrl(importPath)) {
var pathDirectory = path.dirname(vinyl.path);
var importFile = resolveImportFile(pathDirectory, importPath, options.includePaths);
if (!importFile) {
var err = new Error("Cannot find file '" + importPath + "' from '" + pathDirectory + "' (includePaths: " + options.includePaths + ")");
callback(new PluginError(PLUGIN_NAME, err));
}
promises[promises.length] = readFile(importFile, "utf8").then(function(contents) {
result.importFile = importFile;
result.contents = contents;
return result;
});
} else {
promises[promises.length] = new Promise(function(resolve, reject) {
var req = hh.request(importPath, function(res) {
collect(res, function(err, data) {
if (err) {
return reject(err);
}
result.contents = data.toString();
resolve(result);
});
});
req.on("error", reject);
req.end();
});
}
})(index);
}
// Nothing to import.
if (promises.length === 0) {
callback(null, vinyl);
return;
}
// Adding trailing piece.
file[file.length] = contents.slice(lastpos);
// Waiting promises.
Promise.all(promises)
.then(function(results) {
for (var i = 0; i < results.length; i++) {
var result = results[i];
// Strip BOM.
result.contents = stripBom(result.contents);
var vfile = new Vinyl({
path: result.importFile,
contents: new Buffer(result.contents)
});
(function(result) {
results[i] = pify(fileContents)(vfile, null).then(function(vfile) {
result.contents = vfile.contents.toString();
return result;
});
})(result);
}
return Promise.all(results);
})
.then(function(results) {
var iterator = function() { };
if (vinyl.sourceMap) {
var bundle = new MagicString.Bundle();
iterator = function(file, result) {
bundle.addSource({
filename: result.importPath,
content: new MagicString(result.contents)
});
};
}
for (var i = 0; i < results.length; i++) {
var result = results[i];
var index = result.index;
var contents = result.contents;
file[index] = contents;
iterator(file, result);
}
vinyl.contents = new Buffer(file.join(""));
if (vinyl.sourceMap) {
var map = bundle.generateMap({
file: vinyl.relative,
includeContent: true,
hires: true
});
applySourceMap(vinyl, map);
}
callback(null, vinyl);
})
.catch(function(err) {
callback(new PluginError(PLUGIN_NAME, err));
});
}
return through.obj(fileContents);
};
function resolveImportFile(pathDirectory, importPath, includePaths) {
var result = lookupPath(importPath, pathDirectory);
if (result) {
return result;
}
for (var i = 0; i < includePaths.length; i++) {
var includePath = includePaths[i];
var d1 = path.resolve(pathDirectory, includePath);
if (d1 === pathDirectory) {
continue;
}
result = lookupPath(importPath, d1);
if (result) {
return result;
}
var d2 = path.resolve(includePath);
if (d2 === d1) {
continue;
}
result = lookupPath(importPath, d2);
if (result) {
return result;
}
}
return null;
}
function isMatch(path, options) {
if (!options) {
return true;
}
if (!path) {
return false;
}
options = options || {};
var result;
if (options.filter instanceof RegExp) {
var filter = options.filter;
filter.lastIndex = 0;
result = filter.test(path);
}
if (options.matchPattern && !isUrl(path)) {
var matchPattern = options.matchPattern;
result = minimatch(path, matchPattern, options.matchOptions);
}
if (options.extensions) {
var extensions = options.extensions;
var fileExt = getExtension(path);
for (var k = 0; k < extensions.length; k++) {
var extension = extensions[k];
var isInverse = extension.charAt(0) === '!';
if (isInverse) {
extension = extension.slice(1);
}
if (isInverse && fileExt === extension) { // !sass , sass === css
return false;
} else if (!isInverse && fileExt !== extension) {
return false;
}
}
}
if (typeof result === 'undefined') {
result = true;
}
return result;
}
function isUrl(s) {
return /^(http|https):\/\//.test(s);
}
function getExtension(p) {
p = String(p);
return p.substr(p.lastIndexOf('.') + 1);
}