diff --git a/lib/less/import-visitor.js b/lib/less/import-visitor.js index 0d773ca0..7d693372 100644 --- a/lib/less/import-visitor.js +++ b/lib/less/import-visitor.js @@ -1,10 +1,19 @@ (function (tree) { - tree.importVisitor = function(importer, finish, evalEnv) { + tree.importVisitor = function(importer, finish, evalEnv, onceFileDetectionMap, recursionDetector) { this._visitor = new tree.visitor(this); this._importer = importer; this._finish = finish; this.env = evalEnv || new tree.evalEnv(); this.importCount = 0; + this.onceFileDetectionMap = onceFileDetectionMap || {}; + this.recursionDetector = {}; + if (recursionDetector) { + for(var fullFilename in recursionDetector) { + if (recursionDetector.hasOwnProperty(fullFilename)) { + this.recursionDetector[fullFilename] = true; + } + } + } }; tree.importVisitor.prototype = { @@ -51,10 +60,22 @@ env.importMultiple = true; } - this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) { + this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, importedAtRoot, fullPath) { if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } - if (imported && !env.importMultiple) { importNode.skip = imported; } + if (!env.importMultiple) { + if (importedAtRoot) { + importNode.skip = true; + } else { + importNode.skip = function() { + if (fullPath in importVisitor.onceFileDetectionMap) { + return true; + } + importVisitor.onceFileDetectionMap[fullPath] = true; + return false; + }; + } + } var subFinish = function(e) { importVisitor.importCount--; @@ -67,8 +88,11 @@ if (root) { importNode.root = root; importNode.importedFilename = fullPath; - if (!inlineCSS && !importNode.skip) { - new(tree.importVisitor)(importVisitor._importer, subFinish, env) + var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector; + + if (!inlineCSS && (env.importMultiple || !duplicateImport)) { + importVisitor.recursionDetector[fullPath] = true; + new(tree.importVisitor)(importVisitor._importer, subFinish, env, importVisitor.onceFileDetectionMap, importVisitor.recursionDetector) .run(root); return; } diff --git a/lib/less/parser.js b/lib/less/parser.js index 74f2dddf..91457acc 100644 --- a/lib/less/parser.js +++ b/lib/less/parser.js @@ -73,7 +73,7 @@ less.Parser = function Parser(env) { var fileParsedFunc = function (e, root, fullPath) { parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue - var importedPreviously = fullPath in parserImports.files || fullPath === rootFilename; + var importedPreviously = fullPath === rootFilename; parserImports.files[fullPath] = root; // Store the root diff --git a/lib/less/tree/import.js b/lib/less/tree/import.js index 910fc11a..7042f042 100644 --- a/lib/less/tree/import.js +++ b/lib/less/tree/import.js @@ -92,7 +92,14 @@ tree.Import.prototype = { eval: function (env) { var ruleset, features = this.features && this.features.eval(env); - if (this.skip) { return []; } + if (this.skip) { + if (typeof this.skip === "function") { + this.skip = this.skip(); + } + if (this.skip) { + return []; + } + } if (this.options.inline) { //todo needs to reference css file not import