123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- 'use strict';
-
- /*!
- * Jade
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
-
- /**
- * Module dependencies.
- */
-
- var Parser = require('./parser')
- , Lexer = require('./lexer')
- , Compiler = require('./compiler')
- , runtime = require('./runtime')
- , addWith = require('with')
- , fs = require('fs');
-
- /**
- * Expose self closing tags.
- */
-
- exports.selfClosing = require('void-elements');
-
- /**
- * Default supported doctypes.
- */
-
- exports.doctypes = require('./doctypes');
-
- /**
- * Text filters.
- */
-
- exports.filters = require('./filters');
-
- /**
- * Utilities.
- */
-
- exports.utils = require('./utils');
-
- /**
- * Expose `Compiler`.
- */
-
- exports.Compiler = Compiler;
-
- /**
- * Expose `Parser`.
- */
-
- exports.Parser = Parser;
-
- /**
- * Expose `Lexer`.
- */
-
- exports.Lexer = Lexer;
-
- /**
- * Nodes.
- */
-
- exports.nodes = require('./nodes');
-
- /**
- * Jade runtime helpers.
- */
-
- exports.runtime = runtime;
-
- /**
- * Template function cache.
- */
-
- exports.cache = {};
-
- /**
- * Parse the given `str` of jade and return a function body.
- *
- * @param {String} str
- * @param {Object} options
- * @return {Object}
- * @api private
- */
-
- function parse(str, options){
- // Parse
- var parser = new (options.parser || Parser)(str, options.filename, options);
- var tokens;
- try {
- // Parse
- tokens = parser.parse();
- } catch (err) {
- parser = parser.context();
- runtime.rethrow(err, parser.filename, parser.lexer.lineno, parser.input);
- }
-
- // Compile
- var compiler = new (options.compiler || Compiler)(tokens, options);
- var js;
- try {
- js = compiler.compile();
- } catch (err) {
- if (err.line && (err.filename || !options.filename)) {
- runtime.rethrow(err, err.filename, err.line, parser.input);
- }
- }
-
- // Debug compiler
- if (options.debug) {
- console.error('\nCompiled Function:\n\n\u001b[90m%s\u001b[0m', js.replace(/^/gm, ' '));
- }
-
- var globals = [];
-
- globals.push('jade');
- globals.push('jade_mixins');
- globals.push('jade_interp');
- globals.push('jade_debug');
- globals.push('buf');
-
- var body = ''
- + 'var buf = [];\n'
- + 'var jade_mixins = {};\n'
- + 'var jade_interp;\n'
- + (options.self
- ? 'var self = locals || {};\n' + js
- : addWith('locals || {}', '\n' + js, globals)) + ';'
- + 'return buf.join("");';
- return {body: body, dependencies: parser.dependencies};
- }
-
- /**
- * Compile a `Function` representation of the given jade `str`.
- *
- * Options:
- *
- * - `compileDebug` when `false` debugging code is stripped from the compiled
- template, when it is explicitly `true`, the source code is included in
- the compiled template for better accuracy.
- * - `filename` used to improve errors when `compileDebug` is not `false` and to resolve imports/extends
- *
- * @param {String} str
- * @param {Options} options
- * @return {Function}
- * @api public
- */
-
- exports.compile = function(str, options){
- var options = options || {}
- , filename = options.filename
- ? JSON.stringify(options.filename)
- : 'undefined'
- , fn;
-
- str = String(str);
-
- var parsed = parse(str, options);
- if (options.compileDebug !== false) {
- fn = [
- 'var jade_debug = [{ lineno: 1, filename: ' + filename + ' }];'
- , 'try {'
- , parsed.body
- , '} catch (err) {'
- , ' jade.rethrow(err, jade_debug[0].filename, jade_debug[0].lineno' + (options.compileDebug === true ? ',' + JSON.stringify(str) : '') + ');'
- , '}'
- ].join('\n');
- } else {
- fn = parsed.body;
- }
- fn = new Function('locals, jade', fn)
- var res = function(locals){ return fn(locals, Object.create(runtime)) };
- if (options.client) {
- res.toString = function () {
- var err = new Error('The `client` option is deprecated, use the `jade.compileClient` method instead');
- err.name = 'Warning';
- console.error(err.stack || err.message);
- return exports.compileClient(str, options);
- };
- }
- res.dependencies = parsed.dependencies;
- return res;
- };
-
- /**
- * Compile a JavaScript source representation of the given jade `str`.
- *
- * Options:
- *
- * - `compileDebug` When it is `true`, the source code is included in
- * the compiled template for better error messages.
- * - `filename` used to improve errors when `compileDebug` is not `true` and to resolve imports/extends
- * - `name` the name of the resulting function (defaults to "template")
- *
- * @param {String} str
- * @param {Options} options
- * @return {String}
- * @api public
- */
-
- exports.compileClient = function(str, options){
- var options = options || {};
- var name = options.name || 'template';
- var filename = options.filename ? JSON.stringify(options.filename) : 'undefined';
- var fn;
-
- str = String(str);
-
- if (options.compileDebug) {
- options.compileDebug = true;
- fn = [
- 'var jade_debug = [{ lineno: 1, filename: ' + filename + ' }];'
- , 'try {'
- , parse(str, options).body
- , '} catch (err) {'
- , ' jade.rethrow(err, jade_debug[0].filename, jade_debug[0].lineno, ' + JSON.stringify(str) + ');'
- , '}'
- ].join('\n');
- } else {
- options.compileDebug = false;
- fn = parse(str, options).body;
- }
-
- return 'function ' + name + '(locals) {\n' + fn + '\n}';
- };
-
- /**
- * Compile a `Function` representation of the given jade file.
- *
- * Options:
- *
- * - `compileDebug` when `false` debugging code is stripped from the compiled
- template, when it is explicitly `true`, the source code is included in
- the compiled template for better accuracy.
- *
- * @param {String} path
- * @param {Options} options
- * @return {Function}
- * @api public
- */
- exports.compileFile = function (path, options) {
- options = options || {};
-
- var key = path + ':string';
-
- options.filename = path;
- var str = options.cache
- ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
- : fs.readFileSync(path, 'utf8');
-
- return options.cache
- ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
- : exports.compile(str, options);
- };
-
- /**
- * Render the given `str` of jade.
- *
- * Options:
- *
- * - `cache` enable template caching
- * - `filename` filename required for `include` / `extends` and caching
- *
- * @param {String} str
- * @param {Object|Function} options or fn
- * @param {Function|undefined} fn
- * @returns {String}
- * @api public
- */
-
- exports.render = function(str, options, fn){
- // support callback API
- if ('function' == typeof options) {
- fn = options, options = undefined;
- }
- if (typeof fn === 'function') {
- var res
- try {
- res = exports.render(str, options);
- } catch (ex) {
- return fn(ex);
- }
- return fn(null, res);
- }
-
- options = options || {};
-
- // cache requires .filename
- if (options.cache && !options.filename) {
- throw new Error('the "filename" option is required for caching');
- }
-
- var path = options.filename;
- var tmpl = options.cache
- ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
- : exports.compile(str, options);
- return tmpl(options);
- };
-
- /**
- * Render a Jade file at the given `path`.
- *
- * @param {String} path
- * @param {Object|Function} options or callback
- * @param {Function|undefined} fn
- * @returns {String}
- * @api public
- */
-
- exports.renderFile = function(path, options, fn){
- // support callback API
- if ('function' == typeof options) {
- fn = options, options = undefined;
- }
- if (typeof fn === 'function') {
- var res
- try {
- res = exports.renderFile(path, options);
- } catch (ex) {
- return fn(ex);
- }
- return fn(null, res);
- }
-
- options = options || {};
-
- var key = path + ':string';
-
- options.filename = path;
- var str = options.cache
- ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
- : fs.readFileSync(path, 'utf8');
- return exports.render(str, options);
- };
-
-
- /**
- * Compile a Jade file at the given `path` for use on the client.
- *
- * @param {String} path
- * @param {Object} options
- * @returns {String}
- * @api public
- */
-
- exports.compileFileClient = function(path, options){
- options = options || {};
-
- var key = path + ':string';
-
- options.filename = path;
- var str = options.cache
- ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
- : fs.readFileSync(path, 'utf8');
-
- return exports.compileClient(str, options);
- };
-
- /**
- * Express support.
- */
-
- exports.__express = exports.renderFile;
|