Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
295 changes: 152 additions & 143 deletions lib/mu.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,168 +6,177 @@ var util = require('util'),
renderer = require('./mu/renderer'),
errors = require('./mu/errors');

var mu = module.exports = {};
// create a mu instance for backwards compatibility
module.exports = createMu(process.cwd());

mu.root = process.cwd();
mu.cache = {};
// provide a mu factory function
module.exports.createMu = createMu;

mu.fs = function (filename, callback) {
filename = filename.indexOf('/') === 0 || filename.indexOf(':\\') === 1 ? filename : path.join(mu.root, filename);
fs.readFile(filename, 'utf8', callback);
}
function createMu(root) {
var mu = {};

/**
* Compiles a file. The result will be cached as the filename and can be
* rendered via that name.
*
* @param {String} filename The name of the file to compile. If the filename
* starts with a '/', the file is assumed to be absolute, else it is
* relative to mu.root.
* @param {Function(err, Parsed)} callback The function to call when the file has been compiled.
*/
mu.compile = function(filename, callback, unique) {
var parsed,
unique = unique || {};

mu.fs(filename, function (err, contents) {
if (err) {
callback(new Error('file_not_found'));//errors.fileNotFound(mu.root, filename, err)));
}

parsed = parser.parse(contents);
mu.cache[filename] = [parsed, unique];
mu.root = root;
mu.cache = {};

var i = 0;
(function next(err) {
if (err) {
return callback(err);
}
mu.fs = function (filename, callback) {
filename = filename.indexOf('/') === 0 || filename.indexOf(':\\') === 1 ? filename : path.join(mu.root, filename);
fs.readFile(filename, 'utf8', callback);
}

if (i < parsed.partials.length) {
mu.compile(parsed.partials[i], next, unique);
i++;

} else {
callback(undefined, [parsed, {}]);
/**
* Compiles a file. The result will be cached as the filename and can be
* rendered via that name.
*
* @param {String} filename The name of the file to compile. If the filename
* starts with a '/', the file is assumed to be absolute, else it is
* relative to mu.root.
* @param {Function(err, Parsed)} callback The function to call when the file has been compiled.
*/
mu.compile = function(filename, callback, unique) {
var parsed,
unique = unique || {};

mu.fs(filename, function (err, contents) {
if (err) {
callback(new Error('file_not_found'));//errors.fileNotFound(mu.root, filename, err)));
}
}());
});
}

/**
* Compiles a string into the parsed form. If `name` is provided the text
* will be cached by that name. Alternatively you can pass the return
* into mu.render.
*
* @param {String} name (Optional) The name to cache the parsed form as.
* @param {String} template The template to parse.
* @param {Function(err, Parsed)} callback (Optional) An optional callback that
* will be called when the text is parsed. This is only to unify the
* API with mu.compile.
*
* @returns {Parsed} The parsed template unless `callback` is provided.
*/
mu.compileText = function (name, template, callback) {
var parsed;

if (typeof template === 'undefined') {
template = name;
name = undefined;

parsed = parser.parse(contents);
mu.cache[filename] = [parsed, unique];

var i = 0;
(function next(err) {
if (err) {
return callback(err);
}

if (i < parsed.partials.length) {
mu.compile(parsed.partials[i], next, unique);
i++;

} else {
callback(undefined, [parsed, {}]);
}
}());
});
}

try {
parsed = parser.parse(template);

/**
* Compiles a string into the parsed form. If `name` is provided the text
* will be cached by that name. Alternatively you can pass the return
* into mu.render.
*
* @param {String} name (Optional) The name to cache the parsed form as.
* @param {String} template The template to parse.
* @param {Function(err, Parsed)} callback (Optional) An optional callback that
* will be called when the text is parsed. This is only to unify the
* API with mu.compile.
*
* @returns {Parsed} The parsed template unless `callback` is provided.
*/
mu.compileText = function (name, template, callback) {
var parsed;

if (name) {
mu.cache[name] = [parsed, {}];
if (typeof template === 'undefined') {
template = name;
name = undefined;
}

if (callback) callback(undefined, parsed); else return parsed;

} catch (err) {
if (callback) callback(err); else throw err;
}
}
try {
parsed = parser.parse(template);

if (name) {
mu.cache[name] = [parsed, {}];
}

/**
* Renders the previously parsed filename or the parsed object.
*
* @param {String|Parsed} filenameOrParsed Filename or parsed object to render.
* @param {Object} view The data to use when renderings.
*
* @returns {Stream} The render stream.
* @throws {Error(template_not_in_cache)} If filename was not found in cache.
*/
mu.render = function (filenameOrParsed, view) {
var stream,
parsed = typeof filenameOrParsed === 'object' ?
filenameOrParsed :
mu.cache[filenameOrParsed];

if (parsed) {
return beginRender(parsed[0].tokens, view, mu.cache);
} else {
throw new Error('template_not_in_cache'); //errors.templateNotInCache(filename)));
if (callback) callback(undefined, parsed); else return parsed;

} catch (err) {
if (callback) callback(err); else throw err;
}
}
}

mu.renderText = function (template, view, partials) {
var name, parsed, tokens, stream;

partials = partials || {};
partials = shallowCopy(partials);
partials.__proto__ = mu.cache;

for (name in partials) {
if (partials.hasOwnProperty(name) && !partials[name].tokens) {
partials[name] = parser.parse(partials[name]);
/**
* Renders the previously parsed filename or the parsed object.
*
* @param {String|Parsed} filenameOrParsed Filename or parsed object to render.
* @param {Object} view The data to use when renderings.
*
* @returns {Stream} The render stream.
* @throws {Error(template_not_in_cache)} If filename was not found in cache.
*/
mu.render = function (filenameOrParsed, view) {
var stream,
parsed = typeof filenameOrParsed === 'object' ?
filenameOrParsed :
mu.cache[filenameOrParsed];

if (parsed) {
return beginRender(parsed[0].tokens, view, mu.cache);
} else {
throw new Error('template_not_in_cache'); //errors.templateNotInCache(filename)));
}
}

parsed = parser.parse(template);
tokens = parsed.tokens;

return beginRender(tokens, view, partials);
}

/**
* Clears all of the cache or a specific template.
*
* @param templateName String If provided only that template is removed from
* the cache, else everything is.
*/
mu.clearCache = function (templateName) {
if (templateName) {
delete mu.cache[templateName];
} else {
mu.cache = {};
mu.renderText = function (template, view, partials) {
var name, parsed, tokens, stream;

partials = partials || {};
partials = shallowCopy(partials);
partials.__proto__ = mu.cache;

for (name in partials) {
if (partials.hasOwnProperty(name) && !partials[name].tokens) {
partials[name] = parser.parse(partials[name]);
}
}

parsed = parser.parse(template);
tokens = parsed.tokens;

return beginRender(tokens, view, partials);
}
};

/**
* Compiles the template and then renders it. Uses the cache if it
* is available.
*
* @param templateName String The name of the template to render
* @param view Object The view object to inject into the template upon render
* @returns Stream THe output stream
*/
mu.compileAndRender = function (templateName, view) {
var stream = new Stream();
var parsed = mu.cache[templateName];

if (parsed) {
beginRenderWithStream(parsed[0].tokens, view, mu.cache, stream);
} else {
mu.compile(templateName, function (err, parsed) {
if (err) return stream.emit('error', err);

/**
* Clears all of the cache or a specific template.
*
* @param templateName String If provided only that template is removed from
* the cache, else everything is.
*/
mu.clearCache = function (templateName) {
if (templateName) {
delete mu.cache[templateName];
} else {
mu.cache = {};
}
};

/**
* Compiles the template and then renders it. Uses the cache if it
* is available.
*
* @param templateName String The name of the template to render
* @param view Object The view object to inject into the template upon render
* @returns Stream THe output stream
*/
mu.compileAndRender = function (templateName, view) {
var stream = new Stream();
var parsed = mu.cache[templateName];

if (parsed) {
beginRenderWithStream(parsed[0].tokens, view, mu.cache, stream);
});
}

return stream;
};
} else {
mu.compile(templateName, function (err, parsed) {
if (err) return stream.emit('error', err);
beginRenderWithStream(parsed[0].tokens, view, mu.cache, stream);
});
}

return stream;
};

return mu;
}

/// Private API

Expand Down