132 lines
5.7 KiB
JavaScript
132 lines
5.7 KiB
JavaScript
var contexts = require("./contexts"),
|
|
Parser = require('./parser/parser'),
|
|
FunctionImporter = require('./plugins/function-importer');
|
|
|
|
module.exports = function(environment) {
|
|
|
|
// FileInfo = {
|
|
// 'relativeUrls' - option - whether to adjust URL's to be relative
|
|
// 'filename' - full resolved filename of current file
|
|
// 'rootpath' - path to append to normal URLs for this node
|
|
// 'currentDirectory' - path to the current file, absolute
|
|
// 'rootFilename' - filename of the base file
|
|
// 'entryPath' - absolute path to the entry file
|
|
// 'reference' - whether the file should not be output and only output parts that are referenced
|
|
|
|
var ImportManager = function(context, rootFileInfo) {
|
|
this.rootFilename = rootFileInfo.filename;
|
|
this.paths = context.paths || []; // Search paths, when importing
|
|
this.contents = {}; // map - filename to contents of all the files
|
|
this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
|
|
this.mime = context.mime;
|
|
this.error = null;
|
|
this.context = context;
|
|
// Deprecated? Unused outside of here, could be useful.
|
|
this.queue = []; // Files which haven't been imported yet
|
|
this.files = {}; // Holds the imported parse trees.
|
|
};
|
|
/**
|
|
* Add an import to be imported
|
|
* @param path - the raw path
|
|
* @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension)
|
|
* @param currentFileInfo - the current file info (used for instance to work out relative paths)
|
|
* @param importOptions - import options
|
|
* @param callback - callback for when it is imported
|
|
*/
|
|
ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) {
|
|
var importManager = this;
|
|
this.queue.push(path);
|
|
|
|
var fileParsedFunc = function (e, root, fullPath) {
|
|
importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
|
|
|
|
var importedEqualsRoot = fullPath === importManager.rootFilename;
|
|
if (importOptions.optional && e) {
|
|
callback(null, {rules:[]}, false, null);
|
|
}
|
|
else {
|
|
importManager.files[fullPath] = root;
|
|
if (e && !importManager.error) { importManager.error = e; }
|
|
callback(e, root, importedEqualsRoot, fullPath);
|
|
}
|
|
};
|
|
|
|
var newFileInfo = {
|
|
relativeUrls: this.context.relativeUrls,
|
|
entryPath: currentFileInfo.entryPath,
|
|
rootpath: currentFileInfo.rootpath,
|
|
rootFilename: currentFileInfo.rootFilename
|
|
};
|
|
|
|
var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);
|
|
|
|
if (!fileManager) {
|
|
fileParsedFunc({ message: "Could not find a file-manager for " + path });
|
|
return;
|
|
}
|
|
|
|
if (tryAppendLessExtension) {
|
|
path = fileManager.tryAppendExtension(path, importOptions.plugin ? ".js" : ".less");
|
|
}
|
|
|
|
var loadFileCallback = function(loadedFile) {
|
|
var resolvedFilename = loadedFile.filename,
|
|
contents = loadedFile.contents.replace(/^\uFEFF/, '');
|
|
|
|
// Pass on an updated rootpath if path of imported file is relative and file
|
|
// is in a (sub|sup) directory
|
|
//
|
|
// Examples:
|
|
// - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
|
|
// then rootpath should become 'less/module/nav/'
|
|
// - If path of imported file is '../mixins.less' and rootpath is 'less/',
|
|
// then rootpath should become 'less/../'
|
|
newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
|
|
if (newFileInfo.relativeUrls) {
|
|
newFileInfo.rootpath = fileManager.join(
|
|
(importManager.context.rootpath || ""),
|
|
fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
|
|
|
|
if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
|
|
newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
|
|
}
|
|
}
|
|
newFileInfo.filename = resolvedFilename;
|
|
|
|
var newEnv = new contexts.Parse(importManager.context);
|
|
|
|
newEnv.processImports = false;
|
|
importManager.contents[resolvedFilename] = contents;
|
|
|
|
if (currentFileInfo.reference || importOptions.reference) {
|
|
newFileInfo.reference = true;
|
|
}
|
|
|
|
if (importOptions.plugin) {
|
|
new FunctionImporter(newEnv, newFileInfo).eval(contents, function (e, root) {
|
|
fileParsedFunc(e, root, resolvedFilename);
|
|
});
|
|
} else if (importOptions.inline) {
|
|
fileParsedFunc(null, contents, resolvedFilename);
|
|
} else {
|
|
new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
|
|
fileParsedFunc(e, root, resolvedFilename);
|
|
});
|
|
}
|
|
};
|
|
|
|
var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment,
|
|
function(err, loadedFile) {
|
|
if (err) {
|
|
fileParsedFunc(err);
|
|
} else {
|
|
loadFileCallback(loadedFile);
|
|
}
|
|
});
|
|
if (promise) {
|
|
promise.then(loadFileCallback, fileParsedFunc);
|
|
}
|
|
};
|
|
return ImportManager;
|
|
};
|