mirror of
https://github.com/less/less.js.git
synced 2026-05-01 03:00:22 -04:00
refactored the import mechanism, added some doc
This commit is contained in:
@@ -50,22 +50,28 @@ less.Parser = function Parser(env) {
|
||||
inputLength,
|
||||
parser;
|
||||
|
||||
var import = {
|
||||
paths: env && env.paths || [],
|
||||
finish: function () {},
|
||||
stack: [],
|
||||
push: function (path, callback) {
|
||||
var that = this;
|
||||
var stack = this.stack;
|
||||
stack.push(path);
|
||||
// This function is called after all files
|
||||
// have been imported through `@import`.
|
||||
var finish = function () {};
|
||||
|
||||
var imports = this.imports = {
|
||||
paths: env && env.paths || [], // Search paths, when importing
|
||||
queue: [], // Files which haven't been imported yet
|
||||
files: {}, // Holds the imported parse trees
|
||||
push: function (path, callback) {
|
||||
this.queue.push(path);
|
||||
|
||||
//
|
||||
// Import a file asynchronously
|
||||
//
|
||||
less.Parser.importer(path, this.paths, function (root) {
|
||||
this.queue.splice(this.queue.indexOf(path), 1); // Remove the path from the queue
|
||||
this.files[path] = root; // Store the root
|
||||
|
||||
callback(root);
|
||||
stack.splice(stack.indexOf(path), 1)
|
||||
if (stack.length === 0) {
|
||||
that.finish();
|
||||
}
|
||||
});
|
||||
|
||||
if (this.queue.length === 0) { finish() } // Call `finish` if we're done importing
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -161,7 +167,7 @@ less.Parser = function Parser(env) {
|
||||
//
|
||||
return parser = {
|
||||
|
||||
import: import,
|
||||
imports: imports,
|
||||
//
|
||||
// Parse an input string into an abstract syntax tree,
|
||||
// call `callback` when done.
|
||||
@@ -229,8 +235,8 @@ less.Parser = function Parser(env) {
|
||||
error = { name: "ParseError", message: "Parse Error on line " + line + ":\n" + zone };
|
||||
}
|
||||
|
||||
if (import.stack.length > 0) {
|
||||
import.finish = function () { callback(error, root) };
|
||||
if (this.imports.queue.length > 0) {
|
||||
finish = function () { callback(error, root) };
|
||||
} else {
|
||||
callback(error, root);
|
||||
}
|
||||
@@ -721,7 +727,7 @@ less.Parser = function Parser(env) {
|
||||
if ($(/@import\s+/g) &&
|
||||
(path = $(this.entities.quoted) || $(this.entities.url)) &&
|
||||
$(';')) {
|
||||
return new(tree.Import)(path, import);
|
||||
return new(tree.Import)(path, imports);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -7,23 +7,11 @@ if (typeof(require) !== 'undefined') { var tree = require('less/tree') }
|
||||
// the file. That's because in the context of a browser,
|
||||
// most of the time will be spent waiting for the server to respond.
|
||||
//
|
||||
// What we do is pass the `importer` function a callback, which it
|
||||
// will call when the file is available. Meanwhile, we continue parsing
|
||||
// the input. The `eval` function also takes a callback, which we call
|
||||
// inside the first callback [2a], depending on what was called first.
|
||||
// At this point, two things can happen:
|
||||
// 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.
|
||||
//
|
||||
// 1. The import is loaded and parsed before the current file finishes
|
||||
// parsing, in which case, we save the imported rules in `this.rules` [1a],
|
||||
// and when `this.eval` is called (during code-gen), we pass the
|
||||
// imported rules to the callback [1b].
|
||||
//
|
||||
// 2. The current file finishes parsing before the import.
|
||||
// In this case, the rules aren't available yet, so we save
|
||||
// the callback in `this.callback` [2b], which will be called when
|
||||
// the importer is done [2a].
|
||||
//
|
||||
tree.Import = function Import(path, import) {
|
||||
tree.Import = function Import(path, imports) {
|
||||
var that = this;
|
||||
|
||||
// The '.less' extension is optional
|
||||
@@ -33,10 +21,20 @@ tree.Import = function Import(path, import) {
|
||||
this.path = path.value.content || path.value;
|
||||
}
|
||||
|
||||
import.push(this.path, function (root) {
|
||||
that.root = root; // 1a.
|
||||
imports.push(this.path, function (root) {
|
||||
that.root = root;
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// 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 = {
|
||||
toCSS: function () { return "" },
|
||||
eval: function () {
|
||||
|
||||
Reference in New Issue
Block a user