Files
less.js/lib/less/tree/import.js
C. Scott Ananian 72c469d86e Implement syntax in gh #1185 for @import options. Implement multiple & less.
First step in implementing syntax for @import options, proposed in
https://github.com/cloudhead/less.js/issues/1185#issuecomment-13710620
(steps (1) and (2)).

I've implemented the 'multiple' and 'less' options.  One could trivially
add 'once' and 'css' options as well, if there was need.  Proposed
"silent" and "inline" options are deferred for future work.

I left the existing "@import-multiple" and "@import-once" syntax in place,
although the proposal is for this to be deprecated once the new option
syntax is in place.
2013-03-05 11:23:47 +00:00

101 lines
3.3 KiB
JavaScript

(function (tree) {
//
// CSS @import node
//
// The general strategy here is that we don't want to wait
// for the parsing to be completed, before we start importing
// the file. That's because in the context of a browser,
// most of the time will be spent waiting for the server to respond.
//
// On creation, we push the import path to our import queue, though
// `import,push`, we also pass it a callback, which it'll call once
// the file has been fetched, and parsed.
//
tree.Import = function (path, features, options, index, currentFileInfo) {
var that = this;
this.options = options;
this.index = index;
this.path = path;
this.features = features;
this.currentFileInfo = currentFileInfo;
var pathValue = this.getPath();
if (pathValue) {
this.css = /css([\?;].*)?$/.test(pathValue);
}
if (this.options.less) { this.css = false; }
};
//
// The actual import node doesn't return anything, when converted to CSS.
// The reason is that it's used at the evaluation stage, so that the rules
// it imports can be treated like any other rules.
//
// In `eval`, we make sure all Import nodes get evaluated, recursively, so
// we end up with a flat structure, which can easily be imported in the parent
// ruleset.
//
tree.Import.prototype = {
type: "Import",
accept: function (visitor) {
this.features = visitor.visit(this.features);
this.path = visitor.visit(this.path);
this.root = visitor.visit(this.root);
},
toCSS: function (env) {
var features = this.features ? ' ' + this.features.toCSS(env) : '';
if (this.css) {
return "@import " + this.path.toCSS() + features + ';\n';
} else {
return "";
}
},
getPath: function () {
if (this.path instanceof tree.Quoted) {
var path = this.path.value;
return (this.css || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less';
} else if (this.path instanceof tree.URL) {
return this.path.value.value;
}
return null;
},
evalForImport: function (env) {
return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo);
},
evalPath: function (env) {
var path = this.path.eval(env);
var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
if (rootpath && !(path instanceof tree.URL)) {
var pathValue = path.value;
// Add the base path if the import is relative
if (pathValue && env.isPathRelative(pathValue)) {
path.value = rootpath + pathValue;
}
}
return path;
},
eval: function (env) {
var ruleset, features = this.features && this.features.eval(env);
if (this.skip) { return []; }
if (this.css) {
var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index);
if (!newImport.css && this.error) {
throw this.error;
}
return newImport;
} else {
ruleset = new(tree.Ruleset)([], this.root.rules.slice(0));
ruleset.evalImports(env);
return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules;
}
}
};
})(require('../tree'));