Created
May 13, 2013 20:10
-
-
Save danieldkim/5571080 to your computer and use it in GitHub Desktop.
browserified standalone [email protected]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(e){if("function"==typeof bootstrap)bootstrap("jade",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeJade=e}else"undefined"!=typeof window?window.jade=e():global.jade=e()})(function(){var define,ses,bootstrap,module,exports; | |
return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){ | |
// nothing to see here... no file methods for the browser | |
},{}],2:[function(require,module,exports){ | |
/*! | |
* Jade | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Parser = require('./parser') | |
, Lexer = require('./lexer') | |
, Compiler = require('./compiler') | |
, runtime = require('./runtime') | |
// if node | |
, fs = require('fs'); | |
// end | |
/** | |
* Library version. | |
*/ | |
exports.version = '0.30.0'; | |
/** | |
* Expose self closing tags. | |
*/ | |
exports.selfClosing = require('./self-closing'); | |
/** | |
* 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 {String} | |
* @api private | |
*/ | |
function parse(str, options){ | |
try { | |
// Parse | |
var parser = new Parser(str, options.filename, options); | |
// Compile | |
var compiler = new (options.compiler || Compiler)(parser.parse(), options) | |
, js = compiler.compile(); | |
// Debug compiler | |
if (options.debug) { | |
console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' ')); | |
} | |
return '' | |
+ 'var buf = [];\n' | |
+ (options.self | |
? 'var self = locals || {};\n' + js | |
: 'with (locals || {}) {\n' + js + '\n}\n') | |
+ 'return buf.join("");'; | |
} catch (err) { | |
parser = parser.context(); | |
runtime.rethrow(err, parser.filename, parser.lexer.lineno); | |
} | |
} | |
/** | |
* Strip any UTF-8 BOM off of the start of `str`, if it exists. | |
* | |
* @param {String} str | |
* @return {String} | |
* @api private | |
*/ | |
function stripBOM(str){ | |
return 0xFEFF == str.charCodeAt(0) | |
? str.substring(1) | |
: str; | |
} | |
/** | |
* Compile a `Function` representation of the given jade `str`. | |
* | |
* Options: | |
* | |
* - `compileDebug` when `false` debugging code is stripped from the compiled template | |
* - `filename` used to improve errors when `compileDebug` is not `false` | |
* | |
* @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 = stripBOM(String(str)); | |
if (options.compileDebug !== false) { | |
fn = [ | |
'jade.debug = [{ lineno: 1, filename: ' + filename + ' }];' | |
, 'try {' | |
, parse(str, options) | |
, '} catch (err) {' | |
, ' jade.rethrow(err, jade.debug[0].filename, jade.debug[0].lineno);' | |
, '}' | |
].join('\n'); | |
} else { | |
fn = parse(str, options); | |
} | |
if (options.client) return new Function('locals', fn) | |
fn = new Function('locals, jade', fn) | |
return function(locals){ return fn(locals, Object.create(runtime)) } | |
}; | |
/** | |
* Render the given `str` of jade and invoke | |
* the callback `fn(err, str)`. | |
* | |
* Options: | |
* | |
* - `cache` enable template caching | |
* - `filename` filename required for `include` / `extends` and caching | |
* | |
* @param {String} str | |
* @param {Object|Function} options or fn | |
* @param {Function} fn | |
* @api public | |
*/ | |
exports.render = function(str, options, fn){ | |
// swap args | |
if ('function' == typeof options) { | |
fn = options, options = {}; | |
} | |
// cache requires .filename | |
if (options.cache && !options.filename) { | |
return fn(new Error('the "filename" option is required for caching')); | |
} | |
try { | |
var path = options.filename; | |
var tmpl = options.cache | |
? exports.cache[path] || (exports.cache[path] = exports.compile(str, options)) | |
: exports.compile(str, options); | |
fn(null, tmpl(options)); | |
} catch (err) { | |
fn(err); | |
} | |
}; | |
/** | |
* Render a Jade file at the given `path` and callback `fn(err, str)`. | |
* | |
* @param {String} path | |
* @param {Object|Function} options or callback | |
* @param {Function} fn | |
* @api public | |
*/ | |
exports.renderFile = function(path, options, fn){ | |
var key = path + ':string'; | |
if ('function' == typeof options) { | |
fn = options, options = {}; | |
} | |
try { | |
options.filename = path; | |
var str = options.cache | |
? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8')) | |
: fs.readFileSync(path, 'utf8'); | |
exports.render(str, options, fn); | |
} catch (err) { | |
fn(err); | |
} | |
}; | |
/** | |
* Express support. | |
*/ | |
exports.__express = exports.renderFile; | |
},{"fs":1,"./parser":3,"./lexer":4,"./compiler":5,"./runtime":6,"./self-closing":7,"./doctypes":8,"./filters":9,"./utils":10,"./nodes":11}],6:[function(require,module,exports){ | |
/*! | |
* Jade - runtime | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Lame Array.isArray() polyfill for now. | |
*/ | |
if (!Array.isArray) { | |
Array.isArray = function(arr){ | |
return '[object Array]' == Object.prototype.toString.call(arr); | |
}; | |
} | |
/** | |
* Lame Object.keys() polyfill for now. | |
*/ | |
if (!Object.keys) { | |
Object.keys = function(obj){ | |
var arr = []; | |
for (var key in obj) { | |
if (obj.hasOwnProperty(key)) { | |
arr.push(key); | |
} | |
} | |
return arr; | |
} | |
} | |
/** | |
* Merge two attribute objects giving precedence | |
* to values in object `b`. Classes are special-cased | |
* allowing for arrays and merging/joining appropriately | |
* resulting in a string. | |
* | |
* @param {Object} a | |
* @param {Object} b | |
* @return {Object} a | |
* @api private | |
*/ | |
exports.merge = function merge(a, b) { | |
var ac = a['class']; | |
var bc = b['class']; | |
if (ac || bc) { | |
ac = ac || []; | |
bc = bc || []; | |
if (!Array.isArray(ac)) ac = [ac]; | |
if (!Array.isArray(bc)) bc = [bc]; | |
ac = ac.filter(nulls); | |
bc = bc.filter(nulls); | |
a['class'] = ac.concat(bc).join(' '); | |
} | |
for (var key in b) { | |
if (key != 'class') { | |
a[key] = b[key]; | |
} | |
} | |
return a; | |
}; | |
/** | |
* Filter null `val`s. | |
* | |
* @param {Mixed} val | |
* @return {Mixed} | |
* @api private | |
*/ | |
function nulls(val) { | |
return val != null; | |
} | |
/** | |
* Render the given attributes object. | |
* | |
* @param {Object} obj | |
* @param {Object} escaped | |
* @return {String} | |
* @api private | |
*/ | |
exports.attrs = function attrs(obj, escaped){ | |
var buf = [] | |
, terse = obj.terse; | |
delete obj.terse; | |
var keys = Object.keys(obj) | |
, len = keys.length; | |
if (len) { | |
buf.push(''); | |
for (var i = 0; i < len; ++i) { | |
var key = keys[i] | |
, val = obj[key]; | |
if ('boolean' == typeof val || null == val) { | |
if (val) { | |
terse | |
? buf.push(key) | |
: buf.push(key + '="' + key + '"'); | |
} | |
} else if (0 == key.indexOf('data') && 'string' != typeof val) { | |
buf.push(key + "='" + JSON.stringify(val) + "'"); | |
} else if ('class' == key && Array.isArray(val)) { | |
buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); | |
} else if (escaped && escaped[key]) { | |
buf.push(key + '="' + exports.escape(val) + '"'); | |
} else { | |
buf.push(key + '="' + val + '"'); | |
} | |
} | |
} | |
return buf.join(' '); | |
}; | |
/** | |
* Escape the given string of `html`. | |
* | |
* @param {String} html | |
* @return {String} | |
* @api private | |
*/ | |
exports.escape = function escape(html){ | |
return String(html) | |
.replace(/&/g, '&') | |
.replace(/</g, '<') | |
.replace(/>/g, '>') | |
.replace(/"/g, '"'); | |
}; | |
/** | |
* Re-throw the given `err` in context to the | |
* the jade in `filename` at the given `lineno`. | |
* | |
* @param {Error} err | |
* @param {String} filename | |
* @param {String} lineno | |
* @api private | |
*/ | |
exports.rethrow = function rethrow(err, filename, lineno){ | |
if (!filename) throw err; | |
if (typeof window != 'undefined') throw err; | |
var context = 3 | |
, str = require('fs').readFileSync(filename, 'utf8') | |
, lines = str.split('\n') | |
, start = Math.max(lineno - context, 0) | |
, end = Math.min(lines.length, lineno + context); | |
// Error context | |
var context = lines.slice(start, end).map(function(line, i){ | |
var curr = i + start + 1; | |
return (curr == lineno ? ' > ' : ' ') | |
+ curr | |
+ '| ' | |
+ line; | |
}).join('\n'); | |
// Alter exception message | |
err.path = filename; | |
err.message = (filename || 'Jade') + ':' + lineno | |
+ '\n' + context + '\n\n' + err.message; | |
throw err; | |
}; | |
},{"fs":1}],7:[function(require,module,exports){ | |
/*! | |
* Jade - self closing tags | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
module.exports = [ | |
'meta' | |
, 'img' | |
, 'link' | |
, 'input' | |
, 'source' | |
, 'area' | |
, 'base' | |
, 'col' | |
, 'br' | |
, 'hr' | |
]; | |
},{}],8:[function(require,module,exports){ | |
/*! | |
* Jade - doctypes | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
module.exports = { | |
'5': '<!DOCTYPE html>' | |
, 'default': '<!DOCTYPE html>' | |
, 'xml': '<?xml version="1.0" encoding="utf-8" ?>' | |
, 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' | |
, 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' | |
, 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">' | |
, '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' | |
, 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">' | |
, 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">' | |
}; | |
},{}],10:[function(require,module,exports){ | |
/*! | |
* Jade - utils | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Merge `b` into `a`. | |
* | |
* @param {Object} a | |
* @param {Object} b | |
* @return {Object} | |
* @api public | |
*/ | |
exports.merge = function(a, b) { | |
for (var key in b) a[key] = b[key]; | |
return a; | |
}; | |
},{}],12:[function(require,module,exports){ | |
// shim for using process in browser | |
var process = module.exports = {}; | |
process.nextTick = (function () { | |
var canSetImmediate = typeof window !== 'undefined' | |
&& window.setImmediate; | |
var canPost = typeof window !== 'undefined' | |
&& window.postMessage && window.addEventListener | |
; | |
if (canSetImmediate) { | |
return function (f) { return window.setImmediate(f) }; | |
} | |
if (canPost) { | |
var queue = []; | |
window.addEventListener('message', function (ev) { | |
if (ev.source === window && ev.data === 'process-tick') { | |
ev.stopPropagation(); | |
if (queue.length > 0) { | |
var fn = queue.shift(); | |
fn(); | |
} | |
} | |
}, true); | |
return function nextTick(fn) { | |
queue.push(fn); | |
window.postMessage('process-tick', '*'); | |
}; | |
} | |
return function nextTick(fn) { | |
setTimeout(fn, 0); | |
}; | |
})(); | |
process.title = 'browser'; | |
process.browser = true; | |
process.env = {}; | |
process.argv = []; | |
process.binding = function (name) { | |
throw new Error('process.binding is not supported'); | |
} | |
// TODO(shtylman) | |
process.cwd = function () { return '/' }; | |
process.chdir = function (dir) { | |
throw new Error('process.chdir is not supported'); | |
}; | |
},{}],13:[function(require,module,exports){ | |
(function(process){function filter (xs, fn) { | |
var res = []; | |
for (var i = 0; i < xs.length; i++) { | |
if (fn(xs[i], i, xs)) res.push(xs[i]); | |
} | |
return res; | |
} | |
// resolves . and .. elements in a path array with directory names there | |
// must be no slashes, empty elements, or device names (c:\) in the array | |
// (so also no leading and trailing slashes - it does not distinguish | |
// relative and absolute paths) | |
function normalizeArray(parts, allowAboveRoot) { | |
// if the path tries to go above the root, `up` ends up > 0 | |
var up = 0; | |
for (var i = parts.length; i >= 0; i--) { | |
var last = parts[i]; | |
if (last == '.') { | |
parts.splice(i, 1); | |
} else if (last === '..') { | |
parts.splice(i, 1); | |
up++; | |
} else if (up) { | |
parts.splice(i, 1); | |
up--; | |
} | |
} | |
// if the path is allowed to go above the root, restore leading ..s | |
if (allowAboveRoot) { | |
for (; up--; up) { | |
parts.unshift('..'); | |
} | |
} | |
return parts; | |
} | |
// Regex to split a filename into [*, dir, basename, ext] | |
// posix version | |
var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; | |
// path.resolve([from ...], to) | |
// posix version | |
exports.resolve = function() { | |
var resolvedPath = '', | |
resolvedAbsolute = false; | |
for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { | |
var path = (i >= 0) | |
? arguments[i] | |
: process.cwd(); | |
// Skip empty and invalid entries | |
if (typeof path !== 'string' || !path) { | |
continue; | |
} | |
resolvedPath = path + '/' + resolvedPath; | |
resolvedAbsolute = path.charAt(0) === '/'; | |
} | |
// At this point the path should be resolved to a full absolute path, but | |
// handle relative paths to be safe (might happen when process.cwd() fails) | |
// Normalize the path | |
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { | |
return !!p; | |
}), !resolvedAbsolute).join('/'); | |
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; | |
}; | |
// path.normalize(path) | |
// posix version | |
exports.normalize = function(path) { | |
var isAbsolute = path.charAt(0) === '/', | |
trailingSlash = path.slice(-1) === '/'; | |
// Normalize the path | |
path = normalizeArray(filter(path.split('/'), function(p) { | |
return !!p; | |
}), !isAbsolute).join('/'); | |
if (!path && !isAbsolute) { | |
path = '.'; | |
} | |
if (path && trailingSlash) { | |
path += '/'; | |
} | |
return (isAbsolute ? '/' : '') + path; | |
}; | |
// posix version | |
exports.join = function() { | |
var paths = Array.prototype.slice.call(arguments, 0); | |
return exports.normalize(filter(paths, function(p, index) { | |
return p && typeof p === 'string'; | |
}).join('/')); | |
}; | |
exports.dirname = function(path) { | |
var dir = splitPathRe.exec(path)[1] || ''; | |
var isWindows = false; | |
if (!dir) { | |
// No dirname | |
return '.'; | |
} else if (dir.length === 1 || | |
(isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { | |
// It is just a slash or a drive letter with a slash | |
return dir; | |
} else { | |
// It is a full dirname, strip trailing slash | |
return dir.substring(0, dir.length - 1); | |
} | |
}; | |
exports.basename = function(path, ext) { | |
var f = splitPathRe.exec(path)[2] || ''; | |
// TODO: make this comparison case-insensitive on windows? | |
if (ext && f.substr(-1 * ext.length) === ext) { | |
f = f.substr(0, f.length - ext.length); | |
} | |
return f; | |
}; | |
exports.extname = function(path) { | |
return splitPathRe.exec(path)[3] || ''; | |
}; | |
exports.relative = function(from, to) { | |
from = exports.resolve(from).substr(1); | |
to = exports.resolve(to).substr(1); | |
function trim(arr) { | |
var start = 0; | |
for (; start < arr.length; start++) { | |
if (arr[start] !== '') break; | |
} | |
var end = arr.length - 1; | |
for (; end >= 0; end--) { | |
if (arr[end] !== '') break; | |
} | |
if (start > end) return []; | |
return arr.slice(start, end - start + 1); | |
} | |
var fromParts = trim(from.split('/')); | |
var toParts = trim(to.split('/')); | |
var length = Math.min(fromParts.length, toParts.length); | |
var samePartsLength = length; | |
for (var i = 0; i < length; i++) { | |
if (fromParts[i] !== toParts[i]) { | |
samePartsLength = i; | |
break; | |
} | |
} | |
var outputParts = []; | |
for (var i = samePartsLength; i < fromParts.length; i++) { | |
outputParts.push('..'); | |
} | |
outputParts = outputParts.concat(toParts.slice(samePartsLength)); | |
return outputParts.join('/'); | |
}; | |
})(require("__browserify_process")) | |
},{"__browserify_process":12}],3:[function(require,module,exports){ | |
/*! | |
* Jade - Parser | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Lexer = require('./lexer') | |
, nodes = require('./nodes') | |
, utils = require('./utils') | |
, filters = require('./filters') | |
, path = require('path') | |
, extname = path.extname; | |
/** | |
* Initialize `Parser` with the given input `str` and `filename`. | |
* | |
* @param {String} str | |
* @param {String} filename | |
* @param {Object} options | |
* @api public | |
*/ | |
var Parser = exports = module.exports = function Parser(str, filename, options){ | |
this.input = str; | |
this.lexer = new Lexer(str, options); | |
this.filename = filename; | |
this.blocks = []; | |
this.mixins = {}; | |
this.options = options; | |
this.contexts = [this]; | |
}; | |
/** | |
* Tags that may not contain tags. | |
*/ | |
var textOnly = exports.textOnly = ['script', 'style']; | |
/** | |
* Parser prototype. | |
*/ | |
Parser.prototype = { | |
/** | |
* Push `parser` onto the context stack, | |
* or pop and return a `Parser`. | |
*/ | |
context: function(parser){ | |
if (parser) { | |
this.contexts.push(parser); | |
} else { | |
return this.contexts.pop(); | |
} | |
}, | |
/** | |
* Return the next token object. | |
* | |
* @return {Object} | |
* @api private | |
*/ | |
advance: function(){ | |
return this.lexer.advance(); | |
}, | |
/** | |
* Skip `n` tokens. | |
* | |
* @param {Number} n | |
* @api private | |
*/ | |
skip: function(n){ | |
while (n--) this.advance(); | |
}, | |
/** | |
* Single token lookahead. | |
* | |
* @return {Object} | |
* @api private | |
*/ | |
peek: function() { | |
return this.lookahead(1); | |
}, | |
/** | |
* Return lexer lineno. | |
* | |
* @return {Number} | |
* @api private | |
*/ | |
line: function() { | |
return this.lexer.lineno; | |
}, | |
/** | |
* `n` token lookahead. | |
* | |
* @param {Number} n | |
* @return {Object} | |
* @api private | |
*/ | |
lookahead: function(n){ | |
return this.lexer.lookahead(n); | |
}, | |
/** | |
* Parse input returning a string of js for evaluation. | |
* | |
* @return {String} | |
* @api public | |
*/ | |
parse: function(){ | |
var block = new nodes.Block, parser; | |
block.line = this.line(); | |
while ('eos' != this.peek().type) { | |
if ('newline' == this.peek().type) { | |
this.advance(); | |
} else { | |
block.push(this.parseExpr()); | |
} | |
} | |
if (parser = this.extending) { | |
this.context(parser); | |
var ast = parser.parse(); | |
this.context(); | |
// hoist mixins | |
for (var name in this.mixins) | |
ast.unshift(this.mixins[name]); | |
return ast; | |
} else { | |
this.handleBlocks(); | |
} | |
return block; | |
}, | |
/** | |
* Handle blocks, appends and prepends. Must be called from must deep parser (which parses template that does not extends another template). | |
* @api private | |
*/ | |
handleBlocks: function() { | |
this.blocks.reverse(); | |
var blocksHash = {}; // blockName: block object | |
for (var i in this.blocks) { | |
if (!( ({}).hasOwnProperty.call(blocksHash, [this.blocks[i].name]) )) { // just safe call to blocksHash.hasOwnProperty | |
blocksHash[this.blocks[i].name] = this.blocks[i]; | |
} else { | |
switch (this.blocks[i].mode) { | |
case 'append': | |
blocksHash[this.blocks[i].name].nodes = blocksHash[this.blocks[i].name].nodes.concat(this.blocks[i].nodes); | |
break; | |
case 'prepend': | |
blocksHash[this.blocks[i].name].nodes = this.blocks[i].nodes.concat(blocksHash[this.blocks[i].name].nodes); | |
break; | |
default: | |
blocksHash[this.blocks[i].name].nodes = this.blocks[i].nodes; | |
} | |
this.blocks[i] = blocksHash[this.blocks[i].name]; | |
} | |
} | |
}, | |
/** | |
* Expect the given type, or throw an exception. | |
* | |
* @param {String} type | |
* @api private | |
*/ | |
expect: function(type){ | |
if (this.peek().type === type) { | |
return this.advance(); | |
} else { | |
throw new Error('expected "' + type + '", but got "' + this.peek().type + '"'); | |
} | |
}, | |
/** | |
* Accept the given `type`. | |
* | |
* @param {String} type | |
* @api private | |
*/ | |
accept: function(type){ | |
if (this.peek().type === type) { | |
return this.advance(); | |
} | |
}, | |
/** | |
* tag | |
* | doctype | |
* | mixin | |
* | include | |
* | filter | |
* | comment | |
* | text | |
* | each | |
* | code | |
* | yield | |
* | id | |
* | class | |
* | interpolation | |
*/ | |
parseExpr: function(){ | |
switch (this.peek().type) { | |
case 'tag': | |
return this.parseTag(); | |
case 'mixin': | |
return this.parseMixin(); | |
case 'block': | |
return this.parseBlock(); | |
case 'case': | |
return this.parseCase(); | |
case 'when': | |
return this.parseWhen(); | |
case 'default': | |
return this.parseDefault(); | |
case 'extends': | |
return this.parseExtends(); | |
case 'include': | |
return this.parseInclude(); | |
case 'doctype': | |
return this.parseDoctype(); | |
case 'filter': | |
return this.parseFilter(); | |
case 'comment': | |
return this.parseComment(); | |
case 'text': | |
return this.parseText(); | |
case 'each': | |
return this.parseEach(); | |
case 'code': | |
return this.parseCode(); | |
case 'call': | |
return this.parseCall(); | |
case 'interpolation': | |
return this.parseInterpolation(); | |
case 'yield': | |
this.advance(); | |
var block = new nodes.Block; | |
block.yield = true; | |
return block; | |
case 'id': | |
case 'class': | |
var tok = this.advance(); | |
this.lexer.defer(this.lexer.tok('tag', 'div')); | |
this.lexer.defer(tok); | |
return this.parseExpr(); | |
default: | |
throw new Error('unexpected token "' + this.peek().type + '"'); | |
} | |
}, | |
/** | |
* Text | |
*/ | |
parseText: function(){ | |
var tok = this.expect('text'); | |
var node = new nodes.Text(tok.val); | |
node.line = this.line(); | |
return node; | |
}, | |
/** | |
* ':' expr | |
* | block | |
*/ | |
parseBlockExpansion: function(){ | |
if (':' == this.peek().type) { | |
this.advance(); | |
return new nodes.Block(this.parseExpr()); | |
} else { | |
return this.block(); | |
} | |
}, | |
/** | |
* case | |
*/ | |
parseCase: function(){ | |
var val = this.expect('case').val; | |
var node = new nodes.Case(val); | |
node.line = this.line(); | |
node.block = this.block(); | |
return node; | |
}, | |
/** | |
* when | |
*/ | |
parseWhen: function(){ | |
var val = this.expect('when').val | |
return new nodes.Case.When(val, this.parseBlockExpansion()); | |
}, | |
/** | |
* default | |
*/ | |
parseDefault: function(){ | |
this.expect('default'); | |
return new nodes.Case.When('default', this.parseBlockExpansion()); | |
}, | |
/** | |
* code | |
*/ | |
parseCode: function(){ | |
var tok = this.expect('code'); | |
var node = new nodes.Code(tok.val, tok.buffer, tok.escape); | |
var block; | |
var i = 1; | |
node.line = this.line(); | |
while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; | |
block = 'indent' == this.lookahead(i).type; | |
if (block) { | |
this.skip(i-1); | |
node.block = this.block(); | |
} | |
return node; | |
}, | |
/** | |
* comment | |
*/ | |
parseComment: function(){ | |
var tok = this.expect('comment'); | |
var node; | |
if ('indent' == this.peek().type) { | |
node = new nodes.BlockComment(tok.val, this.block(), tok.buffer); | |
} else { | |
node = new nodes.Comment(tok.val, tok.buffer); | |
} | |
node.line = this.line(); | |
return node; | |
}, | |
/** | |
* doctype | |
*/ | |
parseDoctype: function(){ | |
var tok = this.expect('doctype'); | |
var node = new nodes.Doctype(tok.val); | |
node.line = this.line(); | |
return node; | |
}, | |
/** | |
* filter attrs? text-block | |
*/ | |
parseFilter: function(){ | |
var tok = this.expect('filter'); | |
var attrs = this.accept('attrs'); | |
var block; | |
this.lexer.pipeless = true; | |
block = this.parseTextBlock(); | |
this.lexer.pipeless = false; | |
var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); | |
node.line = this.line(); | |
return node; | |
}, | |
/** | |
* each block | |
*/ | |
parseEach: function(){ | |
var tok = this.expect('each'); | |
var node = new nodes.Each(tok.code, tok.val, tok.key); | |
node.line = this.line(); | |
node.block = this.block(); | |
if (this.peek().type == 'code' && this.peek().val == 'else') { | |
this.advance(); | |
node.alternative = this.block(); | |
} | |
return node; | |
}, | |
/** | |
* Resolves a path relative to the template for use in | |
* includes and extends | |
* | |
* @param {String} path | |
* @param {String} purpose Used in error messages. | |
* @return {String} | |
* @api private | |
*/ | |
resolvePath: function (path, purpose) { | |
var p = require('path'); | |
var dirname = p.dirname; | |
var basename = p.basename; | |
var join = p.join; | |
if (path[0] !== '/' && !this.filename) | |
throw new Error('the "filename" option is required to use "' + purpose + '" with "relative" paths'); | |
if (path[0] === '/' && !this.options.basedir) | |
throw new Error('the "basedir" option is required to use "' + purpose + '" with "absolute" paths'); | |
path = join(path[0] === '/' ? this.options.basedir : dirname(this.filename), path); | |
if (basename(path).indexOf('.') === -1) path += '.jade'; | |
return path; | |
}, | |
/** | |
* 'extends' name | |
*/ | |
parseExtends: function(){ | |
var fs = require('fs'); | |
var path = this.resolvePath(this.expect('extends').val.trim(), 'extends'); | |
if ('.jade' != path.substr(-5)) path += '.jade'; | |
var str = fs.readFileSync(path, 'utf8'); | |
var parser = new Parser(str, path, this.options); | |
parser.blocks = this.blocks.reverse(); | |
parser.contexts = this.contexts; | |
this.extending = parser; | |
// TODO: null node | |
return new nodes.Literal(''); | |
}, | |
/** | |
* 'block' name block | |
*/ | |
parseBlock: function(){ | |
var block = this.expect('block'); | |
var mode = block.mode; | |
var name = block.val.trim(); | |
block = 'indent' == this.peek().type | |
? this.block() | |
: new nodes.Block(new nodes.Literal('')); | |
block.mode = mode; | |
block.name = name; | |
this.blocks.push(block); | |
return block; | |
}, | |
/** | |
* include block? | |
*/ | |
parseInclude: function(){ | |
var fs = require('fs'); | |
var path = this.resolvePath(this.expect('include').val.trim(), 'include'); | |
// non-jade | |
if ('.jade' != path.substr(-5)) { | |
var str = fs.readFileSync(path, 'utf8').replace(/\r/g, ''); | |
var ext = extname(path).slice(1); | |
if (filters.exists(ext)) str = filters(ext, str, { filename: path }); | |
return new nodes.Literal(str); | |
} | |
var str = fs.readFileSync(path, 'utf8'); | |
var parser = new Parser(str, path, this.options); | |
parser.blocks = utils.merge([], this.blocks); | |
parser.mixins = this.mixins; | |
this.context(parser); | |
var ast = parser.parse(); | |
this.context(); | |
ast.filename = path; | |
if ('indent' == this.peek().type) { | |
ast.includeBlock().push(this.block()); | |
} | |
return ast; | |
}, | |
/** | |
* call ident block | |
*/ | |
parseCall: function(){ | |
var tok = this.expect('call'); | |
var name = tok.val; | |
var args = tok.args; | |
var mixin = new nodes.Mixin(name, args, new nodes.Block, true); | |
this.tag(mixin); | |
if (mixin.block.isEmpty()) mixin.block = null; | |
return mixin; | |
}, | |
/** | |
* mixin block | |
*/ | |
parseMixin: function(){ | |
var tok = this.expect('mixin'); | |
var name = tok.val; | |
var args = tok.args; | |
var mixin; | |
// definition | |
if ('indent' == this.peek().type) { | |
mixin = new nodes.Mixin(name, args, this.block(), false); | |
this.mixins[name] = mixin; | |
return mixin; | |
// call | |
} else { | |
return new nodes.Mixin(name, args, null, true); | |
} | |
}, | |
/** | |
* indent (text | newline)* outdent | |
*/ | |
parseTextBlock: function(){ | |
var block = new nodes.Block; | |
block.line = this.line(); | |
var spaces = this.expect('indent').val; | |
if (null == this._spaces) this._spaces = spaces; | |
var indent = Array(spaces - this._spaces + 1).join(' '); | |
while ('outdent' != this.peek().type) { | |
switch (this.peek().type) { | |
case 'newline': | |
this.advance(); | |
break; | |
case 'indent': | |
this.parseTextBlock().nodes.forEach(function(node){ | |
block.push(node); | |
}); | |
break; | |
default: | |
var text = new nodes.Text(indent + this.advance().val); | |
text.line = this.line(); | |
block.push(text); | |
} | |
} | |
if (spaces == this._spaces) this._spaces = null; | |
this.expect('outdent'); | |
return block; | |
}, | |
/** | |
* indent expr* outdent | |
*/ | |
block: function(){ | |
var block = new nodes.Block; | |
block.line = this.line(); | |
this.expect('indent'); | |
while ('outdent' != this.peek().type) { | |
if ('newline' == this.peek().type) { | |
this.advance(); | |
} else { | |
block.push(this.parseExpr()); | |
} | |
} | |
this.expect('outdent'); | |
return block; | |
}, | |
/** | |
* interpolation (attrs | class | id)* (text | code | ':')? newline* block? | |
*/ | |
parseInterpolation: function(){ | |
var tok = this.advance(); | |
var tag = new nodes.Tag(tok.val); | |
tag.buffer = true; | |
return this.tag(tag); | |
}, | |
/** | |
* tag (attrs | class | id)* (text | code | ':')? newline* block? | |
*/ | |
parseTag: function(){ | |
// ast-filter look-ahead | |
var i = 2; | |
if ('attrs' == this.lookahead(i).type) ++i; | |
var tok = this.advance(); | |
var tag = new nodes.Tag(tok.val); | |
tag.selfClosing = tok.selfClosing; | |
return this.tag(tag); | |
}, | |
/** | |
* Parse tag. | |
*/ | |
tag: function(tag){ | |
var dot; | |
tag.line = this.line(); | |
// (attrs | class | id)* | |
out: | |
while (true) { | |
switch (this.peek().type) { | |
case 'id': | |
case 'class': | |
var tok = this.advance(); | |
tag.setAttribute(tok.type, "'" + tok.val + "'"); | |
continue; | |
case 'attrs': | |
var tok = this.advance() | |
, obj = tok.attrs | |
, escaped = tok.escaped | |
, names = Object.keys(obj); | |
if (tok.selfClosing) tag.selfClosing = true; | |
for (var i = 0, len = names.length; i < len; ++i) { | |
var name = names[i] | |
, val = obj[name]; | |
tag.setAttribute(name, val, escaped[name]); | |
} | |
continue; | |
default: | |
break out; | |
} | |
} | |
// check immediate '.' | |
if ('.' == this.peek().val) { | |
dot = tag.textOnly = true; | |
this.advance(); | |
} | |
// (text | code | ':')? | |
switch (this.peek().type) { | |
case 'text': | |
tag.block.push(this.parseText()); | |
break; | |
case 'code': | |
tag.code = this.parseCode(); | |
break; | |
case ':': | |
this.advance(); | |
tag.block = new nodes.Block; | |
tag.block.push(this.parseExpr()); | |
break; | |
} | |
// newline* | |
while ('newline' == this.peek().type) this.advance(); | |
tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name); | |
// script special-case | |
if ('script' == tag.name) { | |
var type = tag.getAttribute('type'); | |
if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { | |
tag.textOnly = false; | |
} | |
} | |
// block? | |
if ('indent' == this.peek().type) { | |
if (tag.textOnly) { | |
this.lexer.pipeless = true; | |
tag.block = this.parseTextBlock(); | |
this.lexer.pipeless = false; | |
} else { | |
var block = this.block(); | |
if (tag.block) { | |
for (var i = 0, len = block.nodes.length; i < len; ++i) { | |
tag.block.push(block.nodes[i]); | |
} | |
} else { | |
tag.block = block; | |
} | |
} | |
} | |
return tag; | |
} | |
}; | |
},{"path":13,"fs":1,"./lexer":4,"./utils":10,"./filters":9,"./nodes":11}],11:[function(require,module,exports){ | |
/*! | |
* Jade - nodes | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
exports.Node = require('./node'); | |
exports.Tag = require('./tag'); | |
exports.Code = require('./code'); | |
exports.Each = require('./each'); | |
exports.Case = require('./case'); | |
exports.Text = require('./text'); | |
exports.Block = require('./block'); | |
exports.Mixin = require('./mixin'); | |
exports.Filter = require('./filter'); | |
exports.Comment = require('./comment'); | |
exports.Literal = require('./literal'); | |
exports.BlockComment = require('./block-comment'); | |
exports.Doctype = require('./doctype'); | |
},{"./node":14,"./tag":15,"./code":16,"./case":17,"./each":18,"./text":19,"./block":20,"./mixin":21,"./filter":22,"./comment":23,"./literal":24,"./block-comment":25,"./doctype":26}],14:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Node | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Initialize a `Node`. | |
* | |
* @api public | |
*/ | |
var Node = module.exports = function Node(){}; | |
/** | |
* Clone this node (return itself) | |
* | |
* @return {Node} | |
* @api private | |
*/ | |
Node.prototype.clone = function(){ | |
return this; | |
}; | |
},{}],4:[function(require,module,exports){ | |
/*! | |
* Jade - Lexer | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
var utils = require('./utils'); | |
var parseJSExpression = require('character-parser').parseMax; | |
/** | |
* Initialize `Lexer` with the given `str`. | |
* | |
* Options: | |
* | |
* - `colons` allow colons for attr delimiters | |
* | |
* @param {String} str | |
* @param {Object} options | |
* @api private | |
*/ | |
var Lexer = module.exports = function Lexer(str, options) { | |
options = options || {}; | |
this.input = str.replace(/\r\n|\r/g, '\n'); | |
this.colons = options.colons; | |
this.deferredTokens = []; | |
this.lastIndents = 0; | |
this.lineno = 1; | |
this.stash = []; | |
this.indentStack = []; | |
this.indentRe = null; | |
this.pipeless = false; | |
}; | |
/** | |
* Lexer prototype. | |
*/ | |
Lexer.prototype = { | |
/** | |
* Construct a token with the given `type` and `val`. | |
* | |
* @param {String} type | |
* @param {String} val | |
* @return {Object} | |
* @api private | |
*/ | |
tok: function(type, val){ | |
return { | |
type: type | |
, line: this.lineno | |
, val: val | |
} | |
}, | |
/** | |
* Consume the given `len` of input. | |
* | |
* @param {Number} len | |
* @api private | |
*/ | |
consume: function(len){ | |
this.input = this.input.substr(len); | |
}, | |
/** | |
* Scan for `type` with the given `regexp`. | |
* | |
* @param {String} type | |
* @param {RegExp} regexp | |
* @return {Object} | |
* @api private | |
*/ | |
scan: function(regexp, type){ | |
var captures; | |
if (captures = regexp.exec(this.input)) { | |
this.consume(captures[0].length); | |
return this.tok(type, captures[1]); | |
} | |
}, | |
/** | |
* Defer the given `tok`. | |
* | |
* @param {Object} tok | |
* @api private | |
*/ | |
defer: function(tok){ | |
this.deferredTokens.push(tok); | |
}, | |
/** | |
* Lookahead `n` tokens. | |
* | |
* @param {Number} n | |
* @return {Object} | |
* @api private | |
*/ | |
lookahead: function(n){ | |
var fetch = n - this.stash.length; | |
while (fetch-- > 0) this.stash.push(this.next()); | |
return this.stash[--n]; | |
}, | |
/** | |
* Return the indexOf `(` or `{` or `[` / `)` or `}` or `]` delimiters. | |
* | |
* @return {Number} | |
* @api private | |
*/ | |
bracketExpression: function(skip){ | |
skip = skip || 0; | |
var start = this.input[skip]; | |
if (start != '(' && start != '{' && start != '[') throw new Error('unrecognized start character'); | |
var end = ({'(': ')', '{': '}', '[': ']'})[start]; | |
var range = parseJSExpression(this.input, {start: skip + 1}); | |
if (this.input[range.end] !== end) throw new Error('start character ' + start + ' does not match end character ' + this.input[range.end]); | |
return range; | |
}, | |
/** | |
* Stashed token. | |
*/ | |
stashed: function() { | |
return this.stash.length | |
&& this.stash.shift(); | |
}, | |
/** | |
* Deferred token. | |
*/ | |
deferred: function() { | |
return this.deferredTokens.length | |
&& this.deferredTokens.shift(); | |
}, | |
/** | |
* end-of-source. | |
*/ | |
eos: function() { | |
if (this.input.length) return; | |
if (this.indentStack.length) { | |
this.indentStack.shift(); | |
return this.tok('outdent'); | |
} else { | |
return this.tok('eos'); | |
} | |
}, | |
/** | |
* Blank line. | |
*/ | |
blank: function() { | |
var captures; | |
if (captures = /^\n *\n/.exec(this.input)) { | |
this.consume(captures[0].length - 1); | |
++this.lineno; | |
if (this.pipeless) return this.tok('text', ''); | |
return this.next(); | |
} | |
}, | |
/** | |
* Comment. | |
*/ | |
comment: function() { | |
var captures; | |
if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var tok = this.tok('comment', captures[2]); | |
tok.buffer = '-' != captures[1]; | |
return tok; | |
} | |
}, | |
/** | |
* Interpolated tag. | |
*/ | |
interpolation: function() { | |
if (/^#\{/.test(this.input)) { | |
var match; | |
try { | |
match = this.bracketExpression(1); | |
} catch (ex) { | |
return;//not an interpolation expression, just an unmatched open interpolation | |
} | |
this.consume(match.end + 1); | |
return this.tok('interpolation', match.src); | |
} | |
}, | |
/** | |
* Tag. | |
*/ | |
tag: function() { | |
var captures; | |
if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var tok, name = captures[1]; | |
if (':' == name[name.length - 1]) { | |
name = name.slice(0, -1); | |
tok = this.tok('tag', name); | |
this.defer(this.tok(':')); | |
while (' ' == this.input[0]) this.input = this.input.substr(1); | |
} else { | |
tok = this.tok('tag', name); | |
} | |
tok.selfClosing = !! captures[2]; | |
return tok; | |
} | |
}, | |
/** | |
* Filter. | |
*/ | |
filter: function() { | |
return this.scan(/^:(\w+)/, 'filter'); | |
}, | |
/** | |
* Doctype. | |
*/ | |
doctype: function() { | |
return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype'); | |
}, | |
/** | |
* Id. | |
*/ | |
id: function() { | |
return this.scan(/^#([\w-]+)/, 'id'); | |
}, | |
/** | |
* Class. | |
*/ | |
className: function() { | |
return this.scan(/^\.([\w-]+)/, 'class'); | |
}, | |
/** | |
* Text. | |
*/ | |
text: function() { | |
return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text'); | |
}, | |
/** | |
* Extends. | |
*/ | |
"extends": function() { | |
return this.scan(/^extends? +([^\n]+)/, 'extends'); | |
}, | |
/** | |
* Block prepend. | |
*/ | |
prepend: function() { | |
var captures; | |
if (captures = /^prepend +([^\n]+)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var mode = 'prepend' | |
, name = captures[1] | |
, tok = this.tok('block', name); | |
tok.mode = mode; | |
return tok; | |
} | |
}, | |
/** | |
* Block append. | |
*/ | |
append: function() { | |
var captures; | |
if (captures = /^append +([^\n]+)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var mode = 'append' | |
, name = captures[1] | |
, tok = this.tok('block', name); | |
tok.mode = mode; | |
return tok; | |
} | |
}, | |
/** | |
* Block. | |
*/ | |
block: function() { | |
var captures; | |
if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var mode = captures[1] || 'replace' | |
, name = captures[2] | |
, tok = this.tok('block', name); | |
tok.mode = mode; | |
return tok; | |
} | |
}, | |
/** | |
* Yield. | |
*/ | |
yield: function() { | |
return this.scan(/^yield */, 'yield'); | |
}, | |
/** | |
* Include. | |
*/ | |
include: function() { | |
return this.scan(/^include +([^\n]+)/, 'include'); | |
}, | |
/** | |
* Case. | |
*/ | |
"case": function() { | |
return this.scan(/^case +([^\n]+)/, 'case'); | |
}, | |
/** | |
* When. | |
*/ | |
when: function() { | |
return this.scan(/^when +([^:\n]+)/, 'when'); | |
}, | |
/** | |
* Default. | |
*/ | |
"default": function() { | |
return this.scan(/^default */, 'default'); | |
}, | |
/** | |
* Assignment. | |
*/ | |
assignment: function() { | |
var captures; | |
if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var name = captures[1] | |
, val = captures[2]; | |
return this.tok('code', 'var ' + name + ' = (' + val + ');'); | |
} | |
}, | |
/** | |
* Call mixin. | |
*/ | |
call: function(){ | |
var captures; | |
if (captures = /^\+([-\w]+)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var tok = this.tok('call', captures[1]); | |
// Check for args (not attributes) | |
if (captures = /^ *\(/.exec(this.input)) { | |
try { | |
var range = this.bracketExpression(captures[0].length - 1); | |
if (!/^ *[-\w]+ *=/.test(range.src)) { // not attributes | |
this.consume(range.end + 1); | |
tok.args = range.src; | |
} | |
} catch (ex) { | |
//not a bracket expcetion, just unmatched open parens | |
} | |
} | |
return tok; | |
} | |
}, | |
/** | |
* Mixin. | |
*/ | |
mixin: function(){ | |
var captures; | |
if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var tok = this.tok('mixin', captures[1]); | |
tok.args = captures[2]; | |
return tok; | |
} | |
}, | |
/** | |
* Conditional. | |
*/ | |
conditional: function() { | |
var captures; | |
if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var type = captures[1] | |
, js = captures[2]; | |
switch (type) { | |
case 'if': js = 'if (' + js + ')'; break; | |
case 'unless': js = 'if (!(' + js + '))'; break; | |
case 'else if': js = 'else if (' + js + ')'; break; | |
case 'else': js = 'else'; break; | |
} | |
return this.tok('code', js); | |
} | |
}, | |
/** | |
* While. | |
*/ | |
"while": function() { | |
var captures; | |
if (captures = /^while +([^\n]+)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
return this.tok('code', 'while (' + captures[1] + ')'); | |
} | |
}, | |
/** | |
* Each. | |
*/ | |
each: function() { | |
var captures; | |
if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var tok = this.tok('each', captures[1]); | |
tok.key = captures[2] || '$index'; | |
tok.code = captures[3]; | |
return tok; | |
} | |
}, | |
/** | |
* Code. | |
*/ | |
code: function() { | |
var captures; | |
if (captures = /^(!?=|-)[ \t]*([^\n]+)/.exec(this.input)) { | |
this.consume(captures[0].length); | |
var flags = captures[1]; | |
captures[1] = captures[2]; | |
var tok = this.tok('code', captures[1]); | |
tok.escape = flags.charAt(0) === '='; | |
tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '='; | |
return tok; | |
} | |
}, | |
/** | |
* Attributes. | |
*/ | |
attrs: function() { | |
if ('(' == this.input.charAt(0)) { | |
var index = this.bracketExpression().end | |
, str = this.input.substr(1, index-1) | |
, tok = this.tok('attrs') | |
, len = str.length | |
, colons = this.colons | |
, states = ['key'] | |
, escapedAttr | |
, key = '' | |
, val = '' | |
, quote | |
, c | |
, p; | |
function state(){ | |
return states[states.length - 1]; | |
} | |
function interpolate(attr) { | |
return attr.replace(/(\\)?#\{(.+)/g, function(_, escape, expr){ | |
if (escape) return _; | |
try { | |
var range = parseJSExpression(expr); | |
if (expr[range.end] !== '}') return _.substr(0, 2) + interpolate(_.substr(2)); | |
return quote + " + (" + range.src + ") + " + quote + interpolate(expr.substr(range.end + 1)); | |
} catch (ex) { | |
return _.substr(0, 2) + interpolate(_.substr(2)); | |
} | |
}); | |
} | |
this.consume(index + 1); | |
tok.attrs = {}; | |
tok.escaped = {}; | |
function parse(c) { | |
var real = c; | |
// TODO: remove when people fix ":" | |
if (colons && ':' == c) c = '='; | |
switch (c) { | |
case ',': | |
case '\n': | |
switch (state()) { | |
case 'expr': | |
case 'array': | |
case 'string': | |
case 'object': | |
val += c; | |
break; | |
default: | |
states.push('key'); | |
val = val.trim(); | |
key = key.trim(); | |
if ('' == key) return; | |
key = key.replace(/^['"]|['"]$/g, '').replace('!', ''); | |
tok.escaped[key] = escapedAttr; | |
tok.attrs[key] = '' == val | |
? true | |
: interpolate(val); | |
key = val = ''; | |
} | |
break; | |
case '=': | |
switch (state()) { | |
case 'key char': | |
key += real; | |
break; | |
case 'val': | |
case 'expr': | |
case 'array': | |
case 'string': | |
case 'object': | |
val += real; | |
break; | |
default: | |
escapedAttr = '!' != p; | |
states.push('val'); | |
} | |
break; | |
case '(': | |
if ('val' == state() | |
|| 'expr' == state()) states.push('expr'); | |
val += c; | |
break; | |
case ')': | |
if ('expr' == state() | |
|| 'val' == state()) states.pop(); | |
val += c; | |
break; | |
case '{': | |
if ('val' == state()) states.push('object'); | |
val += c; | |
break; | |
case '}': | |
if ('object' == state()) states.pop(); | |
val += c; | |
break; | |
case '[': | |
if ('val' == state()) states.push('array'); | |
val += c; | |
break; | |
case ']': | |
if ('array' == state()) states.pop(); | |
val += c; | |
break; | |
case '"': | |
case "'": | |
switch (state()) { | |
case 'key': | |
states.push('key char'); | |
break; | |
case 'key char': | |
states.pop(); | |
break; | |
case 'string': | |
if (c == quote) states.pop(); | |
val += c; | |
break; | |
default: | |
states.push('string'); | |
val += c; | |
quote = c; | |
} | |
break; | |
case '': | |
break; | |
default: | |
switch (state()) { | |
case 'key': | |
case 'key char': | |
key += c; | |
break; | |
default: | |
val += c; | |
} | |
} | |
p = c; | |
} | |
for (var i = 0; i < len; ++i) { | |
parse(str.charAt(i)); | |
} | |
parse(','); | |
if ('/' == this.input.charAt(0)) { | |
this.consume(1); | |
tok.selfClosing = true; | |
} | |
return tok; | |
} | |
}, | |
/** | |
* Indent | Outdent | Newline. | |
*/ | |
indent: function() { | |
var captures, re; | |
// established regexp | |
if (this.indentRe) { | |
captures = this.indentRe.exec(this.input); | |
// determine regexp | |
} else { | |
// tabs | |
re = /^\n(\t*) */; | |
captures = re.exec(this.input); | |
// spaces | |
if (captures && !captures[1].length) { | |
re = /^\n( *)/; | |
captures = re.exec(this.input); | |
} | |
// established | |
if (captures && captures[1].length) this.indentRe = re; | |
} | |
if (captures) { | |
var tok | |
, indents = captures[1].length; | |
++this.lineno; | |
this.consume(indents + 1); | |
if (' ' == this.input[0] || '\t' == this.input[0]) { | |
throw new Error('Invalid indentation, you can use tabs or spaces but not both'); | |
} | |
// blank line | |
if ('\n' == this.input[0]) return this.tok('newline'); | |
// outdent | |
if (this.indentStack.length && indents < this.indentStack[0]) { | |
while (this.indentStack.length && this.indentStack[0] > indents) { | |
this.stash.push(this.tok('outdent')); | |
this.indentStack.shift(); | |
} | |
tok = this.stash.pop(); | |
// indent | |
} else if (indents && indents != this.indentStack[0]) { | |
this.indentStack.unshift(indents); | |
tok = this.tok('indent', indents); | |
// newline | |
} else { | |
tok = this.tok('newline'); | |
} | |
return tok; | |
} | |
}, | |
/** | |
* Pipe-less text consumed only when | |
* pipeless is true; | |
*/ | |
pipelessText: function() { | |
if (this.pipeless) { | |
if ('\n' == this.input[0]) return; | |
var i = this.input.indexOf('\n'); | |
if (-1 == i) i = this.input.length; | |
var str = this.input.substr(0, i); | |
this.consume(str.length); | |
return this.tok('text', str); | |
} | |
}, | |
/** | |
* ':' | |
*/ | |
colon: function() { | |
return this.scan(/^: */, ':'); | |
}, | |
/** | |
* Return the next token object, or those | |
* previously stashed by lookahead. | |
* | |
* @return {Object} | |
* @api private | |
*/ | |
advance: function(){ | |
return this.stashed() | |
|| this.next(); | |
}, | |
/** | |
* Return the next token object. | |
* | |
* @return {Object} | |
* @api private | |
*/ | |
next: function() { | |
return this.deferred() | |
|| this.blank() | |
|| this.eos() | |
|| this.pipelessText() | |
|| this.yield() | |
|| this.doctype() | |
|| this.interpolation() | |
|| this["case"]() | |
|| this.when() | |
|| this["default"]() | |
|| this["extends"]() | |
|| this.append() | |
|| this.prepend() | |
|| this.block() | |
|| this.include() | |
|| this.mixin() | |
|| this.call() | |
|| this.conditional() | |
|| this.each() | |
|| this["while"]() | |
|| this.assignment() | |
|| this.tag() | |
|| this.filter() | |
|| this.code() | |
|| this.id() | |
|| this.className() | |
|| this.attrs() | |
|| this.indent() | |
|| this.comment() | |
|| this.colon() | |
|| this.text(); | |
} | |
}; | |
},{"./utils":10,"character-parser":27}],5:[function(require,module,exports){ | |
(function(){ | |
/*! | |
* Jade - Compiler | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var nodes = require('./nodes') | |
, filters = require('./filters') | |
, doctypes = require('./doctypes') | |
, selfClosing = require('./self-closing') | |
, runtime = require('./runtime') | |
, utils = require('./utils') | |
, parseJSExpression = require('character-parser').parseMax | |
// if browser | |
// | |
// if (!Object.keys) { | |
// Object.keys = function(obj){ | |
// var arr = []; | |
// for (var key in obj) { | |
// if (obj.hasOwnProperty(key)) { | |
// arr.push(key); | |
// } | |
// } | |
// return arr; | |
// } | |
// } | |
// | |
// if (!String.prototype.trimLeft) { | |
// String.prototype.trimLeft = function(){ | |
// return this.replace(/^\s+/, ''); | |
// } | |
// } | |
// | |
// end | |
/** | |
* Initialize `Compiler` with the given `node`. | |
* | |
* @param {Node} node | |
* @param {Object} options | |
* @api public | |
*/ | |
var Compiler = module.exports = function Compiler(node, options) { | |
this.options = options = options || {}; | |
this.node = node; | |
this.hasCompiledDoctype = false; | |
this.hasCompiledTag = false; | |
this.pp = options.pretty || false; | |
this.debug = false !== options.compileDebug; | |
this.indents = 0; | |
this.parentIndents = 0; | |
if (options.doctype) this.setDoctype(options.doctype); | |
}; | |
/** | |
* Compiler prototype. | |
*/ | |
Compiler.prototype = { | |
/** | |
* Compile parse tree to JavaScript. | |
* | |
* @api public | |
*/ | |
compile: function(){ | |
this.buf = []; | |
if (this.pp) this.buf.push("jade.indent = [];"); | |
this.lastBufferedIdx = -1; | |
this.visit(this.node); | |
return this.buf.join('\n'); | |
}, | |
/** | |
* Sets the default doctype `name`. Sets terse mode to `true` when | |
* html 5 is used, causing self-closing tags to end with ">" vs "/>", | |
* and boolean attributes are not mirrored. | |
* | |
* @param {string} name | |
* @api public | |
*/ | |
setDoctype: function(name){ | |
name = (name && name.toLowerCase()) || 'default'; | |
this.doctype = doctypes[name] || '<!DOCTYPE ' + name + '>'; | |
this.terse = this.doctype.toLowerCase() == '<!doctype html>'; | |
this.xml = 0 == this.doctype.indexOf('<?xml'); | |
}, | |
/** | |
* Buffer the given `str` exactly as is or with interpolation | |
* | |
* @param {String} str | |
* @param {Boolean} interpolate | |
* @api public | |
*/ | |
buffer: function (str, interpolate) { | |
var self = this; | |
if (interpolate) { | |
var match = /(\\)?([#!]){((?:.|\n)*)$/.exec(str); | |
if (match) { | |
this.buffer(str.substr(0, match.index), false); | |
if (match[1]) { // escape | |
this.buffer(match[2] + '{', false); | |
this.buffer(match[3], true); | |
return; | |
} else { | |
try { | |
var rest = match[3]; | |
var range = parseJSExpression(rest); | |
var code = ('!' == match[2] ? '' : 'jade.escape') + "((jade.interp = " + range.src + ") == null ? '' : jade.interp)"; | |
} catch (ex) { | |
throw ex; | |
//didn't match, just as if escaped | |
this.buffer(match[2] + '{', false); | |
this.buffer(match[3], true); | |
return; | |
} | |
this.bufferExpression(code); | |
this.buffer(rest.substr(range.end + 1), true); | |
return; | |
} | |
} | |
} | |
str = JSON.stringify(str); | |
str = str.substr(1, str.length - 2); | |
if (this.lastBufferedIdx == this.buf.length) { | |
if (this.lastBufferedType === 'code') this.lastBuffered += ' + "'; | |
this.lastBufferedType = 'text'; | |
this.lastBuffered += str; | |
this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + '");' | |
} else { | |
this.buf.push('buf.push("' + str + '");'); | |
this.lastBufferedType = 'text'; | |
this.bufferStartChar = '"'; | |
this.lastBuffered = str; | |
this.lastBufferedIdx = this.buf.length; | |
} | |
}, | |
/** | |
* Buffer the given `src` so it is evaluated at run time | |
* | |
* @param {String} src | |
* @api public | |
*/ | |
bufferExpression: function (src) { | |
if (this.lastBufferedIdx == this.buf.length) { | |
if (this.lastBufferedType === 'text') this.lastBuffered += '"'; | |
this.lastBufferedType = 'code'; | |
this.lastBuffered += ' + (' + src + ')'; | |
this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + ');' | |
} else { | |
this.buf.push('buf.push(' + src + ');'); | |
this.lastBufferedType = 'code'; | |
this.bufferStartChar = ''; | |
this.lastBuffered = '(' + src + ')'; | |
this.lastBufferedIdx = this.buf.length; | |
} | |
}, | |
/** | |
* Buffer an indent based on the current `indent` | |
* property and an additional `offset`. | |
* | |
* @param {Number} offset | |
* @param {Boolean} newline | |
* @api public | |
*/ | |
prettyIndent: function(offset, newline){ | |
offset = offset || 0; | |
newline = newline ? '\n' : ''; | |
this.buffer(newline + Array(this.indents + offset).join(' ')); | |
if (this.parentIndents) | |
this.buf.push("buf.push.apply(buf, jade.indent);"); | |
}, | |
/** | |
* Visit `node`. | |
* | |
* @param {Node} node | |
* @api public | |
*/ | |
visit: function(node){ | |
var debug = this.debug; | |
if (debug) { | |
this.buf.push('jade.debug.unshift({ lineno: ' + node.line | |
+ ', filename: ' + (node.filename | |
? JSON.stringify(node.filename) | |
: 'jade.debug[0].filename') | |
+ ' });'); | |
} | |
// Massive hack to fix our context | |
// stack for - else[ if] etc | |
if (false === node.debug && this.debug) { | |
this.buf.pop(); | |
this.buf.pop(); | |
} | |
this.visitNode(node); | |
if (debug) this.buf.push('jade.debug.shift();'); | |
}, | |
/** | |
* Visit `node`. | |
* | |
* @param {Node} node | |
* @api public | |
*/ | |
visitNode: function(node){ | |
var name = node.constructor.name | |
|| node.constructor.toString().match(/function ([^(\s]+)()/)[1]; | |
return this['visit' + name](node); | |
}, | |
/** | |
* Visit case `node`. | |
* | |
* @param {Literal} node | |
* @api public | |
*/ | |
visitCase: function(node){ | |
var _ = this.withinCase; | |
this.withinCase = true; | |
this.buf.push('switch (' + node.expr + '){'); | |
this.visit(node.block); | |
this.buf.push('}'); | |
this.withinCase = _; | |
}, | |
/** | |
* Visit when `node`. | |
* | |
* @param {Literal} node | |
* @api public | |
*/ | |
visitWhen: function(node){ | |
if ('default' == node.expr) { | |
this.buf.push('default:'); | |
} else { | |
this.buf.push('case ' + node.expr + ':'); | |
} | |
this.visit(node.block); | |
this.buf.push(' break;'); | |
}, | |
/** | |
* Visit literal `node`. | |
* | |
* @param {Literal} node | |
* @api public | |
*/ | |
visitLiteral: function(node){ | |
this.buffer(node.str); | |
}, | |
/** | |
* Visit all nodes in `block`. | |
* | |
* @param {Block} block | |
* @api public | |
*/ | |
visitBlock: function(block){ | |
var len = block.nodes.length | |
, escape = this.escape | |
, pp = this.pp | |
// Block keyword has a special meaning in mixins | |
if (this.parentIndents && block.mode) { | |
if (pp) this.buf.push("jade.indent.push('" + Array(this.indents + 1).join(' ') + "');") | |
this.buf.push('block && block();'); | |
if (pp) this.buf.push("jade.indent.pop();") | |
return; | |
} | |
// Pretty print multi-line text | |
if (pp && len > 1 && !escape && block.nodes[0].isText && block.nodes[1].isText) | |
this.prettyIndent(1, true); | |
for (var i = 0; i < len; ++i) { | |
// Pretty print text | |
if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText) | |
this.prettyIndent(1, false); | |
this.visit(block.nodes[i]); | |
// Multiple text nodes are separated by newlines | |
if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText) | |
this.buffer('\n'); | |
} | |
}, | |
/** | |
* Visit `doctype`. Sets terse mode to `true` when html 5 | |
* is used, causing self-closing tags to end with ">" vs "/>", | |
* and boolean attributes are not mirrored. | |
* | |
* @param {Doctype} doctype | |
* @api public | |
*/ | |
visitDoctype: function(doctype){ | |
if (doctype && (doctype.val || !this.doctype)) { | |
this.setDoctype(doctype.val || 'default'); | |
} | |
if (this.doctype) this.buffer(this.doctype); | |
this.hasCompiledDoctype = true; | |
}, | |
/** | |
* Visit `mixin`, generating a function that | |
* may be called within the template. | |
* | |
* @param {Mixin} mixin | |
* @api public | |
*/ | |
visitMixin: function(mixin){ | |
var name = mixin.name.replace(/-/g, '_') + '_mixin' | |
, args = mixin.args || '' | |
, block = mixin.block | |
, attrs = mixin.attrs | |
, pp = this.pp; | |
if (mixin.call) { | |
if (pp) this.buf.push("jade.indent.push('" + Array(this.indents + 1).join(' ') + "');") | |
if (block || attrs.length) { | |
this.buf.push(name + '.call({'); | |
if (block) { | |
this.buf.push('block: function(){'); | |
// Render block with no indents, dynamically added when rendered | |
this.parentIndents++; | |
var _indents = this.indents; | |
this.indents = 0; | |
this.visit(mixin.block); | |
this.indents = _indents; | |
this.parentIndents--; | |
if (attrs.length) { | |
this.buf.push('},'); | |
} else { | |
this.buf.push('}'); | |
} | |
} | |
if (attrs.length) { | |
var val = this.attrs(attrs); | |
if (val.inherits) { | |
this.buf.push('attributes: jade.merge({' + val.buf | |
+ '}, attributes), escaped: jade.merge(' + val.escaped + ', escaped, true)'); | |
} else { | |
this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped); | |
} | |
} | |
if (args) { | |
this.buf.push('}, ' + args + ');'); | |
} else { | |
this.buf.push('});'); | |
} | |
} else { | |
this.buf.push(name + '(' + args + ');'); | |
} | |
if (pp) this.buf.push("jade.indent.pop();") | |
} else { | |
this.buf.push('var ' + name + ' = function(' + args + '){'); | |
this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};'); | |
this.parentIndents++; | |
this.visit(block); | |
this.parentIndents--; | |
this.buf.push('};'); | |
} | |
}, | |
/** | |
* Visit `tag` buffering tag markup, generating | |
* attributes, visiting the `tag`'s code and block. | |
* | |
* @param {Tag} tag | |
* @api public | |
*/ | |
visitTag: function(tag){ | |
this.indents++; | |
var name = tag.name | |
, pp = this.pp | |
, self = this; | |
function bufferName() { | |
if (tag.buffer) self.bufferExpression(name); | |
else self.buffer(name); | |
} | |
if (!this.hasCompiledTag) { | |
if (!this.hasCompiledDoctype && 'html' == name) { | |
this.visitDoctype(); | |
} | |
this.hasCompiledTag = true; | |
} | |
// pretty print | |
if (pp && !tag.isInline()) | |
this.prettyIndent(0, true); | |
if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) { | |
this.buffer('<'); | |
bufferName(); | |
this.visitAttributes(tag.attrs); | |
this.terse | |
? this.buffer('>') | |
: this.buffer('/>'); | |
} else { | |
// Optimize attributes buffering | |
if (tag.attrs.length) { | |
this.buffer('<'); | |
bufferName(); | |
if (tag.attrs.length) this.visitAttributes(tag.attrs); | |
this.buffer('>'); | |
} else { | |
this.buffer('<'); | |
bufferName(); | |
this.buffer('>'); | |
} | |
if (tag.code) this.visitCode(tag.code); | |
this.escape = 'pre' == tag.name; | |
this.visit(tag.block); | |
// pretty print | |
if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline()) | |
this.prettyIndent(0, true); | |
this.buffer('</'); | |
bufferName(); | |
this.buffer('>'); | |
} | |
this.indents--; | |
}, | |
/** | |
* Visit `filter`, throwing when the filter does not exist. | |
* | |
* @param {Filter} filter | |
* @api public | |
*/ | |
visitFilter: function(filter){ | |
var text = filter.block.nodes.map( | |
function(node){ return node.val; } | |
).join('\n'); | |
filter.attrs = filter.attrs || {}; | |
filter.attrs.filename = this.options.filename; | |
this.buffer(filters(filter.name, text, filter.attrs), true); | |
}, | |
/** | |
* Visit `text` node. | |
* | |
* @param {Text} text | |
* @api public | |
*/ | |
visitText: function(text){ | |
this.buffer(text.val, true); | |
}, | |
/** | |
* Visit a `comment`, only buffering when the buffer flag is set. | |
* | |
* @param {Comment} comment | |
* @api public | |
*/ | |
visitComment: function(comment){ | |
if (!comment.buffer) return; | |
if (this.pp) this.prettyIndent(1, true); | |
this.buffer('<!--' + comment.val + '-->'); | |
}, | |
/** | |
* Visit a `BlockComment`. | |
* | |
* @param {Comment} comment | |
* @api public | |
*/ | |
visitBlockComment: function(comment){ | |
if (!comment.buffer) return; | |
if (0 == comment.val.trim().indexOf('if')) { | |
this.buffer('<!--[' + comment.val.trim() + ']>'); | |
this.visit(comment.block); | |
this.buffer('<![endif]-->'); | |
} else { | |
this.buffer('<!--' + comment.val); | |
this.visit(comment.block); | |
this.buffer('-->'); | |
} | |
}, | |
/** | |
* Visit `code`, respecting buffer / escape flags. | |
* If the code is followed by a block, wrap it in | |
* a self-calling function. | |
* | |
* @param {Code} code | |
* @api public | |
*/ | |
visitCode: function(code){ | |
// Wrap code blocks with {}. | |
// we only wrap unbuffered code blocks ATM | |
// since they are usually flow control | |
// Buffer code | |
if (code.buffer) { | |
var val = code.val.trimLeft(); | |
val = 'null == (jade.interp = '+val+') ? "" : jade.interp'; | |
if (code.escape) val = 'jade.escape(' + val + ')'; | |
this.bufferExpression(val); | |
} else { | |
this.buf.push(code.val); | |
} | |
// Block support | |
if (code.block) { | |
if (!code.buffer) this.buf.push('{'); | |
this.visit(code.block); | |
if (!code.buffer) this.buf.push('}'); | |
} | |
}, | |
/** | |
* Visit `each` block. | |
* | |
* @param {Each} each | |
* @api public | |
*/ | |
visitEach: function(each){ | |
this.buf.push('' | |
+ '// iterate ' + each.obj + '\n' | |
+ ';(function(){\n' | |
+ ' var $$obj = ' + each.obj + ';\n' | |
+ ' if (\'number\' == typeof $$obj.length) {\n'); | |
if (each.alternative) { | |
this.buf.push(' if ($$obj.length) {'); | |
} | |
this.buf.push('' | |
+ ' for (var ' + each.key + ' = 0, $$l = $$obj.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n' | |
+ ' var ' + each.val + ' = $$obj[' + each.key + '];\n'); | |
this.visit(each.block); | |
this.buf.push(' }\n'); | |
if (each.alternative) { | |
this.buf.push(' } else {'); | |
this.visit(each.alternative); | |
this.buf.push(' }'); | |
} | |
this.buf.push('' | |
+ ' } else {\n' | |
+ ' var $$l = 0;\n' | |
+ ' for (var ' + each.key + ' in $$obj) {\n' | |
+ ' $$l++;' | |
+ ' if ($$obj.hasOwnProperty(' + each.key + ')){' | |
+ ' var ' + each.val + ' = $$obj[' + each.key + '];\n'); | |
this.visit(each.block); | |
this.buf.push(' }\n'); | |
this.buf.push(' }\n'); | |
if (each.alternative) { | |
this.buf.push(' if ($$l === 0) {'); | |
this.visit(each.alternative); | |
this.buf.push(' }'); | |
} | |
this.buf.push(' }\n}).call(this);\n'); | |
}, | |
/** | |
* Visit `attrs`. | |
* | |
* @param {Array} attrs | |
* @api public | |
*/ | |
visitAttributes: function(attrs){ | |
var val = this.attrs(attrs); | |
if (val.inherits) { | |
this.bufferExpression("jade.attrs(jade.merge({ " + val.buf + | |
" }, attributes), jade.merge(" + val.escaped + ", escaped, true))"); | |
} else if (val.constant) { | |
eval('var buf={' + val.buf + '};'); | |
this.buffer(runtime.attrs(buf, JSON.parse(val.escaped))); | |
} else { | |
this.bufferExpression("jade.attrs({ " + val.buf + " }, " + val.escaped + ")"); | |
} | |
}, | |
/** | |
* Compile attributes. | |
*/ | |
attrs: function(attrs){ | |
var buf = [] | |
, classes = [] | |
, escaped = {} | |
, constant = attrs.every(function(attr){ return isConstant(attr.val) }) | |
, inherits = false; | |
if (this.terse) buf.push('terse: true'); | |
attrs.forEach(function(attr){ | |
if (attr.name == 'attributes') return inherits = true; | |
escaped[attr.name] = attr.escaped; | |
if (attr.name == 'class') { | |
classes.push('(' + attr.val + ')'); | |
} else { | |
var pair = "'" + attr.name + "':(" + attr.val + ')'; | |
buf.push(pair); | |
} | |
}); | |
if (classes.length) { | |
classes = classes.join(" + ' ' + "); | |
buf.push('"class": ' + classes); | |
} | |
return { | |
buf: buf.join(', '), | |
escaped: JSON.stringify(escaped), | |
inherits: inherits, | |
constant: constant | |
}; | |
} | |
}; | |
/** | |
* Check if expression can be evaluated to a constant | |
* | |
* @param {String} expression | |
* @return {Boolean} | |
* @api private | |
*/ | |
function isConstant(val){ | |
// Check strings/literals | |
if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val)) | |
return true; | |
// Check numbers | |
if (!isNaN(Number(val))) | |
return true; | |
// Check arrays | |
var matches; | |
if (matches = /^ *\[(.*)\] *$/.exec(val)) | |
return matches[1].split(',').every(isConstant); | |
return false; | |
} | |
})() | |
},{"./doctypes":8,"./runtime":6,"./self-closing":7,"./utils":10,"./filters":9,"./nodes":11,"character-parser":27}],9:[function(require,module,exports){ | |
/*! | |
* Jade - filters | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
var transformers = require('transformers'); | |
module.exports = filter; | |
function filter(name, str, options) { | |
if (typeof filter[name] === 'function') { | |
var res = filter[name](str, options); | |
} else if (transformers[name]) { | |
var res = transformers[name].renderSync(str, options); | |
if (transformers[name].outputFormat === 'js') { | |
res = '<script type="text/javascript">\n' + res + '</script>'; | |
} else if (transformers[name].outputFormat === 'css') { | |
res = '<style type="text/css">' + res + '</style>'; | |
} else if (transformers[name].outputFormat === 'xml') { | |
res = res.replace(/'/g, '''); | |
} | |
} else { | |
throw new Error('unknown filter ":' + name + '"'); | |
} | |
return res; | |
} | |
filter.exists = function (name, str, options) { | |
return typeof filter[name] === 'function' || transformers[name]; | |
}; | |
},{"transformers":28}],27:[function(require,module,exports){ | |
exports = (module.exports = parse); | |
exports.parse = parse; | |
function parse(src, state, options) { | |
options = options || {}; | |
state = state || exports.defaultState(); | |
var start = options.start || 0; | |
var end = options.end || src.length; | |
var index = start; | |
while (index < end) { | |
if (state.roundDepth < 0 || state.curlyDepth < 0 || state.squareDepth < 0) { | |
throw new SyntaxError('Mismatched Bracket: ' + src[index - 1]); | |
} | |
exports.parseChar(src[index++], state); | |
} | |
return state; | |
} | |
exports.parseMax = parseMax; | |
function parseMax(src, options) { | |
options = options || {}; | |
var start = options.start || 0; | |
var index = start; | |
var state = exports.defaultState(); | |
while (state.roundDepth >= 0 && state.curlyDepth >= 0 && state.squareDepth >= 0) { | |
if (index >= src.length) { | |
throw new Error('The end of the string was reached with no closing bracket found.'); | |
} | |
exports.parseChar(src[index++], state); | |
} | |
var end = index - 1; | |
return { | |
start: start, | |
end: end, | |
src: src.substring(start, end) | |
}; | |
} | |
exports.parseUntil = parseUntil; | |
function parseUntil(src, delimiter, options) { | |
options = options || {}; | |
var includeLineComment = options.includeLineComment || false; | |
var start = options.start || 0; | |
var index = start; | |
var state = exports.defaultState(); | |
while (state.singleQuote || state.doubleQuote || state.regexp || state.blockComment || | |
(!includeLineComment && state.lineComment) || !startsWith(src, delimiter, index)) { | |
exports.parseChar(src[index++], state); | |
} | |
var end = index; | |
return { | |
start: start, | |
end: end, | |
src: src.substring(start, end) | |
}; | |
} | |
exports.parseChar = parseChar; | |
function parseChar(character, state) { | |
if (character.length !== 1) throw new Error('Character must be a string of length 1'); | |
state = state || defaultState(); | |
var wasComment = state.blockComment || state.lineComment; | |
var lastChar = state.history ? state.history[0] : ''; | |
if (state.lineComment) { | |
if (character === '\n') { | |
state.lineComment = false; | |
} | |
} else if (state.blockComment) { | |
if (state.lastChar === '*' && character === '/') { | |
state.blockComment = false; | |
} | |
} else if (state.singleQuote) { | |
if (character === '\'' && !state.escaped) { | |
state.singleQuote = false; | |
} else if (character === '\\' && !state.escaped) { | |
state.escaped = true; | |
} else { | |
state.escaped = false; | |
} | |
} else if (state.doubleQuote) { | |
if (character === '"' && !state.escaped) { | |
state.doubleQuote = false; | |
} else if (character === '\\' && !state.escaped) { | |
state.escaped = true; | |
} else { | |
state.escaped = false; | |
} | |
} else if (state.regexp) { | |
if (character === '/' && !state.escaped) { | |
state.regexp = false; | |
} else if (character === '\\' && !state.escaped) { | |
state.escaped = true; | |
} else { | |
state.escaped = false; | |
} | |
} else if (lastChar === '/' && character === '/') { | |
history = history.substr(1); | |
state.lineComment = true; | |
} else if (lastChar === '/' && character === '*') { | |
history = history.substr(1); | |
state.blockComment = true; | |
} else if (character === '/') { | |
//could be start of regexp or divide sign | |
var history = state.history.replace(/^\s*/, ''); | |
if (history[0] === ')') { | |
//unless its an `if`, `while`, `for` or `with` it's a divide | |
//this is probably best left though | |
} else if (history[0] === '}') { | |
//unless it's a function expression, it's a regexp | |
//this is probably best left though | |
} else if (isPunctuator(history[0])) { | |
state.regexp = true; | |
} else if (/^\w+\b/.test(history) && isKeyword(/^\w+\b/.exec(history)[0])) { | |
state.regexp = true; | |
} else { | |
// assume it's divide | |
} | |
} else if (character === '\'') { | |
state.singleQuote = true; | |
} else if (character === '"') { | |
state.doubleQuote = true; | |
} else if (character === '(') { | |
state.roundDepth++; | |
} else if (character === ')') { | |
state.roundDepth--; | |
} else if (character === '{') { | |
state.curlyDepth++; | |
} else if (character === '}') { | |
state.curlyDepth--; | |
} else if (character === '[') { | |
state.squareDepth++; | |
} else if (character === ']') { | |
state.squareDepth--; | |
} | |
if (!state.blockComment && !state.lineComment && !wasComment) state.history = character + state.history; | |
return state; | |
} | |
exports.defaultState = defaultState; | |
function defaultState() { | |
return { | |
lineComment: false, | |
blockComment: false, | |
singleQuote: false, | |
doubleQuote: false, | |
regexp: false, | |
escaped: false, | |
roundDepth: 0, | |
curlyDepth: 0, | |
squareDepth: 0, | |
history: '' | |
}; | |
} | |
function startsWith(str, start, i) { | |
return str.substr(i || 0, start.length) === start; | |
} | |
function isPunctuator(c) { | |
var code = c.charCodeAt(0) | |
switch (code) { | |
case 46: // . dot | |
case 40: // ( open bracket | |
case 41: // ) close bracket | |
case 59: // ; semicolon | |
case 44: // , comma | |
case 123: // { open curly brace | |
case 125: // } close curly brace | |
case 91: // [ | |
case 93: // ] | |
case 58: // : | |
case 63: // ? | |
case 126: // ~ | |
case 37: // % | |
case 38: // & | |
case 42: // *: | |
case 43: // + | |
case 45: // - | |
case 47: // / | |
case 60: // < | |
case 62: // > | |
case 94: // ^ | |
case 124: // | | |
case 33: // ! | |
case 61: // = | |
return true; | |
default: | |
return false; | |
} | |
} | |
function isKeyword(id) { | |
return (id === 'if') || (id === 'in') || (id === 'do') || (id === 'var') || (id === 'for') || (id === 'new') || | |
(id === 'try') || (id === 'let') || (id === 'this') || (id === 'else') || (id === 'case') || | |
(id === 'void') || (id === 'with') || (id === 'enum') || (id === 'while') || (id === 'break') || (id === 'catch') || | |
(id === 'throw') || (id === 'const') || (id === 'yield') || (id === 'class') || (id === 'super') || | |
(id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch') || (id === 'export') || | |
(id === 'import') || (id === 'default') || (id === 'finally') || (id === 'extends') || (id === 'function') || | |
(id === 'continue') || (id === 'debugger') || (id === 'package') || (id === 'private') || (id === 'interface') || | |
(id === 'instanceof') || (id === 'implements') || (id === 'protected') || (id === 'public') || (id === 'static') || | |
(id === 'yield') || (id === 'let'); | |
} | |
},{}],15:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Tag | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Attrs = require('./attrs'), | |
Block = require('./block'), | |
inlineTags = require('../inline-tags'); | |
/** | |
* Initialize a `Tag` node with the given tag `name` and optional `block`. | |
* | |
* @param {String} name | |
* @param {Block} block | |
* @api public | |
*/ | |
var Tag = module.exports = function Tag(name, block) { | |
this.name = name; | |
this.attrs = []; | |
this.block = block || new Block; | |
}; | |
/** | |
* Inherit from `Attrs`. | |
*/ | |
Tag.prototype.__proto__ = Attrs.prototype; | |
/** | |
* Clone this tag. | |
* | |
* @return {Tag} | |
* @api private | |
*/ | |
Tag.prototype.clone = function(){ | |
var clone = new Tag(this.name, this.block.clone()); | |
clone.line = this.line; | |
clone.attrs = this.attrs; | |
clone.textOnly = this.textOnly; | |
return clone; | |
}; | |
/** | |
* Check if this tag is an inline tag. | |
* | |
* @return {Boolean} | |
* @api private | |
*/ | |
Tag.prototype.isInline = function(){ | |
return ~inlineTags.indexOf(this.name); | |
}; | |
/** | |
* Check if this tag's contents can be inlined. Used for pretty printing. | |
* | |
* @return {Boolean} | |
* @api private | |
*/ | |
Tag.prototype.canInline = function(){ | |
var nodes = this.block.nodes; | |
function isInline(node){ | |
// Recurse if the node is a block | |
if (node.isBlock) return node.nodes.every(isInline); | |
return node.isText || (node.isInline && node.isInline()); | |
} | |
// Empty tag | |
if (!nodes.length) return true; | |
// Text-only or inline-only tag | |
if (1 == nodes.length) return isInline(nodes[0]); | |
// Multi-line inline-only tag | |
if (this.block.nodes.every(isInline)) { | |
for (var i = 1, len = nodes.length; i < len; ++i) { | |
if (nodes[i-1].isText && nodes[i].isText) | |
return false; | |
} | |
return true; | |
} | |
// Mixed tag | |
return false; | |
}; | |
},{"./attrs":29,"./block":20,"../inline-tags":30}],16:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Code | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a `Code` node with the given code `val`. | |
* Code may also be optionally buffered and escaped. | |
* | |
* @param {String} val | |
* @param {Boolean} buffer | |
* @param {Boolean} escape | |
* @api public | |
*/ | |
var Code = module.exports = function Code(val, buffer, escape) { | |
this.val = val; | |
this.buffer = buffer; | |
this.escape = escape; | |
if (val.match(/^ *else/)) this.debug = false; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Code.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],17:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Case | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a new `Case` with `expr`. | |
* | |
* @param {String} expr | |
* @api public | |
*/ | |
var Case = exports = module.exports = function Case(expr, block){ | |
this.expr = expr; | |
this.block = block; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Case.prototype.__proto__ = Node.prototype; | |
var When = exports.When = function When(expr, block){ | |
this.expr = expr; | |
this.block = block; | |
this.debug = false; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
When.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],18:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Each | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize an `Each` node, representing iteration | |
* | |
* @param {String} obj | |
* @param {String} val | |
* @param {String} key | |
* @param {Block} block | |
* @api public | |
*/ | |
var Each = module.exports = function Each(obj, val, key, block) { | |
this.obj = obj; | |
this.val = val; | |
this.key = key; | |
this.block = block; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Each.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],19:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Text | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a `Text` node with optional `line`. | |
* | |
* @param {String} line | |
* @api public | |
*/ | |
var Text = module.exports = function Text(line) { | |
this.val = ''; | |
if ('string' == typeof line) this.val = line; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Text.prototype.__proto__ = Node.prototype; | |
/** | |
* Flag as text. | |
*/ | |
Text.prototype.isText = true; | |
},{"./node":14}],20:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Block | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a new `Block` with an optional `node`. | |
* | |
* @param {Node} node | |
* @api public | |
*/ | |
var Block = module.exports = function Block(node){ | |
this.nodes = []; | |
if (node) this.push(node); | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Block.prototype.__proto__ = Node.prototype; | |
/** | |
* Block flag. | |
*/ | |
Block.prototype.isBlock = true; | |
/** | |
* Replace the nodes in `other` with the nodes | |
* in `this` block. | |
* | |
* @param {Block} other | |
* @api private | |
*/ | |
Block.prototype.replace = function(other){ | |
other.nodes = this.nodes; | |
}; | |
/** | |
* Pust the given `node`. | |
* | |
* @param {Node} node | |
* @return {Number} | |
* @api public | |
*/ | |
Block.prototype.push = function(node){ | |
return this.nodes.push(node); | |
}; | |
/** | |
* Check if this block is empty. | |
* | |
* @return {Boolean} | |
* @api public | |
*/ | |
Block.prototype.isEmpty = function(){ | |
return 0 == this.nodes.length; | |
}; | |
/** | |
* Unshift the given `node`. | |
* | |
* @param {Node} node | |
* @return {Number} | |
* @api public | |
*/ | |
Block.prototype.unshift = function(node){ | |
return this.nodes.unshift(node); | |
}; | |
/** | |
* Return the "last" block, or the first `yield` node. | |
* | |
* @return {Block} | |
* @api private | |
*/ | |
Block.prototype.includeBlock = function(){ | |
var ret = this | |
, node; | |
for (var i = 0, len = this.nodes.length; i < len; ++i) { | |
node = this.nodes[i]; | |
if (node.yield) return node; | |
else if (node.textOnly) continue; | |
else if (node.includeBlock) ret = node.includeBlock(); | |
else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock(); | |
if (ret.yield) return ret; | |
} | |
return ret; | |
}; | |
/** | |
* Return a clone of this block. | |
* | |
* @return {Block} | |
* @api private | |
*/ | |
Block.prototype.clone = function(){ | |
var clone = new Block; | |
for (var i = 0, len = this.nodes.length; i < len; ++i) { | |
clone.push(this.nodes[i].clone()); | |
} | |
return clone; | |
}; | |
},{"./node":14}],21:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Mixin | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Attrs = require('./attrs'); | |
/** | |
* Initialize a new `Mixin` with `name` and `block`. | |
* | |
* @param {String} name | |
* @param {String} args | |
* @param {Block} block | |
* @api public | |
*/ | |
var Mixin = module.exports = function Mixin(name, args, block, call){ | |
this.name = name; | |
this.args = args; | |
this.block = block; | |
this.attrs = []; | |
this.call = call; | |
}; | |
/** | |
* Inherit from `Attrs`. | |
*/ | |
Mixin.prototype.__proto__ = Attrs.prototype; | |
},{"./attrs":29}],22:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Filter | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node') | |
, Block = require('./block'); | |
/** | |
* Initialize a `Filter` node with the given | |
* filter `name` and `block`. | |
* | |
* @param {String} name | |
* @param {Block|Node} block | |
* @api public | |
*/ | |
var Filter = module.exports = function Filter(name, block, attrs) { | |
this.name = name; | |
this.block = block; | |
this.attrs = attrs; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Filter.prototype.__proto__ = Node.prototype; | |
},{"./node":14,"./block":20}],23:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Comment | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a `Comment` with the given `val`, optionally `buffer`, | |
* otherwise the comment may render in the output. | |
* | |
* @param {String} val | |
* @param {Boolean} buffer | |
* @api public | |
*/ | |
var Comment = module.exports = function Comment(val, buffer) { | |
this.val = val; | |
this.buffer = buffer; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Comment.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],24:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Literal | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a `Literal` node with the given `str. | |
* | |
* @param {String} str | |
* @api public | |
*/ | |
var Literal = module.exports = function Literal(str) { | |
this.str = str; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Literal.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],25:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - BlockComment | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a `BlockComment` with the given `block`. | |
* | |
* @param {String} val | |
* @param {Block} block | |
* @param {Boolean} buffer | |
* @api public | |
*/ | |
var BlockComment = module.exports = function BlockComment(val, block, buffer) { | |
this.block = block; | |
this.val = val; | |
this.buffer = buffer; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
BlockComment.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],26:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Doctype | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'); | |
/** | |
* Initialize a `Doctype` with the given `val`. | |
* | |
* @param {String} val | |
* @api public | |
*/ | |
var Doctype = module.exports = function Doctype(val) { | |
this.val = val; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Doctype.prototype.__proto__ = Node.prototype; | |
},{"./node":14}],30:[function(require,module,exports){ | |
/*! | |
* Jade - inline tags | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
module.exports = [ | |
'a' | |
, 'abbr' | |
, 'acronym' | |
, 'b' | |
, 'br' | |
, 'code' | |
, 'em' | |
, 'font' | |
, 'i' | |
, 'img' | |
, 'ins' | |
, 'kbd' | |
, 'map' | |
, 'samp' | |
, 'small' | |
, 'span' | |
, 'strong' | |
, 'sub' | |
, 'sup' | |
]; | |
},{}],31:[function(require,module,exports){ | |
var Object_keys = function (obj) { | |
if (Object.keys) return Object.keys(obj) | |
else { | |
var res = []; | |
for (var key in obj) res.push(key) | |
return res; | |
} | |
}; | |
var forEach = function (xs, fn) { | |
if (xs.forEach) return xs.forEach(fn) | |
else for (var i = 0; i < xs.length; i++) { | |
fn(xs[i], i, xs); | |
} | |
}; | |
var Script = exports.Script = function NodeScript (code) { | |
if (!(this instanceof Script)) return new Script(code); | |
this.code = code; | |
}; | |
Script.prototype.runInNewContext = function (context) { | |
if (!context) context = {}; | |
var iframe = document.createElement('iframe'); | |
if (!iframe.style) iframe.style = {}; | |
iframe.style.display = 'none'; | |
document.body.appendChild(iframe); | |
var win = iframe.contentWindow; | |
forEach(Object_keys(context), function (key) { | |
win[key] = context[key]; | |
}); | |
if (!win.eval && win.execScript) { | |
// win.eval() magically appears when this is called in IE: | |
win.execScript('null'); | |
} | |
var res = win.eval(this.code); | |
forEach(Object_keys(win), function (key) { | |
context[key] = win[key]; | |
}); | |
document.body.removeChild(iframe); | |
return res; | |
}; | |
Script.prototype.runInThisContext = function () { | |
return eval(this.code); // maybe... | |
}; | |
Script.prototype.runInContext = function (context) { | |
// seems to be just runInNewContext on magical context objects which are | |
// otherwise indistinguishable from objects except plain old objects | |
// for the parameter segfaults node | |
return this.runInNewContext(context); | |
}; | |
forEach(Object_keys(Script.prototype), function (name) { | |
exports[name] = Script[name] = function (code) { | |
var s = Script(code); | |
return s[name].apply(s, [].slice.call(arguments, 1)); | |
}; | |
}); | |
exports.createScript = function (code) { | |
return exports.Script(code); | |
}; | |
exports.createContext = Script.createContext = function (context) { | |
// not really sure what this one does | |
// seems to just make a shallow copy | |
var copy = {}; | |
if(typeof context === 'object') { | |
forEach(Object_keys(context), function (key) { | |
copy[key] = context[key]; | |
}); | |
} | |
return copy; | |
}; | |
},{}],29:[function(require,module,exports){ | |
/*! | |
* Jade - nodes - Attrs | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var Node = require('./node'), | |
Block = require('./block'); | |
/** | |
* Initialize a `Attrs` node. | |
* | |
* @api public | |
*/ | |
var Attrs = module.exports = function Attrs() { | |
this.attrs = []; | |
}; | |
/** | |
* Inherit from `Node`. | |
*/ | |
Attrs.prototype.__proto__ = Node.prototype; | |
/** | |
* Set attribute `name` to `val`, keep in mind these become | |
* part of a raw js object literal, so to quote a value you must | |
* '"quote me"', otherwise or example 'user.name' is literal JavaScript. | |
* | |
* @param {String} name | |
* @param {String} val | |
* @param {Boolean} escaped | |
* @return {Tag} for chaining | |
* @api public | |
*/ | |
Attrs.prototype.setAttribute = function(name, val, escaped){ | |
this.attrs.push({ name: name, val: val, escaped: escaped }); | |
return this; | |
}; | |
/** | |
* Remove attribute `name` when present. | |
* | |
* @param {String} name | |
* @api public | |
*/ | |
Attrs.prototype.removeAttribute = function(name){ | |
for (var i = 0, len = this.attrs.length; i < len; ++i) { | |
if (this.attrs[i] && this.attrs[i].name == name) { | |
delete this.attrs[i]; | |
} | |
} | |
}; | |
/** | |
* Get attribute value by `name`. | |
* | |
* @param {String} name | |
* @return {String} | |
* @api public | |
*/ | |
Attrs.prototype.getAttribute = function(name){ | |
for (var i = 0, len = this.attrs.length; i < len; ++i) { | |
if (this.attrs[i] && this.attrs[i].name == name) { | |
return this.attrs[i].val; | |
} | |
} | |
}; | |
},{"./node":14,"./block":20}],28:[function(require,module,exports){ | |
(function(global){var dirname = require('path').dirname; | |
var Transformer = require('./shared'); | |
/** | |
* minifiers must be first in order to be incorporated inside instances of respective output formats | |
*/ | |
var uglifyJS = require('uglify-js'); | |
exports.uglify = exports.uglifyJS = exports['uglify-js'] = new Transformer({ | |
name: 'uglify-js', | |
engines: ['.'], | |
outputFormat: 'js', | |
isMinifier: true, | |
sync: function (str, options) { | |
options.fromString = true; | |
return this.cache(options) || this.cache(options, uglifyJS.minify(str, options).code); | |
} | |
}); | |
var uglifyCSS = require('css'); | |
exports.uglifyCSS = exports['uglify-css'] = new Transformer({ | |
name: 'uglify-css', | |
engines: ['.'], | |
outputFormat: 'css', | |
isMinifier: true, | |
sync: function (str, options) { | |
options.compress = options.compress != false && options.beautify != true; | |
return this.cache(options) || this.cache(options, uglifyCSS.stringify(uglifyCSS.parse(str), options)); | |
} | |
}); | |
exports.uglifyJSON = exports['uglify-json'] = new Transformer({ | |
name: 'uglify-json', | |
engines: ['.'], | |
outputFormat: 'json', | |
isMinifier: true, | |
sync: function (str, options) { | |
return JSON.stringify(JSON.parse(str), null, options.beautify); | |
} | |
}); | |
/** | |
* Syncronous Templating Languages | |
*/ | |
function sync(str, options) { | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
return tmpl(options); | |
} | |
exports.swig = new Transformer({ | |
name: 'swig', | |
engines: ['swig'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports.atpl = new Transformer({ | |
name: 'atpl', | |
engines: ['atpl'], | |
outputFormat: 'xml', | |
sync: function sync(str, options) { | |
var tmpl = this.cache(options); | |
if (!tmpl) { | |
var cInfo = {cache: options.cache, filename: options.filename}; | |
if (options.filename) { | |
delete options.filename; //atpl can't handle absolute windows file paths properly | |
} | |
tmpl = this.cache(cInfo, this.engine.compile(str, options)); | |
} | |
return tmpl(options); | |
} | |
}); | |
exports.dot = new Transformer({ | |
name: 'dot', | |
engines: ['dot'], | |
outputFormat: 'xml', | |
sync: function sync(str, options) { | |
var tmpl = this.cache(options) || this.cache(options, this.engine.template(str)); | |
return tmpl(options); | |
} | |
}); | |
exports.liquor = new Transformer({ | |
name: 'liquor', | |
engines: ['liquor'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports.ejs = new Transformer({ | |
name: 'ejs', | |
engines: ['ejs'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports.eco = new Transformer({ | |
name: 'eco', | |
engines: ['eco'], | |
outputFormat: 'xml', | |
sync: sync//N.B. eco's internal this.cache isn't quite right but this bypasses it | |
}); | |
exports.jqtpl = new Transformer({ | |
name: 'jqtpl', | |
engines: ['jqtpl'], | |
outputFormat: 'xml', | |
sync: function (str, options) { | |
var engine = this.engine; | |
var key = (options.cache && options.filename) ? options.filename : '@'; | |
engine.compile(str, key); | |
var res = this.engine.render(key, options); | |
if (!(options.cache && options.filename)) { | |
delete engine.cache[key]; | |
} | |
this.cache(options, true); // caching handled internally | |
return res; | |
} | |
}); | |
exports.haml = new Transformer({ | |
name: 'haml', | |
engines: ['hamljs'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports['haml-coffee'] = new Transformer({ | |
name: 'haml-coffee', | |
engines: ['haml-coffee'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports.whiskers = new Transformer({ | |
name: 'whiskers', | |
engines: ['whiskers'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports.hogan = new Transformer({ | |
name: 'hogan', | |
engines: ['hogan.js'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
return tmpl.render(options, options.partials); | |
} | |
}); | |
exports.handlebars = new Transformer({ | |
name: 'handlebars', | |
engines: ['handlebars'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
for (var partial in options.partials) { | |
this.engine.registerPartial(partial, options.partials[partial]); | |
} | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
return tmpl(options); | |
} | |
}); | |
exports.underscore = new Transformer({ | |
name: 'underscore', | |
engines: ['underscore'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
var tmpl = this.cache(options) || this.cache(options, this.engine.template(str)); | |
return tmpl(options); | |
} | |
}); | |
exports.walrus = new Transformer({ | |
name: 'walrus', | |
engines: ['walrus'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
var tmpl = this.cache(options) || this.cache(options, this.engine.parse(str)); | |
return tmpl.compile(options); | |
} | |
}); | |
exports.mustache = new Transformer({ | |
name: 'mustache', | |
engines: ['mustache'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str)); | |
return tmpl(options, options.partials); | |
} | |
}); | |
exports.templayed = new Transformer({ | |
name: 'templayed', | |
engines: ['templayed'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
var tmpl = this.cache(options) || this.cache(options, this.engine(str)); | |
return tmpl(options); | |
} | |
}); | |
exports.plates = new Transformer({ | |
name: 'plates', | |
engines: ['plates'], | |
outputFormat: 'xml', | |
sync: function(str, options){ | |
str = this.cache(options) || this.cache(options, str); | |
return this.engine.bind(str, options, options.map); | |
} | |
}); | |
exports.mote = new Transformer({ | |
name: 'mote', | |
engines: ['mote'], | |
outputFormat: 'xml', | |
sync: sync | |
}); | |
exports.toffee = new Transformer({ | |
name: 'toffee', | |
engines: ['toffee'], | |
outputFormat: 'xml', | |
sync: function (str, options) { | |
var View = this.engine.view; | |
var v = this.cache(options) || this.cache(options, new View(str, options)); | |
var res = v.run(options, require('vm').createContext({})); | |
if (res[0]) throw res[0]; | |
else return res[1]; | |
} | |
}); | |
exports.coffeekup = exports.coffeecup = new Transformer({ | |
name: 'coffeecup', | |
engines: ['coffeecup', 'coffeekup'], | |
outputFormat: 'xml', | |
sync: function (str, options) { | |
var compiled = this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
return compiled(options); | |
} | |
}); | |
/** | |
* Asyncronous Templating Languages | |
*/ | |
exports.just = new Transformer({ | |
name: 'just', | |
engines: ['just'], | |
outputFormat: 'xml', | |
sudoSync: true, | |
async: function (str, options, cb) { | |
var JUST = this.engine; | |
var tmpl = this.cache(options) || this.cache(options, new JUST({ root: { page: str }})); | |
tmpl.render('page', options, cb); | |
} | |
}); | |
exports.ect = new Transformer({ | |
name: 'ect', | |
engines: ['ect'], | |
outputFormat: 'xml', | |
sudoSync: true, // Always runs syncronously | |
async: function (str, options, cb) { | |
var ECT = this.engine; | |
var tmpl = this.cache(options) || this.cache(options, new ECT({ root: { page: str }})); | |
tmpl.render('page', options, cb); | |
} | |
}); | |
exports.jade = new Transformer({ | |
name: 'jade', | |
engines: ['jade', 'then-jade'], | |
outputFormat: 'xml', | |
sudoSync: 'The jade file FILENAME could not be rendered syncronously. N.B. then-jade does not support syncronous rendering.', | |
async: function (str, options, cb) { | |
this.cache(options, true);//jade handles this.cache internally | |
this.engine.render(str, options, cb); | |
} | |
}) | |
exports.dust = new Transformer({ | |
name: 'dust', | |
engines: ['dust', 'dustjs-linkedin'], | |
outputFormat: 'xml', | |
sudoSync: false, | |
async: function (str, options, cb) { | |
var ext = 'dust' | |
, views = '.'; | |
if (options) { | |
if (options.ext) ext = options.ext; | |
if (options.views) views = options.views; | |
if (options.settings && options.settings.views) views = options.settings.views; | |
} | |
this.engine.onLoad = function(path, callback){ | |
if ('' == extname(path)) path += '.' + ext; | |
if ('/' !== path[0]) path = views + '/' + path; | |
read(path, options, callback); | |
}; | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compileFn(str)); | |
if (options && !options.cache) this.engine.cache = {};//invalidate dust's internal cache | |
tmpl(options, cb); | |
} | |
}); | |
exports.jazz = new Transformer({ | |
name: 'jazz', | |
engines: ['jazz'], | |
outputFormat: 'xml', | |
sudoSync: true, // except when an async function is passed to locals | |
async: function (str, options, cb) { | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
tmpl.eval(options, function(str){ | |
cb(null, str); | |
}); | |
} | |
}); | |
exports.qejs = new Transformer({ | |
name: 'qejs', | |
engines: ['qejs'], | |
outputFormat: 'xml', | |
sudoSync: false, | |
async: function (str, options, cb) { | |
var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
tmpl(options).done(function (result) { | |
cb(null, result); | |
}, function (err) { | |
cb(err); | |
}); | |
} | |
}); | |
/** | |
* Stylsheet Languages | |
*/ | |
exports.less = new Transformer({ | |
name: 'less', | |
engines: ['less'], | |
outputFormat: 'css', | |
sudoSync: 'The less file FILENAME could not be rendered syncronously. This is usually because the file contains `@import url` statements.', | |
async: function (str, options, cb) { | |
var self = this; | |
if (self.cache(options)) return cb(null, self.cache(options)); | |
if (options.filename) { | |
options.paths = options.paths || [dirname(options.filename)]; | |
} | |
//If this.cache is enabled, compress by default | |
if (options.compress !== true && options.compress !== false) { | |
options.compress = options.cache || false; | |
} | |
if (options.sudoSync) { | |
options.syncImport = true; | |
} | |
var parser = new(this.engine.Parser)(options); | |
parser.parse(str, function (err, tree) { | |
try { | |
if (err) throw err; | |
var res = tree.toCSS(options); | |
self.cache(options, res); | |
cb(null, res); | |
} catch (ex) { | |
if (!(ex instanceof Error) && typeof ex === 'object') { | |
ex.filename = ex.filename || '"Unkown Source"'; | |
var err = new Error(self.engine.formatError(ex, options).replace(/^[^:]+:/, ''), ex.filename, ex.line); | |
err.name = ex.type; | |
ex = err; | |
} | |
console.log('\n\n' + ex.stack + '\n\n'); | |
return cb(ex); | |
} | |
}); | |
} | |
}); | |
exports.styl = exports.stylus = new Transformer({ | |
name: 'stylus', | |
engines: ['stylus'], | |
outputFormat: 'css', | |
sudoSync: true,// always runs syncronously | |
async: function (str, options, cb) { | |
var self = this; | |
if (self.cache(options)) return cb(null, self.cache(options)); | |
if (options.filename) { | |
options.paths = options.paths || [dirname(options.filename)]; | |
} | |
//If this.cache is enabled, compress by default | |
if (options.compress !== true && options.compress !== false) { | |
options.compress = options.cache || false; | |
} | |
this.engine.render(str, options, function (err, res) { | |
if (err) return cb(err); | |
self.cache(options, res); | |
cb(null, res); | |
}); | |
} | |
}) | |
exports.sass = new Transformer({ | |
name: 'sass', | |
engines: ['sass'], | |
outputFormat: 'css', | |
sync: function (str, options) { | |
try { | |
return this.cache(options) || this.cache(options, this.engine.render(str)); | |
} catch (ex) { | |
if (options.filename) ex.message += ' in ' + options.filename; | |
throw ex; | |
} | |
} | |
}); | |
/** | |
* Miscelaneous | |
*/ | |
exports.md = exports.markdown = new Transformer({ | |
name: 'markdown', | |
engines: ['marked', 'supermarked', 'markdown-js', 'markdown'], | |
outputFormat: 'html', | |
sync: function (str, options) { | |
var arg = options; | |
if (this.engineName === 'markdown') arg = options.dialect; //even if undefined | |
return this.cache(options) || this.cache(options, this.engine.parse(str, arg)); | |
} | |
}); | |
exports.coffee = exports['coffee-script'] = exports.coffeescript = exports.coffeeScript = new Transformer({ | |
name: 'coffee-script', | |
engines: ['coffee-script'], | |
outputFormat: 'js', | |
sync: function (str, options) { | |
return this.cache(options) || this.cache(options, this.engine.compile(str, options)); | |
} | |
}); | |
exports.cson = new Transformer({ | |
name: 'cson', | |
engines: ['cson'], | |
outputFormat: 'json', | |
sync: function (str, options) { | |
//todo: remove once https://github.com/rstacruz/js2coffee/pull/174 accepted & released | |
if (global.Narcissus) delete global.Narcissus; //prevent global leak | |
return this.cache(options) || this.cache(options, JSON.stringify(this.engine.parseSync(str))); | |
} | |
}); | |
exports.cdata = new Transformer({ | |
name: 'cdata', | |
engines: ['.'],// `.` means "no dependency" | |
outputFormat: 'xml', | |
sync: function (str, options) { | |
return this.cache(options) || this.cache(options, '<![CDATA[\n' + str + '\n]]>'); | |
} | |
}); | |
exports.component = exports['component-js'] = new Transformer({ | |
name: 'component-js', | |
engines: ['component-builder'], | |
outputFormat: 'js', | |
async: function (str, options, cb) { | |
if (this.cache(options)) return this.cache(options); | |
var self = this; | |
var builder = new this.engine(dirname(options.filename)); | |
if (options.development) { | |
builder.development(); | |
} | |
if (options.sourceURLs === true || (options.sourceURLs !== false && options.development)) { | |
builder.addSourceURLs(); | |
} | |
var path = require('path'); | |
builder.paths = (options.paths || ['components']).map(function (p) { | |
if (path.resolve(p) === p) { | |
return p; | |
} else { | |
return path.join(dirname(options.filename), p); | |
} | |
}); | |
builder.build(function (err, obj) { | |
if (err) return cb(err); | |
else return cb(null, self.cache(options, obj.require + obj.js)); | |
}); | |
} | |
}); | |
exports['component-css'] = new Transformer({ | |
name: 'component-css', | |
engines: ['component-builder'], | |
outputFormat: 'css', | |
async: function (str, options, cb) { | |
if (this.cache(options)) return this.cache(options); | |
var self = this; | |
var builder = new this.engine(dirname(options.filename)); | |
if (options.development) { | |
builder.development(); | |
} | |
if (options.sourceURLs === true || (options.sourceURLs !== false && options.development)) { | |
builder.addSourceURLs(); | |
} | |
var path = require('path'); | |
builder.paths = (options.paths || ['components']).map(function (p) { | |
if (path.resolve(p) === p) { | |
return p; | |
} else { | |
return path.join(dirname(options.filename), p); | |
} | |
}); | |
builder.build(function (err, obj) { | |
if (err) return cb(err); | |
else return cb(null, self.cache(options, obj.css)); | |
}); | |
} | |
}); | |
exports['html2jade'] = new Transformer({ | |
name: 'html2jade', | |
engines: ['html2jade'], | |
outputFormat: 'jade', | |
async: function (str, options, cb) { | |
return this.cache(options) || this.cache(options, this.engine.convertHtml(str, options, cb)); | |
} | |
}); | |
exports['highlight'] = new Transformer({ | |
name: 'highlight', | |
engines: ['highlight.js'], | |
outputFormat: 'xml', | |
sync: function (str, options, cb) { | |
if (this.cache(options)) return this.cache(options); | |
if (options.lang) { | |
try { | |
return this.cache(options, this.engine.highlight(options.lang, str).value); | |
} catch (ex) {} | |
} | |
if (options.auto || !options.lang) { | |
try { | |
return this.cache(options, this.engine.highlightAuto(str).value); | |
} catch (ex) {} | |
} | |
return this.cache(options, str); | |
} | |
}); | |
/** | |
* Marker transformers (they don't actually apply a transformation, but let you declare the 'outputFormat') | |
*/ | |
exports.css = new Transformer({ | |
name: 'css', | |
engines: ['.'],// `.` means "no dependency" | |
outputFormat: 'css', | |
sync: function (str, options) { | |
return this.cache(options) || this.cache(options, str); | |
} | |
}); | |
exports.js = new Transformer({ | |
name: 'js', | |
engines: ['.'],// `.` means "no dependency" | |
outputFormat: 'js', | |
sync: function (str, options) { | |
return this.cache(options) || this.cache(options, str); | |
} | |
}); | |
})(window) | |
},{"path":13,"vm":31,"./shared":32,"uglify-js":33,"css":34}],35:[function(require,module,exports){ | |
var events = require('events'); | |
exports.isArray = isArray; | |
exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'}; | |
exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'}; | |
exports.print = function () {}; | |
exports.puts = function () {}; | |
exports.debug = function() {}; | |
exports.inspect = function(obj, showHidden, depth, colors) { | |
var seen = []; | |
var stylize = function(str, styleType) { | |
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics | |
var styles = | |
{ 'bold' : [1, 22], | |
'italic' : [3, 23], | |
'underline' : [4, 24], | |
'inverse' : [7, 27], | |
'white' : [37, 39], | |
'grey' : [90, 39], | |
'black' : [30, 39], | |
'blue' : [34, 39], | |
'cyan' : [36, 39], | |
'green' : [32, 39], | |
'magenta' : [35, 39], | |
'red' : [31, 39], | |
'yellow' : [33, 39] }; | |
var style = | |
{ 'special': 'cyan', | |
'number': 'blue', | |
'boolean': 'yellow', | |
'undefined': 'grey', | |
'null': 'bold', | |
'string': 'green', | |
'date': 'magenta', | |
// "name": intentionally not styling | |
'regexp': 'red' }[styleType]; | |
if (style) { | |
return '\033[' + styles[style][0] + 'm' + str + | |
'\033[' + styles[style][1] + 'm'; | |
} else { | |
return str; | |
} | |
}; | |
if (! colors) { | |
stylize = function(str, styleType) { return str; }; | |
} | |
function format(value, recurseTimes) { | |
// Provide a hook for user-specified inspect functions. | |
// Check that value is an object with an inspect function on it | |
if (value && typeof value.inspect === 'function' && | |
// Filter out the util module, it's inspect function is special | |
value !== exports && | |
// Also filter out any prototype objects using the circular check. | |
!(value.constructor && value.constructor.prototype === value)) { | |
return value.inspect(recurseTimes); | |
} | |
// Primitive types cannot have properties | |
switch (typeof value) { | |
case 'undefined': | |
return stylize('undefined', 'undefined'); | |
case 'string': | |
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') | |
.replace(/'/g, "\\'") | |
.replace(/\\"/g, '"') + '\''; | |
return stylize(simple, 'string'); | |
case 'number': | |
return stylize('' + value, 'number'); | |
case 'boolean': | |
return stylize('' + value, 'boolean'); | |
} | |
// For some reason typeof null is "object", so special case here. | |
if (value === null) { | |
return stylize('null', 'null'); | |
} | |
// Look up the keys of the object. | |
var visible_keys = Object_keys(value); | |
var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys; | |
// Functions without properties can be shortcutted. | |
if (typeof value === 'function' && keys.length === 0) { | |
if (isRegExp(value)) { | |
return stylize('' + value, 'regexp'); | |
} else { | |
var name = value.name ? ': ' + value.name : ''; | |
return stylize('[Function' + name + ']', 'special'); | |
} | |
} | |
// Dates without properties can be shortcutted | |
if (isDate(value) && keys.length === 0) { | |
return stylize(value.toUTCString(), 'date'); | |
} | |
var base, type, braces; | |
// Determine the object type | |
if (isArray(value)) { | |
type = 'Array'; | |
braces = ['[', ']']; | |
} else { | |
type = 'Object'; | |
braces = ['{', '}']; | |
} | |
// Make functions say that they are functions | |
if (typeof value === 'function') { | |
var n = value.name ? ': ' + value.name : ''; | |
base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; | |
} else { | |
base = ''; | |
} | |
// Make dates with properties first say the date | |
if (isDate(value)) { | |
base = ' ' + value.toUTCString(); | |
} | |
if (keys.length === 0) { | |
return braces[0] + base + braces[1]; | |
} | |
if (recurseTimes < 0) { | |
if (isRegExp(value)) { | |
return stylize('' + value, 'regexp'); | |
} else { | |
return stylize('[Object]', 'special'); | |
} | |
} | |
seen.push(value); | |
var output = keys.map(function(key) { | |
var name, str; | |
if (value.__lookupGetter__) { | |
if (value.__lookupGetter__(key)) { | |
if (value.__lookupSetter__(key)) { | |
str = stylize('[Getter/Setter]', 'special'); | |
} else { | |
str = stylize('[Getter]', 'special'); | |
} | |
} else { | |
if (value.__lookupSetter__(key)) { | |
str = stylize('[Setter]', 'special'); | |
} | |
} | |
} | |
if (visible_keys.indexOf(key) < 0) { | |
name = '[' + key + ']'; | |
} | |
if (!str) { | |
if (seen.indexOf(value[key]) < 0) { | |
if (recurseTimes === null) { | |
str = format(value[key]); | |
} else { | |
str = format(value[key], recurseTimes - 1); | |
} | |
if (str.indexOf('\n') > -1) { | |
if (isArray(value)) { | |
str = str.split('\n').map(function(line) { | |
return ' ' + line; | |
}).join('\n').substr(2); | |
} else { | |
str = '\n' + str.split('\n').map(function(line) { | |
return ' ' + line; | |
}).join('\n'); | |
} | |
} | |
} else { | |
str = stylize('[Circular]', 'special'); | |
} | |
} | |
if (typeof name === 'undefined') { | |
if (type === 'Array' && key.match(/^\d+$/)) { | |
return str; | |
} | |
name = JSON.stringify('' + key); | |
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { | |
name = name.substr(1, name.length - 2); | |
name = stylize(name, 'name'); | |
} else { | |
name = name.replace(/'/g, "\\'") | |
.replace(/\\"/g, '"') | |
.replace(/(^"|"$)/g, "'"); | |
name = stylize(name, 'string'); | |
} | |
} | |
return name + ': ' + str; | |
}); | |
seen.pop(); | |
var numLinesEst = 0; | |
var length = output.reduce(function(prev, cur) { | |
numLinesEst++; | |
if (cur.indexOf('\n') >= 0) numLinesEst++; | |
return prev + cur.length + 1; | |
}, 0); | |
if (length > 50) { | |
output = braces[0] + | |
(base === '' ? '' : base + '\n ') + | |
' ' + | |
output.join(',\n ') + | |
' ' + | |
braces[1]; | |
} else { | |
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; | |
} | |
return output; | |
} | |
return format(obj, (typeof depth === 'undefined' ? 2 : depth)); | |
}; | |
function isArray(ar) { | |
return ar instanceof Array || | |
Array.isArray(ar) || | |
(ar && ar !== Object.prototype && isArray(ar.__proto__)); | |
} | |
function isRegExp(re) { | |
return re instanceof RegExp || | |
(typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]'); | |
} | |
function isDate(d) { | |
if (d instanceof Date) return true; | |
if (typeof d !== 'object') return false; | |
var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype); | |
var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__); | |
return JSON.stringify(proto) === JSON.stringify(properties); | |
} | |
function pad(n) { | |
return n < 10 ? '0' + n.toString(10) : n.toString(10); | |
} | |
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', | |
'Oct', 'Nov', 'Dec']; | |
// 26 Feb 16:19:34 | |
function timestamp() { | |
var d = new Date(); | |
var time = [pad(d.getHours()), | |
pad(d.getMinutes()), | |
pad(d.getSeconds())].join(':'); | |
return [d.getDate(), months[d.getMonth()], time].join(' '); | |
} | |
exports.log = function (msg) {}; | |
exports.pump = null; | |
var Object_keys = Object.keys || function (obj) { | |
var res = []; | |
for (var key in obj) res.push(key); | |
return res; | |
}; | |
var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) { | |
var res = []; | |
for (var key in obj) { | |
if (Object.hasOwnProperty.call(obj, key)) res.push(key); | |
} | |
return res; | |
}; | |
var Object_create = Object.create || function (prototype, properties) { | |
// from es5-shim | |
var object; | |
if (prototype === null) { | |
object = { '__proto__' : null }; | |
} | |
else { | |
if (typeof prototype !== 'object') { | |
throw new TypeError( | |
'typeof prototype[' + (typeof prototype) + '] != \'object\'' | |
); | |
} | |
var Type = function () {}; | |
Type.prototype = prototype; | |
object = new Type(); | |
object.__proto__ = prototype; | |
} | |
if (typeof properties !== 'undefined' && Object.defineProperties) { | |
Object.defineProperties(object, properties); | |
} | |
return object; | |
}; | |
exports.inherits = function(ctor, superCtor) { | |
ctor.super_ = superCtor; | |
ctor.prototype = Object_create(superCtor.prototype, { | |
constructor: { | |
value: ctor, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}); | |
}; | |
var formatRegExp = /%[sdj%]/g; | |
exports.format = function(f) { | |
if (typeof f !== 'string') { | |
var objects = []; | |
for (var i = 0; i < arguments.length; i++) { | |
objects.push(exports.inspect(arguments[i])); | |
} | |
return objects.join(' '); | |
} | |
var i = 1; | |
var args = arguments; | |
var len = args.length; | |
var str = String(f).replace(formatRegExp, function(x) { | |
if (x === '%%') return '%'; | |
if (i >= len) return x; | |
switch (x) { | |
case '%s': return String(args[i++]); | |
case '%d': return Number(args[i++]); | |
case '%j': return JSON.stringify(args[i++]); | |
default: | |
return x; | |
} | |
}); | |
for(var x = args[i]; i < len; x = args[++i]){ | |
if (x === null || typeof x !== 'object') { | |
str += ' ' + x; | |
} else { | |
str += ' ' + exports.inspect(x); | |
} | |
} | |
return str; | |
}; | |
},{"events":36}],32:[function(require,module,exports){ | |
(function(process){var Promise = require('promise'); | |
var fs = require('fs'); | |
var path = require('path'); | |
var normalize = path.normalize; | |
Promise.prototype.nodeify = function (cb) { | |
if (typeof cb === 'function') { | |
this.then(function (res) { process.nextTick(function () { cb(null, res); }); }, | |
function (err) { process.nextTick(function () { cb(err); }); }); | |
return undefined; | |
} else { | |
return this; | |
} | |
} | |
var minifiers = {}; | |
module.exports = Transformer; | |
function Transformer(obj) { | |
this.name = obj.name; | |
this.engines = obj.engines; | |
this.isBinary = obj.isBinary || false; | |
this.isMinifier = obj.isMinifier || false; | |
this.outputFormat = obj.outputFormat; | |
this._cache = {}; | |
if (typeof obj.async === 'function') { | |
this._renderAsync = obj.async; | |
this.sudoSync = obj.sudoSync || false; | |
} | |
if (typeof obj.sync === 'function') { | |
this._renderSync = obj.sync; | |
this.sync = true; | |
} else { | |
this.sync = obj.sudoSync || false; | |
} | |
if (this.isMinifier) | |
minifiers[this.outputFormat] = this; | |
else { | |
var minifier = minifiers[this.outputFormat]; | |
if (minifier) { | |
this.minify = function(str, options) { | |
if (options && options.minify) | |
return minifier.renderSync(str, typeof options.minify === 'object' && options.minify || {}); | |
return str; | |
} | |
} | |
} | |
} | |
Transformer.prototype.cache = function (options, data) { | |
if (options.cache && options.filename) { | |
if (data) return this.cache[options.filename] = data; | |
else return this.cache[options.filename]; | |
} else { | |
return data; | |
} | |
}; | |
Transformer.prototype.loadModule = function () { | |
if (this.engine) return this.engine; | |
for (var i = 0; i < this.engines.length; i++) { | |
try { | |
var res = this.engines[i] === '.' ? null : (this.engine = require(this.engines[i])); | |
this.engineName = this.engines[i]; | |
return res; | |
} catch (ex) { | |
if (this.engines.length === 1) { | |
throw ex; | |
} | |
} | |
} | |
throw new Error('In order to apply the transform ' + this.name + ' you must install one of ' + this.engines.map(function (e) { return '"' + e + '"'; }).join()); | |
}; | |
Transformer.prototype.minify = function(str, options) { | |
return str; | |
} | |
Transformer.prototype.renderSync = function (str, options) { | |
options = options || {}; | |
options = clone(options); | |
this.loadModule(); | |
if (this._renderSync) { | |
return this.minify(this._renderSync((this.isBinary ? str : fixString(str)), options), options); | |
} else if (this.sudoSync) { | |
options.sudoSync = true; | |
var res, err; | |
this._renderAsync((this.isBinary ? str : fixString(str)), options, function (e, val) { | |
if (e) err = e; | |
else res = val; | |
}); | |
if (err) throw err; | |
else if (res != undefined) return this.minify(res, options); | |
else if (typeof this.sudoSync === 'string') throw new Error(this.sudoSync.replace(/FILENAME/g, options.filename || '')); | |
else throw new Error('There was a problem transforming ' + (options.filename || '') + ' syncronously using ' + this.name); | |
} else { | |
throw new Error(this.name + ' does not support transforming syncronously.'); | |
} | |
}; | |
Transformer.prototype.render = function (str, options, cb) { | |
options = options || {}; | |
var self = this; | |
return new Promise(function (resolve, reject) { | |
self.loadModule(); | |
if (self._renderAsync) { | |
self._renderAsync((self.isBinary ? str : fixString(str)), clone(options), function (err, val) { | |
if (err) reject(err); | |
else resolve(self.minify(val, options)); | |
}) | |
} else { | |
resolve(self.renderSync(str, options)); | |
} | |
}) | |
.nodeify(cb); | |
}; | |
Transformer.prototype.renderFile = function (path, options, cb) { | |
options = options || {}; | |
var self = this; | |
return new Promise(function (resolve, reject) { | |
options.filename = (path = normalize(path)); | |
if (self._cache[path]) | |
resolve(null); | |
else | |
fs.readFile(path, function (err, data) { | |
if (err) reject(err); | |
else resolve(data); | |
}) | |
}) | |
.then(function (str) { | |
return self.render(str, options); | |
}) | |
.nodeify(cb); | |
}; | |
Transformer.prototype.renderFileSync = function (path, options) { | |
options = options || {}; | |
options.filename = (path = normalize(path)); | |
return this.renderSync((this._cache[path] ? null : fs.readFileSync(path)), options); | |
}; | |
function fixString(str) { | |
if (str == null) return str; | |
//convert buffer to string | |
str = str.toString(); | |
// Strip UTF-8 BOM if it exists | |
str = (0xFEFF == str.charCodeAt(0) | |
? str.substring(1) | |
: str); | |
//remove `\r` added by windows | |
return str.replace(/\r/g, ''); | |
} | |
function clone(obj) { | |
if (Array.isArray(obj)) { | |
return obj.map(clone); | |
} else if (obj && typeof obj === 'object') { | |
var res = {}; | |
for (var key in obj) { | |
res[key] = clone(obj[key]); | |
} | |
return res; | |
} else { | |
return obj; | |
} | |
} | |
})(require("__browserify_process")) | |
},{"fs":1,"path":13,"promise":37,"__browserify_process":12}],36:[function(require,module,exports){ | |
(function(process){if (!process.EventEmitter) process.EventEmitter = function () {}; | |
var EventEmitter = exports.EventEmitter = process.EventEmitter; | |
var isArray = typeof Array.isArray === 'function' | |
? Array.isArray | |
: function (xs) { | |
return Object.prototype.toString.call(xs) === '[object Array]' | |
} | |
; | |
function indexOf (xs, x) { | |
if (xs.indexOf) return xs.indexOf(x); | |
for (var i = 0; i < xs.length; i++) { | |
if (x === xs[i]) return i; | |
} | |
return -1; | |
} | |
// By default EventEmitters will print a warning if more than | |
// 10 listeners are added to it. This is a useful default which | |
// helps finding memory leaks. | |
// | |
// Obviously not all Emitters should be limited to 10. This function allows | |
// that to be increased. Set to zero for unlimited. | |
var defaultMaxListeners = 10; | |
EventEmitter.prototype.setMaxListeners = function(n) { | |
if (!this._events) this._events = {}; | |
this._events.maxListeners = n; | |
}; | |
EventEmitter.prototype.emit = function(type) { | |
// If there is no 'error' event listener then throw. | |
if (type === 'error') { | |
if (!this._events || !this._events.error || | |
(isArray(this._events.error) && !this._events.error.length)) | |
{ | |
if (arguments[1] instanceof Error) { | |
throw arguments[1]; // Unhandled 'error' event | |
} else { | |
throw new Error("Uncaught, unspecified 'error' event."); | |
} | |
return false; | |
} | |
} | |
if (!this._events) return false; | |
var handler = this._events[type]; | |
if (!handler) return false; | |
if (typeof handler == 'function') { | |
switch (arguments.length) { | |
// fast cases | |
case 1: | |
handler.call(this); | |
break; | |
case 2: | |
handler.call(this, arguments[1]); | |
break; | |
case 3: | |
handler.call(this, arguments[1], arguments[2]); | |
break; | |
// slower | |
default: | |
var args = Array.prototype.slice.call(arguments, 1); | |
handler.apply(this, args); | |
} | |
return true; | |
} else if (isArray(handler)) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
var listeners = handler.slice(); | |
for (var i = 0, l = listeners.length; i < l; i++) { | |
listeners[i].apply(this, args); | |
} | |
return true; | |
} else { | |
return false; | |
} | |
}; | |
// EventEmitter is defined in src/node_events.cc | |
// EventEmitter.prototype.emit() is also defined there. | |
EventEmitter.prototype.addListener = function(type, listener) { | |
if ('function' !== typeof listener) { | |
throw new Error('addListener only takes instances of Function'); | |
} | |
if (!this._events) this._events = {}; | |
// To avoid recursion in the case that type == "newListeners"! Before | |
// adding it to the listeners, first emit "newListeners". | |
this.emit('newListener', type, listener); | |
if (!this._events[type]) { | |
// Optimize the case of one listener. Don't need the extra array object. | |
this._events[type] = listener; | |
} else if (isArray(this._events[type])) { | |
// Check for listener leak | |
if (!this._events[type].warned) { | |
var m; | |
if (this._events.maxListeners !== undefined) { | |
m = this._events.maxListeners; | |
} else { | |
m = defaultMaxListeners; | |
} | |
if (m && m > 0 && this._events[type].length > m) { | |
this._events[type].warned = true; | |
console.error('(node) warning: possible EventEmitter memory ' + | |
'leak detected. %d listeners added. ' + | |
'Use emitter.setMaxListeners() to increase limit.', | |
this._events[type].length); | |
console.trace(); | |
} | |
} | |
// If we've already got an array, just append. | |
this._events[type].push(listener); | |
} else { | |
// Adding the second element, need to change to array. | |
this._events[type] = [this._events[type], listener]; | |
} | |
return this; | |
}; | |
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | |
EventEmitter.prototype.once = function(type, listener) { | |
var self = this; | |
self.on(type, function g() { | |
self.removeListener(type, g); | |
listener.apply(this, arguments); | |
}); | |
return this; | |
}; | |
EventEmitter.prototype.removeListener = function(type, listener) { | |
if ('function' !== typeof listener) { | |
throw new Error('removeListener only takes instances of Function'); | |
} | |
// does not use listeners(), so no side effect of creating _events[type] | |
if (!this._events || !this._events[type]) return this; | |
var list = this._events[type]; | |
if (isArray(list)) { | |
var i = indexOf(list, listener); | |
if (i < 0) return this; | |
list.splice(i, 1); | |
if (list.length == 0) | |
delete this._events[type]; | |
} else if (this._events[type] === listener) { | |
delete this._events[type]; | |
} | |
return this; | |
}; | |
EventEmitter.prototype.removeAllListeners = function(type) { | |
if (arguments.length === 0) { | |
this._events = {}; | |
return this; | |
} | |
// does not use listeners(), so no side effect of creating _events[type] | |
if (type && this._events && this._events[type]) this._events[type] = null; | |
return this; | |
}; | |
EventEmitter.prototype.listeners = function(type) { | |
if (!this._events) this._events = {}; | |
if (!this._events[type]) this._events[type] = []; | |
if (!isArray(this._events[type])) { | |
this._events[type] = [this._events[type]]; | |
} | |
return this._events[type]; | |
}; | |
})(require("__browserify_process")) | |
},{"__browserify_process":12}],34:[function(require,module,exports){ | |
exports.parse = require('css-parse'); | |
exports.stringify = require('css-stringify'); | |
},{"css-parse":38,"css-stringify":39}],33:[function(require,module,exports){ | |
(function(process,__filename){var path = require("path"); | |
var fs = require("fs"); | |
var vm = require("vm"); | |
var sys = require("util"); | |
var UglifyJS = vm.createContext({ | |
sys : sys, | |
console : console, | |
MOZ_SourceMap : require("source-map") | |
}); | |
function load_global(file) { | |
file = path.resolve(path.dirname(module.filename), file); | |
try { | |
var code = fs.readFileSync(file, "utf8"); | |
return vm.runInContext(code, UglifyJS, file); | |
} catch(ex) { | |
// XXX: in case of a syntax error, the message is kinda | |
// useless. (no location information). | |
sys.debug("ERROR in file: " + file + " / " + ex); | |
process.exit(1); | |
} | |
}; | |
var FILES = exports.FILES = [ | |
"../lib/utils.js", | |
"../lib/ast.js", | |
"../lib/parse.js", | |
"../lib/transform.js", | |
"../lib/scope.js", | |
"../lib/output.js", | |
"../lib/compress.js", | |
"../lib/sourcemap.js", | |
"../lib/mozilla-ast.js" | |
].map(function(file){ | |
return path.join(path.dirname(fs.realpathSync(__filename)), file); | |
}); | |
FILES.forEach(load_global); | |
UglifyJS.AST_Node.warn_function = function(txt) { | |
sys.error("WARN: " + txt); | |
}; | |
// XXX: perhaps we shouldn't export everything but heck, I'm lazy. | |
for (var i in UglifyJS) { | |
if (UglifyJS.hasOwnProperty(i)) { | |
exports[i] = UglifyJS[i]; | |
} | |
} | |
exports.minify = function(files, options) { | |
options = UglifyJS.defaults(options, { | |
outSourceMap : null, | |
sourceRoot : null, | |
inSourceMap : null, | |
fromString : false, | |
warnings : false, | |
mangle : {}, | |
output : null, | |
compress : {} | |
}); | |
if (typeof files == "string") | |
files = [ files ]; | |
// 1. parse | |
var toplevel = null; | |
files.forEach(function(file){ | |
var code = options.fromString | |
? file | |
: fs.readFileSync(file, "utf8"); | |
toplevel = UglifyJS.parse(code, { | |
filename: options.fromString ? "?" : file, | |
toplevel: toplevel | |
}); | |
}); | |
// 2. compress | |
if (options.compress) { | |
var compress = { warnings: options.warnings }; | |
UglifyJS.merge(compress, options.compress); | |
toplevel.figure_out_scope(); | |
var sq = UglifyJS.Compressor(compress); | |
toplevel = toplevel.transform(sq); | |
} | |
// 3. mangle | |
if (options.mangle) { | |
toplevel.figure_out_scope(); | |
toplevel.compute_char_frequency(); | |
toplevel.mangle_names(options.mangle); | |
} | |
// 4. output | |
var map = null; | |
var inMap = null; | |
if (options.inSourceMap) { | |
inMap = fs.readFileSync(options.inSourceMap, "utf8"); | |
} | |
if (options.outSourceMap) map = UglifyJS.SourceMap({ | |
file: options.outSourceMap, | |
orig: inMap, | |
root: options.sourceRoot | |
}); | |
var output = { source_map: map }; | |
if (options.output) { | |
UglifyJS.merge(output, options.output); | |
} | |
var stream = UglifyJS.OutputStream(output); | |
toplevel.print(stream); | |
return { | |
code : stream + "", | |
map : map + "" | |
}; | |
}; | |
// exports.describe_ast = function() { | |
// function doitem(ctor) { | |
// var sub = {}; | |
// ctor.SUBCLASSES.forEach(function(ctor){ | |
// sub[ctor.TYPE] = doitem(ctor); | |
// }); | |
// var ret = {}; | |
// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; | |
// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; | |
// return ret; | |
// } | |
// return doitem(UglifyJS.AST_Node).sub; | |
// } | |
exports.describe_ast = function() { | |
var out = UglifyJS.OutputStream({ beautify: true }); | |
function doitem(ctor) { | |
out.print("AST_" + ctor.TYPE); | |
var props = ctor.SELF_PROPS.filter(function(prop){ | |
return !/^\$/.test(prop); | |
}); | |
if (props.length > 0) { | |
out.space(); | |
out.with_parens(function(){ | |
props.forEach(function(prop, i){ | |
if (i) out.space(); | |
out.print(prop); | |
}); | |
}); | |
} | |
if (ctor.documentation) { | |
out.space(); | |
out.print_string(ctor.documentation); | |
} | |
if (ctor.SUBCLASSES.length > 0) { | |
out.space(); | |
out.with_block(function(){ | |
ctor.SUBCLASSES.forEach(function(ctor, i){ | |
out.indent(); | |
doitem(ctor); | |
out.newline(); | |
}); | |
}); | |
} | |
}; | |
doitem(UglifyJS.AST_Node); | |
return out + ""; | |
}; | |
})(require("__browserify_process"),"/../node_modules/transformers/node_modules/uglify-js/tools/node.js") | |
},{"path":13,"fs":1,"vm":31,"util":35,"source-map":40,"__browserify_process":12}],38:[function(require,module,exports){ | |
module.exports = function(css){ | |
/** | |
* Parse stylesheet. | |
*/ | |
function stylesheet() { | |
return { stylesheet: { rules: rules() }}; | |
} | |
/** | |
* Opening brace. | |
*/ | |
function open() { | |
return match(/^{\s*/); | |
} | |
/** | |
* Closing brace. | |
*/ | |
function close() { | |
return match(/^}\s*/); | |
} | |
/** | |
* Parse ruleset. | |
*/ | |
function rules() { | |
var node; | |
var rules = []; | |
whitespace(); | |
comments(); | |
while (css[0] != '}' && (node = atrule() || rule())) { | |
comments(); | |
rules.push(node); | |
} | |
return rules; | |
} | |
/** | |
* Match `re` and return captures. | |
*/ | |
function match(re) { | |
var m = re.exec(css); | |
if (!m) return; | |
css = css.slice(m[0].length); | |
return m; | |
} | |
/** | |
* Parse whitespace. | |
*/ | |
function whitespace() { | |
match(/^\s*/); | |
} | |
/** | |
* Parse comments; | |
*/ | |
function comments() { | |
while (comment()) ; | |
} | |
/** | |
* Parse comment. | |
*/ | |
function comment() { | |
if ('/' == css[0] && '*' == css[1]) { | |
var i = 2; | |
while ('*' != css[i] || '/' != css[i + 1]) ++i; | |
i += 2; | |
css = css.slice(i); | |
whitespace(); | |
return true; | |
} | |
} | |
/** | |
* Parse selector. | |
*/ | |
function selector() { | |
var m = match(/^([^{]+)/); | |
if (!m) return; | |
return m[0].trim().split(/\s*,\s*/); | |
} | |
/** | |
* Parse declaration. | |
*/ | |
function declaration() { | |
// prop | |
var prop = match(/^(\*?[-\w]+)\s*/); | |
if (!prop) return; | |
prop = prop[0]; | |
// : | |
if (!match(/^:\s*/)) return; | |
// val | |
var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)\s*/); | |
if (!val) return; | |
val = val[0].trim(); | |
// ; | |
match(/^[;\s]*/); | |
return { property: prop, value: val }; | |
} | |
/** | |
* Parse keyframe. | |
*/ | |
function keyframe() { | |
var m; | |
var vals = []; | |
while (m = match(/^(from|to|\d+%|\.\d+%|\d+\.\d+%)\s*/)) { | |
vals.push(m[1]); | |
match(/^,\s*/); | |
} | |
if (!vals.length) return; | |
return { | |
values: vals, | |
declarations: declarations() | |
}; | |
} | |
/** | |
* Parse keyframes. | |
*/ | |
function keyframes() { | |
var m = match(/^@([-\w]+)?keyframes */); | |
if (!m) return; | |
var vendor = m[1]; | |
// identifier | |
var m = match(/^([-\w]+)\s*/); | |
if (!m) return; | |
var name = m[1]; | |
if (!open()) return; | |
comments(); | |
var frame; | |
var frames = []; | |
while (frame = keyframe()) { | |
frames.push(frame); | |
comments(); | |
} | |
if (!close()) return; | |
return { | |
name: name, | |
vendor: vendor, | |
keyframes: frames | |
}; | |
} | |
/** | |
* Parse media. | |
*/ | |
function media() { | |
var m = match(/^@media *([^{]+)/); | |
if (!m) return; | |
var media = m[1].trim(); | |
if (!open()) return; | |
comments(); | |
var style = rules(); | |
if (!close()) return; | |
return { media: media, rules: style }; | |
} | |
/** | |
* Parse import | |
*/ | |
function atimport() { | |
return _atrule('import') | |
} | |
/** | |
* Parse charset | |
*/ | |
function atcharset() { | |
return _atrule('charset'); | |
} | |
/** | |
* Parse non-block at-rules | |
*/ | |
function _atrule(name) { | |
var m = match(new RegExp('^@' + name + ' *([^;\\n]+);\\s*')); | |
if (!m) return; | |
var ret = {} | |
ret[name] = m[1].trim(); | |
return ret; | |
} | |
/** | |
* Parse declarations. | |
*/ | |
function declarations() { | |
var decls = []; | |
if (!open()) return; | |
comments(); | |
// declarations | |
var decl; | |
while (decl = declaration()) { | |
decls.push(decl); | |
comments(); | |
} | |
if (!close()) return; | |
return decls; | |
} | |
/** | |
* Parse at rule. | |
*/ | |
function atrule() { | |
return keyframes() | |
|| media() | |
|| atimport() | |
|| atcharset(); | |
} | |
/** | |
* Parse rule. | |
*/ | |
function rule() { | |
var sel = selector(); | |
if (!sel) return; | |
comments(); | |
return { selectors: sel, declarations: declarations() }; | |
} | |
return stylesheet(); | |
}; | |
},{}],39:[function(require,module,exports){ | |
/** | |
* Stringfy the given AST `node`. | |
* | |
* @param {Object} node | |
* @param {Object} options | |
* @return {String} | |
* @api public | |
*/ | |
module.exports = function(node, options){ | |
return new Compiler(options).compile(node); | |
}; | |
/** | |
* Initialize a new `Compiler`. | |
*/ | |
function Compiler(options) { | |
options = options || {}; | |
this.compress = options.compress; | |
this.indentation = options.indent; | |
} | |
/** | |
* Compile `node`. | |
*/ | |
Compiler.prototype.compile = function(node){ | |
return node.stylesheet.rules.map(this.visit, this) | |
.join(this.compress ? '' : '\n\n'); | |
}; | |
/** | |
* Visit `node`. | |
*/ | |
Compiler.prototype.visit = function(node){ | |
if (node.charset) return this.charset(node); | |
if (node.keyframes) return this.keyframes(node); | |
if (node.media) return this.media(node); | |
if (node.import) return this.import(node); | |
return this.rule(node); | |
}; | |
/** | |
* Visit import node. | |
*/ | |
Compiler.prototype.import = function(node){ | |
return '@import ' + node.import + ';'; | |
}; | |
/** | |
* Visit media node. | |
*/ | |
Compiler.prototype.media = function(node){ | |
if (this.compress) { | |
return '@media ' | |
+ node.media | |
+ '{' | |
+ node.rules.map(this.visit, this).join('') | |
+ '}'; | |
} | |
return '@media ' | |
+ node.media | |
+ ' {\n' | |
+ this.indent(1) | |
+ node.rules.map(this.visit, this).join('\n\n') | |
+ this.indent(-1) | |
+ '\n}'; | |
}; | |
/** | |
* Visit charset node. | |
*/ | |
Compiler.prototype.charset = function(node){ | |
if (this.compress) { | |
return '@charset ' + node.charset + ';'; | |
} | |
return '@charset ' + node.charset + ';\n'; | |
}; | |
/** | |
* Visit keyframes node. | |
*/ | |
Compiler.prototype.keyframes = function(node){ | |
if (this.compress) { | |
return '@' | |
+ (node.vendor || '') | |
+ 'keyframes ' | |
+ node.name | |
+ '{' | |
+ node.keyframes.map(this.keyframe, this).join('') | |
+ '}'; | |
} | |
return '@' | |
+ (node.vendor || '') | |
+ 'keyframes ' | |
+ node.name | |
+ ' {\n' | |
+ this.indent(1) | |
+ node.keyframes.map(this.keyframe, this).join('\n') | |
+ this.indent(-1) | |
+ '}'; | |
}; | |
/** | |
* Visit keyframe node. | |
*/ | |
Compiler.prototype.keyframe = function(node){ | |
if (this.compress) { | |
return node.values.join(',') | |
+ '{' | |
+ node.declarations.map(this.declaration, this).join(';') | |
+ '}'; | |
} | |
return this.indent() | |
+ node.values.join(', ') | |
+ ' {\n' | |
+ this.indent(1) | |
+ node.declarations.map(this.declaration, this).join(';\n') | |
+ this.indent(-1) | |
+ '\n' + this.indent() + '}\n'; | |
}; | |
/** | |
* Visit rule node. | |
*/ | |
Compiler.prototype.rule = function(node){ | |
var indent = this.indent(); | |
if (this.compress) { | |
return node.selectors.join(',') | |
+ '{' | |
+ node.declarations.map(this.declaration, this).join(';') | |
+ '}'; | |
} | |
return node.selectors.map(function(s){ return indent + s }).join(',\n') | |
+ ' {\n' | |
+ this.indent(1) | |
+ node.declarations.map(this.declaration, this).join(';\n') | |
+ this.indent(-1) | |
+ '\n' + this.indent() + '}'; | |
}; | |
/** | |
* Visit declaration node. | |
*/ | |
Compiler.prototype.declaration = function(node){ | |
if (this.compress) { | |
return node.property + ':' + node.value; | |
} | |
return this.indent() + node.property + ': ' + node.value; | |
}; | |
/** | |
* Increase, decrease or return current indentation. | |
*/ | |
Compiler.prototype.indent = function(level) { | |
this.level = this.level || 1; | |
if (null != level) { | |
this.level += level; | |
return ''; | |
} | |
return Array(this.level).join(this.indentation || ' '); | |
}; | |
},{}],37:[function(require,module,exports){ | |
(function(process){var isPromise = require('is-promise') | |
var nextTick | |
if (typeof setImediate === 'function') nextTick = setImediate | |
else if (typeof process === 'object' && process && process.nextTick) nextTick = process.nextTick | |
else nextTick = function (cb) { setTimeout(cb, 0) } | |
var extensions = [] | |
module.exports = Promise | |
function Promise(fn) { | |
if (!(this instanceof Promise)) { | |
return fn ? new Promise(fn) : defer() | |
} | |
if (typeof fn !== 'function') { | |
throw new TypeError('fn is not a function') | |
} | |
var state = { | |
isResolved: false, | |
isSettled: false, | |
isFulfilled: false, | |
value: null, | |
waiting: [], | |
running: false | |
} | |
function _resolve(val) { | |
resolve(state, val); | |
} | |
function _reject(err) { | |
reject(state, err); | |
} | |
this.then = function _then(onFulfilled, onRejected) { | |
return then(state, onFulfilled, onRejected); | |
} | |
_resolve.fulfill = deprecate(_resolve, 'resolver.fulfill(x)', 'resolve(x)') | |
_resolve.reject = deprecate(_reject, 'resolver.reject', 'reject(x)') | |
try { | |
fn(_resolve, _reject) | |
} catch (ex) { | |
_reject(ex) | |
} | |
} | |
function resolve(promiseState, value) { | |
if (promiseState.isResolved) return | |
if (isPromise(value)) { | |
assimilate(promiseState, value) | |
} else { | |
settle(promiseState, true, value) | |
} | |
} | |
function reject(promiseState, reason) { | |
if (promiseState.isResolved) return | |
settle(promiseState, false, reason) | |
} | |
function then(promiseState, onFulfilled, onRejected) { | |
return new Promise(function (resolve, reject) { | |
function done(next, skipTimeout) { | |
var callback = promiseState.isFulfilled ? onFulfilled : onRejected | |
if (typeof callback === 'function') { | |
function timeoutDone() { | |
var val | |
try { | |
val = callback(promiseState.value) | |
} catch (ex) { | |
reject(ex) | |
return next(true) | |
} | |
resolve(val) | |
next(true) | |
} | |
if (skipTimeout) timeoutDone() | |
else nextTick(timeoutDone) | |
} else if (promiseState.isFulfilled) { | |
resolve(promiseState.value) | |
next(skipTimeout) | |
} else { | |
reject(promiseState.value) | |
next(skipTimeout) | |
} | |
} | |
promiseState.waiting.push(done) | |
if (promiseState.isSettled && !promiseState.running) processQueue(promiseState) | |
}) | |
} | |
function processQueue(promiseState) { | |
function next(skipTimeout) { | |
if (promiseState.waiting.length) { | |
promiseState.running = true | |
promiseState.waiting.shift()(next, skipTimeout) | |
} else { | |
promiseState.running = false | |
} | |
} | |
next(false) | |
} | |
function settle(promiseState, isFulfilled, value) { | |
if (promiseState.isSettled) return | |
promiseState.isResolved = promiseState.isSettled = true | |
promiseState.value = value | |
promiseState.isFulfilled = isFulfilled | |
processQueue(promiseState) | |
} | |
function assimilate(promiseState, thenable) { | |
try { | |
promiseState.isResolved = true | |
thenable.then(function (res) { | |
if (isPromise(res)) { | |
assimilate(promiseState, res) | |
} else { | |
settle(promiseState, true, res) | |
} | |
}, function (err) { | |
settle(promiseState, false, err) | |
}) | |
} catch (ex) { | |
settle(promiseState, false, ex) | |
} | |
} | |
Promise.use = function (extension) { | |
extensions.push(extension) | |
} | |
function deprecate(method, name, alternative) { | |
return function () { | |
var err = new Error(name + ' is deprecated use ' + alternative) | |
if (typeof console !== 'undefined' && console && typeof console.warn === 'function') { | |
console.warn(name + ' is deprecated use ' + alternative) | |
if (err.stack) console.warn(err.stack) | |
} else { | |
nextTick(function () { | |
throw err | |
}) | |
} | |
method.apply(this, arguments) | |
} | |
} | |
function defer() { | |
var err = new Error('promise.defer() is deprecated') | |
if (typeof console !== 'undefined' && console && typeof console.warn === 'function') { | |
console.warn('promise.defer() is deprecated') | |
if (err.stack) console.warn(err.stack) | |
} else { | |
nextTick(function () { | |
throw err | |
}) | |
} | |
var resolver | |
var promise = new Promise(function (res) { resolver = res }) | |
return {resolver: resolver, promise: promise} | |
} | |
})(require("__browserify_process")) | |
},{"is-promise":41,"__browserify_process":12}],41:[function(require,module,exports){ | |
module.exports = isPromise; | |
function isPromise(obj) { | |
return obj && typeof obj.then === 'function'; | |
} | |
},{}],40:[function(require,module,exports){ | |
/* | |
* Copyright 2009-2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE.txt or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; | |
exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; | |
exports.SourceNode = require('./source-map/source-node').SourceNode; | |
},{"./source-map/source-map-generator":42,"./source-map/source-map-consumer":43,"./source-map/source-node":44}],42:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
var base64VLQ = require('./base64-vlq'); | |
var util = require('./util'); | |
var ArraySet = require('./array-set').ArraySet; | |
/** | |
* An instance of the SourceMapGenerator represents a source map which is | |
* being built incrementally. To create a new one, you must pass an object | |
* with the following properties: | |
* | |
* - file: The filename of the generated source. | |
* - sourceRoot: An optional root for all URLs in this source map. | |
*/ | |
function SourceMapGenerator(aArgs) { | |
this._file = util.getArg(aArgs, 'file'); | |
this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); | |
this._sources = new ArraySet(); | |
this._names = new ArraySet(); | |
this._mappings = []; | |
this._sourcesContents = null; | |
} | |
SourceMapGenerator.prototype._version = 3; | |
/** | |
* Creates a new SourceMapGenerator based on a SourceMapConsumer | |
* | |
* @param aSourceMapConsumer The SourceMap. | |
*/ | |
SourceMapGenerator.fromSourceMap = | |
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { | |
var sourceRoot = aSourceMapConsumer.sourceRoot; | |
var generator = new SourceMapGenerator({ | |
file: aSourceMapConsumer.file, | |
sourceRoot: sourceRoot | |
}); | |
aSourceMapConsumer.eachMapping(function (mapping) { | |
var newMapping = { | |
generated: { | |
line: mapping.generatedLine, | |
column: mapping.generatedColumn | |
} | |
}; | |
if (mapping.source) { | |
newMapping.source = mapping.source; | |
if (sourceRoot) { | |
newMapping.source = util.relative(sourceRoot, newMapping.source); | |
} | |
newMapping.original = { | |
line: mapping.originalLine, | |
column: mapping.originalColumn | |
}; | |
if (mapping.name) { | |
newMapping.name = mapping.name; | |
} | |
} | |
generator.addMapping(newMapping); | |
}); | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content) { | |
generator.setSourceContent(sourceFile, content); | |
} | |
}); | |
return generator; | |
}; | |
/** | |
* Add a single mapping from original source line and column to the generated | |
* source's line and column for this source map being created. The mapping | |
* object should have the following properties: | |
* | |
* - generated: An object with the generated line and column positions. | |
* - original: An object with the original line and column positions. | |
* - source: The original source file (relative to the sourceRoot). | |
* - name: An optional original token name for this mapping. | |
*/ | |
SourceMapGenerator.prototype.addMapping = | |
function SourceMapGenerator_addMapping(aArgs) { | |
var generated = util.getArg(aArgs, 'generated'); | |
var original = util.getArg(aArgs, 'original', null); | |
var source = util.getArg(aArgs, 'source', null); | |
var name = util.getArg(aArgs, 'name', null); | |
this._validateMapping(generated, original, source, name); | |
if (source && !this._sources.has(source)) { | |
this._sources.add(source); | |
} | |
if (name && !this._names.has(name)) { | |
this._names.add(name); | |
} | |
this._mappings.push({ | |
generated: generated, | |
original: original, | |
source: source, | |
name: name | |
}); | |
}; | |
/** | |
* Set the source content for a source file. | |
*/ | |
SourceMapGenerator.prototype.setSourceContent = | |
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { | |
var source = aSourceFile; | |
if (this._sourceRoot) { | |
source = util.relative(this._sourceRoot, source); | |
} | |
if (aSourceContent !== null) { | |
// Add the source content to the _sourcesContents map. | |
// Create a new _sourcesContents map if the property is null. | |
if (!this._sourcesContents) { | |
this._sourcesContents = {}; | |
} | |
this._sourcesContents[util.toSetString(source)] = aSourceContent; | |
} else { | |
// Remove the source file from the _sourcesContents map. | |
// If the _sourcesContents map is empty, set the property to null. | |
delete this._sourcesContents[util.toSetString(source)]; | |
if (Object.keys(this._sourcesContents).length === 0) { | |
this._sourcesContents = null; | |
} | |
} | |
}; | |
/** | |
* Applies the mappings of a sub-source-map for a specific source file to the | |
* source map being generated. Each mapping to the supplied source file is | |
* rewritten using the supplied source map. Note: The resolution for the | |
* resulting mappings is the minimium of this map and the supplied map. | |
* | |
* @param aSourceMapConsumer The source map to be applied. | |
* @param aSourceFile Optional. The filename of the source file. | |
* If omitted, SourceMapConsumer's file property will be used. | |
*/ | |
SourceMapGenerator.prototype.applySourceMap = | |
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { | |
// If aSourceFile is omitted, we will use the file property of the SourceMap | |
if (!aSourceFile) { | |
aSourceFile = aSourceMapConsumer.file; | |
} | |
var sourceRoot = this._sourceRoot; | |
// Make "aSourceFile" relative if an absolute Url is passed. | |
if (sourceRoot) { | |
aSourceFile = util.relative(sourceRoot, aSourceFile); | |
} | |
// Applying the SourceMap can add and remove items from the sources and | |
// the names array. | |
var newSources = new ArraySet(); | |
var newNames = new ArraySet(); | |
// Find mappings for the "aSourceFile" | |
this._mappings.forEach(function (mapping) { | |
if (mapping.source === aSourceFile && mapping.original) { | |
// Check if it can be mapped by the source map, then update the mapping. | |
var original = aSourceMapConsumer.originalPositionFor({ | |
line: mapping.original.line, | |
column: mapping.original.column | |
}); | |
if (original.source !== null) { | |
// Copy mapping | |
if (sourceRoot) { | |
mapping.source = util.relative(sourceRoot, original.source); | |
} else { | |
mapping.source = original.source; | |
} | |
mapping.original.line = original.line; | |
mapping.original.column = original.column; | |
if (original.name !== null && mapping.name !== null) { | |
// Only use the identifier name if it's an identifier | |
// in both SourceMaps | |
mapping.name = original.name; | |
} | |
} | |
} | |
var source = mapping.source; | |
if (source && !newSources.has(source)) { | |
newSources.add(source); | |
} | |
var name = mapping.name; | |
if (name && !newNames.has(name)) { | |
newNames.add(name); | |
} | |
}, this); | |
this._sources = newSources; | |
this._names = newNames; | |
// Copy sourcesContents of applied map. | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content) { | |
if (sourceRoot) { | |
sourceFile = util.relative(sourceRoot, sourceFile); | |
} | |
this.setSourceContent(sourceFile, content); | |
} | |
}, this); | |
}; | |
/** | |
* A mapping can have one of the three levels of data: | |
* | |
* 1. Just the generated position. | |
* 2. The Generated position, original position, and original source. | |
* 3. Generated and original position, original source, as well as a name | |
* token. | |
* | |
* To maintain consistency, we validate that any new mapping being added falls | |
* in to one of these categories. | |
*/ | |
SourceMapGenerator.prototype._validateMapping = | |
function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, | |
aName) { | |
if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | |
&& aGenerated.line > 0 && aGenerated.column >= 0 | |
&& !aOriginal && !aSource && !aName) { | |
// Case 1. | |
return; | |
} | |
else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | |
&& aOriginal && 'line' in aOriginal && 'column' in aOriginal | |
&& aGenerated.line > 0 && aGenerated.column >= 0 | |
&& aOriginal.line > 0 && aOriginal.column >= 0 | |
&& aSource) { | |
// Cases 2 and 3. | |
return; | |
} | |
else { | |
throw new Error('Invalid mapping.'); | |
} | |
}; | |
function cmpLocation(loc1, loc2) { | |
var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); | |
return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); | |
} | |
function strcmp(str1, str2) { | |
str1 = str1 || ''; | |
str2 = str2 || ''; | |
return (str1 > str2) - (str1 < str2); | |
} | |
function cmpMapping(mappingA, mappingB) { | |
return cmpLocation(mappingA.generated, mappingB.generated) || | |
cmpLocation(mappingA.original, mappingB.original) || | |
strcmp(mappingA.source, mappingB.source) || | |
strcmp(mappingA.name, mappingB.name); | |
} | |
/** | |
* Serialize the accumulated mappings in to the stream of base 64 VLQs | |
* specified by the source map format. | |
*/ | |
SourceMapGenerator.prototype._serializeMappings = | |
function SourceMapGenerator_serializeMappings() { | |
var previousGeneratedColumn = 0; | |
var previousGeneratedLine = 1; | |
var previousOriginalColumn = 0; | |
var previousOriginalLine = 0; | |
var previousName = 0; | |
var previousSource = 0; | |
var result = ''; | |
var mapping; | |
// The mappings must be guarenteed to be in sorted order before we start | |
// serializing them or else the generated line numbers (which are defined | |
// via the ';' separators) will be all messed up. Note: it might be more | |
// performant to maintain the sorting as we insert them, rather than as we | |
// serialize them, but the big O is the same either way. | |
this._mappings.sort(cmpMapping); | |
for (var i = 0, len = this._mappings.length; i < len; i++) { | |
mapping = this._mappings[i]; | |
if (mapping.generated.line !== previousGeneratedLine) { | |
previousGeneratedColumn = 0; | |
while (mapping.generated.line !== previousGeneratedLine) { | |
result += ';'; | |
previousGeneratedLine++; | |
} | |
} | |
else { | |
if (i > 0) { | |
if (!cmpMapping(mapping, this._mappings[i - 1])) { | |
continue; | |
} | |
result += ','; | |
} | |
} | |
result += base64VLQ.encode(mapping.generated.column | |
- previousGeneratedColumn); | |
previousGeneratedColumn = mapping.generated.column; | |
if (mapping.source && mapping.original) { | |
result += base64VLQ.encode(this._sources.indexOf(mapping.source) | |
- previousSource); | |
previousSource = this._sources.indexOf(mapping.source); | |
// lines are stored 0-based in SourceMap spec version 3 | |
result += base64VLQ.encode(mapping.original.line - 1 | |
- previousOriginalLine); | |
previousOriginalLine = mapping.original.line - 1; | |
result += base64VLQ.encode(mapping.original.column | |
- previousOriginalColumn); | |
previousOriginalColumn = mapping.original.column; | |
if (mapping.name) { | |
result += base64VLQ.encode(this._names.indexOf(mapping.name) | |
- previousName); | |
previousName = this._names.indexOf(mapping.name); | |
} | |
} | |
} | |
return result; | |
}; | |
/** | |
* Externalize the source map. | |
*/ | |
SourceMapGenerator.prototype.toJSON = | |
function SourceMapGenerator_toJSON() { | |
var map = { | |
version: this._version, | |
file: this._file, | |
sources: this._sources.toArray(), | |
names: this._names.toArray(), | |
mappings: this._serializeMappings() | |
}; | |
if (this._sourceRoot) { | |
map.sourceRoot = this._sourceRoot; | |
} | |
if (this._sourcesContents) { | |
map.sourcesContent = map.sources.map(function (source) { | |
if (map.sourceRoot) { | |
source = util.relative(map.sourceRoot, source); | |
} | |
return Object.prototype.hasOwnProperty.call( | |
this._sourcesContents, util.toSetString(source)) | |
? this._sourcesContents[util.toSetString(source)] | |
: null; | |
}, this); | |
} | |
return map; | |
}; | |
/** | |
* Render the source map being generated to a string. | |
*/ | |
SourceMapGenerator.prototype.toString = | |
function SourceMapGenerator_toString() { | |
return JSON.stringify(this); | |
}; | |
exports.SourceMapGenerator = SourceMapGenerator; | |
}); | |
},{"./base64-vlq":45,"./util":46,"./array-set":47,"amdefine":48}],43:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
var util = require('./util'); | |
var binarySearch = require('./binary-search'); | |
var ArraySet = require('./array-set').ArraySet; | |
var base64VLQ = require('./base64-vlq'); | |
/** | |
* A SourceMapConsumer instance represents a parsed source map which we can | |
* query for information about the original file positions by giving it a file | |
* position in the generated source. | |
* | |
* The only parameter is the raw source map (either as a JSON string, or | |
* already parsed to an object). According to the spec, source maps have the | |
* following attributes: | |
* | |
* - version: Which version of the source map spec this map is following. | |
* - sources: An array of URLs to the original source files. | |
* - names: An array of identifiers which can be referrenced by individual mappings. | |
* - sourceRoot: Optional. The URL root from which all sources are relative. | |
* - sourcesContent: Optional. An array of contents of the original source files. | |
* - mappings: A string of base64 VLQs which contain the actual mappings. | |
* - file: The generated file this source map is associated with. | |
* | |
* Here is an example source map, taken from the source map spec[0]: | |
* | |
* { | |
* version : 3, | |
* file: "out.js", | |
* sourceRoot : "", | |
* sources: ["foo.js", "bar.js"], | |
* names: ["src", "maps", "are", "fun"], | |
* mappings: "AA,AB;;ABCDE;" | |
* } | |
* | |
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# | |
*/ | |
function SourceMapConsumer(aSourceMap) { | |
var sourceMap = aSourceMap; | |
if (typeof aSourceMap === 'string') { | |
sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); | |
} | |
var version = util.getArg(sourceMap, 'version'); | |
var sources = util.getArg(sourceMap, 'sources'); | |
var names = util.getArg(sourceMap, 'names'); | |
var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); | |
var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); | |
var mappings = util.getArg(sourceMap, 'mappings'); | |
var file = util.getArg(sourceMap, 'file'); | |
if (version !== this._version) { | |
throw new Error('Unsupported version: ' + version); | |
} | |
this._names = ArraySet.fromArray(names); | |
this._sources = ArraySet.fromArray(sources); | |
this.sourceRoot = sourceRoot; | |
this.sourcesContent = sourcesContent; | |
this.file = file; | |
// `this._generatedMappings` and `this._originalMappings` hold the parsed | |
// mapping coordinates from the source map's "mappings" attribute. Each | |
// object in the array is of the form | |
// | |
// { | |
// generatedLine: The line number in the generated code, | |
// generatedColumn: The column number in the generated code, | |
// source: The path to the original source file that generated this | |
// chunk of code, | |
// originalLine: The line number in the original source that | |
// corresponds to this chunk of generated code, | |
// originalColumn: The column number in the original source that | |
// corresponds to this chunk of generated code, | |
// name: The name of the original symbol which generated this chunk of | |
// code. | |
// } | |
// | |
// All properties except for `generatedLine` and `generatedColumn` can be | |
// `null`. | |
// | |
// `this._generatedMappings` is ordered by the generated positions. | |
// | |
// `this._originalMappings` is ordered by the original positions. | |
this._generatedMappings = []; | |
this._originalMappings = []; | |
this._parseMappings(mappings, sourceRoot); | |
} | |
/** | |
* The version of the source mapping spec that we are consuming. | |
*/ | |
SourceMapConsumer.prototype._version = 3; | |
/** | |
* The list of original sources. | |
*/ | |
Object.defineProperty(SourceMapConsumer.prototype, 'sources', { | |
get: function () { | |
return this._sources.toArray().map(function (s) { | |
return this.sourceRoot ? util.join(this.sourceRoot, s) : s; | |
}, this); | |
} | |
}); | |
/** | |
* Parse the mappings in a string in to a data structure which we can easily | |
* query (an ordered list in this._generatedMappings). | |
*/ | |
SourceMapConsumer.prototype._parseMappings = | |
function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { | |
var generatedLine = 1; | |
var previousGeneratedColumn = 0; | |
var previousOriginalLine = 0; | |
var previousOriginalColumn = 0; | |
var previousSource = 0; | |
var previousName = 0; | |
var mappingSeparator = /^[,;]/; | |
var str = aStr; | |
var mapping; | |
var temp; | |
while (str.length > 0) { | |
if (str.charAt(0) === ';') { | |
generatedLine++; | |
str = str.slice(1); | |
previousGeneratedColumn = 0; | |
} | |
else if (str.charAt(0) === ',') { | |
str = str.slice(1); | |
} | |
else { | |
mapping = {}; | |
mapping.generatedLine = generatedLine; | |
// Generated column. | |
temp = base64VLQ.decode(str); | |
mapping.generatedColumn = previousGeneratedColumn + temp.value; | |
previousGeneratedColumn = mapping.generatedColumn; | |
str = temp.rest; | |
if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { | |
// Original source. | |
temp = base64VLQ.decode(str); | |
mapping.source = this._sources.at(previousSource + temp.value); | |
previousSource += temp.value; | |
str = temp.rest; | |
if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { | |
throw new Error('Found a source, but no line and column'); | |
} | |
// Original line. | |
temp = base64VLQ.decode(str); | |
mapping.originalLine = previousOriginalLine + temp.value; | |
previousOriginalLine = mapping.originalLine; | |
// Lines are stored 0-based | |
mapping.originalLine += 1; | |
str = temp.rest; | |
if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { | |
throw new Error('Found a source and line, but no column'); | |
} | |
// Original column. | |
temp = base64VLQ.decode(str); | |
mapping.originalColumn = previousOriginalColumn + temp.value; | |
previousOriginalColumn = mapping.originalColumn; | |
str = temp.rest; | |
if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { | |
// Original name. | |
temp = base64VLQ.decode(str); | |
mapping.name = this._names.at(previousName + temp.value); | |
previousName += temp.value; | |
str = temp.rest; | |
} | |
} | |
this._generatedMappings.push(mapping); | |
if (typeof mapping.originalLine === 'number') { | |
this._originalMappings.push(mapping); | |
} | |
} | |
} | |
this._originalMappings.sort(this._compareOriginalPositions); | |
}; | |
/** | |
* Comparator between two mappings where the original positions are compared. | |
*/ | |
SourceMapConsumer.prototype._compareOriginalPositions = | |
function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { | |
if (mappingA.source > mappingB.source) { | |
return 1; | |
} | |
else if (mappingA.source < mappingB.source) { | |
return -1; | |
} | |
else { | |
var cmp = mappingA.originalLine - mappingB.originalLine; | |
return cmp === 0 | |
? mappingA.originalColumn - mappingB.originalColumn | |
: cmp; | |
} | |
}; | |
/** | |
* Comparator between two mappings where the generated positions are compared. | |
*/ | |
SourceMapConsumer.prototype._compareGeneratedPositions = | |
function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { | |
var cmp = mappingA.generatedLine - mappingB.generatedLine; | |
return cmp === 0 | |
? mappingA.generatedColumn - mappingB.generatedColumn | |
: cmp; | |
}; | |
/** | |
* Find the mapping that best matches the hypothetical "needle" mapping that | |
* we are searching for in the given "haystack" of mappings. | |
*/ | |
SourceMapConsumer.prototype._findMapping = | |
function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, | |
aColumnName, aComparator) { | |
// To return the position we are searching for, we must first find the | |
// mapping for the given position and then return the opposite position it | |
// points to. Because the mappings are sorted, we can use binary search to | |
// find the best mapping. | |
if (aNeedle[aLineName] <= 0) { | |
throw new TypeError('Line must be greater than or equal to 1, got ' | |
+ aNeedle[aLineName]); | |
} | |
if (aNeedle[aColumnName] < 0) { | |
throw new TypeError('Column must be greater than or equal to 0, got ' | |
+ aNeedle[aColumnName]); | |
} | |
return binarySearch.search(aNeedle, aMappings, aComparator); | |
}; | |
/** | |
* Returns the original source, line, and column information for the generated | |
* source's line and column positions provided. The only argument is an object | |
* with the following properties: | |
* | |
* - line: The line number in the generated source. | |
* - column: The column number in the generated source. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - source: The original source file, or null. | |
* - line: The line number in the original source, or null. | |
* - column: The column number in the original source, or null. | |
* - name: The original identifier, or null. | |
*/ | |
SourceMapConsumer.prototype.originalPositionFor = | |
function SourceMapConsumer_originalPositionFor(aArgs) { | |
var needle = { | |
generatedLine: util.getArg(aArgs, 'line'), | |
generatedColumn: util.getArg(aArgs, 'column') | |
}; | |
var mapping = this._findMapping(needle, | |
this._generatedMappings, | |
"generatedLine", | |
"generatedColumn", | |
this._compareGeneratedPositions); | |
if (mapping) { | |
var source = util.getArg(mapping, 'source', null); | |
if (source && this.sourceRoot) { | |
source = util.join(this.sourceRoot, source); | |
} | |
return { | |
source: source, | |
line: util.getArg(mapping, 'originalLine', null), | |
column: util.getArg(mapping, 'originalColumn', null), | |
name: util.getArg(mapping, 'name', null) | |
}; | |
} | |
return { | |
source: null, | |
line: null, | |
column: null, | |
name: null | |
}; | |
}; | |
/** | |
* Returns the original source content. The only argument is | |
* the url of the original source file. Returns null if no | |
* original source content is availible. | |
*/ | |
SourceMapConsumer.prototype.sourceContentFor = | |
function SourceMapConsumer_sourceContentFor(aSource) { | |
if (!this.sourcesContent) { | |
return null; | |
} | |
if (this.sourceRoot) { | |
// Try to remove the sourceRoot | |
var relativeUrl = util.relative(this.sourceRoot, aSource); | |
if (this._sources.has(relativeUrl)) { | |
return this.sourcesContent[this._sources.indexOf(relativeUrl)]; | |
} | |
} | |
if (this._sources.has(aSource)) { | |
return this.sourcesContent[this._sources.indexOf(aSource)]; | |
} | |
throw new Error('"' + aSource + '" is not in the SourceMap.'); | |
}; | |
/** | |
* Returns the generated line and column information for the original source, | |
* line, and column positions provided. The only argument is an object with | |
* the following properties: | |
* | |
* - source: The filename of the original source. | |
* - line: The line number in the original source. | |
* - column: The column number in the original source. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - line: The line number in the generated source, or null. | |
* - column: The column number in the generated source, or null. | |
*/ | |
SourceMapConsumer.prototype.generatedPositionFor = | |
function SourceMapConsumer_generatedPositionFor(aArgs) { | |
var needle = { | |
source: util.getArg(aArgs, 'source'), | |
originalLine: util.getArg(aArgs, 'line'), | |
originalColumn: util.getArg(aArgs, 'column') | |
}; | |
if (this.sourceRoot) { | |
needle.source = util.relative(this.sourceRoot, needle.source); | |
} | |
var mapping = this._findMapping(needle, | |
this._originalMappings, | |
"originalLine", | |
"originalColumn", | |
this._compareOriginalPositions); | |
if (mapping) { | |
return { | |
line: util.getArg(mapping, 'generatedLine', null), | |
column: util.getArg(mapping, 'generatedColumn', null) | |
}; | |
} | |
return { | |
line: null, | |
column: null | |
}; | |
}; | |
SourceMapConsumer.GENERATED_ORDER = 1; | |
SourceMapConsumer.ORIGINAL_ORDER = 2; | |
/** | |
* Iterate over each mapping between an original source/line/column and a | |
* generated line/column in this source map. | |
* | |
* @param Function aCallback | |
* The function that is called with each mapping. | |
* @param Object aContext | |
* Optional. If specified, this object will be the value of `this` every | |
* time that `aCallback` is called. | |
* @param aOrder | |
* Either `SourceMapConsumer.GENERATED_ORDER` or | |
* `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to | |
* iterate over the mappings sorted by the generated file's line/column | |
* order or the original's source/line/column order, respectively. Defaults to | |
* `SourceMapConsumer.GENERATED_ORDER`. | |
*/ | |
SourceMapConsumer.prototype.eachMapping = | |
function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { | |
var context = aContext || null; | |
var order = aOrder || SourceMapConsumer.GENERATED_ORDER; | |
var mappings; | |
switch (order) { | |
case SourceMapConsumer.GENERATED_ORDER: | |
mappings = this._generatedMappings; | |
break; | |
case SourceMapConsumer.ORIGINAL_ORDER: | |
mappings = this._originalMappings; | |
break; | |
default: | |
throw new Error("Unknown order of iteration."); | |
} | |
var sourceRoot = this.sourceRoot; | |
mappings.map(function (mapping) { | |
var source = mapping.source; | |
if (source && sourceRoot) { | |
source = util.join(sourceRoot, source); | |
} | |
return { | |
source: source, | |
generatedLine: mapping.generatedLine, | |
generatedColumn: mapping.generatedColumn, | |
originalLine: mapping.originalLine, | |
originalColumn: mapping.originalColumn, | |
name: mapping.name | |
}; | |
}).forEach(aCallback, context); | |
}; | |
exports.SourceMapConsumer = SourceMapConsumer; | |
}); | |
},{"./util":46,"./binary-search":49,"./array-set":47,"./base64-vlq":45,"amdefine":48}],44:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; | |
var util = require('./util'); | |
/** | |
* SourceNodes provide a way to abstract over interpolating/concatenating | |
* snippets of generated JavaScript source code while maintaining the line and | |
* column information associated with the original source code. | |
* | |
* @param aLine The original line number. | |
* @param aColumn The original column number. | |
* @param aSource The original source's filename. | |
* @param aChunks Optional. An array of strings which are snippets of | |
* generated JS, or other SourceNodes. | |
* @param aName The original identifier. | |
*/ | |
function SourceNode(aLine, aColumn, aSource, aChunks, aName) { | |
this.children = []; | |
this.sourceContents = {}; | |
this.line = aLine === undefined ? null : aLine; | |
this.column = aColumn === undefined ? null : aColumn; | |
this.source = aSource === undefined ? null : aSource; | |
this.name = aName === undefined ? null : aName; | |
if (aChunks != null) this.add(aChunks); | |
} | |
/** | |
* Creates a SourceNode from generated code and a SourceMapConsumer. | |
* | |
* @param aGeneratedCode The generated code | |
* @param aSourceMapConsumer The SourceMap for the generated code | |
*/ | |
SourceNode.fromStringWithSourceMap = | |
function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { | |
// The SourceNode we want to fill with the generated code | |
// and the SourceMap | |
var node = new SourceNode(); | |
// The generated code | |
// Processed fragments are removed from this array. | |
var remainingLines = aGeneratedCode.split('\n'); | |
// We need to remember the position of "remainingLines" | |
var lastGeneratedLine = 1, lastGeneratedColumn = 0; | |
// The generate SourceNodes we need a code range. | |
// To extract it current and last mapping is used. | |
// Here we store the last mapping. | |
var lastMapping = null; | |
aSourceMapConsumer.eachMapping(function (mapping) { | |
if (lastMapping === null) { | |
// We add the generated code until the first mapping | |
// to the SourceNode without any mapping. | |
// Each line is added as separate string. | |
while (lastGeneratedLine < mapping.generatedLine) { | |
node.add(remainingLines.shift() + "\n"); | |
lastGeneratedLine++; | |
} | |
if (lastGeneratedColumn < mapping.generatedColumn) { | |
var nextLine = remainingLines[0]; | |
node.add(nextLine.substr(0, mapping.generatedColumn)); | |
remainingLines[0] = nextLine.substr(mapping.generatedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
} | |
} else { | |
// We add the code from "lastMapping" to "mapping": | |
// First check if there is a new line in between. | |
if (lastGeneratedLine < mapping.generatedLine) { | |
var code = ""; | |
// Associate full lines with "lastMapping" | |
do { | |
code += remainingLines.shift() + "\n"; | |
lastGeneratedLine++; | |
lastGeneratedColumn = 0; | |
} while (lastGeneratedLine < mapping.generatedLine); | |
// When we reached the correct line, we add code until we | |
// reach the correct column too. | |
if (lastGeneratedColumn < mapping.generatedColumn) { | |
var nextLine = remainingLines[0]; | |
code += nextLine.substr(0, mapping.generatedColumn); | |
remainingLines[0] = nextLine.substr(mapping.generatedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
} | |
// Create the SourceNode. | |
addMappingWithCode(lastMapping, code); | |
} else { | |
// There is no new line in between. | |
// Associate the code between "lastGeneratedColumn" and | |
// "mapping.generatedColumn" with "lastMapping" | |
var nextLine = remainingLines[0]; | |
var code = nextLine.substr(0, mapping.generatedColumn - | |
lastGeneratedColumn); | |
remainingLines[0] = nextLine.substr(mapping.generatedColumn - | |
lastGeneratedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
addMappingWithCode(lastMapping, code); | |
} | |
} | |
lastMapping = mapping; | |
}, this); | |
// We have processed all mappings. | |
// Associate the remaining code in the current line with "lastMapping" | |
// and add the remaining lines without any mapping | |
addMappingWithCode(lastMapping, remainingLines.join("\n")); | |
// Copy sourcesContent into SourceNode | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content) { | |
node.setSourceContent(sourceFile, content); | |
} | |
}); | |
return node; | |
function addMappingWithCode(mapping, code) { | |
if (mapping.source === undefined) { | |
node.add(code); | |
} else { | |
node.add(new SourceNode(mapping.originalLine, | |
mapping.originalColumn, | |
mapping.source, | |
code, | |
mapping.name)); | |
} | |
} | |
}; | |
/** | |
* Add a chunk of generated JS to this source node. | |
* | |
* @param aChunk A string snippet of generated JS code, another instance of | |
* SourceNode, or an array where each member is one of those things. | |
*/ | |
SourceNode.prototype.add = function SourceNode_add(aChunk) { | |
if (Array.isArray(aChunk)) { | |
aChunk.forEach(function (chunk) { | |
this.add(chunk); | |
}, this); | |
} | |
else if (aChunk instanceof SourceNode || typeof aChunk === "string") { | |
if (aChunk) { | |
this.children.push(aChunk); | |
} | |
} | |
else { | |
throw new TypeError( | |
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk | |
); | |
} | |
return this; | |
}; | |
/** | |
* Add a chunk of generated JS to the beginning of this source node. | |
* | |
* @param aChunk A string snippet of generated JS code, another instance of | |
* SourceNode, or an array where each member is one of those things. | |
*/ | |
SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { | |
if (Array.isArray(aChunk)) { | |
for (var i = aChunk.length-1; i >= 0; i--) { | |
this.prepend(aChunk[i]); | |
} | |
} | |
else if (aChunk instanceof SourceNode || typeof aChunk === "string") { | |
this.children.unshift(aChunk); | |
} | |
else { | |
throw new TypeError( | |
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk | |
); | |
} | |
return this; | |
}; | |
/** | |
* Walk over the tree of JS snippets in this node and its children. The | |
* walking function is called once for each snippet of JS and is passed that | |
* snippet and the its original associated source's line/column location. | |
* | |
* @param aFn The traversal function. | |
*/ | |
SourceNode.prototype.walk = function SourceNode_walk(aFn) { | |
this.children.forEach(function (chunk) { | |
if (chunk instanceof SourceNode) { | |
chunk.walk(aFn); | |
} | |
else { | |
if (chunk !== '') { | |
aFn(chunk, { source: this.source, | |
line: this.line, | |
column: this.column, | |
name: this.name }); | |
} | |
} | |
}, this); | |
}; | |
/** | |
* Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between | |
* each of `this.children`. | |
* | |
* @param aSep The separator. | |
*/ | |
SourceNode.prototype.join = function SourceNode_join(aSep) { | |
var newChildren; | |
var i; | |
var len = this.children.length; | |
if (len > 0) { | |
newChildren = []; | |
for (i = 0; i < len-1; i++) { | |
newChildren.push(this.children[i]); | |
newChildren.push(aSep); | |
} | |
newChildren.push(this.children[i]); | |
this.children = newChildren; | |
} | |
return this; | |
}; | |
/** | |
* Call String.prototype.replace on the very right-most source snippet. Useful | |
* for trimming whitespace from the end of a source node, etc. | |
* | |
* @param aPattern The pattern to replace. | |
* @param aReplacement The thing to replace the pattern with. | |
*/ | |
SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { | |
var lastChild = this.children[this.children.length - 1]; | |
if (lastChild instanceof SourceNode) { | |
lastChild.replaceRight(aPattern, aReplacement); | |
} | |
else if (typeof lastChild === 'string') { | |
this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); | |
} | |
else { | |
this.children.push(''.replace(aPattern, aReplacement)); | |
} | |
return this; | |
}; | |
/** | |
* Set the source content for a source file. This will be added to the SourceMapGenerator | |
* in the sourcesContent field. | |
* | |
* @param aSourceFile The filename of the source file | |
* @param aSourceContent The content of the source file | |
*/ | |
SourceNode.prototype.setSourceContent = | |
function SourceNode_setSourceContent(aSourceFile, aSourceContent) { | |
this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; | |
}; | |
/** | |
* Walk over the tree of SourceNodes. The walking function is called for each | |
* source file content and is passed the filename and source content. | |
* | |
* @param aFn The traversal function. | |
*/ | |
SourceNode.prototype.walkSourceContents = | |
function SourceNode_walkSourceContents(aFn) { | |
this.children.forEach(function (chunk) { | |
if (chunk instanceof SourceNode) { | |
chunk.walkSourceContents(aFn); | |
} | |
}, this); | |
Object.keys(this.sourceContents).forEach(function (sourceFileKey) { | |
aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]); | |
}, this); | |
}; | |
/** | |
* Return the string representation of this source node. Walks over the tree | |
* and concatenates all the various snippets together to one string. | |
*/ | |
SourceNode.prototype.toString = function SourceNode_toString() { | |
var str = ""; | |
this.walk(function (chunk) { | |
str += chunk; | |
}); | |
return str; | |
}; | |
/** | |
* Returns the string representation of this source node along with a source | |
* map. | |
*/ | |
SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { | |
var generated = { | |
code: "", | |
line: 1, | |
column: 0 | |
}; | |
var map = new SourceMapGenerator(aArgs); | |
var sourceMappingActive = false; | |
this.walk(function (chunk, original) { | |
generated.code += chunk; | |
if (original.source !== null | |
&& original.line !== null | |
&& original.column !== null) { | |
map.addMapping({ | |
source: original.source, | |
original: { | |
line: original.line, | |
column: original.column | |
}, | |
generated: { | |
line: generated.line, | |
column: generated.column | |
}, | |
name: original.name | |
}); | |
sourceMappingActive = true; | |
} else if (sourceMappingActive) { | |
map.addMapping({ | |
generated: { | |
line: generated.line, | |
column: generated.column | |
} | |
}); | |
sourceMappingActive = false; | |
} | |
chunk.split('').forEach(function (ch) { | |
if (ch === '\n') { | |
generated.line++; | |
generated.column = 0; | |
} else { | |
generated.column++; | |
} | |
}); | |
}); | |
this.walkSourceContents(function (sourceFile, sourceContent) { | |
map.setSourceContent(sourceFile, sourceContent); | |
}); | |
return { code: generated.code, map: map }; | |
}; | |
exports.SourceNode = SourceNode; | |
}); | |
},{"./source-map-generator":42,"./util":46,"amdefine":48}],48:[function(require,module,exports){ | |
(function(process){/** vim: et:ts=4:sw=4:sts=4 | |
* @license amdefine 0.0.5 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. | |
* Available via the MIT or new BSD license. | |
* see: http://github.com/jrburke/amdefine for details | |
*/ | |
/*jslint node: true */ | |
/*global module, process */ | |
'use strict'; | |
var path = require('path'); | |
/** | |
* Creates a define for node. | |
* @param {Object} module the "module" object that is defined by Node for the | |
* current module. | |
* @param {Function} [require]. Node's require function for the current module. | |
* It only needs to be passed in Node versions before 0.5, when module.require | |
* did not exist. | |
* @returns {Function} a define function that is usable for the current node | |
* module. | |
*/ | |
function amdefine(module, require) { | |
var defineCache = {}, | |
loaderCache = {}, | |
alreadyCalled = false, | |
makeRequire, stringRequire; | |
/** | |
* Trims the . and .. from an array of path segments. | |
* It will keep a leading path segment if a .. will become | |
* the first path segment, to help with module name lookups, | |
* which act like paths, but can be remapped. But the end result, | |
* all paths that use this function should look normalized. | |
* NOTE: this method MODIFIES the input array. | |
* @param {Array} ary the array of path segments. | |
*/ | |
function trimDots(ary) { | |
var i, part; | |
for (i = 0; ary[i]; i+= 1) { | |
part = ary[i]; | |
if (part === '.') { | |
ary.splice(i, 1); | |
i -= 1; | |
} else if (part === '..') { | |
if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { | |
//End of the line. Keep at least one non-dot | |
//path segment at the front so it can be mapped | |
//correctly to disk. Otherwise, there is likely | |
//no path mapping for a path starting with '..'. | |
//This can still fail, but catches the most reasonable | |
//uses of .. | |
break; | |
} else if (i > 0) { | |
ary.splice(i - 1, 2); | |
i -= 2; | |
} | |
} | |
} | |
} | |
function normalize(name, baseName) { | |
var baseParts; | |
//Adjust any relative paths. | |
if (name && name.charAt(0) === '.') { | |
//If have a base name, try to normalize against it, | |
//otherwise, assume it is a top-level require that will | |
//be relative to baseUrl in the end. | |
if (baseName) { | |
baseParts = baseName.split('/'); | |
baseParts = baseParts.slice(0, baseParts.length - 1); | |
baseParts = baseParts.concat(name.split('/')); | |
trimDots(baseParts); | |
name = baseParts.join('/'); | |
} | |
} | |
return name; | |
} | |
/** | |
* Create the normalize() function passed to a loader plugin's | |
* normalize method. | |
*/ | |
function makeNormalize(relName) { | |
return function (name) { | |
return normalize(name, relName); | |
}; | |
} | |
function makeLoad(id) { | |
function load(value) { | |
loaderCache[id] = value; | |
} | |
load.fromText = function (id, text) { | |
//This one is difficult because the text can/probably uses | |
//define, and any relative paths and requires should be relative | |
//to that id was it would be found on disk. But this would require | |
//bootstrapping a module/require fairly deeply from node core. | |
//Not sure how best to go about that yet. | |
throw new Error('amdefine does not implement load.fromText'); | |
}; | |
return load; | |
} | |
makeRequire = function (systemRequire, exports, module, relId) { | |
function amdRequire(deps, callback) { | |
if (typeof deps === 'string') { | |
//Synchronous, single module require('') | |
return stringRequire(systemRequire, exports, module, deps, relId); | |
} else { | |
//Array of dependencies with a callback. | |
//Convert the dependencies to modules. | |
deps = deps.map(function (depName) { | |
return stringRequire(systemRequire, exports, module, depName, relId); | |
}); | |
//Wait for next tick to call back the require call. | |
process.nextTick(function () { | |
callback.apply(null, deps); | |
}); | |
} | |
} | |
amdRequire.toUrl = function (filePath) { | |
if (filePath.indexOf('.') === 0) { | |
return normalize(filePath, path.dirname(module.filename)); | |
} else { | |
return filePath; | |
} | |
}; | |
return amdRequire; | |
}; | |
//Favor explicit value, passed in if the module wants to support Node 0.4. | |
require = require || function req() { | |
return module.require.apply(module, arguments); | |
}; | |
function runFactory(id, deps, factory) { | |
var r, e, m, result; | |
if (id) { | |
e = loaderCache[id] = {}; | |
m = { | |
id: id, | |
uri: __filename, | |
exports: e | |
}; | |
r = makeRequire(require, e, m, id); | |
} else { | |
//Only support one define call per file | |
if (alreadyCalled) { | |
throw new Error('amdefine with no module ID cannot be called more than once per file.'); | |
} | |
alreadyCalled = true; | |
//Use the real variables from node | |
//Use module.exports for exports, since | |
//the exports in here is amdefine exports. | |
e = module.exports; | |
m = module; | |
r = makeRequire(require, e, m, module.id); | |
} | |
//If there are dependencies, they are strings, so need | |
//to convert them to dependency values. | |
if (deps) { | |
deps = deps.map(function (depName) { | |
return r(depName); | |
}); | |
} | |
//Call the factory with the right dependencies. | |
if (typeof factory === 'function') { | |
result = factory.apply(module.exports, deps); | |
} else { | |
result = factory; | |
} | |
if (result !== undefined) { | |
m.exports = result; | |
if (id) { | |
loaderCache[id] = m.exports; | |
} | |
} | |
} | |
stringRequire = function (systemRequire, exports, module, id, relId) { | |
//Split the ID by a ! so that | |
var index = id.indexOf('!'), | |
originalId = id, | |
prefix, plugin; | |
if (index === -1) { | |
id = normalize(id, relId); | |
//Straight module lookup. If it is one of the special dependencies, | |
//deal with it, otherwise, delegate to node. | |
if (id === 'require') { | |
return makeRequire(systemRequire, exports, module, relId); | |
} else if (id === 'exports') { | |
return exports; | |
} else if (id === 'module') { | |
return module; | |
} else if (loaderCache.hasOwnProperty(id)) { | |
return loaderCache[id]; | |
} else if (defineCache[id]) { | |
runFactory.apply(null, defineCache[id]); | |
return loaderCache[id]; | |
} else { | |
if(systemRequire) { | |
return systemRequire(originalId); | |
} else { | |
throw new Error('No module with ID: ' + id); | |
} | |
} | |
} else { | |
//There is a plugin in play. | |
prefix = id.substring(0, index); | |
id = id.substring(index + 1, id.length); | |
plugin = stringRequire(systemRequire, exports, module, prefix, relId); | |
if (plugin.normalize) { | |
id = plugin.normalize(id, makeNormalize(relId)); | |
} else { | |
//Normalize the ID normally. | |
id = normalize(id, relId); | |
} | |
if (loaderCache[id]) { | |
return loaderCache[id]; | |
} else { | |
plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); | |
return loaderCache[id]; | |
} | |
} | |
}; | |
//Create a define function specific to the module asking for amdefine. | |
function define(id, deps, factory) { | |
if (Array.isArray(id)) { | |
factory = deps; | |
deps = id; | |
id = undefined; | |
} else if (typeof id !== 'string') { | |
factory = id; | |
id = deps = undefined; | |
} | |
if (deps && !Array.isArray(deps)) { | |
factory = deps; | |
deps = undefined; | |
} | |
if (!deps) { | |
deps = ['require', 'exports', 'module']; | |
} | |
//Set up properties for this module. If an ID, then use | |
//internal cache. If no ID, then use the external variables | |
//for this node module. | |
if (id) { | |
//Put the module in deep freeze until there is a | |
//require call for it. | |
defineCache[id] = [id, deps, factory]; | |
} else { | |
runFactory(id, deps, factory); | |
} | |
} | |
//define.require, which has access to all the values in the | |
//cache. Useful for AMD modules that all have IDs in the file, | |
//but need to finally export a value to node based on one of those | |
//IDs. | |
define.require = function (id) { | |
if (loaderCache[id]) { | |
return loaderCache[id]; | |
} | |
if (defineCache[id]) { | |
runFactory.apply(null, defineCache[id]); | |
return loaderCache[id]; | |
} | |
}; | |
define.amd = {}; | |
return define; | |
} | |
module.exports = amdefine; | |
})(require("__browserify_process")) | |
},{"path":13,"__browserify_process":12}],45:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
* | |
* Based on the Base 64 VLQ implementation in Closure Compiler: | |
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java | |
* | |
* Copyright 2011 The Closure Compiler Authors. All rights reserved. | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* * Redistributions in binary form must reproduce the above | |
* copyright notice, this list of conditions and the following | |
* disclaimer in the documentation and/or other materials provided | |
* with the distribution. | |
* * Neither the name of Google Inc. nor the names of its | |
* contributors may be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
var base64 = require('./base64'); | |
// A single base 64 digit can contain 6 bits of data. For the base 64 variable | |
// length quantities we use in the source map spec, the first bit is the sign, | |
// the next four bits are the actual value, and the 6th bit is the | |
// continuation bit. The continuation bit tells us whether there are more | |
// digits in this value following this digit. | |
// | |
// Continuation | |
// | Sign | |
// | | | |
// V V | |
// 101011 | |
var VLQ_BASE_SHIFT = 5; | |
// binary: 100000 | |
var VLQ_BASE = 1 << VLQ_BASE_SHIFT; | |
// binary: 011111 | |
var VLQ_BASE_MASK = VLQ_BASE - 1; | |
// binary: 100000 | |
var VLQ_CONTINUATION_BIT = VLQ_BASE; | |
/** | |
* Converts from a two-complement value to a value where the sign bit is | |
* is placed in the least significant bit. For example, as decimals: | |
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) | |
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) | |
*/ | |
function toVLQSigned(aValue) { | |
return aValue < 0 | |
? ((-aValue) << 1) + 1 | |
: (aValue << 1) + 0; | |
} | |
/** | |
* Converts to a two-complement value from a value where the sign bit is | |
* is placed in the least significant bit. For example, as decimals: | |
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 | |
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 | |
*/ | |
function fromVLQSigned(aValue) { | |
var isNegative = (aValue & 1) === 1; | |
var shifted = aValue >> 1; | |
return isNegative | |
? -shifted | |
: shifted; | |
} | |
/** | |
* Returns the base 64 VLQ encoded value. | |
*/ | |
exports.encode = function base64VLQ_encode(aValue) { | |
var encoded = ""; | |
var digit; | |
var vlq = toVLQSigned(aValue); | |
do { | |
digit = vlq & VLQ_BASE_MASK; | |
vlq >>>= VLQ_BASE_SHIFT; | |
if (vlq > 0) { | |
// There are still more digits in this value, so we must make sure the | |
// continuation bit is marked. | |
digit |= VLQ_CONTINUATION_BIT; | |
} | |
encoded += base64.encode(digit); | |
} while (vlq > 0); | |
return encoded; | |
}; | |
/** | |
* Decodes the next base 64 VLQ value from the given string and returns the | |
* value and the rest of the string. | |
*/ | |
exports.decode = function base64VLQ_decode(aStr) { | |
var i = 0; | |
var strLen = aStr.length; | |
var result = 0; | |
var shift = 0; | |
var continuation, digit; | |
do { | |
if (i >= strLen) { | |
throw new Error("Expected more digits in base 64 VLQ value."); | |
} | |
digit = base64.decode(aStr.charAt(i++)); | |
continuation = !!(digit & VLQ_CONTINUATION_BIT); | |
digit &= VLQ_BASE_MASK; | |
result = result + (digit << shift); | |
shift += VLQ_BASE_SHIFT; | |
} while (continuation); | |
return { | |
value: fromVLQSigned(result), | |
rest: aStr.slice(i) | |
}; | |
}; | |
}); | |
},{"./base64":50,"amdefine":48}],46:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
/** | |
* This is a helper function for getting values from parameter/options | |
* objects. | |
* | |
* @param args The object we are extracting values from | |
* @param name The name of the property we are getting. | |
* @param defaultValue An optional value to return if the property is missing | |
* from the object. If this is not specified and the property is missing, an | |
* error will be thrown. | |
*/ | |
function getArg(aArgs, aName, aDefaultValue) { | |
if (aName in aArgs) { | |
return aArgs[aName]; | |
} else if (arguments.length === 3) { | |
return aDefaultValue; | |
} else { | |
throw new Error('"' + aName + '" is a required argument.'); | |
} | |
} | |
exports.getArg = getArg; | |
var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; | |
function urlParse(aUrl) { | |
var match = aUrl.match(urlRegexp); | |
if (!match) { | |
return null; | |
} | |
return { | |
scheme: match[1], | |
auth: match[3], | |
host: match[4], | |
port: match[6], | |
path: match[7] | |
}; | |
} | |
function join(aRoot, aPath) { | |
var url; | |
if (aPath.match(urlRegexp)) { | |
return aPath; | |
} | |
if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { | |
return aRoot.replace(url.path, '') + aPath; | |
} | |
return aRoot.replace(/\/$/, '') + '/' + aPath; | |
} | |
exports.join = join; | |
/** | |
* Because behavior goes wacky when you set `__proto__` on objects, we | |
* have to prefix all the strings in our set with an arbitrary character. | |
* | |
* See https://github.com/mozilla/source-map/pull/31 and | |
* https://github.com/mozilla/source-map/issues/30 | |
* | |
* @param String aStr | |
*/ | |
function toSetString(aStr) { | |
return '$' + aStr; | |
} | |
exports.toSetString = toSetString; | |
function fromSetString(aStr) { | |
return aStr.substr(1); | |
} | |
exports.fromSetString = fromSetString; | |
function relative(aRoot, aPath) { | |
aRoot = aRoot.replace(/\/$/, ''); | |
return aPath.indexOf(aRoot + '/') === 0 | |
? aPath.substr(aRoot.length + 1) | |
: aPath; | |
} | |
exports.relative = relative; | |
}); | |
},{"amdefine":48}],47:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
var util = require('./util'); | |
/** | |
* A data structure which is a combination of an array and a set. Adding a new | |
* member is O(1), testing for membership is O(1), and finding the index of an | |
* element is O(1). Removing elements from the set is not supported. Only | |
* strings are supported for membership. | |
*/ | |
function ArraySet() { | |
this._array = []; | |
this._set = {}; | |
} | |
/** | |
* Static method for creating ArraySet instances from an existing array. | |
*/ | |
ArraySet.fromArray = function ArraySet_fromArray(aArray) { | |
var set = new ArraySet(); | |
for (var i = 0, len = aArray.length; i < len; i++) { | |
set.add(aArray[i]); | |
} | |
return set; | |
}; | |
/** | |
* Add the given string to this set. | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.add = function ArraySet_add(aStr) { | |
if (this.has(aStr)) { | |
// Already a member; nothing to do. | |
return; | |
} | |
var idx = this._array.length; | |
this._array.push(aStr); | |
this._set[util.toSetString(aStr)] = idx; | |
}; | |
/** | |
* Is the given string a member of this set? | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.has = function ArraySet_has(aStr) { | |
return Object.prototype.hasOwnProperty.call(this._set, | |
util.toSetString(aStr)); | |
}; | |
/** | |
* What is the index of the given string in the array? | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { | |
if (this.has(aStr)) { | |
return this._set[util.toSetString(aStr)]; | |
} | |
throw new Error('"' + aStr + '" is not in the set.'); | |
}; | |
/** | |
* What is the element at the given index? | |
* | |
* @param Number aIdx | |
*/ | |
ArraySet.prototype.at = function ArraySet_at(aIdx) { | |
if (aIdx >= 0 && aIdx < this._array.length) { | |
return this._array[aIdx]; | |
} | |
throw new Error('No element indexed by ' + aIdx); | |
}; | |
/** | |
* Returns the array representation of this set (which has the proper indices | |
* indicated by indexOf). Note that this is a copy of the internal array used | |
* for storing the members so that no one can mess with internal state. | |
*/ | |
ArraySet.prototype.toArray = function ArraySet_toArray() { | |
return this._array.slice(); | |
}; | |
exports.ArraySet = ArraySet; | |
}); | |
},{"./util":46,"amdefine":48}],49:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
/** | |
* Recursive implementation of binary search. | |
* | |
* @param aLow Indices here and lower do not contain the needle. | |
* @param aHigh Indices here and higher do not contain the needle. | |
* @param aNeedle The element being searched for. | |
* @param aHaystack The non-empty array being searched. | |
* @param aCompare Function which takes two elements and returns -1, 0, or 1. | |
*/ | |
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { | |
// This function terminates when one of the following is true: | |
// | |
// 1. We find the exact element we are looking for. | |
// | |
// 2. We did not find the exact element, but we can return the next | |
// closest element that is less than that element. | |
// | |
// 3. We did not find the exact element, and there is no next-closest | |
// element which is less than the one we are searching for, so we | |
// return null. | |
var mid = Math.floor((aHigh - aLow) / 2) + aLow; | |
var cmp = aCompare(aNeedle, aHaystack[mid]); | |
if (cmp === 0) { | |
// Found the element we are looking for. | |
return aHaystack[mid]; | |
} | |
else if (cmp > 0) { | |
// aHaystack[mid] is greater than our needle. | |
if (aHigh - mid > 1) { | |
// The element is in the upper half. | |
return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); | |
} | |
// We did not find an exact match, return the next closest one | |
// (termination case 2). | |
return aHaystack[mid]; | |
} | |
else { | |
// aHaystack[mid] is less than our needle. | |
if (mid - aLow > 1) { | |
// The element is in the lower half. | |
return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); | |
} | |
// The exact needle element was not found in this haystack. Determine if | |
// we are in termination case (2) or (3) and return the appropriate thing. | |
return aLow < 0 | |
? null | |
: aHaystack[aLow]; | |
} | |
} | |
/** | |
* This is an implementation of binary search which will always try and return | |
* the next lowest value checked if there is no exact hit. This is because | |
* mappings between original and generated line/col pairs are single points, | |
* and there is an implicit region between each of them, so a miss just means | |
* that you aren't on the very start of a region. | |
* | |
* @param aNeedle The element you are looking for. | |
* @param aHaystack The array that is being searched. | |
* @param aCompare A function which takes the needle and an element in the | |
* array and returns -1, 0, or 1 depending on whether the needle is less | |
* than, equal to, or greater than the element, respectively. | |
*/ | |
exports.search = function search(aNeedle, aHaystack, aCompare) { | |
return aHaystack.length > 0 | |
? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) | |
: null; | |
}; | |
}); | |
},{"amdefine":48}],50:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module); | |
} | |
define(function (require, exports, module) { | |
var charToIntMap = {}; | |
var intToCharMap = {}; | |
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
.split('') | |
.forEach(function (ch, index) { | |
charToIntMap[ch] = index; | |
intToCharMap[index] = ch; | |
}); | |
/** | |
* Encode an integer in the range of 0 to 63 to a single base 64 digit. | |
*/ | |
exports.encode = function base64_encode(aNumber) { | |
if (aNumber in intToCharMap) { | |
return intToCharMap[aNumber]; | |
} | |
throw new TypeError("Must be between 0 and 63: " + aNumber); | |
}; | |
/** | |
* Decode a single base 64 digit to an integer. | |
*/ | |
exports.decode = function base64_decode(aChar) { | |
if (aChar in charToIntMap) { | |
return charToIntMap[aChar]; | |
} | |
throw new TypeError("Not a valid base 64 digit: " + aChar); | |
}; | |
}); | |
},{"amdefine":48}]},{},[2])(2) | |
}); | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment