less
Version:
Leaner CSS
193 lines • 7.29 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
/* eslint-disable no-unused-vars */
/**
* @todo - Remove unused when JSDoc types are added for visitor methods
*/
var contexts_1 = tslib_1.__importDefault(require("../contexts"));
var visitor_1 = tslib_1.__importDefault(require("./visitor"));
var import_sequencer_1 = tslib_1.__importDefault(require("./import-sequencer"));
var utils = tslib_1.__importStar(require("../utils"));
var ImportVisitor = function (importer, finish) {
this._visitor = new visitor_1.default(this);
this._importer = importer;
this._finish = finish;
this.context = new contexts_1.default.Eval();
this.importCount = 0;
this.onceFileDetectionMap = {};
this.recursionDetector = {};
this._sequencer = new import_sequencer_1.default(this._onSequencerEmpty.bind(this));
};
ImportVisitor.prototype = {
isReplacing: false,
run: function (root) {
try {
// process the contents
this._visitor.visit(root);
}
catch (e) {
this.error = e;
}
this.isFinished = true;
this._sequencer.tryRun();
},
_onSequencerEmpty: function () {
if (!this.isFinished) {
return;
}
this._finish(this.error);
},
visitImport: function (importNode, visitArgs) {
var inlineCSS = importNode.options.inline;
if (!importNode.css || inlineCSS) {
var context = new contexts_1.default.Eval(this.context, utils.copyArray(this.context.frames));
var importParent = context.frames[0];
this.importCount++;
if (importNode.isVariableImport()) {
this._sequencer.addVariableImport(this.processImportNode.bind(this, importNode, context, importParent));
}
else {
this.processImportNode(importNode, context, importParent);
}
}
visitArgs.visitDeeper = false;
},
processImportNode: function (importNode, context, importParent) {
var evaldImportNode;
var inlineCSS = importNode.options.inline;
try {
evaldImportNode = importNode.evalForImport(context);
}
catch (e) {
if (!e.filename) {
e.index = importNode.getIndex();
e.filename = importNode.fileInfo().filename;
}
// attempt to eval properly and treat as css
importNode.css = true;
// if that fails, this error will be thrown
importNode.error = e;
}
if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
if (evaldImportNode.options.multiple) {
context.importMultiple = true;
}
// try appending if we haven't determined if it is css or not
var tryAppendLessExtension = evaldImportNode.css === undefined;
for (var i = 0; i < importParent.rules.length; i++) {
if (importParent.rules[i] === importNode) {
importParent.rules[i] = evaldImportNode;
break;
}
}
var onImported = this.onImported.bind(this, evaldImportNode, context), sequencedOnImported = this._sequencer.addImport(onImported);
this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.fileInfo(), evaldImportNode.options, sequencedOnImported);
}
else {
this.importCount--;
if (this.isFinished) {
this._sequencer.tryRun();
}
}
},
onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
if (e) {
if (!e.filename) {
e.index = importNode.getIndex();
e.filename = importNode.fileInfo().filename;
}
this.error = e;
}
var importVisitor = this, inlineCSS = importNode.options.inline, isPlugin = importNode.options.isPlugin, isOptional = importNode.options.optional, duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
if (!context.importMultiple) {
if (duplicateImport) {
importNode.skip = true;
}
else {
importNode.skip = function () {
if (fullPath in importVisitor.onceFileDetectionMap) {
return true;
}
importVisitor.onceFileDetectionMap[fullPath] = true;
return false;
};
}
}
if (!fullPath && isOptional) {
importNode.skip = true;
}
if (root) {
importNode.root = root;
importNode.importedFilename = fullPath;
if (!inlineCSS && !isPlugin && (context.importMultiple || !duplicateImport)) {
importVisitor.recursionDetector[fullPath] = true;
var oldContext = this.context;
this.context = context;
try {
this._visitor.visit(root);
}
catch (e) {
this.error = e;
}
this.context = oldContext;
}
}
importVisitor.importCount--;
if (importVisitor.isFinished) {
importVisitor._sequencer.tryRun();
}
},
visitDeclaration: function (declNode, visitArgs) {
if (declNode.value.type === 'DetachedRuleset') {
this.context.frames.unshift(declNode);
}
else {
visitArgs.visitDeeper = false;
}
},
visitDeclarationOut: function (declNode) {
if (declNode.value.type === 'DetachedRuleset') {
this.context.frames.shift();
}
},
visitAtRule: function (atRuleNode, visitArgs) {
if (atRuleNode.value) {
this.context.frames.unshift(atRuleNode);
}
else if (atRuleNode.declarations && atRuleNode.declarations.length) {
if (atRuleNode.isRooted) {
this.context.frames.unshift(atRuleNode);
}
else {
this.context.frames.unshift(atRuleNode.declarations[0]);
}
}
else if (atRuleNode.rules && atRuleNode.rules.length) {
this.context.frames.unshift(atRuleNode);
}
},
visitAtRuleOut: function (atRuleNode) {
this.context.frames.shift();
},
visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
this.context.frames.unshift(mixinDefinitionNode);
},
visitMixinDefinitionOut: function (mixinDefinitionNode) {
this.context.frames.shift();
},
visitRuleset: function (rulesetNode, visitArgs) {
this.context.frames.unshift(rulesetNode);
},
visitRulesetOut: function (rulesetNode) {
this.context.frames.shift();
},
visitMedia: function (mediaNode, visitArgs) {
this.context.frames.unshift(mediaNode.rules[0]);
},
visitMediaOut: function (mediaNode) {
this.context.frames.shift();
}
};
exports.default = ImportVisitor;
//# sourceMappingURL=import-visitor.js.map